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

📄 server.cpp

📁 俄罗斯牛人KK的作品,著名的ORDBMS,这里上传最新的3.39版本源代码.希望了解对象关系数据库的同好,请不要错过.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
{
    dbStatement* stmt = findStatement(session, stmt_id);
    int4 response = cli_ok;
    if (stmt == NULL || stmt->cursor == NULL) { 
        response = cli_bad_descriptor;
    } else { 
        stmt->cursor->unfreeze();
    }
    pack4(response);
    return session->sock->write(&response, sizeof response);
}
    
bool dbServer::get_first(dbSession* session, int stmt_id)
{
    dbStatement* stmt = findStatement(session, stmt_id);
    int4 response;
    if (stmt == NULL || stmt->cursor == NULL) { 
        response = cli_bad_descriptor;
    } else if (!stmt->cursor->gotoFirst()) { 
        response = cli_not_found;
    } else { 
        return fetch(session, stmt);
    }
    pack4(response);
    return session->sock->write(&response, sizeof response);
}

bool dbServer::get_last(dbSession* session, int stmt_id)
{
    dbStatement* stmt = findStatement(session, stmt_id);
    int4 response;
    if (stmt == NULL || stmt->cursor == NULL) { 
        response = cli_bad_descriptor;
    } else if (!stmt->cursor->gotoLast()) { 
        response = cli_not_found;
    } else { 
        return fetch(session, stmt);
    }
    pack4(response);
    return session->sock->write(&response, sizeof response);
}

bool dbServer::get_next(dbSession* session, int stmt_id)
{
    dbStatement* stmt = findStatement(session, stmt_id);
    int4 response;
    if (stmt == NULL || stmt->cursor == NULL) { 
        response = cli_bad_descriptor;
    } 
    else if (!((stmt->firstFetch && stmt->cursor->gotoFirst()) ||
               (!stmt->firstFetch && stmt->cursor->moveNext()))) 
    { 
        response = cli_not_found;
    } else { 
        return fetch(session, stmt);
    }
    pack4(response);
    return session->sock->write(&response, sizeof response);
}

bool dbServer::get_prev(dbSession* session, int stmt_id)
{
    dbStatement* stmt = findStatement(session, stmt_id);
    int4 response;
    if (stmt == NULL || stmt->cursor == NULL) { 
        response = cli_bad_descriptor;
    } 
    else if (!((stmt->firstFetch && stmt->cursor->gotoLast()) ||
               (!stmt->firstFetch && stmt->cursor->movePrev()))) 
    { 
        response = cli_not_found;
    } else { 
        return fetch(session, stmt);
    }
    pack4(response);
    return session->sock->write(&response, sizeof response);
}


bool dbServer::skip(dbSession* session, int stmt_id, char* buf)
{
    dbStatement* stmt = findStatement(session, stmt_id);
    int4 response;
    if (stmt == NULL || stmt->cursor == NULL) {
        response = cli_bad_descriptor;
    } else { 
        int n = unpack4(buf);
        if ((n > 0 && !((stmt->firstFetch && stmt->cursor->gotoFirst() && stmt->cursor->skip(n-1)
                         || (!stmt->firstFetch && stmt->cursor->skip(n)))))
            || (n < 0 && !((stmt->firstFetch && stmt->cursor->gotoLast() && stmt->cursor->skip(n+1)
                            || (!stmt->firstFetch && stmt->cursor->skip(n))))))
        {
            response = cli_not_found;
        } else {
            return fetch(session, stmt);
        }
    }
    pack4(response);
    return session->sock->write(&response, sizeof response);
}

bool dbServer::seek(dbSession* session, int stmt_id, char* buf)
{
    dbStatement* stmt = findStatement(session, stmt_id);
    int4 response;
    if (stmt == NULL || stmt->cursor == NULL) {
        response = cli_bad_descriptor;
    } else { 
        oid_t oid = unpack_oid(buf);
        int pos = stmt->cursor->seek(oid); 
        if (pos < 0) { 
            response = cli_not_found;
        } else { 
            return fetch(session, stmt, pos);
        }
    }
    pack4(response);
    return session->sock->write(&response, sizeof response);
}

bool dbServer::fetch(dbSession* session, dbStatement* stmt, oid_t result)
{
    int4 response;
    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, result);

    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::tpRectangle:
            p = pack_rectangle(p, (cli_rectangle_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::remove_current(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->remove();
            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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -