Beispiel #1
0
bool SqlParser::parseTableNameAndAlias(int start, int end,
        StringVector &tables,
        StringVector &aliases) const {
    for (int i = start; i < end;) {

        // Assume ',' separated mutiple table list
        // this is not always true

        // find the first table part
        int keyIds[] = {TK_SQL_INNER, TK_SQL_CROSS, TK_SQL_STRAIGHT_JOIN,
            TK_SQL_LEFT, TK_SQL_RIGHT, TK_SQL_NATURAL, TK_SQL_JOIN, TK_COMMA};

        int table0End;
        if (findTokens(i, end, keyIds, sizeof (keyIds) / sizeof (int), &table0End)) {
            if (!parseSimpleTableNameAndAlias(i, table0End, tables, aliases))
                return false;
            if (getTokenId(table0End) == TK_COMMA) {
                i = table0End + 1;
                continue;
            }
        } else {
            return parseSimpleTableNameAndAlias(i, table0End, tables, aliases);
        }

        bool firstJoin = true;
        while (1) {
            // find the second table in join
            int joinKw[] = {TK_SQL_JOIN, TK_SQL_STRAIGHT_JOIN};
            int table1Start;
            if (!findTokens(table0End, end, joinKw, sizeof (joinKw) / sizeof (int),
                    &table1Start))
                return !firstJoin;

            table1Start++;

            int table1End;
            int condKw[] = {TK_SQL_ON, TK_SQL_USING, TK_COMMA};
            bool found = findTokens(table1Start, end, condKw, sizeof (condKw) / sizeof (int), &table1End);

            if (!parseSimpleTableNameAndAlias(table1Start, table1End, tables, aliases))
                return false;

            i = table1End + 1;
            table0End = i;
            firstJoin = false;

            if (found && getTokenId(table1End) == TK_COMMA)
                break;
            else if (found)
                continue;
            else
                return true;
        }
    }

    return true;
}
Beispiel #2
0
bool SqlParser::setDefaultLimit() {
    static const char *defaultLimit = NULL;
    if (defaultLimit == NULL) {
        defaultLimit = get_config_string("DEFAULT_SELECT_LIMIT");
        if (defaultLimit == NULL)
            defaultLimit = "500";
    }

    int limitPos;
    if (!findToken(1, getTokensLen(), TK_SQL_LIMIT, &limitPos)) {
        g_string_append(inputSql, " LIMIT ");
        g_string_append(inputSql, defaultLimit);
        network_mysqld_proto_set_header_len((unsigned char *) (inputSql->str), inputSql->len - NET_HEADER_SIZE);

        return true;
    }

    if (limitPos + 3 > getTokensLen() - 1) // no offset
        return true;

    if (limitPos + 3 < getTokensLen() - 1) {
        printTokens("only queries with LIMIT at the last field is supported now!");
        return false;
    }

    int offset, rowCount;
    if (getTokenId(limitPos + 2) == TK_COMMA) {
        offset = atoi(getTokenStr(limitPos + 1).c_str());
        rowCount = atoi(getTokenStr(limitPos + 3).c_str());
    } else if (getTokenId(limitPos + 2) == TK_SQL_OFFSET) {
        offset = atoi(getTokenStr(limitPos + 3).c_str());
        rowCount = atoi(getTokenStr(limitPos + 1).c_str());
    } else {
        printTokens("Unrecognized LIMIT OFFSET format:");
        return false;
    }

    // TODO: the tokenizer needs to have the field offset info
    // for now, we search LIMIT from the end
    char *p = inputSql->str + inputSql->len - 1;
    while (toupper(*p) != 'L') p--;

    // remove the old LIMIT OFFSET info
    //
    g_string_truncate(inputSql, p - inputSql->str);

    // add new LIMIT OFFSET info
    char buff[128];
    snprintf(buff, sizeof (buff), "LIMIT %d", offset + rowCount);
    g_string_append(inputSql, buff);
    network_mysqld_proto_set_header_len((unsigned char *) (inputSql->str), inputSql->len - NET_HEADER_SIZE);

    return true;
}
Beispiel #3
0
int
checkPermissionByObjType( rsComm_t *rsComm, char *objName, char *objType, char *user, char *zone, char *oper ) {
    int i;
    int operId;
    int userId;
    operId = getTokenId( rsComm, "access_type", oper );
    if ( operId < 0 ) {
        return operId;
    }

    userId = getUserId( rsComm, user, zone );
    if ( userId < 0 ) {
        return userId;
    }

    if ( !strcmp( objType, "-d" ) ) {
        i = checkPermitForDataObject( rsComm, objName, userId, operId );
    }
    else  if ( !strcmp( objType, "-c" ) ) {
        i = checkPermitForCollection( rsComm, objName, userId, operId );
    }
    else  if ( !strcmp( objType, "-r" ) ) {
        i = checkPermitForResource( rsComm, objName, userId, operId );
    }
    /*
    else  if (!strcmp(objType,"-m"))
      i = checkPermitForMetadata(rsComm, objName, userId, operId);
    */
    else {
        i = INVALID_OBJECT_TYPE;
    }
    return i;
}
Beispiel #4
0
bool SqlParser::findToken(int start, int end, int tokId, int *where) const {
    int i = start;

    while (i < end && getTokenId(i) != tokId)
        i++;

    *where = i;
    return i < end;
}
Beispiel #5
0
void Scan::getToken() {
    string s = string(T_map[T_IDENTIFIER])
               + string("|") + string(T_map[T_NUMBER])
               + string("|") + string(T_map[T_BRACE_SL])
               + string("|") + string(T_map[T_BRACE_SR])
               + string("|") + string(T_map[T_BRACE_ML])
               + string("|") + string(T_map[T_BRACE_MR])
               + string("|") + string(T_map[T_BRACE_LL])
               + string("|") + string(T_map[T_BRACE_LR])
               + string("|") + string(T_map[T_NON])
               + string("|") + string(T_map[T_GTHAN])
               + string("|") + string(T_map[T_LTHAN])
                               + string("|") + string(T_map[T_EQUAL])
                               + string("|") + string(T_map[T_ADD])
                               + string("|") + string(T_map[T_MIN])
                               + string("|") + string(T_map[T_MUL])
                               + string("|") + string(T_map[T_DIV])
                               + string("|") + string(T_map[T_COMMA])
                               + string("|") + string(T_map[T_SQUOTE])
                               + string("|") + string(T_map[T_DQUOTE])
                               + string("|") + string(T_map[T_ESCAPE])
                               + string("|") + string(T_map[T_BLANK])
                               + string("|") + string(T_map[-1]); //no use symnbol

    RexHandle rh;
    rh.setRextext(s);
    rh.run();

    fstream in;
    ofstream out;
    in.open(srcfile);
    out.open(outfile, ios::trunc);

    string ts;
    int line = 0;
    vector<pair<int, int> > tpair;
    while (getline(in, ts)) {
        line++;
        tpair = rh.compareString(ts);
        for (int i = 0; i < tpair.size(); ++i) {
            if (tpair[i].first >= 0 && tpair[i].second >= 0) {
                Token *ttoken = new Token;
                ttoken->start = tpair[i].first;
                ttoken->end = tpair[i].second;
                string tmp = ts.substr((unsigned long) ttoken->start, (unsigned long) ttoken->end - ttoken->start + 1);
                ttoken->token = getTokenId(tmp);
                ttoken->value = tmp;
                ttoken->lineIndex = line;
                list_token.push_back(ttoken);
                out << "Line:" << ttoken->lineIndex << " At:" << ttoken->start << " TokenType:" << ttoken->token <<
                " Value= " << tmp << endl;
            }
        }
    }
    in.close();
    out.close();
}
Beispiel #6
0
bool SqlParser::parseSimpleTableNameAndAlias(int start, int end,
        StringVector &tableNames,
        StringVector &aliases) const {
    if (end - start == 1) {
        if (getTokenId(start) == TK_LITERAL) {
            tableNames.push_back(getTokenStr(start));
            aliases.push_back("");
            return true;
        }
    } else if (end - start == 2) {
        if (getTokenId(start) == TK_LITERAL &&
                getTokenId(start + 1) == TK_LITERAL) {
            tableNames.push_back(getTokenStr(start));
            aliases.push_back(getTokenStr(start + 1));
            return true;
        }
    } else if (end - start == 3 && getTokenId(start + 1) == TK_SQL_AS) {
        if (getTokenId(start) == TK_LITERAL &&
                getTokenId(start + 2) == TK_LITERAL) {
            tableNames.push_back(getTokenStr(start));
            aliases.push_back(getTokenStr(start + 2));
            return true;
        }
    }

    return false;
}
Beispiel #7
0
bool SqlParser::findTokens(int start, int end, int *tokIds, int size, int *where) const {
    int i;
    for (i = start; i < end; i++) {
        int id = getTokenId(i);
        for (int k = 0; k < size; k++) {
            if (tokIds[k] == id) {
                *where = i;
                return true;
            }
        }
    }

    *where = i;
    return false;
}
Beispiel #8
0
void SqlParser::printTokens(const char *str) const {
    std::string msg(str ? str : "");
    if (inputSql) {
        msg.append("\"");
        msg.append(inputSql->str + NET_HEADER_SIZE + 1, inputSql->len - NET_HEADER_SIZE - 1);
        msg.append("\".");
    }

    log_warning(msg.c_str());

    for (size_t i = 0; i < tokens->len; i++) {
        log_debug("SQL Tokens: %2d %20s: \"%s\"\n", i,
                sql_token_get_name(getTokenId(i)),
                getTokenStr(i).c_str());
    }

}
Beispiel #9
0
db_lookup_retval_t SqlParser::parseSql(std::set<std::string> &dbs, int *txLevel, bool parseMaster) {
    dbs.clear();

    StringVector tables, aliases;

    if (getTokensLen() <= 0) {
        log_warning("empty sql for dababase lookup!\n");
        return RET_ERROR_UNPARSABLE;
    }

    switch (getTokenId(0)) {
        case TK_SQL_SELECT:
        {
            int usemaster = 0;
            if (parseMaster) usemaster = 1;
            // special handling for our get unique id function call.
            if (getTokensLen() > 1 && getTokenStr(1) == "get_next_id")
                return RET_USE_DEFAULT_DATABASE;

            int fromStart, fromEnd;

            if (!getSqlFrom(0, &fromStart, &fromEnd)) {
                if ((getTokensLen() > 3 && getTokenId(1) == TK_LITERAL &&
                        getTokenId(2) == TK_OBRACE) ||
                        (getTokensLen() == 2 && getTokenId(1) == TK_LITERAL)) {

                    // for special stored procedures
                    return RET_USE_ALL_PARTITIONS;
                }

                printTokens("no FROM found, using default db: ");
                return RET_USE_DEFAULT_DATABASE;
            }

            if (!parseTableNameAndAlias(fromStart, fromEnd, tables, aliases)) {
                printTokens("could not parse table alias, using default db: ");
                return RET_USE_DEFAULT_DATABASE;
            }

            // for non-partitioned tables, we can use any db
            // since each db should have a view of it
            bool partitioned = false;
            for (size_t i = 0; i < tables.size(); i++) {
                if (dbPart->isPartitionedTable(tables[i])) {
                    partitioned = true;
                    break;
                }
            }
            if (!setDefaultLimit()) {
                printTokens("error in modifying LIMIT: ");
                return RET_ERROR_UNPARSABLE;
            }
            /*
               if (!partitioned)
               return ((*txLevel) > 0 ? RET_USE_DEFAULT_DATABASE : RET_USE_ANY_PARTITION);
             */
            int whereStart, whereEnd;
            if (!getSqlWhere(fromEnd, &whereStart, &whereEnd)) {
                // add LIMIT, change the offset to 0 if needed
                uint64_t aa = 0;
                dbPart->getPartitionNum(tables[0], &aa);

                for (size_t i = 0; i < aa; i++) {
                    std::string db;
                    getDbMapping(tables[0], "", i, db, usemaster, 0);
                    if (!db.empty())
                        dbs.insert(db);
                }
                return RET_USE_ALL_PARTITIONS;
            }

            for (size_t i = 0; i < tables.size(); i++) {
                std::string partitionKey;
                getPartitionKey(tables[i], partitionKey);
                if (partitionKey.empty()) {
                    std::string db;
                    getDbMapping(tables[i], "", 0, db, usemaster, 0);
                    if (!db.empty())
                        dbs.insert(db);
                    continue;
                }


                std::vector<uint64_t> keyValues;
                if (!findPartitionKeyValue(whereStart, whereEnd, tables[i],
                        aliases[i], partitionKey, keyValues)) {
                    printTokens("unrecognized key ranges: ");
                    return RET_ERROR_UNPARSABLE;
                }
                if (keyValues.size() == 0) {
                    uint64_t aa = 0;
                    dbPart->getPartitionNum(tables[0], &aa);

                    for (size_t i = 0; i < aa; i++) {
                        std::string db;
                        getDbMapping(tables[0], "", i, db, usemaster, 0);
                        if (!db.empty())
                            dbs.insert(db);
                    }
                    return RET_USE_ALL_PARTITIONS;
                }

                // find the db partition for all the IDs
                for (size_t k = 0; k < keyValues.size(); k++) {
                    std::string db;
                    getDbMapping(tables[i], partitionKey, keyValues[k], db, usemaster, 0);
                    if (!db.empty())
                        dbs.insert(db);
                }
            }



            if (dbs.empty())
                return RET_USE_ALL_PARTITIONS;

            return RET_DB_LOOKUP_SUCCESS;
        }
        case TK_SQL_UPDATE:
        {
            int setPos;
            if (!findToken(0, getTokensLen(), TK_SQL_SET, &setPos)) {
                printTokens("could not find SET in UPDATE: ");
                return RET_ERROR_UNPARSABLE;
            };

            if (getTokenId(setPos - 1) != TK_LITERAL) {
                printTokens("expecting table name before SET: ");
                return RET_ERROR_UNPARSABLE;
            }

            std::string table = getTokenStr(setPos - 1);

            // for nonpartitioned tables, update the default master db
            if (!(dbPart->isPartitionedTable(table))) {
                std::string db;
                getDbMapping(table, "", 0, db, 1, 0);
                if (!db.empty())
                    dbs.insert(db);
                return RET_USE_ALL_PARTITIONS;
            }

            int whereStart, whereEnd;
            if (!getSqlWhere(setPos + 1, &whereStart, &whereEnd)) {
                printTokens("no WHERE found: ");
                return RET_ERROR_UNPARSABLE;
            }

            std::string partitionKey;
            getPartitionKey(table, partitionKey);

            g_assert(!partitionKey.empty());

            std::vector<uint64_t> keyValues;
            if (!findPartitionKeyValue(whereStart, whereEnd, table, "",
                    partitionKey, keyValues)) {
                printTokens("unrecognized ranges: ");
                return RET_ERROR_UNPARSABLE;
            }

            // find the db partition for all the IDs
            for (size_t k = 0; k < keyValues.size(); k++) {
                std::string db;
                getDbMapping(table, partitionKey, keyValues[k], db, 1, 0);
                if (!db.empty())
                    dbs.insert(db);
            }

            if (dbs.empty())
                return RET_USE_ALL_PARTITIONS;

            return RET_DB_LOOKUP_SUCCESS;
        }
        case TK_SQL_INSERT:
        { // support format: INSERT  ... <table> (...) VALUES (....)

            int pos;
            uint64_t insertid = 0;
            if (!findToken(1, getTokensLen(), TK_LITERAL, &pos)) {
                printTokens("could not find table name: ");
                return RET_ERROR_UNPARSABLE;
            }

            std::string table = getTokenStr(pos);

            std::string partitionKey;
            getPartitionKey(table, partitionKey);

            if (getTokenId(++pos) != TK_OBRACE) {
                printTokens("unrecognized INSERT: ");
                return RET_ERROR_UNPARSABLE;
            }

            pos++;

            std::string autoIncrementColumn;
            dbPart->getAutoIncrementColumn(table, autoIncrementColumn);

            int keyPos = -1;
            int autoColPos = -1;
            for (int i = pos; i < getTokensLen(); i++) {
                if ((getTokenId(i) == TK_CBRACE) ||
                        (autoColPos >= 0 && keyPos >= 0))
                    break;
                if (getTokenId(i) == TK_LITERAL &&
                        tokComp(i, partitionKey) == 0) {
                    keyPos = i - pos;
                    continue;
                }
                if (getTokenId(i) == TK_LITERAL &&
                        tokComp(i, autoIncrementColumn) == 0) {
                    autoColPos = i - pos;
                }
            }

            if ((!partitionKey.empty()) && keyPos == -1 && partitionKey != autoIncrementColumn) {
                log_warning("could not find the partition key %s:", partitionKey.c_str());
                printTokens();
                return RET_ERROR_UNPARSABLE;
            }

            if ((!partitionKey.empty()) && keyPos == -1) {
                // special handling for the case in which partition key type is auto increment.
                // need to get the id first and then modify the INSERT
                uint64_t id;
                if (!dbPart->getNextUniqueId(table, &id)) {
                    log_warning("could not get next unique id for %s", partitionKey.c_str());
                    printTokens();
                    return RET_DB_LOOKUP_ERROR;
                }
                insertid = id;
                std::string db;
                getDbMapping(table, partitionKey, id, db, 1, id);
                if (!db.empty())
                    dbs.insert(db);
                else {
                    printTokens("could not find db for id %d: ");
                    return RET_DB_LOOKUP_ERROR;
                }

                if (modifySqlForInsert(partitionKey, id)) {
                    if (partitionKey == autoIncrementColumn || autoIncrementColumn.empty())
                        return RET_DB_LOOKUP_SUCCESS;
                } else {
                    log_warning("could not insert id for %s ", partitionKey.c_str());
                    printTokens();
                    return RET_DB_LOOKUP_ERROR;
                }
            }

            if (!autoIncrementColumn.empty() && autoColPos < 0 && (partitionKey != autoIncrementColumn)) {
                // need to get unique ids for auto increment columns
                uint64_t id;
                if (!dbPart->getNextUniqueId(table, &id)) {
                    log_warning("could not get next unique id for %s", autoIncrementColumn.c_str());
                    printTokens();
                    return RET_DB_LOOKUP_ERROR;
                }
                insertid = id;
                if (modifySqlForInsert(autoIncrementColumn, id)) {
                    // for nonparitioned table INSERT, use the default master db
                    if (partitionKey.empty())
                        return RET_USE_DEFAULT_DATABASE;

                    if (keyPos == -1)
                        return RET_DB_LOOKUP_SUCCESS;
                } else {
                    log_warning("could not insert id for %s ", autoIncrementColumn.c_str());
                    printTokens();
                    return RET_DB_LOOKUP_ERROR;
                }
            }

            // for nonparitioned table INSERT, use the default master db
            if (partitionKey.empty()) {
                std::string db;
                getDbMapping(table, "", 0, db, 1, insertid);
                if (!db.empty())
                    dbs.insert(db);
                return RET_USE_ALL_PARTITIONS;
            }

            pos += keyPos;

            int valPos;

            if (!findToken(pos, getTokensLen(), TK_SQL_VALUES, &valPos)) {
                printTokens("VALUES is not found: ");
                return RET_ERROR_UNPARSABLE;
            }

            if (getTokenId(valPos + 1) != TK_OBRACE) {
                printTokens("expecting '(' after VALUES: ");
                return RET_ERROR_UNPARSABLE;
            }

            pos = valPos + 2 + keyPos;
            if (pos < getTokensLen()) {//dqm
                //if (pos < getTokensLen() && getTokenId(pos) == TK_INTEGER) {
                uint64_t id = tokenToUint64(pos);
                std::string db;
                getDbMapping(table, partitionKey, id, db, 1, insertid);
                if (!db.empty())
                    dbs.insert(db);

                if (dbs.empty()) {
                    printTokens("could not find db mapping: ");
                    return RET_ERROR_UNPARSABLE;
                }

                return RET_DB_LOOKUP_SUCCESS;
            } else {
                log_warning("could not recognize value for %s:", partitionKey.c_str());
                printTokens();
                return RET_ERROR_UNPARSABLE;
            }

            break;
        }
        
        case TK_SQL_REPLACE:
        { // support format: replace  ... <table> (...) VALUES (....)

            int pos;
            uint64_t insertid = 0;
            if (!findToken(1, getTokensLen(), TK_LITERAL, &pos)) {
                printTokens("could not find table name: ");
                return RET_ERROR_UNPARSABLE;
            }

            std::string table = getTokenStr(pos);

            std::string partitionKey;
            getPartitionKey(table, partitionKey);

            if (getTokenId(++pos) != TK_OBRACE) {
                printTokens("unrecognized INSERT: ");
                return RET_ERROR_UNPARSABLE;
            }

            pos++;

            std::string autoIncrementColumn;
            dbPart->getAutoIncrementColumn(table, autoIncrementColumn);

            int keyPos = -1;
            int autoColPos = -1;
            for (int i = pos; i < getTokensLen(); i++) {
                if ((getTokenId(i) == TK_CBRACE) ||
                        (autoColPos >= 0 && keyPos >= 0))
                    break;
                if (getTokenId(i) == TK_LITERAL &&
                        tokComp(i, partitionKey) == 0) {
                    keyPos = i - pos;
                    continue;
                }
                if (getTokenId(i) == TK_LITERAL &&
                        tokComp(i, autoIncrementColumn) == 0) {
                    autoColPos = i - pos;
                }
            }

            if ((!partitionKey.empty()) && keyPos == -1 && partitionKey != autoIncrementColumn) {
                log_warning("could not find the partition key %s:", partitionKey.c_str());
                printTokens();
                return RET_ERROR_UNPARSABLE;
            }

            if ((!partitionKey.empty()) && keyPos == -1) {
                // special handling for the case in which partition key type is auto increment.
                // need to get the id first and then modify the INSERT
                uint64_t id;
                if (!dbPart->getNextUniqueId(table, &id)) {
                    log_warning("could not get next unique id for %s", partitionKey.c_str());
                    printTokens();
                    return RET_DB_LOOKUP_ERROR;
                }
                insertid = id;
                std::string db;
                getDbMapping(table, partitionKey, id, db, 1, id);
                if (!db.empty())
                    dbs.insert(db);
                else {
                    printTokens("could not find db for id %d: ");
                    return RET_DB_LOOKUP_ERROR;
                }

                if (modifySqlForInsert(partitionKey, id)) {
                    if (partitionKey == autoIncrementColumn || autoIncrementColumn.empty())
                        return RET_DB_LOOKUP_SUCCESS;
                } else {
                    log_warning("could not insert id for %s ", partitionKey.c_str());
                    printTokens();
                    return RET_DB_LOOKUP_ERROR;
                }
            }

            if (!autoIncrementColumn.empty() && autoColPos < 0 && (partitionKey != autoIncrementColumn)) {
                // need to get unique ids for auto increment columns
                uint64_t id;
                if (!dbPart->getNextUniqueId(table, &id)) {
                    log_warning("could not get next unique id for %s", autoIncrementColumn.c_str());
                    printTokens();
                    return RET_DB_LOOKUP_ERROR;
                }
                insertid = id;
                if (modifySqlForInsert(autoIncrementColumn, id)) {
                    // for nonparitioned table INSERT, use the default master db
                    if (partitionKey.empty())
                        return RET_USE_DEFAULT_DATABASE;

                    if (keyPos == -1)
                        return RET_DB_LOOKUP_SUCCESS;
                } else {
                    log_warning("could not insert id for %s ", autoIncrementColumn.c_str());
                    printTokens();
                    return RET_DB_LOOKUP_ERROR;
                }
            }

            // for nonparitioned table INSERT, use the default master db
            if (partitionKey.empty()) {
                std::string db;
                getDbMapping(table, "", 0, db, 1, insertid);
                if (!db.empty())
                    dbs.insert(db);
                return RET_USE_ALL_PARTITIONS;
            }

            pos += keyPos;

            int valPos;

            if (!findToken(pos, getTokensLen(), TK_SQL_VALUES, &valPos)) {
                printTokens("VALUES is not found: ");
                return RET_ERROR_UNPARSABLE;
            }

            if (getTokenId(valPos + 1) != TK_OBRACE) {
                printTokens("expecting '(' after VALUES: ");
                return RET_ERROR_UNPARSABLE;
            }

            pos = valPos + 2 + keyPos;
            if (pos < getTokensLen()) {//dqm
                //if (pos < getTokensLen() && getTokenId(pos) == TK_INTEGER) {
                uint64_t id = tokenToUint64(pos);
                std::string db;
                getDbMapping(table, partitionKey, id, db, 1, insertid);
                if (!db.empty())
                    dbs.insert(db);

                if (dbs.empty()) {
                    printTokens("could not find db mapping: ");
                    return RET_ERROR_UNPARSABLE;
                }

                return RET_DB_LOOKUP_SUCCESS;
            } else {
                log_warning("could not recognize value for %s:", partitionKey.c_str());
                printTokens();
                return RET_ERROR_UNPARSABLE;
            }

            break;
        }

        case TK_SQL_ALTER:
        {
            std::string tableName;
            if (getTokensLen() >= 3 && getTokenId(1) == TK_SQL_TABLE) {
                tableName = getTokenStr(2);
            } else if (getTokensLen() >= 4 && getTokenId(1) == TK_SQL_IGNORE &&
                    getTokenId(2) == TK_SQL_TABLE) {
                tableName = getTokenStr(3);
            } else
                break;
            if (dbPart->isPartitionedTable(tableName))
                return RET_USE_ALL_PARTITIONS;
            else
                return RET_USE_DEFAULT_DATABASE;
        }

        case TK_SQL_CALL:
        {
            return RET_USE_ALL_PARTITIONS;
        }

        case TK_SQL_SHOW:
        {
            if (getTokensLen() == 4 && getTokenId(2) == TK_SQL_FROM &&
                    strcasecmp(getTokenStr(1).c_str(), "fields") == 0) {

                if (dbPart->isPartitionedTable(getTokenStr(3))) {
                    return RET_USE_ANY_PARTITION;
                }
                return RET_USE_DEFAULT_DATABASE;
            }

            if (getTokensLen() == 2 &&
                    strcasecmp(getTokenStr(1).c_str(), "tables") == 0) {

                //special handling for show tables;
                //
                std::string sql = "select table_name ";
                sql.append(" from kind_setting order by table_name");
                g_string_truncate(inputSql, NET_HEADER_SIZE + 1);
                g_string_append_len(inputSql, sql.data(), sql.size());

                network_mysqld_proto_set_header_len((unsigned char *) (inputSql->str),
                        inputSql->len - NET_HEADER_SIZE);

                return RET_USE_DEFAULT_DATABASE;
            } else
                return RET_USE_DEFAULT_DATABASE;

            break;
        }

        case TK_SQL_DELETE:
        {
            int fromPos;
            if (!findToken(1, getTokensLen(), TK_SQL_FROM, &fromPos)) {
                printTokens("could not find FROM in DELETE: ");
                return RET_ERROR_UNPARSABLE;
            };

            if (fromPos >= getTokensLen() - 1) {
                printTokens("could not find table name in DELETE: ");
                return RET_ERROR_UNPARSABLE;
            }

            std::string table = getTokenStr(fromPos + 1);
            // for nonpartitioned tables, update the default master db
            if (!(dbPart->isPartitionedTable(table))) {
                std::string db;
                getDbMapping(table, "", 0, db, 1, 0);
                if (!db.empty())
                    dbs.insert(db);
                return RET_USE_ALL_PARTITIONS;
            }

            int whereStart, whereEnd;
            if (!getSqlWhere(fromPos + 1, &whereStart, &whereEnd)) {
                printTokens("no WHERE found: ");
                return RET_ERROR_UNPARSABLE;
            }

            std::string partitionKey;
            getPartitionKey(table, partitionKey);

            g_assert(!partitionKey.empty());

            std::vector<uint64_t> keyValues;
            if (!findPartitionKeyValue(whereStart, whereEnd, table, "",
                    partitionKey, keyValues)) {
                printTokens("unrecognized ranges: ");
                return RET_ERROR_UNPARSABLE;
            }

            // find the db partition for all the IDs
            for (size_t k = 0; k < keyValues.size(); k++) {
                std::string db;
                getDbMapping(table, partitionKey, keyValues[k], db, 1, 0);
                if (!db.empty())
                    dbs.insert(db);
            }

            if (dbs.empty())
                return RET_USE_ALL_PARTITIONS;

            return RET_DB_LOOKUP_SUCCESS;
        }
        case TK_SQL_DESC:
        case TK_SQL_DESCRIBE:
        {
            if (getTokensLen() >= 2) {
                std::string tableName = getTokenStr(1);
                if (dbPart->isPartitionedTable(tableName))
                    return RET_USE_ANY_PARTITION;
                else
                    return RET_USE_DEFAULT_DATABASE;
            }

            return RET_ERROR_UNPARSABLE;
        }
        case TK_SQL_SET:
        {
            if ((getTokensLen() >= 4) &&
                    (getTokenId(1) == TK_SQL_AUTOCOMMIT) &&
                    (getTokenStr(3).compare("0") == 0)) {
                (*txLevel)++;
            }
            return RET_USE_ALL_DATABASES;
        }
        case TK_SQL_START:
        case TK_SQL_BEGIN:
        {
            (*txLevel)++;
            return RET_USE_ALL_DATABASES;
        }
        case TK_SQL_COMMIT:
        case TK_SQL_ROLLBACK:
        {
            (*txLevel)--;
            return RET_USE_ALL_DATABASES;
        }
        default:
        {
            break;
        }
    }

    printTokens("unrecognized query, using default master db: ");

    return RET_USE_DEFAULT_DATABASE;
}
Beispiel #10
0
bool SqlParser::findPartitionKeyValue(int start, int end,
        const std::string &table,
        const std::string &alias,
        const std::string &partKey,
        std::vector<uint64_t> &keyValues) const {
    int i = start;
    while (i < end) {
        if (getTokenId(i) != TK_LITERAL || tokComp(i, partKey)) {
            i++;
            continue;
        }

        // check the prefix if there is any
        if (i - start >= 2 && getTokenId(i - 1) == TK_DOT &&
                getTokenId(i - 2) == TK_LITERAL) {
            if (tokComp(i - 2, table) && tokComp(i - 2, alias)) {
                i++;
                continue;
            }
        }

        // id = NUM case
        if ((i + 2 < end) && getTokenId(i + 1) == TK_EQ &&
                getTokenId(i + 2) == TK_INTEGER) {
            keyValues.push_back(tokenToUint64(i + 2));
            i += 3;
            continue;
        }

        // IN (...) case
        if (i + 3 < end && getTokenId(i + 1) == TK_SQL_IN &&
                getTokenId(i + 2) == TK_OBRACE) {

            i += 3;
            for (int k = i; k < end; k++, i++) {
                if (getTokenId(k) == TK_CBRACE)
                    break;
                if (getTokenId(k) == TK_INTEGER) {
                    if (getTokenId(k - 1) != TK_COMMA &&
                            getTokenId(k - 1) != TK_OBRACE)
                        return false;

                    keyValues.push_back(tokenToUint64(k));
                }
            }
            continue;
        }
        i++;
    }
    return true;
}
Beispiel #11
0
int
checkPermissionByObjType( rsComm_t *rsComm, char *objName, char *objType, char *user, char *zone, char *oper ) {
    int i;
    rodsLong_t operId;
    rodsLong_t userId;
    operId = getTokenId( rsComm, "access_type", oper );
    if ( operId < 0 ) {
        // jjames - if they provide an invalid oper, give a better return code
        if ( operId == CAT_NO_ROWS_FOUND ) {
            return SYS_INVALID_INPUT_PARAM;
        }
        return operId;
    }

    userId = getUserId( rsComm, user, zone );
    if ( userId < 0 ) {
        return userId;
    }

    if ( !strcmp( objType, "-d" ) ) {
        i = checkPermitForDataObject( rsComm, objName, userId, operId );
    }
    else  if ( !strcmp( objType, "-c" ) ) {
        i = checkPermitForCollection( rsComm, objName, userId, operId );
    }
    else  if ( !strcmp( objType, "-r" ) ) {
        i = checkPermitForResource( rsComm, objName, userId, operId );
    }
    /*
    else  if (!strcmp(objType,"-m"))
      i = checkPermitForMetadata(rsComm, objName, userId, operId);
    */
    else {
        return INVALID_OBJECT_TYPE;
    }

    if ( i == 0 ) { // not found - check groups

        // Issue 3309 - iterate through user's groups and check for permission
        genQueryInp_t genQueryInp;
        genQueryOut_t *genQueryOut = NULL;
        memset( &genQueryInp, 0, sizeof( genQueryInp_t ) );
        genQueryInp.maxRows = MAX_SQL_ROWS;

        addInxIval( &genQueryInp.selectInp, COL_USER_GROUP_NAME, 1 );

        char condstr[MAX_NAME_LEN];
        snprintf( condstr, MAX_NAME_LEN, "= '%s'", user);
        addInxVal( &genQueryInp.sqlCondInp, COL_USER_NAME, condstr);

        sqlResult_t *group_sql_result;
        
        int status = rsGenQuery( rsComm, &genQueryInp, &genQueryOut );

        // note:  if rsGenQuery has an error, just continue to below
        if ( genQueryOut && status >= 0 ) {

            group_sql_result = getSqlResultByInx(genQueryOut, COL_USER_GROUP_NAME);

            if (group_sql_result != nullptr) {

                char *group_str;

                // iterating over groups
                for ( int j = 0; j < genQueryOut->rowCnt; j++ ) {

                    group_str = &group_sql_result->value[group_sql_result->len * j];

                    // if group_str is the same as user then we have already checked this
                    // and don't want to go into an infinite loop
                    if (strcmp(group_str, user) == 0) {
                        continue;
                    }

                    int groupId = getUserId( rsComm, group_str, zone );
                    if ( groupId < 0 ) {
                        continue; 
                    }

                    if ( !strcmp( objType, "-d" ) ) {
                        i = checkPermitForDataObject( rsComm, objName, groupId, operId );
                    }
                    else  if ( !strcmp( objType, "-c" ) ) {
                        i = checkPermitForCollection( rsComm, objName, groupId, operId );
                    }
                    else  if ( !strcmp( objType, "-r" ) ) {
                        i = checkPermitForResource( rsComm, objName, groupId, operId );
                    }

                    if (i == 1) {
                        // break out of loop if this group has permission 
                        break;
                    }
                }   
            }

            freeGenQueryOut( &genQueryOut );
            clearGenQueryInp( &genQueryInp );

        }

    }

    return i;
}