⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subsql.cpp

📁 实现内存数据库的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
			}
			tableId = table->next;
		    }
		    existedTables = tables;
		    if (!completeDescriptorsInitialization()) {
			error("Reference to undefined table");
		    }
		    char* backupName = getenv("FASTDB_BACKUP_NAME");
		    if (backupName != NULL) { 
			char* backupPeriod = getenv("FASTDB_BACKUP_PERIOD");
			time_t period = 60*60*24; // one day
			if (backupPeriod != NULL) { 
			    period = atoi(backupPeriod);
			}
			printf("Schedule backup to file %s each %u seconds\n", 
			       backupName, (unsigned)period);	
			scheduleBackup(backupName, period);			
		    }
		}
		delete[] databaseName;
	    }
	    continue;
		    
	  case tkn_drop:
	    if (!opened) { 
		error("Database not opened");
		continue;
	    }
	    if (monitor->users != 1) { 
		error("Can not perform operation with active appliations");
		continue;
	    }
	    switch (scan()) { 
	      case tkn_table:
		if (expect("table name", tkn_ident)) { 
		    desc = findTable(name);
		    if (desc == NULL) { 
			error("No such table in database");
		    } else { 
			dropTable(desc);
			if (desc == existedTables) { 
			    existedTables = desc->nextDbTable;
			}
			unlinkTable(desc);
			desc->nextDbTable = droppedTables;
			droppedTables = desc;
		    }
		}
		continue;
	      case tkn_hash:
		fd = readFieldName();
		if (fd != NULL) { 
		    if (fd->hashTable == 0) { 
			error("This field is not hashed");
		    } else { 
			dropHashTable(fd);
		    }
		}
		continue;
	      case tkn_index:
		fd = readFieldName();
		if (fd != NULL) { 
		    if (fd->tTree == 0) { 
			error("There is no index for this field");
		    } else { 
			dropIndex(fd);
		    }
		}
		continue;
	      default:
		error("Expecting 'table', 'hash' or 'index' keyword");
	    }
	    continue;

	  case tkn_backup:
	    if (!opened) { 
		error("Database not opened");
		continue;
	    }
	    compactify = false;
	    if ((tkn = scan()) == tkn_compactify) {
		compactify = true;
		tkn = scan();
	    }
	    if (tkn != tkn_sconst) { 
		 error("Backup file name expected");
	    } else { 
		if (!backup(buf, compactify)) { 
		    printf("Backup failed\n");
		} else { 
		    while (droppedTables != NULL) { 
			dbTableDescriptor* next = droppedTables->nextDbTable;
			delete droppedTables; 
			droppedTables = next;
		    }
		    commit();
		    existedTables = tables;
		}
	    }
	    continue;
	    
	  case tkn_create:
	    if (!opened) { 
		error("Database not opened");
		continue;
	    }
	    if (monitor->users != 1) { 
		error("Can not perform operation with active appliations\n");
		continue;
	    }
	    switch (scan()) { 
	      case tkn_hash:
		if (!expect("on", tkn_on)) { 
		    continue;
		}
		fd = readFieldName();
		if (fd != NULL) { 
		    if (fd->hashTable != 0) { 
			error("This field is already hashed");
		    } else { 
			createHashTable(fd);
		    }
		}
		continue;
	      case tkn_index:
		if (!expect("on", tkn_on)) { 
		    continue;
		}
		fd = readFieldName();
		if (fd != NULL) { 
		    if (fd->tTree != 0) { 
			error("Index already exists");
		    } else { 
			createIndex(fd);
		    }
		}
		continue;
		
	      case tkn_table:
		createTable();
		continue;

	      default:
		error("Expecting 'table', 'hash' or 'index' keyword");
	    }
	    continue;

	  case tkn_insert:
	    if (!opened) { 
		error("Database not opened");
		continue;
	    }
	    if (expect("into", tkn_into) && expect("table name", tkn_ident)) {
		if ((desc = findTable(name)) == NULL) { 
		    error("No such table in database");
		    continue;
		}
		if (!expect("values", tkn_values)) { 
		    continue;
		}
		beginTransaction(true);
		modified = true;
		while (expect("(", tkn_lpar)) { 
		    dbList* list = NULL;
		    int n = readValues(&list);
		    if (n <= 0 || !insertRecord(list, desc)) { 
			if (n == 0) { 
			    error("Empty fields list");
			}
			tkn = tkn_semi; // just avoid extra error messages
		    } else { 
			tkn = scan();
		    }
		    while (list != NULL) { 
			dbList* tail = list->next;
			delete list;
			list = tail;
		    }
		    if (tkn == tkn_semi) { 
			break;
		    } else if (tkn != tkn_comma) { 
			error("';' or ',' expected");
		    }
		}
	    }
	    continue;

	  case tkn_delete:
	    if (!opened) { 
		error("Database not opened");
		continue;
	    }
	    if (expect("FROM", tkn_from) && expect("table name", tkn_ident)) {
		if ((desc = findTable(name)) == NULL) { 
		    error("No such table in database");
		} else { 
		    deleteTable(desc);
		}
	    }
	    continue;

	  case tkn_commit:
	    if (!opened) { 
		error("Database not opened");
	    } else { 
		while (droppedTables != NULL) { 
		    dbTableDescriptor* next = droppedTables->nextDbTable;
		    delete droppedTables; 
		    droppedTables = next;
		}
		commit();
		existedTables = tables;
	    }
	    continue;

	  case tkn_rollback:
	    if (!opened) { 
		error("Database not opened");
	    } else { 
		while (droppedTables != NULL) { 
		    dbTableDescriptor* next = droppedTables->nextDbTable;
		    linkTable(droppedTables, droppedTables->tableId); 
		    droppedTables = next;
		}
		rollback();
		while (tables != existedTables) { 
		    dbTableDescriptor* table = tables;
		    unlinkTable(table);
		    delete table;
		}
	    } 
	    continue;

	  case tkn_show:
	    if (!opened) { 
		error("Database not opened");
	    } else { 
		printf("Database file size: %lu Kb\n"
		       "Object index size : %lu handles\n"
		       "Used part of index: %lu handles\n"
		       "Number of users   : %d\n"
		       "Number of readers : %d\n" 
		       "Number of writers : %d\n" 
		       "Number of blocked readers : %d\n" 
		       "Number of blocked writers : %d\n", 
		       (unsigned long)(header->size/1024),
		       (unsigned long)header->root[1-header->curr].indexSize, 
		       (unsigned long)header->root[1-header->curr].indexUsed,
		       monitor->users,
		       monitor->nReaders,
		       monitor->nWriters,
		       monitor->nWaitReaders,
		       monitor->nWaitWriters + monitor->waitForUpgrade);
		printf("\nTABLES:\n");
		printf("OID       FixedSize   Fields  Columns  TableName\n");
		printf("---------------------------------------------------------\n");
		for (dbTableDescriptor* desc=tables; desc != NULL; desc=desc->nextDbTable)
		{ 
		    printf("0x%06x  %8d %8d %8d   %s\n",
			   desc->tableId, desc->fixedSize,
			   desc->nFields, desc->nColumns, desc->name);
		}

	    } 
	    continue;
		       
 	  case tkn_describe:
	    if (!opened) {
		error("Database not opened");
		continue;
	    }	
	    if (expect("table name", tkn_ident)) {
		if ((desc = findTable(name)) == NULL) {
		    error("No such table in database");
		    continue;
		}
                printf("\nOID=0x%06x, TableName=%s\n",desc->tableId, desc->name);
                printf("FieldNo  FieldType        RefTableName     FieldName\n");
                printf("----------------------------------------------------\n");
                dbFieldDescriptor* fd = desc->columns; 
		for (int i = desc->nColumns; --i >= 0;) { 
		    printf("%6d   %-16s %-16s %s\n", fd->fieldNo, 
			   typeMnem[fd->type],
			   fd->refTableName ? fd->refTableName : "(null)", 
			   fd->name);
		    fd = fd->next;
                }
	    }
	    continue;

	  case tkn_help:
	    fprintf(stderr, "SubSQL commands:\n\n\
open 'database-name' ( 'database-file-name' ) ';'\n\
select ('*') from <table-name> where <condition> ';'\n\
update <table-name> set <field-name> '=' <expression> {',' <field-name> '=' <expression>} where <condition> ';'\n\
delete from <table-name>\n\
drop table <table-name>\n\
drop index <table-name> {'.' <field-name>} ';'\n\
create index on <table-name> {'.' <field-name>} ';'\n\
drop hash <table-name> {'.' <field-name>};\n\
create hash on <table-name> {'.' <field-name>}field> ';'\n\
insert into <table-name> values '(' <value>{',' <value>} ')' ';'\n\
backup [compactify] 'file-name'\n\
start server URL number-of-threads\n\
stop server URL\n\
describe <table-name>\n\
show\n\
commit\n\
rollback\n\
exit\n\
help\n\n");
	    continue;
	  case tkn_start:
	    if (!opened) { 
		error("Database not opened");
	    } else { 
		commit(); // allow server therads to process
		existedTables = tables;
		if (expect("server", tkn_server) 
		    && expect("server URL", tkn_sconst))
		{
#if !THREADS_SUPPORTED
		    error("Database was build without pthread support");
#else
		    dbServer* server = dbServer::find(buf);
		    if (server == NULL) { 
			char* serverURL = new char[strlen(buf)+1];
			strcpy(serverURL, buf);
			if (expect("number of threads", tkn_iconst)) { 
			    server = new dbServer(this, serverURL, (int)ival);
			    printf("Server started for URL %s\n", serverURL);
			}
			delete[] serverURL;
		    }
		    if (server != NULL) { 
			server->start();
		    }
#endif
		}
	    }
	    continue;
	  case tkn_stop:
	    if (expect("server", tkn_server) 
		&& expect("server URL", tkn_sconst))
	    {
#if !THREADS_SUPPORTED
		error("Database was build without pthread support");
#else
		dbServer* server = dbServer::find(buf);
		if (server != NULL) { 
		    server->stop();
		    printf("Server stopped for URL %s\n", buf);
		} else { 
		    fprintf(stderr, "No server was started for URL %s\n", buf);
		}
#endif
	    }
	    continue;
	  case tkn_semi:
	    putchar('\n');
	    // no break
	  case tkn_error:
	    continue;
	  case tkn_exit:
	    return false;
	  case tkn_eof:
	    return true;
	  default:
	    error("Unexpected token");
	}
    }
}

	    
void dbSubSql::handleError(dbErrorClass error, char const* msg, int arg)
{
    dbDatabaseThreadContext* ctx = threadContext.get();
    if (ctx == NULL || ctx->interactive) { 
	const int screenWidth = 80;
	int col;
	switch (error) { 
	  case QueryError:
	    col = arg % screenWidth;
	    if (in == stdin) { 
		while (--col >= 0) putc('-', stderr);
		fprintf(stderr, "^\n%s\n", msg);
	    } else { 
		fprintf(stderr, "%s at line %d position %d\n", msg, line, arg);
	    }
	    break;
	  case ArithmeticError:
	    fprintf(stderr, "%s\n", msg);
	    break;
	  case IndexOutOfRangeError:
	    fprintf(stderr, "Index %d is out of range\n", arg);
	    break;
	  case NullReferenceError:
	    fprintf(stderr, "Null object reference is accessed\n");
	    break;
	  default:
	    dbDatabase::handleError(error, msg, arg);
	}
	//
	// Recovery
	//
	if (in == stdin) { 
	    int ch;
	    while ((ch = get()) != '\n' && ch != EOF); 
	} else { 
	    fseek(in, 0, SEEK_END);
	}
    }
#ifdef THROW_EXCEPTION_ON_ERROR
    throw dbException(error, msg, arg);
#else
    if (ctx != NULL) { 
	if (ctx->catched) {	
	    longjmp(ctx->unwind, error);
	} else { 
	    abort();
	}
    }
#endif
}

void dbSubSql::run(int argc, char* argv[])
{
    for (int i = 1; i < argc; i++) { 
        in = fopen(argv[i], "r");
	if (in == NULL) { 
	    fprintf(stderr, "Failed to open '%s' file\n", argv[i]);
	} else { 
	    if (!parse()) { 
		if (opened) { 
		    close();
		}
#if THREADS_SUPPORTED
		dbServer::cleanup();
#endif
		return;
	    }
	}
    }
    in = stdin;
    parse();
    if (opened) { 
	close();
    }
#if THREADS_SUPPORTED
    dbServer::cleanup();
#endif
}

int main(int argc, char* argv[]) 
{
    printf("SubSQL interactive utility for FastDB\n"
	   "Type 'help' for more information\n");
    dbSubSql db;
    db.run(argc, argv);
    return 0;
}
    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -