From d210d5f35d69f7d098a2adb4c0da407558d1c504 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Wed, 21 Apr 2021 15:44:14 +0200 Subject: [PATCH] [jOOQ/jOOQ#7863] Fixed binding of %ROWTYPE IN and OUT parameters Previous commits fixed TABLE OF X%ROWTYPE bindings, but the X%ROWTYPE emulation was not implemented yet. Those can't be bound using ordinary SQLData API, it seems. --- .../main/java/org/jooq/impl/AbstractDataType.java | 6 +++--- .../src/main/java/org/jooq/impl/AbstractParam.java | 7 +++---- .../main/java/org/jooq/impl/AbstractRoutine.java | 14 ++++++++++++-- jOOQ/src/main/java/org/jooq/impl/ArrayTable.java | 2 +- jOOQ/src/main/java/org/jooq/impl/DSL.java | 6 +++--- .../main/java/org/jooq/impl/DefaultBinding.java | 6 +++--- .../org/jooq/impl/DefaultConverterProvider.java | 4 ++-- .../main/java/org/jooq/impl/DefaultDataType.java | 9 +++------ ...TConstant.java => QualifiedRecordConstant.java} | 10 +++++----- jOOQ/src/main/java/org/jooq/impl/Tools.java | 6 +++--- jOOQ/src/main/java/org/jooq/tools/Convert.java | 10 +++++----- .../java/org/jooq/util/jaxb/tools/MiniJAXB.java | 4 ++-- 12 files changed, 45 insertions(+), 39 deletions(-) rename jOOQ/src/main/java/org/jooq/impl/{UDTConstant.java => QualifiedRecordConstant.java} (92%) diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java index f371ea9794..8d64b424d3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java @@ -84,9 +84,9 @@ import org.jooq.JSONB; import org.jooq.Name; import org.jooq.Nullability; // ... +import org.jooq.QualifiedRecord; import org.jooq.Result; import org.jooq.SQLDialect; -import org.jooq.UDTRecord; import org.jooq.XML; import org.jooq.tools.Convert; import org.jooq.types.Interval; @@ -374,7 +374,7 @@ abstract class AbstractDataType extends AbstractNamed implements DataType else if (EnumType.class.isAssignableFrom(tType)) return Types.VARCHAR; - else if (UDTRecord.class.isAssignableFrom(tType)) + else if (QualifiedRecord.class.isAssignableFrom(tType)) return Types.STRUCT; else if (Result.class.isAssignableFrom(tType)) { switch (configuration.family()) { @@ -648,7 +648,7 @@ abstract class AbstractDataType extends AbstractNamed implements DataType @Override public final boolean isUDT() { - return UDTRecord.class.isAssignableFrom(tType0()); + return QualifiedRecord.class.isAssignableFrom(tType0()); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractParam.java b/jOOQ/src/main/java/org/jooq/impl/AbstractParam.java index 7e649e855b..d44a69a6db 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractParam.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractParam.java @@ -54,9 +54,8 @@ import org.jooq.DataType; import org.jooq.Name; import org.jooq.Param; import org.jooq.ParamMode; -import org.jooq.UDTRecord; +import org.jooq.QualifiedRecord; import org.jooq.conf.ParamType; -import org.jooq.tools.JooqLogger; import org.jooq.tools.StringUtils; /** @@ -106,8 +105,8 @@ abstract class AbstractParam extends AbstractParamX implements SimpleQuery ? paramName // [#3707] Protect value.toString call for certain jOOQ types. - : value instanceof UDTRecord - ? ((UDTRecord) value).getUDT().getName() + : value instanceof QualifiedRecord + ? ((QualifiedRecord) value).getQualifier().getName() diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java index 7f17217832..d9df74a66b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java @@ -121,8 +121,10 @@ import org.jooq.Package; import org.jooq.Param; import org.jooq.Parameter; // ... +import org.jooq.QualifiedRecord; import org.jooq.QueryPart; import org.jooq.Record; +import org.jooq.RecordQualifier; import org.jooq.RenderContext; import org.jooq.Result; import org.jooq.Results; @@ -132,7 +134,6 @@ import org.jooq.Schema; import org.jooq.Statement; import org.jooq.UDT; import org.jooq.UDTField; -import org.jooq.UDTRecord; import org.jooq.XMLFormat; import org.jooq.conf.SettingsTools; import org.jooq.exception.ControlFlowSignal; @@ -1094,7 +1095,6 @@ public abstract class AbstractRoutine extends AbstractNamed implements Routin - private final void toSQLAssign(RenderContext context) { @@ -1470,6 +1470,16 @@ public abstract class AbstractRoutine extends AbstractNamed implements Routin + + + + + + + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/ArrayTable.java b/jOOQ/src/main/java/org/jooq/impl/ArrayTable.java index f1f145ed1d..c6a72d2af6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ArrayTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/ArrayTable.java @@ -129,7 +129,7 @@ final class ArrayTable extends AbstractTable { // [#1114] [#7863] VARRAY/TABLE of OBJECT have more than one field if (Record.class.isAssignableFrom(arrayType)) { try { - Record record = (Record) arrayType.getConstructor().newInstance(); + Record record = (Record) arrayType.getDeclaredConstructor().newInstance(); for (Field f : record.fields()) result.add(DSL.field(name(alias.last(), f.getName()), f.getDataType())); diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java index d33812892e..1ea990b7ae 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DSL.java +++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java @@ -292,6 +292,7 @@ import org.jooq.Parameter; import org.jooq.PlainSQL; import org.jooq.Privilege; // ... +import org.jooq.QualifiedRecord; import org.jooq.QuantifiedSelect; import org.jooq.Queries; import org.jooq.Query; @@ -26608,15 +26609,14 @@ public class DSL { public static Param val(Object value, DataType type) { // Advanced data types have dedicated constant types - if (value instanceof UDTRecord) { - return new UDTConstant((UDTRecord) value); + if (value instanceof QualifiedRecord) { + return new QualifiedRecordConstant((QualifiedRecord) value); } - // The default behaviour else { T converted = type.convert(value); diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index 1cbf8b2199..f192aa9ca3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java @@ -509,7 +509,7 @@ public class DefaultBinding implements Binding { if (QualifiedRecord.class.isAssignableFrom(type)) { Class> t = (Class>) type; result.put(getMappedUDTName(configuration, t), t); - QualifiedRecord r = t.getConstructor().newInstance(); + QualifiedRecord r = t.getDeclaredConstructor().newInstance(); for (Field field : r.getQualifier().fields()) typeMap(field.getType(), configuration, result); } @@ -3531,8 +3531,8 @@ public class DefaultBinding implements Binding { @Override final void set0(BindingSetSQLOutputContext ctx, Record value) throws SQLException { - if (value instanceof UDTRecord) - ctx.output().writeObject((UDTRecord) value); + if (value instanceof QualifiedRecord) + ctx.output().writeObject((QualifiedRecord) value); else throw new UnsupportedOperationException("Type " + dataType + " is not supported"); } diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultConverterProvider.java b/jOOQ/src/main/java/org/jooq/impl/DefaultConverterProvider.java index f423394089..7148f84069 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultConverterProvider.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultConverterProvider.java @@ -56,8 +56,8 @@ import org.jooq.ConverterProvider; import org.jooq.EnumType; import org.jooq.JSON; import org.jooq.JSONB; +import org.jooq.QualifiedRecord; import org.jooq.Record; -import org.jooq.UDTRecord; import org.jooq.XML; import org.jooq.exception.DataTypeException; import org.jooq.tools.Convert; @@ -112,7 +112,7 @@ public final class DefaultConverterProvider implements ConverterProvider, Serial || isXML(tWrapper) || Record.class.isAssignableFrom(tWrapper) - || Struct.class.isAssignableFrom(tWrapper) && UDTRecord.class.isAssignableFrom(uWrapper) + || Struct.class.isAssignableFrom(tWrapper) && QualifiedRecord.class.isAssignableFrom(uWrapper) ) { return new AbstractConverter(tType, uType) { diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java b/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java index bc6b02f924..c8bb8b3cad 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java @@ -76,9 +76,8 @@ import org.jooq.EnumType; import org.jooq.Field; import org.jooq.Name; import org.jooq.Nullability; +import org.jooq.QualifiedRecord; import org.jooq.SQLDialect; -import org.jooq.TableRecord; -import org.jooq.UDTRecord; import org.jooq.exception.MappingException; import org.jooq.exception.SQLDialectNotSupportedException; import org.jooq.types.UByte; @@ -691,12 +690,10 @@ public class DefaultDataType extends AbstractDataTypeX { // jOOQ data types are handled here try { - if (UDTRecord.class.isAssignableFrom(type)) - return (DataType) ((UDTRecord) type.newInstance()).getUDT().getDataType(); // [#7174] PostgreSQL table records can be function argument types - else if (TableRecord.class.isAssignableFrom(type)) - return (DataType) ((TableRecord) type.newInstance()).getTable().getDataType(); + if (QualifiedRecord.class.isAssignableFrom(type)) + return (DataType) ((QualifiedRecord) type.getDeclaredConstructor().newInstance()).getQualifier().getDataType(); diff --git a/jOOQ/src/main/java/org/jooq/impl/UDTConstant.java b/jOOQ/src/main/java/org/jooq/impl/QualifiedRecordConstant.java similarity index 92% rename from jOOQ/src/main/java/org/jooq/impl/UDTConstant.java rename to jOOQ/src/main/java/org/jooq/impl/QualifiedRecordConstant.java index 9bb0a1fcaf..a596fa54f3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UDTConstant.java +++ b/jOOQ/src/main/java/org/jooq/impl/QualifiedRecordConstant.java @@ -45,20 +45,20 @@ import static org.jooq.impl.Keywords.K_ROW; import org.jooq.BindContext; import org.jooq.Context; import org.jooq.Field; +import org.jooq.QualifiedRecord; import org.jooq.RenderContext; -import org.jooq.UDTRecord; import org.jooq.conf.ParamType; import org.jooq.exception.SQLDialectNotSupportedException; /** * @author Lukas Eder */ -final class UDTConstant> extends AbstractParam { +final class QualifiedRecordConstant> extends AbstractParam { private static final long serialVersionUID = 6807729087019209084L; - UDTConstant(R value) { - super(value, value.getUDT().getDataType()); + QualifiedRecordConstant(R value) { + super(value, value.getQualifier().getDataType()); } @Override @@ -136,7 +136,7 @@ final class UDTConstant> extends AbstractParam { break; default: { - ctx.visit(value.getUDT()); + ctx.visit(value.getQualifier()); break; } } diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 8bde29fa66..8660fc6e9d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -2981,7 +2981,7 @@ final class Tools { } /** - * Map an {@link UDTRecord} according to the configured + * Map an {@link QualifiedRecord} according to the configured * {@link org.jooq.SchemaMapping} */ @SuppressWarnings("unchecked") @@ -2990,7 +2990,7 @@ final class Tools { } /** - * Map an {@link UDTRecord} according to the configured + * Map an {@link QualifiedRecord} according to the configured * {@link org.jooq.SchemaMapping} */ static final String getMappedUDTName(Configuration configuration, QualifiedRecord record) { @@ -5615,7 +5615,7 @@ final class Tools { private static final EmbeddableRecord newInstance(Class> type) { try { - return type.getConstructor().newInstance(); + return type.getDeclaredConstructor().newInstance(); } catch (Exception e) { throw new MappingException("Cannot create EmbeddableRecord type", e); diff --git a/jOOQ/src/main/java/org/jooq/tools/Convert.java b/jOOQ/src/main/java/org/jooq/tools/Convert.java index 4c9c662d45..b90043a693 100644 --- a/jOOQ/src/main/java/org/jooq/tools/Convert.java +++ b/jOOQ/src/main/java/org/jooq/tools/Convert.java @@ -92,10 +92,10 @@ import org.jooq.EnumType; import org.jooq.Field; import org.jooq.JSON; import org.jooq.JSONB; +import org.jooq.QualifiedRecord; import org.jooq.Record; import org.jooq.Result; import org.jooq.SQLDialect; -import org.jooq.UDTRecord; import org.jooq.XML; import org.jooq.exception.DataTypeException; import org.jooq.impl.IdentityConverter; @@ -197,7 +197,7 @@ public final class Convert { try { Class klass = Class.forName("com.fasterxml.jackson.databind.ObjectMapper"); - jsonMapper = klass.getConstructor().newInstance(); + jsonMapper = klass.getDeclaredConstructor().newInstance(); jsonReadMethod = klass.getMethod("readValue", String.class, Class.class); log.debug("Jackson is available"); } @@ -207,7 +207,7 @@ public final class Convert { try { Class klass = Class.forName("com.google.gson.Gson"); - jsonMapper = klass.getConstructor().newInstance(); + jsonMapper = klass.getDeclaredConstructor().newInstance(); jsonReadMethod = klass.getMethod("fromJson", String.class, Class.class); log.debug("Gson is available"); } @@ -1092,9 +1092,9 @@ public final class Convert { else if (Struct.class.isAssignableFrom(fromClass)) { Struct struct = (Struct) from; - if (UDTRecord.class.isAssignableFrom(toClass)) { + if (QualifiedRecord.class.isAssignableFrom(toClass)) { try { - UDTRecord record = ((UDTRecord) toClass.newInstance()); + QualifiedRecord record = ((QualifiedRecord) toClass.getDeclaredConstructor().newInstance()); record.from(struct.getAttributes()); return (U) record; } diff --git a/jOOQ/src/main/java/org/jooq/util/jaxb/tools/MiniJAXB.java b/jOOQ/src/main/java/org/jooq/util/jaxb/tools/MiniJAXB.java index 31bbfd8126..03375f0282 100644 --- a/jOOQ/src/main/java/org/jooq/util/jaxb/tools/MiniJAXB.java +++ b/jOOQ/src/main/java/org/jooq/util/jaxb/tools/MiniJAXB.java @@ -263,7 +263,7 @@ public final class MiniJAXB { } else if (a != null) { @SuppressWarnings("unchecked") - XmlAdapter adapter = a.value().getConstructor().newInstance(); + XmlAdapter adapter = a.value().getDeclaredConstructor().newInstance(); Reflect.on(result).set(childName, adapter.unmarshal(childElement.getTextContent().trim())); } else { @@ -438,7 +438,7 @@ public final class MiniJAXB { // We're assuming that XJC generated objects are all in the same package Package pkg = klass.getPackage(); try { - T defaults = klass.getConstructor().newInstance(); + T defaults = klass.getDeclaredConstructor().newInstance(); for (Method setter : klass.getMethods()) { if (setter.getName().startsWith("set")) {