📄 subsql.cpp
字号:
elem += fd->components->dbsSize;
}
printf(")");
continue;
case dbField::tpStructure:
if (dateFormat != NULL
&& fd->components->next == fd->components
&& strcmp(fd->components->name, "stamp") == 0)
{
char buf[64];
printf(((dbDateTime*)(base + fd->components->dbsOffs))->asString(buf, sizeof buf, dateFormat));
continue;
}
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::tpRectangle) {
if (node->type != dbList::nTuple) {
return -1;
}
int nCoords = node->aggregate.nComponents;
if (nCoords != rectangle::dim*2) {
return -1;
}
dbList* component = node->aggregate.components;
while (--nCoords >= 0) {
if (component->type != dbList::nInteger && component->type != dbList::nReal) {
return -1;
}
component = component->next;
}
} 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;
}
#ifdef AUTOINCREMENT_SUPPORT
} else if (node->type == dbList::nAutoinc) {
if (fd->type != dbField::tpInt4) {
return -1;
}
#endif
} 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;
coord_t* coord;
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((oid_t)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::tpRectangle:
len = node->aggregate.nComponents;
component = node->aggregate.components;
coord = (coord_t*)(dst + fd->dbsOffs);
assert(len == rectangle::dim*2);
while (--len >= 0) {
*coord++ = (component->type == dbList::nInteger)
? (coord_t)component->ival : (coord_t)component->fval;
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);
dbTable* table = (dbTable*)getRow(desc->tableId);
#ifdef AUTOINCREMENT_SUPPORT
desc->autoincrementCount = table->count;
#endif
int nRows = table->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) {
if (fd->type == dbField::tpRectangle) {
dbRtree::insert(this, fd->tTree, oid, fd->dbsOffs);
} else {
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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -