📄 server.cpp
字号:
for (cb = stmt->columns; cb != NULL; cb = cb->next) {
if (cb->fd->attr & dbFieldDescriptor::Updated) {
if (cb->fd->indexType & HASHED) {
dbHashTable::remove(db, cb->fd->hashTable,
stmt->cursor->currId,
cb->fd->type, cb->fd->dbsSize, cb->fd->dbsOffs);
}
if (cb->fd->indexType & INDEXED) {
if (cb->fd->type == dbField::tpRectangle) {
dbRtree::remove(db, cb->fd->tTree, stmt->cursor->currId,
cb->fd->dbsOffs);
} else {
dbTtree::remove(db, cb->fd->tTree, stmt->cursor->currId,
cb->fd->type, cb->fd->dbsSize, cb->fd->comparator, cb->fd->dbsOffs);
}
}
}
}
db->modified = true;
new_data = (char*)db->putRow(stmt->cursor->currId, offs);
fd = first;
offs = table->fixedSize;
do {
if (fd->type == dbField::tpArray || fd->type == dbField::tpString)
{
int len = ((dbVarying*)(old_data + fd->dbsOffs))->size;
offs = DOALIGN(offs, fd->components->alignment);
for (cb = stmt->columns; cb != NULL; cb = cb->next) {
if (cb->fd == fd) {
len = cb->unpackArray(new_data, offs);
break;
}
}
if (cb == NULL) {
memcpy(new_data + offs,
old_data + ((dbVarying*)(old_data + fd->dbsOffs))->offs,
len*fd->components->dbsSize);
}
((dbVarying*)(new_data + fd->dbsOffs))->size = len;
((dbVarying*)(new_data + fd->dbsOffs))->offs = offs;
offs += len*fd->components->dbsSize;
} else {
for (cb = stmt->columns; cb != NULL; cb = cb->next) {
if (cb->fd == fd) {
if (cb->cliType == cli_autoincrement) { // autoincrement column is ignored
cb = NULL;
break;
}
cb->unpackScalar(new_data, false);
break;
}
}
if (cb == NULL) {
memcpy(new_data + fd->dbsOffs, old_data + fd->dbsOffs,
fd->dbsSize);
}
}
} while ((fd = fd->next) != first);
delete[] old_data;
for (cb = stmt->columns; cb != NULL; cb = cb->next) {
if (cb->fd->attr & dbFieldDescriptor::Updated) {
cb->fd->attr &= ~dbFieldDescriptor::Updated;
if (cb->fd->indexType & HASHED) {
dbHashTable::insert(db, cb->fd->hashTable,
stmt->cursor->currId,
cb->fd->type, cb->fd->dbsSize, cb->fd->dbsOffs, 0);
}
if (cb->fd->indexType & INDEXED) {
if (cb->fd->type == dbField::tpRectangle) {
dbRtree::insert(db, cb->fd->tTree, stmt->cursor->currId,
cb->fd->dbsOffs);
} else {
dbTtree::insert(db, cb->fd->tTree, stmt->cursor->currId,
cb->fd->type, cb->fd->dbsSize, cb->fd->comparator, cb->fd->dbsOffs);
}
}
}
}
response = cli_ok;
pack4(response);
return session->sock->write(&response, sizeof response);
}
char* dbServer::checkColumns(dbStatement* stmt, int n_columns,
dbTableDescriptor* desc, char* data,
int4& response)
{
dbColumnBinding** cpp = &stmt->columns;
response = cli_ok;
while (--n_columns >= 0) {
int cliType = *data++;
char* columnName = data;
dbSymbolTable::add(columnName, tkn_ident, true);
dbFieldDescriptor* fd = desc->findSymbol(columnName);
data += strlen(data) + 1;
if (fd != NULL) {
if ((cliType == cli_oid
&& fd->type == dbField::tpReference)
|| (cliType == cli_rectangle
&& fd->type == dbField::tpRectangle)
|| (((cliType >= cli_bool && cliType <= cli_int8) || cliType == cli_autoincrement)
&& fd->type >= dbField::tpBool
&& fd->type <= dbField::tpInt8)
|| (cliType >= cli_real4 && cliType <= cli_real8
&& fd->type >= dbField::tpReal4
&& fd->type <= dbField::tpReal8)
|| ((cliType == cli_asciiz || cliType == cli_pasciiz)
&& fd->type == dbField::tpString)
|| (cliType == cli_array_of_oid &&
fd->type == dbField::tpArray &&
fd->components->type == dbField::tpReference)
|| (cliType >= cli_array_of_bool
&& fd->type == dbField::tpArray
&& cliType-cli_array_of_bool
== fd->components->type-dbField::tpBool))
{
dbColumnBinding* cb = new dbColumnBinding(fd, cliType);
*cpp = cb;
cpp = &cb->next;
} else {
response = cli_incompatible_type;
break;
}
} else {
TRACE_MSG(("Field '%s' not found\n", columnName));
response = cli_column_not_found;
break;
}
}
return data;
}
bool dbServer::insert(dbSession* session, int stmt_id, char* data, bool prepare)
{
dbStatement* stmt = findStatement(session, stmt_id);
dbTableDescriptor* desc = NULL;
dbColumnBinding* cb;
int4 response;
char reply_buf[sizeof(cli_oid_t) + 8];
char* dst;
oid_t oid = 0;
size_t offs;
int n_columns;
if (stmt == NULL) {
if (!prepare) {
response = cli_bad_statement;
goto return_response;
}
stmt = new dbStatement(stmt_id);
stmt->next = session->stmts;
session->stmts = stmt;
} else {
if (prepare) {
stmt->reset();
} else if ((desc = stmt->table) == NULL) {
response = cli_bad_descriptor;
goto return_response;
}
}
if (prepare) {
session->scanner.reset(data);
if (session->scanner.get() != tkn_insert
|| session->scanner.get() != tkn_into
|| session->scanner.get() != tkn_ident)
{
response = cli_bad_statement;
goto return_response;
}
desc = db->findTable(session->scanner.ident);
if (desc == NULL) {
response = cli_table_not_found;
goto return_response;
}
data += strlen(data)+1;
n_columns = *data++ & 0xFF;
data = checkColumns(stmt, n_columns, desc, data, response);
if (response != cli_ok) {
goto return_response;
}
stmt->table = desc;
}
offs = desc->fixedSize;
for (cb = stmt->columns; cb != NULL; cb = cb->next) {
cb->ptr = data;
if (cb->cliType == cli_autoincrement) {
;
} else if (cb->cliType >= cli_asciiz) {
cb->len = unpack4(data);
data += 4 + cb->len*cb->fd->components->dbsSize;
offs = DOALIGN(offs, cb->fd->components->alignment)
+ cb->len*cb->fd->components->dbsSize;
} else {
data += sizeof_type[cb->cliType];
}
}
db->beginTransaction(dbDatabase::dbExclusiveLock);
db->modified = true;
oid = db->allocateRow(desc->tableId, offs);
#ifdef AUTOINCREMENT_SUPPORT
desc->autoincrementCount = ((dbTable*)db->getRow(desc->tableId))->count;
#endif
dst = (char*)db->getRow(oid);
offs = desc->fixedSize;
for (cb = stmt->columns; cb != NULL; cb = cb->next) {
dbFieldDescriptor* fd = cb->fd;
if (fd->type == dbField::tpArray || fd->type == dbField::tpString) {
offs = DOALIGN(offs, fd->components->alignment);
((dbVarying*)(dst + fd->dbsOffs))->offs = offs;
((dbVarying*)(dst + fd->dbsOffs))->size = cb->len;
offs += cb->unpackArray(dst, offs)*fd->components->dbsSize;
} else {
cb->unpackScalar(dst, true);
}
}
for (cb = stmt->columns; cb != NULL; cb = cb->next) {
if (cb->fd->indexType & HASHED) {
dbHashTable::insert(db, cb->fd->hashTable, oid,
cb->fd->type, cb->fd->dbsSize, cb->fd->dbsOffs, 0);
}
if (cb->fd->indexType & INDEXED) {
if (cb->fd->type == dbField::tpRectangle) {
dbRtree::insert(db, cb->fd->tTree, oid, cb->fd->dbsOffs);
} else {
dbTtree::insert(db, cb->fd->tTree, oid,
cb->fd->type, cb->fd->dbsSize, cb->fd->comparator, cb->fd->dbsOffs);
}
}
}
response = cli_ok;
return_response:
pack4(reply_buf, response);
if (desc == NULL) {
pack4(reply_buf+4, 0);
} else {
#ifdef AUTOINCREMENT_SUPPORT
pack4(reply_buf+4, desc->autoincrementCount);
#else
pack4(reply_buf+4, ((dbTable*)db->getRow(desc->tableId))->nRows);
#endif
}
pack_oid(reply_buf+8, oid);
return session->sock->write(reply_buf, sizeof reply_buf);
}
bool dbServer::describe_table(dbSession* session, char const* table)
{
dbTableDescriptor* desc = db->findTableByName(table);
if (desc == NULL) {
char response[8];
pack4(response, 0);
pack4(response+4, -1);
return session->sock->write(response, sizeof response);
} else {
int i, length = 0;
dbFieldDescriptor* fd = desc->columns;
for (i = desc->nColumns; --i >= 0;) {
length += strlen(fd->name)+2+3;
if (fd->refTableName != NULL) {
length += strlen(fd->refTableName);
} else if (fd->type == dbField::tpArray && fd->components->refTableName != NULL) {
length += strlen(fd->components->refTableName);
}
if (fd->inverseRefName != NULL) {
length += strlen(fd->inverseRefName);
}
fd = fd->next;
}
dbSmallBuffer response(length+8);
char* p = (char*)response;
pack4(p, length);
pack4(p+4, desc->nColumns);
p += 8;
for (i = desc->nColumns, fd = desc->columns; --i >= 0;) {
int flags = 0;
*p++ = map_type(fd);
if (fd->tTree != 0) {
flags |= cli_indexed;
}
if (fd->hashTable != 0) {
flags |= cli_hashed;
}
*p++ = (char)flags;
strcpy(p, fd->name);
p += strlen(fd->name)+1;
if (fd->refTableName != NULL) {
strcpy(p, fd->refTableName);
p += strlen(p) + 1;
} else if (fd->type == dbField::tpArray && fd->components->refTableName != NULL) {
strcpy(p, fd->components->refTableName);
p += strlen(p) + 1;
} else {
*p++ = '\0';
}
if (fd->inverseRefName != NULL) {
strcpy(p, fd->inverseRefName);
p += strlen(p) + 1;
} else {
*p++ = '\0';
}
fd = fd->next;
}
return session->sock->write(response, length+8);
}
}
bool dbServer::show_tables(dbSession* session)
{
dbTableDescriptor* desc=db->tables;
if (desc == NULL) {
char response[8];
pack4(response, 0);
pack4(response+4, -1);
return session->sock->write(response, sizeof response);
} else {
int length = 0, n = 0;
for (desc=db->tables; desc != NULL; desc=desc->nextDbTable) {
if (strcmp(desc->name, "Metatable")) {
length += strlen(desc->name)+1;
n++;
}
}
dbSmallBuffer response(length+8);
char* p = (char*)response;
pack4(p, length);
pack4(p+4, n);
p += 8;
for (desc=db->tables; desc != NULL; desc=desc->nextDbTable) {
if (strcmp(desc->name, "Metatable")) {
strcpy(p, desc->name);
p += strlen(desc->name)+1;
}
}
return session->sock->write(response, length+8);
}
}
bool dbServer::create_table(dbSession* session, char* data, bool create)
{
db->beginTransaction(dbDatabase::dbExclusiveLock);
db->modified = true;
char* tableName = data;
data += strlen(data) + 1;
int nColumns = *data++ & 0xFF;
cli_field_descriptor* columns = new cli_field_descriptor[nColumns];
for (int i = 0; i < nColumns; i++) {
columns[i].type = (cli_var_type)*data++;
columns[i].flags = *data++ & 0xFF;
columns[i].name = data;
data += strlen(data) + 1;
if (*data != 0) {
columns[i].refTableName = data;
data += strlen(data) + 1;
} else {
columns[i].refTableName = NULL;
data += 1;
}
if (*data != 0) {
columns[i].inverseRefFieldName = data;
data += strlen(data) + 1;
} else {
columns[i].inverseRefFieldName = NULL;
data += 1;
}
}
if (session->existed_tables == NULL) {
session->existed_tables = db->tables;
}
int4 response;
if (create) {
if (session->existed_tables == NULL) {
session->existed_tables = db->tables;
}
response = dbCLI::create_table(db, tableName, nColumns, columns);
} else {
response = dbCLI::alter_table(db, tableName, nColumns, columns);
}
pack4(response);
return session->sock->write(&response, sizeof response);
}
bool dbServer::drop_table(dbSession* session, char* tableName)
{
db->beginTransaction(dbDatabase::dbExclusiveLock);
dbTableDescriptor* desc = db->findTableByName(tableName);
int4 response = cli_ok;
if (desc != NULL) {
db->dropTable(desc);
if (desc == session->existed_tables) {
session->existed_tables = desc->nextDbTable;
}
db->unlinkTable(desc);
desc->nextDbTable = session->dropped_tables;
session->dropped_tables = desc;
} else {
response = cli_table_not_found;
}
pack4(response);
return session->sock->write(&response, sizeof response);
}
bool dbServer::alter_index(dbSession* session, char* data)
{
char* tableName = data;
data += strlen(data) + 1;
char* fieldName = data;
data += strlen(data) + 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -