Search in sources :

Example 1 with QueryColumn

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

the class AbstractSqlParserTest method validateTopDownColumns.

private void validateTopDownColumns(QueryModel model) {
    ObjList<QueryColumn> columns = model.getColumns();
    final ObjList<LowerCaseCharSequenceHashSet> nameSets = new ObjList<>();
    QueryModel nested = model.getNestedModel();
    while (nested != null) {
        nameSets.clear();
        for (int i = 0, n = nested.getJoinModels().size(); i < n; i++) {
            LowerCaseCharSequenceHashSet set = new LowerCaseCharSequenceHashSet();
            final QueryModel m = nested.getJoinModels().getQuick(i);
            final ObjList<QueryColumn> cols = m.getTopDownColumns();
            for (int j = 0, k = cols.size(); j < k; j++) {
                QueryColumn qc = cols.getQuick(j);
                Assert.assertTrue(set.add(qc.getName()));
            }
            nameSets.add(set);
        }
        for (int i = 0, n = columns.size(); i < n; i++) {
            AbstractSqlParserTest.checkLiteralIsInSet(columns.getQuick(i).getAst(), nameSets, nested.getAliasIndexes());
        }
        columns = nested.getTopDownColumns();
        nested = nested.getNestedModel();
    }
}
Also used : QueryColumn(io.questdb.griffin.model.QueryColumn) QueryModel(io.questdb.griffin.model.QueryModel)

Example 2 with QueryColumn

use of io.questdb.griffin.model.QueryColumn 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 3 with QueryColumn

use of io.questdb.griffin.model.QueryColumn 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 4 with QueryColumn

use of io.questdb.griffin.model.QueryColumn 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 5 with QueryColumn

use of io.questdb.griffin.model.QueryColumn 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

QueryColumn (io.questdb.griffin.model.QueryColumn)7 ExpressionNode (io.questdb.griffin.model.ExpressionNode)6 Function (io.questdb.cairo.sql.Function)2 AbstractGriffinTest (io.questdb.griffin.AbstractGriffinTest)2 SqlException (io.questdb.griffin.SqlException)2 GroupByFunction (io.questdb.griffin.engine.functions.GroupByFunction)2 SymbolFunction (io.questdb.griffin.engine.functions.SymbolFunction)2 QueryModel (io.questdb.griffin.model.QueryModel)2 ObjList (io.questdb.std.ObjList)2 Test (org.junit.Test)2