Search in sources :

Example 6 with ExpressionNode

use of io.questdb.griffin.model.ExpressionNode in project questdb by bluestreak01.

the class WhereClauseParser method removeWithin.

private boolean removeWithin(AliasTranslator translator, ExpressionNode node, RecordMetadata metadata, FunctionParser functionParser, SqlExecutionContext executionContext, LongList prefixes) throws SqlException {
    if (isWithinKeyword(node.token)) {
        if (prefixes.size() > 0) {
            throw SqlException.$(node.position, "Multiple 'within' expressions not supported");
        }
        if (node.paramCount < 2) {
            throw SqlException.$(node.position, "Too few arguments for 'within'");
        }
        ExpressionNode col = node.paramCount < 3 ? node.lhs : node.args.getLast();
        if (col.type != ExpressionNode.LITERAL) {
            throw SqlException.unexpectedToken(col.position, col.token);
        }
        CharSequence column = translator.translateAlias(col.token);
        if (metadata.getColumnIndexQuiet(column) == -1) {
            throw SqlException.invalidColumn(col.position, col.token);
        }
        final int hashColumnIndex = metadata.getColumnIndex(column);
        final int hashColumnType = metadata.getColumnType(hashColumnIndex);
        if (!ColumnType.isGeoHash(hashColumnType)) {
            throw SqlException.$(node.position, "GeoHash column type expected");
        }
        if (prefixes.size() == 0) {
            prefixes.add(hashColumnIndex);
            prefixes.add(hashColumnType);
        }
        int c = node.paramCount - 1;
        if (c == 1) {
            ExpressionNode inArg = node.rhs;
            processArgument(inArg, metadata, functionParser, executionContext, hashColumnType, prefixes);
        } else {
            for (c--; c > -1; c--) {
                ExpressionNode inArg = node.args.getQuick(c);
                processArgument(inArg, metadata, functionParser, executionContext, hashColumnType, prefixes);
            }
        }
        return true;
    } else {
        return false;
    }
}
Also used : ExpressionNode(io.questdb.griffin.model.ExpressionNode) FlyweightCharSequence(io.questdb.std.str.FlyweightCharSequence)

Example 7 with ExpressionNode

use of io.questdb.griffin.model.ExpressionNode in project questdb by bluestreak01.

the class GroupByUtils method prepareGroupByRecordFunctions.

public static void prepareGroupByRecordFunctions(@NotNull QueryModel model, RecordMetadata metadata, @NotNull ListColumnFilter listColumnFilter, ObjList<GroupByFunction> groupByFunctions, @Transient IntList groupByFunctionPositions, ObjList<Function> recordFunctions, @Transient IntList recordFunctionPositions, GenericRecordMetadata groupByMetadata, ArrayColumnTypes keyTypes, int keyColumnIndex, boolean timestampUnimportant, int timestampIndex) throws SqlException {
    recordFunctionPositions.clear();
    // Process group-by functions first to get the idea of
    // how many map values we will have.
    // Map value count is needed to calculate offsets for
    // map key columns.
    ObjList<QueryColumn> columns = model.getColumns();
    int valueColumnIndex = 0;
    int inferredKeyColumnCount = 0;
    // when we have same column several times in a row
    // we only add it once to map keys
    int lastIndex = -1;
    for (int i = 0, n = columns.size(); i < n; i++) {
        final QueryColumn column = columns.getQuick(i);
        final ExpressionNode node = column.getAst();
        final int type;
        if (node.type == ExpressionNode.LITERAL) {
            // this is key
            int index = metadata.getColumnIndexQuiet(node.token);
            if (index == -1) {
                throw SqlException.invalidColumn(node.position, node.token);
            }
            type = metadata.getColumnType(index);
            if (index != timestampIndex || timestampUnimportant) {
                if (lastIndex != index) {
                    listColumnFilter.add(index + 1);
                    keyTypes.add(type);
                    keyColumnIndex++;
                    lastIndex = index;
                }
                final Function fun;
                switch(ColumnType.tagOf(type)) {
                    case ColumnType.BOOLEAN:
                        fun = BooleanColumn.newInstance(keyColumnIndex - 1);
                        break;
                    case ColumnType.BYTE:
                        fun = ByteColumn.newInstance(keyColumnIndex - 1);
                        break;
                    case ColumnType.SHORT:
                        fun = ShortColumn.newInstance(keyColumnIndex - 1);
                        break;
                    case ColumnType.CHAR:
                        fun = CharColumn.newInstance(keyColumnIndex - 1);
                        break;
                    case ColumnType.INT:
                        fun = IntColumn.newInstance(keyColumnIndex - 1);
                        break;
                    case ColumnType.LONG:
                        fun = LongColumn.newInstance(keyColumnIndex - 1);
                        break;
                    case ColumnType.FLOAT:
                        fun = FloatColumn.newInstance(keyColumnIndex - 1);
                        break;
                    case ColumnType.DOUBLE:
                        fun = DoubleColumn.newInstance(keyColumnIndex - 1);
                        break;
                    case ColumnType.STRING:
                        fun = StrColumn.newInstance(keyColumnIndex - 1);
                        break;
                    case ColumnType.SYMBOL:
                        fun = new MapSymbolColumn(keyColumnIndex - 1, index, metadata.isSymbolTableStatic(index));
                        break;
                    case ColumnType.DATE:
                        fun = DateColumn.newInstance(keyColumnIndex - 1);
                        break;
                    case ColumnType.TIMESTAMP:
                        fun = TimestampColumn.newInstance(keyColumnIndex - 1);
                        break;
                    case ColumnType.LONG256:
                        fun = Long256Column.newInstance(keyColumnIndex - 1);
                        break;
                    default:
                        fun = BinColumn.newInstance(keyColumnIndex - 1);
                        break;
                }
                recordFunctions.add(fun);
                recordFunctionPositions.add(node.position);
            } else {
                // set this function to null, cursor will replace it with an instance class
                // timestamp function returns value of class member which makes it impossible
                // to create these columns in advance of cursor instantiation
                recordFunctions.add(null);
                groupByFunctionPositions.add(0);
                if (groupByMetadata.getTimestampIndex() == -1) {
                    groupByMetadata.setTimestampIndex(i);
                }
                assert ColumnType.tagOf(type) == ColumnType.TIMESTAMP;
            }
            // and finish with populating metadata for this factory
            if (column.getAlias() == null) {
                groupByMetadata.add(BaseRecordMetadata.copyOf(metadata, index));
            } else {
                groupByMetadata.add(new TableColumnMetadata(Chars.toString(column.getAlias()), metadata.getColumnHash(index), type, metadata.isColumnIndexed(index), metadata.getIndexValueBlockCapacity(index), metadata.isSymbolTableStatic(index), metadata.getMetadata(index)));
            }
            inferredKeyColumnCount++;
        } else {
            // add group-by function as a record function as well
            // so it can produce column values
            final GroupByFunction groupByFunction = groupByFunctions.getQuick(valueColumnIndex);
            recordFunctions.add(groupByFunction);
            recordFunctionPositions.add(groupByFunctionPositions.getQuick(valueColumnIndex++));
            type = groupByFunction.getType();
            // and finish with populating metadata for this factory
            groupByMetadata.add(new TableColumnMetadata(Chars.toString(column.getName()), 0, type, false, 0, groupByFunction instanceof SymbolFunction && (((SymbolFunction) groupByFunction).isSymbolTableStatic()), groupByFunction.getMetadata()));
        }
    }
    validateGroupByColumns(model, inferredKeyColumnCount);
}
Also used : GroupByFunction(io.questdb.griffin.engine.functions.GroupByFunction) SymbolFunction(io.questdb.griffin.engine.functions.SymbolFunction) GroupByFunction(io.questdb.griffin.engine.functions.GroupByFunction) Function(io.questdb.cairo.sql.Function) QueryColumn(io.questdb.griffin.model.QueryColumn) ExpressionNode(io.questdb.griffin.model.ExpressionNode) SymbolFunction(io.questdb.griffin.engine.functions.SymbolFunction)

Example 8 with ExpressionNode

use of io.questdb.griffin.model.ExpressionNode in project questdb by bluestreak01.

the class GroupByUtils method prepareGroupByFunctions.

