Search in sources :

Example 1 with DbObject

use of org.h2.engine.DbObject in project h2database by h2database.

the class AlterTableAlterColumn method checkViewsAreValid.

/**
 * Check that a table or view is still valid.
 *
 * @param tableOrView the table or view to check
 */
private void checkViewsAreValid(DbObject tableOrView) {
    for (DbObject view : tableOrView.getChildren()) {
        if (view instanceof TableView) {
            String sql = ((TableView) view).getQuery();
            // check if the query is still valid
            // do not execute, not even with limit 1, because that could
            // have side effects or take a very long time
            session.prepare(sql);
            checkViewsAreValid(view);
        }
    }
}
Also used : DbObject(org.h2.engine.DbObject) TableView(org.h2.table.TableView)

Example 2 with DbObject

use of org.h2.engine.DbObject in project h2database by h2database.

the class AlterTableAlterColumn method cloneTableStructure.

private Table cloneTableStructure(Table table, Column[] columns, Database db, String tempName, ArrayList<Column> newColumns) {
    for (Column col : columns) {
        newColumns.add(col.getClone());
    }
    if (type == CommandInterface.ALTER_TABLE_DROP_COLUMN) {
        for (Column removeCol : columnsToRemove) {
            Column foundCol = null;
            for (Column newCol : newColumns) {
                if (newCol.getName().equals(removeCol.getName())) {
                    foundCol = newCol;
                    break;
                }
            }
            if (foundCol == null) {
                throw DbException.throwInternalError(removeCol.getCreateSQL());
            }
            newColumns.remove(foundCol);
        }
    } else if (type == CommandInterface.ALTER_TABLE_ADD_COLUMN) {
        int position;
        if (addFirst) {
            position = 0;
        } else if (addBefore != null) {
            position = table.getColumn(addBefore).getColumnId();
        } else if (addAfter != null) {
            position = table.getColumn(addAfter).getColumnId() + 1;
        } else {
            position = columns.length;
        }
        if (columnsToAdd != null) {
            for (Column column : columnsToAdd) {
                newColumns.add(position++, column);
            }
        }
    } else if (type == CommandInterface.ALTER_TABLE_ALTER_COLUMN_CHANGE_TYPE) {
        int position = oldColumn.getColumnId();
        newColumns.set(position, newColumn);
    }
    // create a table object in order to get the SQL statement
    // can't just use this table, because most column objects are 'shared'
    // with the old table
    // still need a new id because using 0 would mean: the new table tries
    // to use the rows of the table 0 (the meta table)
    int id = db.allocateObjectId();
    CreateTableData data = new CreateTableData();
    data.tableName = tempName;
    data.id = id;
    data.columns = newColumns;
    data.temporary = table.isTemporary();
    data.persistData = table.isPersistData();
    data.persistIndexes = table.isPersistIndexes();
    data.isHidden = table.isHidden();
    data.create = true;
    data.session = session;
    Table newTable = getSchema().createTable(data);
    newTable.setComment(table.getComment());
    StringBuilder buff = new StringBuilder();
    buff.append(newTable.getCreateSQL());
    StringBuilder columnList = new StringBuilder();
    for (Column nc : newColumns) {
        if (columnList.length() > 0) {
            columnList.append(", ");
        }
        if (type == CommandInterface.ALTER_TABLE_ADD_COLUMN && columnsToAdd != null && columnsToAdd.contains(nc)) {
            Expression def = nc.getDefaultExpression();
            columnList.append(def == null ? "NULL" : def.getSQL());
        } else {
            columnList.append(nc.getSQL());
        }
    }
    buff.append(" AS SELECT ");
    if (columnList.length() == 0) {
        // special case: insert into test select * from
        buff.append('*');
    } else {
        buff.append(columnList);
    }
    buff.append(" FROM ").append(table.getSQL());
    String newTableSQL = buff.toString();
    String newTableName = newTable.getName();
    Schema newTableSchema = newTable.getSchema();
    newTable.removeChildrenAndResources(session);
    execute(newTableSQL, true);
    newTable = newTableSchema.getTableOrView(session, newTableName);
    ArrayList<String> triggers = New.arrayList();
    for (DbObject child : table.getChildren()) {
        if (child instanceof Sequence) {
            continue;
        } else if (child instanceof Index) {
            Index idx = (Index) child;
            if (idx.getIndexType().getBelongsToConstraint()) {
                continue;
            }
        }
        String createSQL = child.getCreateSQL();
        if (createSQL == null) {
            continue;
        }
        if (child instanceof TableView) {
            continue;
        } else if (child.getType() == DbObject.TABLE_OR_VIEW) {
            DbException.throwInternalError();
        }
        String quotedName = Parser.quoteIdentifier(tempName + "_" + child.getName());
        String sql = null;
        if (child instanceof ConstraintReferential) {
            ConstraintReferential r = (ConstraintReferential) child;
            if (r.getTable() != table) {
                sql = r.getCreateSQLForCopy(r.getTable(), newTable, quotedName, false);
            }
        }
        if (sql == null) {
            sql = child.getCreateSQLForCopy(newTable, quotedName);
        }
        if (sql != null) {
            if (child instanceof TriggerObject) {
                triggers.add(sql);
            } else {
                execute(sql, true);
            }
        }
    }
    table.setModified();
    // otherwise the sequence is dropped if the table is dropped
    for (Column col : newColumns) {
        Sequence seq = col.getSequence();
        if (seq != null) {
            table.removeSequence(seq);
            col.setSequence(null);
        }
    }
    for (String sql : triggers) {
        execute(sql, true);
    }
    return newTable;
}
Also used : Table(org.h2.table.Table) DbObject(org.h2.engine.DbObject) Schema(org.h2.schema.Schema) TriggerObject(org.h2.schema.TriggerObject) Index(org.h2.index.Index) Sequence(org.h2.schema.Sequence) ConstraintReferential(org.h2.constraint.ConstraintReferential) Constraint(org.h2.constraint.Constraint) Column(org.h2.table.Column) Expression(org.h2.expression.Expression) TableView(org.h2.table.TableView)

Example 3 with DbObject

use of org.h2.engine.DbObject in project h2database by h2database.

the class AlterTableAlterColumn method checkDefaultReferencesTable.

private static void checkDefaultReferencesTable(Table table, Expression defaultExpression) {
    if (defaultExpression == null) {
        return;
    }
    HashSet<DbObject> dependencies = new HashSet<>();
    ExpressionVisitor visitor = ExpressionVisitor.getDependenciesVisitor(dependencies);
    defaultExpression.isEverything(visitor);
    if (dependencies.contains(table)) {
        throw DbException.get(ErrorCode.COLUMN_IS_REFERENCED_1, defaultExpression.getSQL());
    }
}
Also used : DbObject(org.h2.engine.DbObject) ExpressionVisitor(org.h2.expression.ExpressionVisitor) HashSet(java.util.HashSet)

Example 4 with DbObject

use of org.h2.engine.DbObject in project h2database by h2database.

the class AlterTableAlterColumn method copyData.

private void copyData(Table table, ArrayList<Sequence> sequences, boolean createConstraints) {
    if (table.isTemporary()) {
        throw DbException.getUnsupportedException("TEMP TABLE");
    }
    Database db = session.getDatabase();
    String baseName = table.getName();
    String tempName = db.getTempTableName(baseName, session);
    Column[] columns = table.getColumns();
    ArrayList<Column> newColumns = New.arrayList();
    Table newTable = cloneTableStructure(table, columns, db, tempName, newColumns);
    if (sequences != null) {
        for (Sequence sequence : sequences) {
            table.addSequence(sequence);
        }
    }
    try {
        // check if a view would become invalid
        // (because the column to drop is referenced or so)
        checkViews(table, newTable);
    } catch (DbException e) {
        execute("DROP TABLE " + newTable.getName(), true);
        throw DbException.get(ErrorCode.VIEW_IS_INVALID_2, e, getSQL(), e.getMessage());
    }
    String tableName = table.getName();
    ArrayList<TableView> dependentViews = new ArrayList<>(table.getDependentViews());
    for (TableView view : dependentViews) {
        table.removeDependentView(view);
    }
    execute("DROP TABLE " + table.getSQL() + " IGNORE", true);
    db.renameSchemaObject(session, newTable, tableName);
    for (DbObject child : newTable.getChildren()) {
        if (child instanceof Sequence) {
            continue;
        }
        String name = child.getName();
        if (name == null || child.getCreateSQL() == null) {
            continue;
        }
        if (name.startsWith(tempName + "_")) {
            name = name.substring(tempName.length() + 1);
            SchemaObject so = (SchemaObject) child;
            if (so instanceof Constraint) {
                if (so.getSchema().findConstraint(session, name) != null) {
                    name = so.getSchema().getUniqueConstraintName(session, newTable);
                }
            } else if (so instanceof Index) {
                if (so.getSchema().findIndex(session, name) != null) {
                    name = so.getSchema().getUniqueIndexName(session, newTable, name);
                }
            }
            db.renameSchemaObject(session, so, name);
        }
    }
    if (createConstraints) {
        createConstraints();
    }
    for (TableView view : dependentViews) {
        String sql = view.getCreateSQL(true, true);
        execute(sql, true);
    }
}
Also used : SchemaObject(org.h2.schema.SchemaObject) Table(org.h2.table.Table) DbObject(org.h2.engine.DbObject) Constraint(org.h2.constraint.Constraint) ArrayList(java.util.ArrayList) Index(org.h2.index.Index) Sequence(org.h2.schema.Sequence) DbException(org.h2.message.DbException) Column(org.h2.table.Column) Database(org.h2.engine.Database) TableView(org.h2.table.TableView)

