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..05dafe4779 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 @@ -290,10 +291,46 @@ operator fun TableLike<*>.get(field: Field) = this.field(field) // ---------------------------------------------------------------------------- @Support -operator fun Field>.get(index: Int) = arrayGet(this, index) +operator fun Field?>.get(index: Int) = arrayGet(this, index) @Support -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 +// ---------------------------------------------------------------------------- + +@Support +@JvmName("jsonGetElement") +operator fun Field.get(index: Int) = jsonGetElement(this, index) + +@Support +@JvmName("jsonGetElement") +operator fun Field.get(index: Field) = jsonGetElement(this, index) + +@Support +@JvmName("jsonGetAttribute") +operator fun Field.get(name: String) = jsonGetAttribute(this, name) + +@Support +@JvmName("jsonGetAttribute") +operator fun Field.get(name: Field) = jsonGetAttribute(this, name) + +@Support +@JvmName("jsonbGetElement") +operator fun Field.get(index: Int) = jsonbGetElement(this, index) + +@Support +@JvmName("jsonbGetElement") +operator fun Field.get(index: Field) = jsonbGetElement(this, index) + +@Support +@JvmName("jsonbGetAttribute") +operator fun Field.get(name: String) = jsonbGetAttribute(this, name) + +@Support +@JvmName("jsonbGetAttribute") +operator fun Field.get(name: Field) = jsonbGetAttribute(this, name) // ---------------------------------------------------------------------------- // Extensions to make Select> a scalar subquery of type Field 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/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); } 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/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/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/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/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index 20bdbfb481..c42172cfe5 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; @@ -800,16 +801,12 @@ 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()) { + case POSTGRES: case YUGABYTEDB: return true; @@ -820,6 +817,20 @@ public class DefaultBinding implements Binding { + + + + + + + + + + + + + + @@ -941,6 +952,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(' ') @@ -5458,7 +5489,13 @@ 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); 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/FieldMapsForInsert.java b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java index 3ab6dcda72..76bd0aeaae 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) @@ -329,6 +341,20 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple + + + + + + + + + + + + + + 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/IsJson.java b/jOOQ/src/main/java/org/jooq/impl/IsJson.java index 0a9be1d6d8..9230eccc3d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/IsJson.java +++ b/jOOQ/src/main/java/org/jooq/impl/IsJson.java @@ -85,6 +85,27 @@ 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 +115,7 @@ implements + case MARIADB: case MYSQL: ctx.visit(function(N_JSON_VALID, BOOLEAN, field)); break; @@ -106,6 +128,11 @@ implements + + + + + default: ctx.visit(field).sql(' ').visit(K_IS_JSON); break; 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/IsNotJson.java b/jOOQ/src/main/java/org/jooq/impl/IsNotJson.java index 3b15e2a35e..d57801cb2a 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; @@ -106,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/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 a789f35962..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 @@ -193,6 +198,10 @@ implements + + + + 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 + + + + + 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/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/JSONEntryImpl.java b/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java index 3d8841fe72..0ce20610fd 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,21 @@ 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/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/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/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 d17e7c6a79..b72a78b6b9 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,33 @@ 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/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; } diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index 2f0424bab3..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"); @@ -170,7 +171,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 +200,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"); @@ -207,6 +208,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"); @@ -274,6 +276,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"); @@ -392,6 +395,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"); @@ -420,6 +424,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 +448,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/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()) diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index 3a8b54e51d..46c47ad184 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; @@ -10053,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; @@ -10073,6 +10075,14 @@ final class DefaultParseContext extends AbstractScope implements ParseContext { parse(')'); return result; + } + else if (parseFunctionNameIf("OBJECT_AGG") && requireProEdition()) { + + + + + + } return null; 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;