public static void prepareGroupByFunctions(QueryModel model, RecordMetadata metadata, FunctionParser functionParser, SqlExecutionContext executionContext, ObjList<GroupByFunction> groupByFunctions, @Transient IntList groupByFunctionPositions, ArrayColumnTypes valueTypes) throws SqlException {
    groupByFunctionPositions.clear();
    final ObjList<QueryColumn> columns = model.getColumns();
    for (int i = 0, n = columns.size(); i < n; i++) {
        final QueryColumn column = columns.getQuick(i);
        final ExpressionNode node = column.getAst();
        if (node.type != ExpressionNode.LITERAL) {
            // this can fail
            ExpressionNode columnAst = column.getAst();
            final Function function = functionParser.parseFunction(columnAst, metadata, executionContext);
            // so we have them do all the work
            assert function instanceof GroupByFunction;
            GroupByFunction func = (GroupByFunction) function;
            func.pushValueTypes(valueTypes);
            groupByFunctions.add(func);
            groupByFunctionPositions.add(columnAst.position);
        }
    }
}
Also used : GroupByFunction(io.questdb.griffin.engine.functions.GroupByFunction) SymbolFunction(io.questdb.griffin.engine.functions.SymbolFunction) GroupByFunction(io.questdb.griffin.engine.functions.GroupByFunction) Function(io.questdb.cairo.sql.Function) QueryColumn(io.questdb.griffin.model.QueryColumn) ExpressionNode(io.questdb.griffin.model.ExpressionNode)

Example 9 with ExpressionNode

use of io.questdb.griffin.model.ExpressionNode in project questdb by bluestreak01.

the class GroupByUtils method validateGroupByColumns.

public static void validateGroupByColumns(@NotNull QueryModel model, int inferredKeyColumnCount) throws SqlException {
    final ObjList<ExpressionNode> groupByColumns = model.getGroupBy();
    int explicitKeyColumnCount = groupByColumns.size();
    if (explicitKeyColumnCount == 0) {
        return;
    }
    final QueryModel nested = model.getNestedModel();
    QueryModel chooseModel = model;
    while (chooseModel != null && chooseModel.getSelectModelType() != QueryModel.SELECT_MODEL_CHOOSE && chooseModel.getSelectModelType() != QueryModel.SELECT_MODEL_NONE) {
        chooseModel = chooseModel.getNestedModel();
    }
    for (int i = 0; i < explicitKeyColumnCount; i++) {
        final ExpressionNode key = groupByColumns.getQuick(i);
        switch(key.type) {
            case ExpressionNode.LITERAL:
                final int dotIndex = Chars.indexOf(key.token, '.');
                if (dotIndex > -1) {
                    int aliasIndex = model.getAliasIndex(key.token, 0, dotIndex);
                    if (aliasIndex > -1) {
                        // we should now check against main model
                        int refColumn = model.getAliasToColumnMap().keyIndex(key.token);
                        if (refColumn > -1) {
                            // a.x not found, look for "x"
                            refColumn = model.getAliasToColumnMap().keyIndex(key.token, dotIndex + 1, key.token.length());
                        }
                        if (refColumn > -1) {
                            throw SqlException.$(key.position, "group by column does not match any key column is select statement");
                        }
                    } else {
                        if (chooseModel != null && chooseModel.getColumnNameToAliasMap().keyIndex(key.token) < 0) {
                            continue;
                        }
                        throw SqlException.$(key.position, "invalid column reference");
                    }
                } else {
                    int refColumn = model.getAliasToColumnMap().keyIndex(key.token);
                    if (refColumn > -1) {
                        throw SqlException.$(key.position, "group by column does not match any key column is select statement");
                    }
                    QueryColumn qc = model.getAliasToColumnMap().valueAt(refColumn);
                    if (qc.getAst().type != ExpressionNode.LITERAL && qc.getAst().type != ExpressionNode.CONSTANT) {
                        throw SqlException.$(key.position, "group by column references aggregate expression");
                    }
                }
                break;
            case ExpressionNode.BIND_VARIABLE:
                throw SqlException.$(key.position, "bind variable is not allowed here");
            case ExpressionNode.FUNCTION:
            case ExpressionNode.OPERATION:
            case ExpressionNode.CONSTANT:
                final ObjList<QueryColumn> availableColumns = nested.getTopDownColumns();
                boolean invalid = true;
                for (int j = 0, n = availableColumns.size(); j < n; j++) {
                    final QueryColumn qc = availableColumns.getQuick(j);
                    if (qc.getAst().type == key.type) {
                        if (ExpressionNode.compareNodesGroupBy(key, qc.getAst(), chooseModel)) {
                            invalid = false;
                            break;
                        }
                    }
                }
                if (invalid) {
                    throw SqlException.$(key.position, "group by expression does not match anything select in statement");
                }
                break;
            default:
                throw SqlException.$(key.position, "unsupported type of expression");
        }
    }
    if (explicitKeyColumnCount < inferredKeyColumnCount) {
        throw SqlException.$(model.getModelPosition(), "not enough columns in group by");
    }
}
Also used : ExpressionNode(io.questdb.griffin.model.ExpressionNode) QueryColumn(io.questdb.griffin.model.QueryColumn) QueryModel(io.questdb.griffin.model.QueryModel)

