use of herddb.model.Column 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.model.Column in project herddb by diennea.
the class SortOp method optimize.
@Override
public PlannerOp optimize() {
if (input instanceof BindableTableScanOp) {
BindableTableScanOp op = (BindableTableScanOp) input;
// we can change the statement, this node will be lost and the tablescan too
ScanStatement statement = op.getStatement();
statement.setComparator(this);
if (fields.length == 1 && directions[0]) {
Table tableDef = statement.getTableDef();
if (tableDef.getPrimaryKey().length == 1) {
if (statement.getProjection() != null && statement.getProjection() instanceof ZeroCopyProjection) {
ZeroCopyProjection zeroCopyProjection = (ZeroCopyProjection) statement.getProjection();
int index = zeroCopyProjection.mapPosition(fields[0]);
Column col = tableDef.resolveColumName(index);
if (col.name.equals(tableDef.getPrimaryKey()[0])) {
this.onlyPrimaryKeyAndAscending = true;
}
} else if (statement.getProjection() != null && statement.getProjection() instanceof IdentityProjection) {
Column col = tableDef.resolveColumName(fields[0]);
if (col.name.equals(tableDef.getPrimaryKey()[0])) {
this.onlyPrimaryKeyAndAscending = true;
}
}
}
}
return new SortedBindableTableScanOp(statement);
} else if (input instanceof TableScanOp) {
TableScanOp op = (TableScanOp) input;
// we can change the statement, this node will be lost and the tablescan too
ScanStatement statement = op.getStatement();
statement.setComparator(this);
if (fields.length == 1 && directions[0]) {
Table tableDef = statement.getTableDef();
if (tableDef.getPrimaryKey().length == 1) {
if (statement.getProjection() != null && statement.getProjection() instanceof ZeroCopyProjection) {
ZeroCopyProjection zeroCopyProjection = (ZeroCopyProjection) statement.getProjection();
int index = zeroCopyProjection.mapPosition(fields[0]);
Column col = tableDef.resolveColumName(index);
if (col.name.equals(tableDef.getPrimaryKey()[0])) {
this.onlyPrimaryKeyAndAscending = true;
}
} else if (statement.getProjection() != null && statement.getProjection() instanceof IdentityProjection) {
Column col = tableDef.resolveColumName(fields[0]);
if (col.name.equals(tableDef.getPrimaryKey()[0])) {
this.onlyPrimaryKeyAndAscending = true;
}
}
}
}
return new SortedTableScanOp(statement);
}
return this;
}
use of herddb.model.Column in project herddb by diennea.
the class SQLAggregator method createOutputColumns.
private static Column[] createOutputColumns(List<SelectItem> selectItems, DataScanner wrapped) throws StatementExecutionException {
Column[] columns = new Column[selectItems.size()];
int i = 0;
for (SelectItem item : selectItems) {
boolean done = false;
if (item instanceof SelectExpressionItem) {
SelectExpressionItem sei = (SelectExpressionItem) item;
Expression expression = sei.getExpression();
if (expression instanceof Function) {
Function f = (Function) expression;
String fieldName = f.toString();
if (sei.getAlias() != null && sei.getAlias().getName() != null) {
fieldName = sei.getAlias().getName();
}
if (fieldName == null) {
fieldName = "field" + i;
}
Column aggregated = BuiltinFunctions.toAggregatedOutputColumn(fieldName, f);
if (aggregated != null) {
columns[i] = aggregated;
done = true;
}
} else if (expression instanceof net.sf.jsqlparser.schema.Column) {
net.sf.jsqlparser.schema.Column c = (net.sf.jsqlparser.schema.Column) expression;
String name = c.getColumnName();
boolean found = false;
for (Column co : wrapped.getSchema()) {
if (co.name.equals(name)) {
columns[i] = co;
found = true;
break;
}
}
if (!found) {
throw new StatementExecutionException("cannot find column " + name + " is upstream scanner");
}
done = true;
} else {
throw new StatementExecutionException("unhandled aggregate query selectable item:" + expression);
}
}
i++;
if (!done) {
throw new StatementExecutionException("unhandled aggregate function " + item);
}
}
return columns;
}
use of herddb.model.Column in project herddb by diennea.
the class SQLPlanner method buildInsertStatement.
private ExecutionPlan buildInsertStatement(String defaultTableSpace, Insert s, boolean returnValues) throws StatementExecutionException {
String tableSpace = s.getTable().getSchemaName();
String tableName = s.getTable().getName();
if (tableSpace == null) {
tableSpace = defaultTableSpace;
}
TableSpaceManager tableSpaceManager = manager.getTableSpaceManager(tableSpace);
if (tableSpaceManager == null) {
throw new StatementExecutionException("no such tablespace " + tableSpace + " here at " + manager.getNodeId());
}
AbstractTableManager tableManager = tableSpaceManager.getTableManager(tableName);
if (tableManager == null) {
throw new StatementExecutionException("no such table " + tableName + " in tablespace " + tableSpace);
}
Table table = tableManager.getTable();
ItemsList itemlist = s.getItemsList();
if (itemlist instanceof ExpressionList) {
int index = 0;
List<Expression> keyValueExpression = new ArrayList<>();
List<String> keyExpressionToColumn = new ArrayList<>();
List<CompiledSQLExpression> valuesExpressions = new ArrayList<>();
List<net.sf.jsqlparser.schema.Column> valuesColumns = new ArrayList<>();
ExpressionList list = (ExpressionList) itemlist;
if (s.getColumns() != null) {
for (net.sf.jsqlparser.schema.Column c : s.getColumns()) {
Column column = table.getColumn(c.getColumnName());
if (column == null) {
throw new StatementExecutionException("no such column " + c.getColumnName() + " in table " + tableName + " in tablespace " + tableSpace);
}
Expression expression;
try {
expression = list.getExpressions().get(index++);
} catch (IndexOutOfBoundsException badQuery) {
throw new StatementExecutionException("bad number of VALUES in INSERT clause");
}
if (table.isPrimaryKeyColumn(column.name)) {
keyExpressionToColumn.add(column.name);
keyValueExpression.add(expression);
}
valuesColumns.add(c);
valuesExpressions.add(SQLExpressionCompiler.compileExpression(null, expression));
}
} else {
for (Column column : table.columns) {
Expression expression = list.getExpressions().get(index++);
if (table.isPrimaryKeyColumn(column.name)) {
keyExpressionToColumn.add(column.name);
keyValueExpression.add(expression);
}
valuesColumns.add(new net.sf.jsqlparser.schema.Column(column.name));
valuesExpressions.add(SQLExpressionCompiler.compileExpression(null, expression));
}
}
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(table, keyExpressionToColumn, keyValueExpression);
}
RecordFunction valuesfunction = new SQLRecordFunction(table, valuesColumns, valuesExpressions);
try {
return ExecutionPlan.simple(new InsertStatement(tableSpace, tableName, keyfunction, valuesfunction).setReturnValues(returnValues));
} catch (IllegalArgumentException err) {
throw new StatementExecutionException(err);
}
} else if (itemlist instanceof MultiExpressionList) {
if (returnValues) {
throw new StatementExecutionException("cannot 'return values' on multi-values insert");
}
MultiExpressionList multilist = (MultiExpressionList) itemlist;
List<InsertStatement> inserts = new ArrayList<>();
for (ExpressionList list : multilist.getExprList()) {
List<Expression> keyValueExpression = new ArrayList<>();
List<String> keyExpressionToColumn = new ArrayList<>();
List<CompiledSQLExpression> valuesExpressions = new ArrayList<>();
List<net.sf.jsqlparser.schema.Column> valuesColumns = new ArrayList<>();
int index = 0;
if (s.getColumns() != null) {
for (net.sf.jsqlparser.schema.Column c : s.getColumns()) {
Column column = table.getColumn(c.getColumnName());
if (column == null) {
throw new StatementExecutionException("no such column " + c.getColumnName() + " in table " + tableName + " in tablespace " + tableSpace);
}
Expression expression;
try {
expression = list.getExpressions().get(index++);
} catch (IndexOutOfBoundsException badQuery) {
throw new StatementExecutionException("bad number of VALUES in INSERT clause");
}
if (table.isPrimaryKeyColumn(column.name)) {
keyExpressionToColumn.add(column.name);
keyValueExpression.add(expression);
}
valuesColumns.add(c);
valuesExpressions.add(SQLExpressionCompiler.compileExpression(null, expression));
}
} else {
for (Column column : table.columns) {
Expression expression = list.getExpressions().get(index++);
if (table.isPrimaryKeyColumn(column.name)) {
keyExpressionToColumn.add(column.name);
keyValueExpression.add(expression);
}
valuesColumns.add(new net.sf.jsqlparser.schema.Column(column.name));
valuesExpressions.add(SQLExpressionCompiler.compileExpression(null, expression));
}
}
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(table, keyExpressionToColumn, keyValueExpression);
}
RecordFunction valuesfunction = new SQLRecordFunction(table, valuesColumns, valuesExpressions);
InsertStatement insert = new InsertStatement(tableSpace, tableName, keyfunction, valuesfunction);
inserts.add(insert);
}
try {
return ExecutionPlan.multiInsert(inserts);
} catch (IllegalArgumentException err) {
throw new StatementExecutionException(err);
}
} else {
List<Expression> keyValueExpression = new ArrayList<>();
List<String> keyExpressionToColumn = new ArrayList<>();
List<CompiledSQLExpression> valuesExpressions = new ArrayList<>();
List<net.sf.jsqlparser.schema.Column> valuesColumns = new ArrayList<>();
Select select = s.getSelect();
ExecutionPlan datasource = buildSelectStatement(defaultTableSpace, select, true, -1);
if (s.getColumns() == null) {
throw new StatementExecutionException("for INSERT ... SELECT you have to declare the columns to be filled in (use INSERT INTO TABLE(c,c,c,) SELECT .....)");
}
IntHolder holder = new IntHolder(1);
for (net.sf.jsqlparser.schema.Column c : s.getColumns()) {
Column column = table.getColumn(c.getColumnName());
if (column == null) {
throw new StatementExecutionException("no such column " + c.getColumnName() + " in table " + tableName + " in tablespace " + tableSpace);
}
JdbcParameter readFromResultSetAsJdbcParameter = new JdbcParameter();
readFromResultSetAsJdbcParameter.setIndex(holder.value++);
if (table.isPrimaryKeyColumn(column.name)) {
keyExpressionToColumn.add(column.name);
keyValueExpression.add(readFromResultSetAsJdbcParameter);
}
valuesColumns.add(c);
valuesExpressions.add(SQLExpressionCompiler.compileExpression(null, readFromResultSetAsJdbcParameter));
}
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(table, keyExpressionToColumn, keyValueExpression);
}
RecordFunction valuesfunction = new SQLRecordFunction(table, valuesColumns, valuesExpressions);
try {
return ExecutionPlan.dataManipulationFromSelect(new InsertStatement(tableSpace, tableName, keyfunction, valuesfunction).setReturnValues(returnValues), datasource);
} catch (IllegalArgumentException err) {
throw new StatementExecutionException(err);
}
}
}
use of herddb.model.Column in project herddb by diennea.
the class SQLPlanner method buildAlterStatement.
private Statement buildAlterStatement(String defaultTableSpace, Alter alter) throws StatementExecutionException {
if (alter.getTable() == null) {
throw new StatementExecutionException("missing table name");
}
String tableSpace = alter.getTable().getSchemaName();
if (tableSpace == null) {
tableSpace = defaultTableSpace;
}
List<Column> addColumns = new ArrayList<>();
List<Column> modifyColumns = new ArrayList<>();
List<String> dropColumns = new ArrayList<>();
String tableName = alter.getTable().getName();
if (alter.getAlterExpressions() == null || alter.getAlterExpressions().size() != 1) {
throw new StatementExecutionException("supported multi-alter operation '" + alter + "'");
}
AlterExpression alterExpression = alter.getAlterExpressions().get(0);
AlterOperation operation = alterExpression.getOperation();
Boolean changeAutoIncrement = null;
switch(operation) {
case ADD:
{
List<AlterExpression.ColumnDataType> cols = alterExpression.getColDataTypeList();
for (AlterExpression.ColumnDataType cl : cols) {
Column newColumn = Column.column(cl.getColumnName(), sqlDataTypeToColumnType(cl.getColDataType().getDataType(), cl.getColDataType().getArgumentsStringList()));
addColumns.add(newColumn);
}
}
break;
case DROP:
dropColumns.add(alterExpression.getColumnName());
break;
case MODIFY:
{
TableSpaceManager tableSpaceManager = manager.getTableSpaceManager(tableSpace);
if (tableSpaceManager == null) {
throw new StatementExecutionException("bad tablespace '" + tableSpace + "'");
}
AbstractTableManager tableManager = tableSpaceManager.getTableManager(tableName);
if (tableManager == null) {
throw new StatementExecutionException("bad table " + tableName + " in tablespace '" + tableSpace + "'");
}
Table table = tableManager.getTable();
List<AlterExpression.ColumnDataType> cols = alterExpression.getColDataTypeList();
for (AlterExpression.ColumnDataType cl : cols) {
String columnName = cl.getColumnName().toLowerCase();
Column oldColumn = table.getColumn(columnName);
if (oldColumn == null) {
throw new StatementExecutionException("bad column " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'");
}
Map<String, AbstractIndexManager> indexes = tableSpaceManager.getIndexesOnTable(tableName);
if (indexes != null) {
for (AbstractIndexManager am : indexes.values()) {
for (String indexedColumn : am.getColumnNames()) {
if (indexedColumn.equalsIgnoreCase(oldColumn.name)) {
throw new StatementExecutionException("cannot alter indexed " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'," + "index name is " + am.getIndexName());
}
}
}
}
int newType = sqlDataTypeToColumnType(cl.getColDataType().getDataType(), cl.getColDataType().getArgumentsStringList());
if (oldColumn.type != newType) {
throw new StatementExecutionException("cannot change datatype to " + cl.getColDataType().getDataType() + " for column " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'");
}
List<String> columnSpecs = decodeColumnSpecs(cl.getColumnSpecs());
if (table.isPrimaryKeyColumn(columnName)) {
boolean new_auto_increment = decodeAutoIncrement(columnSpecs);
if (new_auto_increment && table.primaryKey.length > 1) {
throw new StatementExecutionException("cannot add auto_increment flag to " + cl.getColDataType().getDataType() + " for column " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'");
}
if (table.auto_increment != new_auto_increment) {
changeAutoIncrement = new_auto_increment;
}
}
String renameTo = decodeRenameTo(columnSpecs);
if (renameTo != null) {
columnName = renameTo;
}
Column newColumnDef = Column.column(columnName, newType, oldColumn.serialPosition);
modifyColumns.add(newColumnDef);
}
}
break;
default:
throw new StatementExecutionException("supported alter operation '" + alter + "'");
}
return new AlterTableStatement(addColumns, modifyColumns, dropColumns, changeAutoIncrement, tableName, tableSpace, null);
}
Aggregations