[jOOQ/jOOQ#8553] Add support for foreign keys referencing unique key
columns in different order than in the unique key definition - Added jOOQ-meta implementation - Added H2Database implementation
This commit is contained in:
parent
8f9c389132
commit
4e140b7062
@ -99,6 +99,15 @@ implements TableDefinition {
|
||||
return getDatabase().getRelations().getUniqueKeys(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final UniqueKeyDefinition getUniqueKey(String name) {
|
||||
for (UniqueKeyDefinition uk : getUniqueKeys())
|
||||
if (uk.getInputName().equals(name))
|
||||
return uk;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<ForeignKeyDefinition> getForeignKeys() {
|
||||
return getDatabase().getRelations().getForeignKeys(this);
|
||||
|
||||
@ -44,18 +44,20 @@ import java.util.Set;
|
||||
|
||||
public class DefaultForeignKeyDefinition extends AbstractConstraintDefinition implements ForeignKeyDefinition {
|
||||
|
||||
private final List<ColumnDefinition> keyColumns;
|
||||
private final UniqueKeyDefinition uniqueKey;
|
||||
private final List<ColumnDefinition> fkColumns;
|
||||
private final List<ColumnDefinition> ukColumns;
|
||||
private final UniqueKeyDefinition uk;
|
||||
|
||||
public DefaultForeignKeyDefinition(SchemaDefinition schema, String name, TableDefinition table, UniqueKeyDefinition uniqueKey) {
|
||||
this(schema, name, table, uniqueKey, true);
|
||||
}
|
||||
|
||||
public DefaultForeignKeyDefinition(SchemaDefinition schema, String name, TableDefinition table, UniqueKeyDefinition uniqueKey, boolean enforced) {
|
||||
public DefaultForeignKeyDefinition(SchemaDefinition schema, String name, TableDefinition table, UniqueKeyDefinition uk, boolean enforced) {
|
||||
super(schema, table, name, enforced);
|
||||
|
||||
this.keyColumns = new ArrayList<>();
|
||||
this.uniqueKey = uniqueKey;
|
||||
this.fkColumns = new ArrayList<>();
|
||||
this.ukColumns = new ArrayList<>();
|
||||
this.uk = uk;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -65,22 +67,22 @@ public class DefaultForeignKeyDefinition extends AbstractConstraintDefinition im
|
||||
|
||||
@Override
|
||||
public List<ColumnDefinition> getKeyColumns() {
|
||||
return keyColumns;
|
||||
return fkColumns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UniqueKeyDefinition getReferencedKey() {
|
||||
return uniqueKey;
|
||||
return uk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDefinition getReferencedTable() {
|
||||
return uniqueKey.getTable();
|
||||
return uk.getTable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ColumnDefinition> getReferencedColumns() {
|
||||
return uniqueKey.getKeyColumns();
|
||||
return ukColumns;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -39,6 +39,7 @@ package org.jooq.meta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
@ -189,14 +190,54 @@ public class DefaultRelations implements Relations {
|
||||
ColumnDefinition foreignKeyColumn,
|
||||
String uniqueKeyName,
|
||||
TableDefinition uniqueKeyTable,
|
||||
boolean enforced) {
|
||||
boolean enforced
|
||||
) {
|
||||
UniqueKeyDefinition uk = uniqueKeys.get(key(uniqueKeyTable, uniqueKeyName));
|
||||
Key key = key(foreignKeyTable, foreignKeyName);
|
||||
|
||||
if (uk == null) {
|
||||
log.info("Ignoring foreign key", uniqueKeyName + " (unique key unavailable)");
|
||||
|
||||
// [#7826] Prevent incomplete keys from being generated
|
||||
if (foreignKeyTable != null) {
|
||||
|
||||
incompleteKeys.add(key);
|
||||
foreignKeys.remove(key);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
addForeignKey(foreignKeyName, foreignKeyTable, foreignKeyColumn, uniqueKeyName, uniqueKeyTable, getNextUkColumn(key, uk), enforced);
|
||||
}
|
||||
|
||||
private Map<Key, Integer> nextUkColumnIndex = new HashMap<>();
|
||||
|
||||
private ColumnDefinition getNextUkColumn(Key key, UniqueKeyDefinition uk) {
|
||||
Integer index = nextUkColumnIndex.get(key);
|
||||
|
||||
if (index == null)
|
||||
nextUkColumnIndex.put(key, index = 0);
|
||||
else
|
||||
nextUkColumnIndex.put(key, index = index + 1);
|
||||
|
||||
return uk.getKeyColumns().get(index);
|
||||
}
|
||||
|
||||
public void addForeignKey(
|
||||
String foreignKeyName,
|
||||
TableDefinition foreignKeyTable,
|
||||
ColumnDefinition foreignKeyColumn,
|
||||
String uniqueKeyName,
|
||||
TableDefinition uniqueKeyTable,
|
||||
ColumnDefinition uniqueKeyColumn,
|
||||
boolean enforced
|
||||
) {
|
||||
// [#2718] Column exclusions may hit foreign key references. Ignore
|
||||
// such foreign keys
|
||||
Key key = key(foreignKeyTable, foreignKeyName);
|
||||
if (foreignKeyColumn == null) {
|
||||
log.info("Ignoring foreign key", foreignKeyColumn + " (column unavailable)");
|
||||
if (foreignKeyColumn == null || uniqueKeyColumn == null) {
|
||||
log.info("Ignoring foreign key", foreignKeyColumn + " referencing " + uniqueKeyColumn + " (column unavailable)");
|
||||
|
||||
// [#7826] Prevent incomplete keys from being generated
|
||||
if (foreignKeyTable != null) {
|
||||
@ -213,11 +254,11 @@ public class DefaultRelations implements Relations {
|
||||
// [#1134] Prevent NPE's when a foreign key references a unique key
|
||||
// from another schema
|
||||
if (uniqueKeyTable == null) {
|
||||
log.info("Ignoring foreign key", foreignKeyName + " (" + foreignKeyColumn + ") referencing " + uniqueKeyName + " references a schema out of scope for jooq-meta: " + uniqueKeyTable);
|
||||
log.info("Ignoring foreign key", foreignKeyName + " (" + foreignKeyColumn + ") referencing " + uniqueKeyName + " (" + uniqueKeyColumn + ") references a schema out of scope for jooq-meta: " + uniqueKeyTable);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("Adding foreign key", foreignKeyName + " (" + foreignKeyColumn + ") referencing " + uniqueKeyName);
|
||||
log.info("Adding foreign key", foreignKeyName + " (" + foreignKeyColumn + ") referencing " + uniqueKeyName + " (" + uniqueKeyColumn + ")");
|
||||
|
||||
ForeignKeyDefinition foreignKey = foreignKeys.get(key);
|
||||
|
||||
@ -226,15 +267,23 @@ public class DefaultRelations implements Relations {
|
||||
|
||||
// If the unique key is not loaded, ignore this foreign key
|
||||
if (uniqueKey != null) {
|
||||
foreignKey = new DefaultForeignKeyDefinition(foreignKeyColumn.getSchema(), foreignKeyName, foreignKeyColumn.getContainer(), uniqueKey, enforced);
|
||||
foreignKeys.put(key, foreignKey);
|
||||
foreignKey = new DefaultForeignKeyDefinition(
|
||||
foreignKeyColumn.getSchema(),
|
||||
foreignKeyName,
|
||||
foreignKeyColumn.getContainer(),
|
||||
uniqueKey,
|
||||
enforced
|
||||
);
|
||||
|
||||
foreignKeys.put(key, foreignKey);
|
||||
uniqueKey.getForeignKeys().add(foreignKey);
|
||||
}
|
||||
}
|
||||
|
||||
if (foreignKey != null)
|
||||
if (foreignKey != null) {
|
||||
foreignKey.getKeyColumns().add(foreignKeyColumn);
|
||||
foreignKey.getReferencedColumns().add(uniqueKeyColumn);
|
||||
}
|
||||
}
|
||||
|
||||
public void addCheckConstraint(TableDefinition table, CheckConstraintDefinition constraint) {
|
||||
|
||||
@ -90,6 +90,11 @@ public interface TableDefinition extends Definition {
|
||||
*/
|
||||
List<UniqueKeyDefinition> getUniqueKeys();
|
||||
|
||||
/**
|
||||
* Get the unique key for this table by name.
|
||||
*/
|
||||
UniqueKeyDefinition getUniqueKey(String name);
|
||||
|
||||
/**
|
||||
* Get the foreign keys for this table.
|
||||
*/
|
||||
|
||||
@ -287,6 +287,7 @@ public class H2Database extends AbstractDatabase {
|
||||
CrossReferences.FKTABLE_NAME,
|
||||
CrossReferences.FKTABLE_SCHEMA,
|
||||
CrossReferences.FKCOLUMN_NAME,
|
||||
CrossReferences.PKCOLUMN_NAME,
|
||||
Constraints.CONSTRAINT_NAME,
|
||||
Constraints.TABLE_NAME,
|
||||
Constraints.CONSTRAINT_SCHEMA)
|
||||
@ -314,6 +315,7 @@ public class H2Database extends AbstractDatabase {
|
||||
String foreignKeyColumn = record.get(CrossReferences.FKCOLUMN_NAME);
|
||||
String uniqueKey = record.get(Constraints.CONSTRAINT_NAME);
|
||||
String uniqueKeyTableName = record.get(Constraints.TABLE_NAME);
|
||||
String uniqueKeyColumn = record.get(CrossReferences.PKCOLUMN_NAME);
|
||||
|
||||
TableDefinition foreignKeyTable = getTable(foreignKeySchema, foreignKeyTableName);
|
||||
TableDefinition uniqueKeyTable = getTable(uniqueKeySchema, uniqueKeyTableName);
|
||||
@ -324,7 +326,9 @@ public class H2Database extends AbstractDatabase {
|
||||
foreignKeyTable,
|
||||
foreignKeyTable.getColumn(foreignKeyColumn),
|
||||
uniqueKey,
|
||||
uniqueKeyTable
|
||||
uniqueKeyTable,
|
||||
uniqueKeyTable.getColumn(uniqueKeyColumn),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user