[jOOQ/jOOQ#13534] Avoid rendering PostgreSQL native cast operator :: which cannot be used in Hibernate native queries
This commit is contained in:
parent
91a4e86125
commit
ee187a4c04
@ -45,6 +45,7 @@ import java.sql.SQLFeatureNotSupportedException;
|
||||
import org.jooq.BindingGetSQLInputContext;
|
||||
import org.jooq.BindingSQLContext;
|
||||
import org.jooq.BindingSetSQLOutputContext;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.impl.AbstractBinding;
|
||||
import org.jooq.impl.DSL;
|
||||
|
||||
@ -66,34 +67,48 @@ public abstract class AbstractPostgresBinding<T, U> extends AbstractBinding<T, U
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sqlInline(BindingSQLContext<U> ctx) throws SQLException {
|
||||
if (ctx.value() instanceof Object[]) {
|
||||
ctx.render().visit(keyword("ARRAY")).sql('[');
|
||||
/**
|
||||
* A checked exception throwing {@link Consumer}.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
private interface ThrowingRunnable {
|
||||
void run() throws SQLException;
|
||||
}
|
||||
|
||||
String separator = "";
|
||||
for (Object value : ((Object[]) ctx.value())) {
|
||||
ctx.render().sql(separator).visit(value == null ? keyword("NULL") : DSL.inline("" + value));
|
||||
separator = ", ";
|
||||
}
|
||||
private void castIfNeeded(Context<?> ctx, ThrowingRunnable content) throws SQLException {
|
||||
String castType = castType();
|
||||
|
||||
ctx.render().sql(']');
|
||||
if (castType != null) {
|
||||
ctx.visit(keyword("cast")).sql('(');
|
||||
content.run();
|
||||
ctx.sql(' ').visit(keyword("as")).sql(' ').sql(castType).sql(')');
|
||||
}
|
||||
else
|
||||
super.sqlInline(ctx);
|
||||
content.run();
|
||||
}
|
||||
|
||||
String castType = castType();
|
||||
if (castType != null)
|
||||
ctx.render().sql("::").sql(castType);
|
||||
@Override
|
||||
protected void sqlInline(BindingSQLContext<U> ctx) throws SQLException {
|
||||
castIfNeeded(ctx.render(), () -> {
|
||||
if (ctx.value() instanceof Object[]) {
|
||||
ctx.render().visit(keyword("ARRAY")).sql('[');
|
||||
|
||||
String separator = "";
|
||||
for (Object value : ((Object[]) ctx.value())) {
|
||||
ctx.render().sql(separator).visit(value == null ? keyword("NULL") : DSL.inline("" + value));
|
||||
separator = ", ";
|
||||
}
|
||||
|
||||
ctx.render().sql(']');
|
||||
}
|
||||
else
|
||||
super.sqlInline(ctx);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sqlBind(BindingSQLContext<U> ctx) throws SQLException {
|
||||
super.sqlBind(ctx);
|
||||
|
||||
String castType = castType();
|
||||
if (castType != null)
|
||||
ctx.render().sql("::").sql(castType);
|
||||
castIfNeeded(ctx.render(), () -> super.sqlBind(ctx));
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -40,21 +40,19 @@ package org.jooq.impl;
|
||||
import static java.util.Arrays.asList;
|
||||
// ...
|
||||
// ...
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
import static org.jooq.SQLDialect.YUGABYTEDB;
|
||||
import static org.jooq.impl.Cast.renderCastIf;
|
||||
import static org.jooq.impl.Keywords.K_ARRAY;
|
||||
import static org.jooq.impl.Keywords.K_INT;
|
||||
import static org.jooq.impl.Names.N_ARRAY;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jooq.Context;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Function1;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.Record;
|
||||
// ...
|
||||
@ -95,15 +93,23 @@ final class Array<T> extends AbstractField<T[]> implements QOM.Array<T> {
|
||||
|
||||
|
||||
default:
|
||||
boolean squareBrackets = true;
|
||||
renderCastIf(ctx,
|
||||
c -> {
|
||||
switch (ctx.family()) {
|
||||
|
||||
ctx.visit(K_ARRAY)
|
||||
.sql(squareBrackets ? '[' : '(')
|
||||
.visit(fields)
|
||||
.sql(squareBrackets ? ']' : ')');
|
||||
|
||||
if (fields.fields.length == 0 && REQUIRES_CAST.contains(ctx.dialect()))
|
||||
ctx.sql("::").visit(K_INT).sql("[]");
|
||||
|
||||
|
||||
|
||||
|
||||
default:
|
||||
ctx.visit(K_ARRAY).sql('[').visit(fields).sql(']');
|
||||
break;
|
||||
}
|
||||
},
|
||||
c -> c.visit(K_INT).sql("[]"),
|
||||
() -> fields.fields.length == 0 && REQUIRES_CAST.contains(ctx.dialect())
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -58,13 +58,11 @@ import static org.jooq.impl.SQLDataType.VARCHAR;
|
||||
import java.sql.Date;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import org.jooq.Context;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Function1;
|
||||
import org.jooq.Keyword;
|
||||
import org.jooq.LanguageContext;
|
||||
// ...
|
||||
@ -330,31 +328,57 @@ final class Cast<T> extends AbstractField<T> implements QOM.Cast<T> {
|
||||
|
||||
@Override
|
||||
public void accept(Context<?> ctx) {
|
||||
|
||||
// Avoid casting bind values inside an explicit cast...
|
||||
CastMode castMode = ctx.castMode();
|
||||
|
||||
// Default rendering, if no special case has applied yet
|
||||
ctx.visit(K_CAST).sql('(')
|
||||
.castMode(CastMode.NEVER)
|
||||
.visit(expression)
|
||||
.castMode(castMode)
|
||||
.sql(' ').visit(K_AS).sql(' ');
|
||||
|
||||
if (typeAsKeyword != null)
|
||||
ctx.visit(typeAsKeyword);
|
||||
renderCast(ctx,
|
||||
c -> c.visit(expression),
|
||||
c -> {
|
||||
if (typeAsKeyword != null)
|
||||
c.visit(typeAsKeyword);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
else
|
||||
ctx.sql(type.getCastTypeName(ctx.configuration()));
|
||||
|
||||
ctx.sql(')');
|
||||
else
|
||||
c.sql(type.getCastTypeName(c.configuration()));
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static <E extends Throwable> void renderCast(
|
||||
Context<?> ctx,
|
||||
ThrowingConsumer<? super Context<?>, E> expression,
|
||||
ThrowingConsumer<? super Context<?>, E> type
|
||||
) throws E {
|
||||
|
||||
// Avoid casting bind values inside an explicit cast...
|
||||
CastMode castMode = ctx.castMode();
|
||||
|
||||
// Default rendering, if no special case has applied yet
|
||||
ctx.visit(K_CAST).sql('(')
|
||||
.castMode(CastMode.NEVER);
|
||||
|
||||
expression.accept(ctx);
|
||||
|
||||
ctx.castMode(castMode)
|
||||
.sql(' ').visit(K_AS).sql(' ');
|
||||
|
||||
type.accept(ctx);
|
||||
ctx.sql(')');
|
||||
}
|
||||
|
||||
static <E extends Throwable> void renderCastIf(
|
||||
Context<?> ctx,
|
||||
ThrowingConsumer<? super Context<?>, E> expression,
|
||||
ThrowingConsumer<? super Context<?>, E> type,
|
||||
BooleanSupplier test
|
||||
) throws E {
|
||||
if (test.getAsBoolean())
|
||||
renderCast(ctx, expression, type);
|
||||
else
|
||||
expression.accept(ctx);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// XXX: Query Object Model
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -219,7 +219,7 @@ implements
|
||||
|
||||
// [#3824] Ensure that the output for DATE arithmetic will also be of type DATE, not TIMESTAMP
|
||||
else
|
||||
ctx.sql('(').visit(date).sql(" + ").visit(interval).sql(" * ").visit(K_INTERVAL).sql(' ').visit(inline(string)).sql(")::date");
|
||||
ctx.sql("cast((").visit(date).sql(" + ").visit(interval).sql(" * ").visit(K_INTERVAL).sql(' ').visit(inline(string)).sql(") as date)");
|
||||
|
||||
else
|
||||
ctx.sql('(').visit(date).sql(" + ").visit(interval).sql(" * ").visit(K_INTERVAL).sql(' ').visit(inline(string)).sql(")");
|
||||
|
||||
@ -94,6 +94,8 @@ import static org.jooq.impl.DSL.using;
|
||||
import static org.jooq.impl.DefaultBinding.DefaultDoubleBinding.REQUIRES_LITERAL_CAST;
|
||||
import static org.jooq.impl.DefaultBinding.DefaultDoubleBinding.infinity;
|
||||
import static org.jooq.impl.DefaultBinding.DefaultDoubleBinding.nan;
|
||||
import static org.jooq.impl.DefaultBinding.DefaultEnumTypeBinding.pgEnumValue;
|
||||
import static org.jooq.impl.DefaultBinding.DefaultEnumTypeBinding.pgRenderEnumCast;
|
||||
import static org.jooq.impl.DefaultBinding.DefaultJSONBBinding.EMULATE_AS_BLOB;
|
||||
import static org.jooq.impl.DefaultBinding.DefaultResultBinding.readMultisetJSON;
|
||||
import static org.jooq.impl.DefaultBinding.DefaultResultBinding.readMultisetXML;
|
||||
@ -123,6 +125,7 @@ import static org.jooq.impl.Keywords.K_TIME_WITH_TIME_ZONE;
|
||||
import static org.jooq.impl.Keywords.K_TRUE;
|
||||
import static org.jooq.impl.Keywords.K_YEAR_TO_DAY;
|
||||
import static org.jooq.impl.Keywords.K_YEAR_TO_FRACTION;
|
||||
import static org.jooq.impl.Names.N_BYTEA;
|
||||
import static org.jooq.impl.Names.N_ST_GEOMFROMTEXT;
|
||||
import static org.jooq.impl.Names.N_ST_GEOMFROMWKB;
|
||||
import static org.jooq.impl.R2DBC.isR2dbc;
|
||||
@ -1223,11 +1226,6 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
}
|
||||
|
||||
ctx.render().sql(squareBrackets ? ']' : ')');
|
||||
|
||||
// [#3214] Some PostgreSQL array type literals need explicit casting
|
||||
// TODO: This seems mutually exclusive with the previous branch. Still needed?
|
||||
if ((REQUIRES_ARRAY_CAST.contains(ctx.dialect())) && dataType.getArrayComponentDataType().isEnum())
|
||||
DefaultEnumTypeBinding.pgRenderEnumCast(ctx.render(), dataType.getType());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1243,24 +1241,22 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
@Override
|
||||
final void sqlBind0(BindingSQLContext<U> ctx, Object[] value) throws SQLException {
|
||||
super.sqlBind0(ctx, value);
|
||||
|
||||
// In Postgres, some additional casting must be done in some cases...
|
||||
switch (ctx.family()) {
|
||||
|
||||
|
||||
case POSTGRES:
|
||||
case YUGABYTEDB:
|
||||
Cast.renderCastIf(ctx.render(),
|
||||
c -> super.sqlBind0(ctx, value),
|
||||
c -> {
|
||||
|
||||
// Postgres needs explicit casting for enum (array) types
|
||||
if (EnumType.class.isAssignableFrom(dataType.getType().getComponentType()))
|
||||
DefaultEnumTypeBinding.pgRenderEnumCast(ctx.render(), dataType.getType());
|
||||
pgRenderEnumCast(ctx.render(), dataType.getType(), pgEnumValue(dataType.getType()));
|
||||
|
||||
// ... and also for other array types
|
||||
else
|
||||
ctx.render().sql("::")
|
||||
.sql(dataType.getCastTypeName(ctx.render().configuration()));
|
||||
}
|
||||
ctx.render().sql(dataType.getCastTypeName(ctx.render().configuration()));
|
||||
},
|
||||
|
||||
// In Postgres, some additional casting must be done in some cases...
|
||||
() -> REQUIRES_ARRAY_CAST.contains(ctx.family())
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@ -2063,11 +2059,10 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
case POSTGRES:
|
||||
case YUGABYTEDB:
|
||||
ctx.render()
|
||||
.sql("E'")
|
||||
.sql(PostgresUtils.toPGString(value))
|
||||
.sql("'::bytea");
|
||||
|
||||
Cast.renderCast(ctx.render(),
|
||||
c -> c.sql("E'").sql(PostgresUtils.toPGString(value)).sql("'"),
|
||||
c -> c.visit(N_BYTEA)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2673,19 +2668,28 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
@Override
|
||||
final void sqlInline0(BindingSQLContext<U> ctx, EnumType value) throws SQLException {
|
||||
binding(VARCHAR).sql(new DefaultBindingSQLContext<>(ctx.configuration(), ctx.data(), ctx.render(), value.getLiteral()));
|
||||
EnumType enumValue = pgEnumValue(dataType.getType());
|
||||
|
||||
if (REQUIRE_ENUM_CAST.contains(ctx.dialect()))
|
||||
pgRenderEnumCast(ctx.render(), dataType.getType());
|
||||
Cast.renderCastIf(ctx.render(),
|
||||
c -> binding(VARCHAR).sql(new DefaultBindingSQLContext<>(ctx.configuration(), ctx.data(), ctx.render(), value.getLiteral())),
|
||||
c -> pgRenderEnumCast(c, dataType.getType(), enumValue),
|
||||
|
||||
// Postgres needs explicit casting for enum (array) types
|
||||
() -> REQUIRE_ENUM_CAST.contains(ctx.dialect()) && enumValue.getSchema() != null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
final void sqlBind0(BindingSQLContext<U> ctx, EnumType value) throws SQLException {
|
||||
super.sqlBind0(ctx, value);
|
||||
EnumType enumValue = pgEnumValue(dataType.getType());
|
||||
|
||||
// Postgres needs explicit casting for enum (array) types
|
||||
if (REQUIRE_ENUM_CAST.contains(ctx.dialect()))
|
||||
pgRenderEnumCast(ctx.render(), dataType.getType());
|
||||
Cast.renderCastIf(ctx.render(),
|
||||
c -> super.sqlBind0(ctx, value),
|
||||
c -> pgRenderEnumCast(c, dataType.getType(), enumValue),
|
||||
|
||||
// Postgres needs explicit casting for enum (array) types
|
||||
() -> REQUIRE_ENUM_CAST.contains(ctx.dialect()) && enumValue.getSchema() != null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2718,7 +2722,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
return Types.VARCHAR;
|
||||
}
|
||||
|
||||
static final void pgRenderEnumCast(RenderContext render, Class<?> type) {
|
||||
static final EnumType pgEnumValue(Class<?> type) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends EnumType> enumType = (Class<? extends EnumType>) (
|
||||
@ -2731,21 +2735,23 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
if (enums == null || enums.length == 0)
|
||||
throw new IllegalArgumentException("Not a valid EnumType : " + type);
|
||||
|
||||
Schema schema = enums[0].getSchema();
|
||||
if (schema != null) {
|
||||
render.sql("::");
|
||||
return enums[0];
|
||||
}
|
||||
|
||||
schema = using(render.configuration()).map(schema);
|
||||
if (schema != null && TRUE.equals(render.configuration().settings().isRenderSchema())) {
|
||||
render.visit(schema);
|
||||
render.sql('.');
|
||||
static final void pgRenderEnumCast(Context<?> ctx, Class<?> type, EnumType value) {
|
||||
Schema schema = value.getSchema();
|
||||
if (schema != null) {
|
||||
schema = using(ctx.configuration()).map(schema);
|
||||
if (schema != null && TRUE.equals(ctx.configuration().settings().isRenderSchema())) {
|
||||
ctx.visit(schema);
|
||||
ctx.sql('.');
|
||||
}
|
||||
|
||||
render.visit(name(enums[0].getName()));
|
||||
}
|
||||
ctx.visit(name(value.getName()));
|
||||
|
||||
if (type.isArray())
|
||||
render.sql("[]");
|
||||
if (type.isArray())
|
||||
ctx.sql("[]");
|
||||
}
|
||||
}
|
||||
|
||||
static final <E extends EnumType> E getEnumType(Class<? extends E> type, String literal) {
|
||||
@ -3678,7 +3684,7 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
}
|
||||
|
||||
static final class DefaultRecordBinding<U> extends InternalBinding<Record, U> {
|
||||
private static final Set<SQLDialect> REQUIRE_RECORD_CAST = SQLDialect.supportedBy(POSTGRES, YUGABYTEDB);
|
||||
static final Set<SQLDialect> REQUIRE_RECORD_CAST = SQLDialect.supportedBy(POSTGRES, YUGABYTEDB);
|
||||
|
||||
DefaultRecordBinding(DataType<Record> dataType, Converter<Record, U> converter) {
|
||||
super(dataType, converter);
|
||||
@ -3686,20 +3692,25 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
|
||||
@Override
|
||||
void sqlBind0(BindingSQLContext<U> ctx, Record value) throws SQLException {
|
||||
super.sqlBind0(ctx, value);
|
||||
|
||||
if (REQUIRE_RECORD_CAST.contains(ctx.dialect()) && value != null)
|
||||
pgRenderRecordCast(ctx.render(), value);
|
||||
Cast.renderCastIf(ctx.render(),
|
||||
c -> super.sqlBind0(ctx, value),
|
||||
c -> pgRenderRecordCast(ctx.render(), value),
|
||||
() -> REQUIRE_RECORD_CAST.contains(ctx.dialect()) && value != null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
final void sqlInline0(BindingSQLContext<U> ctx, Record value) throws SQLException {
|
||||
if (REQUIRE_RECORD_CAST.contains(ctx.dialect())) {
|
||||
ctx.render().visit(inline(PostgresUtils.toPGString(value)));
|
||||
pgRenderRecordCast(ctx.render(), value);
|
||||
}
|
||||
else
|
||||
ctx.render().sql("[UDT]");
|
||||
Cast.renderCastIf(ctx.render(),
|
||||
c -> {
|
||||
if (REQUIRE_RECORD_CAST.contains(ctx.dialect()))
|
||||
ctx.render().visit(inline(PostgresUtils.toPGString(value)));
|
||||
else
|
||||
ctx.render().sql("[UDT]");
|
||||
},
|
||||
c -> pgRenderRecordCast(ctx.render(), value),
|
||||
() -> REQUIRE_RECORD_CAST.contains(ctx.dialect())
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@ -3817,11 +3828,11 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
// interfaces. Instead, a string representation of a UDT has to be parsed
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
static final void pgRenderRecordCast(RenderContext render, Record value) {
|
||||
static final void pgRenderRecordCast(Context<?> ctx, Record value) {
|
||||
if (value instanceof UDTRecord)
|
||||
render.sql("::").visit(((UDTRecord<?>) value).getUDT().getQualifiedName());
|
||||
ctx.visit(((UDTRecord<?>) value).getUDT().getQualifiedName());
|
||||
else if (value instanceof TableRecord)
|
||||
render.sql("::").visit(((TableRecord<?>) value).getTable().getQualifiedName());
|
||||
ctx.visit(((TableRecord<?>) value).getTable().getQualifiedName());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@ -165,6 +165,33 @@ final class Extract extends AbstractField<Integer> implements QOM.Extract {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -138,7 +138,10 @@ final class JSONExists extends AbstractCondition implements JSONExistsOnStep, UN
|
||||
|
||||
case POSTGRES:
|
||||
case YUGABYTEDB:
|
||||
ctx.visit(N_JSONB_PATH_EXISTS).sql('(').visit(castIfNeeded(json, JSONB)).sql(", ").visit(path).sql("::jsonpath)");
|
||||
ctx.visit(N_JSONB_PATH_EXISTS).sql('(')
|
||||
.visit(castIfNeeded(json, JSONB)).sql(", ");
|
||||
Cast.renderCast(ctx, c -> c.visit(path), c -> c.visit(Names.N_JSONPATH));
|
||||
ctx.sql(')');
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@ -219,13 +219,13 @@ implements
|
||||
ctx,
|
||||
select(map(columns, col -> col.forOrdinality
|
||||
? DSL.field("o").as(col.field)
|
||||
: DSL.field("(jsonb_path_query_first(j, {0}::jsonpath)->>0)::{1}",
|
||||
: DSL.field("cast((jsonb_path_query_first(j, cast({0} as jsonpath))->>0) as {1})",
|
||||
col.path != null ? val(col.path) : inline("$." + col.field.getName()),
|
||||
keyword(col.type.getCastTypeName(ctx.configuration()))
|
||||
).as(col.field)))
|
||||
.from(hasOrdinality
|
||||
? "jsonb_path_query({0}, {1}::jsonpath) {with} {ordinality} {as} t(j, o)"
|
||||
: "jsonb_path_query({0}, {1}::jsonpath) {as} t(j)",
|
||||
? "jsonb_path_query({0}, cast({1} as jsonpath)) {with} {ordinality} {as} t(j, o)"
|
||||
: "jsonb_path_query({0}, cast({1} as jsonpath)) {as} t(j)",
|
||||
json.getType() == JSONB.class ? json : json.cast(JSONB),
|
||||
path
|
||||
),
|
||||
|
||||
@ -184,7 +184,7 @@ implements
|
||||
|
||||
case POSTGRES:
|
||||
case YUGABYTEDB:
|
||||
ctx.visit(function(N_JSONB_PATH_QUERY_FIRST, json.getDataType(), castIfNeeded(json, JSONB), DSL.field("{0}::jsonpath", path)));
|
||||
ctx.visit(function(N_JSONB_PATH_QUERY_FIRST, json.getDataType(), castIfNeeded(json, JSONB), DSL.field("cast({0} as jsonpath)", path)));
|
||||
break;
|
||||
|
||||
default: {
|
||||
|
||||
@ -97,6 +97,7 @@ final class Names {
|
||||
static final Name N_BIT_X_NOR = systemName("bit_xnor");
|
||||
static final Name N_BOOLAND_AGG = systemName("booland_agg");
|
||||
static final Name N_BOOLOR_AGG = systemName("boolor_agg");
|
||||
static final Name N_BYTEA = systemName("bytea");
|
||||
static final Name N_BYTE_LENGTH = systemName("byte_length");
|
||||
static final Name N_CAST = systemName("cast");
|
||||
static final Name N_CEILING = systemName("ceiling");
|
||||
@ -173,6 +174,7 @@ final class Names {
|
||||
static final Name N_JSONB_OBJECT_AGG = systemName("jsonb_object_agg");
|
||||
static final Name N_JSONB_PATH_EXISTS = systemName("jsonb_path_exists");
|
||||
static final Name N_JSONB_PATH_QUERY_FIRST = systemName("jsonb_path_query_first");
|
||||
static final Name N_JSONPATH = systemName("jsonpath");
|
||||
static final Name N_JSON_AGG = systemName("json_agg");
|
||||
static final Name N_JSON_ARRAYAGG = systemName("json_arrayagg");
|
||||
static final Name N_JSON_BUILD_ARRAY = systemName("json_build_array");
|
||||
|
||||
@ -40,6 +40,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_ROW;
|
||||
import static org.jooq.impl.Tools.getMappedUDTName;
|
||||
|
||||
@ -129,40 +130,38 @@ final class QualifiedRecordConstant<R extends QualifiedRecord<R>> extends Abstra
|
||||
}
|
||||
|
||||
private final void toSQLInline(RenderContext ctx) {
|
||||
switch (ctx.family()) {
|
||||
Cast.renderCastIf(ctx,
|
||||
c -> {
|
||||
switch (c.family()) {
|
||||
|
||||
|
||||
case POSTGRES:
|
||||
case YUGABYTEDB:
|
||||
ctx.visit(K_ROW);
|
||||
break;
|
||||
case POSTGRES:
|
||||
case YUGABYTEDB:
|
||||
c.visit(K_ROW);
|
||||
break;
|
||||
|
||||
default: {
|
||||
ctx.visit(value.getQualifier());
|
||||
break;
|
||||
}
|
||||
}
|
||||
default: {
|
||||
c.visit(value.getQualifier());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.sql('(');
|
||||
c.sql('(');
|
||||
|
||||
String separator = "";
|
||||
for (Field<?> field : value.fields()) {
|
||||
ctx.sql(separator);
|
||||
ctx.visit(val(value.get(field), field));
|
||||
separator = ", ";
|
||||
}
|
||||
String separator = "";
|
||||
for (Field<?> field : value.fields()) {
|
||||
c.sql(separator);
|
||||
c.visit(val(value.get(field), field));
|
||||
separator = ", ";
|
||||
}
|
||||
|
||||
ctx.sql(')');
|
||||
c.sql(')');
|
||||
},
|
||||
|
||||
// [#13174] Need to cast inline UDT ROW expressions to the UDT type
|
||||
switch (ctx.family()) {
|
||||
|
||||
|
||||
case POSTGRES:
|
||||
case YUGABYTEDB:
|
||||
ctx.sql("::").visit(value.getQualifier());
|
||||
break;
|
||||
}
|
||||
// [#13174] Need to cast inline UDT ROW expressions to the UDT type
|
||||
c -> c.visit(value.getQualifier()),
|
||||
() -> REQUIRE_RECORD_CAST.contains(ctx.dialect())
|
||||
);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
||||
Loading…
Reference in New Issue
Block a user