Search in sources :

Example 31 with ExprNode

use of com.questdb.griffin.common.ExprNode in project questdb by bluestreak01.

the class SqlLexerOptimiser method moveWhereInsideSubQueries.

private void moveWhereInsideSubQueries(QueryModel model) throws ParserException {
    model.getParsedWhere().clear();
    final ObjList<ExprNode> nodes = model.parseWhereClause();
    model.setWhereClause(null);
    final int n = nodes.size();
    if (n > 0) {
        for (int i = 0; i < n; i++) {
            final ExprNode node = nodes.getQuick(i);
            // collect table references this where clause element
            literalCollectorAIndexes.clear();
            literalCollectorANames.clear();
            literalCollector.withModel(model);
            literalCollector.resetNullCount();
            traversalAlgo.traverse(node, literalCollector.lhs());
            // at this point we must not have constant conditions in where clause
            assert literalCollectorAIndexes.size() > 0;
            // by now all where clause must reference single table only and all column references have to be valid
            // they would have been rewritten and validated as join analysis stage
            final int tableIndex = literalCollectorAIndexes.getQuick(0);
            final QueryModel parent = model.getJoinModels().getQuick(tableIndex);
            final QueryModel nested = parent.getNestedModel();
            if (nested == null) {
                // there is no nested model for this table, keep where clause element with this model
                addWhereNode(parent, node);
            } else {
                try {
                    traversalAlgo.traverse(node, literalCheckingVisitor.of(nested.getColumnNameTypeMap()));
                    // go ahead and rewrite expression
                    traversalAlgo.traverse(node, literalRewritingVisitor.of(nested.getAliasToColumnMap()));
                    // whenever nested model has explicitly defined columns it must also
                    // have its owen nested model, where we assign new "where" clauses
                    addWhereNode(nested, node);
                } catch (NonLiteralException ignore) {
                    // keep node where it is
                    addWhereNode(parent, node);
                }
            }
        }
        model.getParsedWhere().clear();
    }
    if (model.getNestedModel() != null) {
        moveWhereInsideSubQueries(model.getNestedModel());
    }
    ObjList<QueryModel> joinModels = model.getJoinModels();
    for (int i = 0, m = joinModels.size(); i < m; i++) {
        QueryModel nested = joinModels.getQuick(i);
        if (nested != model) {
            moveWhereInsideSubQueries(nested);
        }
    }
}
Also used : ExprNode(com.questdb.griffin.common.ExprNode)

Example 32 with ExprNode

use of com.questdb.griffin.common.ExprNode in project questdb by bluestreak01.

the class SqlLexerOptimiser method resolveJoinColumns.

private void resolveJoinColumns(QueryModel model) throws ParserException {
    ObjList<QueryModel> joinModels = model.getJoinModels();
    final int size = joinModels.size();
    final CharSequence modelAlias = setAndGetModelAlias(model);
    // collect own alias
    collectAlias(model, 0, model);
    if (size > 1) {
        for (int i = 1; i < size; i++) {
            final QueryModel jm = joinModels.getQuick(i);
            final ObjList<ExprNode> jc = jm.getJoinColumns();
            final int joinColumnsSize = jc.size();
            if (joinColumnsSize > 0) {
                final CharSequence jmAlias = setAndGetModelAlias(jm);
                ExprNode joinCriteria = jm.getJoinCriteria();
                for (int j = 0; j < joinColumnsSize; j++) {
                    ExprNode node = jc.getQuick(j);
                    ExprNode eq = makeOperation("=", makeModelAlias(modelAlias, node), makeModelAlias(jmAlias, node));
                    if (joinCriteria == null) {
                        joinCriteria = eq;
                    } else {
                        joinCriteria = makeOperation("and", joinCriteria, eq);
                    }
                }
                jm.setJoinCriteria(joinCriteria);
            }
            resolveJoinColumns(jm);
            collectAlias(model, i, jm);
        }
    }
    if (model.getNestedModel() != null) {
        resolveJoinColumns(model.getNestedModel());
    }
}
Also used : ExprNode(com.questdb.griffin.common.ExprNode) FlyweightCharSequence(com.questdb.std.str.FlyweightCharSequence)

Example 33 with ExprNode

