diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractKey.java b/jOOQ/src/main/java/org/jooq/impl/AbstractKey.java index 94fcb7218e..47c893bcc0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractKey.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractKey.java @@ -43,11 +43,13 @@ import java.util.List; import org.jooq.Constraint; import org.jooq.ConstraintEnforcementStep; import org.jooq.Context; +import org.jooq.ForeignKey; import org.jooq.Key; import org.jooq.Name; import org.jooq.Record; import org.jooq.Table; import org.jooq.TableField; +import org.jooq.UniqueKey; /** * Common base class for Key's @@ -133,8 +135,16 @@ abstract class AbstractKey extends AbstractNamed implements Ke return true; if (obj == null) return false; - if (getClass() != obj.getClass()) + if (!(obj instanceof AbstractKey)) return false; + if (this instanceof ForeignKey) { + if (!(obj instanceof ForeignKey)) + return false; + } + else if (this instanceof UniqueKey) { + if (!(obj instanceof UniqueKey)) + return false; + } AbstractKey other = (AbstractKey) obj; if (!getQualifiedName().equals(other.getQualifiedName())) return false; diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractMeta.java b/jOOQ/src/main/java/org/jooq/impl/AbstractMeta.java index 8da824e148..9edb52af4f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractMeta.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractMeta.java @@ -52,12 +52,14 @@ import org.jooq.Catalog; import org.jooq.Configuration; import org.jooq.DDLExportConfiguration; import org.jooq.Domain; +import org.jooq.ForeignKey; import org.jooq.Index; import org.jooq.Meta; import org.jooq.Name; import org.jooq.Named; import org.jooq.Queries; import org.jooq.Query; +import org.jooq.Record; import org.jooq.Schema; import org.jooq.Sequence; import org.jooq.Table; @@ -514,6 +516,42 @@ abstract class AbstractMeta extends AbstractScope implements Meta, Serializable return InformationSchemaExport.exportCatalogs(configuration(), getCatalogs()); } + final Table lookupTable(Table table) { + + // TODO: This is a re-occurring pattern in Meta implementations. Should we have a more generic way to look up objects in a Catalog/Schema? + Catalog catalog = getCatalog(table.getCatalog().getName()); + if (catalog == null) + return null; + + Schema schema = catalog.getSchema(table.getSchema().getName()); + if (schema == null) + return null; + + return schema.getTable(table.getName()); + } + + final UniqueKey lookupKey(Table in, UniqueKey uk) { + for (UniqueKey k : in.getKeys()) + + // [#10279] [#10281] Cannot use Key::equals here, because that is + // name-based. 1) The name is irrelevant for this lookup, 2) some + // key implementations (e.g. MetaPrimaryKey for H2) don't produce + // the correct key name, but the index name. + if (k.getFields().equals(uk.getFields())) + return k; + + return null; + } + + final UniqueKey lookupUniqueKey(ForeignKey fk) { + Table table = lookupTable(fk.getKey().getTable()); + + if (table == null) + return null; + + return lookupKey(table, fk.getKey()); + } + @Override public int hashCode() { return ddl().hashCode(); diff --git a/jOOQ/src/main/java/org/jooq/impl/DetachedMeta.java b/jOOQ/src/main/java/org/jooq/impl/DetachedMeta.java index 62c214c878..19f14d48f8 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DetachedMeta.java +++ b/jOOQ/src/main/java/org/jooq/impl/DetachedMeta.java @@ -45,15 +45,11 @@ import java.util.List; import org.jooq.Catalog; import org.jooq.Check; -import org.jooq.Comment; -import org.jooq.DataType; import org.jooq.Domain; import org.jooq.Field; import org.jooq.ForeignKey; import org.jooq.Index; import org.jooq.Meta; -import org.jooq.Name; -import org.jooq.Package; import org.jooq.Record; import org.jooq.Schema; import org.jooq.Sequence; @@ -87,7 +83,7 @@ final class DetachedMeta extends AbstractMeta { private final void resolveReferences() { for (Catalog catalog : getCatalogs()) - ((DetachedCatalog) catalog).resolveReferences(this); + ((DetachedCatalog) catalog).resolveReferences(); } @Override @@ -95,32 +91,27 @@ final class DetachedMeta extends AbstractMeta { List result = new ArrayList<>(); for (Catalog catalog : delegate.getCatalogs()) - result.add(DetachedCatalog.copyOf(catalog)); + result.add(new DetachedCatalog(catalog)); return result; } - private static class DetachedCatalog extends CatalogImpl { - private static final long serialVersionUID = 7979890261252183486L; + private class DetachedCatalog extends CatalogImpl { + private static final long serialVersionUID = 7979890261252183486L; + private final List schemas; - private final List schemas = new ArrayList<>(); + DetachedCatalog(Catalog catalog) { + super(catalog.getQualifiedName(), catalog.getCommentPart()); - private DetachedCatalog(String name, String comment) { - super(name, comment); - } - - private final void resolveReferences(Meta meta) { - for (Schema schema : schemas) - ((DetachedSchema) schema).resolveReferences(meta); - } - - static DetachedCatalog copyOf(Catalog catalog) { - DetachedCatalog result = new DetachedCatalog(catalog.getName(), catalog.getComment()); + schemas = new ArrayList<>(); for (Schema schema : catalog.getSchemas()) - result.schemas.add(DetachedSchema.copyOf(schema, result)); + schemas.add(new DetachedSchema(this, schema)); + } - return result; + private final void resolveReferences() { + for (DetachedSchema schema : schemas) + schema.resolveReferences(); } @Override @@ -129,36 +120,35 @@ final class DetachedMeta extends AbstractMeta { } } - private static class DetachedSchema extends SchemaImpl { - private static final long serialVersionUID = -95755926444275258L; + private class DetachedSchema extends SchemaImpl { + private static final long serialVersionUID = -95755926444275258L; - private final List> domains = new ArrayList<>(); - private final List> tables = new ArrayList<>(); - private final List> sequences = new ArrayList<>(); - private final List> udts = new ArrayList<>(); + private final List> domains; + private final List> tables; + private final List> sequences; + private final List> udts; - private DetachedSchema(String name, Catalog owner, String comment) { - super(name, owner, comment); - } + DetachedSchema(DetachedCatalog catalog, Schema schema) { + super(schema.getQualifiedName(), catalog, schema.getCommentPart()); - static DetachedSchema copyOf(Schema schema, Catalog owner) { - DetachedSchema result = new DetachedSchema(schema.getName(), owner, schema.getComment()); + domains = new ArrayList<>(); + tables = new ArrayList<>(); + sequences = new ArrayList<>(); + udts = new ArrayList<>(); for (Domain domain : schema.getDomains()) - result.domains.add(DetachedDomain.copyOf(domain, result)); + domains.add(new DetachedDomain<>(this, domain)); for (Table table : schema.getTables()) - result.tables.add(DetachedTable.copyOf(table, result)); + tables.add(new DetachedTable<>(this, table)); for (Sequence sequence : schema.getSequences()) - result.sequences.add(DetachedSequence.copyOf(sequence, result)); + sequences.add(new DetachedSequence<>(this, sequence)); for (UDT udt : schema.getUDTs()) - result.udts.add(DetachedUDT.copyOf(udt, result)); - - return result; + udts.add(new DetachedUDT<>(this, udt)); } - final void resolveReferences(Meta meta) { - for (Table table : tables) - ((DetachedTable) table).resolveReferences(meta); + final void resolveReferences() { + for (DetachedTable table : tables) + table.resolveReferences(); } @Override @@ -182,28 +172,57 @@ final class DetachedMeta extends AbstractMeta { } } - private static class DetachedDomain extends DomainImpl { + private class DetachedDomain extends DomainImpl { private static final long serialVersionUID = -1607062195966296849L; - private DetachedDomain(Schema schema, Name name, DataType type, Check... checks) { - super(schema, name, type, checks); - } - - static DetachedDomain copyOf(Domain domain, Schema owner) { - return new DetachedDomain<>(owner, domain.getQualifiedName(), domain.getDataType(), domain.getChecks().toArray(EMPTY_CHECK)); + DetachedDomain(DetachedSchema schema, Domain domain) { + super(schema, domain.getQualifiedName(), domain.getDataType(), domain.getChecks().toArray(EMPTY_CHECK)); } } - private static class DetachedTable extends TableImpl { + private class DetachedTable extends TableImpl { private static final long serialVersionUID = -6070726881709997500L; - private final List indexes = new ArrayList<>(); - private final List> keys = new ArrayList<>(); + private final List indexes; + private final List> uniqueKeys; private UniqueKey primaryKey; - private final List> references = new ArrayList<>(); + private final List> foreignKeys; + private final List> checks; - private DetachedTable(Name name, Schema owner, Comment comment) { - super(name, owner, null, null, comment); + DetachedTable(DetachedSchema schema, Table table) { + super(table.getQualifiedName(), schema, null, null, table.getCommentPart(), table.getOptions()); + + indexes = new ArrayList<>(); + uniqueKeys = new ArrayList<>(); + foreignKeys = new ArrayList<>(); + checks = new ArrayList<>(); + + for (Field field : table.fields()) + DetachedTable.createField(field.getUnqualifiedName(), field.getDataType(), this, field.getComment()); + + for (Index index : table.getIndexes()) { + List> indexFields = index.getFields(); + SortField[] copiedFields = new SortField[indexFields.size()]; + + for (int i = 0; i < indexFields.size(); i++) { + SortField field = indexFields.get(i); + copiedFields[i] = field(field.getName()).sort(field.getOrder()); + // [#9009] TODO NULLS FIRST / NULLS LAST + } + + indexes.add(Internal.createIndex(index.getQualifiedName(), this, copiedFields, index.getUnique())); + } + + for (UniqueKey uk : table.getKeys()) + uniqueKeys.add(Internal.createUniqueKey(this, uk.getQualifiedName(), fields(uk.getFieldsArray()), uk.enforced())); + + UniqueKey pk = table.getPrimaryKey(); + for (UniqueKey uk : uniqueKeys) + if (uk.equals(pk)) + primaryKey = uk; + + foreignKeys.addAll(table.getReferences()); + checks.addAll(table.getChecks()); } @SuppressWarnings("unchecked") @@ -213,51 +232,28 @@ final class DetachedMeta extends AbstractMeta { // TODO: [#9456] This auxiliary method should not be necessary // We should be able to call TableLike.fields instead. TableField[] result = new TableField[tableFields.length]; + for (int i = 0; i < tableFields.length; i++) result[i] = (TableField) field(tableFields[i].getName()); + return result; } - static DetachedTable copyOf(Table table, Schema owner) { - DetachedTable result = new DetachedTable<>(table.getUnqualifiedName(), owner, table.getCommentPart()); - - for (Field field : table.fields()) - DetachedTable.createField(field.getName(), field.getDataType(), result, field.getComment()); - for (Index index : table.getIndexes()) { - List> indexFields = index.getFields(); - SortField[] copiedFields = new SortField[indexFields.size()]; - for (int i = 0; i < indexFields.size(); i++) { - SortField field = indexFields.get(i); - copiedFields[i] = result.field(field.getName()).sort(field.getOrder()); - // [#9009] TODO NULLS FIRST / NULLS LAST - } - result.indexes.add(org.jooq.impl.Internal.createIndex(index.getName(), result, copiedFields, index.getUnique())); - } - for (UniqueKey key : table.getKeys()) - result.keys.add(org.jooq.impl.Internal.createUniqueKey(result, key.getName(), result.fields(key.getFieldsArray()))); - UniqueKey pk = table.getPrimaryKey(); - if (pk != null) - result.primaryKey = org.jooq.impl.Internal.createUniqueKey(result, pk.getName(), result.fields(pk.getFieldsArray())); - result.references.addAll(table.getReferences()); - return result; - } - - final void resolveReferences(Meta meta) { + final void resolveReferences() { // TODO: Is there a better way than temporarily keeping the wrong // ReferenceImpl in this list until we "know better"? - for (int i = 0; i < references.size(); i++) { - ForeignKey ref = references.get(i); - Name name = ref.getKey().getTable().getQualifiedName(); - Table table = resolveTable(name, meta); - UniqueKey pk = table == null ? null : table.getPrimaryKey(); - references.set(i, org.jooq.impl.Internal.createForeignKey(pk, this, ref.getName(), fields(ref.getFieldsArray()))); - } - } + for (int i = 0; i < foreignKeys.size(); i++) { + ForeignKey fk = foreignKeys.get(i); - private final Table resolveTable(Name tableName, Meta meta) { - List> list = meta.getTables(tableName); - return list.isEmpty() ? null : list.get(0); + foreignKeys.set(i, org.jooq.impl.Internal.createForeignKey( + lookupUniqueKey(fk), + this, + fk.getQualifiedName(), + fields(fk.getFieldsArray()), + fk.enforced()) + ); + } } @Override @@ -267,7 +263,7 @@ final class DetachedMeta extends AbstractMeta { @Override public final List> getKeys() { - return Collections.unmodifiableList(keys); + return Collections.unmodifiableList(uniqueKeys); } @Override @@ -277,35 +273,39 @@ final class DetachedMeta extends AbstractMeta { @Override public final List> getReferences() { - return Collections.unmodifiableList(references); + return Collections.unmodifiableList(foreignKeys); + } + + @Override + public final List> getChecks() { + return Collections.unmodifiableList(checks); } } - private static class DetachedSequence extends SequenceImpl { + private class DetachedSequence extends SequenceImpl { private static final long serialVersionUID = -1607062195966296849L; - private DetachedSequence(String name, Schema owner, DataType dataType) { - super(name, owner, dataType); - } - - static DetachedSequence copyOf(Sequence sequence, Schema owner) { - return new DetachedSequence<>(sequence.getName(), owner, sequence.getDataType()); + DetachedSequence(DetachedSchema schema, Sequence sequence) { + super( + sequence.getQualifiedName(), + schema, + sequence.getDataType(), + false, + sequence.getStartWith(), + sequence.getIncrementBy(), + sequence.getMinvalue(), + sequence.getMaxvalue(), + sequence.getCycle(), + sequence.getCache() + ); } } - private static class DetachedUDT> extends UDTImpl { + private class DetachedUDT> extends UDTImpl { private static final long serialVersionUID = -5732449514562314202L; - private DetachedUDT(String name, Schema owner, Package package_, boolean synthetic) { - super(name, owner, package_, synthetic); - } - - static DetachedUDT copyOf(UDT udt, Schema owner) { - Package package_ = null; - - - - return new DetachedUDT<>(udt.getName(), owner, package_, udt.isSynthetic()); + DetachedUDT(DetachedSchema schema, UDT udt) { + super(udt.getName(), schema, udt.isSynthetic()); } } } \ No newline at end of file diff --git a/jOOQ/src/main/java/org/jooq/impl/FilteredMeta.java b/jOOQ/src/main/java/org/jooq/impl/FilteredMeta.java index 5bea9c10b2..f410c13428 100644 --- a/jOOQ/src/main/java/org/jooq/impl/FilteredMeta.java +++ b/jOOQ/src/main/java/org/jooq/impl/FilteredMeta.java @@ -393,15 +393,7 @@ final class FilteredMeta extends AbstractMeta { fkLoop: for (ForeignKey fk : delegate.getReferences()) { - Table table = lookupTable(fk.getKey().getTable()); - - if (table == null) - continue fkLoop; - - UniqueKey uk = null; - for (UniqueKey k : table.getKeys()) - if (k.equals(fk.getKey())) - uk = k; + UniqueKey uk = lookupUniqueKey(fk); if (uk == null) continue fkLoop; @@ -429,19 +421,5 @@ final class FilteredMeta extends AbstractMeta { public final List> getChecks() { return delegate.getChecks(); } - - private final Table lookupTable(Table table) { - - // TODO: This is a re-occurring pattern in Meta implementations. Should we have a more generic way to look up objects in a Catalog/Schema? - Catalog catalog = getCatalog(); - if (catalog == null) - return null; - - Schema schema = catalog.getSchema(table.getSchema().getName()); - if (schema == null) - return null; - - return schema.getTable(table.getName()); - } } } diff --git a/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java b/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java index 9b64ca3164..0ad3da8d89 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/MetaImpl.java @@ -57,7 +57,6 @@ import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; @@ -71,8 +70,7 @@ import org.jooq.Catalog; import org.jooq.Condition; import org.jooq.Configuration; import org.jooq.ConnectionCallable; -import org.jooq.Constraint; -import org.jooq.Context; +import org.jooq.ConstraintEnforcementStep; import org.jooq.DataType; import org.jooq.Field; import org.jooq.ForeignKey; @@ -904,36 +902,15 @@ final class MetaImpl extends AbstractMeta { } } - private final class MetaPrimaryKey extends AbstractNamed implements UniqueKey { + private final class MetaPrimaryKey extends AbstractKey implements UniqueKey { /** * Generated UID */ private static final long serialVersionUID = 6997258619475953490L; - private final Table pkTable; - private final TableField[] pkFields; - MetaPrimaryKey(Table table, String pkName, TableField[] fields) { - super(pkName == null ? null : DSL.name(pkName), null); - - this.pkTable = table; - this.pkFields = fields; - } - - @Override - public final Table getTable() { - return pkTable; - } - - @Override - public final List> getFields() { - return Collections.unmodifiableList(Arrays.asList(pkFields)); - } - - @Override - public final TableField[] getFieldsArray() { - return pkFields.clone(); + super(table, pkName == null ? null : DSL.name(pkName), fields, true); } @Override @@ -941,18 +918,13 @@ final class MetaImpl extends AbstractMeta { return true; } - @Override - public final boolean enforced() { - return true; - } - @Override @SuppressWarnings("unchecked") public final List> getReferences() { Result result = meta(new MetaFunction() { @Override public Result run(DatabaseMetaData meta) throws SQLException { - ResultSet rs = meta.getExportedKeys(null, pkTable.getSchema().getName(), pkTable.getName()); + ResultSet rs = meta.getExportedKeys(null, getTable().getSchema().getName(), getTable().getName()); return dsl().fetch( rs, @@ -1009,17 +981,12 @@ final class MetaImpl extends AbstractMeta { } @Override - public final Constraint constraint() { + final ConstraintEnforcementStep constraint0() { if (isPrimary()) return DSL.constraint(getName()).primaryKey(getFieldsArray()); else return DSL.constraint(getName()).unique(getFieldsArray()); } - - @Override - public final void accept(Context ctx) { - ctx.visit(getUnqualifiedName()); - } } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/SequenceImpl.java b/jOOQ/src/main/java/org/jooq/impl/SequenceImpl.java index 3a5e14a61e..2ab71f76ff 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SequenceImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SequenceImpl.java @@ -107,16 +107,16 @@ public class SequenceImpl extends AbstractTypedNamed implem } SequenceImpl( - Name name, - Schema schema, - DataType type, - boolean nameIsPlainSQL, - Field startWith, - Field incrementBy, - Field minvalue, - Field maxvalue, - boolean cycle, - Field cache + Name name, + Schema schema, + DataType type, + boolean nameIsPlainSQL, + Field startWith, + Field incrementBy, + Field minvalue, + Field maxvalue, + boolean cycle, + Field cache ) { super(qualify(schema, name), CommentImpl.NO_COMMENT, type);