?? class.cpp
字號:
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;
}
void dbTableDescriptor::checkRelationship()
{
dbFieldDescriptor* fd;
for (fd = inverseFields; fd != NULL; fd = fd->nextInverseField)
{
dbTableDescriptor* refTable =
fd->refTable ? fd->refTable : fd->components->refTable;
fd->inverseRef = refTable->findSymbol(fd->inverseRefName);
if (fd->inverseRef == NULL
|| fd->inverseRef->inverseRefName != fd->name)
{
char msg[256];
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);
}
}
}
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::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);
for (dbFieldDescriptor* fd = firstField; fd != NULL; fd = fd->nextField)
{
if (strcmp(fd->longName, (char*)field + field->name.offs) != 0
|| (!fd->refTable && *((char*)field+field->tableName.offs) != '\0')
|| (fd->refTable && strcmp((char*)field + field->tableName.offs,
fd->refTable->name) != 0)
|| (fd->inverseRefName == NULL
&& *((char*)field + field->inverse.offs) != '\0')
|| (fd->inverseRefName != NULL
&& strcmp((char*)field + field->inverse.offs,
fd->inverseRefName) != 0)
|| fd->dbsOffs != field->offset
|| fd->type != field->type)
{
return false;
}
fd->tTree = field->tTree;
fd->hashTable = field->hashTable;
field += 1;
}
return true;
}
dbTableDescriptor::dbTableDescriptor(dbTable* table)
{
next = chain;
chain = this;
cloneOf = NULL;
isStatic = false;
name = (char*)table + table->name.offs;
dbSymbolTable::add
(name, tkn_ident, true);
nextFieldLink = &firstField;
hashedFields = NULL;
indexedFields = NULL;
inverseFields = NULL;
nFields = 0;
nColumns = 0;
fixedSize = table->fixedSize;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -