subsql.cpp
来自「一个功能强大的内存数据库源代码,c++编写,有详细的注释」· C++ 代码 · 共 1,947 行 · 第 1/4 页
CPP
1,947 行
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(dbExclusiveLock); 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"); continue; } dbAnyCursor cursor(*desc, dbCursorForUpdate, NULL); dbDatabaseThreadContext* ctx = threadContext.get(); ctx->interactive = true; ctx->catched = true; #ifdef THROW_EXCEPTION_ON_ERROR try {#else if (setjmp(ctx->unwind) == 0) {#endif if (readCondition()) { query = buf; cursor.reset(); select(&cursor, query); if (!query.compiled()) { dbExprNode::cleanup(); ctx->catched = false; continue; } } else { ctx->catched = false; continue; } int n_deleted = cursor.getNumberOfRecords(); cursor.removeAllSelected(); printf("\n\t%d records deleted\n", n_deleted);#ifdef THROW_EXCEPTION_ON_ERROR } catch(dbException const&) {}#else } else { if (query.mutexLocked) { query.mutexLocked = false; query.mutex.unlock(); } }#endif if (!modified) { commit(); // release locks } ctx->catched = false; } 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\create <table-name> '('<field-name> <field-type> {',' <field-name> <field-type>}')' ';' \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 threads 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"); char* subsqlAccessType = getenv("SUBSQL_ACCESS_TYPE"); dbDatabase::dbAccessType accessType = dbDatabase::dbAllAccess; if (subsqlAccessType != NULL) { if (strcmp(subsqlAccessType, "read-only") == 0) { accessType = dbDatabase::dbReadOnly; } else if (strcmp(subsqlAccessType, "concurrent-read") == 0) { accessType = dbDatabase::dbConcurrentRead; } else if (strcmp(subsqlAccessType, "concurrent-update") == 0) { accessType = dbDatabase::dbConcurrentUpdate; } else if (strcmp(subsqlAccessType, "normal") && strcmp(subsqlAccessType, "all-access") && strcmp(subsqlAccessType, "read-write") && strcmp(subsqlAccessType, "update")) { fprintf(stderr, "Invalid access type: '%s'\n", subsqlAccessType); return 1; } } dbSubSql db(accessType); db.run(argc, argv); return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?