From a3060161b4263d0c52a5cfa1cfd5413bbcc84c90 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 20 Feb 2023 09:20:08 +0100 Subject: [PATCH 01/18] [jOOQ/jOOQ#14658] Get MariaDB dialect up to date --- .../java/org/jooq/codegen/JavaGenerator.java | 5 ++++ .../jooq/meta/DefaultDataTypeDefinition.java | 1 + jOOQ/src/main/java/org/jooq/DSLContext.java | 2 +- jOOQ/src/main/java/org/jooq/Field.java | 4 +-- .../java/org/jooq/InsertOnDuplicateStep.java | 4 +-- jOOQ/src/main/java/org/jooq/InsertQuery.java | 4 +-- .../java/org/jooq/JSONObjectAggNullStep.java | 1 + .../main/java/org/jooq/SelectJoinStep.java | 12 ++++---- .../java/org/jooq/impl/AbstractRoutine.java | 23 +++++++++++++++ jOOQ/src/main/java/org/jooq/impl/DSL.java | 6 ++-- jOOQ/src/main/java/org/jooq/impl/IsJson.java | 19 ++++++++++++ .../main/java/org/jooq/impl/IsNotJson.java | 1 + .../main/java/org/jooq/impl/JSONBKeys.java | 29 +++++++++++++++++++ .../src/main/java/org/jooq/impl/JSONKeys.java | 7 +++++ .../java/org/jooq/impl/JSONObjectAgg.java | 22 ++++++++++++++ jOOQ/src/main/java/org/jooq/impl/Names.java | 4 ++- .../main/java/org/jooq/impl/ParserImpl.java | 2 ++ 17 files changed, 129 insertions(+), 17 deletions(-) diff --git a/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java b/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java index 0aa439f929..af79fc65f2 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java @@ -198,6 +198,7 @@ import org.jooq.meta.jaxb.VisibilityModifier; // ... // ... import org.jooq.meta.postgres.PostgresRoutineDefinition; +// ... import org.jooq.tools.JooqLogger; import org.jooq.tools.StopWatch; import org.jooq.tools.StringUtils; @@ -8484,6 +8485,10 @@ public class JavaGenerator extends AbstractGenerator { + + + + out.println("}"); for (ParameterDefinition parameter : routine.getInParameters()) { diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/DefaultDataTypeDefinition.java b/jOOQ-meta/src/main/java/org/jooq/meta/DefaultDataTypeDefinition.java index f3e23b216c..bad10233ca 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/DefaultDataTypeDefinition.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/DefaultDataTypeDefinition.java @@ -449,6 +449,7 @@ public class DefaultDataTypeDefinition implements DataTypeDefinition { + return false; diff --git a/jOOQ/src/main/java/org/jooq/DSLContext.java b/jOOQ/src/main/java/org/jooq/DSLContext.java index 3ca43ed886..7e3a24dc84 100644 --- a/jOOQ/src/main/java/org/jooq/DSLContext.java +++ b/jOOQ/src/main/java/org/jooq/DSLContext.java @@ -11032,7 +11032,7 @@ public interface DSLContext extends Scope { * @see DSL#set(Name, Param) */ @NotNull @CheckReturnValue - @Support({ MYSQL, POSTGRES, YUGABYTEDB }) + @Support({ MARIADB, MYSQL, POSTGRES, YUGABYTEDB }) RowCountQuery set(Name name, Param value); /** diff --git a/jOOQ/src/main/java/org/jooq/Field.java b/jOOQ/src/main/java/org/jooq/Field.java index c827f1e867..c0675605ed 100644 --- a/jOOQ/src/main/java/org/jooq/Field.java +++ b/jOOQ/src/main/java/org/jooq/Field.java @@ -1259,7 +1259,7 @@ extends * Create a condition to check if this field contains JSON data. */ @NotNull - @Support({ MYSQL }) + @Support({ MARIADB, MYSQL }) Condition isJson(); /** @@ -1268,7 +1268,7 @@ extends * Create a condition to check if this field does not contain JSON data. */ @NotNull - @Support({ MYSQL }) + @Support({ MARIADB, MYSQL }) Condition isNotJson(); // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/InsertOnDuplicateStep.java b/jOOQ/src/main/java/org/jooq/InsertOnDuplicateStep.java index 42549cef73..e5ba11ab7b 100644 --- a/jOOQ/src/main/java/org/jooq/InsertOnDuplicateStep.java +++ b/jOOQ/src/main/java/org/jooq/InsertOnDuplicateStep.java @@ -106,14 +106,14 @@ public interface InsertOnDuplicateStep extends InsertReturning * Add a ON CONFLICT ON CONSTRAINT clause to this INSERT statement. */ @NotNull @CheckReturnValue - @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MYSQL, POSTGRES, YUGABYTEDB }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, YUGABYTEDB }) InsertOnConflictDoUpdateStep onConflictOnConstraint(Constraint constraint); /** * Add a ON CONFLICT ON CONSTRAINT clause to this INSERT statement. */ @NotNull @CheckReturnValue - @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MYSQL, POSTGRES, YUGABYTEDB }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, YUGABYTEDB }) InsertOnConflictDoUpdateStep onConflictOnConstraint(Name constraint); /** diff --git a/jOOQ/src/main/java/org/jooq/InsertQuery.java b/jOOQ/src/main/java/org/jooq/InsertQuery.java index 2d5121e9f7..320f082c3b 100644 --- a/jOOQ/src/main/java/org/jooq/InsertQuery.java +++ b/jOOQ/src/main/java/org/jooq/InsertQuery.java @@ -143,7 +143,7 @@ public interface InsertQuery extends StoreQuery, Insert, * ON CONFLICT ON CONSTRAINT clause in this INSERT * statement. */ - @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MYSQL, POSTGRES, YUGABYTEDB }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, YUGABYTEDB }) void onConflictOnConstraint(Name constraint); /** @@ -151,7 +151,7 @@ public interface InsertQuery extends StoreQuery, Insert, * ON CONFLICT ON CONSTRAINT clause in this INSERT * statement. */ - @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MYSQL, POSTGRES, YUGABYTEDB }) + @Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, YUGABYTEDB }) void onConflictOnConstraint(Constraint constraint); /** diff --git a/jOOQ/src/main/java/org/jooq/JSONObjectAggNullStep.java b/jOOQ/src/main/java/org/jooq/JSONObjectAggNullStep.java index c036ab29ee..8286bfcb00 100644 --- a/jOOQ/src/main/java/org/jooq/JSONObjectAggNullStep.java +++ b/jOOQ/src/main/java/org/jooq/JSONObjectAggNullStep.java @@ -48,6 +48,7 @@ import static org.jooq.SQLDialect.MARIADB; import static org.jooq.SQLDialect.MYSQL; // ... import static org.jooq.SQLDialect.POSTGRES; +// ... import static org.jooq.SQLDialect.SQLITE; import static org.jooq.SQLDialect.YUGABYTEDB; diff --git a/jOOQ/src/main/java/org/jooq/SelectJoinStep.java b/jOOQ/src/main/java/org/jooq/SelectJoinStep.java index 2a68b35175..66e7c4d590 100644 --- a/jOOQ/src/main/java/org/jooq/SelectJoinStep.java +++ b/jOOQ/src/main/java/org/jooq/SelectJoinStep.java @@ -1907,7 +1907,7 @@ public interface SelectJoinStep extends SelectWhereStep { * @see Table#straightJoin(TableLike) */ @NotNull @CheckReturnValue - @Support({ MYSQL }) + @Support({ MARIADB, MYSQL }) SelectOnStep straightJoin(TableLike table); /** @@ -1922,7 +1922,7 @@ public interface SelectJoinStep extends SelectWhereStep { * @see Table#straightJoin(SQL) */ @NotNull @CheckReturnValue - @Support({ MYSQL }) + @Support({ MARIADB, MYSQL }) @PlainSQL SelectOnStep straightJoin(SQL sql); @@ -1938,7 +1938,7 @@ public interface SelectJoinStep extends SelectWhereStep { * @see Table#straightJoin(String) */ @NotNull @CheckReturnValue - @Support({ MYSQL }) + @Support({ MARIADB, MYSQL }) @PlainSQL SelectOnStep straightJoin(String sql); @@ -1955,7 +1955,7 @@ public interface SelectJoinStep extends SelectWhereStep { * @see Table#straightJoin(String, Object...) */ @NotNull @CheckReturnValue - @Support({ MYSQL }) + @Support({ MARIADB, MYSQL }) @PlainSQL SelectOnStep straightJoin(String sql, Object... bindings); @@ -1972,7 +1972,7 @@ public interface SelectJoinStep extends SelectWhereStep { * @see Table#straightJoin(String, QueryPart...) */ @NotNull @CheckReturnValue - @Support({ MYSQL }) + @Support({ MARIADB, MYSQL }) @PlainSQL SelectOnStep straightJoin(String sql, QueryPart... parts); @@ -1983,6 +1983,6 @@ public interface SelectJoinStep extends SelectWhereStep { * @see Table#straightJoin(Name) */ @NotNull @CheckReturnValue - @Support({ MYSQL }) + @Support({ MARIADB, MYSQL }) SelectOnStep straightJoin(Name name); } diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java index 3e595a20ef..2bfc5fe4c1 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java @@ -49,6 +49,7 @@ import static org.jooq.SQLDialect.FIREBIRD; import static org.jooq.SQLDialect.POSTGRES; // ... // ... +// ... import static org.jooq.SQLDialect.YUGABYTEDB; import static org.jooq.XMLFormat.RecordFormat.COLUMN_NAME_ELEMENTS; import static org.jooq.conf.ThrowExceptions.THROW_NONE; @@ -388,6 +389,17 @@ implements return executeSelectFromPOSTGRES(); } + + + + + + + + + + + // Procedures (no return value) are always executed as CallableStatement else if (type == null) { return executeCallableStatement(); @@ -475,6 +487,14 @@ implements + + + + + + + + @@ -887,6 +907,7 @@ implements + else @@ -1094,6 +1115,7 @@ implements + else @@ -1521,6 +1543,7 @@ implements + { context.sql("? = "); } diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java index 1070fe3c6c..6d5b4b6d72 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DSL.java +++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java @@ -10013,7 +10013,7 @@ public class DSL { * @see DSLContext#set(Name, Param) */ @NotNull @CheckReturnValue - @Support({ MYSQL, POSTGRES, YUGABYTEDB }) + @Support({ MARIADB, MYSQL, POSTGRES, YUGABYTEDB }) public static org.jooq.RowCountQuery set(Name name, Param value) { return dsl().set(name, value); } @@ -23785,7 +23785,7 @@ public class DSL { } /** - * Get the REGEXP_REPLACE_ALL function. + * Get the REGEXP_REPLACE_FIRST function. */ @NotNull @Support({ MYSQL, POSTGRES, YUGABYTEDB }) @@ -23794,7 +23794,7 @@ public class DSL { } /** - * Get the REGEXP_REPLACE_ALL function. + * Get the REGEXP_REPLACE_FIRST function. */ @NotNull @Support({ MYSQL, POSTGRES, YUGABYTEDB }) diff --git a/jOOQ/src/main/java/org/jooq/impl/IsJson.java b/jOOQ/src/main/java/org/jooq/impl/IsJson.java index 0a9be1d6d8..6409dc3ed1 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsJson.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsJson.java @@ -85,6 +85,24 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- + @Override + final boolean parenthesised(Context ctx) { + switch (ctx.family()) { + case MARIADB: + case MYSQL: + return true; + + + + + + + + default: + return false; + } + } + @Override public final void accept(Context ctx) { switch (ctx.family()) { @@ -94,6 +112,7 @@ implements + case MARIADB: case MYSQL: ctx.visit(function(N_JSON_VALID, BOOLEAN, field)); break; diff --git a/jOOQ/src/main/java/org/jooq/impl/IsNotJson.java b/jOOQ/src/main/java/org/jooq/impl/IsNotJson.java index 3b15e2a35e..8a2b38cc3d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsNotJson.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsNotJson.java @@ -94,6 +94,7 @@ implements + case MARIADB: case MYSQL: ctx.visit(condition(function(N_JSON_VALID, BOOLEAN, field)).not()); break; diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONBKeys.java b/jOOQ/src/main/java/org/jooq/impl/JSONBKeys.java index f1e61496e3..7d3ea94b9e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONBKeys.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONBKeys.java @@ -91,6 +91,31 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- + @Override + final boolean parenthesised(Context ctx) { + switch (ctx.family()) { + + + case POSTGRES: + case YUGABYTEDB: + return false; + + + + + + + + + + case SQLITE: + return false; + + default: + return false; + } + } + @Override public final void accept(Context ctx) { switch (ctx.family()) { @@ -119,6 +144,10 @@ implements + + + + case SQLITE: ctx.visit(DSL.field(select(jsonbArrayAgg(DSL.field(name("key")))).from("json_each({0})", field))); break; diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONKeys.java b/jOOQ/src/main/java/org/jooq/impl/JSONKeys.java index 9f97d2e13b..45ae8c7ffd 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONKeys.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONKeys.java @@ -103,6 +103,9 @@ implements + + + case SQLITE: return false; @@ -135,6 +138,10 @@ implements + + + + case SQLITE: ctx.visit(DSL.field(select(jsonArrayAgg(DSL.field(name("key")))).from("json_each({0})", field))); break; diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java b/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java index d17e7c6a79..49c2737e86 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java @@ -48,6 +48,7 @@ import static org.jooq.impl.Names.N_JSONB_OBJECT_AGG; import static org.jooq.impl.Names.N_JSON_GROUP_OBJECT; import static org.jooq.impl.Names.N_JSON_OBJECTAGG; import static org.jooq.impl.Names.N_JSON_OBJECT_AGG; +import static org.jooq.impl.Names.N_OBJECT_AGG; import static org.jooq.impl.QOM.JSONOnNull.ABSENT_ON_NULL; import static org.jooq.impl.QOM.JSONOnNull.NULL_ON_NULL; import static org.jooq.impl.SQLDataType.BLOB; @@ -105,6 +106,10 @@ implements + + + + case POSTGRES: case YUGABYTEDB: acceptPostgres(ctx); @@ -162,6 +167,23 @@ implements acceptOverClause(ctx); } + + + + + + + + + + + + + + + + + private final void acceptGroupConcat(Context ctx) { ctx.sql('(').visit(groupConcatEmulation(ctx)).sql(')'); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index 2f0424bab3..0cd8e03e30 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -170,7 +170,6 @@ final class Names { static final Name N_JSON_TRANSFORM = systemName("json_transform"); static final Name N_JSON_TYPE = systemName("json_type"); static final Name N_JSON_UNQUOTE = systemName("json_unquote"); - static final Name N_JSON_VALID = systemName("json_valid"); static final Name N_JSON_VALUE = systemName("json_value"); static final Name N_LAG = systemName("lag"); static final Name N_LAST_VALUE = systemName("last_value"); @@ -200,6 +199,7 @@ final class Names { static final Name N_NTILE = systemName("ntile"); static final Name N_NULL = systemName("null"); static final Name N_NVL2 = systemName("nvl2"); + static final Name N_OBJECT_AGG = systemName("object_agg"); static final Name N_OBJECT_CONSTRUCT = systemName("object_construct"); static final Name N_OBJECT_CONSTRUCT_KEEP_NULL = systemName("object_construct_keep_null"); static final Name N_OFFSET = systemName("offset"); @@ -420,6 +420,7 @@ final class Names { static final Name N_JSON_REMOVE = systemName("json_remove"); static final Name N_JSON_REPLACE = systemName("json_replace"); static final Name N_JSON_SET = systemName("json_set"); + static final Name N_JSON_VALID = systemName("json_valid"); static final Name N_LCASE = systemName("lcase"); static final Name N_LEFT = systemName("left"); static final Name N_LEN = systemName("len"); @@ -443,6 +444,7 @@ final class Names { static final Name N_NEWID = systemName("newid"); static final Name N_NULLIF = systemName("nullif"); static final Name N_NVL = systemName("nvl"); + static final Name N_OBJECT_KEYS = systemName("object_keys"); static final Name N_OCTET_LENGTH = systemName("octet_length"); static final Name N_OTRANSLATE = systemName("otranslate"); static final Name N_OVERLAY = systemName("overlay"); diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index 3a8b54e51d..f9fdf068a5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -8876,6 +8876,8 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { return octetLength((Field) parseFieldParenthesised()); else if ((field = parseFieldObjectConstructIf()) != null) return field; + else if (parseFunctionNameIf("OBJECT_KEYS")) + return parseFunctionArgs1(DSL::jsonKeys); break; From 0e67112dbc348f84dcbe5d25f8507c6d0eaa1176 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 20 Feb 2023 09:30:24 +0100 Subject: [PATCH 02/18] [jOOQ/jOOQ#14653] Fix regression in MariaDB's JSON_OBJECTAGG --- .../main/java/org/jooq/impl/AbstractAggregateFunction.java | 4 ++-- jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java | 5 +++++ jOOQ/src/main/java/org/jooq/impl/ListAgg.java | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractAggregateFunction.java b/jOOQ/src/main/java/org/jooq/impl/AbstractAggregateFunction.java index b2028cabce..07f93619a0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractAggregateFunction.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractAggregateFunction.java @@ -292,10 +292,10 @@ implements else - ctx.visit(wrap(args).map((arg, i) -> applyFilter(arg, i) ? DSL.when(filter, arg == ASTERISK ? one() : arg) : arg).map(fun)); + ctx.visit(wrap(args).map((arg, i) -> applyFilter(ctx, arg, i) ? DSL.when(filter, arg == ASTERISK ? one() : arg) : arg).map(fun)); } - boolean applyFilter(Field arg, int i) { + boolean applyFilter(Context ctx, Field arg, int i) { return true; } diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java b/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java index 49c2737e86..354f475029 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java @@ -181,6 +181,11 @@ implements + + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/ListAgg.java b/jOOQ/src/main/java/org/jooq/impl/ListAgg.java index 9860f9434c..ce513bb39f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ListAgg.java +++ b/jOOQ/src/main/java/org/jooq/impl/ListAgg.java @@ -166,7 +166,7 @@ final class ListAgg extends AbstractAggregateFunction implements UNotYet } @Override - boolean applyFilter(Field arg, int i) { + boolean applyFilter(Context ctx, Field arg, int i) { return i == 0; } From 6d6a6a16f1b17b5385a5bbc517bac110e9107e8a Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 20 Feb 2023 09:36:53 +0100 Subject: [PATCH 03/18] [jOOQ/jOOQ#14653] Added parser support for OBJECT_AGG() --- jOOQ/src/main/java/org/jooq/impl/ParserImpl.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index f9fdf068a5..46c47ad184 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -10055,9 +10055,9 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { private final AggregateFilterStep parseJSONObjectAggFunctionIf() { boolean jsonb = false; + AggregateFilterStep result; if (parseFunctionNameIf("JSON_OBJECTAGG", "JSON_OBJECT_AGG", "JSON_GROUP_OBJECT") || (jsonb = parseFunctionNameIf("JSONB_OBJECT_AGG"))) { - AggregateFilterStep result; JSONObjectAggNullStep s1; JSONObjectAggReturningStep s2; JSONOnNull onNull; @@ -10075,6 +10075,14 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { parse(')'); return result; + } + else if (parseFunctionNameIf("OBJECT_AGG") && requireProEdition()) { + + + + + + } return null; From 0260b160a622a888837ca9e89bcb3092ee4e8978 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 20 Feb 2023 09:40:02 +0100 Subject: [PATCH 04/18] [jOOQ/jOOQ#14653] Fix support annotations on JSON_ARRAYAGG .. RETURNING and JSON_OBJECTAGG .. RETURNING --- jOOQ/src/main/java/org/jooq/JSONArrayAggReturningStep.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jOOQ/src/main/java/org/jooq/JSONArrayAggReturningStep.java b/jOOQ/src/main/java/org/jooq/JSONArrayAggReturningStep.java index f62f9c4bdc..5f2a75c448 100644 --- a/jOOQ/src/main/java/org/jooq/JSONArrayAggReturningStep.java +++ b/jOOQ/src/main/java/org/jooq/JSONArrayAggReturningStep.java @@ -44,8 +44,11 @@ import org.jetbrains.annotations.*; // ... // ... import static org.jooq.SQLDialect.H2; +import static org.jooq.SQLDialect.MARIADB; +import static org.jooq.SQLDialect.MYSQL; // ... import static org.jooq.SQLDialect.POSTGRES; +// ... import static org.jooq.SQLDialect.SQLITE; import static org.jooq.SQLDialect.YUGABYTEDB; @@ -65,6 +68,6 @@ public interface JSONArrayAggReturningStep extends AggregateFilterStep { * function. */ @NotNull - @Support({ H2, POSTGRES, SQLITE, YUGABYTEDB }) + @Support({ H2, MARIADB, MYSQL, POSTGRES, SQLITE, YUGABYTEDB }) AggregateFilterStep returning(DataType returning); } From 22a77ea8423e82894b71e1ad54e4e2b208433e67 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 20 Feb 2023 11:42:59 +0100 Subject: [PATCH 05/18] [jOOQ/jOOQ#14653] Support the JSON (VARIANT) data type --- .../java/org/jooq/impl/DefaultBinding.java | 22 +++++++++++ .../org/jooq/impl/FieldMapsForInsert.java | 37 +++++++++++++++---- jOOQ/src/main/java/org/jooq/impl/Names.java | 1 + 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index 20bdbfb481..9e17a9ee25 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java @@ -130,6 +130,7 @@ 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_PARSE_JSON; 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; @@ -810,6 +811,7 @@ public class DefaultBinding implements Binding { + case POSTGRES: case YUGABYTEDB: return true; @@ -941,6 +943,26 @@ public class DefaultBinding implements Binding { } private final void sqlCast(BindingSQLContext ctx, T converted, DataType t, Integer length, Integer precision, Integer scale) throws SQLException { + switch (ctx.family()) { + + + + + + + + + + + + + default: + sqlCast0(ctx, converted, t, length, precision, scale); + break; + } + } + + private final void sqlCast0(BindingSQLContext ctx, T converted, DataType t, Integer length, Integer precision, Integer scale) throws SQLException { ctx.render().visit(K_CAST).sql('('); sql(ctx, converted); ctx.render().sql(' ').visit(K_AS).sql(' ') diff --git a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java index 3ab6dcda72..ed57db4e24 100644 --- a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java +++ b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java @@ -191,6 +191,15 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple + + + + + + + + + @@ -207,19 +216,22 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple } default: { - ctx.formatSeparator() - .start(INSERT_VALUES) - .visit(K_VALUES) - .sql(' '); - toSQL92Values(ctx); - ctx.end(INSERT_VALUES); - + toSQLValues(ctx); break; } } } } + private final void toSQLValues(Context ctx) { + ctx.formatSeparator() + .start(INSERT_VALUES) + .visit(K_VALUES) + .sql(' '); + toSQL92Values(ctx); + ctx.end(INSERT_VALUES); + } + static final void toSQLInsertSelect(Context ctx, Select select) { ctx.formatSeparator() .start(INSERT_SELECT) @@ -326,6 +338,17 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple + + + + + + + + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index 0cd8e03e30..2b86a63da5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -448,6 +448,7 @@ final class Names { static final Name N_OCTET_LENGTH = systemName("octet_length"); static final Name N_OTRANSLATE = systemName("otranslate"); static final Name N_OVERLAY = systemName("overlay"); + static final Name N_PARSE_JSON = systemName("parse_json"); static final Name N_PI = systemName("pi"); static final Name N_POSITION = systemName("position"); static final Name N_PRIOR = systemName("prior"); From 0e9b6bfd91aaf3ba7634dcab35660371324092f3 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 20 Feb 2023 15:11:39 +0100 Subject: [PATCH 06/18] [jOOQ/jOOQ#14660] Work around Snowflake's INSERT .. VALUES limitation of not being able to reference expressions --- jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java | 1 + jOOQ/src/main/java/org/jooq/impl/Tools.java | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java index ed57db4e24..6ce44f4b1f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java +++ b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java @@ -357,6 +357,7 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple + default: diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 7a1c7fcba3..82aa9a755b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -3799,6 +3799,11 @@ final class Tools { return field instanceof Param; } + static final boolean isParamOrCastParam(Field field) { + return field instanceof Param + || field instanceof Cast && isParamOrCastParam(((Cast) field).$field()); + } + static final boolean isVal(Field field) { return field instanceof Val || field instanceof ConvertedVal && ((ConvertedVal) field).delegate instanceof Val; From d21c6f226114d8fb6f2f231420093a4a58304303 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 20 Feb 2023 15:14:57 +0100 Subject: [PATCH 07/18] [jOOQ/jOOQ#14653] Re-generate Names class --- jOOQ/src/main/java/org/jooq/impl/Names.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index 2b86a63da5..f2f6043801 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -207,6 +207,7 @@ final class Names { static final Name N_OPENXML = systemName("openxml"); static final Name N_ORDINAL = systemName("ordinal"); static final Name N_OREPLACE = systemName("oreplace"); + static final Name N_PARSE_JSON = systemName("parse_json"); static final Name N_PERCENTILE_CONT = systemName("percentile_cont"); static final Name N_PERCENTILE_DISC = systemName("percentile_disc"); static final Name N_PERCENT_RANK = systemName("percent_rank"); @@ -448,7 +449,6 @@ final class Names { static final Name N_OCTET_LENGTH = systemName("octet_length"); static final Name N_OTRANSLATE = systemName("otranslate"); static final Name N_OVERLAY = systemName("overlay"); - static final Name N_PARSE_JSON = systemName("parse_json"); static final Name N_PI = systemName("pi"); static final Name N_POSITION = systemName("position"); static final Name N_PRIOR = systemName("prior"); From 848b2b9b8a9c8768ccf3a402bccea785686b61fa Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 20 Feb 2023 15:17:25 +0100 Subject: [PATCH 08/18] Still javac 8 compiler hiccups --- jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index 9e17a9ee25..c5cd9cbeaa 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java @@ -5480,7 +5480,7 @@ public class DefaultBinding implements Binding { - static final class DefaultJSONBinding extends InternalBinding { + static final class DefaultJSONBinding extends InternalBinding { DefaultJSONBinding(DataType dataType, Converter converter) { super(dataType, converter); From 694f566df9571cc6d90bc5488dab64f531685d44 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 20 Feb 2023 16:12:51 +0100 Subject: [PATCH 09/18] [jOOQ/jOOQ#14653] Support JSON_GET_ATTRIBUTE and JSON_GET_ELEMENT --- .../java/org/jooq/impl/JSONBGetAttribute.java | 31 +++++++++++++++++++ .../java/org/jooq/impl/JSONBGetElement.java | 31 +++++++++++++++++++ .../java/org/jooq/impl/JSONGetAttribute.java | 31 +++++++++++++++++++ .../java/org/jooq/impl/JSONGetElement.java | 31 +++++++++++++++++++ jOOQ/src/main/java/org/jooq/impl/Names.java | 2 ++ 5 files changed, 126 insertions(+) diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONBGetAttribute.java b/jOOQ/src/main/java/org/jooq/impl/JSONBGetAttribute.java index ab5a449727..3e4648514f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONBGetAttribute.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONBGetAttribute.java @@ -92,6 +92,33 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- + @Override + final boolean parenthesised(Context ctx) { + switch (ctx.family()) { + + + + + + + + + + + + + + + + case MARIADB: + case MYSQL: + return false; + + default: + return false; + } + } + @Override public final void accept(Context ctx) { switch (ctx.family()) { @@ -123,6 +150,10 @@ implements + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONBGetElement.java b/jOOQ/src/main/java/org/jooq/impl/JSONBGetElement.java index 755a921be1..c4ff3efc83 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONBGetElement.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONBGetElement.java @@ -92,6 +92,33 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- + @Override + final boolean parenthesised(Context ctx) { + switch (ctx.family()) { + + + + + + + + + + + + + + + + case MARIADB: + case MYSQL: + return false; + + default: + return false; + } + } + @Override public final void accept(Context ctx) { switch (ctx.family()) { @@ -118,6 +145,10 @@ implements + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONGetAttribute.java b/jOOQ/src/main/java/org/jooq/impl/JSONGetAttribute.java index 908dd291b1..544557a401 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONGetAttribute.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONGetAttribute.java @@ -92,6 +92,33 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- + @Override + final boolean parenthesised(Context ctx) { + switch (ctx.family()) { + + + + + + + + + + + + + + + + case MARIADB: + case MYSQL: + return false; + + default: + return false; + } + } + @Override public final void accept(Context ctx) { switch (ctx.family()) { @@ -123,6 +150,10 @@ implements + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONGetElement.java b/jOOQ/src/main/java/org/jooq/impl/JSONGetElement.java index 61e8d67523..09ca940de8 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONGetElement.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONGetElement.java @@ -92,6 +92,33 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- + @Override + final boolean parenthesised(Context ctx) { + switch (ctx.family()) { + + + + + + + + + + + + + + + + case MARIADB: + case MYSQL: + return false; + + default: + return false; + } + } + @Override public final void accept(Context ctx) { switch (ctx.family()) { @@ -118,6 +145,10 @@ implements + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index f2f6043801..fe99da5016 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -131,6 +131,7 @@ final class Names { static final Name N_GENERATOR = systemName("generator"); static final Name N_GEN_ID = systemName("gen_id"); static final Name N_GEN_UUID = systemName("gen_uuid"); + static final Name N_GET = systemName("get"); static final Name N_GETDATE = systemName("getdate"); static final Name N_GREATEST = systemName("greatest"); static final Name N_GROUPING_SETS = systemName("grouping sets"); @@ -393,6 +394,7 @@ final class Names { static final Name N_GENERATE_UUID = systemName("generate_uuid"); static final Name N_GENGUID = systemName("genguid"); static final Name N_GEN_RANDOM_UUID = systemName("gen_random_uuid"); + static final Name N_GET = systemName("get"); static final Name N_GETBIT = systemName("getbit"); static final Name N_GET_BIT = systemName("get_bit"); static final Name N_GOTO = systemName("goto"); From cb7addce1dfc0e8fa662fd262e45118daedfe3a0 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 20 Feb 2023 20:00:47 +0100 Subject: [PATCH 10/18] [jOOQ/jOOQ#14653] Better handle the null/undefined difference in JSON_ARRAY --- jOOQ/src/main/java/org/jooq/impl/JSONArray.java | 4 ++++ .../main/java/org/jooq/impl/JSONEntryImpl.java | 17 +++++++++++++++++ jOOQ/src/main/java/org/jooq/impl/Names.java | 2 +- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONArray.java b/jOOQ/src/main/java/org/jooq/impl/JSONArray.java index a789f35962..9c7c3a19c6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONArray.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONArray.java @@ -193,6 +193,10 @@ implements + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java b/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java index 3d8841fe72..72264ce712 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java @@ -62,7 +62,9 @@ import static org.jooq.impl.Names.N_JSON_EXTRACT; import static org.jooq.impl.Names.N_JSON_MERGE; import static org.jooq.impl.Names.N_JSON_MERGE_PRESERVE; import static org.jooq.impl.Names.N_JSON_QUERY; +import static org.jooq.impl.Names.N_PARSE_JSON; import static org.jooq.impl.Names.N_RAWTOHEX; +import static org.jooq.impl.Names.N_TO_VARIANT; import static org.jooq.impl.SQLDataType.BIT; import static org.jooq.impl.SQLDataType.BOOLEAN; import static org.jooq.impl.SQLDataType.JSON; @@ -78,9 +80,11 @@ import java.util.function.Function; import org.jooq.Context; import org.jooq.DataType; import org.jooq.Field; +import org.jooq.JSON; import org.jooq.JSONEntry; import org.jooq.JSONEntryValueStep; import org.jooq.Param; +// ... import org.jooq.QueryPart; import org.jooq.Record1; // ... @@ -292,6 +296,19 @@ final class JSONEntryImpl extends AbstractQueryPart implements JSONEntry, return field; } + + + + + + + + + + + + + @SuppressWarnings("unchecked") private static Field booleanCase(Field field) { return case_((Field) field).when(inline(true), inline("true")).when(inline(false), inline("false")); diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index fe99da5016..eda0386a00 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -131,7 +131,6 @@ final class Names { static final Name N_GENERATOR = systemName("generator"); static final Name N_GEN_ID = systemName("gen_id"); static final Name N_GEN_UUID = systemName("gen_uuid"); - static final Name N_GET = systemName("get"); static final Name N_GETDATE = systemName("getdate"); static final Name N_GREATEST = systemName("greatest"); static final Name N_GROUPING_SETS = systemName("grouping sets"); @@ -276,6 +275,7 @@ final class Names { static final Name N_TIMESTAMP_SUB = systemName("timestamp_sub"); static final Name N_TO_CLOB = systemName("to_clob"); static final Name N_TO_NUMBER = systemName("to_number"); + static final Name N_TO_VARIANT = systemName("to_variant"); static final Name N_TRUNCATE = systemName("truncate"); static final Name N_TRUNCNUM = systemName("truncnum"); static final Name N_UNNEST = systemName("unnest"); From 9a641b5b915b1f69a14d4bd7567490917b2a6a3f Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 21 Feb 2023 08:42:07 +0100 Subject: [PATCH 11/18] [jOOQ/jOOQ#10018] Added kotlin extension methods --- .../main/kotlin/org/jooq/kotlin/Extensions.kt | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt b/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt index 7699b6ccd5..70d7776233 100644 --- a/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt +++ b/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt @@ -2,6 +2,7 @@ package org.jooq.kotlin import org.jetbrains.annotations.Blocking import org.jooq.* +import org.jooq.SQLDialect.* import org.jooq.impl.DSL.* import java.util.stream.Collector @@ -289,11 +290,47 @@ operator fun TableLike<*>.get(field: Field) = this.field(field) // Extensions to make Field aware of its being an array // ---------------------------------------------------------------------------- -@Support +@Support(AURORA_POSTGRES, COCKROACHDB, H2, HSQLDB, POSTGRES, YUGABYTEDB) operator fun Field>.get(index: Int) = arrayGet(this, index) -@Support -operator fun Field>.get(index: Field) = arrayGet(this, index) +@Support(AURORA_POSTGRES, COCKROACHDB, H2, HSQLDB, POSTGRES, YUGABYTEDB) +operator fun Field>.get(index: Field) = arrayGet(this, index) + +// ---------------------------------------------------------------------------- +// Extensions to make Field and Field aware of its being JSON +// ---------------------------------------------------------------------------- + +@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@JvmName("jsonGetElement") +operator fun Field.get(index: Int) = jsonGetElement(this, index) + +@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@JvmName("jsonGetElement") +operator fun Field.get(index: Field) = jsonGetElement(this, index) + +@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@JvmName("jsonGetAttribute") +operator fun Field.get(name: String) = jsonGetAttribute(this, name) + +@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@JvmName("jsonGetAttribute") +operator fun Field.get(name: Field) = jsonGetAttribute(this, name) + +@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@JvmName("jsonbGetElement") +operator fun Field.get(index: Int) = jsonbGetElement(this, index) + +@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@JvmName("jsonbGetElement") +operator fun Field.get(index: Field) = jsonbGetElement(this, index) + +@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@JvmName("jsonbGetAttribute") +operator fun Field.get(name: String) = jsonbGetAttribute(this, name) + +@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@JvmName("jsonbGetAttribute") +operator fun Field.get(name: Field) = jsonbGetAttribute(this, name) // ---------------------------------------------------------------------------- // Extensions to make Select> a scalar subquery of type Field From 6cd1481da2ecc71ccfdbf662f6026005a07b9ef7 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 21 Feb 2023 09:10:59 +0100 Subject: [PATCH 12/18] [jOOQ/jOOQ#14653] Add IS JSON support --- jOOQ/src/main/java/org/jooq/impl/IsJson.java | 8 ++++++++ jOOQ/src/main/java/org/jooq/impl/IsNotJson.java | 5 +++++ jOOQ/src/main/java/org/jooq/impl/Names.java | 1 + 3 files changed, 14 insertions(+) diff --git a/jOOQ/src/main/java/org/jooq/impl/IsJson.java b/jOOQ/src/main/java/org/jooq/impl/IsJson.java index 6409dc3ed1..9230eccc3d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsJson.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsJson.java @@ -98,6 +98,9 @@ implements + + + default: return false; } @@ -125,6 +128,11 @@ implements + + + + + default: ctx.visit(field).sql(' ').visit(K_IS_JSON); break; diff --git a/jOOQ/src/main/java/org/jooq/impl/IsNotJson.java b/jOOQ/src/main/java/org/jooq/impl/IsNotJson.java index 8a2b38cc3d..d57801cb2a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsNotJson.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsNotJson.java @@ -107,6 +107,11 @@ implements + + + + + default: ctx.visit(field).sql(' ').visit(K_IS_NOT_JSON); break; diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index eda0386a00..b5bcde4f8a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -83,6 +83,7 @@ final class Names { static final Name N_BYTE_LENGTH = systemName("byte_length"); static final Name N_CAST = systemName("cast"); static final Name N_CHARINDEX = systemName("charindex"); + static final Name N_CHECK_JSON = systemName("check_json"); static final Name N_CHOOSE = systemName("choose"); static final Name N_COLLECT = systemName("collect"); static final Name N_CONCAT = systemName("concat"); From a31028f9eeaa409f185c406394a0fba80d71a570 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 21 Feb 2023 10:01:07 +0100 Subject: [PATCH 13/18] [jOOQ/jOOQ#10018] Added kotlin extension methods --- jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt b/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt index 70d7776233..517ec31353 100644 --- a/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt +++ b/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt @@ -291,10 +291,10 @@ operator fun TableLike<*>.get(field: Field) = this.field(field) // ---------------------------------------------------------------------------- @Support(AURORA_POSTGRES, COCKROACHDB, H2, HSQLDB, POSTGRES, YUGABYTEDB) -operator fun Field>.get(index: Int) = arrayGet(this, index) +operator fun Field?>.get(index: Int) = arrayGet(this, index) @Support(AURORA_POSTGRES, COCKROACHDB, H2, HSQLDB, POSTGRES, YUGABYTEDB) -operator fun Field>.get(index: Field) = arrayGet(this, index) +operator fun Field?>.get(index: Field) = arrayGet(this, index) // ---------------------------------------------------------------------------- // Extensions to make Field and Field aware of its being JSON From cb4e8ff49b67f02e7773da312bc13af1717bc040 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 21 Feb 2023 10:33:39 +0100 Subject: [PATCH 14/18] [jOOQ/jOOQ#14665] Non-boolean field emulation should be NOT NULL aware --- .../src/main/java/org/jooq/impl/AbstractCondition.java | 9 --------- jOOQ/src/main/java/org/jooq/impl/AbstractField.java | 9 +++++++++ jOOQ/src/main/java/org/jooq/impl/Exists.java | 8 ++++---- jOOQ/src/main/java/org/jooq/impl/IsDistinctFrom.java | 10 +++++----- .../src/main/java/org/jooq/impl/IsNotDistinctFrom.java | 4 ++-- jOOQ/src/main/java/org/jooq/impl/IsNotNull.java | 8 ++++---- jOOQ/src/main/java/org/jooq/impl/IsNull.java | 8 ++++---- jOOQ/src/main/java/org/jooq/impl/JSONArray.java | 5 +++++ jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java | 2 ++ jOOQ/src/main/java/org/jooq/impl/JSONObject.java | 5 +++++ jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java | 5 +++++ jOOQ/src/main/java/org/jooq/impl/NullCondition.java | 5 ----- 12 files changed, 45 insertions(+), 33 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractCondition.java b/jOOQ/src/main/java/org/jooq/impl/AbstractCondition.java index aa4749234d..a40d3ce3a6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractCondition.java @@ -64,15 +64,6 @@ abstract class AbstractCondition extends AbstractField implements Condi super(DSL.name("condition"), SQLDataType.BOOLEAN); } - /** - * [#10179] Subclasses may override this method to indicate that the - * condition may produce TRUE, FALSE, or - * NULL. - */ - boolean isNullable() { - return true; - } - @Override public Clause[] clauses(Context ctx) { return CLAUSES; diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java index 53597bd8c4..52a56b6d52 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java @@ -121,6 +121,15 @@ implements // XXX: API (not implemented) // ------------------------------------------------------------------------ + /** + * [#10179] [#14665] Subclasses may override this method to indicate that + * the condition may produce TRUE, FALSE, or + * NULL. + */ + boolean isNullable() { + return true; + } + @Override public abstract void accept(Context ctx); diff --git a/jOOQ/src/main/java/org/jooq/impl/Exists.java b/jOOQ/src/main/java/org/jooq/impl/Exists.java index 831930af95..bac589c709 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Exists.java +++ b/jOOQ/src/main/java/org/jooq/impl/Exists.java @@ -85,15 +85,15 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- - - - private static final Clause[] CLAUSES_EXISTS = { Clause.CONDITION, Clause.CONDITION_EXISTS }; - @Override final boolean isNullable() { return false; } + + + private static final Clause[] CLAUSES_EXISTS = { Clause.CONDITION, Clause.CONDITION_EXISTS }; + @Override final boolean parenthesised(Context ctx) { return true; diff --git a/jOOQ/src/main/java/org/jooq/impl/IsDistinctFrom.java b/jOOQ/src/main/java/org/jooq/impl/IsDistinctFrom.java index 65895d475c..12698edeb7 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsDistinctFrom.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsDistinctFrom.java @@ -88,6 +88,11 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- + @Override + final boolean isNullable() { + return false; + } + static final Set EMULATE_DISTINCT_PREDICATE = SQLDialect.supportedUntil(CUBRID, DERBY); @@ -97,11 +102,6 @@ implements - @Override - final boolean isNullable() { - return false; - } - @Override public final void accept(Context ctx) { diff --git a/jOOQ/src/main/java/org/jooq/impl/IsNotDistinctFrom.java b/jOOQ/src/main/java/org/jooq/impl/IsNotDistinctFrom.java index 9f35351a72..e6f8e9b78b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsNotDistinctFrom.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsNotDistinctFrom.java @@ -88,13 +88,13 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- - - @Override final boolean isNullable() { return false; } + + @Override public final void accept(Context ctx) { diff --git a/jOOQ/src/main/java/org/jooq/impl/IsNotNull.java b/jOOQ/src/main/java/org/jooq/impl/IsNotNull.java index 16c586b29f..3a86f6eef3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsNotNull.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsNotNull.java @@ -85,15 +85,15 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- - - - private static final Clause[] CLAUSES = { Clause.CONDITION, Clause.CONDITION_IS_NOT_NULL }; - @Override final boolean isNullable() { return false; } + + + private static final Clause[] CLAUSES = { Clause.CONDITION, Clause.CONDITION_IS_NOT_NULL }; + @Override public final void accept(Context ctx) { diff --git a/jOOQ/src/main/java/org/jooq/impl/IsNull.java b/jOOQ/src/main/java/org/jooq/impl/IsNull.java index ddb045e81a..38b2c451be 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsNull.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsNull.java @@ -85,15 +85,15 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- - - - private static final Clause[] CLAUSES = { Clause.CONDITION, Clause.CONDITION_IS_NULL }; - @Override final boolean isNullable() { return false; } + + + private static final Clause[] CLAUSES = { Clause.CONDITION, Clause.CONDITION_IS_NULL }; + @Override public final void accept(Context ctx) { diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONArray.java b/jOOQ/src/main/java/org/jooq/impl/JSONArray.java index 9c7c3a19c6..0a6a78330b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONArray.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONArray.java @@ -134,6 +134,11 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- + @Override + final boolean isNullable() { + return false; + } + @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java b/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java index 72264ce712..0ce20610fd 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java @@ -309,6 +309,8 @@ final class JSONEntryImpl extends AbstractQueryPart implements JSONEntry, + + @SuppressWarnings("unchecked") private static Field booleanCase(Field field) { return case_((Field) field).when(inline(true), inline("true")).when(inline(false), inline("false")); diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONObject.java b/jOOQ/src/main/java/org/jooq/impl/JSONObject.java index 99fc79276e..80d6f35466 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONObject.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONObject.java @@ -134,6 +134,11 @@ implements // XXX: QueryPart API // ------------------------------------------------------------------------- + @Override + final boolean isNullable() { + return false; + } + @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java b/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java index 354f475029..b72a78b6b9 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java @@ -183,6 +183,11 @@ implements + + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/NullCondition.java b/jOOQ/src/main/java/org/jooq/impl/NullCondition.java index 810ea02816..d412c4e4c5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/NullCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/NullCondition.java @@ -71,11 +71,6 @@ implements static final NullCondition INSTANCE = new NullCondition(); static final Set NO_SUPPORT_UNTYPED_NULL = SQLDialect.supportedBy(DERBY, HSQLDB); - @Override - final boolean isNullable() { - return true; - } - @Override final boolean parenthesised(Context ctx) { return !NO_SUPPORT_UNTYPED_NULL.contains(ctx.dialect()) From abf66f37bd49343dfd41a043170c23c0fa15034d Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 21 Feb 2023 10:46:08 +0100 Subject: [PATCH 15/18] [jOOQ/jOOQ#14653] Support ABSENT ON NULL and NULL ON NULL also on JSON_OBJECTAGG and JSON_ARRAYAGG for Snowflake --- jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java b/jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java index 0eca206b54..f1290d3ef7 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java @@ -137,6 +137,11 @@ implements + + + + + From 14a62a47ef6dd8f7f053ef07152f98798a2c3adf Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 21 Feb 2023 12:48:29 +0100 Subject: [PATCH 16/18] [jOOQ/jOOQ#14648] Add Spatial support to Snowflake --- .../java/org/jooq/impl/DefaultBinding.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index c5cd9cbeaa..c42172cfe5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java @@ -801,12 +801,7 @@ public class DefaultBinding implements Binding { } // [#7242] [#13252] Other vendor specific types also need a lot of casting - if (dataType.isJSON() - || dataType.isXML() - - - - ) { + if (dataType.isJSON() || dataType.isXML()) { switch (ctx.family()) { @@ -822,6 +817,20 @@ public class DefaultBinding implements Binding { + + + + + + + + + + + + + + @@ -5473,6 +5482,12 @@ public class DefaultBinding implements Binding { + + + + + + From 7065b2a8dc72d666b80ae06f64da34063eb8a624 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 21 Feb 2023 13:39:02 +0100 Subject: [PATCH 17/18] [jOOQ/jOOQ#10018] No support annotations on kotlin extensions yet --- .../main/kotlin/org/jooq/kotlin/Extensions.kt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt b/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt index 517ec31353..05dafe4779 100644 --- a/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt +++ b/jOOQ-kotlin/src/main/kotlin/org/jooq/kotlin/Extensions.kt @@ -290,45 +290,45 @@ operator fun TableLike<*>.get(field: Field) = this.field(field) // Extensions to make Field aware of its being an array // ---------------------------------------------------------------------------- -@Support(AURORA_POSTGRES, COCKROACHDB, H2, HSQLDB, POSTGRES, YUGABYTEDB) +@Support operator fun Field?>.get(index: Int) = arrayGet(this, index) -@Support(AURORA_POSTGRES, COCKROACHDB, H2, HSQLDB, POSTGRES, YUGABYTEDB) +@Support operator fun Field?>.get(index: Field) = arrayGet(this, index) // ---------------------------------------------------------------------------- // Extensions to make Field and Field aware of its being JSON // ---------------------------------------------------------------------------- -@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@Support @JvmName("jsonGetElement") operator fun Field.get(index: Int) = jsonGetElement(this, index) -@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@Support @JvmName("jsonGetElement") operator fun Field.get(index: Field) = jsonGetElement(this, index) -@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@Support @JvmName("jsonGetAttribute") operator fun Field.get(name: String) = jsonGetAttribute(this, name) -@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@Support @JvmName("jsonGetAttribute") operator fun Field.get(name: Field) = jsonGetAttribute(this, name) -@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@Support @JvmName("jsonbGetElement") operator fun Field.get(index: Int) = jsonbGetElement(this, index) -@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@Support @JvmName("jsonbGetElement") operator fun Field.get(index: Field) = jsonbGetElement(this, index) -@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@Support @JvmName("jsonbGetAttribute") operator fun Field.get(name: String) = jsonbGetAttribute(this, name) -@Support(AURORA_POSTGRES, COCKROACHDB, DB2_11, MARIADB_10_2, MYSQL_5_7, ORACLE12C, POSTGRES, SNOWFLAKE, SQLITE_3_38, YUGABYTEDB) +@Support @JvmName("jsonbGetAttribute") operator fun Field.get(name: Field) = jsonbGetAttribute(this, name) From db6d2abd6ff131b413497a4089ba8f9b6bbf383b Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 21 Feb 2023 14:06:24 +0100 Subject: [PATCH 18/18] [jOOQ/jOOQ#14648] Add Spatial support to Snowflake --- jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java index 6ce44f4b1f..76bd0aeaae 100644 --- a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java +++ b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java @@ -357,6 +357,8 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple + +