Search in sources :

Example 1 with AggregateOp

use of herddb.model.planner.AggregateOp in project herddb by diennea.

the class JSQLParserPlanner method planAggregate.

private PlannerOp planAggregate(List<SelectExpressionItem> fieldList, OpSchema inputSchema, PlannerOp input, OpSchema originalTableSchema, GroupByElement groupBy) {
    List<Column> outputSchemaKeysInGroupBy = new ArrayList<>();
    List<String> fieldnamesKeysInGroupBy = new ArrayList<>();
    List<Column> outputSchemaAggregationResults = new ArrayList<>();
    List<String> fieldnamesAggregationResults = new ArrayList<>();
    List<Integer> projectionAggregationResults = new ArrayList<>();
    List<List<Integer>> argLists = new ArrayList<>();
    List<String> aggtypes = new ArrayList<>();
    List<Column> originalOutputSchema = new ArrayList<>();
    List<String> originalFieldNames = new ArrayList<>();
    Set<String> nonAggregateColumns = new HashSet<>();
    int k = 0;
    for (SelectExpressionItem sel : fieldList) {
        Alias alias = sel.getAlias();
        String fieldName = null;
        if (alias != null) {
            checkSupported(alias.getAliasColumns() == null);
            fieldName = fixMySqlBackTicks(alias.getName().toLowerCase());
        }
        Expression exp = sel.getExpression();
        Function fn = SQLParserExpressionCompiler.detectAggregatedFunction(exp);
        if (fn != null) {
            int type = SQLParserExpressionCompiler.getAggregateFunctionType(exp, inputSchema);
            ColumnRef additionalColumn = SQLParserExpressionCompiler.getAggregateFunctionArgument(fn, inputSchema);
            aggtypes.add(fixMySqlBackTicks(fn.getName().toLowerCase()));
            if (additionalColumn != null) {
                // SELECT min(col) -> we have to add "col" to the scan
                IntHolder pos = new IntHolder();
                findColumnInSchema(additionalColumn.tableName, fixMySqlBackTicks(additionalColumn.name), originalTableSchema, pos);
                checkSupported(pos.value >= 0);
                argLists.add(Collections.singletonList(pos.value));
            } else {
                argLists.add(Collections.emptyList());
            }
            if (fieldName == null) {
                fieldName = "expr$" + k;
            }
            Column col = Column.column(fieldName, type);
            outputSchemaAggregationResults.add(col);
            originalFieldNames.add(fieldName);
            originalOutputSchema.add(col);
            fieldnamesAggregationResults.add(fieldName);
            projectionAggregationResults.add(k);
        } else if (exp instanceof net.sf.jsqlparser.schema.Column) {
            net.sf.jsqlparser.schema.Column colRef = (net.sf.jsqlparser.schema.Column) exp;
            String tableAlias = extractTableName(colRef);
            ColumnRef colInSchema = findColumnInSchema(tableAlias, fixMySqlBackTicks(colRef.getColumnName()), inputSchema, new IntHolder());
            checkSupported(colInSchema != null);
            if (fieldName == null) {
                fieldName = colInSchema.name;
            }
            Column col = Column.column(fieldName, colInSchema.type);
            originalFieldNames.add(fieldName);
            originalOutputSchema.add(col);
            nonAggregateColumns.add(fieldName);
        } else {
            checkSupported(false);
        }
        k++;
    }
    // GROUP BY
    List<Integer> groupedFieldsIndexes = new ArrayList<>();
    List<Integer> projectionForGroupByFields = new ArrayList<>();
    if (groupBy != null) {
        checkSupported(groupBy.getGroupingSets() == null || groupBy.getGroupingSets().isEmpty());
        int posInGroupBy = 0;
        for (Expression exp : groupBy.getGroupByExpressions()) {
            if (exp instanceof net.sf.jsqlparser.schema.Column) {
                net.sf.jsqlparser.schema.Column colRef = (net.sf.jsqlparser.schema.Column) exp;
                String tableName = extractTableName(colRef);
                IntHolder pos = new IntHolder();
                ColumnRef colInSchema = findColumnInSchema(tableName, fixMySqlBackTicks(colRef.getColumnName()), inputSchema, pos);
                checkSupported(colInSchema != null);
                groupedFieldsIndexes.add(pos.value);
                fieldnamesKeysInGroupBy.add(fixMySqlBackTicks(colRef.getColumnName()));
                outputSchemaKeysInGroupBy.add(colInSchema.toColumn());
                projectionForGroupByFields.add(posInGroupBy);
            } else {
                checkSupported(false);
            }
            posInGroupBy++;
        }
    } else {
        // -> column MUST be in GROUP BY !
        for (String s : nonAggregateColumns) {
            throw new StatementExecutionException("field " + s + " MUST appear in GROUP BY clause");
        }
    }
    PlannerOp op;
    if (!groupedFieldsIndexes.isEmpty()) {
        // this is tricky,
        // the AggregateOp always create a result in the form of
        // FIELD1,FIELD2......AGG1,AGG2
        // Basically it puts all of the results of the aggregation to the right
        // So we have to add a projection that makes the resultset appear
        // as it is defined in the SELECT clause
        List<Column> outputSchema = new ArrayList<>();
        outputSchema.addAll(outputSchemaKeysInGroupBy);
        outputSchema.addAll(outputSchemaAggregationResults);
        Column[] outputSchemaArray = outputSchema.toArray(new Column[0]);
        List<String> aggreateFieldNames = new ArrayList<>();
        aggreateFieldNames.addAll(fieldnamesKeysInGroupBy);
        aggreateFieldNames.addAll(fieldnamesAggregationResults);
        op = new AggregateOp(input, aggreateFieldNames.toArray(new String[0]), outputSchemaArray, aggtypes.toArray(new String[0]), argLists, groupedFieldsIndexes);
        String[] reodereded = originalFieldNames.toArray(new String[0]);
        int[] projections = new int[originalFieldNames.size()];
        int i = 0;
        for (int pos : projectionForGroupByFields) {
            projections[pos] = i++;
        }
        for (int pos : projectionAggregationResults) {
            projections[pos] = i++;
        }
        ProjectOp.ZeroCopyProjection projection = new ProjectOp.ZeroCopyProjection(reodereded, originalOutputSchema.toArray(new Column[0]), projections);
        op = new ProjectOp(projection, op);
    } else {
        // no "GROUP BY", so no need for an additional projection
        // this is the SELECT COUNT(*) FROM TABLE case
        op = new AggregateOp(input, originalFieldNames.toArray(new String[0]), originalOutputSchema.toArray(new Column[0]), aggtypes.toArray(new String[0]), argLists, groupedFieldsIndexes);
    }
    return op;
}
Also used : SelectExpressionItem(net.sf.jsqlparser.statement.select.SelectExpressionItem) ArrayList(java.util.ArrayList) StatementExecutionException(herddb.model.StatementExecutionException) Function(net.sf.jsqlparser.expression.Function) CompiledFunction(herddb.sql.expressions.CompiledFunction) RecordFunction(herddb.model.RecordFunction) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction) Column(herddb.model.Column) IntHolder(herddb.utils.IntHolder) ItemsList(net.sf.jsqlparser.expression.operators.relational.ItemsList) ArrayList(java.util.ArrayList) ExpressionList(net.sf.jsqlparser.expression.operators.relational.ExpressionList) MultiExpressionList(net.sf.jsqlparser.expression.operators.relational.MultiExpressionList) List(java.util.List) SetOperationList(net.sf.jsqlparser.statement.select.SetOperationList) HashSet(java.util.HashSet) PlannerOp(herddb.model.planner.PlannerOp) ProjectOp(herddb.model.planner.ProjectOp) AggregateOp(herddb.model.planner.AggregateOp) AccessCurrentRowExpression(herddb.sql.expressions.AccessCurrentRowExpression) Expression(net.sf.jsqlparser.expression.Expression) CompiledMultiAndExpression(herddb.sql.expressions.CompiledMultiAndExpression) JdbcParameterExpression(herddb.sql.expressions.JdbcParameterExpression) AlterExpression(net.sf.jsqlparser.statement.alter.AlterExpression) TypedJdbcParameterExpression(herddb.sql.expressions.TypedJdbcParameterExpression) ConstantExpression(herddb.sql.expressions.ConstantExpression) SignedExpression(net.sf.jsqlparser.expression.SignedExpression) CompiledSQLExpression(herddb.sql.expressions.CompiledSQLExpression) CompiledEqualsExpression(herddb.sql.expressions.CompiledEqualsExpression) Alias(net.sf.jsqlparser.expression.Alias) ColumnRef(herddb.sql.expressions.ColumnRef)

