use of herddb.sql.expressions.CompiledSQLExpression in project herddb by diennea.
the class JSQLParserPlanner method planerInsertOrUpsert.
private ExecutionPlan planerInsertOrUpsert(String defaultTableSpace, net.sf.jsqlparser.schema.Table table, List<net.sf.jsqlparser.schema.Column> columns, ItemsList itemsList, boolean returnValues, boolean upsert) throws StatementExecutionException, StatementNotSupportedException {
OpSchema inputSchema = getTableSchema(defaultTableSpace, table);
TableSpaceManager tableSpaceManager = manager.getTableSpaceManager(inputSchema.tableSpace);
AbstractTableManager tableManager = tableSpaceManager.getTableManager(inputSchema.name);
Table tableImpl = tableManager.getTable();
List<CompiledSQLExpression> keyValueExpression = new ArrayList<>();
List<String> keyExpressionToColumn = new ArrayList<>();
List<CompiledSQLExpression> valuesExpressions = new ArrayList<>();
List<String> valuesColumns = new ArrayList<>();
boolean invalid = false;
int index = 0;
if (columns == null) {
// INSERT INTO TABLE VALUES (xxxx) (no column list)
columns = new ArrayList<>();
for (Column c : tableImpl.getColumns()) {
columns.add(new net.sf.jsqlparser.schema.Column(c.name));
}
}
if (itemsList instanceof ExpressionList) {
List<Expression> values = ((ExpressionList) itemsList).getExpressions();
for (net.sf.jsqlparser.schema.Column column : columns) {
CompiledSQLExpression exp = SQLParserExpressionCompiler.compileExpression(values.get(index), inputSchema);
String columnName = fixMySqlBackTicks(column.getColumnName()).toLowerCase();
if (exp instanceof ConstantExpression || exp instanceof JdbcParameterExpression || exp instanceof TypedJdbcParameterExpression || exp instanceof CompiledFunction) {
boolean isAlwaysNull = (exp instanceof ConstantExpression) && ((ConstantExpression) exp).isNull();
if (!isAlwaysNull) {
if (tableImpl.isPrimaryKeyColumn(columnName)) {
keyExpressionToColumn.add(columnName);
keyValueExpression.add(exp);
}
Column columnFromSchema = tableImpl.getColumn(columnName);
if (columnFromSchema == null) {
throw new StatementExecutionException("Column '" + columnName + "' not found in table " + tableImpl.name);
}
valuesColumns.add(columnFromSchema.name);
valuesExpressions.add(exp);
}
index++;
} else {
checkSupported(false, "Unsupported expression type " + exp.getClass().getName());
break;
}
}
// handle default values
for (Column col : tableImpl.getColumns()) {
if (!valuesColumns.contains(col.name)) {
if (col.defaultValue != null) {
valuesColumns.add(col.name);
CompiledSQLExpression defaultValueExpression = makeDefaultValue(col);
valuesExpressions.add(defaultValueExpression);
} else if (ColumnTypes.isNotNullDataType(col.type) && !tableImpl.auto_increment) {
throw new StatementExecutionException("Column '" + col.name + "' has no default value and does not allow NULLs");
}
}
}
DMLStatement statement;
if (!invalid) {
RecordFunction keyfunction;
if (keyValueExpression.isEmpty() && tableImpl.auto_increment) {
keyfunction = new AutoIncrementPrimaryKeyRecordFunction();
} else {
if (keyValueExpression.size() != tableImpl.primaryKey.length) {
throw new StatementExecutionException("you must set a value for the primary key (expressions=" + keyValueExpression.size() + ")");
}
keyfunction = new SQLRecordKeyFunction(keyExpressionToColumn, keyValueExpression, tableImpl);
}
RecordFunction valuesfunction = new SQLRecordFunction(valuesColumns, tableImpl, valuesExpressions);
statement = new InsertStatement(inputSchema.tableSpace, inputSchema.name, keyfunction, valuesfunction, upsert).setReturnValues(returnValues);
} else {
throw new StatementNotSupportedException();
}
PlannerOp op = new SimpleInsertOp(statement.setReturnValues(returnValues));
return optimizePlan(op);
} else if (itemsList instanceof MultiExpressionList) {
List<ExpressionList> records = ((MultiExpressionList) itemsList).getExprList();
ValuesOp values = planValuesForInsertOp(columns, tableImpl, inputSchema, records);
InsertOp op = new InsertOp(tableImpl.tablespace, tableImpl.name, values, returnValues, upsert);
return optimizePlan(op);
} else {
checkSupported(false);
return null;
}
}
use of herddb.sql.expressions.CompiledSQLExpression in project herddb by diennea.
the class SQLRecordKeyFunction method computeNewValue.
@Override
@SuppressFBWarnings("BC_UNCONFIRMED_CAST")
public byte[] computeNewValue(Record previous, StatementEvaluationContext context, TableContext tableContext) throws StatementExecutionException {
SQLStatementEvaluationContext statementEvaluationContext = (SQLStatementEvaluationContext) context;
if (isConstant) {
byte[] cachedResult = statementEvaluationContext.getConstant(this);
if (cachedResult != null) {
return cachedResult;
}
}
final DataAccessor prevRecord = previous == null ? DataAccessor.NULL : previous.getDataAccessor(tableContext.getTable());
Map<String, Object> pk = new HashMap<>();
for (int i = 0; i < columns.length; i++) {
herddb.model.Column c = columns[i];
CompiledSQLExpression expression = expressions.get(i);
Object value = expression.evaluate(prevRecord, context);
if (value == null) {
throw new InvalidNullValueForKeyException("error while converting primary key " + pk + ", keys cannot be null");
}
try {
value = RecordSerializer.convert(c.type, value);
} catch (StatementExecutionException err) {
throw new StatementExecutionException("error on column " + c.name + " (" + ColumnTypes.typeToString(c.type) + "):" + err.getMessage(), err);
}
pk.put(c.name, value);
}
try {
// maybe this is only a partial primary key
byte[] result = RecordSerializer.serializePrimaryKeyRaw(pk, table, pkColumnNames);
if (isConstant) {
statementEvaluationContext.cacheConstant(this, result);
}
return result;
} catch (Exception err) {
throw new StatementExecutionException("error while converting primary key " + pk + ": " + err, err);
}
}
use of herddb.sql.expressions.CompiledSQLExpression in project herddb by diennea.
the class IndexUtils method discoverIndexOperations.
static void discoverIndexOperations(final String tableSpace, CompiledSQLExpression where, Table table, SQLRecordPredicate predicate, Object debug, TableSpaceManager tableSpaceManager) throws StatementExecutionException {
IndexOperation op = scanForIndexAccess(where, table, tableSpaceManager);
predicate.setIndexOperation(op);
CompiledSQLExpression filterPk = findFiltersOnPrimaryKey(table, where);
if (filterPk != null) {
filterPk = remapPositionalAccessToToPrimaryKeyAccessor(filterPk, table, debug);
}
predicate.setPrimaryKeyFilter(filterPk);
}
use of herddb.sql.expressions.CompiledSQLExpression in project herddb by diennea.
the class SQLRecordPredicateTest method testEvaluateExpression.
@Test
public void testEvaluateExpression() throws Exception {
try (DBManager manager = new DBManager("localhost", new MemoryMetadataStorageManager(), new MemoryDataStorageManager(), new MemoryCommitLogManager(), null, null)) {
manager.start();
assertTrue(manager.waitForTablespace(TableSpace.DEFAULT, 10000));
Table table = Table.builder().name("t1").column("pk", ColumnTypes.STRING).column("name", ColumnTypes.STRING).primaryKey("pk").build();
CreateTableStatement st2 = new CreateTableStatement(table);
manager.executeStatement(st2, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
{
TranslatedQuery translated = manager.getPlanner().translate(TableSpace.DEFAULT, "SELECT * " + "FROM t1 " + "where pk >= ?", Collections.emptyList(), true, true, false, -1);
ScanStatement scan = translated.plan.mainStatement.unwrap(ScanStatement.class);
assertTrue(scan.getPredicate() instanceof SQLRecordPredicate);
SQLRecordPredicate pred = (SQLRecordPredicate) scan.getPredicate();
assertTrue(pred.getPrimaryKeyFilter() != null && (pred.getPrimaryKeyFilter() instanceof CompiledSQLExpression));
assertTrue(pred.getWhere() != null && (pred.getWhere() instanceof CompiledSQLExpression));
StatementEvaluationContext ctx = new SQLStatementEvaluationContext("the-query", Arrays.asList("my-string"), false, false);
Record record = RecordSerializer.makeRecord(table, "pk", "test", "name", "myname");
assertEquals(Boolean.TRUE, pred.evaluate(record, ctx));
long start = System.currentTimeMillis();
int size = 20_000_000;
for (int i = 0; i < size; i++) {
pred.evaluate(record, ctx);
}
long end = System.currentTimeMillis();
double speed = (int) (size * 1000d / (end - start));
System.out.println("speed: " + speed + " eval/s" + " per " + size + " records");
}
}
}
Aggregations