Search in sources :

Example 96 with Table

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

the class JSQLParserPlanner 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;
    }
    tableSpace = fixMySqlBackTicks(tableSpace);
    List<Column> addColumns = new ArrayList<>();
    List<Column> modifyColumns = new ArrayList<>();
    List<String> dropColumns = new ArrayList<>();
    List<String> dropForeignKeys = new ArrayList<>();
    List<ForeignKeyDef> addForeignKeys = new ArrayList<>();
    String tableName = fixMySqlBackTicks(alter.getTable().getName().toLowerCase());
    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;
    TableSpaceManager tableSpaceManager = manager.getTableSpaceManager(tableSpace);
    if (tableSpaceManager == null) {
        throw new StatementExecutionException("bad tablespace '" + tableSpace + "'");
    }
    Table table = getTable(defaultTableSpace, alter.getTable());
    switch(operation) {
        case ADD:
            {
                if (alterExpression.getColDataTypeList() != null) {
                    List<AlterExpression.ColumnDataType> cols = alterExpression.getColDataTypeList();
                    for (AlterExpression.ColumnDataType cl : cols) {
                        List<String> columnSpecs = decodeColumnSpecs(cl.getColumnSpecs());
                        int type = sqlDataTypeToColumnType(cl.getColDataType().getDataType(), cl.getColDataType().getArgumentsStringList(), columnSpecs);
                        Column newColumn = Column.column(fixMySqlBackTicks(cl.getColumnName()), type, decodeDefaultValue(cl, type));
                        addColumns.add(newColumn);
                    }
                } else if (alterExpression.getIndex() != null && alterExpression.getIndex() instanceof ForeignKeyIndex) {
                    ForeignKeyDef fkIndex = parseForeignKeyIndex((ForeignKeyIndex) alterExpression.getIndex(), table, tableName, tableSpace);
                    addForeignKeys.add(fkIndex);
                } else {
                    throw new StatementExecutionException("Unrecognized ALTER TABLE ADD ... statement");
                }
            }
            break;
        case DROP:
            if (alterExpression.getColumnName() != null) {
                dropColumns.add(fixMySqlBackTicks(alterExpression.getColumnName()));
            } else if (alterExpression.getConstraintName() != null) {
                dropForeignKeys.add(fixMySqlBackTicks(alterExpression.getConstraintName()));
            } else {
                throw new StatementExecutionException("Unrecognized ALTER TABLE DROP ... statement");
            }
            break;
        case MODIFY:
            {
                List<AlterExpression.ColumnDataType> cols = alterExpression.getColDataTypeList();
                for (AlterExpression.ColumnDataType cl : cols) {
                    String columnName = fixMySqlBackTicks(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()) {
                                indexedColumn = fixMySqlBackTicks(indexedColumn);
                                if (indexedColumn.equalsIgnoreCase(oldColumn.name)) {
                                    throw new StatementExecutionException("cannot alter indexed " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'," + "index name is " + am.getIndexName());
                                }
                            }
                        }
                    }
                    List<String> columnSpecs = decodeColumnSpecs(cl.getColumnSpecs());
                    int newType = sqlDataTypeToColumnType(cl.getColDataType().getDataType(), cl.getColDataType().getArgumentsStringList(), columnSpecs);
                    if (oldColumn.type != newType) {
                        if (ColumnTypes.isNotNullToNullConversion(oldColumn.type, newType)) {
                        // allow change from "STRING NOT NULL" to "STRING NULL"
                        } else if (ColumnTypes.isNullToNotNullConversion(oldColumn.type, newType)) {
                        // allow change from "STRING NULL" to "STRING NOT NULL"
                        // it will require a check on table at execution time
                        } else {
                            throw new StatementExecutionException("cannot change datatype to " + ColumnTypes.typeToString(newType) + " for column " + columnName + " (" + ColumnTypes.typeToString(oldColumn.type) + ") in table " + tableName + " in tablespace '" + tableSpace + "'");
                        }
                    }
                    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;
                        }
                    }
                    Bytes newDefault = oldColumn.defaultValue;
                    if (containsDefaultClause(cl)) {
                        newDefault = decodeDefaultValue(cl, newType);
                    }
                    Column newColumnDef = Column.column(columnName, newType, oldColumn.serialPosition, newDefault);
                    modifyColumns.add(newColumnDef);
                }
            }
            break;
        case CHANGE:
            {
                String columnName = alterExpression.getColOldName();
                List<AlterExpression.ColumnDataType> cols = alterExpression.getColDataTypeList();
                if (cols.size() != 1) {
                    throw new StatementExecutionException("bad CHANGE column " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'");
                }
                AlterExpression.ColumnDataType cl = cols.get(0);
                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()) {
                            indexedColumn = fixMySqlBackTicks(indexedColumn);
                            if (indexedColumn.equalsIgnoreCase(oldColumn.name)) {
                                throw new StatementExecutionException("cannot alter indexed " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'," + "index name is " + am.getIndexName());
                            }
                        }
                    }
                }
                List<String> columnSpecs = decodeColumnSpecs(cl.getColumnSpecs());
                int newType = sqlDataTypeToColumnType(cl.getColDataType().getDataType(), cl.getColDataType().getArgumentsStringList(), columnSpecs);
                if (oldColumn.type != newType) {
                    throw new StatementExecutionException("cannot change datatype to " + ColumnTypes.typeToString(newType) + " for column " + columnName + " (" + ColumnTypes.typeToString(oldColumn.type) + ") in table " + tableName + " in tablespace '" + tableSpace + "'");
                }
                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 = fixMySqlBackTicks(cl.getColumnName().toLowerCase());
                if (renameTo != null) {
                    columnName = renameTo;
                }
                Column newColumnDef = Column.column(columnName, newType, oldColumn.serialPosition, oldColumn.defaultValue);
                modifyColumns.add(newColumnDef);
            }
            break;
        default:
            throw new StatementExecutionException("supported alter operation '" + alter + "'");
    }
    return new AlterTableStatement(addColumns, modifyColumns, dropColumns, changeAutoIncrement, tableName.toLowerCase(), tableSpace, null, dropForeignKeys, addForeignKeys);
}
Also used : AlterOperation(net.sf.jsqlparser.statement.alter.AlterOperation) Table(herddb.model.Table) ShowCreateTableCalculator.calculateShowCreateTable(herddb.sql.functions.ShowCreateTableCalculator.calculateShowCreateTable) 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) Bytes(herddb.utils.Bytes) Column(herddb.model.Column) TableSpaceManager(herddb.core.TableSpaceManager) ItemsList(net.sf.jsqlparser.expression.operators.relational.ItemsList) ArrayList(java.util.ArrayList) ExpressionList(net.sf.jsqlparser.expression.operators.relational.ExpressionList) MultiExpressionList(net.sf.jsqlparser.expression.operators.relational.MultiExpressionList) List(java.util.List) SetOperationList(net.sf.jsqlparser.statement.select.SetOperationList) ForeignKeyDef(herddb.model.ForeignKeyDef) ForeignKeyIndex(net.sf.jsqlparser.statement.create.table.ForeignKeyIndex) Map(java.util.Map)