Example 2 with AggregateOp

use of herddb.model.planner.AggregateOp in project herddb by diennea.

the class CalcitePlanner method planAggregate.

private PlannerOp planAggregate(EnumerableAggregate op, RelDataType rowType, boolean returnValues) {
    List<RelDataTypeField> fieldList = op.getRowType().getFieldList();
    List<AggregateCall> calls = op.getAggCallList();
    String[] fieldnames = new String[fieldList.size()];
    String[] aggtypes = new String[calls.size()];
    Column[] columns = new Column[fieldList.size()];
    List<Integer> groupedFiledsIndexes = op.getGroupSet().toList();
    List<List<Integer>> argLists = new ArrayList<>(calls.size());
    int i = 0;
    int idaggcall = 0;
    for (RelDataTypeField c : fieldList) {
        int type = convertToHerdType(c.getType());
        Column co = Column.column(c.getName(), type);
        columns[i] = co;
        fieldnames[i] = c.getName().toLowerCase();
        i++;
    }
    for (AggregateCall call : calls) {
        aggtypes[idaggcall++] = call.getAggregation().getName();
        argLists.add(call.getArgList());
    }
    PlannerOp input = convertRelNode(op.getInput(), null, returnValues, false);
    return new AggregateOp(input, fieldnames, columns, aggtypes, argLists, groupedFiledsIndexes);
}
Also used : PlannerOp(herddb.model.planner.PlannerOp) ArrayList(java.util.ArrayList) AggregateCall(org.apache.calcite.rel.core.AggregateCall) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) AggregateOp(herddb.model.planner.AggregateOp) Column(herddb.model.Column) ArrayList(java.util.ArrayList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList)

