subsql.cpp
来自「FastDb是高效的内存数据库系统」· C++ 代码 · 共 3,037 行 · 第 1/5 页
CPP
3,037 行
default:
error("Expecting 'table', 'hash' or 'index' keyword");
continue;
}
break;
case tkn_alter:
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_table:
updateTable(false);
break;
default:
error("Expecting 'table' keyword");
continue;
}
break;
case tkn_insert:
if (!opened)
{
error("Database not opened");
continue;
}
if (accessType == dbReadOnly)
{
error("Operation is not possible in read-only mode");
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");
}
}
}
break;
case tkn_delete:
if (!opened)
{
error("Database not opened");
continue;
}
if (accessType == dbReadOnly)
{
error("Operation is not possible in read-only mode");
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 = (char const*)buf;
cursor.reset();
select(&cursor, query);
if (!query.compiled())
{
dbExprNodeAllocator::instance.reset();
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
ctx->catched = false;
}
break;
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("FastDB version : %d.%02d\n"
"Database version : %d.%02d\n"
"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",
FASTDB_MAJOR_VERSION, FASTDB_MINOR_VERSION,
header->majorVersion, header->minorVersion,
(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 InverseFieldName\n");
printf("----------------------------------------------------------------------------\n");
dbFieldDescriptor* fd = desc->columns;
for (int i = desc->nColumns; --i >= 0;)
{
printf("%6d %-16s %-16s %-16s %s\n",
fd->fieldNo,
typeMnem[fd->type],
fd->refTableName != NULL
? fd->refTableName
: (fd->type == dbField::tpArray && fd->components->refTableName != NULL)
? fd->components->refTableName
: "(null)",
fd->name,
(fd->inverseRefName != NULL ? fd->inverseRefName : "(null)"));
fd = fd->next;
}
}
continue;
case tkn_export:
if (!opened)
{
error("Database not opened");
continue;
}
if (expect("xml file name", tkn_sconst))
{
FILE* f;
if (strcmp(buf, "-") == 0)
{
f = stdout;
}
else
{
f = fopen(buf, "w");
}
if (f != NULL)
{
exportDatabase(f);
fclose(f);
}
else
{
error("Failed to open output file");
}
}
continue;
case tkn_import:
if (!opened)
{
error("Database not opened");
continue;
}
if (accessType == dbReadOnly)
{
error("Operation is not possible in read-only mode");
continue;
}
if (expect("xml file name", tkn_sconst))
{
FILE* f;
if (strcmp(buf, "-") == 0)
{
f = stdin;
}
else
{
f = fopen(buf, "r");
}
if (f != NULL)
{
if (!importDatabase(f))
{
error("Import from XML file failed: incorrect file format");
}
fclose(f);
}
else
{
error("Failed to open input file");
}
}
break;
case tkn_autocommit:
switch (scan())
{
case tkn_on:
autocommit = true;
break;
case tkn_off:
autocommit = false;
break;
default:
error("ON or OFF expected");
}
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 <table-name> '('<field-name> <field-type> {',' <field-name> <field-type>}')' ';' \n\
alter table <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\
start http server URL\n\
stop http server\n\
describe <table-name>\n\
import 'xml-file-name'\n\
export 'xml-file-name'\n\
show\n\
commit\n\
rollback\n\
autocommit (on|off)\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;
tkn = scan();
if (tkn == tkn_http)
{
if (expect("server", tkn_server)
&& expect("HTTP server URL", tkn_sconst))
{
#if !THREADS_SUPPORTED
error("Database was build without pthread support");
#else
startHttpServer(buf);
#endif
}
}
else if (tkn == 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
}
else
{
error("Token 'server' expected");
}
}
continue;
case tkn_stop:
tkn = scan();
if (tkn == tkn_http)
{
if (expect("server", tkn_server) && expect("HTTP server URL", tkn_sconst))
{
#if !THREADS_SUPPORTED
error("Database was build without pthread support");
#else
stopHttpServer(buf);
#endif
}
}
else if (tkn == tkn_server)
{
if (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
}
}
else
{
error("Token 'server' expected");
}
continue;
case tkn_semi:
putchar('\n');
// no break
case tkn_error:
continue;
case tkn_exit:
return false;
case tkn_version:
printf("FastDB version %d.%02d\n", FASTDB_MAJOR_VERSION, FASTDB_MINOR_VERSION);
continue;
case tkn_eof:
return true;
default:
error("Unexpected token");
continue;
}
if (autocommit)
{
commit();
}
}
}
void exportString(FILE* out, char* src, int len)
{
fprintf(out, "\"");
while (--len > 0)
{
byte b = (byte)*src++;
switch (b)
{
case '&':
fprintf(out, "&
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?