Example 97 with Table

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

the class JSQLParserPlanner method buildSelectStatement.

private ExecutionPlan buildSelectStatement(String defaultTableSpace, int maxRows, Select select, boolean forceScan) throws StatementExecutionException {
    checkSupported(select.getWithItemsList() == null);
    SelectBody selectBody = select.getSelectBody();
    PlannerOp op = buildSelectBody(defaultTableSpace, maxRows, selectBody, forceScan).optimize();
    // Simplify Scan to Get
    if (!forceScan && op instanceof BindableTableScanOp) {
        ScanStatement scanStatement = op.unwrap(ScanStatement.class);
        if (scanStatement != null && scanStatement.getPredicate() != null) {
            Table tableDef = scanStatement.getTableDef();
            CompiledSQLExpression where = scanStatement.getPredicate().unwrap(CompiledSQLExpression.class);
            SQLRecordKeyFunction keyFunction = IndexUtils.findIndexAccess(where, tableDef.getPrimaryKey(), tableDef, "=", tableDef);
            if (keyFunction == null || !keyFunction.isFullPrimaryKey()) {
                throw new StatementExecutionException("unsupported GET not on PK (" + keyFunction + ")");
            }
            GetStatement get = new GetStatement(scanStatement.getTableSpace(), scanStatement.getTable(), keyFunction, scanStatement.getPredicate(), true);
            return ExecutionPlan.simple(get);
        }
    }
    return ExecutionPlan.simple(new SQLPlannedOperationStatement(op), op);
}
Also used : PlannerOp(herddb.model.planner.PlannerOp) Table(herddb.model.Table) ShowCreateTableCalculator.calculateShowCreateTable(herddb.sql.functions.ShowCreateTableCalculator.calculateShowCreateTable) CreateTable(net.sf.jsqlparser.statement.create.table.CreateTable) GetStatement(herddb.model.commands.GetStatement) CompiledSQLExpression(herddb.sql.expressions.CompiledSQLExpression) SelectBody(net.sf.jsqlparser.statement.select.SelectBody) StatementExecutionException(herddb.model.StatementExecutionException) BindableTableScanOp(herddb.model.planner.BindableTableScanOp) ScanStatement(herddb.model.commands.ScanStatement) SQLPlannedOperationStatement(herddb.model.commands.SQLPlannedOperationStatement)

