diff --git a/jOOQ/src/main/java/org/jooq/JSONArrayAggNullStep.java b/jOOQ/src/main/java/org/jooq/JSONArrayAggNullStep.java index f765fb019e..2e7bd149b4 100644 --- a/jOOQ/src/main/java/org/jooq/JSONArrayAggNullStep.java +++ b/jOOQ/src/main/java/org/jooq/JSONArrayAggNullStep.java @@ -55,19 +55,19 @@ import org.jooq.impl.DSL; * * @author Lukas Eder */ -public interface JSONArrayAggNullStep extends AggregateFilterStep { +public interface JSONArrayAggNullStep extends JSONArrayAggReturningStep { /** * Include NULL values in output JSON. */ @NotNull @Support({ H2, POSTGRES }) - AggregateFilterStep nullOnNull(); + JSONArrayAggReturningStep nullOnNull(); /** * Exclude NULL values in output JSON. */ @NotNull @Support({ H2, POSTGRES }) - AggregateFilterStep absentOnNull(); + JSONArrayAggReturningStep absentOnNull(); } diff --git a/jOOQ/src/main/java/org/jooq/JSONArrayAggReturningStep.java b/jOOQ/src/main/java/org/jooq/JSONArrayAggReturningStep.java new file mode 100644 index 0000000000..886f40ae3f --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/JSONArrayAggReturningStep.java @@ -0,0 +1,67 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq; + +import org.jetbrains.annotations.*; + + +// ... +// ... +import static org.jooq.SQLDialect.H2; +// ... +import static org.jooq.SQLDialect.POSTGRES; + +import org.jooq.impl.DSL; + +/** + * A step in the construction of {@link DSL#jsonArrayAgg(Field)} or + * {@link DSL#jsonbArrayAgg(Field)} functions where the RETURNING + * clause can be defined. + * + * @author Lukas Eder + */ +public interface JSONArrayAggReturningStep extends AggregateFilterStep { + + /** + * Add a RETURNING clause to the JSON_ARRAYAGG + * function. + */ + @NotNull + @Support({ H2, POSTGRES }) + AggregateFilterStep returning(DataType returning); +} diff --git a/jOOQ/src/main/java/org/jooq/JSONArrayNullStep.java b/jOOQ/src/main/java/org/jooq/JSONArrayNullStep.java index 005dbadc4c..31769b991e 100644 --- a/jOOQ/src/main/java/org/jooq/JSONArrayNullStep.java +++ b/jOOQ/src/main/java/org/jooq/JSONArrayNullStep.java @@ -37,40 +37,51 @@ */ package org.jooq; +import static org.jooq.SQLDialect.*; + +import java.util.*; + 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 org.jooq.impl.DSL; - /** - * A step in the construction of {@link DSL#jsonArray(Field...)} or - * {@link DSL#jsonbArray(Field...)} functions where the NULL clause - * can be defined. - * - * @author Lukas Eder + * A step in the construction of the JSON ARRAY function. + *

+ *

Referencing XYZ*Step types directly from client code

+ *

+ * It is usually not recommended to reference any XYZ*Step types + * directly from client code, or assign them to local variables. When writing + * dynamic SQL, creating a statement's components dynamically, and passing them + * to the DSL API statically is usually a better choice. See the manual's + * section about dynamic SQL for details: https://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql. + *

+ * Drawbacks of referencing the XYZ*Step types directly: + *

    + *
  • They're operating on mutable implementations (as of jOOQ 3.x)
  • + *
  • They're less composable and not easy to get right when dynamic SQL gets + * complex
  • + *
  • They're less readable
  • + *
  • They might have binary incompatible changes between minor releases
  • + *
*/ -public interface JSONArrayNullStep extends Field { +@SuppressWarnings({ "unused" }) +public interface JSONArrayNullStep extends JSONArrayReturningStep { /** + * Add the NULL ON NULL clause to the JSON ARRAY function. + *

* Include NULL values in output JSON. */ - @NotNull @Support({ H2, MARIADB, MYSQL, POSTGRES }) - Field nullOnNull(); + @NotNull + JSONArrayReturningStep nullOnNull(); /** + * Add the ABSENT ON NULL clause to the JSON ARRAY function. + *

* Exclude NULL values in output JSON. */ - @NotNull @Support({ H2, POSTGRES }) - Field absentOnNull(); + @NotNull + JSONArrayReturningStep absentOnNull(); } diff --git a/jOOQ/src/main/java/org/jooq/JSONArrayReturningStep.java b/jOOQ/src/main/java/org/jooq/JSONArrayReturningStep.java new file mode 100644 index 0000000000..523b523001 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/JSONArrayReturningStep.java @@ -0,0 +1,76 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq; + +import static org.jooq.SQLDialect.*; + +import java.util.*; + +import org.jetbrains.annotations.*; + +/** + * A step in the construction of the JSON ARRAY function. + *

+ *

Referencing XYZ*Step types directly from client code

+ *

+ * It is usually not recommended to reference any XYZ*Step types + * directly from client code, or assign them to local variables. When writing + * dynamic SQL, creating a statement's components dynamically, and passing them + * to the DSL API statically is usually a better choice. See the manual's + * section about dynamic SQL for details: https://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql. + *

+ * Drawbacks of referencing the XYZ*Step types directly: + *

    + *
  • They're operating on mutable implementations (as of jOOQ 3.x)
  • + *
  • They're less composable and not easy to get right when dynamic SQL gets + * complex
  • + *
  • They're less readable
  • + *
  • They might have binary incompatible changes between minor releases
  • + *
+ */ +@SuppressWarnings({ "unused" }) +public interface JSONArrayReturningStep extends Field { + + /** + * Add the RETURNING clause to the JSON ARRAY function. + */ + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + @NotNull + Field returning(DataType returning); +} diff --git a/jOOQ/src/main/java/org/jooq/JSONObjectAggNullStep.java b/jOOQ/src/main/java/org/jooq/JSONObjectAggNullStep.java index c518f1c450..5ed626d504 100644 --- a/jOOQ/src/main/java/org/jooq/JSONObjectAggNullStep.java +++ b/jOOQ/src/main/java/org/jooq/JSONObjectAggNullStep.java @@ -58,19 +58,19 @@ import org.jooq.impl.DSL; * * @author Lukas Eder */ -public interface JSONObjectAggNullStep extends AggregateFilterStep { +public interface JSONObjectAggNullStep extends JSONObjectAggReturningStep { /** * Include NULL values in output JSON. */ @NotNull @Support({ H2, MARIADB, MYSQL, POSTGRES }) - AggregateFilterStep nullOnNull(); + JSONObjectAggReturningStep nullOnNull(); /** * Exclude NULL values in output JSON. */ @NotNull @Support({ H2, MARIADB, MYSQL, POSTGRES }) - AggregateFilterStep absentOnNull(); + JSONObjectAggReturningStep absentOnNull(); } diff --git a/jOOQ/src/main/java/org/jooq/JSONObjectAggReturningStep.java b/jOOQ/src/main/java/org/jooq/JSONObjectAggReturningStep.java new file mode 100644 index 0000000000..30d91ca46b --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/JSONObjectAggReturningStep.java @@ -0,0 +1,70 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq; + +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 org.jooq.impl.DSL; + +/** + * A step in the construction of {@link DSL#jsonObjectAgg(JSONEntry)} or + * {@link DSL#jsonbObjectAgg(JSONEntry)} functions where the + * RETURNING clause can be defined. + * + * @author Lukas Eder + */ +public interface JSONObjectAggReturningStep extends AggregateFilterStep { + + /** + * Add a RETURNING clause to the JSON_ARRAYAGG + * function. + */ + @NotNull + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + AggregateFilterStep returning(DataType returning); +} diff --git a/jOOQ/src/main/java/org/jooq/JSONObjectNullStep.java b/jOOQ/src/main/java/org/jooq/JSONObjectNullStep.java index bf1cd342a4..c36aa5f9a2 100644 --- a/jOOQ/src/main/java/org/jooq/JSONObjectNullStep.java +++ b/jOOQ/src/main/java/org/jooq/JSONObjectNullStep.java @@ -37,41 +37,51 @@ */ package org.jooq; +import static org.jooq.SQLDialect.*; + +import java.util.*; + 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 org.jooq.impl.DSL; - /** - * A step in the construction of {@link DSL#jsonObject(JSONEntry...)} or - * {@link DSL#jsonbObject(JSONEntry...)} functions where the NULL - * clause can be defined. - * - * @author Lukas Eder + * A step in the construction of the JSON OBJECT function. + *

+ *

Referencing XYZ*Step types directly from client code

+ *

+ * It is usually not recommended to reference any XYZ*Step types + * directly from client code, or assign them to local variables. When writing + * dynamic SQL, creating a statement's components dynamically, and passing them + * to the DSL API statically is usually a better choice. See the manual's + * section about dynamic SQL for details: https://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql. + *

+ * Drawbacks of referencing the XYZ*Step types directly: + *

    + *
  • They're operating on mutable implementations (as of jOOQ 3.x)
  • + *
  • They're less composable and not easy to get right when dynamic SQL gets + * complex
  • + *
  • They're less readable
  • + *
  • They might have binary incompatible changes between minor releases
  • + *
*/ -public interface JSONObjectNullStep extends Field { +@SuppressWarnings({ "unused" }) +public interface JSONObjectNullStep extends JSONObjectReturningStep { /** + * Add the NULL ON NULL clause to the JSON OBJECT function. + *

* Include NULL values in output JSON. */ - @NotNull @Support({ H2, MARIADB, MYSQL, POSTGRES }) - Field nullOnNull(); + @NotNull + JSONObjectReturningStep nullOnNull(); /** + * Add the ABSENT ON NULL clause to the JSON OBJECT function. + *

* Exclude NULL values in output JSON. */ - @NotNull @Support({ H2, POSTGRES }) - Field absentOnNull(); + @NotNull + JSONObjectReturningStep absentOnNull(); } diff --git a/jOOQ/src/main/java/org/jooq/JSONObjectReturningStep.java b/jOOQ/src/main/java/org/jooq/JSONObjectReturningStep.java new file mode 100644 index 0000000000..012e1bba1a --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/JSONObjectReturningStep.java @@ -0,0 +1,76 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq; + +import static org.jooq.SQLDialect.*; + +import java.util.*; + +import org.jetbrains.annotations.*; + +/** + * A step in the construction of the JSON OBJECT function. + *

+ *

Referencing XYZ*Step types directly from client code

+ *

+ * It is usually not recommended to reference any XYZ*Step types + * directly from client code, or assign them to local variables. When writing + * dynamic SQL, creating a statement's components dynamically, and passing them + * to the DSL API statically is usually a better choice. See the manual's + * section about dynamic SQL for details: https://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql. + *

+ * Drawbacks of referencing the XYZ*Step types directly: + *

    + *
  • They're operating on mutable implementations (as of jOOQ 3.x)
  • + *
  • They're less composable and not easy to get right when dynamic SQL gets + * complex
  • + *
  • They're less readable
  • + *
  • They might have binary incompatible changes between minor releases
  • + *
+ */ +@SuppressWarnings({ "unused" }) +public interface JSONObjectReturningStep extends Field { + + /** + * Add the RETURNING clause to the JSON OBJECT function. + */ + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + @NotNull + Field returning(DataType returning); +} diff --git a/jOOQ/src/main/java/org/jooq/JSONValueOnStep.java b/jOOQ/src/main/java/org/jooq/JSONValueOnStep.java index 3b387947af..f37546af38 100644 --- a/jOOQ/src/main/java/org/jooq/JSONValueOnStep.java +++ b/jOOQ/src/main/java/org/jooq/JSONValueOnStep.java @@ -52,7 +52,7 @@ import org.jooq.impl.DSL; * * @author Lukas Eder */ -public interface JSONValueOnStep extends Field { +public interface JSONValueOnStep extends JSONValueReturningStep { diff --git a/jOOQ/src/main/java/org/jooq/JSONValueReturningStep.java b/jOOQ/src/main/java/org/jooq/JSONValueReturningStep.java new file mode 100644 index 0000000000..71a7c940b4 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/JSONValueReturningStep.java @@ -0,0 +1,76 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq; + +import static org.jooq.SQLDialect.*; + +import java.util.*; + +import org.jetbrains.annotations.*; + +/** + * A step in the construction of the JSON VALUE function. + *

+ *

Referencing XYZ*Step types directly from client code

+ *

+ * It is usually not recommended to reference any XYZ*Step types + * directly from client code, or assign them to local variables. When writing + * dynamic SQL, creating a statement's components dynamically, and passing them + * to the DSL API statically is usually a better choice. See the manual's + * section about dynamic SQL for details: https://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql. + *

+ * Drawbacks of referencing the XYZ*Step types directly: + *

    + *
  • They're operating on mutable implementations (as of jOOQ 3.x)
  • + *
  • They're less composable and not easy to get right when dynamic SQL gets + * complex
  • + *
  • They're less readable
  • + *
  • They might have binary incompatible changes between minor releases
  • + *
+ */ +@SuppressWarnings({ "unused" }) +public interface JSONValueReturningStep extends Field { + + /** + * Add the RETURNING clause to the JSON VALUE function. + */ + @Support({ MARIADB, MYSQL, POSTGRES }) + @NotNull + Field returning(DataType returning); +} diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java index 7f440445d5..674952e0bb 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DSL.java +++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java @@ -18389,6 +18389,100 @@ public class DSL { return new Xmlforest(fields); } + // ------------------------------------------------------------------------- + // JSON functions + // ------------------------------------------------------------------------- + + /** + * The JSON_ARRAY function. + */ + @NotNull + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + public static JSONArrayNullStep jsonArray(Field... fields) { + return new JSONArray<>(SQLDataType.JSON, Arrays.asList(fields)); + } + + /** + * The JSON_ARRAY function. + */ + @NotNull + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + public static JSONArrayNullStep jsonArray(Collection> fields) { + return new JSONArray<>(SQLDataType.JSON, fields); + } + + /** + * The JSONB_ARRAY function. + */ + @NotNull + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + public static JSONArrayNullStep jsonbArray(Field... fields) { + return new JSONArray<>(SQLDataType.JSONB, Arrays.asList(fields)); + } + + /** + * The JSONB_ARRAY function. + */ + @NotNull + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + public static JSONArrayNullStep jsonbArray(Collection> fields) { + return new JSONArray<>(SQLDataType.JSONB, fields); + } + + /** + * The JSON_OBJECT function. + */ + @NotNull + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + public static JSONObjectNullStep jsonObject(Field... entries) { + return new JSONObject<>(SQLDataType.JSON, Tools.jsonEntries(entries)); + } + + /** + * The JSON_OBJECT function. + */ + @NotNull + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + public static JSONObjectNullStep jsonObject(JSONEntry... entries) { + return new JSONObject<>(SQLDataType.JSON, Arrays.asList(entries)); + } + + /** + * The JSON_OBJECT function. + */ + @NotNull + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + public static JSONObjectNullStep jsonObject(Collection> entries) { + return new JSONObject<>(SQLDataType.JSON, entries); + } + + /** + * The JSONB_OBJECT function. + */ + @NotNull + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + public static JSONObjectNullStep jsonbObject(Field... entries) { + return new JSONObject<>(SQLDataType.JSONB, Tools.jsonEntries(entries)); + } + + /** + * The JSONB_OBJECT function. + */ + @NotNull + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + public static JSONObjectNullStep jsonbObject(JSONEntry... entries) { + return new JSONObject<>(SQLDataType.JSONB, Arrays.asList(entries)); + } + + /** + * The JSONB_OBJECT function. + */ + @NotNull + @Support({ H2, MARIADB, MYSQL, POSTGRES }) + public static JSONObjectNullStep jsonbObject(Collection> entries) { + return new JSONObject<>(SQLDataType.JSONB, entries); + } + @@ -22228,7 +22322,7 @@ public class DSL { @NotNull @Support({ MARIADB, MYSQL, POSTGRES }) public static JSONValueOnStep jsonValue(Field json, Field path) { - return new JSONValue<>(SQLDataType.JSON, json, path); + return new JSONValue<>(SQLDataType.JSON, json, path, null); } /** @@ -22246,43 +22340,7 @@ public class DSL { @NotNull @Support({ MARIADB, MYSQL, POSTGRES }) public static JSONValueOnStep jsonbValue(Field json, Field path) { - return new JSONValue<>(SQLDataType.JSONB, json, path); - } - - /** - * The JSON array constructor. - */ - @NotNull - @Support({ H2, MARIADB, MYSQL, POSTGRES }) - public static JSONArrayNullStep jsonArray(Field... fields) { - return jsonArray(Arrays.asList(fields)); - } - - /** - * The JSON array constructor. - */ - @NotNull - @Support({ H2, MARIADB, MYSQL, POSTGRES }) - public static JSONArrayNullStep jsonArray(Collection> fields) { - return new JSONArray<>(JSON, fields); - } - - /** - * The JSONB array constructor. - */ - @NotNull - @Support({ H2, MARIADB, MYSQL, POSTGRES }) - public static JSONArrayNullStep jsonbArray(Field... fields) { - return jsonbArray(Arrays.asList(fields)); - } - - /** - * The JSONB array constructor. - */ - @NotNull - @Support({ H2, MARIADB, MYSQL, POSTGRES }) - public static JSONArrayNullStep jsonbArray(Collection> fields) { - return new JSONArray<>(JSONB, fields); + return new JSONValue<>(SQLDataType.JSONB, json, path, null); } /** @@ -22379,63 +22437,6 @@ public class DSL { return jsonObject(Tools.EMPTY_JSONENTRY); } - /** - * The JSON object constructor. - */ - @NotNull - @Support({ H2, MARIADB, MYSQL, POSTGRES }) - public static JSONObjectNullStep jsonObject(Field... entries) { - return jsonObject(Tools.jsonEntries(entries)); - } - - /** - * The JSON object constructor. - */ - @NotNull - @Support({ H2, MARIADB, MYSQL, POSTGRES }) - public static JSONObjectNullStep jsonObject(JSONEntry... entries) { - return jsonObject(Arrays.asList(entries)); - } - - /** - * The JSON object constructor. - */ - @NotNull - @Support({ H2, MARIADB, MYSQL, POSTGRES }) - public static JSONObjectNullStep jsonObject(Collection> entries) { - return new JSONObject<>(JSON, entries); - } - - /** - * The JSONB object constructor. - *

- * This is the same as calling {@link #jsonEntry(String, Field)} with - * {@link Field#getName()} as a key. - */ - @NotNull - @Support({ H2, MARIADB, MYSQL, POSTGRES }) - public static JSONObjectNullStep jsonbObject(Field... entries) { - return jsonbObject(Tools.jsonEntries(entries)); - } - - /** - * The JSONB object constructor. - */ - @NotNull - @Support({ H2, MARIADB, MYSQL, POSTGRES }) - public static JSONObjectNullStep jsonbObject(JSONEntry... entries) { - return jsonbObject(Arrays.asList(entries)); - } - - /** - * The JSONB object constructor. - */ - @NotNull - @Support({ H2, MARIADB, MYSQL, POSTGRES }) - public static JSONObjectNullStep jsonbObject(Collection> entries) { - return new JSONObject<>(JSONB, entries); - } - /** * The JSON array aggregate function. */ diff --git a/jOOQ/src/main/java/org/jooq/impl/DropSchemaImpl.java b/jOOQ/src/main/java/org/jooq/impl/DropSchemaImpl.java index f094286196..9a1efd99a5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DropSchemaImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/DropSchemaImpl.java @@ -160,7 +160,7 @@ implements private void accept0(Context ctx) { if (dropSchemaIfExists && !supportsIfExists(ctx)) - tryCatch(ctx, DDLStatementType.DROP_SCHEMA, c -> accept0(c)); + tryCatch(ctx, DDLStatementType.DROP_SCHEMA, c -> accept1(c)); else accept1(ctx); } diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONArray.java b/jOOQ/src/main/java/org/jooq/impl/JSONArray.java index a52dd814e7..2e340774ca 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONArray.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONArray.java @@ -37,56 +37,71 @@ */ package org.jooq.impl; -import static org.jooq.SQLDialect.H2; -import static org.jooq.impl.DSL.jsonArrayAgg; -import static org.jooq.impl.DSL.jsonbArrayAgg; -import static org.jooq.impl.DSL.row; -import static org.jooq.impl.DSL.select; -import static org.jooq.impl.DSL.values; -import static org.jooq.impl.JSONEntryImpl.jsonCastMapper; -import static org.jooq.impl.JSONNull.JSONNullType.ABSENT_ON_NULL; -import static org.jooq.impl.JSONNull.JSONNullType.NULL_ON_NULL; -import static org.jooq.impl.Keywords.K_JSON_ARRAY; -import static org.jooq.impl.Names.N_JSONB_BUILD_ARRAY; -import static org.jooq.impl.Names.N_JSON_ARRAY; -import static org.jooq.impl.Names.N_JSON_BUILD_ARRAY; -import static org.jooq.impl.QueryPartListView.wrap; -import static org.jooq.impl.SQLDataType.JSON; +import static org.jooq.impl.DSL.*; +import static org.jooq.impl.Internal.*; +import static org.jooq.impl.Keywords.*; +import static org.jooq.impl.Names.*; +import static org.jooq.impl.SQLDataType.*; +import static org.jooq.impl.Tools.*; +import static org.jooq.impl.Tools.BooleanDataKey.*; +import static org.jooq.impl.Tools.DataExtendedKey.*; +import static org.jooq.impl.Tools.DataKey.*; +import static org.jooq.SQLDialect.*; -import java.util.Collection; +import org.jooq.*; +import org.jooq.conf.*; +import org.jooq.impl.*; +import org.jooq.tools.*; -import org.jooq.Context; -import org.jooq.DataType; -import org.jooq.Field; -import org.jooq.JSONArrayNullStep; -import org.jooq.Row1; -import org.jooq.Table; -import org.jooq.impl.JSONNull.JSONNullType; +import java.util.*; /** - * The JSON array constructor. - * - * @author Lukas Eder + * The JSON ARRAY statement. */ -final class JSONArray extends AbstractField implements JSONArrayNullStep { +@SuppressWarnings({ "hiding", "rawtypes", "unchecked", "unused" }) +final class JSONArray +extends + AbstractField +implements + JSONArrayNullStep, + JSONArrayReturningStep +{ - /** - * Generated UID - */ - private static final long serialVersionUID = 1772007627336725780L; - private final QueryPartList> args; - private final JSONNullType nullType; + private static final long serialVersionUID = 1L; - JSONArray(DataType type, Collection> args) { - this(type, args, null); + private final DataType type; + private final Collection> fields; + private JSONOnNull onNull; + private DataType returning; + + JSONArray( + DataType type, + Collection> fields + ) { + this( + type, + fields, + null, + null + ); } - JSONArray(DataType type, Collection> args, JSONNullType nullType) { - super(N_JSON_ARRAY, type); + JSONArray( + DataType type, + Collection> fields, + JSONOnNull onNull, + DataType returning + ) { + super( + N_JSON_ARRAY, + type + ); - this.args = new QueryPartList<>(args); - this.nullType = nullType; + this.type = type; + this.fields = fields; + this.onNull = onNull; + this.returning = returning; } // ------------------------------------------------------------------------- @@ -94,20 +109,29 @@ final class JSONArray extends AbstractField implements JSONArrayNullStep nullOnNull() { - return new JSONArray<>(getDataType(), args, NULL_ON_NULL); + public final JSONArray nullOnNull() { + this.onNull = JSONOnNull.NULL_ON_NULL; + return this; } @Override - public final JSONArray absentOnNull() { - return new JSONArray<>(getDataType(), args, ABSENT_ON_NULL); + public final JSONArray absentOnNull() { + this.onNull = JSONOnNull.ABSENT_ON_NULL; + return this; + } + + @Override + public final JSONArray returning(DataType returning) { + this.returning = returning; + return this; } // ------------------------------------------------------------------------- // XXX: QueryPart API // ------------------------------------------------------------------------- - @SuppressWarnings({ "rawtypes", "unchecked" }) + + @Override public void accept(Context ctx) { switch (ctx.family()) { @@ -117,11 +141,12 @@ final class JSONArray extends AbstractField implements JSONArrayNullStep field : fields) + rows[i++] = row(field); Table t = values(rows).as("t", "a"); Field a = t.field("a"); @@ -132,23 +157,51 @@ final class JSONArray extends AbstractField implements JSONArrayNullStep>) fields).map(JSONEntryImpl.jsonCastMapper(ctx)), + jsonNull, + jsonReturning + ).separator("") + ).sql(')'); - ctx.visit(K_JSON_ARRAY).sql('(').visit(wrap(wrap(args).map(jsonCastMapper(ctx)), jsonNull).separator("")).sql(')'); break; } } } + + + + // ------------------------------------------------------------------------- + // The Object API + // ------------------------------------------------------------------------- + + @Override + public boolean equals(Object that) { + if (that instanceof JSONArray) { + return + StringUtils.equals(type, ((JSONArray) that).type) && + StringUtils.equals(fields, ((JSONArray) that).fields) && + StringUtils.equals(onNull, ((JSONArray) that).onNull) && + StringUtils.equals(returning, ((JSONArray) that).returning) + ; + } + else + return super.equals(that); + } } diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java b/jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java index 40e257df9e..ca2b01aba9 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONArrayAgg.java @@ -44,8 +44,8 @@ import static org.jooq.impl.DSL.function; import static org.jooq.impl.DSL.groupConcat; import static org.jooq.impl.DSL.inline; import static org.jooq.impl.JSONEntryImpl.jsonCast; -import static org.jooq.impl.JSONNull.JSONNullType.ABSENT_ON_NULL; -import static org.jooq.impl.JSONNull.JSONNullType.NULL_ON_NULL; +import static org.jooq.impl.JSONOnNull.ABSENT_ON_NULL; +import static org.jooq.impl.JSONOnNull.NULL_ON_NULL; import static org.jooq.impl.Names.N_JSONB_AGG; import static org.jooq.impl.Names.N_JSON_AGG; import static org.jooq.impl.Names.N_JSON_ARRAYAGG; @@ -57,13 +57,15 @@ import static org.jooq.impl.SQLDataType.VARCHAR; import java.util.Collection; import java.util.Set; +import org.jooq.AggregateFilterStep; import org.jooq.Context; import org.jooq.DataType; import org.jooq.Field; import org.jooq.JSONArrayAggOrderByStep; import org.jooq.OrderField; import org.jooq.SQLDialect; -import org.jooq.impl.JSONNull.JSONNullType; + +import org.jetbrains.annotations.NotNull; /** @@ -81,7 +83,8 @@ implements JSONArrayAggOrderByStep { private static final long serialVersionUID = 1772007627336725780L; static final Set EMULATE_WITH_GROUP_CONCAT = SQLDialect.supportedBy(MARIADB, MYSQL); - private JSONNullType nullType; + private JSONOnNull onNull; + private DataType returning; JSONArrayAgg(DataType type, Field arg) { super(false, N_JSON_ARRAYAGG, type, arg); @@ -117,7 +120,7 @@ implements JSONArrayAggOrderByStep { ctx.sql(')'); // TODO: What about a user-defined filter clause? - if (nullType == ABSENT_ON_NULL) + if (onNull == ABSENT_ON_NULL) acceptFilterClause(ctx, arguments.get(0).isNotNull()); break; @@ -161,22 +164,32 @@ implements JSONArrayAggOrderByStep { ctx.visit(jsonCast(ctx, arguments.get(0))); acceptOrderBy(ctx); - JSONNull jsonNull = new JSONNull(nullType); + JSONNull jsonNull = new JSONNull(onNull); if (jsonNull.rendersContent(ctx)) ctx.sql(' ').visit(jsonNull); + JSONReturning jsonReturning = new JSONReturning(returning); + if (jsonReturning.rendersContent(ctx)) + ctx.sql(' ').visit(jsonReturning); + ctx.sql(')'); } @Override public final JSONArrayAgg nullOnNull() { - nullType = NULL_ON_NULL; + onNull = NULL_ON_NULL; return this; } @Override public final JSONArrayAgg absentOnNull() { - nullType = ABSENT_ON_NULL; + onNull = ABSENT_ON_NULL; + return this; + } + + @Override + public final JSONArrayAgg returning(DataType r) { + this.returning = r; return this; } diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java b/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java index 3d38c967c9..199987d595 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONEntryImpl.java @@ -140,7 +140,7 @@ final class JSONEntryImpl extends AbstractQueryPart implements JSONEntry, } } - static final Function, Field> jsonCastMapper(final Context ctx) { + static final Function, ? extends Field> jsonCastMapper(final Context ctx) { return field -> jsonCast(ctx, field); } diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONNull.java b/jOOQ/src/main/java/org/jooq/impl/JSONNull.java index cacb2ec986..645c0668c8 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONNull.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONNull.java @@ -39,8 +39,8 @@ package org.jooq.impl; import static org.jooq.SQLDialect.MARIADB; import static org.jooq.SQLDialect.MYSQL; -import static org.jooq.impl.JSONNull.JSONNullType.ABSENT_ON_NULL; -import static org.jooq.impl.JSONNull.JSONNullType.NULL_ON_NULL; +import static org.jooq.impl.JSONOnNull.ABSENT_ON_NULL; +import static org.jooq.impl.JSONOnNull.NULL_ON_NULL; import static org.jooq.impl.Keywords.K_ABSENT; import static org.jooq.impl.Keywords.K_NULL; import static org.jooq.impl.Keywords.K_ON; @@ -61,9 +61,9 @@ final class JSONNull extends AbstractQueryPart { private static final long serialVersionUID = 3121287280045911346L; static final Set NO_SUPPORT_ABSENT_ON_NULL = SQLDialect.supportedBy(MARIADB, MYSQL); - final JSONNullType type; + final JSONOnNull type; - JSONNull(JSONNullType type) { + JSONNull(JSONOnNull type) { this.type = type; } @@ -80,8 +80,4 @@ final class JSONNull extends AbstractQueryPart { else if (type == ABSENT_ON_NULL) ctx.visit(K_ABSENT).sql(' ').visit(K_ON).sql(' ').visit(K_NULL); } - - enum JSONNullType { - NULL_ON_NULL, ABSENT_ON_NULL - } } diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONObject.java b/jOOQ/src/main/java/org/jooq/impl/JSONObject.java index 79c470c607..f7d34d2f1b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONObject.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONObject.java @@ -37,64 +37,71 @@ */ package org.jooq.impl; -import static org.jooq.SQLDialect.H2; -// ... -import static org.jooq.impl.DSL.asterisk; -import static org.jooq.impl.DSL.inline; -import static org.jooq.impl.DSL.jsonEntry; -import static org.jooq.impl.DSL.jsonObject; -import static org.jooq.impl.DSL.key; -import static org.jooq.impl.DSL.row; -import static org.jooq.impl.DSL.select; -import static org.jooq.impl.DSL.unquotedName; -import static org.jooq.impl.DSL.values; -import static org.jooq.impl.JSONNull.JSONNullType.ABSENT_ON_NULL; -import static org.jooq.impl.JSONNull.JSONNullType.NULL_ON_NULL; -import static org.jooq.impl.Keywords.K_JSON_OBJECT; -import static org.jooq.impl.Names.N_JSON_MERGE; -import static org.jooq.impl.Names.N_JSON_OBJECT; -import static org.jooq.impl.Names.N_T; -import static org.jooq.impl.QueryPartListView.wrap; -import static org.jooq.impl.SQLDataType.VARCHAR; +import static org.jooq.impl.DSL.*; +import static org.jooq.impl.Internal.*; +import static org.jooq.impl.Keywords.*; +import static org.jooq.impl.Names.*; +import static org.jooq.impl.SQLDataType.*; +import static org.jooq.impl.Tools.*; +import static org.jooq.impl.Tools.BooleanDataKey.*; +import static org.jooq.impl.Tools.DataExtendedKey.*; +import static org.jooq.impl.Tools.DataKey.*; +import static org.jooq.SQLDialect.*; -import java.util.Collection; -import java.util.UUID; +import org.jooq.*; +import org.jooq.conf.*; +import org.jooq.impl.*; +import org.jooq.tools.*; -import org.jooq.Context; -import org.jooq.DataType; -import org.jooq.Field; -import org.jooq.JSONB; -import org.jooq.JSONEntry; -import org.jooq.JSONObjectNullStep; -import org.jooq.Name; -// ... -import org.jooq.impl.JSONNull.JSONNullType; +import java.util.*; /** - * The JSON array constructor. - * - * @author Lukas Eder + * The JSON OBJECT statement. */ -final class JSONObject extends AbstractField implements JSONObjectNullStep { +@SuppressWarnings({ "hiding", "rawtypes", "unchecked", "unused" }) +final class JSONObject +extends + AbstractField +implements + JSONObjectNullStep, + JSONObjectReturningStep +{ - /** - * Generated UID - */ - private static final long serialVersionUID = 1772007627336725780L; + private static final long serialVersionUID = 1L; - private final QueryPartList> args; - private final JSONNullType nullType; + private final DataType type; + private final Collection> entries; + private JSONOnNull onNull; + private DataType returning; - JSONObject(DataType type, Collection> args) { - this(type, args, null); + JSONObject( + DataType type, + Collection> entries + ) { + this( + type, + entries, + null, + null + ); } - JSONObject(DataType type, Collection> args, JSONNullType nullType) { - super(N_JSON_OBJECT, type); + JSONObject( + DataType type, + Collection> entries, + JSONOnNull onNull, + DataType returning + ) { + super( + N_JSON_OBJECT, + type + ); - this.args = new QueryPartList<>(args); - this.nullType = nullType; + this.type = type; + this.entries = entries; + this.onNull = onNull; + this.returning = returning; } // ------------------------------------------------------------------------- @@ -102,19 +109,29 @@ final class JSONObject extends AbstractField implements JSONObjectNullStep // ------------------------------------------------------------------------- @Override - public final JSONObject nullOnNull() { - return new JSONObject<>(getDataType(), args, NULL_ON_NULL); + public final JSONObject nullOnNull() { + this.onNull = JSONOnNull.NULL_ON_NULL; + return this; } @Override - public final JSONObject absentOnNull() { - return new JSONObject<>(getDataType(), args, ABSENT_ON_NULL); + public final JSONObject absentOnNull() { + this.onNull = JSONOnNull.ABSENT_ON_NULL; + return this; + } + + @Override + public final JSONObject returning(DataType returning) { + this.returning = returning; + return this; } // ------------------------------------------------------------------------- // XXX: QueryPart API // ------------------------------------------------------------------------- + + @Override public final void accept(Context ctx) { switch (ctx.family()) { @@ -124,12 +141,12 @@ final class JSONObject extends AbstractField implements JSONObjectNullStep case POSTGRES: - if (nullType == ABSENT_ON_NULL) + if (onNull == JSONOnNull.ABSENT_ON_NULL) ctx.visit(unquotedName(getDataType().getType() == JSONB.class ? "jsonb_strip_nulls" : "json_strip_nulls")).sql('('); - ctx.visit(unquotedName(getDataType().getType() == JSONB.class ? "jsonb_build_object" : "json_build_object")).sql('(').visit(args).sql(')'); + ctx.visit(unquotedName(getDataType().getType() == JSONB.class ? "jsonb_build_object" : "json_build_object")).sql('(').visit(QueryPartCollectionView.wrap(entries)).sql(')'); - if (nullType == ABSENT_ON_NULL) + if (onNull == JSONOnNull.ABSENT_ON_NULL) ctx.sql(')'); break; @@ -170,29 +187,31 @@ final class JSONObject extends AbstractField implements JSONObjectNullStep - case MARIADB: + case MARIADB: { + JSONEntry first; // Workaround for https://jira.mariadb.org/browse/MDEV-13701 - if (args.size() > 1) { + if (entries.size() > 1) { ctx.visit(N_JSON_MERGE).sql('(').visit(inline("{}")) .formatIndentStart(); - for (JSONEntry entry : args) + for (JSONEntry entry : entries) ctx.sql(',').formatSeparator().visit(jsonObject(entry)); ctx.formatIndentEnd() .formatNewLine() .sql(')'); } - else if (!args.isEmpty() && isJSONArray(args.get(0).value())) { + else if (!entries.isEmpty() && isJSONArray((first = entries.iterator().next()).value())) { ctx.visit(jsonObject( - key(args.get(0).key()).value(DSL.field("{0}({1}, {2})", getDataType(), N_JSON_MERGE, inline("[]"), args.get(0).value())) + key(first.key()).value(DSL.field("{0}({1}, {2})", getDataType(), N_JSON_MERGE, inline("[]"), first.value())) )); } else acceptStandard(ctx); break; + } default: acceptStandard(ctx); @@ -208,18 +227,39 @@ final class JSONObject extends AbstractField implements JSONObjectNullStep private final void acceptStandard(Context ctx) { JSONNull jsonNull; + JSONReturning jsonReturning = new JSONReturning(returning); // Workaround for https://github.com/h2database/h2database/issues/2496 - if (args.isEmpty() && ctx.family() == H2) - jsonNull = new JSONNull(NULL_ON_NULL); + if (entries.isEmpty() && ctx.family() == H2) + jsonNull = new JSONNull(JSONOnNull.NULL_ON_NULL); else - jsonNull = new JSONNull(nullType); + jsonNull = new JSONNull(onNull); - ctx.visit(K_JSON_OBJECT).sql('(').visit(wrap(args, jsonNull).separator("")).sql(')'); + ctx.visit(K_JSON_OBJECT).sql('(').visit(QueryPartListView.wrap(QueryPartCollectionView.wrap(entries), jsonNull, jsonReturning).separator("")).sql(')'); + } + + + + // ------------------------------------------------------------------------- + // The Object API + // ------------------------------------------------------------------------- + + @Override + public boolean equals(Object that) { + if (that instanceof JSONObject) { + return + StringUtils.equals(type, ((JSONObject) that).type) && + StringUtils.equals(entries, ((JSONObject) that).entries) && + StringUtils.equals(onNull, ((JSONObject) that).onNull) && + StringUtils.equals(returning, ((JSONObject) that).returning) + ; + } + else + return super.equals(that); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java b/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java index 4434cc33de..7c00853985 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONObjectAgg.java @@ -43,8 +43,8 @@ import static org.jooq.impl.DSL.inline; import static org.jooq.impl.DSL.jsonObject; import static org.jooq.impl.DSL.jsonValue; import static org.jooq.impl.DSL.when; -import static org.jooq.impl.JSONNull.JSONNullType.ABSENT_ON_NULL; -import static org.jooq.impl.JSONNull.JSONNullType.NULL_ON_NULL; +import static org.jooq.impl.JSONOnNull.ABSENT_ON_NULL; +import static org.jooq.impl.JSONOnNull.NULL_ON_NULL; import static org.jooq.impl.Names.N_JSONB_OBJECT_AGG; import static org.jooq.impl.Names.N_JSON_OBJECTAGG; import static org.jooq.impl.Names.N_JSON_OBJECT_AGG; @@ -56,7 +56,6 @@ import org.jooq.Field; import org.jooq.JSON; import org.jooq.JSONEntry; import org.jooq.JSONObjectAggNullStep; -import org.jooq.impl.JSONNull.JSONNullType; /** @@ -74,7 +73,8 @@ implements JSONObjectAggNullStep { private static final long serialVersionUID = 1772007627336725780L; private final JSONEntry entry; - private JSONNullType nullType; + private JSONOnNull onNull; + private DataType returning; JSONObjectAgg(DataType type, JSONEntry entry) { super(false, N_JSON_OBJECTAGG, type, entry.key(), entry.value()); @@ -101,7 +101,7 @@ implements JSONObjectAggNullStep { // [#10089] These dialects support non-standard JSON_OBJECTAGG without ABSENT ON NULL support case MARIADB: case MYSQL: - if (nullType == ABSENT_ON_NULL) + if (onNull == ABSENT_ON_NULL) acceptGroupConcat(ctx); @@ -124,7 +124,7 @@ implements JSONObjectAggNullStep { ctx.sql(')'); // TODO: What about a user-defined filter clause? - if (nullType == ABSENT_ON_NULL) + if (onNull == ABSENT_ON_NULL) acceptFilterClause(ctx, entry.value().isNotNull()); acceptOverClause(ctx); @@ -152,7 +152,7 @@ implements JSONObjectAggNullStep { break; } - if (nullType == ABSENT_ON_NULL) + if (onNull == ABSENT_ON_NULL) value = when(entry.value().isNull(), inline((String) null)).else_((Field) value); } @@ -162,7 +162,7 @@ implements JSONObjectAggNullStep { inline('"'), DSL.replace(entry.key(), inline('"'), inline("\\\"")), inline("\":"), - nullType == ABSENT_ON_NULL ? value1 : DSL.coalesce(value1, inline("null")) + onNull == ABSENT_ON_NULL ? value1 : DSL.coalesce(value1, inline("null")) ))); acceptOverClause(c); })); @@ -173,23 +173,33 @@ implements JSONObjectAggNullStep { private final void acceptStandard(Context ctx) { ctx.visit(N_JSON_OBJECTAGG).sql('(').visit(entry); - JSONNull jsonNull = new JSONNull(nullType); + JSONNull jsonNull = new JSONNull(onNull); if (jsonNull.rendersContent(ctx)) ctx.sql(' ').visit(jsonNull); + JSONReturning jsonReturning = new JSONReturning(returning); + if (jsonReturning.rendersContent(ctx)) + ctx.sql(' ').visit(jsonReturning); + ctx.sql(')'); acceptOverClause(ctx); } @Override public final JSONObjectAgg nullOnNull() { - nullType = NULL_ON_NULL; + onNull = NULL_ON_NULL; return this; } @Override public final JSONObjectAgg absentOnNull() { - nullType = ABSENT_ON_NULL; + onNull = ABSENT_ON_NULL; + return this; + } + + @Override + public final JSONObjectAgg returning(DataType r) { + this.returning = r; return this; } } diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONOnNull.java b/jOOQ/src/main/java/org/jooq/impl/JSONOnNull.java new file mode 100644 index 0000000000..ab104f4f5e --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/JSONOnNull.java @@ -0,0 +1,49 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + + +import org.jooq.*; + +/** + * The JSONOnNull. + */ +enum JSONOnNull { + NULL_ON_NULL, + ABSENT_ON_NULL, +} diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONReturning.java b/jOOQ/src/main/java/org/jooq/impl/JSONReturning.java new file mode 100644 index 0000000000..c542c97f29 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/JSONReturning.java @@ -0,0 +1,80 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + +// ... +// ... +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.impl.Keywords.K_RETURNING; + +import java.util.Set; + +import org.jooq.Context; +import org.jooq.DataType; +import org.jooq.SQLDialect; + +/** + * @author Lukas Eder + */ +final class JSONReturning extends AbstractQueryPart { + + /** + * Generated UID + */ + private static final long serialVersionUID = 3121287280045911346L; + static final Set NO_SUPPORT_RETURNING = SQLDialect.supportedBy(H2, MARIADB, MYSQL, POSTGRES); + final DataType type; + + JSONReturning(DataType type) { + this.type = type; + } + + @Override + public final boolean rendersContent(Context ctx) { + return !NO_SUPPORT_RETURNING.contains(ctx.dialect()) && type != null; + } + + @Override + public final void accept(Context ctx) { + if (!NO_SUPPORT_RETURNING.contains(ctx.dialect())) + ctx.visit(K_RETURNING).sql(' ').sql(type.getCastTypeName(ctx.configuration())); + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONValue.java b/jOOQ/src/main/java/org/jooq/impl/JSONValue.java index 059b53e77d..f9e5052f64 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONValue.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONValue.java @@ -62,7 +62,6 @@ import org.jooq.JSONValueOnStep; import org.jooq.Keyword; // ... import org.jooq.SQLDialect; -import org.jooq.conf.ParamType; /** @@ -87,25 +86,22 @@ implements private final Field json; private final Field path; + private final DataType returning; + private final Behaviour onError; + private final Field onErrorDefault; + private final Behaviour onEmpty; + private final Field onEmptyDefault; + private final Field default_; - - - - - - - - - - - JSONValue(DataType type, Field json, Field path) { - this(type, json, path, null, null, null, null, null); + JSONValue(DataType type, Field json, Field path, DataType returning) { + this(type, json, path, returning, null, null, null, null, null); } private JSONValue( DataType type, Field json, Field path, + DataType returning, Behaviour onError, Field onErrorDefault, Behaviour onEmpty, @@ -116,13 +112,12 @@ implements this.json = json; this.path = path; - - - - - - - + this.returning = returning; + this.onError = onError; + this.onErrorDefault = onErrorDefault; + this.onEmpty = onEmpty; + this.onEmptyDefault = onEmptyDefault; + this.default_ = default_; } @@ -168,6 +163,11 @@ implements + + @Override + public final JSONValue returning(DataType r) { + return new JSONValue<>(getDataType(), json, path, r, onError, onErrorDefault, onEmpty, onEmptyDefault, null); + } // ------------------------------------------------------------------------- // XXX: QueryPart API @@ -210,6 +210,9 @@ implements + if (returning != null) + ctx.separatorRequired(true).visit(new JSONReturning(returning)); + ctx.sql(')'); break; } diff --git a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java index a7ec205f8b..d910dd7fea 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ParserImpl.java @@ -291,7 +291,6 @@ import static org.jooq.impl.DSL.splitPart; import static org.jooq.impl.DSL.sql; import static org.jooq.impl.DSL.sqrt; import static org.jooq.impl.DSL.square; -// ... import static org.jooq.impl.DSL.stddevPop; import static org.jooq.impl.DSL.stddevSamp; import static org.jooq.impl.DSL.sum; @@ -337,8 +336,8 @@ import static org.jooq.impl.DSL.xmlquery; import static org.jooq.impl.DSL.xmltable; import static org.jooq.impl.DSL.year; import static org.jooq.impl.DSL.zero; -import static org.jooq.impl.JSONNull.JSONNullType.ABSENT_ON_NULL; -import static org.jooq.impl.JSONNull.JSONNullType.NULL_ON_NULL; +import static org.jooq.impl.JSONOnNull.ABSENT_ON_NULL; +import static org.jooq.impl.JSONOnNull.NULL_ON_NULL; import static org.jooq.impl.Keywords.K_DELETE; import static org.jooq.impl.Keywords.K_INSERT; import static org.jooq.impl.Keywords.K_SELECT; @@ -378,7 +377,6 @@ import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -497,10 +495,14 @@ import org.jooq.InsertValuesStepN; import org.jooq.JSON; import org.jooq.JSONArrayAggNullStep; import org.jooq.JSONArrayAggOrderByStep; +import org.jooq.JSONArrayAggReturningStep; import org.jooq.JSONArrayNullStep; +import org.jooq.JSONArrayReturningStep; import org.jooq.JSONEntry; import org.jooq.JSONObjectAggNullStep; +import org.jooq.JSONObjectAggReturningStep; import org.jooq.JSONObjectNullStep; +import org.jooq.JSONObjectReturningStep; import org.jooq.JSONTableColumnPathStep; import org.jooq.JSONTableColumnsStep; import org.jooq.JSONValueDefaultStep; @@ -595,7 +597,6 @@ import org.jooq.conf.RenderNameCase; import org.jooq.conf.RenderQuotedNames; import org.jooq.conf.Settings; import org.jooq.conf.SettingsTools; -import org.jooq.impl.JSONNull.JSONNullType; import org.jooq.impl.ScopeStack.Value; import org.jooq.impl.XMLParse.DocumentOrContent; import org.jooq.tools.StringUtils; @@ -8308,8 +8309,9 @@ final class ParserContext { + DataType returning = parseJSONReturningIf(); parse(')'); - return s1; + return returning == null ? s1 : s1.returning(returning); } return null; @@ -8339,6 +8341,10 @@ final class ParserContext { return null; } + private final DataType parseJSONReturningIf() { + return parseKeywordIf("RETURNING") ? parseDataType() : null; + } + private final Field parseFieldJSONArrayConstructorIf() { if (parseFunctionNameIf("JSON_ARRAY")) { parse('('); @@ -8346,21 +8352,24 @@ final class ParserContext { return DSL.jsonArray(); List> result = null; - JSONNullType nullType = parseJSONNullTypeIf(); + JSONOnNull onNull = parseJSONNullTypeIf(); + DataType returning = parseJSONReturningIf(); - if (nullType == null) { + if (onNull == null && returning == null) { result = parseFields(); - nullType = parseJSONNullTypeIf(); + onNull = parseJSONNullTypeIf(); + returning = parseJSONReturningIf(); } parse(')'); - JSONArrayNullStep a = result == null ? DSL.jsonArray() : DSL.jsonArray(result); - return nullType == NULL_ON_NULL - ? a.nullOnNull() - : nullType == ABSENT_ON_NULL - ? a.absentOnNull() - : a; + JSONArrayNullStep s1 = result == null ? DSL.jsonArray() : DSL.jsonArray(result); + JSONArrayReturningStep s2 = onNull == NULL_ON_NULL + ? s1.nullOnNull() + : onNull == ABSENT_ON_NULL + ? s1.absentOnNull() + : s1; + return returning == null ? s2 : s2.returning(returning); } return null; @@ -8369,18 +8378,23 @@ final class ParserContext { private final Field parseFieldJSONArrayAggIf() { if (parseFunctionNameIf("JSON_ARRAYAGG")) { Field result; - JSONArrayAggOrderByStep s1; - JSONArrayAggNullStep s2; - JSONNullType nullType; + JSONArrayAggOrderByStep s1; + JSONArrayAggNullStep s2; + JSONArrayAggReturningStep s3; + JSONOnNull onNull; + DataType returning; parse('('); - result = s2 = s1 = DSL.jsonArrayAgg(parseField()); + result = s3 = s2 = s1 = DSL.jsonArrayAgg(parseField()); if (parseKeywordIf("ORDER BY")) - result = s2 = s1.orderBy(parseSortSpecification()); + result = s3 = s2 = s1.orderBy(parseSortSpecification()); - if ((nullType = parseJSONNullTypeIf()) != null) - result = nullType == ABSENT_ON_NULL ? s2.absentOnNull() : s2.nullOnNull(); + if ((onNull = parseJSONNullTypeIf()) != null) + result = s3 = onNull == ABSENT_ON_NULL ? s2.absentOnNull() : s2.nullOnNull(); + + if ((returning = parseJSONReturningIf()) != null) + result = s3.returning(returning); parse(')'); return result; @@ -8396,23 +8410,27 @@ final class ParserContext { return DSL.jsonObject(); List> result = new ArrayList<>(); - JSONNullType nullType = parseJSONNullTypeIf(); + JSONOnNull onNull = parseJSONNullTypeIf(); + DataType returning = parseJSONReturningIf(); - if (nullType == null) { + if (onNull == null && returning == null) { do result.add(parseJSONEntry()); while (parseIf(',')); - nullType = parseJSONNullTypeIf(); + onNull = parseJSONNullTypeIf(); + returning = parseJSONReturningIf(); } + parse(')'); - JSONObjectNullStep o = DSL.jsonObject(result); - return nullType == NULL_ON_NULL - ? o.nullOnNull() - : nullType == ABSENT_ON_NULL - ? o.absentOnNull() - : o; + JSONObjectNullStep s1 = DSL.jsonObject(result); + JSONObjectReturningStep s2 = onNull == NULL_ON_NULL + ? s1.nullOnNull() + : onNull == ABSENT_ON_NULL + ? s1.absentOnNull() + : s1; + return returning == null ? s2 : s2.returning(returning); } return null; @@ -8421,14 +8439,19 @@ final class ParserContext { private final Field parseFieldJSONObjectAggIf() { if (parseFunctionNameIf("JSON_OBJECTAGG")) { Field result; - JSONObjectAggNullStep s1; - JSONNullType nullType; + JSONObjectAggNullStep s1; + JSONObjectAggReturningStep s2; + JSONOnNull onNull; + DataType returning; parse('('); - result = s1 = DSL.jsonObjectAgg(parseJSONEntry()); + result = s2 = s1 = DSL.jsonObjectAgg(parseJSONEntry()); - if ((nullType = parseJSONNullTypeIf()) != null) - result = nullType == ABSENT_ON_NULL ? s1.absentOnNull() : s1.nullOnNull(); + if ((onNull = parseJSONNullTypeIf()) != null) + result = s2 = onNull == ABSENT_ON_NULL ? s1.absentOnNull() : s1.nullOnNull(); + + if ((returning = parseJSONReturningIf()) != null) + result = s2.returning(returning); parse(')'); return result; @@ -8437,7 +8460,7 @@ final class ParserContext { return null; } - private final JSONNullType parseJSONNullTypeIf() { + private final JSONOnNull parseJSONNullTypeIf() { if (parseKeywordIf("NULL ON NULL")) return NULL_ON_NULL; else if (parseKeywordIf("ABSENT ON NULL")) diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 091ada90b1..1b3d01136c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -2017,13 +2017,13 @@ final class Tools { return result; } - static final JSONEntry[] jsonEntries(Field... fields) { + static final List> jsonEntries(Field... fields) { if (fields == null) return null; - JSONEntry[] result = new JSONEntry[fields.length]; - for (int i = 0; i < fields.length; i++) - result[i] = jsonEntry(fields[i]); + List> result = new ArrayList<>(fields.length); + for (Field field : fields) + result.add(jsonEntry(field)); return result; }