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

📄 class.cpp

📁 最新版本!fastdb是高效的内存数据库系统
💻 CPP
📖 第 1 页 / 共 4 页
字号:
}


int dbTableDescriptor::initialAutoincrementCount;


dbTableDescriptor::dbTableDescriptor(char const*        tableName, 
                                     dbDatabase*        database,
                                     size_t             objSize, 
                                     describeFunc       func,
                                     dbTableDescriptor* original)
{
    cloneOf = original;
    if (original == NULL) {
        isStatic = true;
        link();
    } else {
        isStatic = false;
    }
    name = (char*)tableName;
    dbSymbolTable::add(name, tkn_ident, FASTDB_CLONE_ANY_IDENTIFIER);
    describeComponentsFunc = func;
    columns = (*func)();
    nextFieldLink = &firstField;
    hashedFields = NULL;
    indexedFields = NULL;
    inverseFields = NULL;
    tableId = 0;
    nFields = 0;
    nColumns = 0;
    db = database;
    fixedDatabase = database != NULL;
    fixedSize = sizeof(dbRecord);
    int attr = dbFieldDescriptor::OneToOneMapping;
    appSize = 0;
    autoincrementCount = initialAutoincrementCount;
    size_t maxAlignment = calculateFieldsAttributes(columns, "", 
                                                    sizeof(dbRecord), 
                                                    HASHED|INDEXED, attr);
#if CHECK_RECORD_SIZE
    appSize = DOALIGN(appSize, maxAlignment);
    if (appSize < objSize) { 
        fprintf(stderr, "Warning: may be not all fields of the class '%s' "
                "were described\n", name);
    }
#endif
    *nextFieldLink = NULL;
}


int dbTableDescriptor::calculateFieldsAttributes(dbFieldDescriptor* first,
                                                 char const*        prefix, 
                                                 int                offs,
                                                 int                indexMask, 
                                                 int&               attr)
{
    dbFieldDescriptor *field = first;
    size_t alignment = 1;
    do { 
        if (field->method) { 
            assert(((void)"Not empty record", field != first));
            do { 
                assert(((void)"Methods should be specified after variables", 
                        field->method != NULL));
                field->dbsOffs = first->dbsOffs;
                field->components = first;
                if (attr & dbFieldDescriptor::OneToOneMapping) { 
                    field->method = field->method->optimize();
                }
            } while ((field = field->next) != first);
            break;
        }
        if (*prefix != '\0') { 
            char* p = new char[strlen(prefix)+strlen(field->name)+1];
            sprintf(p, "%s%s", prefix, field->name);
            field->longName = p;
        } else { 
            nColumns += 1;
            field->longName = new char[strlen(field->name)+1];
            strcpy(field->longName, field->name);
        }
        field->defTable = this;
        field->indexType &= indexMask|DB_FIELD_INHERITED_MASK;
        field->attr = (attr & dbFieldDescriptor::ComponentOfArray) 
                    | dbFieldDescriptor::OneToOneMapping;
        if (field->inverseRefName) { 
            assert(!(attr & dbFieldDescriptor::ComponentOfArray)
                   && (field->type == dbField::tpReference 
                       || (field->type == dbField::tpArray 
                           && field->components->type==dbField::tpReference)));
            field->nextInverseField = inverseFields;
            inverseFields = field; 
        }
        *nextFieldLink = field;
        nextFieldLink = &field->nextField;
        field->fieldNo = nFields++;
                   
        switch (field->type) { 
          case dbField::tpArray:
            { 
                size_t saveOffs = fixedSize;
                size_t saveAppSize = appSize;
                fixedSize = 0;
                attr = (attr | dbFieldDescriptor::HasArrayComponents)
                     & ~dbFieldDescriptor::OneToOneMapping;
                field->attr |= dbFieldDescriptor::ComponentOfArray;
                calculateFieldsAttributes(field->components, field->longName,
                                          0, 0, field->attr);
                if (field->components->dbsSize != field->components->appSize) {
                    field->attr &= ~dbFieldDescriptor::OneToOneMapping;
                }
                fixedSize = saveOffs;
                appSize = DOALIGN(saveAppSize, sizeof(void*)) 
                    + sizeof(void*)*3;
                break;
            }
          case dbField::tpStructure:
            { 
                char* aggregateName = new char[strlen(field->longName) + 2];
                sprintf(aggregateName, "%s.", field->longName);
                size_t saveOffs = fixedSize;        
                size_t saveAppSize = appSize;       
                appSize = 0;
                size_t struct_alignment = 
                    calculateFieldsAttributes(field->components, 
                                              aggregateName,
                                              offs + field->appOffs, 
                                              field->indexType,
                                              field->attr);
                field->alignment = struct_alignment;
                field->dbsOffs = field->components->dbsOffs;
                attr |= field->attr & dbFieldDescriptor::HasArrayComponents;
                attr &= field->attr | ~dbFieldDescriptor::OneToOneMapping;
                field->dbsSize = DOALIGN(fixedSize-saveOffs, struct_alignment);
                if ((field->attr & dbFieldDescriptor::HasArrayComponents)
                    && struct_alignment < sizeof(void*))
                {
                    struct_alignment = sizeof(void*);
                }
                appSize = DOALIGN(appSize, struct_alignment) 
                        + DOALIGN(saveAppSize, struct_alignment);
                delete[] aggregateName;
                break;
            } 
          case dbField::tpString:
            attr = (attr | dbFieldDescriptor::HasArrayComponents)
                & ~dbFieldDescriptor::OneToOneMapping;
            // no break
          default:
            appSize = DOALIGN(appSize, field->appSize) + field->appSize;
        }
        if (alignment < field->alignment) { 
            alignment = field->alignment;
        }
        if (field->type != dbField::tpStructure) { 
            field->dbsOffs = fixedSize = DOALIGN(fixedSize, field->alignment);
            fixedSize += field->dbsSize;
            if (field->dbsOffs != offs + field->appOffs) { 
                attr &= ~dbFieldDescriptor::OneToOneMapping;
            }

            if (field->indexType & (HASHED|INDEXED)) {
                assert(!(field->attr & dbFieldDescriptor::ComponentOfArray));
                if (field->indexType & HASHED) { 
                    field->nextHashedField = hashedFields;
                    hashedFields = field;
                }
                if (field->indexType & INDEXED) { 
                    field->nextIndexedField = indexedFields;
                    indexedFields = field;
                }
            }
        }
    } while ((field = field->next) != first);

    return alignment;
}


int dbFieldDescriptor::sizeWithoutOneField(dbFieldDescriptor* field, 
                                           byte* base, size_t& size)
{
    dbFieldDescriptor* fd = this;
    int offs, last = 0;
    do { 
        if (fd != field) { 
            if (fd->type == dbField::tpArray || fd->type == dbField::tpString){
                dbVarying* arr = (dbVarying*)(base + fd->dbsOffs);
                if (arr->offs > last) { 
                    last = arr->offs;
                }
                int n = arr->size;
                size = DOALIGN(size, fd->components->alignment)
                     + fd->components->dbsSize * n;
                if (fd->attr & HasArrayComponents) { 
                    byte* elem = base + arr->offs;
                    while (--n >= 0) {
                        offs = fd->components->sizeWithoutOneField(field, 
                                                                   elem, size);
                        if (arr->offs + offs > last) { 
                            last = arr->offs + offs;
                        }
                        elem += fd->components->dbsSize;
                    }
                }
            } else if (fd->attr & HasArrayComponents) { 
                offs = fd->components->sizeWithoutOneField(field, base, size);
                if (offs > last) { 
                    last = offs;
                }
            }
        }
    } while ((fd = fd->next) != this);

    return last;
}


size_t dbFieldDescriptor::copyRecordExceptOneField(dbFieldDescriptor* field, 
                                                   byte* dst, byte* src, 
                                                   size_t offs)
{
    dbFieldDescriptor* fd = this;
    do { 
        if (fd != field) { 
            if (fd->type == dbField::tpArray || fd->type == dbField::tpString){
                dbVarying* srcArr = (dbVarying*)(src + fd->dbsOffs);
                dbVarying* dstArr = (dbVarying*)(dst + fd->dbsOffs);
                int n = srcArr->size;
                byte* srcElem = src + srcArr->offs;
                offs = DOALIGN(offs, fd->components->alignment);
                byte* dstElem = dst + offs;
                dstArr->offs = offs;
                dstArr->size = n;
                size_t sizeElem = fd->components->dbsSize;
                size_t offsElem = sizeElem * n;
                offs += offsElem;
                if (fd->attr & HasArrayComponents) { 
                    while (--n >= 0) {
                        offsElem = fd->components->
                            copyRecordExceptOneField(field, dstElem, srcElem,
                                                     offsElem);
                        offsElem -= sizeElem;
                        dstElem += sizeElem;
                        srcElem += sizeElem;
                    }
                    offs += offsElem;
                } else { 
                    memcpy(dstElem, srcElem, offsElem);
                } 
            } else if (fd->attr & HasArrayComponents) { 
                offs = fd->components->copyRecordExceptOneField(field, dst, 
                                                                src, offs);
            } else if (fd->method == NULL) {
                memcpy(dst+fd->dbsOffs, src+fd->dbsOffs, fd->dbsSize);
            }
        }
    } while ((fd = fd->next) != this);

    return offs;
}


