subsql.cpp
来自「一个功能强大的内存数据库源代码,c++编写,有详细的注释」· C++ 代码 · 共 1,947 行 · 第 1/4 页
CPP
1,947 行
int dbSubSql::parseType(){ 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: return expect("to", tkn_to) && expect("referenced table name", tkn_ident) ? dbField::tpReference : 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) { case dbField::tpBool: *(bool*)(dst+fd->dbsOffs) = node->bval; break; case dbField::tpInt1: *(int1*)(dst+fd->dbsOffs) = (int1)node->ival; break; case dbField::tpInt2: *(int2*)(dst+fd->dbsOffs) = (int2)node->ival; break; case dbField::tpInt4: *(int4*)(dst+fd->dbsOffs) = (int4)node->ival; break; case dbField::tpInt8: *(db_int8*)(dst+fd->dbsOffs) = node->ival; break; case dbField::tpReal4: *(real4*)(dst+fd->dbsOffs) = (real4)node->fval; break; case dbField::tpReal8: *(real8*)(dst+fd->dbsOffs) = node->fval; break; case dbField::tpReference: if (isValidOid(node->ival)) { *(oid_t*)(dst+fd->dbsOffs) = (oid_t)node->ival; } else { return -1; } break; case dbField::tpString: ((dbVarying*)(dst+fd->dbsOffs))->offs = offs; len = strlen(node->sval) + 1; ((dbVarying*)(dst+fd->dbsOffs))->size = len; memcpy(dst + offs, node->sval, len); offs += len; break; case dbField::tpRawBinary: len = node->aggregate.nComponents; component = node->aggregate.components; elem = dst + fd->dbsOffs; while (--len >= 0) { *elem++ = (byte)component->ival; component = component->next; } break; case dbField::tpArray: len = node->aggregate.nComponents; elem = (byte*)DOALIGN(long(dst) + offs, fd->components->alignment); offs = elem - dst; ((dbVarying*)(dst+fd->dbsOffs))->offs = offs; ((dbVarying*)(dst+fd->dbsOffs))->size = len; elemSize = fd->components->dbsSize; elemOffs = len*elemSize; offs += elemOffs; component = node->aggregate.components; while (--len >= 0) { elemOffs = initializeRecordFields(component, elem, elemOffs, fd->components); elemOffs -= elemSize; elem += elemSize; component = component->next; } offs += elemOffs; break; case dbField::tpStructure: offs = initializeRecordFields(node->aggregate.components, dst, offs, fd->components); } } node = node->next; } while ((fd = fd->next) != first); return offs;}bool dbSubSql::insertRecord(dbList* list, dbTableDescriptor* desc){ int size = calculateRecordSize(list, desc->fixedSize, desc->columns); if (size < 0) { error("Incompatible types in insert statement"); return false; } oid_t oid = allocateRow(desc->tableId, size); byte* dst = (byte*)getRow(oid); initializeRecordFields(list, dst, desc->fixedSize, desc->columns); int nRows = ((dbTable*)getRow(desc->tableId))->nRows; dbFieldDescriptor* fd; for (fd = desc->hashedFields; fd != NULL; fd = fd->nextHashedField){ dbHashTable::insert(this, fd->hashTable, oid, fd->type, fd->dbsSize, fd->dbsOffs, nRows); } for (fd = desc->indexedFields; fd != NULL; fd = fd->nextIndexedField) { dbTtree::insert(this, fd->tTree, oid, fd->type, fd->dbsSize, fd->comparator, fd->dbsOffs); } return true;}int dbSubSql::readValues(dbList** chain){ int i, n = 0; int tkn; dbList* node; while (true) { switch (scan()) { case tkn_lpar: node = new dbList(dbList::nTuple); node->aggregate.components = NULL; i = readValues(&node->aggregate.components); if (i < 0) { return -1; } node->aggregate.nComponents = i; break; case tkn_rpar: return -n; // valid only in case of empty list case tkn_iconst: node = new dbList(dbList::nInteger); node->ival = ival; break; case tkn_true: node = new dbList(dbList::nBool); node->bval = true; break; case tkn_false: node = new dbList(dbList::nBool); node->bval = false; break; case tkn_fconst: node = new dbList(dbList::nReal); node->fval = fval; break; case tkn_sconst: node = new dbList(dbList::nString); node->sval = new char[strlen(buf)+1]; strcpy(node->sval, buf); break; case tkn_autoincrement: node = new dbList(dbList::nAutoinc); break; case tkn_error: return -1; default: error("Syntax error in insert list"); return -1; } *chain = node; chain = &node->next; n += 1; if ((tkn = scan()) == tkn_rpar) { return n; } if (tkn != tkn_comma) { error("',' expected"); return -1; } }}dbFieldDescriptor* dbSubSql::readFieldName(){ int tkn; if (expect("table name", tkn_ident)) { dbTableDescriptor* desc; dbFieldDescriptor* fd; if ((desc = findTable(name)) == NULL) { error("No such table in database"); return NULL; } if (expect(".", tkn_dot) && expect("field name", tkn_ident)) { if ((fd = desc->findSymbol(name)) == NULL) { error("No such field in the table"); return NULL; } else if (fd->type == dbField::tpArray) { error("Array components can not be indexed"); return NULL; } } else { return NULL; } while ((tkn = scan()) != tkn_semi) { if (tkn != tkn_dot) { error("'.' expected"); return NULL; } if (expect("field name", tkn_ident)) { if ((fd = fd->find(name)) == NULL) { error("No such field in the table"); return NULL; } else if (fd->type == dbField::tpArray) { error("Array components can not be indexed"); return NULL; } } else { return NULL; } } if (fd->type == dbField::tpStructure) { error("Structures can not be indexed"); return NULL; } return fd; } return NULL;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?