diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java index 0633d0e53c..7e666530d0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java @@ -1484,6 +1484,11 @@ implements + + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java index c9c5f75a4a..c66ee0e9f7 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DSL.java +++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java @@ -123,6 +123,7 @@ import static org.jooq.impl.SQLDataType.VARCHAR; import static org.jooq.impl.Tools.EMPTY_FIELD; import static org.jooq.impl.Tools.combine; import static org.jooq.impl.Tools.configuration; +import static org.jooq.impl.Tools.getRecordQualifier; import static org.jooq.impl.Tools.isEmpty; import static org.jooq.impl.Tools.map; import static org.jooq.impl.Tools.mostSpecificArray; @@ -31610,8 +31611,10 @@ public class DSL { public static Param val(Object value, DataType type) { // Advanced data types have dedicated constant types - if (value instanceof QualifiedRecord) - return new QualifiedRecordConstant((QualifiedRecord) value); + if (value instanceof QualifiedRecord r) + return new QualifiedRecordConstant(r, r.getQualifier()); + else if (value == null && QualifiedRecord.class.isAssignableFrom(type.getType())) + return new QualifiedRecordConstant(null, getRecordQualifier(type)); diff --git a/jOOQ/src/main/java/org/jooq/impl/QualifiedRecordConstant.java b/jOOQ/src/main/java/org/jooq/impl/QualifiedRecordConstant.java index e7910609b2..76e29df972 100644 --- a/jOOQ/src/main/java/org/jooq/impl/QualifiedRecordConstant.java +++ b/jOOQ/src/main/java/org/jooq/impl/QualifiedRecordConstant.java @@ -41,6 +41,7 @@ package org.jooq.impl; import static org.jooq.conf.ParamType.INLINED; import static org.jooq.impl.DSL.val; import static org.jooq.impl.DefaultBinding.DefaultRecordBinding.REQUIRE_RECORD_CAST; +import static org.jooq.impl.Keywords.K_NULL; import static org.jooq.impl.Keywords.K_ROW; import static org.jooq.impl.Tools.getMappedUDTName; @@ -48,6 +49,7 @@ import org.jooq.BindContext; import org.jooq.Context; import org.jooq.Field; import org.jooq.QualifiedRecord; +import org.jooq.RecordQualifier; import org.jooq.RenderContext; import org.jooq.conf.ParamType; import org.jooq.exception.SQLDialectNotSupportedException; @@ -58,8 +60,12 @@ import org.jooq.impl.QOM.UNotYetImplemented; */ final class QualifiedRecordConstant> extends AbstractParam implements UNotYetImplemented { - QualifiedRecordConstant(R value) { - super(value, value.getQualifier().getDataType()); + final RecordQualifier qualifier; + + QualifiedRecordConstant(R value, RecordQualifier qualifier) { + super(value, qualifier.getDataType()); + + this.qualifier = qualifier; } @Override @@ -132,34 +138,39 @@ final class QualifiedRecordConstant> extends Abstra private final void toSQLInline(RenderContext ctx) { Cast.renderCastIf(ctx, c -> { - switch (c.family()) { + if (value == null) { + c.visit(K_NULL); + } + else { + switch (c.family()) { - case POSTGRES: - case YUGABYTEDB: - c.visit(K_ROW); - break; + case POSTGRES: + case YUGABYTEDB: + c.visit(K_ROW); + break; - default: { - c.visit(value.getQualifier()); - break; + default: { + c.visit(qualifier); + break; + } } + + c.sql('('); + + String separator = ""; + for (Field field : value.fields()) { + c.sql(separator); + c.visit(val(value.get(field), field)); + separator = ", "; + } + + c.sql(')'); } - - c.sql('('); - - String separator = ""; - for (Field field : value.fields()) { - c.sql(separator); - c.visit(val(value.get(field), field)); - separator = ", "; - } - - c.sql(')'); }, // [#13174] Need to cast inline UDT ROW expressions to the UDT type - c -> c.visit(value.getQualifier()), + c -> c.visit(qualifier), () -> REQUIRE_RECORD_CAST.contains(ctx.dialect()) ); } @@ -198,8 +209,9 @@ final class QualifiedRecordConstant> extends Abstra // inlined instead: ROW(.., .., ..) case POSTGRES: case YUGABYTEDB: { - for (Field field : value.fields()) - ctx.visit(val(value.get(field))); + if (value != null) + for (Field field : value.fields()) + ctx.visit(val(value.get(field), field.getDataType())); break; }