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 + -
显示快捷键?