Search in sources :

Example 1 with StatementExecutionException

use of herddb.model.StatementExecutionException 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 StatementExecutionException

use of herddb.model.StatementExecutionException 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;
}
Also used : SelectExpressionItem(net.sf.jsqlparser.statement.select.SelectExpressionItem) RawString(herddb.utils.RawString) StatementExecutionException(herddb.model.StatementExecutionException) Function(net.sf.jsqlparser.expression.Function) Column(herddb.model.Column) Expression(net.sf.jsqlparser.expression.Expression) SelectItem(net.sf.jsqlparser.statement.select.SelectItem)

Example 3 with StatementExecutionException

use of herddb.model.StatementExecutionException 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 4 with StatementExecutionException

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

the class SQLPlanner method buildSelectStatement.

private ExecutionPlan buildSelectStatement(String defaultTableSpace, Select s, boolean scan, int maxRows) throws StatementExecutionException {
    PlainSelect selectBody = (PlainSelect) s.getSelectBody();
    net.sf.jsqlparser.schema.Table fromTable = (net.sf.jsqlparser.schema.Table) selectBody.getFromItem();
    TableRef mainTable = TableRef.buildFrom(fromTable, defaultTableSpace);
    String mainTableAlias = mainTable.tableAlias;
    String tableSpace = mainTable.tableSpace;
    TableSpaceManager tableSpaceManager = manager.getTableSpaceManager(tableSpace);
    if (tableSpaceManager == null) {
        throw new TableSpaceDoesNotExistException("no such tablespace " + tableSpace + " here at " + manager.getNodeId());
    }
    AbstractTableManager tableManager = tableSpaceManager.getTableManager(mainTable.tableName);
    if (tableManager == null) {
        throw new TableDoesNotExistException("no such table " + mainTable.tableName + " in tablespace " + tableSpace);
    }
    // linked hash map retains the order of insertions
    LinkedHashMap<String, JoinSupport> joins = new LinkedHashMap<>();
    boolean joinPresent = false;
    joins.put(mainTable.tableAlias, new JoinSupport(mainTable, tableManager));
    if (selectBody.getJoins() != null) {
        for (Join join : selectBody.getJoins()) {
            joinPresent = true;
            if (join.isLeft() || join.isCross() || join.isRight() || join.isOuter() || join.isSimple()) {
                throw new StatementExecutionException("unsupported JOIN type: " + join);
            }
            net.sf.jsqlparser.schema.Table joinedTable = (net.sf.jsqlparser.schema.Table) join.getRightItem();
            TableRef joinedTableRef = TableRef.buildFrom(joinedTable, defaultTableSpace);
            if (!joinedTableRef.tableSpace.equalsIgnoreCase(mainTable.tableSpace)) {
                throw new TableDoesNotExistException("unsupported cross-tablespace JOIN " + "between" + mainTable.tableSpace + "." + mainTable.tableName + " and " + joinedTableRef.tableSpace + "." + joinedTableRef.tableName);
            }
            AbstractTableManager joinedTableManager = tableSpaceManager.getTableManager(joinedTableRef.tableName);
            if (joinedTableManager == null) {
                throw new TableDoesNotExistException("no such table " + joinedTableRef.tableName + " in tablespace " + tableSpace);
            }
            JoinSupport joinSupport = new JoinSupport(joinedTableRef, joinedTableManager);
            joins.put(joinedTableRef.tableAlias, joinSupport);
        }
    }
    Projection mainTableProjection;
    Table table = tableManager.getTable();
    boolean allColumns = false;
    boolean containsAggregateFunctions = false;
    for (SelectItem c : selectBody.getSelectItems()) {
        if (c instanceof AllColumns) {
            allColumns = true;
            break;
        } else if (c instanceof AllTableColumns) {
            AllTableColumns allTableColumns = (AllTableColumns) c;
            TableRef ref = TableRef.buildFrom(allTableColumns.getTable(), defaultTableSpace);
            if (!joinPresent && ref.tableAlias.equals(mainTable.tableAlias)) {
                // select a.*  FROM table a
                allColumns = true;
            } else {
                // select a.*, b.* FROM table a JOIN table b
                joins.get(ref.tableAlias).allColumns = true;
            }
        } else if (c instanceof SelectExpressionItem) {
            SelectExpressionItem se = (SelectExpressionItem) c;
            if (isAggregateFunction(se.getExpression())) {
                containsAggregateFunctions = true;
            }
            if (!joinPresent) {
                joins.get(mainTable.tableAlias).selectItems.add(c);
            } else {
                ColumnReferencesDiscovery discoverMainTableAlias = discoverMainTableAlias(se.getExpression());
                String mainTableAliasForItem = discoverMainTableAlias.getMainTableAlias();
                if (discoverMainTableAlias.isContainsMixedAliases()) {
                    throw new StatementExecutionException("unsupported single SELECT ITEM with mixed aliases: " + c);
                }
                if (mainTableAliasForItem == null) {
                    mainTableAliasForItem = mainTable.tableAlias;
                }
                joins.get(mainTableAliasForItem).selectItems.add(c);
            }
        } else {
            throw new StatementExecutionException("unsupported SELECT ITEM type: " + c);
        }
    }
    if (allColumns) {
        mainTableProjection = Projection.IDENTITY(table.columnNames, table.columns);
        for (Map.Entry<String, JoinSupport> join : joins.entrySet()) {
            JoinSupport support = join.getValue();
            support.projection = Projection.IDENTITY(support.table.columnNames, support.table.columns);
            support.allColumns = true;
        }
    } else {
        if (!joinPresent) {
            mainTableProjection = new SQLProjection(table, mainTableAlias, selectBody.getSelectItems());
        } else {
            for (JoinSupport support : joins.values()) {
                if (support.allColumns) {
                    support.projection = Projection.IDENTITY(support.table.columnNames, support.table.columns);
                } else {
                    support.projection = new SQLProjection(support.table, support.tableRef.tableAlias, support.selectItems);
                }
            }
            mainTableProjection = joins.get(mainTableAlias).projection;
        }
    }
    if (scan) {
        if (!joinPresent) {
            SQLRecordPredicate where = selectBody.getWhere() != null ? new SQLRecordPredicate(table, mainTableAlias, selectBody.getWhere()) : null;
            if (where != null) {
                discoverIndexOperations(selectBody.getWhere(), table, mainTableAlias, where, tableSpaceManager);
            }
            Aggregator aggregator = null;
            ScanLimitsImpl scanLimits = null;
            if (containsAggregateFunctions || (selectBody.getGroupByColumnReferences() != null && !selectBody.getGroupByColumnReferences().isEmpty())) {
                aggregator = new SQLAggregator(selectBody.getSelectItems(), selectBody.getGroupByColumnReferences(), manager.getRecordSetFactory());
            }
            TupleComparator comparatorOnScan = null;
            TupleComparator comparatorOnPlan = null;
            if (selectBody.getOrderByElements() != null && !selectBody.getOrderByElements().isEmpty()) {
                if (aggregator != null) {
                    comparatorOnPlan = SingleColumnSQLTupleComparator.make(mainTableAlias, selectBody.getOrderByElements(), null);
                } else {
                    comparatorOnScan = SingleColumnSQLTupleComparator.make(mainTableAlias, selectBody.getOrderByElements(), table.primaryKey);
                }
            }
            Limit limit = selectBody.getLimit();
            Top top = selectBody.getTop();
            if (limit != null && top != null) {
                throw new StatementExecutionException("LIMIT and TOP cannot be used on the same query");
            }
            if (limit != null) {
                if (limit.isLimitAll() || limit.isLimitNull() || limit.getOffset() instanceof JdbcParameter) {
                    throw new StatementExecutionException("Invalid LIMIT clause (limit=" + limit + ")");
                }
                if (maxRows > 0 && limit.getRowCount() instanceof JdbcParameter) {
                    throw new StatementExecutionException("Invalid LIMIT clause (limit=" + limit + ") and JDBC setMaxRows=" + maxRows);
                }
                int rowCount;
                int rowCountJdbcParameter = -1;
                if (limit.getRowCount() instanceof JdbcParameter) {
                    rowCount = -1;
                    rowCountJdbcParameter = ((JdbcParameter) limit.getRowCount()).getIndex() - 1;
                } else {
                    rowCount = ((Number) resolveValue(limit.getRowCount(), false)).intValue();
                }
                int offset = limit.getOffset() != null ? ((Number) resolveValue(limit.getOffset(), false)).intValue() : 0;
                scanLimits = new ScanLimitsImpl(rowCount, offset, rowCountJdbcParameter + 1);
            } else if (top != null) {
                if (top.isPercentage() || top.getExpression() == null) {
                    throw new StatementExecutionException("Invalid TOP clause (top=" + top + ")");
                }
                try {
                    int rowCount = Integer.parseInt(resolveValue(top.getExpression(), false) + "");
                    scanLimits = new ScanLimitsImpl(rowCount, 0);
                } catch (NumberFormatException error) {
                    throw new StatementExecutionException("Invalid TOP clause: " + error, error);
                }
            }
            if (maxRows > 0) {
                if (scanLimits == null) {
                    scanLimits = new ScanLimitsImpl(maxRows, 0);
                } else if (scanLimits.getMaxRows() <= 0 || scanLimits.getMaxRows() > maxRows) {
                    scanLimits = new ScanLimitsImpl(maxRows, scanLimits.getOffset());
                }
            }
            ScanLimitsImpl limitsOnScan = null;
            ScanLimitsImpl limitsOnPlan = null;
            if (aggregator != null) {
                limitsOnPlan = scanLimits;
            } else {
                limitsOnScan = scanLimits;
            }
            try {
                ScanStatement statement = new ScanStatement(tableSpace, mainTable.tableName, mainTableProjection, where, comparatorOnScan, limitsOnScan);
                return ExecutionPlan.make(statement, aggregator, limitsOnPlan, comparatorOnPlan);
            } catch (IllegalArgumentException err) {
                throw new StatementExecutionException(err);
            }
        } else {
            if (containsAggregateFunctions || (selectBody.getGroupByColumnReferences() != null && !selectBody.getGroupByColumnReferences().isEmpty())) {
                throw new StatementExecutionException("AGGREGATEs are not yet supported with JOIN");
            }
            Limit limit = selectBody.getLimit();
            Top top = selectBody.getTop();
            if (limit != null && top != null) {
                throw new StatementExecutionException("LIMIT and TOP cannot be used on the same query");
            }
            ScanLimitsImpl scanLimits = null;
            if (limit != null) {
                if (limit.isLimitAll() || limit.isLimitNull() || limit.getOffset() instanceof JdbcParameter) {
                    throw new StatementExecutionException("Invalid LIMIT clause (limit=" + limit + ")");
                }
                if (maxRows > 0 && limit.getRowCount() instanceof JdbcParameter) {
                    throw new StatementExecutionException("Invalid LIMIT clause (limit=" + limit + ") and JDBC setMaxRows=" + maxRows);
                }
                int rowCount;
                int rowCountJdbcParameter = -1;
                if (limit.getRowCount() instanceof JdbcParameter) {
                    rowCount = -1;
                    rowCountJdbcParameter = ((JdbcParameter) limit.getRowCount()).getIndex() - 1;
                } else {
                    rowCount = ((Number) resolveValue(limit.getRowCount(), false)).intValue();
                }
                int offset = limit.getOffset() != null ? ((Number) resolveValue(limit.getOffset(), false)).intValue() : 0;
                scanLimits = new ScanLimitsImpl(rowCount, offset, rowCountJdbcParameter + 1);
            } else if (top != null) {
                if (top.isPercentage() || top.getExpression() == null) {
                    throw new StatementExecutionException("Invalid TOP clause");
                }
                try {
                    int rowCount = Integer.parseInt(resolveValue(top.getExpression(), false) + "");
                    scanLimits = new ScanLimitsImpl(rowCount, 0);
                } catch (NumberFormatException error) {
                    throw new StatementExecutionException("Invalid TOP clause: " + error, error);
                }
            }
            if (maxRows > 0) {
                if (scanLimits == null) {
                    scanLimits = new ScanLimitsImpl(maxRows, 0);
                } else if (scanLimits.getMaxRows() <= 0 || scanLimits.getMaxRows() > maxRows) {
                    scanLimits = new ScanLimitsImpl(maxRows, scanLimits.getOffset());
                }
            }
            List<ColumnReferencesDiscovery> conditionsOnJoinedResult = new ArrayList<>();
            List<ScanStatement> scans = new ArrayList<>();
            for (Map.Entry<String, JoinSupport> join : joins.entrySet()) {
                String alias = join.getKey();
                JoinSupport joinSupport = join.getValue();
                Expression collectedConditionsForAlias = collectConditionsForAlias(alias, selectBody.getWhere(), conditionsOnJoinedResult, mainTableAlias);
                LOG.severe("Collected WHERE for alias " + alias + ": " + collectedConditionsForAlias);
                if (collectedConditionsForAlias == null) {
                    joinSupport.predicate = null;
                } else {
                    joinSupport.predicate = new SQLRecordPredicate(join.getValue().table, alias, collectedConditionsForAlias);
                }
            }
            for (Join join : selectBody.getJoins()) {
                if (join.getOnExpression() != null) {
                    ColumnReferencesDiscovery discoverMainTableAliasForJoinCondition = discoverMainTableAlias(join.getOnExpression());
                    conditionsOnJoinedResult.add(discoverMainTableAliasForJoinCondition);
                    LOG.severe("Collected ON-condition on final JOIN result: " + join.getOnExpression());
                }
            }
            for (ColumnReferencesDiscovery e : conditionsOnJoinedResult) {
                LOG.severe("Collected WHERE on final JOIN result: " + e.getExpression());
                for (Map.Entry<String, List<net.sf.jsqlparser.schema.Column>> entry : e.getColumnsByTable().entrySet()) {
                    String tableAlias = entry.getKey();
                    List<net.sf.jsqlparser.schema.Column> filteredColumnsOnJoin = entry.getValue();
                    LOG.severe("for  TABLE " + tableAlias + " we need to load " + filteredColumnsOnJoin);
                    JoinSupport support = joins.get(tableAlias);
                    if (support == null) {
                        throw new StatementExecutionException("invalid table alias " + tableAlias);
                    }
                    if (!support.allColumns) {
                        for (net.sf.jsqlparser.schema.Column c : filteredColumnsOnJoin) {
                            support.selectItems.add(new SelectExpressionItem(c));
                        }
                        support.projection = new SQLProjection(support.table, support.tableRef.tableAlias, support.selectItems);
                    }
                }
            }
            Map<String, Table> tables = new HashMap<>();
            for (Map.Entry<String, JoinSupport> join : joins.entrySet()) {
                JoinSupport joinSupport = join.getValue();
                tables.put(join.getKey(), joinSupport.table);
                ScanStatement statement = new ScanStatement(tableSpace, joinSupport.table.name, joinSupport.projection, joinSupport.predicate, null, null);
                scans.add(statement);
            }
            TuplePredicate joinFilter = null;
            if (!conditionsOnJoinedResult.isEmpty()) {
                joinFilter = new SQLRecordPredicate(null, null, composeAndExpression(conditionsOnJoinedResult));
            }
            Projection joinProjection = null;
            if (!allColumns) {
                joinProjection = new SQLProjection(tableSpace, tables, selectBody.getSelectItems());
            }
            TupleComparator comparatorOnPlan = null;
            if (selectBody.getOrderByElements() != null && !selectBody.getOrderByElements().isEmpty()) {
                comparatorOnPlan = SingleColumnSQLTupleComparator.make(mainTableAlias, selectBody.getOrderByElements(), null);
            }
            try {
                return ExecutionPlan.joinedScan(scans, joinFilter, joinProjection, scanLimits, comparatorOnPlan);
            } catch (IllegalArgumentException err) {
                throw new StatementExecutionException(err);
            }
        }
    } else {
        if (selectBody.getWhere() == null) {
            throw new StatementExecutionException("unsupported GET without WHERE");
        }
        if (joinPresent) {
            throw new StatementExecutionException("unsupported GET with JOIN");
        }
        // SELECT * FROM WHERE KEY=? AND ....
        SQLRecordKeyFunction keyFunction = findPrimaryKeyIndexSeek(selectBody.getWhere(), table, mainTableAlias);
        if (keyFunction == null || !keyFunction.isFullPrimaryKey()) {
            throw new StatementExecutionException("unsupported GET not on PK, bad where clause: " + selectBody.getWhere() + " (" + selectBody.getWhere().getClass() + ")");
        }
        Predicate where = buildSimplePredicate(selectBody.getWhere(), table, mainTableAlias);
        try {
            return ExecutionPlan.simple(new GetStatement(tableSpace, mainTable.tableName, keyFunction, where, false));
        } catch (IllegalArgumentException err) {
            throw new StatementExecutionException(err);
        }
    }
}
Also used : TuplePredicate(herddb.model.TuplePredicate) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Projection(herddb.model.Projection) StatementExecutionException(herddb.model.StatementExecutionException) LinkedHashMap(java.util.LinkedHashMap) TuplePredicate(herddb.model.TuplePredicate) Predicate(herddb.model.Predicate) TableSpaceManager(herddb.core.TableSpaceManager) 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) Top(net.sf.jsqlparser.statement.select.Top) AbstractTableManager(herddb.core.AbstractTableManager) GetStatement(herddb.model.commands.GetStatement) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) TableSpaceDoesNotExistException(herddb.model.TableSpaceDoesNotExistException) SelectExpressionItem(net.sf.jsqlparser.statement.select.SelectExpressionItem) PlainSelect(net.sf.jsqlparser.statement.select.PlainSelect) TupleComparator(herddb.model.TupleComparator) AllColumns(net.sf.jsqlparser.statement.select.AllColumns) Column(herddb.model.Column) SelectItem(net.sf.jsqlparser.statement.select.SelectItem) ScanStatement(herddb.model.commands.ScanStatement) Table(herddb.model.Table) CreateTable(net.sf.jsqlparser.statement.create.table.CreateTable) JdbcParameter(net.sf.jsqlparser.expression.JdbcParameter) Join(net.sf.jsqlparser.statement.select.Join) Aggregator(herddb.model.Aggregator) ScanLimitsImpl(herddb.model.ScanLimitsImpl) TableDoesNotExistException(herddb.model.TableDoesNotExistException) 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) AllTableColumns(net.sf.jsqlparser.statement.select.AllTableColumns) Limit(net.sf.jsqlparser.statement.select.Limit)

