Search in sources :

Example 6 with PlannerOp

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

the class JSQLParserPlanner method buildSetOperationList.

private PlannerOp buildSetOperationList(String defaultTableSpace, int maxRows, SetOperationList list, boolean forceScan) {
    checkSupported(list.getFetch() == null);
    checkSupported(list.getLimit() == null);
    checkSupported(list.getOffset() == null);
    checkSupported(list.getOrderByElements() == null);
    checkSupported(list.getOperations().size() == 1);
    checkSupported(list.getSelects().size() == 2);
    final SetOperation operation = list.getOperations().get(0);
    checkSupported(operation instanceof UnionOp);
    UnionOp unionOp = (UnionOp) operation;
    // only "UNION ALL"
    checkSupported(unionOp.isAll());
    checkSupported(!unionOp.isDistinct());
    List<PlannerOp> inputs = new ArrayList<>();
    for (SelectBody body : list.getSelects()) {
        inputs.add(buildSelectBody(defaultTableSpace, -1, body, forceScan));
    }
    PlannerOp op = new UnionAllOp(inputs);
    if (maxRows > 0) {
        op = new LimitOp(op, new ConstantExpression(maxRows, ColumnTypes.NOTNULL_LONG), null);
    }
    return op;
}
Also used : SetOperation(net.sf.jsqlparser.statement.select.SetOperation) UnionOp(net.sf.jsqlparser.statement.select.UnionOp) PlannerOp(herddb.model.planner.PlannerOp) UnionAllOp(herddb.model.planner.UnionAllOp) ConstantExpression(herddb.sql.expressions.ConstantExpression) ArrayList(java.util.ArrayList) SelectBody(net.sf.jsqlparser.statement.select.SelectBody) LimitOp(herddb.model.planner.LimitOp)

Example 7 with PlannerOp

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

the class JSQLParserPlanner method buildDeleteStatement.

private ExecutionPlan buildDeleteStatement(String defaultTableSpace, Delete delete) throws StatementExecutionException {
    net.sf.jsqlparser.schema.Table table = delete.getTable();
    // no alias for DELETE!
    checkSupported(table.getAlias() == null);
    OpSchema tableSchema = getTableSchema(defaultTableSpace, table);
    TableSpaceManager tableSpaceManager = manager.getTableSpaceManager(tableSchema.tableSpace);
    AbstractTableManager tableManager = tableSpaceManager.getTableManager(tableSchema.name);
    Table tableImpl = tableManager.getTable();
    checkSupported(delete.getLimit() == null);
    checkSupported(delete.getJoins() == null);
    checkSupported(delete.getOrderByElements() == null);
    checkSupported(delete.getTables() == null || delete.getTables().isEmpty());
    Predicate where = null;
    if (delete.getWhere() != null) {
        CompiledSQLExpression whereExpression = SQLParserExpressionCompiler.compileExpression(delete.getWhere(), tableSchema);
        if (whereExpression != null) {
            SQLRecordPredicate sqlWhere = new SQLRecordPredicate(tableImpl, null, whereExpression);
            IndexUtils.discoverIndexOperations(tableSchema.tableSpace, whereExpression, tableImpl, sqlWhere, delete, tableSpaceManager);
            where = sqlWhere;
        }
    }
    PlannerOp op = new SimpleDeleteOp(new DeleteStatement(tableSchema.tableSpace, tableSchema.name, null, where));
    return optimizePlan(op);
}
Also used : Table(herddb.model.Table) ShowCreateTableCalculator.calculateShowCreateTable(herddb.sql.functions.ShowCreateTableCalculator.calculateShowCreateTable) CreateTable(net.sf.jsqlparser.statement.create.table.CreateTable) PlannerOp(herddb.model.planner.PlannerOp) CompiledSQLExpression(herddb.sql.expressions.CompiledSQLExpression) DeleteStatement(herddb.model.commands.DeleteStatement) Predicate(herddb.model.Predicate) AbstractTableManager(herddb.core.AbstractTableManager) SimpleDeleteOp(herddb.model.planner.SimpleDeleteOp) TableSpaceManager(herddb.core.TableSpaceManager) OpSchema(herddb.sql.expressions.OpSchema)

Example 8 with PlannerOp

use of herddb.model.planner.PlannerOp 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 9 with PlannerOp

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

the class CalcitePlanner method planDelete.