Example 98 with Table

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

the class FileDataStorageManager method readTablespaceStructure.

public static List<Table> readTablespaceStructure(Path file, String tableSpace, LogSequenceNumber sequenceNumber) throws IOException, DataStorageManagerException {
    try (InputStream input = new BufferedInputStream(Files.newInputStream(file, StandardOpenOption.READ), 4 * 1024 * 1024);
        ExtendedDataInputStream din = new ExtendedDataInputStream(input)) {
        // version
        long version = din.readVLong();
        // flags for future implementations
        long flags = din.readVLong();
        if (version != 1 || flags != 0) {
            throw new DataStorageManagerException("corrupted table list file " + file.toAbsolutePath());
        }
        String readname = din.readUTF();
        if (!readname.equals(tableSpace)) {
            throw new DataStorageManagerException("file " + file.toAbsolutePath() + " is not for spablespace " + tableSpace);
        }
        long ledgerId = din.readZLong();
        long offset = din.readZLong();
        if (sequenceNumber != null) {
            if (ledgerId != sequenceNumber.ledgerId || offset != sequenceNumber.offset) {
                throw new DataStorageManagerException("file " + file.toAbsolutePath() + " is not for sequence number " + sequenceNumber);
            }
        }
        int numTables = din.readInt();
        List<Table> res = new ArrayList<>();
        for (int i = 0; i < numTables; i++) {
            byte[] tableData = din.readArray();
            Table table = Table.deserialize(tableData);
            res.add(table);
        }
        return Collections.unmodifiableList(res);
    }
}
Also used : ExtendedDataInputStream(herddb.utils.ExtendedDataInputStream) DataStorageManagerException(herddb.storage.DataStorageManagerException) Table(herddb.model.Table) BufferedInputStream(java.io.BufferedInputStream) BufferedInputStream(java.io.BufferedInputStream) ODirectFileInputStream(herddb.utils.ODirectFileInputStream) ExtendedDataInputStream(herddb.utils.ExtendedDataInputStream) SimpleByteArrayInputStream(herddb.utils.SimpleByteArrayInputStream) InputStream(java.io.InputStream) ArrayList(java.util.ArrayList)

Example 99 with Table

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

the class FileDataStorageManager method writeTables.

