public void rename(String newName) { super.rename(newName); if (constraints != null) { for (int i = 0, size = constraints.size(); i < size; i++) { Constraint constraint = constraints.get(i); constraint.rebuild(); } } }
/** * Enable or disable foreign key constraint checking for this table. * * @param session the session * @param enabled true if checking should be enabled * @param checkExisting true if existing rows must be checked during this call */ public void setCheckForeignKeyConstraints( Session session, boolean enabled, boolean checkExisting) { if (enabled && checkExisting) { if (constraints != null) { for (Constraint c : constraints) { c.checkExistingData(session); } } } checkForeignKeyConstraints = enabled; }
private void fireConstraints(Session session, Row oldRow, Row newRow, boolean before) { if (constraints != null) { // don't use enhanced for loop to avoid creating objects for (int i = 0, size = constraints.size(); i < size; i++) { Constraint constraint = constraints.get(i); if (constraint.isBefore() == before) { constraint.checkRow(session, this, oldRow, newRow); } } } }
/** * If the index is still required by a constraint, transfer the ownership to it. Otherwise, the * index is removed. * * @param session the session * @param index the index that is no longer required */ public void removeIndexOrTransferOwnership(Session session, Index index) { boolean stillNeeded = false; if (constraints != null) { for (Constraint cons : constraints) { if (cons.usesIndex(index)) { cons.setIndexOwner(index); database.update(session, cons); stillNeeded = true; } } } if (!stillNeeded) { database.removeSchemaObject(session, index); } }
@Override public int compareTo(Constraint other) { if (this == other) { return 0; } int thisType = getConstraintTypeOrder(); int otherType = other.getConstraintTypeOrder(); return thisType - otherType; }
/** * Check that this column is not referenced by a multi-column constraint or multi-column index. If * it is, an exception is thrown. Single-column references and indexes are dropped. * * @param session the session * @param col the column * @throws DbException if the column is referenced by multi-column constraints or indexes */ public void dropSingleColumnConstraintsAndIndexes(Session session, Column col) { ArrayList<Constraint> constraintsToDrop = New.arrayList(); if (constraints != null) { for (int i = 0, size = constraints.size(); i < size; i++) { Constraint constraint = constraints.get(i); HashSet<Column> columns = constraint.getReferencedColumns(this); if (!columns.contains(col)) { continue; } if (columns.size() == 1) { constraintsToDrop.add(constraint); } else { throw DbException.get(ErrorCode.COLUMN_IS_REFERENCED_1, constraint.getSQL()); } } } ArrayList<Index> indexesToDrop = New.arrayList(); ArrayList<Index> indexes = getIndexes(); if (indexes != null) { for (int i = 0, size = indexes.size(); i < size; i++) { Index index = indexes.get(i); if (index.getCreateSQL() == null) { continue; } if (index.getColumnIndex(col) < 0) { continue; } if (index.getColumns().length == 1) { indexesToDrop.add(index); } else { throw DbException.get(ErrorCode.COLUMN_IS_REFERENCED_1, index.getSQL()); } } } for (Constraint c : constraintsToDrop) { session.getDatabase().removeSchemaObject(session, c); } for (Index i : indexesToDrop) { // the index may already have been dropped when dropping the constraint if (getIndexes().contains(i)) { session.getDatabase().removeSchemaObject(session, i); } } }
/** * Add all objects that this table depends on to the hash set. * * @param dependencies the current set of dependencies */ public void addDependencies(HashSet<DbObject> dependencies) { if (dependencies.contains(this)) { // avoid endless recursion return; } if (sequences != null) { for (Sequence s : sequences) { dependencies.add(s); } } ExpressionVisitor visitor = ExpressionVisitor.getDependenciesVisitor(dependencies); if (columns != null) for (Column col : columns) { col.isEverything(visitor); } if (constraints != null) { for (Constraint c : constraints) { c.isEverything(visitor); } } dependencies.add(this); }
@Override public ResultInterface query(int maxrows) { session.getUser().checkAdmin(); reset(); Database db = session.getDatabase(); if (schemaNames != null) { for (String schemaName : schemaNames) { Schema schema = db.findSchema(schemaName); if (schema == null) { throw DbException.get(ErrorCode.SCHEMA_NOT_FOUND_1, schemaName); } } } try { result = createResult(); deleteStore(); openOutput(); if (out != null) { buffer = new byte[Constants.IO_BUFFER_SIZE]; } if (settings) { for (Setting setting : db.getAllSettings()) { if (setting.getName().equals(SetTypes.getTypeName(SetTypes.CREATE_BUILD))) { // don't add CREATE_BUILD to the script // (it is only set when creating the database) continue; } add(setting.getCreateSQL(), false); } } if (out != null) { add("", true); } for (User user : db.getAllUsers()) { add(user.getCreateSQL(passwords), false); } for (Role role : db.getAllRoles()) { add(role.getCreateSQL(true), false); } for (Schema schema : db.getAllSchemas()) { if (excludeSchema(schema)) { continue; } add(schema.getCreateSQL(), false); } for (UserDataType datatype : db.getAllUserDataTypes()) { if (drop) { add(datatype.getDropSQL(), false); } add(datatype.getCreateSQL(), false); } for (SchemaObject obj : db.getAllSchemaObjects(DbObject.CONSTANT)) { if (excludeSchema(obj.getSchema())) { continue; } Constant constant = (Constant) obj; add(constant.getCreateSQL(), false); } final ArrayList<Table> tables = db.getAllTablesAndViews(false); // sort by id, so that views are after tables and views on views // after the base views Collections.sort( tables, new Comparator<Table>() { @Override public int compare(Table t1, Table t2) { return t1.getId() - t2.getId(); } }); // Generate the DROP XXX ... IF EXISTS for (Table table : tables) { if (excludeSchema(table.getSchema())) { continue; } if (excludeTable(table)) { continue; } if (table.isHidden()) { continue; } table.lock(session, false, false); String sql = table.getCreateSQL(); if (sql == null) { // null for metadata tables continue; } if (drop) { add(table.getDropSQL(), false); } } for (SchemaObject obj : db.getAllSchemaObjects(DbObject.FUNCTION_ALIAS)) { if (excludeSchema(obj.getSchema())) { continue; } if (drop) { add(obj.getDropSQL(), false); } add(obj.getCreateSQL(), false); } for (UserAggregate agg : db.getAllAggregates()) { if (drop) { add(agg.getDropSQL(), false); } add(agg.getCreateSQL(), false); } for (SchemaObject obj : db.getAllSchemaObjects(DbObject.SEQUENCE)) { if (excludeSchema(obj.getSchema())) { continue; } Sequence sequence = (Sequence) obj; if (drop) { add(sequence.getDropSQL(), false); } add(sequence.getCreateSQL(), false); } // Generate CREATE TABLE and INSERT...VALUES int count = 0; for (Table table : tables) { if (excludeSchema(table.getSchema())) { continue; } if (excludeTable(table)) { continue; } if (table.isHidden()) { continue; } table.lock(session, false, false); String createTableSql = table.getCreateSQL(); if (createTableSql == null) { // null for metadata tables continue; } final String tableType = table.getTableType(); add(createTableSql, false); final ArrayList<Constraint> constraints = table.getConstraints(); if (constraints != null) { for (Constraint constraint : constraints) { if (Constraint.PRIMARY_KEY.equals(constraint.getConstraintType())) { add(constraint.getCreateSQLWithoutIndexes(), false); } } } if (Table.TABLE.equals(tableType)) { if (table.canGetRowCount()) { String rowcount = "-- " + table.getRowCountApproximation() + " +/- SELECT COUNT(*) FROM " + table.getSQL(); add(rowcount, false); } if (data) { count = generateInsertValues(count, table); } } final ArrayList<Index> indexes = table.getIndexes(); for (int j = 0; indexes != null && j < indexes.size(); j++) { Index index = indexes.get(j); if (!index.getIndexType().getBelongsToConstraint()) { add(index.getCreateSQL(), false); } } } if (tempLobTableCreated) { add("DROP TABLE IF EXISTS SYSTEM_LOB_STREAM", true); add("CALL SYSTEM_COMBINE_BLOB(-1)", true); add("DROP ALIAS IF EXISTS SYSTEM_COMBINE_CLOB", true); add("DROP ALIAS IF EXISTS SYSTEM_COMBINE_BLOB", true); tempLobTableCreated = false; } // Generate CREATE CONSTRAINT ... final ArrayList<SchemaObject> constraints = db.getAllSchemaObjects(DbObject.CONSTRAINT); Collections.sort( constraints, new Comparator<SchemaObject>() { @Override public int compare(SchemaObject c1, SchemaObject c2) { return ((Constraint) c1).compareTo((Constraint) c2); } }); for (SchemaObject obj : constraints) { if (excludeSchema(obj.getSchema())) { continue; } Constraint constraint = (Constraint) obj; if (excludeTable(constraint.getTable())) { continue; } if (constraint.getTable().isHidden()) { continue; } if (!Constraint.PRIMARY_KEY.equals(constraint.getConstraintType())) { add(constraint.getCreateSQLWithoutIndexes(), false); } } // Generate CREATE TRIGGER ... for (SchemaObject obj : db.getAllSchemaObjects(DbObject.TRIGGER)) { if (excludeSchema(obj.getSchema())) { continue; } TriggerObject trigger = (TriggerObject) obj; if (excludeTable(trigger.getTable())) { continue; } add(trigger.getCreateSQL(), false); } // Generate GRANT ... for (Right right : db.getAllRights()) { Table table = right.getGrantedTable(); if (table != null) { if (excludeSchema(table.getSchema())) { continue; } if (excludeTable(table)) { continue; } } add(right.getCreateSQL(), false); } // Generate COMMENT ON ... for (Comment comment : db.getAllComments()) { add(comment.getCreateSQL(), false); } if (out != null) { out.close(); } } catch (IOException e) { throw DbException.convertIOException(e, getFileName()); } finally { closeIO(); } result.done(); LocalResult r = result; reset(); return r; }
/** * Try to execute the statement. * * @return the update count */ private int tryUpdate() { if (!transactional) { session.commit(true); } Database db = session.getDatabase(); Table table = getSchema().getTableOrView(session, tableName); if (getSchema().findConstraint(session, constraintName) != null) { if (ifNotExists) { return 0; } throw DbException.get(ErrorCode.CONSTRAINT_ALREADY_EXISTS_1, constraintName); } session.getUser().checkRight(table, Right.ALL); db.lockMeta(session); table.lock(session, true, true); Constraint constraint; switch (type) { case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY: { IndexColumn.mapColumns(indexColumns, table); index = table.findPrimaryKey(); ArrayList<Constraint> constraints = table.getConstraints(); for (int i = 0; constraints != null && i < constraints.size(); i++) { Constraint c = constraints.get(i); if (Constraint.PRIMARY_KEY.equals(c.getConstraintType())) { throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY); } } if (index != null) { // if there is an index, it must match with the one declared // we don't test ascending / descending IndexColumn[] pkCols = index.getIndexColumns(); if (pkCols.length != indexColumns.length) { throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY); } for (int i = 0; i < pkCols.length; i++) { if (pkCols[i].column != indexColumns[i].column) { throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY); } } } if (index == null) { IndexType indexType = IndexType.createPrimaryKey(table.isPersistIndexes(), primaryKeyHash); String indexName = table.getSchema().getUniqueIndexName(session, table, Constants.PREFIX_PRIMARY_KEY); int id = getObjectId(); try { index = table.addIndex(session, indexName, id, indexColumns, indexType, true, null); } finally { getSchema().freeUniqueName(indexName); } } index.getIndexType().setBelongsToConstraint(true); int constraintId = getObjectId(); String name = generateConstraintName(table); ConstraintUnique pk = new ConstraintUnique(getSchema(), constraintId, name, table, true); pk.setColumns(indexColumns); pk.setIndex(index, true); constraint = pk; break; } case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_UNIQUE: { IndexColumn.mapColumns(indexColumns, table); boolean isOwner = false; if (index != null && canUseUniqueIndex(index, table, indexColumns)) { isOwner = true; index.getIndexType().setBelongsToConstraint(true); } else { index = getUniqueIndex(table, indexColumns); if (index == null) { index = createIndex(table, indexColumns, true); isOwner = true; } } int id = getObjectId(); String name = generateConstraintName(table); ConstraintUnique unique = new ConstraintUnique(getSchema(), id, name, table, false); unique.setColumns(indexColumns); unique.setIndex(index, isOwner); constraint = unique; break; } case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_CHECK: { int id = getObjectId(); String name = generateConstraintName(table); ConstraintCheck check = new ConstraintCheck(getSchema(), id, name, table); TableFilter filter = new TableFilter(session, table, null, false, null); checkExpression.mapColumns(filter, 0); checkExpression = checkExpression.optimize(session); check.setExpression(checkExpression); check.setTableFilter(filter); constraint = check; if (checkExisting) { check.checkExistingData(session); } break; } case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_REFERENTIAL: { Table refTable = refSchema.getTableOrView(session, refTableName); session.getUser().checkRight(refTable, Right.ALL); if (!refTable.canReference()) { throw DbException.get( ErrorCode.FEATURE_NOT_SUPPORTED_1, "Reference " + refTable.getSQL()); } boolean isOwner = false; IndexColumn.mapColumns(indexColumns, table); if (index != null && canUseIndex(index, table, indexColumns)) { isOwner = true; index.getIndexType().setBelongsToConstraint(true); } else { index = getIndex(table, indexColumns); if (index == null) { index = createIndex(table, indexColumns, false); isOwner = true; } } if (refIndexColumns == null) { Index refIdx = refTable.getPrimaryKey(); refIndexColumns = refIdx.getIndexColumns(); } else { IndexColumn.mapColumns(refIndexColumns, refTable); } if (refIndexColumns.length != indexColumns.length) { throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH); } boolean isRefOwner = false; if (refIndex != null && refIndex.getTable() == refTable && canUseIndex(refIndex, refTable, refIndexColumns)) { isRefOwner = true; refIndex.getIndexType().setBelongsToConstraint(true); } else { refIndex = null; } if (refIndex == null) { refIndex = getIndex(refTable, refIndexColumns); if (refIndex == null) { refIndex = createIndex(refTable, refIndexColumns, true); isRefOwner = true; } } int id = getObjectId(); String name = generateConstraintName(table); ConstraintReferential ref = new ConstraintReferential(getSchema(), id, name, table); ref.setColumns(indexColumns); ref.setIndex(index, isOwner); ref.setRefTable(refTable); ref.setRefColumns(refIndexColumns); ref.setRefIndex(refIndex, isRefOwner); if (checkExisting) { ref.checkExistingData(session); } constraint = ref; refTable.addConstraint(constraint); ref.setDeleteAction(deleteAction); ref.setUpdateAction(updateAction); break; } default: throw DbException.throwInternalError("type=" + type); } // parent relationship is already set with addConstraint constraint.setComment(comment); if (table.isTemporary() && !table.isGlobalTemporary()) { session.addLocalTempTableConstraint(constraint); } else { db.addSchemaObject(session, constraint); } table.addConstraint(constraint); return 0; }