bool dbTableDescriptor::checkRelationship() 
{
    dbFieldDescriptor* fd;
    bool result = true;
    for (fd = inverseFields; fd != NULL; fd = fd->nextInverseField) { 
        char msg[MAX_MSG_SIZE];
        dbTableDescriptor* refTable = 
            fd->refTable ? fd->refTable : fd->components->refTable;
        if (refTable == NULL) { 
            result = false;
            sprintf(msg, "Failed to locate referenced table %s", refTable->name);
            db->handleError(dbDatabase::InconsistentInverseReference, msg);
        } else { 
            fd->inverseRef = refTable->findSymbol(fd->inverseRefName);
            if (fd->inverseRef == NULL 
                || fd->inverseRef->inverseRefName != fd->name)
            {
                result = false;
                if (fd->inverseRef == NULL) { 
                    sprintf(msg, "Failed to locate inverse reference field %s.%s for field %s.%s", 
                            refTable->name, fd->inverseRefName, fd->defTable->name, fd->longName);
                } else {
                    sprintf(msg, "Inverse references for field %s.%s is %s.%s, but its inverse reference is %s", 
                            fd->defTable->name, fd->longName, refTable->name, fd->inverseRefName, fd->inverseRef->inverseRefName);
                }
                db->handleError(dbDatabase::InconsistentInverseReference, msg);
            } 
        }
    }
    return result;
}

dbFieldDescriptor* dbTableDescriptor::find(char const* name)
{
    char* symnam = (char*)name;
    dbSymbolTable::add(symnam, tkn_ident);
    return findSymbol(symnam);
}

dbFieldDescriptor* dbTableDescriptor::findSymbol(const char* name)
{
    dbFieldDescriptor* first = columns;
    dbFieldDescriptor* field = first;
    do { 
        if (field->name == name) { 
            return field;
        }
    } while ((field = field->next) != first);
    return NULL;
}

dbFieldDescriptor& dbFieldDescriptor::adjustOffsets(long offs)
{
    if (offs != 0) { 
        dbFieldDescriptor* fd = this;
        do { 
            fd->appOffs += offs;
        } while ((fd = fd->next) != this);
    }
    return *this;
}




bool dbTableDescriptor::match(dbTable* table, bool confirmDeleteColumns) 
{
    unsigned nFields = table->fields.size;
    unsigned nMatches = 0;
    bool formatNotChanged = (nFields == this->nFields);

    for (dbFieldDescriptor* fd = firstField; fd != NULL; fd = fd->nextField) { 
        dbField* field = (dbField*)((char*)table + table->fields.offs);
        fd->oldDbsType = dbField::tpUnknown;
        for (int n = nFields; --n >= 0; field++) { 
            if (strcmp(fd->longName, (char*)field + field->name.offs) == 0) {
                assert(((void)"field can be converted to new format",
                        (fd->type == dbField::tpReference
                         && field->type == dbField::tpReference
                         && strcmp((char*)field + field->tableName.offs,
                                      fd->refTable->name) == 0)
                        || (fd->type <= dbField::tpReal8 
                            && field->type <= dbField::tpReal8)
                        || (fd->type == dbField::tpString
                            && field->type == dbField::tpString)
                        || (fd->type == dbField::tpRectangle
                            && field->type == dbField::tpRectangle)
                        || (fd->type >= dbField::tpArray
                            && fd->type == field->type)));
                fd->oldDbsType = field->type;
                fd->oldDbsOffs = field->offset;
                fd->oldDbsSize = field->size;
                if (field->type != fd->type || field->offset != fd->dbsOffs) {
                    formatNotChanged = false;
                }
                nMatches += 1;
                //
                // Try to reuse indices
                //
                fd->hashTable = 0;
                fd->tTree = 0;

                if (field->type == fd->type) { 
                    if ((fd->indexType & HASHED) != 0 && field->hashTable != 0) { 
                        fd->hashTable = field->hashTable; // reuse index
                        field->hashTable = 0; // prevent index from destruction
                    }
                    if ((fd->indexType & INDEXED) != 0 && field->tTree != 0) { 
                        fd->tTree = field->tTree; // reuse index
                        field->tTree = 0; // prevent index from destruction
                    }
                }
                break;
            }
        }
    }
    if (!confirmDeleteColumns) {             
        assert(((void)"field can be removed only from empty table",
                nFields==nMatches));
    }
    return formatNotChanged;
}

void dbTableDescriptor::setFlags() { 
    for (dbFieldDescriptor* fd = firstField; fd != NULL; fd = fd->nextField) {
        if (fd->tTree != 0) { 
            fd->indexType |= INDEXED;
        } else if (fd->hashTable != 0) { 
            fd->indexType |= HASHED;
        }
    }
}


bool dbTableDescriptor::equal(dbTable* table) 
{
#ifdef AUTOINCREMENT_SUPPORT
    autoincrementCount = table->count;
#endif
    if (nColumns != table->nColumns || 
        nFields != table->fields.size || fixedSize != table->fixedSize) 
    { 
        return false;
    }
    dbField* field = (dbField*)((char*)table + table->fields.offs);

⌨️ 快捷键说明

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