From fcb59a3c01e4a9eea64d138f07b48d2386e917b0 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 21 Nov 2023 09:49:36 +0100 Subject: [PATCH] [jOOQ/jOOQ#13295] Allow for specifying both and / in --- .../java/org/jooq/meta/AbstractDatabase.java | 110 ++++++---------- .../meta/AbstractTypedElementDefinition.java | 121 +++++++++--------- 2 files changed, 98 insertions(+), 133 deletions(-) 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 26592fc57d..faea1ad9c6 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java @@ -1583,85 +1583,49 @@ public abstract class AbstractDatabase implements Database { log.warn("DEPRECATED", "The element in is deprecated. Use instead: " + type); } - if (StringUtils.isBlank(type.getName())) { - if (StringUtils.isBlank(type.getUserType())) { - if (type.getVisibilityModifier() == null - && StringUtils.isBlank(type.getGenerator()) - && !TRUE.equals(type.isAuditInsertTimestamp()) - && !TRUE.equals(type.isAuditInsertUser()) - && !TRUE.equals(type.isAuditUpdateTimestamp()) - && !TRUE.equals(type.isAuditUpdateUser())) { - log.warn("Bad configuration for . Any of , , , , , , , or is required: " + type); + if (StringUtils.isBlank(type.getUserType())) { + if (type.getVisibilityModifier() == null + && StringUtils.isBlank(type.getGenerator()) + && StringUtils.isBlank(type.getName()) + && !TRUE.equals(type.isAuditInsertTimestamp()) + && !TRUE.equals(type.isAuditInsertUser()) + && !TRUE.equals(type.isAuditUpdateTimestamp()) + && !TRUE.equals(type.isAuditUpdateUser())) { + log.warn("Bad configuration for . Any of , , , , , , , or is required: " + type); - it2.remove(); - continue; - } - else if (!commercial()) { - log.warn(", , , , , and are commercial only features. Please upgrade to the jOOQ Professional Edition or jOOQ Enterprise Edition: " + type); + it2.remove(); + continue; + } + else if (!commercial()) { + log.warn(", , , , , and are commercial only features. Please upgrade to the jOOQ Professional Edition or jOOQ Enterprise Edition: " + type); - it2.remove(); - continue; - } - } - - if (StringUtils.isBlank(type.getBinding()) - && StringUtils.isBlank(type.getConverter()) - && StringUtils.isBlank(type.getGenerator()) - && !TRUE.equals(type.isAuditInsertTimestamp()) - && !TRUE.equals(type.isAuditInsertUser()) - && !TRUE.equals(type.isAuditUpdateTimestamp()) - && !TRUE.equals(type.isAuditUpdateUser()) - && type.getVisibilityModifier() == null - && !Boolean.TRUE.equals(type.isAutoConverter()) - && !Boolean.TRUE.equals(type.isEnumConverter()) - && !Boolean.TRUE.equals(type.isXmlConverter()) - && !Boolean.TRUE.equals(type.isJsonConverter()) - && type.getLambdaConverter() == null - ) { - type.setAutoConverter(true); - - if (log.isDebugEnabled()) - log.debug(" is implicit for : " + type); - } - } - else { - if (!StringUtils.isBlank(type.getUserType())) { - log.warn("Bad configuration for . is not allowed when is provided: " + type); - type.setUserType(null); - } - if (!StringUtils.isBlank(type.getBinding())) { - log.warn("Bad configuration for . is not allowed when is provided: " + type); - type.setBinding(null); - } - if (!StringUtils.isBlank(type.getConverter())) { - log.warn("Bad configuration for . is not allowed when is provided: " + type); - type.setConverter(null); - } - if (Boolean.TRUE.equals(type.isAutoConverter())) { - log.warn("Bad configuration for . is not allowed when is provided: " + type); - type.setEnumConverter(null); - } - if (Boolean.TRUE.equals(type.isEnumConverter())) { - log.warn("Bad configuration for . is not allowed when is provided: " + type); - type.setEnumConverter(null); - } - if (Boolean.TRUE.equals(type.isXmlConverter())) { - log.warn("Bad configuration for . is not allowed when is provided: " + type); - type.setXmlConverter(null); - } - if (Boolean.TRUE.equals(type.isJsonConverter())) { - log.warn("Bad configuration for . is not allowed when is provided: " + type); - type.setJsonConverter(null); - } - if (type.getLambdaConverter() != null) { - log.warn("Bad configuration for . is not allowed when is provided: " + type); - type.setLambdaConverter(null); + it2.remove(); + continue; } } - if (type.getUserType() != null && StringUtils.equals(type.getUserType(), typeName)) { + if (StringUtils.isBlank(type.getBinding()) + && StringUtils.isBlank(type.getConverter()) + && StringUtils.isBlank(type.getGenerator()) + && !TRUE.equals(type.isAuditInsertTimestamp()) + && !TRUE.equals(type.isAuditInsertUser()) + && !TRUE.equals(type.isAuditUpdateTimestamp()) + && !TRUE.equals(type.isAuditUpdateUser()) + && type.getVisibilityModifier() == null + && !Boolean.TRUE.equals(type.isAutoConverter()) + && !Boolean.TRUE.equals(type.isEnumConverter()) + && !Boolean.TRUE.equals(type.isXmlConverter()) + && !Boolean.TRUE.equals(type.isJsonConverter()) + && type.getLambdaConverter() == null + ) { + type.setAutoConverter(true); + + if (log.isDebugEnabled()) + log.debug(" is implicit for : " + type); + } + + if (type.getUserType() != null && StringUtils.equals(type.getUserType(), typeName)) return customType(this, type); - } } return null; 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 5bbf36e46c..a2f5b19194 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractTypedElementDefinition.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractTypedElementDefinition.java @@ -228,7 +228,8 @@ public abstract class AbstractTypedElementDefinition ForcedType forcedType = db.getConfiguredForcedType(child, definedType); if (forcedType != null) { - String uType = forcedType.getName(); + String uType = forcedType.getUserType(); + String name = forcedType.getName(); String generator = forcedType.getGenerator(); String converter = null; String binding = result.getBinding(); @@ -239,11 +240,62 @@ public abstract class AbstractTypedElementDefinition + boolean n = result.isNullable(); + String d = result.getDefaultValue(); + boolean i = result.isIdentity(); + boolean r = result.isReadonly(); + String g = result.getGeneratedAlwaysAs(); + + int l = 0; + int p = 0; + int s = 0; + CustomType customType = customType(db, forcedType); + + // [#2486] Allow users to override length, precision, and scale + if (name != null) { + DataType forcedDataType = null; + + Matcher matcher = LENGTH_PRECISION_SCALE_PATTERN.matcher(name); + if (matcher.find()) { + if (!isEmpty(matcher.group(1))) { + l = p = convert(matcher.group(1), int.class); + } + else { + p = convert(matcher.group(2), int.class); + s = convert(matcher.group(3), int.class); + } + } + + try { + forcedDataType = getDataType(db, name, p, s); + + // [#677] SQLDataType matches are actual type-rewrites + if (forcedDataType != null) + result = new DefaultDataTypeDefinition(db, child.getSchema(), name, l, p, s, n, r, g, d, i, (Name) null, generator, converter, binding, null); + + } + catch (SQLDialectNotSupportedException e) { + + if (!db.getConfiguredCustomTypes().isEmpty()) { + if (customType != null) + db.markUsed(forcedType); + + // [#7373] [#10944] Refer to only if someone is still using the feature + else + log.warn("Bad configuration for " + forcedType.getName() + ". No matching found, and no matching SQLDataType found: " + forcedType); + } + } + } + if (customType != null) { + + // [#7373] [#10944] Historically, configured custom types could have a userType declaration in their names + // This is no longer documented, but should be maintained, still uType = (!StringUtils.isBlank(customType.getType())) ? customType.getType() : customType.getName(); + name = customType.getName(); if (generator == null) generator = customType.getGenerator(); @@ -258,14 +310,14 @@ public abstract class AbstractTypedElementDefinition // [#13791] AutoConverters profit from simplified configuration if (TRUE.equals(customType.isAutoConverter()) || AutoConverter.class.getName().equals(customType.getConverter())) { - String tType = tType(db, resolver, definedType); + String tType = tType(db, resolver, result); converter = resolver.constructorCall(AutoConverter.class.getName() + "<" + resolver.ref(tType) + ", " + resolver.ref(uType) + ">") + "(" + resolver.classLiteral(tType) + ", " + resolver.classLiteral(uType) + ")"; } // [#5877] [#6567] ... so do EnumConverters else if (TRUE.equals(customType.isEnumConverter()) || EnumConverter.class.getName().equals(customType.getConverter())) { - String tType = tType(db, resolver, definedType); + String tType = tType(db, resolver, result); converter = resolver.constructorCall(EnumConverter.class.getName() + "<" + resolver.ref(tType) + ", " + resolver.ref(uType) + ">") + "(" + resolver.classLiteral(tType) + ", " + resolver.classLiteral(uType) + ")"; } @@ -275,7 +327,7 @@ public abstract class AbstractTypedElementDefinition converter = resolver.constructorCall(XMLtoJAXBConverter.class.getName() + "<" + resolver.ref(uType) + ">") + "(" + resolver.classLiteral(uType) + ")"; } else if (TRUE.equals(customType.isJsonConverter())) { - if (tType(db, resolver, definedType).endsWith("JSONB")) + if (tType(db, resolver, result).endsWith("JSONB")) converter = resolver.constructorCall("org.jooq.jackson.extensions.converters.JSONBtoJacksonConverter<" + resolver.ref(uType) + ">") + "(" + resolver.classLiteral(uType) + ")"; else converter = resolver.constructorCall("org.jooq.jackson.extensions.converters.JSONtoJacksonConverter<" + resolver.ref(uType) + ">") + "(" + resolver.classLiteral(uType) + ")"; @@ -289,12 +341,12 @@ public abstract class AbstractTypedElementDefinition else if (customType.getLambdaConverter() != null) { LambdaConverter c = customType.getLambdaConverter(); - String tType = tType(db, resolver, definedType); + String tType = tType(db, resolver, result); converter = resolver.ref(Converter.class) + ".of" + (!FALSE.equals(c.isNullable()) ? "Nullable" : "") + "(" + resolver.classLiteral(tType) + ", " + resolver.classLiteral(uType) + ", " + c.getFrom() + ", " + c.getTo() + ")"; } else if (!StringUtils.isBlank(customType.getConverter())) { if (TRUE.equals(customType.isGenericConverter())) { - String tType = tType(db, resolver, definedType); + String tType = tType(db, resolver, result); converter = resolver.constructorCall(customType.getConverter() + "<" + resolver.ref(tType) + ", " + resolver.ref(uType) + ">") + "(" + resolver.classLiteral(tType) + ", " + resolver.classLiteral(uType) + ")"; } else @@ -303,7 +355,7 @@ public abstract class AbstractTypedElementDefinition if (!StringUtils.isBlank(customType.getBinding())) { if (TRUE.equals(customType.isGenericBinding())) { - String tType = tType(db, resolver, definedType); + String tType = tType(db, resolver, result); binding = resolver.constructorCall(customType.getBinding() + "<" + resolver.ref(tType) + ", " + resolver.ref(uType) + ">") + "(" + resolver.classLiteral(tType) + ", " + resolver.classLiteral(uType) + ")"; } else @@ -324,50 +376,11 @@ public abstract class AbstractTypedElementDefinition - if (uType != null) { + if (name != null || uType != null) { db.markUsed(forcedType); log.info("Forcing type", child + " to " + forcedType); - DataType forcedDataType = null; - - boolean n = result.isNullable(); - String d = result.getDefaultValue(); - boolean i = result.isIdentity(); - boolean r = result.isReadonly(); - String g = result.getGeneratedAlwaysAs(); - - int l = 0; - int p = 0; - int s = 0; - - // [#2486] Allow users to override length, precision, and scale - Matcher matcher = LENGTH_PRECISION_SCALE_PATTERN.matcher(uType); - if (matcher.find()) { - if (!isEmpty(matcher.group(1))) { - l = p = convert(matcher.group(1), int.class); - } - else { - p = convert(matcher.group(2), int.class); - s = convert(matcher.group(3), int.class); - } - } - - try { - forcedDataType = getDataType(db, uType, p, s); - } catch (SQLDialectNotSupportedException ignore) {} - - // [#677] SQLDataType matches are actual type-rewrites - if (forcedDataType != null) { - - // [#3704] When matches a custom type AND a data type rewrite, the rewrite was usually accidental. - if (customType != null) - log.warn("Custom type conflict", child + " has custom type " + customType + " forced by " + forcedType + " but a data type rewrite applies"); - - result = new DefaultDataTypeDefinition(db, child.getSchema(), uType, l, p, s, n, r, g, d, i, (Name) null, generator, converter, binding, null); - } - - // Other forced types are UDT's, enums, etc. - else if (customType != null) { + if (customType != null) { l = result.getLength(); p = result.getPrecision(); s = result.getScale(); @@ -375,18 +388,6 @@ public abstract class AbstractTypedElementDefinition Name u = result.getQualifiedUserType(); result = new DefaultDataTypeDefinition(db, definedType.getSchema(), t, l, p, s, n, r, g, d, i, u, generator, converter, binding, uType); } - - // [#4597] If we don't have a type-rewrite (forcedDataType) or a - // matching customType, the user probably malconfigured - // their or - else { - - // [#7373] [#10944] Refer to only if someone is still using the feature - if (db.getConfiguredCustomTypes().isEmpty()) - log.warn("Bad configuration for " + forcedType.getName() + ". No matching SQLDataType found: " + forcedType); - else - log.warn("Bad configuration for " + forcedType.getName() + ". No matching found, and no matching SQLDataType found: " + forcedType); - } } if (generator != null) {