Search in sources :

Example 1 with AutoIncrementPrimaryKeyRecordFunction

use of herddb.model.AutoIncrementPrimaryKeyRecordFunction 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);
    }
}
Also used : DataAccessor(herddb.utils.DataAccessor) ConstantExpression(herddb.sql.expressions.ConstantExpression) ArrayList(java.util.ArrayList) CompiledSQLExpression(herddb.sql.expressions.CompiledSQLExpression) StatementExecutionException(herddb.model.StatementExecutionException) InsertStatement(herddb.model.commands.InsertStatement) Bytes(herddb.utils.Bytes) DataScanner(herddb.model.DataScanner) Column(herddb.model.Column) DMLStatementExecutionResult(herddb.model.DMLStatementExecutionResult) StatementExecutionResult(herddb.model.StatementExecutionResult) SQLRecordFunction(herddb.sql.SQLRecordFunction) SQLRecordFunction(herddb.sql.SQLRecordFunction) RecordFunction(herddb.model.RecordFunction) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction) SQLRecordKeyFunction(herddb.sql.SQLRecordKeyFunction) DataScannerException(herddb.model.DataScannerException) ScanResult(herddb.model.ScanResult) Table(herddb.model.Table) DMLStatementExecutionResult(herddb.model.DMLStatementExecutionResult) TransactionContext(herddb.model.TransactionContext) DMLStatement(herddb.model.DMLStatement) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction)

Example 2 with AutoIncrementPrimaryKeyRecordFunction

use of herddb.model.AutoIncrementPrimaryKeyRecordFunction 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);
        }
    }
}
Also used : ItemsList(net.sf.jsqlparser.expression.operators.relational.ItemsList) ArrayList(java.util.ArrayList) CompiledSQLExpression(herddb.sql.expressions.CompiledSQLExpression) StatementExecutionException(herddb.model.StatementExecutionException) InsertStatement(herddb.model.commands.InsertStatement) ExecutionPlan(herddb.model.ExecutionPlan) Column(herddb.model.Column) TableSpaceManager(herddb.core.TableSpaceManager) MultiExpressionList(net.sf.jsqlparser.expression.operators.relational.MultiExpressionList) IntHolder(herddb.utils.IntHolder) ItemsList(net.sf.jsqlparser.expression.operators.relational.ItemsList) ArrayList(java.util.ArrayList) ExpressionList(net.sf.jsqlparser.expression.operators.relational.ExpressionList) ColumnsList(herddb.model.ColumnsList) MultiExpressionList(net.sf.jsqlparser.expression.operators.relational.MultiExpressionList) List(java.util.List) RecordFunction(herddb.model.RecordFunction) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction) ExpressionList(net.sf.jsqlparser.expression.operators.relational.ExpressionList) MultiExpressionList(net.sf.jsqlparser.expression.operators.relational.MultiExpressionList) Table(herddb.model.Table) CreateTable(net.sf.jsqlparser.statement.create.table.CreateTable) JdbcParameter(net.sf.jsqlparser.expression.JdbcParameter) AbstractTableManager(herddb.core.AbstractTableManager) Expression(net.sf.jsqlparser.expression.Expression) AlterExpression(net.sf.jsqlparser.statement.alter.AlterExpression) BinaryExpression(net.sf.jsqlparser.expression.BinaryExpression) AndExpression(net.sf.jsqlparser.expression.operators.conditional.AndExpression) SignedExpression(net.sf.jsqlparser.expression.SignedExpression) CompiledSQLExpression(herddb.sql.expressions.CompiledSQLExpression) PlainSelect(net.sf.jsqlparser.statement.select.PlainSelect) Select(net.sf.jsqlparser.statement.select.Select) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction)

Example 3 with AutoIncrementPrimaryKeyRecordFunction

use of herddb.model.AutoIncrementPrimaryKeyRecordFunction in project herddb by diennea.

the class SimpleRecoveryTest method autoIncrementAfterRestart_from_snapshot.

