subsql.cpp
来自「FastDb是高效的内存数据库系统」· C++ 代码 · 共 3,037 行 · 第 1/5 页
CPP
3,037 行
{
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 = (char const*)(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 (autocommit || !modified)
{
commit(); // release locks
}
dbExprNodeAllocator::instance.reset();
ctx->catched = false;
dbFree(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 = (char const*)buf;
cursor.reset();
select(&cursor, query);
if (!query.compiled())
{
dbExprNodeAllocator::instance.reset();
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 || autocommit)
{
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;
}
break;
case tkn_drop:
if (!opened)
{
error("Database not opened");
continue;
}
if (accessType == dbReadOnly)
{
error("Operation is not possible in read-only mode");
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;
}
}
break;
case tkn_hash:
fd = readFieldName();
if (fd != NULL)
{
if (fd->hashTable == 0)
{
error("This field is not hashed");
}
else
{
dropHashTable(fd);
}
}
break;
case tkn_index:
fd = readFieldName();
if (fd != NULL)
{
if (fd->tTree == 0)
{
error("There is no index for this field");
}
else
{
dropIndex(fd);
}
}
break;
default:
error("Expecting 'table', 'hash' or 'index' keyword");
continue;
}
break;
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 (accessType == dbReadOnly)
{
error("Operation is not possible in read-only mode");
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);
}
}
break;
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);
}
}
break;
case tkn_table:
updateTable(true);
break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?