@Override
public Collection<PostCheckpointAction> writeTables(String tableSpace, LogSequenceNumber sequenceNumber, List<Table> tables, List<Index> indexlist, boolean prepareActions) throws DataStorageManagerException {
    if (sequenceNumber.isStartOfTime() && !tables.isEmpty()) {
        throw new DataStorageManagerException("impossible to write a non empty table list at start-of-time");
    }
    Path tableSpaceDirectory = getTablespaceDirectory(tableSpace);
    try {
        Files.createDirectories(tableSpaceDirectory);
        Path fileTables = getTablespaceTablesMetadataFile(tableSpace, sequenceNumber);
        Path fileIndexes = getTablespaceIndexesMetadataFile(tableSpace, sequenceNumber);
        Path parent = getParent(fileTables);
        Files.createDirectories(parent);
        LOGGER.log(Level.FINE, "writeTables for tableSpace " + tableSpace + " sequenceNumber " + sequenceNumber + " to " + fileTables.toAbsolutePath().toString());
        try (ManagedFile file = ManagedFile.open(fileTables, requirefsync);
            SimpleBufferedOutputStream buffer = new SimpleBufferedOutputStream(file.getOutputStream(), COPY_BUFFERS_SIZE);
            ExtendedDataOutputStream dout = new ExtendedDataOutputStream(buffer)) {
            // version
            dout.writeVLong(1);
            // flags for future implementations
            dout.writeVLong(0);
            dout.writeUTF(tableSpace);
            dout.writeZLong(sequenceNumber.ledgerId);
            dout.writeZLong(sequenceNumber.offset);
            dout.writeInt(tables.size());
            for (Table t : tables) {
                byte[] tableSerialized = t.serialize();
                dout.writeArray(tableSerialized);
            }
            dout.flush();
            file.sync();
        } catch (IOException err) {
            throw new DataStorageManagerException(err);
        }
        try (ManagedFile file = ManagedFile.open(fileIndexes, requirefsync);
            SimpleBufferedOutputStream buffer = new SimpleBufferedOutputStream(file.getOutputStream(), COPY_BUFFERS_SIZE);
            ExtendedDataOutputStream dout = new ExtendedDataOutputStream(buffer)) {
            // version
            dout.writeVLong(1);
            // flags for future implementations
            dout.writeVLong(0);
            dout.writeUTF(tableSpace);
            dout.writeZLong(sequenceNumber.ledgerId);
            dout.writeZLong(sequenceNumber.offset);
            if (indexlist != null) {
                dout.writeInt(indexlist.size());
                for (Index t : indexlist) {
                    byte[] indexSerialized = t.serialize();
                    dout.writeArray(indexSerialized);
                }
            } else {
                dout.writeInt(0);
            }
            dout.flush();
            file.sync();
        } catch (IOException err) {
            throw new DataStorageManagerException(err);
        }
    } catch (IOException err) {
        throw new DataStorageManagerException(err);
    }
    Collection<PostCheckpointAction> result = new ArrayList<>();
    if (prepareActions) {
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(tableSpaceDirectory)) {
            for (Path p : stream) {
                if (isTablespaceIndexesMetadataFile(p)) {
                    try {
                        LogSequenceNumber logPositionInFile = readLogSequenceNumberFromIndexMetadataFile(tableSpace, p);
                        if (sequenceNumber.after(logPositionInFile)) {
                            LOGGER.log(Level.FINEST, "indexes metadata file " + p.toAbsolutePath() + ". will be deleted after checkpoint end");
                            result.add(new DeleteFileAction(tableSpace, "indexes", "delete indexesmetadata file " + p.toAbsolutePath(), p));
                        }
                    } catch (DataStorageManagerException ignore) {
                        LOGGER.log(Level.SEVERE, "Unparsable indexesmetadata file " + p.toAbsolutePath(), ignore);
                        result.add(new DeleteFileAction(tableSpace, "indexes", "delete unparsable indexesmetadata file " + p.toAbsolutePath(), p));
                    }
                } else if (isTablespaceTablesMetadataFile(p)) {
                    try {
                        LogSequenceNumber logPositionInFile = readLogSequenceNumberFromTablesMetadataFile(tableSpace, p);
                        if (sequenceNumber.after(logPositionInFile)) {
                            LOGGER.log(Level.FINEST, "tables metadata file " + p.toAbsolutePath() + ". will be deleted after checkpoint end");
                            result.add(new DeleteFileAction(tableSpace, "tables", "delete tablesmetadata file " + p.toAbsolutePath(), p));
                        }
                    } catch (DataStorageManagerException ignore) {
                        LOGGER.log(Level.SEVERE, "Unparsable tablesmetadata file " + p.toAbsolutePath(), ignore);
                        result.add(new DeleteFileAction(tableSpace, "transactions", "delete unparsable tablesmetadata file " + p.toAbsolutePath(), p));
                    }
                }
            }
        } catch (IOException err) {
            LOGGER.log(Level.SEVERE, "Could not list dir " + tableSpaceDirectory, err);
        }
    }
    return result;
}
Also used : Path(java.nio.file.Path) DataStorageManagerException(herddb.storage.DataStorageManagerException) Table(herddb.model.Table) ArrayList(java.util.ArrayList) LogSequenceNumber(herddb.log.LogSequenceNumber) Index(herddb.model.Index) BLinkKeyToPageIndex(herddb.index.blink.BLinkKeyToPageIndex) KeyToPageIndex(herddb.index.KeyToPageIndex) IOException(java.io.IOException) ManagedFile(herddb.utils.ManagedFile) ExtendedDataOutputStream(herddb.utils.ExtendedDataOutputStream) PostCheckpointAction(herddb.core.PostCheckpointAction) SimpleBufferedOutputStream(herddb.utils.SimpleBufferedOutputStream)

