use of herddb.model.StatementExecutionResult in project herddb by diennea.
the class TableSpaceManager method executeStatementAsyncInternal.
private CompletableFuture<StatementExecutionResult> executeStatementAsyncInternal(Statement statement, StatementEvaluationContext context, TransactionContext transactionContext, boolean rollbackOnError) throws StatementExecutionException {
Transaction transaction = transactions.get(transactionContext.transactionId);
if (transaction != null && !transaction.tableSpace.equals(tableSpaceName)) {
return Futures.exception(new StatementExecutionException("transaction " + transaction.transactionId + " is for tablespace " + transaction.tableSpace + ", not for " + tableSpaceName));
}
if (transactionContext.transactionId > 0 && transaction == null) {
return Futures.exception(new StatementExecutionException("transaction " + transactionContext.transactionId + " not found on tablespace " + tableSpaceName));
}
boolean isTransactionCommand = statement instanceof CommitTransactionStatement || statement instanceof RollbackTransactionStatement || // AlterTable implictly commits the transaction
statement instanceof AlterTableStatement;
if (transaction != null) {
transaction.touch();
if (!isTransactionCommand) {
transaction.increaseRefcount();
}
}
CompletableFuture<StatementExecutionResult> res;
try {
if (statement instanceof TableAwareStatement) {
res = executeTableAwareStatement(statement, transaction, context);
} else if (statement instanceof SQLPlannedOperationStatement) {
res = executePlannedOperationStatement(statement, transactionContext, context);
} else if (statement instanceof BeginTransactionStatement) {
if (transaction != null) {
res = Futures.exception(new StatementExecutionException("transaction already started"));
} else {
res = beginTransactionAsync(context, true);
}
} else if (statement instanceof CommitTransactionStatement) {
res = commitTransaction((CommitTransactionStatement) statement, context);
} else if (statement instanceof RollbackTransactionStatement) {
res = rollbackTransaction((RollbackTransactionStatement) statement, context);
} else if (statement instanceof CreateTableStatement) {
res = CompletableFuture.completedFuture(createTable((CreateTableStatement) statement, transaction, context));
} else if (statement instanceof CreateIndexStatement) {
res = CompletableFuture.completedFuture(createIndex((CreateIndexStatement) statement, transaction, context));
} else if (statement instanceof DropTableStatement) {
res = CompletableFuture.completedFuture(dropTable((DropTableStatement) statement, transaction, context));
} else if (statement instanceof DropIndexStatement) {
res = CompletableFuture.completedFuture(dropIndex((DropIndexStatement) statement, transaction, context));
} else if (statement instanceof AlterTableStatement) {
res = CompletableFuture.completedFuture(alterTable((AlterTableStatement) statement, transactionContext, context));
} else {
res = Futures.exception(new StatementExecutionException("unsupported statement " + statement).fillInStackTrace());
}
} catch (StatementExecutionException error) {
res = Futures.exception(error);
}
if (transaction != null && !isTransactionCommand) {
res = res.whenComplete((a, b) -> {
transaction.decreaseRefCount();
});
}
if (rollbackOnError) {
long txId = transactionContext.transactionId;
if (txId > 0) {
res = res.whenComplete((xx, error) -> {
if (error != null) {
LOGGER.log(Level.FINE, tableSpaceName + " force rollback of implicit transaction " + txId, error);
try {
rollbackTransaction(new RollbackTransactionStatement(tableSpaceName, txId), context).get();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
error.addSuppressed(ex);
} catch (ExecutionException ex) {
error.addSuppressed(ex.getCause());
}
throw new HerdDBInternalException(error);
}
});
}
}
return res;
}
use of herddb.model.StatementExecutionResult in project herddb by diennea.
the class DeleteOp method executeAsync.
@Override
public CompletableFuture<StatementExecutionResult> executeAsync(TableSpaceManager tableSpaceManager, TransactionContext transactionContext, StatementEvaluationContext context, boolean lockRequired, boolean forWrite) {
// not supported for deletes
final boolean returnValues = false;
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;
List<DMLStatement> statements = new ArrayList<>();
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);
}
Bytes key = RecordSerializer.serializeIndexKey(row, table, table.getPrimaryKey());
DMLStatement deleteStatement = new DeleteStatement(tableSpace, tableName, null, new RawKeyEquals(key));
statements.add(deleteStatement);
}
if (statements.isEmpty()) {
return CompletableFuture.completedFuture(new DMLStatementExecutionResult(transactionId, 0, null, null));
}
if (statements.size() == 1) {
return tableSpaceManager.executeStatementAsync(statements.get(0), context, transactionContext);
}
CompletableFuture<StatementExecutionResult> finalResult = new CompletableFuture<>();
AtomicInteger updateCounts = new AtomicInteger();
AtomicReference<Bytes> lastKey = new AtomicReference<>();
AtomicReference<Bytes> lastNewValue = new AtomicReference<>();
class ComputeNext implements BiConsumer<StatementExecutionResult, Throwable> {
int current;
public ComputeNext(int current) {
this.current = current;
}
@Override
public void accept(StatementExecutionResult res, Throwable error) {
if (error != null) {
finalResult.completeExceptionally(error);
return;
}
DMLStatementExecutionResult dml = (DMLStatementExecutionResult) res;
updateCounts.addAndGet(dml.getUpdateCount());
if (returnValues) {
lastKey.set(dml.getKey());
lastNewValue.set(dml.getNewvalue());
}
long newTransactionId = res.transactionId;
if (current == statements.size()) {
DMLStatementExecutionResult finalDMLResult = new DMLStatementExecutionResult(newTransactionId, updateCounts.get(), lastKey.get(), lastNewValue.get());
finalResult.complete(finalDMLResult);
return;
}
DMLStatement nextStatement = statements.get(current);
TransactionContext transactionContext = new TransactionContext(newTransactionId);
CompletableFuture<StatementExecutionResult> nextPromise = tableSpaceManager.executeStatementAsync(nextStatement, context, transactionContext);
nextPromise.whenComplete(new ComputeNext(current + 1));
}
}
DMLStatement firstStatement = statements.get(0);
tableSpaceManager.executeStatementAsync(firstStatement, context, transactionContext).whenComplete(new ComputeNext(1));
return finalResult;
} catch (DataScannerException err) {
throw new StatementExecutionException(err);
}
}
use of herddb.model.StatementExecutionResult in project herddb by diennea.
the class InsertOp method executeAsync.
@Override
public CompletableFuture<StatementExecutionResult> executeAsync(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;
List<DMLStatement> statements = new ArrayList<>();
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, column.type);
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, upsert).setReturnValues(returnValues);
statements.add(insertStatement);
}
if (statements.isEmpty()) {
return CompletableFuture.completedFuture(new DMLStatementExecutionResult(transactionId, 0, null, null));
}
if (statements.size() == 1) {
return tableSpaceManager.executeStatementAsync(statements.get(0), context, transactionContext);
}
if (returnValues) {
return Futures.exception(new StatementExecutionException("cannot 'return values' on multi-values insert"));
}
CompletableFuture<StatementExecutionResult> finalResult = new CompletableFuture<>();
AtomicInteger updateCounts = new AtomicInteger();
AtomicReference<Bytes> lastKey = new AtomicReference<>();
AtomicReference<Bytes> lastNewValue = new AtomicReference<>();
class ComputeNext implements BiConsumer<StatementExecutionResult, Throwable> {
int current;
public ComputeNext(int current) {
this.current = current;
}
@Override
public void accept(StatementExecutionResult res, Throwable error) {
if (error != null) {
finalResult.completeExceptionally(error);
return;
}
DMLStatementExecutionResult dml = (DMLStatementExecutionResult) res;
updateCounts.addAndGet(dml.getUpdateCount());
if (returnValues) {
lastKey.set(dml.getKey());
lastNewValue.set(dml.getNewvalue());
}
long newTransactionId = res.transactionId;
if (current == statements.size()) {
DMLStatementExecutionResult finalDMLResult = new DMLStatementExecutionResult(newTransactionId, updateCounts.get(), lastKey.get(), lastNewValue.get());
finalResult.complete(finalDMLResult);
return;
}
DMLStatement nextStatement = statements.get(current);
TransactionContext transactionContext = new TransactionContext(newTransactionId);
CompletableFuture<StatementExecutionResult> nextPromise = tableSpaceManager.executeStatementAsync(nextStatement, context, transactionContext);
nextPromise.whenComplete(new ComputeNext(current + 1));
}
}
DMLStatement firstStatement = statements.get(0);
tableSpaceManager.executeStatementAsync(firstStatement, context, transactionContext).whenComplete(new ComputeNext(1));
return finalResult;
} catch (DataScannerException err) {
throw new StatementExecutionException(err);
}
}
use of herddb.model.StatementExecutionResult in project herddb by diennea.
the class ProjectOp method execute.
@Override
public StatementExecutionResult execute(TableSpaceManager tableSpaceManager, TransactionContext transactionContext, StatementEvaluationContext context, boolean lockRequired, boolean forWrite) throws StatementExecutionException {
// TODO merge projection + scan + sort + limit
StatementExecutionResult input = this.input.execute(tableSpaceManager, transactionContext, context, lockRequired, forWrite);
ScanResult downstream = (ScanResult) input;
DataScanner dataScanner = downstream.dataScanner;
DataScanner projected = new ProjectedDataScanner(dataScanner, projection.getFieldNames(), projection.getColumns(), context);
return new ScanResult(downstream.transactionId, projected);
}
use of herddb.model.StatementExecutionResult in project herddb by diennea.
the class ReplaceOp method executeAsync.
@Override
public CompletableFuture<StatementExecutionResult> executeAsync(TableSpaceManager tableSpaceManager, TransactionContext transactionContext, StatementEvaluationContext context, boolean lockRequired, boolean forWrite) {
StatementExecutionResult input = this.input.execute(tableSpaceManager, transactionContext, context, true, true);
ScanResult downstreamScanResult = (ScanResult) input;
TableManager tableManager = (TableManager) tableSpaceManager.getTableManager(tableName);
final Table table = tableManager.getTable();
TableContext tableContext = tableManager.buildTableContext();
long transactionId = transactionContext.transactionId;
List<DMLStatement> statements = new ArrayList<>();
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);
}
Bytes oldKey = RecordSerializer.serializeIndexKey(row, table, table.getPrimaryKey());
byte[] oldValue = RecordSerializer.serializeValueRaw(row.toMap(), table, -1);
DMLStatement deleteStatement = new DeleteStatement(tableSpace, tableName, oldKey, null);
statements.add(deleteStatement);
Record oldRecord = new Record(oldKey, Bytes.from_array(oldValue));
byte[] newKey = this.keyFunction.computeNewValue(oldRecord, context, tableContext);
byte[] newValue = this.recordFunction.computeNewValue(oldRecord, context, tableContext);
DMLStatement insertStatement = new InsertStatement(tableSpace, tableName, new Record(Bytes.from_array(newKey), Bytes.from_array(newValue))).setReturnValues(returnValues);
statements.add(insertStatement);
}
if (statements.isEmpty()) {
return CompletableFuture.completedFuture(new DMLStatementExecutionResult(transactionId, 0, null, null));
}
if (statements.size() == 1) {
return tableSpaceManager.executeStatementAsync(statements.get(0), context, transactionContext);
}
CompletableFuture<StatementExecutionResult> finalResult = new CompletableFuture<>();
AtomicInteger updateCounts = new AtomicInteger();
AtomicReference<Bytes> lastKey = new AtomicReference<>();
AtomicReference<Bytes> lastNewValue = new AtomicReference<>();
class ComputeNext implements BiConsumer<StatementExecutionResult, Throwable> {
int current;
public ComputeNext(int current) {
this.current = current;
}
@Override
public void accept(StatementExecutionResult res, Throwable error) {
if (error != null) {
finalResult.completeExceptionally(error);
return;
}
DMLStatementExecutionResult dml = (DMLStatementExecutionResult) res;
updateCounts.addAndGet(dml.getUpdateCount());
if (returnValues) {
lastKey.set(dml.getKey());
lastNewValue.set(dml.getNewvalue());
}
long newTransactionId = res.transactionId;
if (current == statements.size()) {
DMLStatementExecutionResult finalDMLResult = new DMLStatementExecutionResult(newTransactionId, updateCounts.get(), lastKey.get(), lastNewValue.get());
finalResult.complete(finalDMLResult);
return;
}
DMLStatement nextStatement = statements.get(current);
TransactionContext transactionContext = new TransactionContext(newTransactionId);
CompletableFuture<StatementExecutionResult> nextPromise = tableSpaceManager.executeStatementAsync(nextStatement, context, transactionContext);
nextPromise.whenComplete(new ComputeNext(current + 1));
}
}
DMLStatement firstStatement = statements.get(0);
tableSpaceManager.executeStatementAsync(firstStatement, context, transactionContext).whenComplete(new ComputeNext(1));
return finalResult;
} catch (DataScannerException err) {
throw new StatementExecutionException(err);
}
}
Aggregations