use of herddb.utils.Bytes 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.utils.Bytes in project herddb by diennea.
the class LogEntry method deserialize.
public static LogEntry deserialize(ExtendedDataInputStream dis) throws EOFException {
try {
long timestamp = dis.readLong();
short type = dis.readShort();
long transactionId = dis.readLong();
// in 0.2 it was 'tablespace uuid'
dis.readUTF();
Bytes key = null;
Bytes value = null;
String tableName = null;
switch(type) {
case LogEntryType.UPDATE:
tableName = dis.readUTF();
key = dis.readBytes();
value = dis.readBytes();
break;
case LogEntryType.INSERT:
tableName = dis.readUTF();
key = dis.readBytes();
value = dis.readBytes();
break;
case LogEntryType.DELETE:
tableName = dis.readUTF();
key = dis.readBytes();
break;
case LogEntryType.DROP_TABLE:
case LogEntryType.TRUNCATE_TABLE:
tableName = dis.readUTF();
break;
case LogEntryType.DROP_INDEX:
value = dis.readBytes();
break;
case LogEntryType.CREATE_INDEX:
tableName = dis.readUTF();
value = dis.readBytes();
break;
case LogEntryType.CREATE_TABLE:
case LogEntryType.ALTER_TABLE:
// value contains the table definition
tableName = dis.readUTF();
value = dis.readBytes();
break;
case LogEntryType.BEGINTRANSACTION:
case LogEntryType.COMMITTRANSACTION:
case LogEntryType.ROLLBACKTRANSACTION:
break;
case LogEntryType.NOOP:
break;
case LogEntryType.TABLE_CONSISTENCY_CHECK:
tableName = dis.readUTF();
value = dis.readBytes();
break;
default:
throw new IllegalArgumentException("unsupported type " + type);
}
return new LogEntry(timestamp, type, transactionId, tableName, key, value);
} catch (EOFException e) {
/* Entry "corrupted" cause stream premature end, propagate */
throw e;
} catch (IOException err) {
/* Stream read error */
throw new RuntimeException(err);
}
}
use of herddb.utils.Bytes 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);
}
}
use of herddb.utils.Bytes in project herddb by diennea.
the class UpdateOp 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);
}
Bytes key = RecordSerializer.serializeIndexKey(row, table, table.getPrimaryKey());
DMLStatement updateStatement = new UpdateStatement(tableSpace, tableName, new ConstValueRecordFunction(key), this.recordFunction, null).setReturnValues(returnValues);
statements.add(updateStatement);
}
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.utils.Bytes in project herddb by diennea.
the class Transaction method deserialize.
public static Transaction deserialize(String tableSpace, ExtendedDataInputStream in) throws IOException {
// version
long version = in.readVLong();
// flags for future implementations
long flags = in.readVLong();
if (version != 1 || flags != 0) {
throw new IOException("corrupted transaction file");
}
long id = in.readZLong();
long ledgerId = in.readZLong();
long offset = in.readZLong();
LogSequenceNumber lastSequenceNumber = new LogSequenceNumber(ledgerId, offset);
Transaction t = new Transaction(id, tableSpace, new CommitLogResult(lastSequenceNumber, false, true));
int size = in.readVInt();
for (int i = 0; i < size; i++) {
String table = in.readUTF();
int numRecords = in.readVInt();
Map<Bytes, Record> records = new HashMap<>();
for (int k = 0; k < numRecords; k++) {
byte[] key = in.readArray();
byte[] value = in.readArray();
Bytes bKey = Bytes.from_array(key);
Record record = new Record(bKey, Bytes.from_array(value));
records.put(bKey, record);
}
t.changedRecords.put(table, records);
}
size = in.readVInt();
for (int i = 0; i < size; i++) {
String table = in.readUTF();
int numRecords = in.readVInt();
Map<Bytes, Record> records = new HashMap<>();
for (int k = 0; k < numRecords; k++) {
byte[] key = in.readArray();
byte[] value = in.readArray();
Bytes bKey = Bytes.from_array(key);
Record record = new Record(bKey, Bytes.from_array(value));
records.put(bKey, record);
}
t.newRecords.put(table, records);
}
size = in.readVInt();
for (int i = 0; i < size; i++) {
String table = in.readUTF();
int numRecords = in.readVInt();
Set<Bytes> records = new HashSet<>();
for (int k = 0; k < numRecords; k++) {
byte[] key = in.readArray();
records.add(Bytes.from_array(key));
}
t.deletedRecords.put(table, records);
}
size = in.readVInt();
if (size > 0) {
t.newTables = new HashMap<>();
for (int i = 0; i < size; i++) {
byte[] data = in.readArray();
Table table = Table.deserialize(data);
t.newTables.put(table.name, table);
}
}
size = in.readVInt();
if (size > 0) {
t.droppedTables = new HashSet<>();
for (int i = 0; i < size; i++) {
t.droppedTables.add(in.readUTF());
}
}
size = in.readVInt();
if (size > 0) {
t.newIndexes = new HashMap<>();
for (int i = 0; i < size; i++) {
byte[] data = in.readArray();
Index index = Index.deserialize(data);
t.newIndexes.put(index.name, index);
}
}
size = in.readVInt();
if (size > 0) {
t.droppedIndexes = new HashSet<>();
for (int i = 0; i < size; i++) {
t.droppedIndexes.add(in.readUTF());
}
}
return t;
}
Aggregations