Search in sources :

Example 1 with ConstantExpression

use of herddb.sql.expressions.ConstantExpression in project herddb by diennea.

the class InsertOp method execute.

@Override
public StatementExecutionResult execute(TableSpaceManager tableSpaceManager, TransactionContext transactionContext, StatementEvaluationContext context, boolean lockRequired, boolean forWrite) {
    StatementExecutionResult input = this.input.execute(tableSpaceManager, transactionContext, context, true, true);
    ScanResult downstreamScanResult = (ScanResult) input;
    final Table table = tableSpaceManager.getTableManager(tableName).getTable();
    long transactionId = transactionContext.transactionId;
    int updateCount = 0;
    Bytes key = null;
    Bytes newValue = null;
    try (DataScanner inputScanner = downstreamScanResult.dataScanner) {
        while (inputScanner.hasNext()) {
            DataAccessor row = inputScanner.next();
            long transactionIdFromScanner = inputScanner.getTransactionId();
            if (transactionIdFromScanner > 0 && transactionIdFromScanner != transactionId) {
                transactionId = transactionIdFromScanner;
                transactionContext = new TransactionContext(transactionId);
            }
            int index = 0;
            List<CompiledSQLExpression> keyValueExpression = new ArrayList<>();
            List<String> keyExpressionToColumn = new ArrayList<>();
            List<CompiledSQLExpression> valuesExpressions = new ArrayList<>();
            List<String> valuesColumns = new ArrayList<>();
            for (Column column : table.getColumns()) {
                Object value = row.get(index++);
                if (value != null) {
                    ConstantExpression exp = new ConstantExpression(value);
                    if (table.isPrimaryKeyColumn(column.name)) {
                        keyExpressionToColumn.add(column.name);
                        keyValueExpression.add(exp);
                    }
                    valuesColumns.add(column.name);
                    valuesExpressions.add(exp);
                }
            }
            RecordFunction keyfunction;
            if (keyValueExpression.isEmpty() && table.auto_increment) {
                keyfunction = new AutoIncrementPrimaryKeyRecordFunction();
            } else {
                if (keyValueExpression.size() != table.primaryKey.length) {
                    throw new StatementExecutionException("you must set a value for the primary key (expressions=" + keyValueExpression.size() + ")");
                }
                keyfunction = new SQLRecordKeyFunction(keyExpressionToColumn, keyValueExpression, table);
            }
            RecordFunction valuesfunction = new SQLRecordFunction(valuesColumns, table, valuesExpressions);
            DMLStatement insertStatement = new InsertStatement(tableSpace, tableName, keyfunction, valuesfunction).setReturnValues(returnValues);
            DMLStatementExecutionResult _result = (DMLStatementExecutionResult) tableSpaceManager.executeStatement(insertStatement, context, transactionContext);
            updateCount += _result.getUpdateCount();
            if (_result.transactionId > 0 && _result.transactionId != transactionId) {
                transactionId = _result.transactionId;
                transactionContext = new TransactionContext(transactionId);
            }
            key = _result.getKey();
            newValue = _result.getNewvalue();
        }
        if (updateCount > 1 && returnValues) {
            if (transactionId > 0) {
                // usually the first record will be rolledback with transaction failure
                throw new StatementExecutionException("cannot 'return values' on multi-values insert");
            } else {
                throw new StatementExecutionException("cannot 'return values' on multi-values insert, at least record could have been written because autocommit=true");
            }
        }
        return new DMLStatementExecutionResult(transactionId, updateCount, key, newValue);
    } catch (DataScannerException err) {
        throw new StatementExecutionException(err);
    }
}
Also used : DataAccessor(herddb.utils.DataAccessor) ConstantExpression(herddb.sql.expressions.ConstantExpression) ArrayList(java.util.ArrayList) CompiledSQLExpression(herddb.sql.expressions.CompiledSQLExpression) StatementExecutionException(herddb.model.StatementExecutionException) InsertStatement(herddb.model.commands.InsertStatement) Bytes(herddb.utils.Bytes) DataScanner(herddb.model.DataScanner) Column(herddb.model.Column) DMLStatementExecutionResult(herddb.model.DMLStatementExecutionResult) StatementExecutionResult(herddb.model.StatementExecutionResult) SQLRecordFunction(herddb.sql.SQLRecordFunction) SQLRecordFunction(herddb.sql.SQLRecordFunction) RecordFunction(herddb.model.RecordFunction) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction) SQLRecordKeyFunction(herddb.sql.SQLRecordKeyFunction) DataScannerException(herddb.model.DataScannerException) ScanResult(herddb.model.ScanResult) Table(herddb.model.Table) DMLStatementExecutionResult(herddb.model.DMLStatementExecutionResult) TransactionContext(herddb.model.TransactionContext) DMLStatement(herddb.model.DMLStatement) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction)

