Search in sources :

Example 1 with UpdateOp

use of herddb.model.planner.UpdateOp 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

AutoIncrementPrimaryKeyRecordFunction (herddb.model.AutoIncrementPrimaryKeyRecordFunction)1 Predicate (herddb.model.Predicate)1 RecordFunction (herddb.model.RecordFunction)1 Table (herddb.model.Table)1 ScanStatement (herddb.model.commands.ScanStatement)1 UpdateStatement (herddb.model.commands.UpdateStatement)1 BindableTableScanOp (herddb.model.planner.BindableTableScanOp)1 FilterOp (herddb.model.planner.FilterOp)1 FilteredTableScanOp (herddb.model.planner.FilteredTableScanOp)1 PlannerOp (herddb.model.planner.PlannerOp)1 ProjectOp (herddb.model.planner.ProjectOp)1 ReplaceOp (herddb.model.planner.ReplaceOp)1 SimpleUpdateOp (herddb.model.planner.SimpleUpdateOp)1 TableScanOp (herddb.model.planner.TableScanOp)1 UpdateOp (herddb.model.planner.UpdateOp)1 CompiledSQLExpression (herddb.sql.expressions.CompiledSQLExpression)1 ShowCreateTableCalculator.calculateShowCreateTable (herddb.sql.functions.ShowCreateTableCalculator.calculateShowCreateTable)1 ArrayList (java.util.ArrayList)1 RelOptTable (org.apache.calcite.plan.RelOptTable)1 RexNode (org.apache.calcite.rex.RexNode)1