⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.cpp

📁 俄罗斯牛人KK的作品,著名的ORDBMS,这里上传最新的3.39版本源代码.希望了解对象关系数据库的同好,请不要错过.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    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 + -