提交 dd2140c5 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Try to find matching UNIQUE constraint for FOREIGN KEY constraint

上级 67e7b4bd
......@@ -2014,9 +2014,31 @@ public class MetaTable extends Table {
if (indexColumns == null) {
continue;
}
ConstraintUnique referenced;
if (constraintType == Constraint.Type.REFERENTIAL) {
referenced = lookupUniqueForReferential((ConstraintReferential) constraint);
} else {
referenced = null;
}
for (int i = 0; i < indexColumns.length; i++) {
IndexColumn indexColumn = indexColumns[i];
String ordinalPosition = Integer.toString(i + 1);
String positionInUniqueConstraint;
if (constraintType == Constraint.Type.REFERENTIAL) {
positionInUniqueConstraint = ordinalPosition;
if (referenced != null) {
Column c = ((ConstraintReferential) constraint).getRefColumns()[i].column;
IndexColumn[] refColumns = referenced.getColumns();
for (int j = 0; j < refColumns.length; j++) {
if (refColumns[j].column.equals(c)) {
positionInUniqueConstraint = Integer.toString(j + 1);
break;
}
}
}
} else {
positionInUniqueConstraint = null;
}
add(rows,
// CONSTRAINT_CATALOG
catalog,
......@@ -2035,7 +2057,7 @@ public class MetaTable extends Table {
// ORDINAL_POSITION
ordinalPosition,
// POSITION_IN_UNIQUE_CONSTRAINT
(constraintType == Constraint.Type.REFERENTIAL ? ordinalPosition : null)
positionInUniqueConstraint
);
}
}
......@@ -2051,7 +2073,13 @@ public class MetaTable extends Table {
if (hideTable(table, session)) {
continue;
}
Index index = constraint.getUniqueIndex();
// Should be referenced unique constraint, but H2 uses indexes instead.
// So try to find matching unique constraint first and there is no such
// constraint use index name to return something.
SchemaObject unique = lookupUniqueForReferential(constraint);
if (unique == null) {
unique = constraint.getUniqueIndex();
}
add(rows,
// CONSTRAINT_CATALOG
catalog,
......@@ -2062,10 +2090,9 @@ public class MetaTable extends Table {
// UNIQUE_CONSTRAINT_CATALOG
catalog,
// UNIQUE_CONSTRAINT_SCHEMA
identifier(index.getSchema().getName()),
identifier(unique.getSchema().getName()),
// UNIQUE_CONSTRAINT_NAME
// Should be name of referenced unique constraint, but H2 uses indexes instead
index.getName(),
unique.getName(),
// MATCH_OPTION
"NONE",
// UPDATE_RULE
......@@ -2097,6 +2124,19 @@ public class MetaTable extends Table {
}
}
private static ConstraintUnique lookupUniqueForReferential(ConstraintReferential referential) {
Table table = referential.getRefTable();
for (Constraint c : table.getConstraints()) {
if (c.getConstraintType() == Constraint.Type.UNIQUE) {
ConstraintUnique unique = (ConstraintUnique) c;
if (unique.getReferencedColumns(table).equals(referential.getReferencedColumns(table))) {
return unique;
}
}
}
return null;
}
@Override
public void removeRow(Session session, Row row) {
throw DbException.getUnsupportedException("META");
......
......@@ -18,6 +18,9 @@ CREATE TABLE T2(C1 INT, C2 INT, C3 INT, C4 INT);
ALTER TABLE T2 ADD CONSTRAINT FK_1 FOREIGN KEY (C3, C4) REFERENCES T1(C1, C3) ON DELETE SET NULL;
> ok
ALTER TABLE T2 ADD CONSTRAINT FK_2 FOREIGN KEY (C3, C4) REFERENCES T1(C4, C3) ON UPDATE CASCADE ON DELETE SET DEFAULT;
> ok
ALTER TABLE T2 ADD CONSTRAINT CH_1 CHECK C4 > 0;
> ok
......@@ -35,7 +38,8 @@ SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME, IS_DEFERRABLE, INITIALLY_DE
> U_1 UNIQUE T1 NO NO
> CH_1 CHECK T2 NO NO
> FK_1 FOREIGN KEY T2 NO NO
> rows (ordered): 4
> FK_2 FOREIGN KEY T2 NO NO
> rows (ordered): 5
SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE LIMIT 0;
> CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION POSITION_IN_UNIQUE_CONSTRAINT
......@@ -53,21 +57,34 @@ SELECT CONSTRAINT_NAME, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, POSITION_IN_U
> U_1 T1 C4 2 null
> FK_1 T2 C3 1 1
> FK_1 T2 C4 2 2
> rows (ordered): 6
> FK_2 T2 C3 1 2
> FK_2 T2 C4 2 1
> rows (ordered): 8
SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS LIMIT 0;
> CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE
> ------------------ ----------------- --------------- ------------------------- ------------------------ ---------------------- ------------ ----------- -----------
> rows: 0
-- H2 returns name of the index istead of name of the referenced constraint as UNIQUE_CONSTRAINT_NAME
-- H2 may return name of the index istead of name of the referenced constraint as UNIQUE_CONSTRAINT_NAME
SELECT CONSTRAINT_NAME, SUBSTRING(UNIQUE_CONSTRAINT_NAME, 0, 11) AS UCN_PART, MATCH_OPTION, UPDATE_RULE, DELETE_RULE FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE CONSTRAINT_CATALOG = DATABASE() AND CONSTRAINT_SCHEMA = SCHEMA() AND UNIQUE_CONSTRAINT_CATALOG = DATABASE() AND UNIQUE_CONSTRAINT_SCHEMA = SCHEMA()
ORDER BY CONSTRAINT_NAME, UNIQUE_CONSTRAINT_NAME;
> CONSTRAINT_NAME UCN_PART MATCH_OPTION UPDATE_RULE DELETE_RULE
> --------------- ----------- ------------ ----------- -----------
> FK_1 FK_1_INDEX_ NONE RESTRICT SET NULL
> rows (ordered): 1
> FK_2 U_1 NONE CASCADE SET DEFAULT
> rows (ordered): 2
SELECT U1.TABLE_NAME T1, U1.COLUMN_NAME C1, U2.TABLE_NAME T2, U2.COLUMN_NAME C2
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE U1 JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC ON U1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE U2 ON RC.UNIQUE_CONSTRAINT_NAME = U2.CONSTRAINT_NAME AND U1.POSITION_IN_UNIQUE_CONSTRAINT = U2.ORDINAL_POSITION
WHERE U1.CONSTRAINT_NAME = 'FK_2' ORDER BY U1.COLUMN_NAME;
> T1 C1 T2 C2
> -- -- -- --
> T2 C3 T1 C4
> T2 C4 T1 C3
> rows (ordered): 2
DROP TABLE T2;
> ok
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论