private PlannerOp planDelete(EnumerableTableModify dml) {
    PlannerOp input = convertRelNode(dml.getInput(), null, false, false);
    final String tableSpace = dml.getTable().getQualifiedName().get(0);
    final String tableName = dml.getTable().getQualifiedName().get(1);
    final TableImpl tableImpl = (TableImpl) dml.getTable().unwrap(org.apache.calcite.schema.Table.class);
    Table table = tableImpl.tableManager.getTable();
    DeleteStatement delete = null;
    if (input instanceof TableScanOp) {
        delete = new DeleteStatement(tableSpace, tableName, null, null);
    } else if (input instanceof FilterOp) {
        FilterOp filter = (FilterOp) input;
        if (filter.getInput() instanceof TableScanOp) {
            SQLRecordPredicate pred = new SQLRecordPredicate(table, null, filter.getCondition());
            delete = new DeleteStatement(tableSpace, tableName, null, pred);
        }
    } else if (input instanceof BindableTableScanOp) {
        BindableTableScanOp filter = (BindableTableScanOp) input;
        Predicate pred = filter.getStatement().getPredicate();
        delete = new DeleteStatement(tableSpace, tableName, null, pred);
    }
    if (delete != null) {
        return new SimpleDeleteOp(delete);
    } else {
        return new DeleteOp(tableSpace, tableName, input);
    }
}
Also used : PlannerOp(herddb.model.planner.PlannerOp) Table(herddb.model.Table) ShowCreateTableCalculator.calculateShowCreateTable(herddb.sql.functions.ShowCreateTableCalculator.calculateShowCreateTable) SqlStdOperatorTable(org.apache.calcite.sql.fun.SqlStdOperatorTable) RelOptTable(org.apache.calcite.plan.RelOptTable) ProjectableFilterableTable(org.apache.calcite.schema.ProjectableFilterableTable) ScannableTable(org.apache.calcite.schema.ScannableTable) AbstractTable(org.apache.calcite.schema.impl.AbstractTable) ModifiableTable(org.apache.calcite.schema.ModifiableTable) FilteredTableScanOp(herddb.model.planner.FilteredTableScanOp) BindableTableScanOp(herddb.model.planner.BindableTableScanOp) TableScanOp(herddb.model.planner.TableScanOp) FilterOp(herddb.model.planner.FilterOp) DeleteStatement(herddb.model.commands.DeleteStatement) Predicate(herddb.model.Predicate) SimpleDeleteOp(herddb.model.planner.SimpleDeleteOp) DeleteOp(herddb.model.planner.DeleteOp) SimpleDeleteOp(herddb.model.planner.SimpleDeleteOp) BindableTableScanOp(herddb.model.planner.BindableTableScanOp)

Example 10 with PlannerOp

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

the class CalcitePlanner method planUpdate.