Example 2 with ConstantExpression

use of herddb.sql.expressions.ConstantExpression in project herddb by diennea.

the class CalcitePlanner method translate.

@Override
public TranslatedQuery translate(String defaultTableSpace, String query, List<Object> parameters, boolean scan, boolean allowCache, boolean returnValues, int maxRows) throws StatementExecutionException {
    query = SQLPlanner.rewriteExecuteSyntax(query);
    if (query.startsWith("EXECUTE") || query.startsWith("CREATE") || query.startsWith("DROP") || query.startsWith("ALTER") || query.startsWith("TRUNCATE")) {
        return fallback.translate(defaultTableSpace, query, parameters, scan, allowCache, returnValues, maxRows);
    }
    if (parameters == null) {
        parameters = Collections.emptyList();
    }
    String cacheKey = "scan:" + scan + ",defaultTableSpace:" + defaultTableSpace + ",query:" + query + ",returnValues:" + returnValues + ",maxRows:" + maxRows;
    if (allowCache) {
        ExecutionPlan cached = cache.get(cacheKey);
        if (cached != null) {
            return new TranslatedQuery(cached, new SQLStatementEvaluationContext(query, parameters));
        }
    }
    if (!isCachable(query)) {
        allowCache = false;
    }
    try {
        if (query.startsWith("EXPLAIN ")) {
            query = query.substring("EXPLAIN ".length());
            PlannerResult plan = runPlanner(defaultTableSpace, query);
            PlannerOp finalPlan = convertRelNode(plan.topNode, plan.originalRowType, returnValues).optimize();
            ValuesOp values = new ValuesOp(manager.getNodeId(), new String[] { "name", "value" }, new Column[] { column("name", ColumnTypes.STRING), column("value", ColumnTypes.STRING) }, java.util.Arrays.asList(java.util.Arrays.asList(new ConstantExpression("query"), new ConstantExpression(query)), java.util.Arrays.asList(new ConstantExpression("logicalplan"), new ConstantExpression(RelOptUtil.dumpPlan("", plan.logicalPlan, SqlExplainFormat.TEXT, SqlExplainLevel.ALL_ATTRIBUTES))), java.util.Arrays.asList(new ConstantExpression("plan"), new ConstantExpression(RelOptUtil.dumpPlan("", plan.topNode, SqlExplainFormat.TEXT, SqlExplainLevel.ALL_ATTRIBUTES))), java.util.Arrays.asList(new ConstantExpression("finalplan"), new ConstantExpression(finalPlan + ""))));
            ExecutionPlan executionPlan = ExecutionPlan.simple(new SQLPlannedOperationStatement(values));
            return new TranslatedQuery(executionPlan, new SQLStatementEvaluationContext(query, parameters));
        }
        PlannerResult plan = runPlanner(defaultTableSpace, query);
        SQLPlannedOperationStatement sqlPlannedOperationStatement = new SQLPlannedOperationStatement(convertRelNode(plan.topNode, plan.originalRowType, returnValues).optimize());
        if (LOG.isLoggable(Level.FINE)) {
            LOG.log(Level.FINE, "Query: {0} --HerdDB Plan {1}", new Object[] { query, sqlPlannedOperationStatement.getRootOp() });
        }
        if (!scan) {
            ScanStatement scanStatement = sqlPlannedOperationStatement.unwrap(ScanStatement.class);
            if (scanStatement != null) {
                Table tableDef = scanStatement.getTableDef();
                CompiledSQLExpression where = scanStatement.getPredicate().unwrap(CompiledSQLExpression.class);
                SQLRecordKeyFunction keyFunction = findIndexAccess(where, tableDef.getPrimaryKey(), tableDef, "=", tableDef);
                if (keyFunction == null || !keyFunction.isFullPrimaryKey()) {
                    throw new StatementExecutionException("unsupported GET not on PK, bad where clause: " + query);
                }
                GetStatement get = new GetStatement(scanStatement.getTableSpace(), scanStatement.getTable(), keyFunction, scanStatement.getPredicate(), true);
                ExecutionPlan executionPlan = ExecutionPlan.simple(get);
                if (allowCache) {
                    cache.put(cacheKey, executionPlan);
                }
                return new TranslatedQuery(executionPlan, new SQLStatementEvaluationContext(query, parameters));
            }
        }
        if (maxRows > 0) {
            PlannerOp op = new LimitOp(sqlPlannedOperationStatement.getRootOp(), new ConstantExpression(maxRows), new ConstantExpression(0)).optimize();
            sqlPlannedOperationStatement = new SQLPlannedOperationStatement(op);
        }
        ExecutionPlan executionPlan = ExecutionPlan.simple(sqlPlannedOperationStatement);
        if (allowCache) {
            cache.put(cacheKey, executionPlan);
        }
        return new TranslatedQuery(executionPlan, new SQLStatementEvaluationContext(query, parameters));
    } catch (CalciteContextException ex) {
        LOG.log(Level.INFO, "Error while parsing '" + ex.getOriginalStatement() + "'", ex);
        // TODO can this be done better ?
        throw new StatementExecutionException(ex.getMessage());
    } catch (RelConversionException | ValidationException | SqlParseException ex) {
        LOG.log(Level.INFO, "Error while parsing '" + query + "'", ex);
        // TODO can this be done better ?
        throw new StatementExecutionException(ex.getMessage().replace("org.apache.calcite.runtime.CalciteContextException: ", ""));
    } catch (MetadataStorageManagerException ex) {
        LOG.log(Level.INFO, "Error while parsing '" + query + "'", ex);
        throw new StatementExecutionException(ex);
    }
}
Also used : PlannerOp(herddb.model.planner.PlannerOp) Table(herddb.model.Table) 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) ValidationException(org.apache.calcite.tools.ValidationException) SqlParseException(org.apache.calcite.sql.parser.SqlParseException) ConstantExpression(herddb.sql.expressions.ConstantExpression) CompiledSQLExpression(herddb.sql.expressions.CompiledSQLExpression) LimitOp(herddb.model.planner.LimitOp) ValuesOp(herddb.model.planner.ValuesOp) StatementExecutionException(herddb.model.StatementExecutionException) RelConversionException(org.apache.calcite.tools.RelConversionException) SQLPlannedOperationStatement(herddb.model.commands.SQLPlannedOperationStatement) MetadataStorageManagerException(herddb.metadata.MetadataStorageManagerException) CalciteContextException(org.apache.calcite.runtime.CalciteContextException) ExecutionPlan(herddb.model.ExecutionPlan) GetStatement(herddb.model.commands.GetStatement) ScanStatement(herddb.model.commands.ScanStatement)

Example 3 with ConstantExpression

use of herddb.sql.expressions.ConstantExpression in project herddb by diennea.

the class CalcitePlanner method planInsert.

private PlannerOp planInsert(EnumerableTableModify dml, boolean returnValues) {
    final String tableSpace = dml.getTable().getQualifiedName().get(0);
    final String tableName = dml.getTable().getQualifiedName().get(1);
    DMLStatement statement = null;
    if (dml.getInput() instanceof EnumerableProject) {
        // fastest path for insert into TABLE(s,b,c) values(?,?,?)
        EnumerableProject project = (EnumerableProject) dml.getInput();
        if (project.getInput() instanceof EnumerableValues) {
            EnumerableValues values = (EnumerableValues) project.getInput();
            if (values.getTuples().size() == 1) {
                final TableImpl tableImpl = (TableImpl) dml.getTable().unwrap(org.apache.calcite.schema.Table.class);
                Table table = tableImpl.tableManager.getTable();
                int index = 0;
                List<RexNode> projects = project.getProjects();
                List<CompiledSQLExpression> keyValueExpression = new ArrayList<>();
                List<String> keyExpressionToColumn = new ArrayList<>();
                List<CompiledSQLExpression> valuesExpressions = new ArrayList<>();
                List<String> valuesColumns = new ArrayList<>();
                boolean invalid = false;
                for (Column column : table.getColumns()) {
                    CompiledSQLExpression exp = SQLExpressionCompiler.compileExpression(projects.get(index));
                    if (exp instanceof ConstantExpression || exp instanceof JdbcParameterExpression || exp instanceof TypedJdbcParameterExpression) {
                        boolean isAlwaysNull = (exp instanceof ConstantExpression) && ((ConstantExpression) exp).isNull();
                        if (!isAlwaysNull) {
                            if (table.isPrimaryKeyColumn(column.name)) {
                                keyExpressionToColumn.add(column.name);
                                keyValueExpression.add(exp);
                            }
                            valuesColumns.add(column.name);
                            valuesExpressions.add(exp);
                        }
                        index++;
                    } else {
                        invalid = true;
                        break;
                    }
                }
                if (!invalid) {
                    RecordFunction keyfunction;
                    if (keyValueExpression.isEmpty() && table.auto_increment) {
                        keyfunction = new AutoIncrementPrimaryKeyRecordFunction();
                    } else {
                        if (keyValueExpression.size() != table.primaryKey.length) {
                            throw new StatementExecutionException("you must set a value for the primary key (expressions=" + keyValueExpression.size() + ")");
                        }
                        keyfunction = new SQLRecordKeyFunction(keyExpressionToColumn, keyValueExpression, table);
                    }
                    RecordFunction valuesfunction = new SQLRecordFunction(valuesColumns, table, valuesExpressions);
                    statement = new InsertStatement(tableSpace, tableName, keyfunction, valuesfunction).setReturnValues(returnValues);
                }
            }
        }
    }
    if (statement != null) {
        return new SimpleInsertOp(statement);
    }
    PlannerOp input = convertRelNode(dml.getInput(), null, false);
    try {
        return new InsertOp(tableSpace, tableName, input, returnValues);
    } catch (IllegalArgumentException err) {
        throw new StatementExecutionException(err);
    }
}
Also used : ConstantExpression(herddb.sql.expressions.ConstantExpression) ArrayList(java.util.ArrayList) CompiledSQLExpression(herddb.sql.expressions.CompiledSQLExpression) StatementExecutionException(herddb.model.StatementExecutionException) InsertStatement(herddb.model.commands.InsertStatement) SimpleInsertOp(herddb.model.planner.SimpleInsertOp) Column(herddb.model.Column) RecordFunction(herddb.model.RecordFunction) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction) Table(herddb.model.Table) 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) PlannerOp(herddb.model.planner.PlannerOp) JdbcParameterExpression(herddb.sql.expressions.JdbcParameterExpression) TypedJdbcParameterExpression(herddb.sql.expressions.TypedJdbcParameterExpression) EnumerableProject(org.apache.calcite.adapter.enumerable.EnumerableProject) TypedJdbcParameterExpression(herddb.sql.expressions.TypedJdbcParameterExpression) EnumerableValues(org.apache.calcite.adapter.enumerable.EnumerableValues) DMLStatement(herddb.model.DMLStatement) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction) RexNode(org.apache.calcite.rex.RexNode) SimpleInsertOp(herddb.model.planner.SimpleInsertOp) InsertOp(herddb.model.planner.InsertOp)

