📄 compiler.cpp
字号:
{
if (lex != tkn_start) {
return;
}
int pos = currPos;
if (scan() != tkn_from) {
error("FROM expected after START", pos);
}
pos = currPos;
switch (scan()) {
case tkn_first:
query.startFrom = dbCompiledQuery::StartFromFirst;
break;
case tkn_last:
query.startFrom = dbCompiledQuery::StartFromLast;
break;
case tkn_var:
if (varType == dbQueryElement::qVarReference) {
if (varRefTable != table) {
error("Incompatiable type of reference variable");
}
query.startFrom = dbCompiledQuery::StartFromRef;
} else if (varType == dbQueryElement::qVarArrayOfRef) {
if (varRefTable != table) {
error("Incompatiable type of array of reference variable");
}
query.startFrom = dbCompiledQuery::StartFromArray;
} else if (varType == dbQueryElement::qVarArrayOfRefPtr) {
if (varRefTable != table) {
error("Incompatiable type of array of reference variable");
}
query.startFrom = dbCompiledQuery::StartFromArrayPtr;
} else {
error("Reference or array of reference variable expected");
}
query.root = varPtr;
break;
default:
error("FIRST, LAST or reference varaible expected", pos);
}
if ((lex = scan()) == tkn_follow) {
pos = currPos;
if (scan() != tkn_by) {
error("BY expected after FOLLOW", pos);
}
do {
pos = currPos;
if (scan() != tkn_ident) {
error("Field name expected", pos);
}
dbFieldDescriptor* fd;
if ((fd = table->findSymbol(name)) == NULL) {
error("Field not found");
}
while (fd->type == dbField::tpStructure) {
pos = currPos;
if (scan() != tkn_dot) {
error("'.' expected", pos);
}
pos = currPos;
if (scan() != tkn_ident) {
error("Field name expected", pos);
}
if ((fd = fd->find(name)) == NULL) {
error("Field not found");
}
}
if (!(fd->type == dbField::tpReference
&& fd->refTable == table) &&
!(fd->type == dbField::tpArray
&& fd->components->type == dbField::tpReference
&& fd->components->refTable == table))
{
error("Follow field should be of compatibale reference "
"or array of reference type");
}
dbFollowByNode* node = new dbFollowByNode;
node->field = fd;
node->next = query.follow; // list should be inverted
query.follow = node;
} while ((lex = scan()) == tkn_comma);
}
}
void dbCompiler::deleteNode(dbExprNode* node) {
dbMutex& mutex = dbExprNodeAllocator::instance.getMutex();
dbCriticalSection cs(mutex);
delete node;
}
void dbCompiler::compileLimitPart(dbQuery& query)
{
if (lex == tkn_limit) {
int pos = currPos;
size_t l1 = 0;
int4* lp1 = NULL;
switch (scan()) {
case tkn_iconst:
l1 = (size_t)ivalue;
break;
case tkn_var:
if (varType != dbQueryElement::qVarInt4) {
error("LIMIT parameter should have int4 type", pos);
}
lp1 = (int4*)varPtr;
break;
default:
error("Parameter or integer constant expected", pos);
}
if ((lex = scan()) == tkn_comma) {
pos = currPos;
size_t l2 = 0;
int4* lp2 = NULL;
switch (scan()) {
case tkn_iconst:
l2 = (size_t)ivalue;
break;
case tkn_var:
if (varType != dbQueryElement::qVarInt4) {
error("LIMIT parameter should have int4 type", pos);
}
lp2 = (int4*)varPtr;
break;
default:
error("Parameter or integer constant expected", pos);
}
query.stmtLimitStart = l1;
query.stmtLimitStartPtr = lp1;
query.stmtLimitLen = l2;
query.stmtLimitLenPtr = lp2;
lex = scan();
} else {
query.stmtLimitStart = 0;
query.stmtLimitStartPtr = NULL;
query.stmtLimitLen = l1;
query.stmtLimitLenPtr = lp1;
}
query.limitSpecified = true;
}
}
void dbCompiler::compileOrderByPart(dbQuery& query)
{
if (lex == tkn_order) {
dbOrderByNode** opp = &query.order;
int pos = currPos;
if (scan() != tkn_by) {
error("BY expected after ORDER", pos);
}
int parentheses = 0;
do {
pos = currPos;
int tkn = scan();
if (tkn == tkn_lpar) {
parentheses += 1;
} else {
ungetToken(tkn);
}
dbExprNode* expr = disjunction();
dbOrderByNode* node = new dbOrderByNode;
switch (expr->cop) {
case dbvmLoadSelfBool:
case dbvmLoadSelfInt1:
case dbvmLoadSelfInt2:
case dbvmLoadSelfInt4:
case dbvmLoadSelfInt8:
case dbvmLoadSelfReal4:
case dbvmLoadSelfReal8:
case dbvmLoadSelfString:
case dbvmLoadSelfArray:
case dbvmLoadSelfReference:
case dbvmLoadSelfRawBinary:
assert(expr->ref.field != NULL);
node->field = expr->ref.field;
node->expr = NULL;
deleteNode(expr);
break;
case dbvmLength:
if (expr->operand[0]->cop == dbvmLoadSelfArray) {
node->field = expr->operand[0]->ref.field;
node->expr = NULL;
deleteNode(expr);
break;
}
// no break
default:
if (expr->type > tpReference) {
error("Expressions in ORDER BY part should have scalar type", pos);
}
node->field = NULL;
node->expr = expr;
}
node->table = table;
node->ascent = true;
*opp = node;
opp = &node->next;
*opp = NULL;
if (lex == tkn_desc) {
node->ascent = false;
lex = scan();
} else if (lex == tkn_asc) {
lex = scan();
}
if (lex == tkn_rpar) {
if (--parentheses < 0) {
error("Unbalanced parentheses ");
}
lex = scan();
}
} while (lex == tkn_comma);
}
}
dbExprNode* dbCompiler::compileExpression(dbTableDescriptor* table, char const* expr, int startPos)
{
TRACE_MSG(("Compile expression %s for table %s\n", table->name));
if (setjmp(abortCompilation) == 0) {
this->table = table;
bindings = NULL;
nFreeVars = 0;
dbQueryElement elem(dbQueryElement::qExpression, expr, NULL);
queryElement = &elem;
currPos = firstPos = 0;
offsetWithinStatement = startPos;
return disjunction();
} else {
return NULL;
}
}
bool dbCompiler::compile(dbTableDescriptor* table, dbQuery& query)
{
TRACE_MSG(("Compile query for table %s\n", table->name));
query.destroy();
if (setjmp(abortCompilation) == 0) {
this->table = table;
bindings = NULL;
nFreeVars = 0;
queryElement = query.elements;
currPos = firstPos = 0;
hasToken = false;
offsetWithinStatement = query.pos;
lex = tkn_eof;
dbExprNode* expr = disjunction();
if (expr->type != tpBoolean && expr->type != tpVoid) {
error("Conditional expression should have boolean type\n");
}
compileStartFollowPart(query);
compileOrderByPart(query);
compileLimitPart(query);
if (lex != tkn_eof) {
error("START, ORDER BY or LIMIT expected");
}
query.tree = expr;
query.table = table;
return true;
} else {
dbMutex& mutex = dbExprNodeAllocator::instance.getMutex();
dbCriticalSection cs(mutex);
for (dbOrderByNode *op = query.order, *nop; op != NULL; op = nop) {
nop = op->next;
delete op;
}
for (dbFollowByNode *fp = query.follow, *nfp; fp != NULL; fp = nfp) {
nfp = fp->next;
delete fp;
}
return false;
}
}
dbCompiler::dbCompiler() {
static struct {
char* name;
int tag;
} keywords[] = {
{"all", tkn_all},
{"abs", tkn_abs},
{"and", tkn_and},
{"area", tkn_area},
{"asc", tkn_asc},
{"between", tkn_between},
{"by", tkn_by},
{"current", tkn_current},
{"desc", tkn_desc},
{"escape", tkn_escape},
{"exists", tkn_exists},
{"first", tkn_first},
{"false", tkn_false},
{"follow", tkn_follow},
{"from", tkn_from},
{"in", tkn_in},
{"is", tkn_is},
{"integer", tkn_integer},
{"insert", tkn_insert},
{"into", tkn_into},
{"last", tkn_last},
{"length", tkn_length},
{"like", tkn_like},
{"limit", tkn_limit},
{"lower", tkn_lower},
#ifdef USE_REGEX
{"match", tkn_match},
#endif
{"not", tkn_not},
{"null", tkn_null},
{"or", tkn_or},
{"order", tkn_order},
{"overlaps",tkn_overlaps},
{"real", tkn_real},
{"select", tkn_select},
{"start", tkn_start},
{"string", tkn_string},
{"table", tkn_table},
{"true", tkn_true},
{"upper", tkn_upper},
{"where", tkn_where}
};
if (!initialized) {
for (unsigned i = 0; i < itemsof(keywords); i++) {
dbSymbolTable::add(keywords[i].name, keywords[i].tag, FASTDB_CLONE_ANY_IDENTIFIER);
}
initialized = true;
}
}
void dbInheritedAttribute::removeTemporaries()
{
for (dbStringValue *next, *s = tempStrings; s != NULL; s = next) {
next = s->next;
delete s;
}
}
END_FASTDB_NAMESPACE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -