📄 subsql.cpp
字号:
offs -= sizeof(dbField);
}
table->fields.size = nFields;
table->fixedSize = size;
table->nRows = 0;
table->nColumns = nColumns;
table->firstRow = 0;
table->lastRow = 0;
linkTable(new dbTableDescriptor(table), oid);
if (!completeDescriptorsInitialization()) {
error("Reference to undefined table");
}
}
return tkn == tkn_rpar;
}
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, *(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;
}
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;
}
*(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:
*(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:
*(oid_t*)(dst+fd->dbsOffs) = 0;
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->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 {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -