From 007d25fb769438f1eb66ab8ccaf4b5d459a5978c Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 6 Dec 2019 17:48:12 +0100 Subject: [PATCH] [jOOQ/jOOQ#8528] Cache interpreted objects for better bi-directionality --- .../java/org/jooq/impl/DDLInterpreter.java | 293 ++++++++++++++---- jOOQ/src/main/java/org/jooq/impl/Diff.java | 7 + 2 files changed, 238 insertions(+), 62 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/DDLInterpreter.java b/jOOQ/src/main/java/org/jooq/impl/DDLInterpreter.java index 0c89f00693..c0cf1e3161 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DDLInterpreter.java +++ b/jOOQ/src/main/java/org/jooq/impl/DDLInterpreter.java @@ -54,6 +54,7 @@ import static org.jooq.tools.StringUtils.defaultIfNull; import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -100,15 +101,24 @@ import org.jooq.tools.JooqLogger; @SuppressWarnings("serial") final class DDLInterpreter { - private static final JooqLogger log = JooqLogger.getLogger(DDLInterpreter.class); + private static final JooqLogger log = JooqLogger.getLogger(DDLInterpreter.class); - private final Configuration configuration; - private final InterpreterNameLookupCaseSensitivity caseSensitivity; - private final Locale locale; - private final Map catalogs = new LinkedHashMap<>(); - private final MutableCatalog defaultCatalog; - private final MutableSchema defaultSchema; - private MutableSchema currentSchema; + private final Configuration configuration; + private final InterpreterNameLookupCaseSensitivity caseSensitivity; + private final Locale locale; + private final Map catalogs = new LinkedHashMap<>(); + private final MutableCatalog defaultCatalog; + private final MutableSchema defaultSchema; + private MutableSchema currentSchema; + + // Caches + private final Map interpretedCatalogs = new HashMap<>(); + private final Map interpretedSchemas = new HashMap<>(); + private final Map interpretedTables = new HashMap<>(); + private final Map> interpretedUniqueKeys = new HashMap<>(); + private final Map> interpretedForeignKeys = new HashMap<>(); + private final Map interpretedIndexes = new HashMap<>(); + private final Map interpretedSequences = new HashMap<>(); DDLInterpreter(Configuration configuration) { this.configuration = configuration; @@ -129,7 +139,7 @@ final class DDLInterpreter { List result = new ArrayList<>(); for (MutableCatalog catalog : catalogs.values()) - result.add(catalog.new InterpretedCatalog()); + result.add(catalog.interpretedCatalog()); return result; } @@ -141,6 +151,8 @@ final class DDLInterpreter { // ------------------------------------------------------------------------- final void accept(Query query) { + invalidateCaches(); + if (log.isDebugEnabled()) log.debug(query); @@ -200,6 +212,16 @@ final class DDLInterpreter { throw unsupportedQuery(query); } + private final void invalidateCaches() { + interpretedCatalogs.clear(); + interpretedSchemas.clear(); + interpretedTables.clear(); + interpretedUniqueKeys.clear(); + interpretedForeignKeys.clear(); + interpretedIndexes.clear(); + interpretedSequences.clear(); + } + private final void accept0(CreateSchemaImpl query) { Schema schema = query.$schema(); @@ -1246,6 +1268,15 @@ final class DDLInterpreter { name(name); } + Name qualifiedName() { + MutableNamed parent = parent(); + + if (parent == null) + return name; + else + return parent.qualifiedName().append(name); + } + UnqualifiedName name() { return name; } @@ -1281,6 +1312,7 @@ final class DDLInterpreter { } } + abstract MutableNamed parent(); abstract void drop(); @Override @@ -1301,6 +1333,21 @@ final class DDLInterpreter { schemas.clear(); } + @Override + final MutableNamed parent() { + return null; + } + + final InterpretedCatalog interpretedCatalog() { + Name qualifiedName = qualifiedName(); + InterpretedCatalog result = interpretedCatalogs.get(qualifiedName); + + if (result == null) + interpretedCatalogs.put(qualifiedName, result = new InterpretedCatalog()); + + return result; + } + private final class InterpretedCatalog extends CatalogImpl { InterpretedCatalog() { super(MutableCatalog.this.name(), MutableCatalog.this.comment()); @@ -1311,7 +1358,7 @@ final class DDLInterpreter { List result = new ArrayList<>(schemas.size()); for (MutableSchema schema : schemas) - result.add(schema.new InterpretedSchema(this)); + result.add(schema.interpretedSchema()); return result; } @@ -1336,6 +1383,21 @@ final class DDLInterpreter { sequences.clear(); } + @Override + final MutableNamed parent() { + return catalog; + } + + final InterpretedSchema interpretedSchema() { + Name qualifiedName = qualifiedName(); + InterpretedSchema result = interpretedSchemas.get(qualifiedName); + + if (result == null) + interpretedSchemas.put(qualifiedName, result = new InterpretedSchema(catalog.interpretedCatalog())); + + return result; + } + final boolean isEmpty() { return tables.isEmpty(); } @@ -1358,7 +1420,7 @@ final class DDLInterpreter { List> result = new ArrayList<>(tables.size()); for (MutableTable table : tables) - result.add(table.new InterpretedTable(this)); + result.add(table.interpretedTable()); return result; } @@ -1368,7 +1430,7 @@ final class DDLInterpreter { List> result = new ArrayList<>(sequences.size()); for (MutableSequence sequence : sequences) - result.add(sequence.new InterpretedSequence(this)); + result.add(sequence.interpretedSequence()); return result; } @@ -1405,6 +1467,21 @@ final class DDLInterpreter { fields.clear(); } + @Override + final MutableNamed parent() { + return schema; + } + + final InterpretedTable interpretedTable() { + Name qualifiedName = qualifiedName(); + InterpretedTable result = interpretedTables.get(qualifiedName); + + if (result == null) + interpretedTables.put(qualifiedName, result = new InterpretedTable(schema.interpretedSchema())); + + return result; + } + boolean hasReferencingTables() { if (primaryKey != null && !primaryKey.referencingKeys.isEmpty()) return true; @@ -1484,7 +1561,9 @@ final class DDLInterpreter { @Override public final UniqueKey getPrimaryKey() { - return interpretedKey(MutableTable.this.primaryKey); + return MutableTable.this.primaryKey != null + ? MutableTable.this.primaryKey.interpretedKey() + : null; } @Override @@ -1496,7 +1575,7 @@ final class DDLInterpreter { result.add(pk); for (MutableUniqueKey uk : MutableTable.this.uniqueKeys) - result.add(interpretedKey(uk)); + result.add(uk.interpretedKey()); return result; } @@ -1506,7 +1585,7 @@ final class DDLInterpreter { List> result = new ArrayList<>(); for (MutableForeignKey fk : MutableTable.this.foreignKeys) - result.add(interpretedKey(fk)); + result.add(fk.interpretedKey()); return result; } @@ -1526,56 +1605,10 @@ final class DDLInterpreter { List result = new ArrayList<>(); for (MutableIndex i : MutableTable.this.indexes) - result.add(interpretedIndex(i)); + result.add(i.interpretedIndex()); return result; } - - @SuppressWarnings("unchecked") - private final UniqueKey interpretedKey(MutableUniqueKey key) { - if (key == null) - return null; - - TableField[] f = new TableField[key.keyFields.size()]; - - // TODO: Refactor these constructor calls - InterpretedTable t = key.keyTable.new InterpretedTable(key.keyTable.schema.new InterpretedSchema(key.keyTable.schema.catalog.new InterpretedCatalog())); - - for (int i = 0; i < f.length; i++) - f[i] = (TableField) t.field(key.keyFields.get(i).name()); - - // TODO: Cache these? - return new UniqueKeyImpl(t, key.name().last(), f); - } - - @SuppressWarnings("unchecked") - private final ForeignKey interpretedKey(MutableForeignKey key) { - if (key == null) - return null; - - TableField[] f = new TableField[key.keyFields.size()]; - - for (int i = 0; i < f.length; i++) - f[i] = (TableField) field(key.keyFields.get(i).name()); - - // TODO: Refactor these constructor calls - // TODO: Cache these? - return new ReferenceImpl<>(key.referencedKey.keyTable.new InterpretedTable((MutableSchema.InterpretedSchema) getSchema()).interpretedKey(key.referencedKey), this, key.name().last(), f); - } - - private final Index interpretedIndex(MutableIndex idx) { - if (idx == null) - return null; - - SortField[] f = new SortField[idx.fields.size()]; - - for (int i = 0; i < f.length; i++) { - MutableSortField msf = idx.fields.get(i); - f[i] = field(msf.name()).sort(msf.sort); - } - - return new IndexImpl(idx.name(), this, f, null, idx.unique); - } } } @@ -1599,6 +1632,21 @@ final class DDLInterpreter { @Override final void drop() {} + @Override + final MutableNamed parent() { + return schema; + } + + final InterpretedSequence interpretedSequence() { + Name qualifiedName = qualifiedName(); + InterpretedSequence result = interpretedSequences.get(qualifiedName); + + if (result == null) + interpretedSequences.put(qualifiedName, result = new InterpretedSequence(schema.interpretedSchema())); + + return result; + } + private final class InterpretedSequence extends SequenceImpl { @SuppressWarnings("unchecked") InterpretedSequence(Schema schema) { @@ -1623,6 +1671,11 @@ final class DDLInterpreter { this.keyTable = table; this.keyFields = fields; } + + @Override + final MutableNamed parent() { + return keyTable; + } } private final class MutableCheck extends MutableNamed { @@ -1638,6 +1691,21 @@ final class DDLInterpreter { @Override final void drop() {} + + @Override + final MutableNamed parent() { + return table; + } + + @Override + final Name qualifiedName() { + + // TODO: Find a better way to identify unnamed constraints. + if (name().empty()) + return super.qualifiedName().append(condition.toString()); + else + return super.qualifiedName(); + } } private final class MutableUniqueKey extends MutableKey { @@ -1652,6 +1720,37 @@ final class DDLInterpreter { // TODO Is this StackOverflowError safe? referencingKeys.clear(); } + + @Override + final Name qualifiedName() { + + // TODO: Find a better way to identify unnamed constraints. + if (name().empty()) + return super.qualifiedName().append(keyFields.toString()); + else + return super.qualifiedName(); + } + + @SuppressWarnings("unchecked") + final UniqueKeyImpl interpretedKey() { + Name qualifiedName = qualifiedName(); + UniqueKeyImpl result = interpretedUniqueKeys.get(qualifiedName); + + if (result == null) { + MutableTable.InterpretedTable t = keyTable.interpretedTable(); + TableField[] f = new TableField[keyFields.size()]; + + for (int i = 0; i < f.length; i++) + f[i] = (TableField) t.field(keyFields.get(i).name()); + + // Add to map before adding bi-directionality to avoid StackOverflowErrors + interpretedUniqueKeys.put(qualifiedName, result = new UniqueKeyImpl<>(t, name().last(), f)); + for (MutableForeignKey referencingKey : referencingKeys) + result.references.add((ForeignKey) referencingKey.interpretedKey()); + } + + return result; + } } private final class MutableForeignKey extends MutableKey { @@ -1679,6 +1778,35 @@ final class DDLInterpreter { final void drop() { this.referencedKey.referencingKeys.remove(this); } + + @Override + final Name qualifiedName() { + + // TODO: Find a better way to identify unnamed constraints. + if (name().empty()) + return super.qualifiedName().append(referencedKey.qualifiedName()); + else + return super.qualifiedName(); + } + + @SuppressWarnings("unchecked") + final ReferenceImpl interpretedKey() { + Name qualifiedName = qualifiedName(); + ReferenceImpl result = interpretedForeignKeys.get(qualifiedName); + + if (result == null) { + MutableTable.InterpretedTable t = keyTable.interpretedTable(); + TableField[] f = new TableField[keyFields.size()]; + + for (int i = 0; i < f.length; i++) + f[i] = (TableField) t.field(keyFields.get(i).name()); + + interpretedForeignKeys.put(qualifiedName, result = new ReferenceImpl<>(referencedKey.interpretedKey(), t, name().last(), f)); + } + + return result; + } + } private final class MutableIndex extends MutableNamed { @@ -1696,6 +1824,37 @@ final class DDLInterpreter { @Override final void drop() {} + + @Override + final MutableNamed parent() { + return table; + } + + @Override + final Name qualifiedName() { + + // TODO: Can we have unnamed indexes? + return super.qualifiedName(); + } + + final Index interpretedIndex() { + Name qualifiedName = qualifiedName(); + Index result = interpretedIndexes.get(qualifiedName); + + if (result == null) { + Table t = table.interpretedTable(); + SortField[] f = new SortField[fields.size()]; + + for (int i = 0; i < f.length; i++) { + MutableSortField msf = fields.get(i); + f[i] = t.field(msf.name()).sort(msf.sort); + } + + interpretedIndexes.put(qualifiedName, result = new IndexImpl(name(), t, f, null, unique)); + } + + return result; + } } private final class MutableField extends MutableNamed { @@ -1711,6 +1870,11 @@ final class DDLInterpreter { @Override final void drop() {} + + @Override + final MutableNamed parent() { + return table; + } } private final class MutableSortField extends MutableNamed { @@ -1726,6 +1890,11 @@ final class DDLInterpreter { @Override final void drop() {} + + @Override + final MutableNamed parent() { + return field.parent(); + } } private final class MutableNamedList extends AbstractList { diff --git a/jOOQ/src/main/java/org/jooq/impl/Diff.java b/jOOQ/src/main/java/org/jooq/impl/Diff.java index 07f030c328..7c3fbc587d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Diff.java +++ b/jOOQ/src/main/java/org/jooq/impl/Diff.java @@ -686,6 +686,13 @@ package org.jooq.impl; + + + + + + +