Aggregations

StatementExecutionException (herddb.model.StatementExecutionException)3 Table (herddb.model.Table)3 CompiledSQLExpression (herddb.sql.expressions.CompiledSQLExpression)3 ConstantExpression (herddb.sql.expressions.ConstantExpression)3 AutoIncrementPrimaryKeyRecordFunction (herddb.model.AutoIncrementPrimaryKeyRecordFunction)2 Column (herddb.model.Column)2 DMLStatement (herddb.model.DMLStatement)2 RecordFunction (herddb.model.RecordFunction)2 InsertStatement (herddb.model.commands.InsertStatement)2 PlannerOp (herddb.model.planner.PlannerOp)2 ArrayList (java.util.ArrayList)2 RelOptTable (org.apache.calcite.plan.RelOptTable)2 ModifiableTable (org.apache.calcite.schema.ModifiableTable)2 ProjectableFilterableTable (org.apache.calcite.schema.ProjectableFilterableTable)2 ScannableTable (org.apache.calcite.schema.ScannableTable)2 AbstractTable (org.apache.calcite.schema.impl.AbstractTable)2 MetadataStorageManagerException (herddb.metadata.MetadataStorageManagerException)1 DMLStatementExecutionResult (herddb.model.DMLStatementExecutionResult)1 DataScanner (herddb.model.DataScanner)1 DataScannerException (herddb.model.DataScannerException)1