⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compiler.cpp

📁 俄罗斯牛人KK的作品,著名的ORDBMS,这里上传最新的3.39版本源代码.希望了解对象关系数据库的同好,请不要错过.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
{
    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 + -