use of com.questdb.griffin.common.ExprNode in project questdb by bluestreak01.

the class SqlLexerOptimiser method rewriteCase.

private ExprNode rewriteCase(ExprNode node) throws ParserException {
    traversalAlgo.traverse(node, node1 -> {
        if (node1.type == ExprNode.FUNCTION && Chars.equals("case", node1.token)) {
            tempExprNodes.clear();
            ExprNode literal = null;
            ExprNode elseExpr;
            boolean convertToSwitch = true;
            final int paramCount = node1.paramCount;
            final int lim;
            if ((paramCount & 1) == 1) {
                elseExpr = node1.args.getQuick(0);
                lim = 0;
            } else {
                elseExpr = null;
                lim = -1;
            }
            for (int i = paramCount - 1; i > lim; i--) {
                if ((i & 1) == 1) {
                    // this is "then" clause, copy it as as
                    tempExprNodes.add(node1.args.getQuick(i));
                    continue;
                }
                ExprNode where = node1.args.getQuick(i);
                if (where.type == ExprNode.OPERATION && where.token.charAt(0) == '=') {
                    ExprNode thisConstant;
                    ExprNode thisLiteral;
                    if (where.lhs.type == ExprNode.CONSTANT && where.rhs.type == ExprNode.LITERAL) {
                        thisConstant = where.lhs;
                        thisLiteral = where.rhs;
                    } else if (where.lhs.type == ExprNode.LITERAL && where.rhs.type == ExprNode.CONSTANT) {
                        thisConstant = where.rhs;
                        thisLiteral = where.lhs;
                    } else {
                        convertToSwitch = false;
                        // not supported
                        break;
                    }
                    if (literal == null) {
                        literal = thisLiteral;
                        tempExprNodes.add(thisConstant);
                    } else if (Chars.equals(literal.token, thisLiteral.token)) {
                        tempExprNodes.add(thisConstant);
                    } else {
                        convertToSwitch = false;
                        // not supported
                        break;
                    }
                } else {
                    convertToSwitch = false;
                    // not supported
                    break;
                }
            }
            if (convertToSwitch) {
                node1.token = "switch";
                node1.args.clear();
                node1.args.add(literal);
                node1.args.add(elseExpr);
                node1.args.addAll(tempExprNodes);
            }
        }
    });
    return node;
}
Also used : ExprNode(com.questdb.griffin.common.ExprNode)

Example 34 with ExprNode

use of com.questdb.griffin.common.ExprNode in project questdb by bluestreak01.

the class SqlLexerOptimiser method parseSelectClause.