Aggregations

Column (herddb.model.Column)2 AggregateOp (herddb.model.planner.AggregateOp)2 PlannerOp (herddb.model.planner.PlannerOp)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 ImmutableList (com.google.common.collect.ImmutableList)1 AutoIncrementPrimaryKeyRecordFunction (herddb.model.AutoIncrementPrimaryKeyRecordFunction)1 RecordFunction (herddb.model.RecordFunction)1 StatementExecutionException (herddb.model.StatementExecutionException)1 ProjectOp (herddb.model.planner.ProjectOp)1 AccessCurrentRowExpression (herddb.sql.expressions.AccessCurrentRowExpression)1 ColumnRef (herddb.sql.expressions.ColumnRef)1 CompiledEqualsExpression (herddb.sql.expressions.CompiledEqualsExpression)1 CompiledFunction (herddb.sql.expressions.CompiledFunction)1 CompiledMultiAndExpression (herddb.sql.expressions.CompiledMultiAndExpression)1 CompiledSQLExpression (herddb.sql.expressions.CompiledSQLExpression)1 ConstantExpression (herddb.sql.expressions.ConstantExpression)1 JdbcParameterExpression (herddb.sql.expressions.JdbcParameterExpression)1 TypedJdbcParameterExpression (herddb.sql.expressions.TypedJdbcParameterExpression)1 IntHolder (herddb.utils.IntHolder)1