subsql.cpp
来自「FastDb是高效的内存数据库系统」· C++ 代码 · 共 3,037 行 · 第 1/5 页
CPP
3,037 行
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::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;
}
bool dbSubSql::updateFields(dbAnyCursor* cursor, dbUpdateElement* elems)
{
char buf[64], *src;
dbInheritedAttribute iattr;
dbSynthesizedAttribute sattr;
iattr.db = this;
iattr.oid = cursor->currId;
iattr.table = (dbTable*)getRow(cursor->table->tableId);
iattr.record = (byte*)getRow(cursor->currId);
iattr.paramBase = (size_t)cursor->paramBase;
do
{
dbExprNode* expr = elems->value;
dbFieldDescriptor* fd = elems->field;
execute(expr, iattr, sattr);
byte* dst = cursor->record + fd->appOffs;
switch (fd->type)
{
case dbField::tpBool:
switch (expr->type)
{
case tpInteger:
*(bool*)dst = sattr.ivalue != 0;
continue;
case tpBoolean:
*(bool*)dst = sattr.bvalue;
continue;
case tpReal:
*(bool*)dst = sattr.fvalue != 0;
continue;
case tpString:
*(bool*)dst = *sattr.base == 'T' || *sattr.base == 't' || *sattr.base == '1';
continue;
}
break;
case dbField::tpInt1:
switch (expr->type)
{
case tpInteger:
*(int1*)dst = (int1)sattr.ivalue;
continue;
case tpBoolean:
*(int1*)dst = sattr.bvalue ? 1 : 0;
continue;
case tpReal:
*(int1*)dst = (int1)sattr.fvalue;
continue;
case tpString:
*(int1*)dst = (int1)atoi((char*)sattr.base);
continue;
}
break;
case dbField::tpInt2:
switch (expr->type)
{
case tpInteger:
*(int2*)dst = (int2)sattr.ivalue;
continue;
case tpBoolean:
*(int2*)dst = sattr.bvalue ? 1 : 0;
continue;
case tpReal:
*(int2*)dst = (int2)sattr.fvalue;
continue;
case tpString:
*(int2*)dst = (int2)atoi((char*)sattr.base);
continue;
}
break;
case dbField::tpInt4:
switch (expr->type)
{
case tpInteger:
*(int4*)dst = (int4)sattr.ivalue;
continue;
case tpBoolean:
*(int4*)dst = sattr.bvalue ? 1 : 0;
continue;
case tpReal:
*(int4*)dst = (int4)sattr.fvalue;
continue;
case tpString:
*(int4*)dst = (int1)atoi((char*)sattr.base);
continue;
}
break;
case dbField::tpInt8:
switch (expr->type)
{
case tpInteger:
*(db_int8*)dst = sattr.ivalue;
continue;
case tpBoolean:
*(db_int8*)dst = sattr.bvalue ? 1 : 0;
continue;
case tpReal:
*(db_int8*)dst = (db_int8)sattr.fvalue;
continue;
case tpString:
*(db_int8*)dst = (db_int8)atoi((char*)sattr.base);
continue;
}
break;
case dbField::tpReal4:
switch (expr->type)
{
case tpInteger:
*(real4*)dst = (real4)sattr.ivalue;
continue;
case tpBoolean:
*(real4*)dst = (real4)(sattr.bvalue ? 1 : 0);
continue;
case tpReal:
*(real4*)dst = (real4)sattr.fvalue;
continue;
case tpString:
*(real4*)dst = (real4)atof((char*)sattr.base);
continue;
}
break;
case dbField::tpReal8:
switch (expr->type)
{
case tpInteger:
*(real8*)dst = (real8)sattr.ivalue;
continue;
case tpBoolean:
*(real8*)dst = sattr.bvalue ? 1.0 : 0.0;
continue;
case tpReal:
*(real8*)dst = sattr.fvalue;
continue;
case tpString:
*(real8*)dst = atof((char*)sattr.base);
continue;
}
break;
case dbField::tpString:
src = buf;
switch (expr->type)
{
case tpInteger:
sprintf(buf, INT8_FORMAT, sattr.ivalue);
break;
case tpBoolean:
strcpy(buf, sattr.bvalue ? "t" : "f");
break;
case tpReal:
sprintf(buf, "%f", sattr.fvalue);
break;
case tpString:
src = (char*)sattr.base;
break;
}
*(char**)dst = new char[strlen(src)+1];
strcpy(*(char**)dst, src);
elems->strValue = *(char**)dst;
continue;
case dbField::tpReference:
if (expr->type == tpInteger)
{
*(oid_t*)dst = sattr.oid;
continue;
}
}
assert(false);
}
while ((elems = elems->next) != NULL);
return true;
}
bool dbSubSql::parse()
{
dbTableDescriptor* desc;
dbFieldDescriptor* fd;
int tkn;
bool count, outputOid, compactify;
line = 1;
pos = 0;
while (true)
{
if (in == stdin)
{
printf(prompt);
tkn = scan();
pos += strlen(prompt);
}
else
{
tkn = scan();
}
switch (tkn)
{
case tkn_update:
if (!opened)
{
error("Database not opened");
continue;
}
if (accessType == dbReadOnly)
{
error("Operation is not possible in read-only mode");
continue;
}
if (expect("table name", tkn_ident))
{
if ((desc = findTable(name)) == NULL)
{
error("No such table in database");
continue;
}
if (!expect("set", tkn_set))
{
continue;
}
dbDatabaseThreadContext* ctx = threadContext.get();
byte *record = dbMalloc(desc->appSize);
ctx->interactive = true;
ctx->catched = true;
dbUpdateElement* elems = NULL;
if (!expect("field name", tkn_ident))
{
goto updateCleanup;
}
#ifdef THROW_EXCEPTION_ON_ERROR
try
{
#else
if (setjmp(ctx->unwind) == 0)
{
#endif
char* condition = NULL;
int startPos = pos;
while (true)
{
dbUpdateElement* elem = new dbUpdateElement;
dbFieldDescriptor* fd = desc->findSymbol(name);
if (fd == NULL)
{
error("No such field in the table");
goto updateCleanup;
}
if (fd->type > dbField::tpReference)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?