private void parseSelectClause(QueryModel model) throws ParserException {
    while (true) {
        CharSequence tok = tok("column");
        final ExprNode expr;
        // this is quite dramatic workaround for lexer
        // because lexer tokenizes expressions, for something like 'a.*' it would
        // produce two tokens, 'a.' and '*'
        // we should be able to tell if they are together or there is whitespace between them
        // for example "a.  *' would also produce two token and it must be a error
        // to determine if wildcard is correct we would rely on token position
        final char last = tok.charAt(tok.length() - 1);
        if (last == '*') {
            expr = nextLiteral(lexer.toImmutable(tok), lexer.position());
        } else if (last == '.') {
            // stash 'a.' token
            final int pos = lexer.position() + tok.length();
            Lexer2.NameAssembler nameAssembler = lexer.getNameAssembler();
            nameAssembler.put(tok);
            tok = tok("*");
            if (Chars.equals(tok, '*')) {
                if (lexer.position() > pos) {
                    throw ParserException.$(pos, "whitespace is not allowed");
                }
                nameAssembler.put('*');
                expr = nextLiteral(nameAssembler.toImmutable(), lexer.position());
            } else {
                throw ParserException.$(pos, "'*' expected");
            }
        } else {
            lexer.unparse();
            expr = expr();
            if (expr == null) {
                throw ParserException.$(lexer.position(), "missing expression");
            }
        }
        CharSequence alias;
        tok = tok("',', 'from', 'over' or literal");
        if (columnAliasStop.excludes(tok)) {
            if (Chars.indexOf(tok, '.') != -1) {
                throw ParserException.$(lexer.position(), "'.' is not allowed here");
            }
            alias = lexer.toImmutable(tok);
            tok = tok("',', 'from' or 'over'");
        } else {
            alias = createColumnAlias(expr, model);
        }
        if (Chars.equals(tok, "over")) {
            // analytic
            expectTok('(');
            AnalyticColumn col = analyticColumnPool.next().of(alias, expr);
            tok = tok("'");
            if (Chars.equals(tok, "partition")) {
                expectTok("by");
                ObjList<ExprNode> partitionBy = col.getPartitionBy();
                do {
                    partitionBy.add(expectLiteral());
                    tok = tok("'order' or ')'");
                } while (Chars.equals(tok, ','));
            }
            if (Chars.equals(tok, "order")) {
                expectTok("by");
                do {
                    ExprNode e = expectLiteral();
                    tok = tok("'asc' or 'desc'");
                    if (Chars.equalsIgnoreCase(tok, "desc")) {
                        col.addOrderBy(e, QueryModel.ORDER_DIRECTION_DESCENDING);
                        tok = tok("',' or ')'");
                    } else {
                        col.addOrderBy(e, QueryModel.ORDER_DIRECTION_ASCENDING);
                        if (Chars.equalsIgnoreCase(tok, "asc")) {
                            tok = tok("',' or ')'");
                        }
                    }
                } while (Chars.equals(tok, ','));
            }
            expectTok(tok, lexer.position(), ')');
            model.addColumn(col);
            tok = tok("'from' or ','");
        } else {
            model.addColumn(queryColumnPool.next().of(alias, expr));
        }
        if (Chars.equals(tok, "from")) {
            break;
        }
        if (!Chars.equals(tok, ',')) {
            throw err("',' or 'from' expected");
        }
    }
}
Also used : ExprNode(com.questdb.griffin.common.ExprNode) FlyweightCharSequence(com.questdb.std.str.FlyweightCharSequence)

Example 35 with ExprNode

use of com.questdb.griffin.common.ExprNode in project questdb by bluestreak01.

the class QueryModel method getTableMetadata.

public RecordMetadata getTableMetadata(CairoEngine engine, FlyweightCharSequence charSequence) throws ParserException {
    // table name must not contain quotes by now
    ExprNode readerNode = getTableName();
    int lo = 0;
    int hi = readerNode.token.length();
    if (Chars.startsWith(readerNode.token, NO_ROWID_MARKER)) {
        lo += NO_ROWID_MARKER.length();
    }
    if (lo == hi) {
        throw ParserException.$(readerNode.position, "come on, where is table name?");
    }
    int status = engine.getStatus(readerNode.token, lo, hi);
    if (status == TableUtils.TABLE_DOES_NOT_EXIST) {
        throw ParserException.$(readerNode.position, "table does not exist");
    }
    if (status == TableUtils.TABLE_RESERVED) {
        throw ParserException.$(readerNode.position, "table directory is of unknown format");
    }
    try (TableReader r = engine.getReader(charSequence.of(readerNode.token, lo, hi - lo))) {
        return r.getMetadata();
    } catch (EntryLockedException e) {
        throw ParserException.position(readerNode.position).put("table is locked: ").put(charSequence);
    } catch (CairoException e) {
        throw ParserException.position(readerNode.position).put(e);
    }
}
Also used : ExprNode(com.questdb.griffin.common.ExprNode) CairoException(com.questdb.cairo.CairoException) TableReader(com.questdb.cairo.TableReader) EntryLockedException(com.questdb.cairo.pool.ex.EntryLockedException)

Aggregations

ExprNode (com.questdb.griffin.common.ExprNode)40 FlyweightCharSequence (com.questdb.std.str.FlyweightCharSequence)14 NumericException (com.questdb.common.NumericException)2 CairoException (com.questdb.cairo.CairoException)1 TableReader (com.questdb.cairo.TableReader)1 EntryLockedException (com.questdb.cairo.pool.ex.EntryLockedException)1 RecordColumnMetadata (com.questdb.common.RecordColumnMetadata)1 RecordMetadata (com.questdb.common.RecordMetadata)1 IntrinsicModel (com.questdb.griffin.lexer.model.IntrinsicModel)1 NotNull (org.jetbrains.annotations.NotNull)1