private PlannerOp planUpdate(EnumerableTableModify dml, boolean returnValues) {
    PlannerOp input = convertRelNode(dml.getInput(), null, false, false);
    List<String> updateColumnList = dml.getUpdateColumnList();
    List<RexNode> sourceExpressionList = dml.getSourceExpressionList();
    final String tableSpace = dml.getTable().getQualifiedName().get(0);
    final String tableName = dml.getTable().getQualifiedName().get(1);
    final TableImpl tableImpl = (TableImpl) dml.getTable().unwrap(org.apache.calcite.schema.Table.class);
    Table table = tableImpl.tableManager.getTable();
    List<CompiledSQLExpression> expressionsForValue = new ArrayList<>(sourceExpressionList.size());
    List<CompiledSQLExpression> expressionsForKey = new ArrayList<>(sourceExpressionList.size());
    List<String> updateColumnListInValue = new ArrayList<>(updateColumnList.size());
    List<String> updateColumnListInPk = new ArrayList<>();
    for (int i = 0; i < updateColumnList.size(); i++) {
        String columnName = updateColumnList.get(i);
        boolean isPk = table.isPrimaryKeyColumn(columnName);
        RexNode node = sourceExpressionList.get(i);
        CompiledSQLExpression exp = SQLExpressionCompiler.compileExpression(node);
        if (isPk) {
            updateColumnListInPk.add(columnName);
            expressionsForKey.add(exp);
        } else {
            updateColumnListInValue.add(columnName);
            expressionsForValue.add(exp);
        }
    }
    if (expressionsForKey.isEmpty()) {
        // standard UPDATE, we are not updating any column in the PK
        RecordFunction function = new SQLRecordFunction(updateColumnListInValue, table, expressionsForValue);
        UpdateStatement update = null;
        if (input instanceof TableScanOp) {
            update = new UpdateStatement(tableSpace, tableName, null, function, null);
        } else if (input instanceof FilterOp) {
            FilterOp filter = (FilterOp) input;
            if (filter.getInput() instanceof TableScanOp) {
                SQLRecordPredicate pred = new SQLRecordPredicate(table, null, filter.getCondition());
                update = new UpdateStatement(tableSpace, tableName, null, function, pred);
            }
        } else if (input instanceof ProjectOp) {
            ProjectOp proj = (ProjectOp) input;
            if (proj.getInput() instanceof TableScanOp) {
                update = new UpdateStatement(tableSpace, tableName, null, function, null);
            } else if (proj.getInput() instanceof FilterOp) {
                FilterOp filter = (FilterOp) proj.getInput();
                if (filter.getInput() instanceof TableScanOp) {
                    SQLRecordPredicate pred = new SQLRecordPredicate(table, null, filter.getCondition());
                    update = new UpdateStatement(tableSpace, tableName, null, function, pred);
                }
            } else if (proj.getInput() instanceof FilteredTableScanOp) {
                FilteredTableScanOp filter = (FilteredTableScanOp) proj.getInput();
                Predicate pred = filter.getPredicate();
                update = new UpdateStatement(tableSpace, tableName, null, function, pred);
            } else if (proj.getInput() instanceof BindableTableScanOp) {
                BindableTableScanOp filter = (BindableTableScanOp) proj.getInput();
                ScanStatement scan = filter.getStatement();
                if (scan.getComparator() == null && scan.getLimits() == null && scan.getTableDef() != null) {
                    Predicate pred = scan.getPredicate();
                    update = new UpdateStatement(tableSpace, tableName, null, function, pred);
                }
            }
        }
        if (update != null) {
            return new SimpleUpdateOp(update.setReturnValues(returnValues));
        } else {
            return new UpdateOp(tableSpace, tableName, input, returnValues, function);
        }
    } else {
        // bad stuff ! we are updating the PK, we need to transform this to a sequence of delete and inserts
        // ReplaceOp won't execute the two statements atomically
        RecordFunction functionForValue = new SQLRecordFunction(updateColumnListInValue, table, expressionsForValue);
        SQLRecordKeyFunction functionForKey = new SQLRecordKeyFunction(updateColumnListInPk, expressionsForKey, table);
        return new ReplaceOp(tableSpace, tableName, input, returnValues, functionForKey, functionForValue);
    }
}
Also used : SimpleUpdateOp(herddb.model.planner.SimpleUpdateOp) UpdateOp(herddb.model.planner.UpdateOp) FilterOp(herddb.model.planner.FilterOp) ArrayList(java.util.ArrayList) CompiledSQLExpression(herddb.sql.expressions.CompiledSQLExpression) Predicate(herddb.model.Predicate) ReplaceOp(herddb.model.planner.ReplaceOp) RecordFunction(herddb.model.RecordFunction) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction) ScanStatement(herddb.model.commands.ScanStatement) UpdateStatement(herddb.model.commands.UpdateStatement) PlannerOp(herddb.model.planner.PlannerOp) Table(herddb.model.Table) ShowCreateTableCalculator.calculateShowCreateTable(herddb.sql.functions.ShowCreateTableCalculator.calculateShowCreateTable) SqlStdOperatorTable(org.apache.calcite.sql.fun.SqlStdOperatorTable) RelOptTable(org.apache.calcite.plan.RelOptTable) ProjectableFilterableTable(org.apache.calcite.schema.ProjectableFilterableTable) ScannableTable(org.apache.calcite.schema.ScannableTable) AbstractTable(org.apache.calcite.schema.impl.AbstractTable) ModifiableTable(org.apache.calcite.schema.ModifiableTable) FilteredTableScanOp(herddb.model.planner.FilteredTableScanOp) BindableTableScanOp(herddb.model.planner.BindableTableScanOp) TableScanOp(herddb.model.planner.TableScanOp) ProjectOp(herddb.model.planner.ProjectOp) FilteredTableScanOp(herddb.model.planner.FilteredTableScanOp) SimpleUpdateOp(herddb.model.planner.SimpleUpdateOp) RexNode(org.apache.calcite.rex.RexNode) BindableTableScanOp(herddb.model.planner.BindableTableScanOp)

Aggregations

PlannerOp (herddb.model.planner.PlannerOp)27 CompiledSQLExpression (herddb.sql.expressions.CompiledSQLExpression)16 Column (herddb.model.Column)12 Table (herddb.model.Table)9 ShowCreateTableCalculator.calculateShowCreateTable (herddb.sql.functions.ShowCreateTableCalculator.calculateShowCreateTable)9 ArrayList (java.util.ArrayList)9 ConstantExpression (herddb.sql.expressions.ConstantExpression)8 RelDataType (org.apache.calcite.rel.type.RelDataType)8 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)8 StatementExecutionException (herddb.model.StatementExecutionException)7 ScanStatement (herddb.model.commands.ScanStatement)6 AutoIncrementPrimaryKeyRecordFunction (herddb.model.AutoIncrementPrimaryKeyRecordFunction)5 RecordFunction (herddb.model.RecordFunction)5 JdbcParameterExpression (herddb.sql.expressions.JdbcParameterExpression)5 TypedJdbcParameterExpression (herddb.sql.expressions.TypedJdbcParameterExpression)5 List (java.util.List)5 CreateTable (net.sf.jsqlparser.statement.create.table.CreateTable)5 AbstractTableManager (herddb.core.AbstractTableManager)4 TableSpaceManager (herddb.core.TableSpaceManager)4 Predicate (herddb.model.Predicate)4