server.cpp
来自「一个功能强大的内存数据库源代码,c++编写,有详细的注释」· C++ 代码 · 共 1,520 行 · 第 1/3 页
CPP
1,520 行
dbColumnBinding* cb; stmt->firstFetch = false; if (stmt->cursor->isEmpty()) { response = cli_not_found; pack4(response); return session->sock->write(&response, sizeof response); } int msg_size = sizeof(cli_oid_t) + 4; char* data = (char*)db->getRow(stmt->cursor->currId); for (cb = stmt->columns; cb != NULL; cb = cb->next) { if (cb->cliType == cli_autoincrement) { msg_size += 4; } else if (cb->cliType >= cli_array_of_oid) { msg_size += 4 + ((dbVarying*)(data + cb->fd->dbsOffs))->size * sizeof_type[cb->cliType - cli_array_of_oid]; } else if (cb->cliType >= cli_asciiz) { msg_size += 4 + ((dbVarying*)(data + cb->fd->dbsOffs))->size; } else { msg_size += sizeof_type[cb->cliType]; } } if (stmt->buf_size < msg_size) { delete[] stmt->buf; stmt->buf = new char[msg_size]; stmt->buf_size = msg_size; } char* p = stmt->buf; p = pack4(p, msg_size); p = pack_oid(p, stmt->cursor->currId); for (cb = stmt->columns; cb != NULL; cb = cb->next) { char* src = data + cb->fd->dbsOffs; switch (cb->fd->type) { case dbField::tpBool: case dbField::tpInt1: switch (sizeof_type[cb->cliType]) { case 1: *p++ = *src; break; case 2: p = pack2(p, (int2)*(char*)src); break; case 4: p = pack4(p, (int4)*(char*)src); break; case 8: p = pack8(p, (db_int8)*(char*)src); break; default: assert(false); } break; case dbField::tpInt2: switch (sizeof_type[cb->cliType]) { case 1: *p++ = (char)*(int2*)src; break; case 2: p = pack2(p, src); break; case 4: p = pack4(p, (int4)*(int2*)src); break; case 8: p = pack8(p, (db_int8)*(int2*)src); break; default: assert(false); } break; case dbField::tpInt4: switch (sizeof_type[cb->cliType]) { case 1: *p++ = (char)*(int4*)src; break; case 2: p = pack2(p, (int2)*(int4*)src); break; case 4: p = pack4(p, src); break; case 8: p = pack8(p, (db_int8)*(int4*)src); break; default: assert(false); } break; case dbField::tpInt8: switch (sizeof_type[cb->cliType]) { case 1: *p++ = (char)*(db_int8*)src; break; case 2: p = pack2(p, (int2)*(db_int8*)src); break; case 4: p = pack4(p, (int4)*(db_int8*)src); break; case 8: p = pack8(p, src); break; default: assert(false); } break; case dbField::tpReal4: switch (cb->cliType) { case cli_real4: p = pack4(p, src); break; case cli_real8: { real8 temp = *(real4*)src; p = pack8(p, (char*)&temp); } break; default: assert(false); } break; case dbField::tpReal8: switch (cb->cliType) { case cli_real4: { real4 temp = (real4)*(real8*)src; p = pack4(p, (char*)&temp); } break; case cli_real8: p = pack8(p, src); break; default: assert(false); } break; case dbField::tpString: { dbVarying* v = (dbVarying*)src; p = pack4(p, v->size); memcpy(p, data + v->offs, v->size); p += v->size; } break; case dbField::tpReference: p = pack_oid(p, *(oid_t*)src); break; case dbField::tpArray: { dbVarying* v = (dbVarying*)src; int n = v->size; p = pack4(p, n); src = data + v->offs; switch (sizeof_type[cb->cliType-cli_array_of_oid]) { case 2: while (--n >= 0) { p = pack2(p, src); src += 2; } break; case 4: while (--n >= 0) { p = pack4(p, src); src += 4; } break; case 8: while (--n >= 0) { p = pack8(p, src); src += 8; } break; default: memcpy(p, src, n); p += n; } break; } default: assert(false); } } assert(p - stmt->buf == msg_size); return session->sock->write(stmt->buf, msg_size);} bool dbServer::remove(dbSession* session, int stmt_id){ dbStatement* stmt = findStatement(session, stmt_id); int4 response; if (stmt == NULL) { response = cli_bad_descriptor; } else { if (stmt->cursor->isEmpty()) { response = cli_not_found; } else { stmt->cursor->removeAllSelected(); response = cli_ok; } } pack4(response); return session->sock->write(&response, sizeof response);}bool dbServer::update(dbSession* session, int stmt_id, char* new_data){ dbStatement* stmt = findStatement(session, stmt_id); dbColumnBinding* cb; int4 response; if (stmt == NULL) { response = cli_bad_descriptor; pack4(response); return session->sock->write(&response, sizeof response); } if (stmt->cursor->isEmpty()) { response = cli_not_found; pack4(response); return session->sock->write(&response, sizeof response); } char* old_data = stmt->buf + sizeof(cli_oid_t) + 4; for (cb = stmt->columns; cb != NULL; cb = cb->next) { cb->ptr = new_data; if (cb->cliType >= cli_asciiz) { int new_len = unpack4(new_data); int old_len = unpack4(old_data); cb->len = new_len; if (cb->fd->indexType & (HASHED|INDEXED) && memcmp(new_data, old_data, new_len+4) != 0) { cb->fd->attr |= dbFieldDescriptor::Updated; } if (cb->cliType >= cli_array_of_oid) { new_len *= sizeof_type[cb->cliType - cli_array_of_oid]; old_len *= sizeof_type[cb->cliType - cli_array_of_oid]; } new_data += 4 + new_len; old_data += 4 + old_len; } else { int size = sizeof_type[cb->cliType]; if (cb->fd->indexType & (HASHED|INDEXED) && memcmp(new_data, old_data, size) != 0) { cb->fd->attr |= dbFieldDescriptor::Updated; } new_data += size; old_data += size; } } db->beginTransaction(dbDatabase::dbExclusiveLock); dbRecord* rec = db->getRow(stmt->cursor->currId); dbTableDescriptor* table = stmt->query.table; dbFieldDescriptor *first = table->columns, *fd = first; size_t offs = table->fixedSize; do { if (fd->type == dbField::tpArray || fd->type == dbField::tpString) { int len = ((dbVarying*)((char*)rec + fd->dbsOffs))->size; for (cb = stmt->columns; cb != NULL; cb = cb->next) { if (cb->fd == fd) { len = cb->len; break; } } offs = DOALIGN(offs, fd->components->alignment) + len*fd->components->dbsSize; } } while ((fd = fd->next) != first); old_data = new char[rec->size]; memcpy(old_data, rec, rec->size); 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) { 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) { cb->unpackScalar(new_data); 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) { 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_bool && cliType <= cli_int8 && 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++; 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); 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); } } 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) { 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)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?