Example 10 with ExpressionNode

use of io.questdb.griffin.model.ExpressionNode in project questdb by bluestreak01.

the class SampleByFirstLastRecordCursorFactory method buildFirstLastIndex.

private void buildFirstLastIndex(int[] firstLastIndex, int[] queryToFrameColumnMapping, RecordMetadata metadata, ObjList<QueryColumn> columns, int timestampIndex) throws SqlException {
    for (int i = 0, n = firstLastIndex.length; i < n; i++) {
        QueryColumn column = columns.getQuick(i);
        ExpressionNode ast = column.getAst();
        int resultSetColumnType = groupByMetadata.getColumnType(i);
        if (ast.rhs != null) {
            if (SqlKeywords.isLastFunction(ast.token)) {
                firstLastIndex[i] = LAST_OUT_INDEX;
            } else if (SqlKeywords.isFirstFunction(ast.token)) {
                firstLastIndex[i] = FIRST_OUT_INDEX;
            } else {
                throw SqlException.$(ast.position, "expected first() or last() functions but got ").put(ast.token);
            }
            int underlyingColIndex = metadata.getColumnIndex(ast.rhs.token);
            queryToFrameColumnMapping[i] = underlyingColIndex;
            int underlyingType = metadata.getColumnType(underlyingColIndex);
            if (underlyingType != resultSetColumnType || ColumnType.pow2SizeOf(resultSetColumnType) > 3) {
                throw SqlException.$(ast.position, "column \"").put(metadata.getColumnName(underlyingColIndex)).put("\": first(), last() is not supported on data type ").put(ColumnType.nameOf(underlyingType)).put(" ");
            }
        } else {
            int underlyingColIndex = metadata.getColumnIndex(ast.token);
            queryToFrameColumnMapping[i] = underlyingColIndex;
            if (underlyingColIndex == timestampIndex) {
                groupByTimestampIndex = i;
            }
        }
    }
}
Also used : QueryColumn(io.questdb.griffin.model.QueryColumn) ExpressionNode(io.questdb.griffin.model.ExpressionNode)

Aggregations

ExpressionNode (io.questdb.griffin.model.ExpressionNode)22 QueryColumn (io.questdb.griffin.model.QueryColumn)6 FlyweightCharSequence (io.questdb.std.str.FlyweightCharSequence)6 Function (io.questdb.cairo.sql.Function)4 GroupByFunction (io.questdb.griffin.engine.functions.GroupByFunction)3 AbstractGriffinTest (io.questdb.griffin.AbstractGriffinTest)2 SqlException (io.questdb.griffin.SqlException)2 SymbolFunction (io.questdb.griffin.engine.functions.SymbolFunction)2 ObjList (io.questdb.std.ObjList)2 Test (org.junit.Test)2 AbstractGeoHashFunction (io.questdb.griffin.engine.functions.AbstractGeoHashFunction)1 IntrinsicModel (io.questdb.griffin.model.IntrinsicModel)1 QueryModel (io.questdb.griffin.model.QueryModel)1 NotNull (org.jetbrains.annotations.NotNull)1