From 0eb5a0801664991959f21a973e5b1f3fbf07f73d Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 10 Jan 2025 15:14:31 +0100 Subject: [PATCH] [jOOQ/jOOQ#16567] Restore caching of resolvedType in AbstractTypedElementDefinition --- .../java/org/jooq/codegen/JavaGenerator.java | 6 ++++++ .../java/org/jooq/meta/AbstractDatabase.java | 12 ++++------- .../org/jooq/meta/AbstractDefinition.java | 21 +++++++++++++++++++ .../meta/AbstractTypedElementDefinition.java | 14 ++++++++----- .../jooq/meta/DefaultJavaTypeResolver.java | 5 +++++ .../main/java/org/jooq/meta/Definition.java | 9 ++++++++ .../java/org/jooq/meta/JavaTypeResolver.java | 10 +++++++++ 7 files changed, 64 insertions(+), 13 deletions(-) diff --git a/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java b/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java index 308231c8b6..663b677f7d 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java @@ -78,6 +78,7 @@ import java.sql.Date; import java.sql.Time; import java.sql.Timestamp; import java.time.Instant; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -11605,6 +11606,11 @@ public class JavaGenerator extends AbstractGenerator { private boolean ignoreImports(Mode m) { return m == POJO || m == RECORD; } + + @Override + public Object cacheKey() { + return new AbstractMap.SimpleImmutableEntry<>(out.file(), mode != null ? mode : Mode.DEFAULT); + } } protected JavaTypeResolver resolver(JavaWriter out) { diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java index 26c54915cc..b550262092 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java @@ -736,10 +736,8 @@ public abstract class AbstractDatabase implements Database { return pattern.matcher(definition.getName()).matches() || pattern.matcher(definition.getQualifiedName()).matches(); - List parts = Arrays.asList(definition.getQualifiedNamePart().parts()); - - for (int i = parts.size() - 1; i >= 0; i--) - if (pattern.matcher(DSL.name(parts.subList(i, parts.size()).toArray(new Name[0])).unquotedName().toString()).matches()) + for (String partiallyQualifiedName : definition.getPartiallyQualifiedNames()) + if (pattern.matcher(partiallyQualifiedName).matches()) return true; return false; @@ -753,10 +751,8 @@ public abstract class AbstractDatabase implements Database { return set.contains(definition.getName()) || set.contains(definition.getQualifiedName()); - List parts = Arrays.asList(definition.getQualifiedNamePart().parts()); - - for (int i = parts.size() - 1; i >= 0; i--) - if (set.contains(DSL.name(parts.subList(i, parts.size()).toArray(new Name[0])).unquotedName().toString())) + for (String partiallyQualifiedName : definition.getPartiallyQualifiedNames()) + if (set.contains(partiallyQualifiedName)) return true; return false; diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDefinition.java b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDefinition.java index cb5437f97a..0c4ea85a98 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDefinition.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDefinition.java @@ -47,12 +47,15 @@ import static org.jooq.tools.StringUtils.isEmpty; import java.sql.Connection; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.jooq.DSLContext; import org.jooq.Name; // ... import org.jooq.SQLDialect; +import org.jooq.impl.DSL; +import org.jooq.impl.DefaultConfiguration; import org.jooq.meta.jaxb.CommentType; import org.jooq.tools.StringUtils; @@ -80,6 +83,7 @@ public abstract class AbstractDefinition implements Definition { private transient Name qualifiedInputNamePart; private transient Name qualifiedOutputNamePart; private transient Integer hashCode; + private transient List partiallyQualifiedNames; public AbstractDefinition(Database database, SchemaDefinition schema, String name) { this(database, schema, name, null); @@ -307,6 +311,23 @@ public abstract class AbstractDefinition implements Definition { return qualifiedOutputNamePart; } + // [#16567] Avoid re-creating rendering contexts every time we render a name for matching purposes. + private static final DSLContext CTX = new DefaultConfiguration().dsl(); + + @Override + public final List getPartiallyQualifiedNames() { + if (partiallyQualifiedNames == null) { + partiallyQualifiedNames = new ArrayList<>(); + + List parts = Arrays.asList(getQualifiedNamePart().parts()); + + for (int i = parts.size() - 1; i >= 0; i--) + partiallyQualifiedNames.add(CTX.render(DSL.name(parts.subList(i, parts.size()).toArray(new Name[0])).unquotedName())); + } + + return partiallyQualifiedNames; + } + @Override public final Database getDatabase() { return database; diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractTypedElementDefinition.java b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractTypedElementDefinition.java index c4b85a114d..34fd79ce57 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractTypedElementDefinition.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractTypedElementDefinition.java @@ -46,7 +46,9 @@ import static org.jooq.tools.StringUtils.isEmpty; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -77,11 +79,12 @@ implements TypedElementDefinition { - private static final JooqLogger log = JooqLogger.getLogger(AbstractTypedElementDefinition.class); - private static final Pattern LENGTH_PRECISION_SCALE_PATTERN = Pattern.compile("[\\w\\s]+(?:\\(\\s*?(\\d+)\\s*?\\)|\\(\\s*?(\\d+)\\s*?,\\s*?(\\d+)\\s*?\\))"); + private static final JooqLogger log = JooqLogger.getLogger(AbstractTypedElementDefinition.class); + private static final Pattern LENGTH_PRECISION_SCALE_PATTERN = Pattern.compile("[\\w\\s]+(?:\\(\\s*?(\\d+)\\s*?\\)|\\(\\s*?(\\d+)\\s*?,\\s*?(\\d+)\\s*?\\))"); - private final DataTypeDefinition definedType; - private transient DataTypeDefinition type; + private final DataTypeDefinition definedType; + private transient DataTypeDefinition type; + private Map resolvedType; public AbstractTypedElementDefinition(T container, String name, int position, DataTypeDefinition definedType, String comment) { this(container, name, position, definedType, comment, null); @@ -91,6 +94,7 @@ implements super(container, name, position, comment, overload); this.definedType = definedType; + this.resolvedType = new HashMap<>(); } @Override @@ -103,7 +107,7 @@ implements @Override public DataTypeDefinition getType(JavaTypeResolver resolver) { - return mapDefinedType(container, this, definedType, resolver); + return resolvedType.computeIfAbsent(resolver.cacheKey(), key -> mapDefinedType(container, this, definedType, resolver)); } @Override diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/DefaultJavaTypeResolver.java b/jOOQ-meta/src/main/java/org/jooq/meta/DefaultJavaTypeResolver.java index b8537e0be2..acc8f1a26b 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/DefaultJavaTypeResolver.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/DefaultJavaTypeResolver.java @@ -79,4 +79,9 @@ final class DefaultJavaTypeResolver implements JavaTypeResolver { public T resolveDefinedType(Supplier supplier) { return supplier.get(); } + + @Override + public Object cacheKey() { + return ""; + } } \ No newline at end of file diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/Definition.java b/jOOQ-meta/src/main/java/org/jooq/meta/Definition.java index 77288f205f..d9c9db6125 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/Definition.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/Definition.java @@ -43,6 +43,7 @@ import java.util.List; import org.jooq.Name; // ... import org.jooq.meta.jaxb.CommentType; +import org.jooq.meta.jaxb.ForcedType; import org.jooq.meta.jaxb.SyntheticObjectsType; /** @@ -151,6 +152,14 @@ public interface Definition { */ Name getQualifiedOutputNamePart(); + /** + * @return A list of partially qualified names for this definition, going + * from {@link #getName()} (unqualified) to + * {@link #getQualifiedName()} (fully qualified), mostly used for + * caching purposes when looking up {@link ForcedType}. + */ + List getPartiallyQualifiedNames(); + /** * @return The overload suffix if applicable */ diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/JavaTypeResolver.java b/jOOQ-meta/src/main/java/org/jooq/meta/JavaTypeResolver.java index 489718ca36..74059be8b4 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/JavaTypeResolver.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/JavaTypeResolver.java @@ -103,4 +103,14 @@ public interface JavaTypeResolver { * which may not need imports in some output modes. */ T resolveDefinedType(Supplier supplier); + + /** + * Get a cache key for this resolver, which can be used for caching calls to + * {@link #resolve(DataTypeDefinition)}. + *

+ * It can be safely assumed that consecutive calls to + * {@link #resolve(DataTypeDefinition)} will produce the same result, + * considering the cache key. + */ + Object cacheKey(); }