private Index createIndex(Table t, IndexColumn[] cols, boolean unique) { int indexId = getObjectId(); IndexType indexType; if (unique) { // for unique constraints indexType = IndexType.createUnique(t.isPersistIndexes(), false); } else { // constraints indexType = IndexType.createNonUnique(t.isPersistIndexes()); } indexType.setBelongsToConstraint(true); String prefix = constraintName == null ? "CONSTRAINT" : constraintName; String indexName = t.getSchema().getUniqueIndexName(session, t, prefix + "_INDEX_"); try { return t.addIndex(session, indexName, indexId, cols, indexType, true, null); } finally { getSchema().freeUniqueName(indexName); } }
/** * 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; }