[jOOQ/jOOQ#16567] Restore caching of resolvedType in AbstractTypedElementDefinition

This commit is contained in:
Lukas Eder 2025-01-10 15:14:31 +01:00
parent d69db14a0f
commit 0eb5a08016
7 changed files with 64 additions and 13 deletions

View File

@ -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) {

View File

@ -736,10 +736,8 @@ public abstract class AbstractDatabase implements Database {
return pattern.matcher(definition.getName()).matches()
|| pattern.matcher(definition.getQualifiedName()).matches();
List<Name> 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<Name> 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;

View File

@ -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<String> 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<String> getPartiallyQualifiedNames() {
if (partiallyQualifiedNames == null) {
partiallyQualifiedNames = new ArrayList<>();
List<Name> 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;

View File

@ -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<T>
{
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<Object, DataTypeDefinition> 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

View File

@ -79,4 +79,9 @@ final class DefaultJavaTypeResolver implements JavaTypeResolver {
public <T> T resolveDefinedType(Supplier<T> supplier) {
return supplier.get();
}
@Override
public Object cacheKey() {
return "";
}
}

View File

@ -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<String> getPartiallyQualifiedNames();
/**
* @return The overload suffix if applicable
*/

View File

@ -103,4 +103,14 @@ public interface JavaTypeResolver {
* which may not need imports in some output modes.
*/
<T> T resolveDefinedType(Supplier<T> supplier);
/**
* Get a cache key for this resolver, which can be used for caching calls to
* {@link #resolve(DataTypeDefinition)}.
* <p>
* It can be safely assumed that consecutive calls to
* {@link #resolve(DataTypeDefinition)} will produce the same result,
* considering the cache key.
*/
Object cacheKey();
}