diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRow.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRow.java index 935184054f..d4ce30d43d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRow.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRow.java @@ -45,6 +45,7 @@ import static org.jooq.impl.Names.N_ROW; import static org.jooq.impl.QueryPartListView.wrap; import static org.jooq.impl.Tools.extractVal; import static org.jooq.impl.Tools.isVal; +import static org.jooq.impl.Tools.isVal1; import static org.jooq.impl.Tools.nullSafe; import java.util.Collection; @@ -224,7 +225,8 @@ implements findConversionCandidates: { for (int i = 0; i < size; i++) - if (isVal(fields.field(i)) && !isVal(row.field(i))) + if (isVal1(fields.field(i), v -> v.inferredDataType) + && !isVal1(row.field(i), v -> v.inferredDataType)) break findConversionCandidates; return this; @@ -233,10 +235,12 @@ implements Field[] result = new Field[size]; for (int i = 0; i < size; i++) { Field f = fields.field(i); - Val v; + Val val; - if ((v = extractVal(f)) != null) - result[i] = v.convertTo(row.field(i).getDataType()); + if (isVal1(fields.field(i), v -> v.inferredDataType) + && !isVal1(row.field(i), v -> v.inferredDataType) + && (val = extractVal(f)) != null) + result[i] = val.convertTo(row.field(i).getDataType()); else result[i] = f; } diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java b/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java index dd18e5c989..3ac2d66f19 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java @@ -843,14 +843,34 @@ public class DefaultDataType extends AbstractDataTypeX { private static final class DiscouragedStaticTypeRegistryUsage extends RuntimeException {} public static final DataType getDataType(SQLDialect dialect, Class type, DataType fallbackDataType) { - return check(getDataType0(dialect, type, fallbackDataType)); + return getDataType0(dialect, type, fallbackDataType); } - private static final DataType check(DataType result) { + static final DataType check(DataType result) { // [#5713] [#15286] TODO: Move this to a dynamic type registry and make warning configurable - if (result instanceof ConvertedDataType || result instanceof LegacyConvertedDataType) - getDataType.warn("Static type registry", "The deprecated static type registry was being accessed for a non-built-in data type: " + result + ". It is strongly recommended not looking up DataType references from Class references by relying on the internal static type registry. See https://github.com/jOOQ/jOOQ/issues/15286 for details.", new DiscouragedStaticTypeRegistryUsage()); + if (result instanceof LegacyConvertedDataType) { + DiscouragedStaticTypeRegistryUsage e = new DiscouragedStaticTypeRegistryUsage(); + + getDataType.warn("Static type registry", """ + The deprecated static type registry was being accessed for a non-built-in data type: {result}. + + It is strongly recommended not looking up DataType references from Class references by + relying on the internal static type registry. For example, avoid calling DSL.val(Object) or + DSL.val(Object, Class), and call DSL.val(Object, DataType), providing an explicit DataType + reference to jOOQ if your DataType uses a Converter or a Binding. If you think jOOQ should + be able to infer your user type in your particular query, please report a bug here: + https://jooq.org/bug + + See https://github.com/jOOQ/jOOQ/issues/15286 for more details. + """.replace("{result}", "" + result), e); + + // [#16090] [#16425] + // An undocumented flag to throw the logged exception to help with faster fixing of this problem + // Users should not rely on this flag as it may be removed without announcement when it isn't needed anymore. + if ("true".equals(System.getProperty("org.jooq.throw-on-discouraged-static-type-registry-access"))) + throw e; + } if (result instanceof ArrayDataType a) check(a.elementType); diff --git a/jOOQ/src/main/java/org/jooq/impl/Val.java b/jOOQ/src/main/java/org/jooq/impl/Val.java index e0ce74568c..027b538d9e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Val.java +++ b/jOOQ/src/main/java/org/jooq/impl/Val.java @@ -177,6 +177,11 @@ final class Val extends AbstractParam implements UEmpty { @Override public void accept(Context ctx) { + + // [#16090] [#16425] Inferred user types shouldn't rely on static type registry + if (inferredDataType) + DefaultDataType.check(getDataType()); + if (getDataType().isEmbeddable()) { // TODO [#12021] [#12706] ROW must consistently follow MULTISET emulation