Example 5 with DbObject

use of org.h2.engine.DbObject in project h2database by h2database.

the class AlterTableRenameColumn method update.

@Override
public int update() {
    session.commit(true);
    Database db = session.getDatabase();
    Table table = getSchema().findTableOrView(session, tableName);
    if (table == null) {
        if (ifTableExists) {
            return 0;
        }
        throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableName);
    }
    Column column = table.getColumn(oldName);
    session.getUser().checkRight(table, Right.ALL);
    table.checkSupportAlter();
    // we need to update CHECK constraint
    // since it might reference the name of the column
    Expression newCheckExpr = column.getCheckConstraint(session, newName);
    table.renameColumn(column, newName);
    column.removeCheckConstraint();
    column.addCheckConstraint(session, newCheckExpr);
    table.setModified();
    db.updateMeta(session, table);
    for (DbObject child : table.getChildren()) {
        if (child.getCreateSQL() != null) {
            db.updateMeta(session, child);
        }
    }
    return 0;
}
Also used : Table(org.h2.table.Table) Column(org.h2.table.Column) Expression(org.h2.expression.Expression) DbObject(org.h2.engine.DbObject) Database(org.h2.engine.Database)

Aggregations

DbObject (org.h2.engine.DbObject)12 Constraint (org.h2.constraint.Constraint)11 Table (org.h2.table.Table)9 Database (org.h2.engine.Database)8 Right (org.h2.engine.Right)5 Index (org.h2.index.Index)5 Sequence (org.h2.schema.Sequence)5 Schema (org.h2.schema.Schema)4 SchemaObject (org.h2.schema.SchemaObject)4 Column (org.h2.table.Column)4 TableView (org.h2.table.TableView)4 ArrayList (java.util.ArrayList)3 HashSet (java.util.HashSet)3 Role (org.h2.engine.Role)3 User (org.h2.engine.User)3 DbException (org.h2.message.DbException)3 TriggerObject (org.h2.schema.TriggerObject)3 IOException (java.io.IOException)2 ConstraintReferential (org.h2.constraint.ConstraintReferential)2 Comment (org.h2.engine.Comment)2