Example 5 with StatementExecutionException

use of herddb.model.StatementExecutionException 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);
}
Also used : AlterOperation(net.sf.jsqlparser.statement.alter.AlterOperation) Table(herddb.model.Table) CreateTable(net.sf.jsqlparser.statement.create.table.CreateTable) AbstractIndexManager(herddb.core.AbstractIndexManager) AlterTableStatement(herddb.model.commands.AlterTableStatement) ArrayList(java.util.ArrayList) StatementExecutionException(herddb.model.StatementExecutionException) AlterExpression(net.sf.jsqlparser.statement.alter.AlterExpression) Column(herddb.model.Column) AbstractTableManager(herddb.core.AbstractTableManager) TableSpaceManager(herddb.core.TableSpaceManager) 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) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap)

Aggregations

StatementExecutionException (herddb.model.StatementExecutionException)163 Table (herddb.model.Table)69 ArrayList (java.util.ArrayList)57 DataScanner (herddb.model.DataScanner)49 TransactionContext (herddb.model.TransactionContext)47 DataStorageManagerException (herddb.storage.DataStorageManagerException)40 List (java.util.List)40 DataScannerException (herddb.model.DataScannerException)39 StatementExecutionResult (herddb.model.StatementExecutionResult)39 Column (herddb.model.Column)37 DataAccessor (herddb.utils.DataAccessor)36 LogNotAvailableException (herddb.log.LogNotAvailableException)35 LogEntry (herddb.log.LogEntry)34 Test (org.junit.Test)34 InsertStatement (herddb.model.commands.InsertStatement)32 Bytes (herddb.utils.Bytes)32 CommitLogResult (herddb.log.CommitLogResult)31 Record (herddb.model.Record)31 DMLStatementExecutionResult (herddb.model.DMLStatementExecutionResult)30 Map (java.util.Map)30