📄 subsql.cpp
字号:
return NULL;
}
while ((tkn = scan()) != tkn_semi) {
if (tkn != tkn_dot) {
error("'.' expected");
return NULL;
}
if (expect("field name", tkn_ident)) {
if ((fd = fd->find(name)) == NULL) {
error("No such field in the table");
return NULL;
} else if (fd->type == dbField::tpArray) {
error("Array components can not be indexed");
return NULL;
}
} else {
return NULL;
}
}
if (fd->type == dbField::tpReference) {
error("References can not be indexed");
return NULL;
}
if (fd->type == dbField::tpStructure) {
error("Structures can not be indexed");
return NULL;
}
return fd;
}
return NULL;
}
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:
*(int8*)dst = sattr.ivalue;
continue;
case tpBoolean:
*(int8*)dst = sattr.bvalue ? 1 : 0;
continue;
case tpReal:
*(int8*)dst = (int8)sattr.fvalue;
continue;
case tpString:
*(int8*)dst = (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;
}
assert(false);
} while ((elems = elems->next) != NULL);
return true;
}
bool dbSubSql::parse()
{
dbTableDescriptor* desc;
dbFieldDescriptor* fd;
int tkn;
bool 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->find(name);
if (fd == NULL) {
error("No such field in the table");
goto updateCleanup;
}
if (fd->type > dbField::tpString) {
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);
} else {
select(&cursor);
}
if (!query.compiled()) {
goto updateCleanup;
}
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;
if ((tkn = scan()) == tkn_all) {
outputOid = false;
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 (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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -