subsql.cpp

来自「FastDb是高效的内存数据库系统」· C++ 代码 · 共 3,037 行 · 第 1/5 页

CPP
3,037
字号
      fields[nFields++].type = type;
    }
    else if (type == dbField::tpReference)
    {
      fields[nFields-1].refTableName = refTableName;
      varyingLength += strlen(refTableName);

      if (inverseRefName != NULL)
      {
        fields[nFields-1].inverseRefName = inverseRefName;
        varyingLength += strlen(inverseRefName);
      }
    }

    tkn = scan();
  }

  if (tkn == tkn_rpar)
  {
    beginTransaction(dbExclusiveLock);
    dbTableDescriptor* oldDesc = findTable(name);

    if (oldDesc != NULL)
    {
      if (create)
      {
        error("Table already exists");
        return false;
      }
    }
    else
    {
      if (!create)
      {
        error("Table not found");
        return false;
      }
    }

    dbTable* table;
    oid_t oid;

    if (create)
    {
      modified = true;
      oid = allocateRow(dbMetaTableId,
                        sizeof(dbTable) + sizeof(dbField)*nFields + varyingLength);
      table = (dbTable*)getRow(oid);
    }
    else
    {
      oid = oldDesc->tableId;
      table = (dbTable*)new char[sizeof(dbTable) + sizeof(dbField)*nFields + varyingLength];
    }

    int offs = sizeof(dbTable) + sizeof(dbField)*nFields;
    table->name.offs = offs;
    table->name.size = strlen(name)+1;
    strcpy((char*)table + offs, name);
    offs += table->name.size;
    size_t size = sizeof(dbRecord);
    table->fields.offs = sizeof(dbTable);
    dbField* field = (dbField*)((char*)table + table->fields.offs);
    offs -= sizeof(dbTable);
    bool arrayComponent = false;

    for (int i = 0; i < nFields; i++)
    {
      field->name.offs = offs;
      field->name.size = strlen(fields[i].name) + 1;
      strcpy((char*)field + offs, fields[i].name);
      offs += field->name.size;

      field->tableName.offs = offs;

      if (fields[i].refTableName)
      {
        field->tableName.size = strlen(fields[i].refTableName) + 1;
        strcpy((char*)field + offs, fields[i].refTableName);
        offs += field->tableName.size;
      }
      else
      {
        field->tableName.size = 1;
        *((char*)field + offs++) = '\0';
      }

      field->inverse.offs = offs;

      if (fields[i].inverseRefName)
      {
        field->inverse.size = strlen(fields[i].inverseRefName) + 1;
        strcpy((char*)field + offs, fields[i].inverseRefName);
        offs += field->inverse.size;
      }
      else
      {
        field->inverse.size = 1;
        *((char*)field + offs++) = '\0';
      }

      field->type = fields[i].type;
      field->size = typeDesc[fields[i].type].size;

      if (!arrayComponent)
      {
        size = DOALIGN(size, typeDesc[fields[i].type].alignment);
        field->offset = size;
        size += field->size;
      }
      else
      {
        field->offset = 0;
      }

      field->hashTable = 0;
      field->tTree = 0;
      arrayComponent = field->type == dbField::tpArray;
      field += 1;
      offs -= sizeof(dbField);
    }

    table->fields.size = nFields;
    table->fixedSize = size;
    table->nRows = 0;
    table->nColumns = nColumns;
    table->firstRow = 0;
    table->lastRow = 0;

    if (create)
    {
      linkTable(new dbTableDescriptor(table), oid);
    }
    else
    {
      dbTableDescriptor* newDesc = new dbTableDescriptor(table);
      delete[] (char*)table;
      dbTable* oldTable = (dbTable*)getRow(oid);

      if (!newDesc->equal(oldTable))
      {
        bool saveConfirmDeleteColumns = confirmDeleteColumns;
        confirmDeleteColumns = true;
        modified = true;
        schemeVersion += 1;
        unlinkTable(oldDesc);

        if (oldTable->nRows == 0)
        {
          updateTableDescriptor(newDesc, oid);
        }
        else
        {
          reformatTable(oid, newDesc);
        }

        delete oldDesc;
        confirmDeleteColumns = saveConfirmDeleteColumns;
      }
    }

    if (!completeDescriptorsInitialization())
    {
      warning("Reference to undefined table");
    }
  }

  return tkn == tkn_rpar;
}

int dbSubSql::parseType(char*& refTableName, char*& inverseFieldName)
{
  switch (scan())
  {

  case tkn_bool:
    return dbField::tpBool;

  case tkn_int1:
    return dbField::tpInt1;

  case tkn_int2:
    return dbField::tpInt2;

  case tkn_int4:
    return dbField::tpInt4;

  case tkn_int8:
    return dbField::tpInt8;

  case tkn_real4:
    return dbField::tpReal4;

  case tkn_real8:
    return dbField::tpReal8;

  case tkn_array:
    return expect("of", tkn_of) ? dbField::tpArray : dbField::tpUnknown;

  case tkn_string:
    return dbField::tpString;

  case tkn_reference:

    if (expect("to", tkn_to) && expect("referenced table name", tkn_ident))
    {
      refTableName = new char[strlen(buf)+1];
      strcpy(refTableName, buf);
      int tkn = scan();

      if (tkn == tkn_inverse)
      {
        if (!expect("inverse reference field name", tkn_ident))
        {
          return dbField::tpUnknown;
        }

        inverseFieldName = new char[strlen(buf)+1];
        strcpy(inverseFieldName, buf);
      }
      else
      {
        inverseFieldName = NULL;
        ungetToken = tkn;
      }

      return dbField::tpReference;
    }
    else
    {
      return dbField::tpUnknown;
    }

  default:
    error("Field type expected");
  }

  return dbField::tpUnknown;
}

int dbSubSql::readExpression()
{
  int i, ch;

  for (i = 0; (ch = get
                      ()) != ';' && ch != ',' && ch != EOF; i++)
    {
      if (i+1 >= buflen)
      {
        char* newbuf = new char[buflen*2];
        memcpy(newbuf, buf, buflen);
        buf = newbuf;
        buflen *= 2;
      }

      buf[i] = ch;
    }

  buf[i] = '\0';
  return ch;
}

bool dbSubSql::readCondition()
{
  int i, ch;

  for (i = 0; (ch = get
                      ()) != ';' && ch !=  EOF; i++)
    {
      if (i+1 >= buflen)
      {
        char* newbuf = new char[buflen*2];
        memcpy(newbuf, buf, buflen);
        buf = newbuf;
        buflen *= 2;
      }

      buf[i] = ch;
    }

  buf[i] = '\0';

  if (ch != ';')
  {
    error("unexpected end of input");
    return false;
  }

  return true;
}


void dbSubSql::dumpRecord(byte* base, dbFieldDescriptor* first)
{
  int i, n;
  byte* elem;
  dbFieldDescriptor* fd = first;

  do
  {
    if (fd != first)
    {
      printf(", ");
    }

    switch (fd->type)
    {

    case dbField::tpBool:
      printf("%s", *(bool*)(base + fd->dbsOffs)
             ? "true" : "false");
      continue;

    case dbField::tpInt1:
      printf("%d", *(int1*)(base + fd->dbsOffs));
      continue;

    case dbField::tpInt2:
      printf("%d", *(int2*)(base + fd->dbsOffs));
      continue;

    case dbField::tpInt4:
      printf("%d", *(int4*)(base + fd->dbsOffs));
      continue;

    case dbField::tpInt8:
      printf(INT8_FORMAT, *(db_int8*)(base + fd->dbsOffs));
      continue;

    case dbField::tpReal4:
      printf("%f", *(real4*)(base + fd->dbsOffs));
      continue;

    case dbField::tpReal8:
      printf("%f", *(real8*)(base + fd->dbsOffs));
      continue;

    case dbField::tpString:
      printf("'%s'", (char*)base+((dbVarying*)(base+fd->dbsOffs))->offs);
      continue;

    case dbField::tpReference:
      printf("#%x", *(oid_t*)(base + fd->dbsOffs));
      continue;

    case dbField::tpRawBinary:
      n = fd->dbsSize;
      elem = base + fd->dbsOffs;
      printf("(");

      for (i = 0; i < n; i++)
      {
        if (i != 0)
        {
          printf(", ");
        }

        printf("%02x", *elem++);
      }

      printf(")");
      continue;

    case dbField::tpArray:
      n = ((dbVarying*)(base + fd->dbsOffs))->size;
      elem = base + ((dbVarying*)(base + fd->dbsOffs))->offs;
      printf("(");

      for (i = 0; i < n; i++)
      {
        if (i != 0)
        {
          printf(", ");
        }

        dumpRecord(elem, fd->components);
        elem += fd->components->dbsSize;
      }

      printf(")");
      continue;

    case dbField::tpStructure:
      printf("(");
      dumpRecord(base, fd->components);
      printf(")");
    }
  }
  while ((fd = fd->next) != first);
}

int dbSubSql::calculateRecordSize(dbList* node, int offs,
                                  dbFieldDescriptor* first)
{
  dbFieldDescriptor* fd = first;

  do
  {
    if (node == NULL)
    {
      return -1;
    }

    if (fd->type == dbField::tpArray)
    {
      if (node->type != dbList::nTuple)
      {
        return -1;
      }

      int nElems = node->aggregate.nComponents;
      offs = DOALIGN(offs, fd->components->alignment)
             + nElems*fd->components->dbsSize;

      if (fd->attr & dbFieldDescriptor::HasArrayComponents)
      {
        dbList* component = node->aggregate.components;

        while (--nElems >= 0)
        {
          int d = calculateRecordSize(component,offs,fd->components);

          if (d < 0)
            return d;

          offs = d;

          component = component->next;
        }
      }
    }
    else if (fd->type == dbField::tpString)
    {
      if (node->type != dbList::nString)
      {
        return -1;
      }

      offs += strlen(node->sval) + 1;
    }
    else if (fd->type == dbField::tpRawBinary)
    {
      if (node->type != dbList::nTuple)
      {
        return -1;
      }

      int nElems = node->aggregate.nComponents;
      dbList* component = node->aggregate.components;

      if (size_t(nElems) > fd->dbsSize)
      {
        return -1;
      }

      while (--nElems >= 0)
      {
        if (component->type != dbList::nInteger
            || (component->ival & ~0xFF) != 0)
        {
          return -1;
        }

        component = component->next;
      }
    }
    else
    {
      if (!((node->type == dbList::nBool && fd->type == dbField::tpBool)
            || (node->type == dbList::nInteger
                && (fd->type == dbField::tpInt1
                    || fd->type == dbField::tpInt2
                    || fd->type == dbField::tpInt4
                    || fd->type == dbField::tpInt8
                    || fd->type == dbField::tpReference))
            || (node->type == dbList::nReal
                && (fd->type == dbField::tpReal4
                    || fd->type == dbField::tpReal8))
            || (node->type == dbList::nTuple
                && fd->type == dbField::tpStructure)))
      {
        return -1;
      }

      if (fd->attr & dbFieldDescriptor::HasArrayComponents)
      {
        int d = calculateRecordSize(node->aggregate.components,
                                    offs, fd->components);

        if (d < 0)
          return d;

        offs = d;
      }
    }

    node = node->next;
  }
  while ((fd = fd->next) != first);

  return offs;
}

bool dbSubSql::isValidOid(oid_t oid)
{
  return oid == 0 ||
         (oid < currIndexSize && (currIndex[oid] & (dbFreeHandleMarker|dbInternalObjectMarker)) == 0);
}

int dbSubSql::initializeRecordFields(dbList* node, byte* dst, int offs,
                                     dbFieldDescriptor* first)
{
  dbFieldDescriptor* fd = first;
  dbList* component;
  byte* elem;
  int len, elemOffs, elemSize;

  do
  {
    if (node->type == dbList::nString && fd->type != dbField::tpString)
    {
      char* s = node->sval;
      long  ival;

      switch (fd->type)
      {

      case dbField::tpBool:
        *(bool*)(dst+fd->dbsOffs) = *s == '1' || *s == 't' || *s == 'T';
        break;

      case dbField::tpInt1:

        if (sscanf(s, "%ld", &ival) != 1)
        {
          return -1;
        }

        *(int1*)(dst+fd->dbsOffs) = (int1)ival;

      case dbField::tpInt2:

        if (sscanf(s, "%ld", &ival) != 1)
        {
          return -1;
        }

        *(int2*)(dst+fd->dbsOffs) = (int2)ival;

      case dbField::tpInt4:

        if (sscanf(s, "%ld", &ival) != 1)
        {
          return -1;
        }

        *(int4*)(dst+fd->dbsOffs) = (int4)ival;

      case dbField::tpInt8:

        if (sscanf(s, "%ld", &ival) != 1)
        {
          return -1;
        }

        *(db_int8*)(dst+fd->dbsOffs) = ival;
        break;

      case dbField::tpReal4:

        if (sscanf(s, "%f", (real4*)(dst+fd->dbsOffs)) != 1)
        {
          return -1;
        }

        break;

      case dbField::tpReal8:

        if (sscanf(s, "%lf", (real8*)(dst+fd->dbsOffs)) != 1)
        {
          return -1;
        }

        break;
      }

#ifdef AUTOINCREMENT_SUPPORT

    }
    else if (node->type == dbList::nAutoinc)
    {
      if (fd->type != dbField::tpInt4)
      {
        *(int4*)(dst+fd->dbsOffs) = fd->defTable->autoincrementCount;
      }
      else
      {
        return -1;
      }

#endif

    }
    else
    {
      switch (fd->type)
      {

⌨️ 快捷键说明

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