@Test
public void autoIncrementAfterRestart_from_snapshot() throws Exception {
    Path dataPath = folder.newFolder("data").toPath();
    Path logsPath = folder.newFolder("logs").toPath();
    Path metadataPath = folder.newFolder("metadata").toPath();
    Path tmoDir = folder.newFolder("tmoDir").toPath();
    String nodeId = "localhost";
    try (DBManager manager = new DBManager("localhost", new FileMetadataStorageManager(metadataPath), new FileDataStorageManager(dataPath), new FileCommitLogManager(logsPath), tmoDir, null)) {
        manager.start();
        CreateTableSpaceStatement st1 = new CreateTableSpaceStatement("tblspace1", Collections.singleton(nodeId), nodeId, 1, 0, 0);
        manager.executeStatement(st1, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        manager.waitForTablespace("tblspace1", 10000);
        Table table = Table.builder().tablespace("tblspace1").name("t1").column("id", ColumnTypes.INTEGER).primaryKey("id", true).build();
        CreateTableStatement st2 = new CreateTableStatement(table);
        manager.executeStatement(st2, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        manager.checkpoint();
        InsertStatement insert = new InsertStatement("tblspace1", "t1", new AutoIncrementPrimaryKeyRecordFunction(), new ConstValueRecordFunction(new byte[0]), false);
        DMLStatementExecutionResult insertResult = manager.executeUpdate(insert, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        assertEquals(1, insertResult.getUpdateCount());
        int newValue = insertResult.getKey().to_int();
        assertEquals(1, newValue);
        GetResult get = manager.get(new GetStatement("tblspace1", "t1", insertResult.getKey(), null, false), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        assertTrue(get.found());
        long next_value = manager.getTableSpaceManager("tblspace1").getTableManager("t1").getNextPrimaryKeyValue();
        assertEquals(2, next_value);
        manager.checkpoint();
    }
    try (DBManager manager = new DBManager("localhost", new FileMetadataStorageManager(metadataPath), new FileDataStorageManager(dataPath), new FileCommitLogManager(logsPath), tmoDir, null)) {
        manager.start();
        manager.waitForTablespace("tblspace1", 10000);
        InsertStatement insert = new InsertStatement("tblspace1", "t1", new AutoIncrementPrimaryKeyRecordFunction(), new ConstValueRecordFunction(new byte[0]), false);
        DMLStatementExecutionResult insertResult = manager.executeUpdate(insert, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        assertEquals(1, insertResult.getUpdateCount());
        int newValue = insertResult.getKey().to_int();
        assertEquals(2, newValue);
        GetResult get = manager.get(new GetStatement("tblspace1", "t1", insertResult.getKey(), null, false), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        assertTrue(get.found());
        long next_value = manager.getTableSpaceManager("tblspace1").getTableManager("t1").getNextPrimaryKeyValue();
        assertEquals(3, next_value);
    }
}
Also used : Path(java.nio.file.Path) Table(herddb.model.Table) GetResult(herddb.model.GetResult) FileMetadataStorageManager(herddb.file.FileMetadataStorageManager) CreateTableStatement(herddb.model.commands.CreateTableStatement) InsertStatement(herddb.model.commands.InsertStatement) FileCommitLogManager(herddb.file.FileCommitLogManager) CreateTableSpaceStatement(herddb.model.commands.CreateTableSpaceStatement) ConstValueRecordFunction(herddb.model.ConstValueRecordFunction) DMLStatementExecutionResult(herddb.model.DMLStatementExecutionResult) GetStatement(herddb.model.commands.GetStatement) FileDataStorageManager(herddb.file.FileDataStorageManager) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction) Test(org.junit.Test)

Example 4 with AutoIncrementPrimaryKeyRecordFunction

use of herddb.model.AutoIncrementPrimaryKeyRecordFunction in project herddb by diennea.

the class SimpleRecoveryTest method autoIncrementAfterRestart_from_log.

@Test
public void autoIncrementAfterRestart_from_log() throws Exception {
    Path dataPath = folder.newFolder("data").toPath();
    Path logsPath = folder.newFolder("logs").toPath();
    Path metadataPath = folder.newFolder("metadata").toPath();
    Path tmoDir = folder.newFolder("tmoDir").toPath();
    String nodeId = "localhost";
    try (DBManager manager = new DBManager("localhost", new FileMetadataStorageManager(metadataPath), new FileDataStorageManager(dataPath), new FileCommitLogManager(logsPath), tmoDir, null)) {
        manager.start();
        CreateTableSpaceStatement st1 = new CreateTableSpaceStatement("tblspace1", Collections.singleton(nodeId), nodeId, 1, 0, 0);
        manager.executeStatement(st1, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        manager.waitForTablespace("tblspace1", 10000);
        Table table = Table.builder().tablespace("tblspace1").name("t1").column("id", ColumnTypes.INTEGER).primaryKey("id", true).build();
        CreateTableStatement st2 = new CreateTableStatement(table);
        manager.executeStatement(st2, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        manager.checkpoint();
        InsertStatement insert = new InsertStatement("tblspace1", "t1", new AutoIncrementPrimaryKeyRecordFunction(), new ConstValueRecordFunction(new byte[0]), false);
        DMLStatementExecutionResult insertResult = manager.executeUpdate(insert, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        assertEquals(1, insertResult.getUpdateCount());
        int newValue = insertResult.getKey().to_int();
        assertEquals(1, newValue);
        GetResult get = manager.get(new GetStatement("tblspace1", "t1", insertResult.getKey(), null, false), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        assertTrue(get.found());
        long next_value = manager.getTableSpaceManager("tblspace1").getTableManager("t1").getNextPrimaryKeyValue();
        assertEquals(2, next_value);
    }
    try (DBManager manager = new DBManager("localhost", new FileMetadataStorageManager(metadataPath), new FileDataStorageManager(dataPath), new FileCommitLogManager(logsPath), tmoDir, null)) {
        manager.start();
        manager.waitForTablespace("tblspace1", 10000);
        InsertStatement insert = new InsertStatement("tblspace1", "t1", new AutoIncrementPrimaryKeyRecordFunction(), new ConstValueRecordFunction(new byte[0]), false);
        DMLStatementExecutionResult insertResult = manager.executeUpdate(insert, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        assertEquals(1, insertResult.getUpdateCount());
        int newValue = insertResult.getKey().to_int();
        assertEquals(2, newValue);
        GetResult get = manager.get(new GetStatement("tblspace1", "t1", insertResult.getKey(), null, false), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        assertTrue(get.found());
        long next_value = manager.getTableSpaceManager("tblspace1").getTableManager("t1").getNextPrimaryKeyValue();
        assertEquals(3, next_value);
    }
}
Also used : Path(java.nio.file.Path) Table(herddb.model.Table) GetResult(herddb.model.GetResult) FileMetadataStorageManager(herddb.file.FileMetadataStorageManager) CreateTableStatement(herddb.model.commands.CreateTableStatement) InsertStatement(herddb.model.commands.InsertStatement) FileCommitLogManager(herddb.file.FileCommitLogManager) CreateTableSpaceStatement(herddb.model.commands.CreateTableSpaceStatement) ConstValueRecordFunction(herddb.model.ConstValueRecordFunction) DMLStatementExecutionResult(herddb.model.DMLStatementExecutionResult) GetStatement(herddb.model.commands.GetStatement) FileDataStorageManager(herddb.file.FileDataStorageManager) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction) Test(org.junit.Test)

Example 5 with AutoIncrementPrimaryKeyRecordFunction

use of herddb.model.AutoIncrementPrimaryKeyRecordFunction 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);
    }
}
Also used : DataAccessor(herddb.utils.DataAccessor) ConstantExpression(herddb.sql.expressions.ConstantExpression) ArrayList(java.util.ArrayList) CompiledSQLExpression(herddb.sql.expressions.CompiledSQLExpression) StatementExecutionException(herddb.model.StatementExecutionException) InsertStatement(herddb.model.commands.InsertStatement) Bytes(herddb.utils.Bytes) CompletableFuture(java.util.concurrent.CompletableFuture) DataScanner(herddb.model.DataScanner) Column(herddb.model.Column) DMLStatementExecutionResult(herddb.model.DMLStatementExecutionResult) StatementExecutionResult(herddb.model.StatementExecutionResult) SQLRecordFunction(herddb.sql.SQLRecordFunction) SQLRecordFunction(herddb.sql.SQLRecordFunction) RecordFunction(herddb.model.RecordFunction) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction) SQLRecordKeyFunction(herddb.sql.SQLRecordKeyFunction) DataScannerException(herddb.model.DataScannerException) ScanResult(herddb.model.ScanResult) Table(herddb.model.Table) AtomicReference(java.util.concurrent.atomic.AtomicReference) DMLStatementExecutionResult(herddb.model.DMLStatementExecutionResult) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TransactionContext(herddb.model.TransactionContext) DMLStatement(herddb.model.DMLStatement) AutoIncrementPrimaryKeyRecordFunction(herddb.model.AutoIncrementPrimaryKeyRecordFunction) BiConsumer(java.util.function.BiConsumer)

Aggregations

AutoIncrementPrimaryKeyRecordFunction (herddb.model.AutoIncrementPrimaryKeyRecordFunction)7 Table (herddb.model.Table)7 InsertStatement (herddb.model.commands.InsertStatement)7 Column (herddb.model.Column)5 RecordFunction (herddb.model.RecordFunction)5 StatementExecutionException (herddb.model.StatementExecutionException)5 CompiledSQLExpression (herddb.sql.expressions.CompiledSQLExpression)5 ArrayList (java.util.ArrayList)5 DMLStatement (herddb.model.DMLStatement)4 DMLStatementExecutionResult (herddb.model.DMLStatementExecutionResult)4 ConstantExpression (herddb.sql.expressions.ConstantExpression)4 AbstractTableManager (herddb.core.AbstractTableManager)2 TableSpaceManager (herddb.core.TableSpaceManager)2 FileCommitLogManager (herddb.file.FileCommitLogManager)2 FileDataStorageManager (herddb.file.FileDataStorageManager)2 FileMetadataStorageManager (herddb.file.FileMetadataStorageManager)2 ConstValueRecordFunction (herddb.model.ConstValueRecordFunction)2 DataScanner (herddb.model.DataScanner)2 DataScannerException (herddb.model.DataScannerException)2 GetResult (herddb.model.GetResult)2