subsql.cpp
来自「一个功能强大的内存数据库源代码,c++编写,有详细的注释」· C++ 代码 · 共 1,947 行 · 第 1/4 页
CPP
1,947 行
bool dbSubSql::updateFields(dbAnyCursor* cursor, dbUpdateElement* elems){ char buf[64], *src; dbInheritedAttribute iattr; dbSynthesizedAttribute sattr; iattr.db = this; iattr.oid = cursor->currId; iattr.table = (dbTable*)getRow(cursor->table->tableId); iattr.record = (byte*)getRow(cursor->currId); iattr.paramBase = (size_t)cursor->paramBase; do { dbExprNode* expr = elems->value; dbFieldDescriptor* fd = elems->field; execute(expr, iattr, sattr); byte* dst = cursor->record + fd->appOffs; switch (fd->type) { case dbField::tpBool: switch (expr->type) { case tpInteger: *(bool*)dst = sattr.ivalue != 0; continue; case tpBoolean: *(bool*)dst = sattr.bvalue; continue; case tpReal: *(bool*)dst = sattr.fvalue != 0; continue; case tpString: *(bool*)dst = *sattr.base == 'T' || *sattr.base == 't' || *sattr.base == '1'; continue; } break; case dbField::tpInt1: switch (expr->type) { case tpInteger: *(int1*)dst = (int1)sattr.ivalue; continue; case tpBoolean: *(int1*)dst = sattr.bvalue ? 1 : 0; continue; case tpReal: *(int1*)dst = (int1)sattr.fvalue; continue; case tpString: *(int1*)dst = (int1)atoi((char*)sattr.base); continue; } break; case dbField::tpInt2: switch (expr->type) { case tpInteger: *(int2*)dst = (int2)sattr.ivalue; continue; case tpBoolean: *(int2*)dst = sattr.bvalue ? 1 : 0; continue; case tpReal: *(int2*)dst = (int2)sattr.fvalue; continue; case tpString: *(int2*)dst = (int2)atoi((char*)sattr.base); continue; } break; case dbField::tpInt4: switch (expr->type) { case tpInteger: *(int4*)dst = (int4)sattr.ivalue; continue; case tpBoolean: *(int4*)dst = sattr.bvalue ? 1 : 0; continue; case tpReal: *(int4*)dst = (int4)sattr.fvalue; continue; case tpString: *(int4*)dst = (int1)atoi((char*)sattr.base); continue; } break; case dbField::tpInt8: switch (expr->type) { case tpInteger: *(db_int8*)dst = sattr.ivalue; continue; case tpBoolean: *(db_int8*)dst = sattr.bvalue ? 1 : 0; continue; case tpReal: *(db_int8*)dst = (db_int8)sattr.fvalue; continue; case tpString: *(db_int8*)dst = (db_int8)atoi((char*)sattr.base); continue; } break; case dbField::tpReal4: switch (expr->type) { case tpInteger: *(real4*)dst = (real4)sattr.ivalue; continue; case tpBoolean: *(real4*)dst = sattr.bvalue ? 1.0 : 0.0; continue; case tpReal: *(real4*)dst = (real4)sattr.fvalue; continue; case tpString: *(real4*)dst = (real4)atof((char*)sattr.base); continue; } break; case dbField::tpReal8: switch (expr->type) { case tpInteger: *(real8*)dst = (real8)sattr.ivalue; continue; case tpBoolean: *(real8*)dst = sattr.bvalue ? 1.0 : 0.0; continue; case tpReal: *(real8*)dst = sattr.fvalue; continue; case tpString: *(real8*)dst = atof((char*)sattr.base); continue; } break; case dbField::tpString: src = buf; switch (expr->type) { case tpInteger: sprintf(buf, INT8_FORMAT, sattr.ivalue); break; case tpBoolean: strcpy(buf, sattr.bvalue ? "t" : "f"); break; case tpReal: sprintf(buf, "%f", sattr.fvalue); break; case tpString: src = (char*)sattr.base; break; } *(char**)dst = new char[strlen(src)+1]; strcpy(*(char**)dst, src); elems->strValue = *(char**)dst; continue; case dbField::tpReference: if (expr->type == tpInteger) { *(oid_t*)dst = sattr.oid; continue; } } assert(false); } while ((elems = elems->next) != NULL); return true;}bool dbSubSql::parse() { dbTableDescriptor* desc; dbFieldDescriptor* fd; int tkn; bool count, outputOid, compactify; line = 1; pos = 0; while (true) { if (in == stdin) { printf(prompt); tkn = scan(); pos += strlen(prompt); } else { tkn = scan(); } switch (tkn) { case tkn_update: 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; } if (!expect("set", tkn_set)) { continue; } dbDatabaseThreadContext* ctx = threadContext.get(); byte *record = new byte[desc->appSize]; ctx->interactive = true; ctx->catched = true; dbUpdateElement* elems = NULL; if (!expect("field name", tkn_ident)) { goto updateCleanup; } #ifdef THROW_EXCEPTION_ON_ERROR try {#else if (setjmp(ctx->unwind) == 0) {#endif char* condition = NULL; int startPos = pos; while (true) { dbUpdateElement* elem = new dbUpdateElement; dbFieldDescriptor* fd = desc->findSymbol(name); if (fd == NULL) { error("No such field in the table"); goto updateCleanup; } if (fd->type > dbField::tpReference) { error("Field can not be updated"); goto updateCleanup; } elem->field = fd; elem->next = elems; elems = elem; if (!expect("=", tkn_eq)) { goto updateCleanup; } startPos = pos; int ch = readExpression(); if (ch == EOF) { error("unexpected end of input"); goto updateCleanup; } condition = strstr(buf, "where"); if (condition != NULL) { *condition = '\0'; } dbExprNode* expr = ctx->compiler.compileExpression(desc, buf, startPos); if (expr == NULL) { goto updateCleanup; } if (expr->type > tpString) { error("Invalid expression type"); goto updateCleanup; } elem->value = expr; if (condition == NULL && ch == ',') { if (!expect("field name", tkn_ident)) { goto updateCleanup; } } else { break; } } dbAnyCursor cursor(*desc, dbCursorForUpdate, record); cursor.reset(); if (condition != NULL) { query.pos = startPos + (condition - buf) + 5; query = condition + 5; select(&cursor, query); if (!query.compiled()) { goto updateCleanup; } } else { select(&cursor); } if (cursor.gotoFirst()) { do { cursor.fetch(); if (!updateFields(&cursor, elems)) { goto updateCleanup; } cursor.update(); } while (cursor.gotoNext()); } printf("\n\t%d records updated\n", cursor.getNumberOfRecords());#ifdef THROW_EXCEPTION_ON_ERROR } catch(dbException const&) {}#else } else { if (query.mutexLocked) { query.mutexLocked = false; query.mutex.unlock(); } }#endif updateCleanup: query.reset(); while (elems != NULL) { dbUpdateElement* elem = elems; elems = elems->next; delete elem; } if (!modified) { commit(); // release locks } dbExprNode::cleanup(); ctx->catched = false; delete[] record; } continue; case tkn_select: if (!opened) { error("Database not opened"); continue; } outputOid = true; count = false; if ((tkn = scan()) == tkn_all) { outputOid = false; tkn = scan(); } else if (tkn == tkn_count) { if (!expect("'('", tkn_lpar) || !expect("'*'", tkn_all) || !expect("')'", tkn_rpar)) { continue; } count = true; tkn = scan(); } if (tkn != tkn_from) { error("'from' keyword expected"); continue; } if (scan() != tkn_ident) { error("Table name expected"); continue; } if ((desc = findTable(name)) != NULL) { dbAnyCursor cursor(*desc, dbCursorViewOnly, NULL); query.pos = pos; 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; } if (count) { printf("%d records selected\n", cursor.getNumberOfRecords()); } else { if (cursor.gotoFirst()) { dbFieldDescriptor* fd = desc->columns; do { printf("%s ", fd->name); } while ((fd = fd->next) != desc->columns); if (outputOid) { printf("\n#%x: (", cursor.currId); } else { printf("\n("); } dumpRecord((byte*)getRow(cursor.currId), cursor.table->columns); printf(")"); while (cursor.gotoNext()) { if (outputOid) { printf(",\n#%x: (", cursor.currId); } else { printf(",\n("); } dumpRecord((byte*)getRow(cursor.currId), cursor.table->columns); printf(")"); } printf("\n\t%d records selected\n", cursor.getNumberOfRecords()); } else { fprintf(stderr, "No records selected\n"); } }#ifdef THROW_EXCEPTION_ON_ERROR } catch(dbException const&) {}#else } else { if (query.mutexLocked) { query.mutexLocked = false; query.mutex.unlock(); } }#endif ctx->catched = false; if (!modified) { commit(); // release locks } } else { error("No such table in database"); } continue; case tkn_open: if (expect("database name", tkn_sconst)) { char* databaseName = new char[strlen(buf)+1]; strcpy(databaseName, buf); char* fileName = NULL; if ((tkn = scan()) == tkn_sconst) { fileName = buf; } else if (tkn != tkn_semi) { delete[] databaseName; error("database file name expected"); continue; } if (opened) { close(); while (droppedTables != NULL) { dbTableDescriptor* next = droppedTables->nextDbTable; delete droppedTables; droppedTables = next; } opened = false; dbTableDescriptor::cleanup(); } time_t transactionCommitDelay = 0; char* delay = getenv("FASTDB_COMMIT_DELAY"); if (delay != NULL) { transactionCommitDelay = atoi(delay); } if (!open(databaseName, fileName, INFINITE, transactionCommitDelay)) { fprintf(stderr, "Database not opened\n"); } else { opened = true; dbTable* table = (dbTable*)getRow(dbMetaTableId); dbTableDescriptor* desc = new dbTableDescriptor(table); linkTable(desc, dbMetaTableId); oid_t tableId = table->firstRow; while (tableId != 0) { table = (dbTable*)getRow(tableId); for (desc = tables; desc != NULL && desc->tableId != tableId; desc = desc->nextDbTable); if (desc == NULL) { dbTableDescriptor* desc = new dbTableDescriptor(table); linkTable(desc, tableId); desc->setFlags(); } 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:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?