Example 100 with Table

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

the class SortOp method optimize.

@Override
public PlannerOp optimize() {
    if (input instanceof BindableTableScanOp) {
        BindableTableScanOp op = (BindableTableScanOp) input;
        // we can change the statement, this node will be lost and the tablescan too
        ScanStatement statement = op.getStatement();
        statement.setComparator(this);
        if (fields.length == 1 && directions[0]) {
            Table tableDef = statement.getTableDef();
            if (tableDef.getPrimaryKey().length == 1) {
                if (statement.getProjection() != null && statement.getProjection() instanceof ZeroCopyProjection) {
                    ZeroCopyProjection zeroCopyProjection = (ZeroCopyProjection) statement.getProjection();
                    int index = zeroCopyProjection.mapPosition(fields[0]);
                    Column col = tableDef.resolveColumName(index);
                    if (col.name.equals(tableDef.getPrimaryKey()[0])) {
                        this.onlyPrimaryKeyAndAscending = true;
                    }
                } else if (statement.getProjection() != null && statement.getProjection() instanceof IdentityProjection) {
                    Column col = tableDef.resolveColumName(fields[0]);
                    if (col.name.equals(tableDef.getPrimaryKey()[0])) {
                        this.onlyPrimaryKeyAndAscending = true;
                    }
                }
            }
        }
        return new SortedBindableTableScanOp(statement);
    } else if (input instanceof TableScanOp) {
        TableScanOp op = (TableScanOp) input;
        // we can change the statement, this node will be lost and the tablescan too
        ScanStatement statement = op.getStatement();
        statement.setComparator(this);
        if (fields.length == 1 && directions[0]) {
            Table tableDef = statement.getTableDef();
            if (tableDef.getPrimaryKey().length == 1) {
                if (statement.getProjection() != null && statement.getProjection() instanceof ZeroCopyProjection) {
                    ZeroCopyProjection zeroCopyProjection = (ZeroCopyProjection) statement.getProjection();
                    int index = zeroCopyProjection.mapPosition(fields[0]);
                    Column col = tableDef.resolveColumName(index);
                    if (col.name.equals(tableDef.getPrimaryKey()[0])) {
                        this.onlyPrimaryKeyAndAscending = true;
                    }
                } else if (statement.getProjection() != null && statement.getProjection() instanceof IdentityProjection) {
                    Column col = tableDef.resolveColumName(fields[0]);
                    if (col.name.equals(tableDef.getPrimaryKey()[0])) {
                        this.onlyPrimaryKeyAndAscending = true;
                    }
                }
            }
        }
        return new SortedTableScanOp(statement);
    }
    return this;
}
Also used : Table(herddb.model.Table) ZeroCopyProjection(herddb.model.planner.ProjectOp.ZeroCopyProjection) Column(herddb.model.Column) IdentityProjection(herddb.model.planner.ProjectOp.IdentityProjection) ScanStatement(herddb.model.commands.ScanStatement)

Aggregations

Table (herddb.model.Table)288 Test (org.junit.Test)191 CreateTableStatement (herddb.model.commands.CreateTableStatement)181 CreateTableSpaceStatement (herddb.model.commands.CreateTableSpaceStatement)132 InsertStatement (herddb.model.commands.InsertStatement)118 DataScanner (herddb.model.DataScanner)110 Index (herddb.model.Index)98 ScanStatement (herddb.model.commands.ScanStatement)98 GetStatement (herddb.model.commands.GetStatement)85 TransactionContext (herddb.model.TransactionContext)84 GetResult (herddb.model.GetResult)81 MemoryCommitLogManager (herddb.mem.MemoryCommitLogManager)80 MemoryMetadataStorageManager (herddb.mem.MemoryMetadataStorageManager)80 TranslatedQuery (herddb.sql.TranslatedQuery)78 MemoryDataStorageManager (herddb.mem.MemoryDataStorageManager)77 Bytes (herddb.utils.Bytes)76 StatementExecutionException (herddb.model.StatementExecutionException)73 Record (herddb.model.Record)72 CreateIndexStatement (herddb.model.commands.CreateIndexStatement)72 Path (java.nio.file.Path)64