localcli.cpp
来自「FastDb是高效的内存数据库系统」· C++ 代码 · 共 3,024 行 · 第 1/5 页
CPP
3,024 行
{
case cli_oid:
case cli_bool:
case cli_int1:
case cli_int2:
case cli_int4:
case cli_autoincrement:
case cli_int8:
case cli_real4:
case cli_real8:
case cli_asciiz:
case cli_pasciiz:
break;
case cli_array_of_oid:
case cli_array_of_bool:
case cli_array_of_int1:
case cli_array_of_int2:
case cli_array_of_int4:
case cli_array_of_int8:
case cli_array_of_real4:
case cli_array_of_real8:
case cli_array_of_string:
varyingLength += strlen(columns[i].name) + 2 + 3;
nFields += 1;
break;
case cli_unknown:
return cli_unsupported_type;
}
}
db->beginTransaction(dbDatabase::dbExclusiveLock);
oid_t oid = db->allocateRow(dbMetaTableId,
sizeof(dbTable) + sizeof(dbField)*nFields + varyingLength);
dbTable* table = (dbTable*)db->putRow(oid);
int offs = sizeof(dbTable) + sizeof(dbField)*nFields;
table->name.offs = offs;
table->name.size = strlen(tableName)+1;
strcpy((char*)table + offs, tableName);
offs += table->name.size;
size_t size = sizeof(dbRecord);
table->fields.offs = sizeof(dbTable);
int fieldOffs = table->fields.offs;
dbField* field = (dbField*)((char*)table + fieldOffs);
offs -= sizeof(dbTable);
for (i = 0; i < nColumns; i++, fieldOffs += sizeof(dbField), field++, offs -= sizeof(dbField))
{
field->name.offs = offs;
field->name.size = strlen(columns[i].name) + 1;
strcpy((char*)field + offs, columns[i].name);
offs += field->name.size;
field->tableName.offs = offs;
int type = columns[i].type;
if (type == cli_oid || type == cli_array_of_oid)
{
if (type == cli_oid)
{
field->tableName.size = strlen(columns[i].refTableName) + 1;
strcpy((char*)field + offs, columns[i].refTableName);
offs += field->tableName.size;
}
else
{
field->tableName.size = 1;
*((char*)field + offs) = '\0';
offs += 1;
}
field->inverse.offs = offs;
if (columns[i].inverseRefFieldName != NULL)
{
field->inverse.size = strlen(columns[i].inverseRefFieldName) + 1;
strcpy((char*)field + offs, columns[i].inverseRefFieldName);
offs += field->inverse.size;
}
else
{
field->inverse.size = 1;
*((char*)field + offs) = '\0';
offs += 1;
}
}
else
{
field->tableName.size = 1;
*((char*)field + offs) = '\0';
offs += 1;
field->inverse.size = 1;
field->inverse.offs = offs;
*((char*)field + offs) = '\0';
offs += 1;
}
field->tTree = field->hashTable = 0;
switch (type)
{
case cli_oid:
field->type = dbField::tpReference;
field->size = sizeof(oid_t);
break;
case cli_bool:
field->type = dbField::tpBool;
field->size = sizeof(bool);
break;
case cli_int1:
field->type = dbField::tpInt1;
field->size = sizeof(int1);
break;
case cli_int2:
field->type = dbField::tpInt2;
field->size = sizeof(int2);
break;
case cli_int4:
case cli_autoincrement:
field->type = dbField::tpInt4;
field->size = sizeof(int4);
break;
case cli_int8:
field->type = dbField::tpInt8;
field->size = sizeof(db_int8);
break;
case cli_real4:
field->type = dbField::tpReal4;
field->size = sizeof(real4);
break;
case cli_real8:
field->type = dbField::tpReal8;
field->size = sizeof(real8);
break;
case cli_asciiz:
case cli_pasciiz:
field->type = dbField::tpString;
field->size = sizeof(dbVarying);
field->offset = DOALIGN(size, sizeof(int4));
size = field->offset + sizeof(dbVarying);
if (columns[i].flags & cli_hashed)
{
oid_t hashOid = dbHashTable::allocate(db);
table = (dbTable*)db->getRow(oid);
field = (dbField*)((char*)table + fieldOffs);
field->hashTable = hashOid;
}
else
{
field->hashTable = 0;
}
if (columns[i].flags & cli_indexed)
{
oid_t treeOid = dbTtree::allocate(db);
table = (dbTable*)db->getRow(oid);
field = (dbField*)((char*)table + fieldOffs);
field->tTree = treeOid;
}
else
{
field->tTree = 0;
}
continue;
case cli_array_of_oid:
case cli_array_of_bool:
case cli_array_of_int1:
case cli_array_of_int2:
case cli_array_of_int4:
case cli_array_of_int8:
case cli_array_of_real4:
case cli_array_of_real8:
case cli_array_of_string:
field->type = dbField::tpArray;
field->size = sizeof(dbVarying);
field->offset = DOALIGN(size, sizeof(int4));
size = field->offset + sizeof(dbVarying);
field->hashTable = field->tTree = 0;
field += 1;
fieldOffs += sizeof(dbField);
offs -= sizeof(dbField);
field->name.offs = offs;
field->name.size = strlen(columns[i].name) + 3;
sprintf((char*)field + offs, "%s[]", columns[i].name);
offs += field->name.size;
field->tableName.offs = offs;
if (type == cli_array_of_oid)
{
field->tableName.size = strlen(columns[i].refTableName) + 1;
strcpy((char*)field + offs, columns[i].refTableName);
offs += field->tableName.size;
}
else
{
field->tableName.size = 1;
*((char*)field + offs) = '\0';
offs += 1;
}
field->inverse.offs = offs;
field->inverse.size = 1;
*((char*)field + offs) = '\0';
offs += 1;
field->offset = 0;
field->hashTable = field->tTree = 0;
switch (type)
{
case cli_array_of_oid:
field->type = dbField::tpReference;
field->size = sizeof(oid_t);
break;
case cli_array_of_bool:
field->type = dbField::tpBool;
field->size = sizeof(bool);
break;
case cli_array_of_int1:
field->type = dbField::tpInt1;
field->size = sizeof(int1);
break;
case cli_array_of_int2:
field->type = dbField::tpInt2;
field->size = sizeof(int2);
break;
case cli_array_of_int4:
field->type = dbField::tpInt4;
field->size = sizeof(int4);
break;
case cli_array_of_int8:
field->type = dbField::tpInt8;
field->size = sizeof(db_int8);
break;
case cli_array_of_real4:
field->type = dbField::tpReal4;
field->size = sizeof(real4);
break;
case cli_array_of_real8:
field->type = dbField::tpReal8;
field->size = sizeof(real8);
break;
case cli_array_of_string:
field->type = dbField::tpString;
field->size = sizeof(dbVarying);
break;
}
continue;
}
if (columns[i].flags & cli_hashed)
{
oid_t hashOid = dbHashTable::allocate(db);
table = (dbTable*)db->getRow(oid);
field = (dbField*)((char*)table + fieldOffs);
field->hashTable = hashOid;
}
else
{
field->hashTable = 0;
}
if (columns[i].flags & cli_indexed)
{
oid_t treeOid = dbTtree::allocate(db);
table = (dbTable*)db->getRow(oid);
field = (dbField*)((char*)table + fieldOffs);
field->tTree = treeOid;
}
else
{
field->tTree = 0;
}
field->offset = DOALIGN(size, field->size);
size = field->offset + sizeof(dbVarying);
}
table->fields.size = nFields;
table->fixedSize = size;
table->nRows = 0;
table->nColumns = nColumns;
table->firstRow = 0;
table->lastRow = 0;
db->linkTable(new dbTableDescriptor(table), oid);
if (!db->completeDescriptorsInitialization())
{
return cli_table_not_found;
}
return cli_ok;
}
int cli_drop_table(int session, char const* tableName)
{
return dbCLI::instance.drop_table(session, tableName);
}
int dbCLI::drop_table(int session, char const* tableName)
{
session_desc* s = sessions.get(session);
if (s == NULL)
{
return cli_bad_descriptor;
}
dbDatabase* db = s->db;
dbTableDescriptor* desc = db->findTableByName(tableName);
if (desc == NULL)
{
return cli_table_not_found;
}
db->dropTable(desc);
if (desc == s->existed_tables)
{
s->existed_tables = desc->nextDbTable;
}
db->unlinkTable(desc);
desc->nextDbTable = s->dropped_tables;
s->dropped_tables = desc;
return cli_ok;
}
int cli_alter_index(int session, char const* tableName, char const* fieldName, int newFlags)
{
return dbCLI::instance.alter_index(session, tableName, fieldName, newFlags);
}
int dbCLI::alter_index(int session, char const* tableName, char const* fieldName, int newFlags)
{
session_desc* s = sessions.get(session);
if (s == NULL)
{
return cli_bad_descriptor;
}
return alter_index(s->db, tableName, fieldName, newFlags);
}
int dbCLI::alter_index(dbDatabase* db, char const* tableName, char const* fieldName, int newFlags)
{
db->beginTransaction(dbDatabase::dbExclusiveLock);
dbTableDescriptor* desc = db->findTableByName(tableName);
if (desc == NULL)
{
return cli_table_not_found;
}
dbFieldDescriptor* fd = desc->find(fieldName);
if (fd == NULL)
{
return cli_column_not_found;
}
if (fd->tTree != 0 && (newFlags & cli_indexed) == 0)
{
db->dropIndex(fd);
}
if (fd->hashTable != 0 && (newFlags & cli_hashed) == 0)
{
db->dropHashTable(fd);
}
if (fd->tTree == 0 && (newFlags & cli_indexed) != 0)
{
db->createIndex(fd);
}
if (fd->hashTable == 0 && (newFlags & cli_hashed) != 0)
{
db->createHashTable(fd);
}
return cli_ok;
}
cli_error_handler cli_set_error_handler(int session, cli_error_handler new_handler)
{
return dbCLI::instance.set_error_handler(session, new_handler);
}
cli_error_handler dbCLI::set_error_handler(int session, cli_error_handler new_handler)
{
session_desc* s = sessions.get(session);
if (s == NULL)
{
return NULL;
}
return (cli_error_handler)s->db->setErrorHandler(dbDatabase::dbErrorHandler(new_handler));
}
int cli_attach(int session)
{
return dbCLI::instance.attach(session);
}
int dbCLI::attach(int session)
{
session_desc* s = sessions.get(session);
if (s == NULL)
{
return cli_bad_descriptor;
}
s->db->attach();
return cli_ok;
}
int cli_detach(int session, int detach_mode)
{
return dbCLI::instance.detach(session, detach_mode);
}
int dbCLI::detach(int session, int detach_mode)
{
session_desc* s = sessions.get(session);
if (s == NULL)
{
return cli_bad_descriptor;
}
s->db->detach(detach_mode);
return cli_ok;
}
void cli_free_memory(int, void* ptr)
{
free(ptr);
}
int cli_get_database_state(int session, cli_database_monitor* monitor)
{
return dbCLI::instance.get_database_state(session, monitor);
}
int dbCLI::get_database_state(int session, cli_database_monitor* monitor)
{
session_desc* s = sessions.get(session);
if (s == NULL)
{
return cli_bad_descriptor;
}
dbMonitor* dbm = s->db->monitor;
monitor->n_readers = dbm->nReaders;
monitor->n_writers = dbm->nWriters;
monitor->n_blocked_readers = dbm->nWaitReaders;
monitor->n_blocked_writers = dbm->nWaitWriters;
monitor->n_users = dbm->users;
return cli_ok;
}
void cli_set_trace_function(cli_trace_function_t func)
{
dbTraceFunction = func;
}
int cli_prepare_query(int session, char const* query)
{
return dbCLI::instance.prepare_query(session, query);
}
int dbCLI::prepare_query(int session, char const* query)
{
char *p, *q;
int tkn;
session_desc* s = sessions.get(session);
if (s == NULL)
{
return cli_bad_descriptor;
}
statement_desc* stmt = statements.allocate();
stmt->columns = NULL;
stmt->params = NULL;
stmt->session = s;
stmt->for_update = 0;
stmt->first_fetch = true;
stmt->prepared = false;
stmt->n_params = 0;
stmt->n_columns = 0;
stmt->n_autoincremented_columns = 0;
stmt->oid = 0;
stmt->updated = false;
stmt->query.reset();
stmt->sql.put(strlen(query)+1);
p = stmt->sql.base();
strcpy(p, query);
sql_scanner scanner(p);
if (scanner.get() != tkn_select)
{
statements.free(stmt);
return cli_bad_statement;
}
if ((tkn = scanner.get()) == tkn_all)
{
tkn = scanner.get();
}
if (tkn != tkn_from || scanner.get() != tkn_ident)
{
statements.free(stmt);
return cli_bad_statement;
}
stmt->table = s->db->findTable(scanner.identifier());
if (stmt->table == NULL)
{
statements.free(stmt);
return cli_table_not_found;
}
p = scanner.current_position();
q = p;
int offs = 0;
while (*p != '\0')
{
if (*p == '\'')
{
do
{
do
{
p += 1;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?