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);
}
}
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);
}
}
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);
}
}
Aggregations