From 9dce9661935518741e71bba815d020796e31cc53 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 12 Jun 2020 15:51:11 +0200 Subject: [PATCH] [jOOQ/jOOQ#10204] Refactor CatalogMetaImpl - CatalogMetaImpl should use FilteredMeta - SchemaMetaImpl and TableMetaImpl are no longer necessary - [jOOQ/jOOQ#10274] [jOOQ/jOOQ#7172] Some equals methods were adapted - Fixed check constraints and identities - Create copies of PK and UK using Internal API - Support FKs referencing UKs - [jOOQ/jOOQ#10276] Don't export FKs pointing outside of a schema subset --- .../java/org/jooq/impl/CatalogMetaImpl.java | 117 +++++++++------- .../org/jooq/impl/CatalogMetaProvider.java | 2 +- jOOQ/src/main/java/org/jooq/impl/DDL.java | 2 +- .../java/org/jooq/impl/DefaultDSLContext.java | 6 +- jOOQ/src/main/java/org/jooq/impl/Diff.java | 4 +- .../main/java/org/jooq/impl/FilteredMeta.java | 64 +++++++-- .../java/org/jooq/impl/MigrationImpl.java | 5 - .../java/org/jooq/impl/SchemaMetaImpl.java | 126 ------------------ .../org/jooq/impl/SchemaMetaProvider.java | 2 +- .../java/org/jooq/impl/TableFieldImpl.java | 5 +- .../main/java/org/jooq/impl/TableImpl.java | 7 +- .../java/org/jooq/impl/TableMetaProvider.java | 2 +- jOOQ/src/main/java/org/jooq/impl/Tools.java | 2 + 13 files changed, 137 insertions(+), 207 deletions(-) delete mode 100644 jOOQ/src/main/java/org/jooq/impl/SchemaMetaImpl.java diff --git a/jOOQ/src/main/java/org/jooq/impl/CatalogMetaImpl.java b/jOOQ/src/main/java/org/jooq/impl/CatalogMetaImpl.java index 01f79428d9..988517dfad 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CatalogMetaImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/CatalogMetaImpl.java @@ -37,27 +37,30 @@ */ package org.jooq.impl; +import static org.jooq.impl.Tools.EMPTY_CATALOG; + import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.jooq.Catalog; import org.jooq.Configuration; -import org.jooq.Domain; +import org.jooq.Meta; import org.jooq.Schema; -import org.jooq.Sequence; import org.jooq.Table; -import org.jooq.UniqueKey; /** * @author Lukas Eder */ +@SuppressWarnings("serial") final class CatalogMetaImpl extends AbstractMeta { - private static final long serialVersionUID = 7582210274970452691L; - private final Catalog[] catalogs; + private static final long serialVersionUID = 7582210274970452691L; + private final Catalog[] catalogs; - CatalogMetaImpl(Configuration configuration, Catalog[] catalogs) { + private CatalogMetaImpl(Configuration configuration, Catalog[] catalogs) { super(configuration); this.catalogs = catalogs; @@ -68,59 +71,73 @@ final class CatalogMetaImpl extends AbstractMeta { return Arrays.asList(catalogs); } - @Override - final List getSchemas0() { - List result = new ArrayList<>(); - - for (Catalog catalog : catalogs) - result.addAll(catalog.getSchemas()); - - return result; + static final Meta filterCatalogs(Configuration configuration, Catalog[] catalogs) { + return filterCatalogs0(configuration, catalogs, new HashSet<>(Arrays.asList(catalogs))); } - @Override - final List> getDomains0() { - List> result = new ArrayList<>(); - - for (Catalog catalog : catalogs) - for (Schema schema : catalog.getSchemas()) - result.addAll(schema.getDomains()); - - return super.getDomains0(); + static final Meta filterCatalogs(Configuration configuration, Set catalogs) { + return filterCatalogs0(configuration, catalogs.toArray(EMPTY_CATALOG), catalogs); } - @Override - final List> getTables0() { - List> result = new ArrayList<>(); - - for (Catalog catalog : catalogs) - for (Schema schema : catalog.getSchemas()) - result.addAll(schema.getTables()); - - return result; + private static final Meta filterCatalogs0(Configuration configuration, Catalog[] array, Set set) { + return new CatalogMetaImpl(configuration, array).filterCatalogs(new Predicate() { + @Override + public boolean test(Catalog catalog) { + return set.contains(catalog); + } + }); } - @Override - final List> getSequences0() { - List> result = new ArrayList<>(); - - for (Catalog catalog : catalogs) - for (Schema schema : catalog.getSchemas()) - result.addAll(schema.getSequences()); - - return result; + static final Meta filterSchemas(Configuration configuration, Schema[] schemas) { + return filterSchemas(configuration, new HashSet<>(Arrays.asList(schemas))); } - @Override - final List> getPrimaryKeys0() { - List> result = new ArrayList<>(); - for (Catalog catalog : catalogs) - for (Schema schema : catalog.getSchemas()) - for (Table table : schema.getTables()) - if (table.getPrimaryKey() != null) - result.add(table.getPrimaryKey()); + static final Meta filterSchemas(Configuration configuration, Set schemas) { - return result; + // TODO: Some schemas may belong to another catalog + Catalog defaultCatalog = new CatalogImpl("") { + @Override + public List getSchemas() { + return new ArrayList<>(schemas); + } + }; + + Set c = new HashSet<>(); + for (Schema schema : schemas) + c.add(schema.getCatalog() != null ? schema.getCatalog() : defaultCatalog); + + return filterCatalogs(configuration, c).filterSchemas(new Predicate() { + @Override + public boolean test(Schema schema) { + return schemas.contains(schema); + } + }); + } + + static final Meta filterTables(Configuration configuration, Table[] tables) { + return filterTables(configuration, new HashSet<>(Arrays.asList(tables))); + } + + static final Meta filterTables(Configuration configuration, Set> tables) { + + // TODO: Some tables may belong to another schema + Schema defaultSchema = new SchemaImpl("") { + @Override + public List> getTables() { + return new ArrayList>(tables); + } + }; + + Set s = new HashSet<>(); + for (Table table : tables) + s.add(table.getSchema() != null ? table.getSchema() : defaultSchema); + + return filterSchemas(configuration, s).filterTables(new Predicate>() { + @Override + public boolean test(Table table) { + return tables.contains(table); + } + }); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/CatalogMetaProvider.java b/jOOQ/src/main/java/org/jooq/impl/CatalogMetaProvider.java index 103fc49c77..029b5a5bac 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CatalogMetaProvider.java +++ b/jOOQ/src/main/java/org/jooq/impl/CatalogMetaProvider.java @@ -60,6 +60,6 @@ public class CatalogMetaProvider implements MetaProvider { @Override public Meta provide() { - return new CatalogMetaImpl(configuration, catalogs); + return CatalogMetaImpl.filterCatalogs(configuration, catalogs); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/DDL.java b/jOOQ/src/main/java/org/jooq/impl/DDL.java index a49eadfd46..67339f890e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DDL.java +++ b/jOOQ/src/main/java/org/jooq/impl/DDL.java @@ -197,7 +197,7 @@ final class DDL { return s3.constraints(constraints); } - private final Query createTable(Table table) { + final Query createTable(Table table) { return createTable(table, constraints(table)); } diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java index 5f71bafad8..fbebb5cbd5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java @@ -428,17 +428,17 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri @Override public Meta meta(Catalog... catalogs) { - return new CatalogMetaImpl(configuration(), catalogs); + return CatalogMetaImpl.filterCatalogs(configuration(), catalogs); } @Override public Meta meta(Schema... schemas) { - return new SchemaMetaImpl(configuration(), schemas); + return CatalogMetaImpl.filterSchemas(configuration(), schemas); } @Override public Meta meta(Table... tables) { - return new TableMetaImpl(configuration(), tables); + return CatalogMetaImpl.filterTables(configuration(), tables); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/Diff.java b/jOOQ/src/main/java/org/jooq/impl/Diff.java index bd2afd302f..d5983c1e8b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Diff.java +++ b/jOOQ/src/main/java/org/jooq/impl/Diff.java @@ -277,7 +277,9 @@ final class Diff { private final Create> CREATE_TABLE = new Create>() { @Override public void create(DiffResult r, Table t) { - r.queries.addAll(Arrays.asList(ctx.ddl(t, exportConf).queries())); + + // [#10204] [#10276] DSLContext.ddl(Table) doesn't produce foreign keys + r.queries.addAll(Arrays.asList(ddl.queries(t).queries())); } }; diff --git a/jOOQ/src/main/java/org/jooq/impl/FilteredMeta.java b/jOOQ/src/main/java/org/jooq/impl/FilteredMeta.java index a038f234f8..bb6c372952 100644 --- a/jOOQ/src/main/java/org/jooq/impl/FilteredMeta.java +++ b/jOOQ/src/main/java/org/jooq/impl/FilteredMeta.java @@ -42,9 +42,11 @@ import java.util.Collections; import java.util.List; import org.jooq.Catalog; +import org.jooq.Check; import org.jooq.Domain; import org.jooq.Field; import org.jooq.ForeignKey; +import org.jooq.Identity; import org.jooq.Index; import org.jooq.Meta; import org.jooq.QueryPart; @@ -319,10 +321,11 @@ final class FilteredMeta extends AbstractMeta { private transient List indexes; private transient List> keys; private transient UniqueKey primaryKey; + private transient Identity identity; private transient List> references; private FilteredTable(FilteredSchema schema, Table delegate) { - super(delegate.getQualifiedName(), schema, null, null, DSL.comment(delegate.getComment())); + super(delegate.getQualifiedName(), schema, null, null, DSL.comment(delegate.getComment()), delegate.getOptions()); this.delegate = delegate; @@ -344,22 +347,38 @@ final class FilteredMeta extends AbstractMeta { } @Override + @SuppressWarnings("unchecked") public final List> getKeys() { if (keys == null) { keys = new ArrayList<>(); for (UniqueKey key : delegate.getKeys()) - keys.add(key); + keys.add(key(key)); UniqueKey pk = delegate.getPrimaryKey(); if (pk != null) if (primaryKeyFilter == null || primaryKeyFilter.test(pk)) - primaryKey = pk; + primaryKey = key(pk); + + Identity id = delegate.getIdentity(); + if (id != null) + identity = Internal.createIdentity(this, (TableField) field(id.getField())); } return Collections.unmodifiableList(keys); } + @SuppressWarnings("unchecked") + private final UniqueKey key(UniqueKey key) { + TableField[] fields1 = key.getFieldsArray(); + TableField[] fields2 = new TableField[fields1.length]; + + for (int i = 0; i < fields2.length; i++) + fields2[i] = (TableField) field(fields1[i]); + + return Internal.createUniqueKey(this, key.getName(), fields2, key.enforced()); + } + @Override public final UniqueKey getPrimaryKey() { getKeys(); @@ -372,25 +391,44 @@ final class FilteredMeta extends AbstractMeta { if (references == null) { references = new ArrayList<>(); - for (ForeignKey key : delegate.getReferences()) { - Table table = lookupTable(key.getKey().getTable()); + fkLoop: + for (ForeignKey fk : delegate.getReferences()) { + Table table = lookupTable(fk.getKey().getTable()); - // TODO: Support FKs referencing UKs - if (table != null && table.getPrimaryKey() != null) { - TableField[] fields1 = key.getFieldsArray(); - TableField[] fields2 = new TableField[fields1.length]; + if (table == null) + continue fkLoop; - for (int i = 0; i < fields2.length; i++) - fields2[i] = (TableField) field(fields1[i]); + UniqueKey uk = null; + for (UniqueKey k : table.getKeys()) + if (k.equals(fk.getKey())) + uk = k; - references.add(Internal.createForeignKey(table.getPrimaryKey(), this, key.getName(), fields2)); - } + if (uk == null) + continue fkLoop; + + TableField[] fields1 = fk.getFieldsArray(); + TableField[] fields2 = new TableField[fields1.length]; + + for (int i = 0; i < fields2.length; i++) + fields2[i] = (TableField) field(fields1[i]); + + references.add(Internal.createForeignKey(uk, this, fk.getName(), fields2, fk.enforced())); } } return Collections.unmodifiableList(references); } + @Override + public final Identity getIdentity() { + return identity; + } + + @Override + 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? diff --git a/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java b/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java index 55d676bebe..abd284d895 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java @@ -518,11 +518,6 @@ final class MigrationImpl extends AbstractScope implements Migration { super(alias, null, aliased, parameters, DSL.comment("The migration log of jOOQ Migrations.")); } - @Override - public Schema getSchema() { - return new SchemaImpl(""); - } - @Override public Identity getIdentity() { return Internal.createIdentity(JOOQ_MIGRATIONS_CHANGELOG, JOOQ_MIGRATIONS_CHANGELOG.ID); diff --git a/jOOQ/src/main/java/org/jooq/impl/SchemaMetaImpl.java b/jOOQ/src/main/java/org/jooq/impl/SchemaMetaImpl.java deleted file mode 100644 index 873a5172d3..0000000000 --- a/jOOQ/src/main/java/org/jooq/impl/SchemaMetaImpl.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Other licenses: - * ----------------------------------------------------------------------------- - * Commercial licenses for this work are available. These replace the above - * ASL 2.0 and offer limited warranties, support, maintenance, and commercial - * database integrations. - * - * For more information, please visit: http://www.jooq.org/licenses - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */ -package org.jooq.impl; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import org.jooq.Catalog; -import org.jooq.Configuration; -import org.jooq.Domain; -import org.jooq.Schema; -import org.jooq.Sequence; -import org.jooq.Table; -import org.jooq.UniqueKey; - -/** - * @author Lukas Eder - */ -final class SchemaMetaImpl extends AbstractMeta { - - private static final long serialVersionUID = -505810795492145873L; - private final Schema[] schemas; - - SchemaMetaImpl(Configuration configuration, Schema[] schemas) { - super(configuration); - - this.schemas = schemas; - } - - @Override - final List getCatalogs0() { - Set result = new LinkedHashSet<>(); - - for (Schema schema : schemas) - if (schema.getCatalog() != null) - result.add(schema.getCatalog()); - - return new ArrayList<>(result); - } - - @Override - final List getSchemas0() { - return Collections.unmodifiableList(Arrays.asList(schemas)); - } - - @Override - final List> getDomains0() { - List> result = new ArrayList<>(); - - for (Schema schema : schemas) - result.addAll(schema.getDomains()); - - return result; - } - - @Override - final List> getTables0() { - List> result = new ArrayList<>(); - - for (Schema schema : schemas) - result.addAll(schema.getTables()); - - return result; - } - - @Override - final List> getSequences0() { - List> result = new ArrayList<>(); - - for (Schema schema : schemas) - result.addAll(schema.getSequences()); - - return result; - } - - @Override - final List> getPrimaryKeys0() { - List> result = new ArrayList<>(); - - for (Schema schema : schemas) - for (Table table : schema.getTables()) - if (table.getPrimaryKey() != null) - result.add(table.getPrimaryKey()); - - return result; - } -} diff --git a/jOOQ/src/main/java/org/jooq/impl/SchemaMetaProvider.java b/jOOQ/src/main/java/org/jooq/impl/SchemaMetaProvider.java index bc8f2ff161..9152632e97 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SchemaMetaProvider.java +++ b/jOOQ/src/main/java/org/jooq/impl/SchemaMetaProvider.java @@ -60,6 +60,6 @@ public class SchemaMetaProvider implements MetaProvider { @Override public Meta provide() { - return new SchemaMetaImpl(configuration, schemas); + return CatalogMetaImpl.filterSchemas(configuration, schemas); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java b/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java index 1c26baab67..370b4d32f8 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java @@ -51,7 +51,6 @@ import org.jooq.Name; import org.jooq.Record; import org.jooq.Table; import org.jooq.TableField; -import org.jooq.tools.StringUtils; /** * A common base type for table fields. @@ -112,9 +111,7 @@ final class TableFieldImpl extends AbstractField impleme // rather expensive implementation of AbstractQueryPart.equals() if (that instanceof TableField) { TableField other = (TableField) that; - return - StringUtils.equals(getTable(), other.getTable()) && - StringUtils.equals(getName(), other.getName()); + return getQualifiedName().equals(other.getQualifiedName()); } return super.equals(that); diff --git a/jOOQ/src/main/java/org/jooq/impl/TableImpl.java b/jOOQ/src/main/java/org/jooq/impl/TableImpl.java index edeaddb093..579d9222f4 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TableImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/TableImpl.java @@ -364,7 +364,12 @@ public class TableImpl extends AbstractTable { if (that instanceof TableImpl) { TableImpl other = (TableImpl) that; return - StringUtils.equals(getSchema(), other.getSchema()) && + + // [#7172] [#10274] Cannot use getQualifiedName() yet here + StringUtils.equals( + getSchema() == null ? "" : getSchema().getName(), + other.getSchema() == null ? "" : other.getSchema().getName() + ) && StringUtils.equals(getName(), other.getName()) && Arrays.equals(parameters, other.parameters); } diff --git a/jOOQ/src/main/java/org/jooq/impl/TableMetaProvider.java b/jOOQ/src/main/java/org/jooq/impl/TableMetaProvider.java index e81bf3d9e8..53a431e7f5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TableMetaProvider.java +++ b/jOOQ/src/main/java/org/jooq/impl/TableMetaProvider.java @@ -60,6 +60,6 @@ public class TableMetaProvider implements MetaProvider { @Override public Meta provide() { - return new TableMetaImpl(configuration, tables); + return CatalogMetaImpl.filterTables(configuration, tables); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 1d79ea4ecd..3fe4bf1bb7 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -299,6 +299,7 @@ final class Tools { // ------------------------------------------------------------------------ static final byte[] EMPTY_BYTE = {}; + static final Catalog[] EMPTY_CATALOG = {}; static final Check[] EMPTY_CHECK = {}; static final Clause[] EMPTY_CLAUSE = {}; static final Collection[] EMPTY_COLLECTION = {}; @@ -313,6 +314,7 @@ final class Tools { static final QueryPart[] EMPTY_QUERYPART = {}; static final Record[] EMPTY_RECORD = {}; static final Row[] EMPTY_ROW = {}; + static final Schema[] EMTPY_SCHEMA = {}; static final SortField[] EMPTY_SORTFIELD = {}; static final String[] EMPTY_STRING = {}; static final Table[] EMPTY_TABLE = {};