From eece41ce41d505febb23409d2648c59b2a45d9ca Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 16 Apr 2020 12:07:23 +0200 Subject: [PATCH] [jOOQ/jOOQ#8950] Added JSON_TABLE support --- .../JSONTableColumnForOrdinalityStep.java | 57 ++++ .../org/jooq/JSONTableColumnPathStep.java | 58 ++++ .../org/jooq/JSONTableColumnsFirstStep.java | 93 ++++++ .../java/org/jooq/JSONTableColumnsStep.java | 47 +++ jOOQ/src/main/java/org/jooq/impl/DSL.java | 33 +++ .../main/java/org/jooq/impl/JSONTable.java | 273 ++++++++++++++++++ .../src/main/java/org/jooq/impl/Keywords.java | 1 + jOOQ/src/main/java/org/jooq/impl/Names.java | 1 + .../src/main/java/org/jooq/impl/XMLTable.java | 4 +- 9 files changed, 565 insertions(+), 2 deletions(-) create mode 100644 jOOQ/src/main/java/org/jooq/JSONTableColumnForOrdinalityStep.java create mode 100644 jOOQ/src/main/java/org/jooq/JSONTableColumnPathStep.java create mode 100644 jOOQ/src/main/java/org/jooq/JSONTableColumnsFirstStep.java create mode 100644 jOOQ/src/main/java/org/jooq/JSONTableColumnsStep.java create mode 100644 jOOQ/src/main/java/org/jooq/impl/JSONTable.java diff --git a/jOOQ/src/main/java/org/jooq/JSONTableColumnForOrdinalityStep.java b/jOOQ/src/main/java/org/jooq/JSONTableColumnForOrdinalityStep.java new file mode 100644 index 0000000000..22d4e98910 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/JSONTableColumnForOrdinalityStep.java @@ -0,0 +1,57 @@ +/* + * 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.MYSQL; +// ... + +/** + * A step in the construction of an JSON_TABLE expression. + * + * @author Lukas Eder + */ +public interface JSONTableColumnForOrdinalityStep { + + /** + * Specify the FOR ORDINALITY clause on a column in the + * COLUMNS clause of the JSON_TABLE predicate. + */ + @Support({ MYSQL }) + JSONTableColumnsStep forOrdinality(); + +} diff --git a/jOOQ/src/main/java/org/jooq/JSONTableColumnPathStep.java b/jOOQ/src/main/java/org/jooq/JSONTableColumnPathStep.java new file mode 100644 index 0000000000..f389b233d3 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/JSONTableColumnPathStep.java @@ -0,0 +1,58 @@ +/* + * 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.MYSQL; +// ... + +/** + * A step in the construction of an JSON_TABLE expression. + * + * @author Lukas Eder + */ +public interface JSONTableColumnPathStep extends JSONTableColumnForOrdinalityStep, JSONTableColumnsStep { + + /** + * Specify the PATH of a column in the COLUMNS + * clause of the JSON_TABLE predicate. + */ + @Support({ MYSQL }) + JSONTableColumnsStep path(String path); + +} diff --git a/jOOQ/src/main/java/org/jooq/JSONTableColumnsFirstStep.java b/jOOQ/src/main/java/org/jooq/JSONTableColumnsFirstStep.java new file mode 100644 index 0000000000..3c80e7f2a6 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/JSONTableColumnsFirstStep.java @@ -0,0 +1,93 @@ +/* + * 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.MYSQL; +// ... + +/** + * A step in the construction of an JSON_TABLE expression. + * + * @author Lukas Eder + */ +public interface JSONTableColumnsFirstStep { + + /** + * Add a column to the COLUMNS clause of the + * JSON_TABLE expression. + */ + @Support({ MYSQL }) + JSONTableColumnForOrdinalityStep column(String name); + + /** + * Add a column to the COLUMNS clause of the + * JSON_TABLE expression. + */ + @Support({ MYSQL }) + JSONTableColumnForOrdinalityStep column(Name name); + + /** + * Add a column to the COLUMNS clause of the + * JSON_TABLE expression. + */ + @Support({ MYSQL }) + JSONTableColumnPathStep column(Field name); + + /** + * Add a column to the COLUMNS clause of the + * JSON_TABLE expression. + */ + @Support({ MYSQL }) + JSONTableColumnPathStep column(String name, DataType type); + + /** + * Add a column to the COLUMNS clause of the + * JSON_TABLE expression. + */ + @Support({ MYSQL }) + JSONTableColumnPathStep column(Name name, DataType type); + + /** + * Add a column to the COLUMNS clause of the + * JSON_TABLE expression. + */ + @Support({ MYSQL }) + JSONTableColumnPathStep column(Field name, DataType type); + +} diff --git a/jOOQ/src/main/java/org/jooq/JSONTableColumnsStep.java b/jOOQ/src/main/java/org/jooq/JSONTableColumnsStep.java new file mode 100644 index 0000000000..4073b2cc3d --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/JSONTableColumnsStep.java @@ -0,0 +1,47 @@ +/* + * 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; + +/** + * A step in the construction of an JSON_TABLE expression. + * + * @author Lukas Eder + */ +public interface JSONTableColumnsStep extends JSONTableColumnsFirstStep, Table { + +} diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java index d434544849..ca046ad839 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DSL.java +++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java @@ -240,6 +240,7 @@ import org.jooq.JSONEntry; import org.jooq.JSONExistsOnStep; import org.jooq.JSONObjectAggNullStep; import org.jooq.JSONObjectNullStep; +import org.jooq.JSONTableColumnsFirstStep; import org.jooq.JSONValueOnStep; import org.jooq.Keyword; // ... @@ -18765,6 +18766,38 @@ public class DSL { return new JSONExists(field, nullSafe(path)); } + /** + * The JSON table function. + */ + @Support({ MYSQL }) + public static JSONTableColumnsFirstStep jsonTable(JSON json, String path) { + return jsonTable(Tools.field(json), Tools.field(path)); + } + + /** + * The JSON table function. + */ + @Support({ MYSQL }) + public static JSONTableColumnsFirstStep jsonTable(Field json, Field path) { + return new JSONTable(nullSafe(json), nullSafe(path)); + } + + /** + * The JSON table function. + */ + @Support({ MYSQL }) + public static JSONTableColumnsFirstStep jsonbTable(JSONB json, String path) { + return jsonbTable(Tools.field(json), Tools.field(path)); + } + + /** + * The JSON table function. + */ + @Support({ MYSQL }) + public static JSONTableColumnsFirstStep jsonbTable(Field json, Field path) { + return new JSONTable(nullSafe(json), nullSafe(path)); + } + // ------------------------------------------------------------------------- // XXX Aggregate functions // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONTable.java b/jOOQ/src/main/java/org/jooq/impl/JSONTable.java new file mode 100644 index 0000000000..fae742e0eb --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/JSONTable.java @@ -0,0 +1,273 @@ +/* + * 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.MYSQL; +// ... +import static org.jooq.conf.ParamType.INLINED; +import static org.jooq.impl.DSL.inline; +import static org.jooq.impl.Keywords.K_COLUMNS; +import static org.jooq.impl.Keywords.K_FOR; +import static org.jooq.impl.Keywords.K_JSON_TABLE; +import static org.jooq.impl.Keywords.K_ORDINALITY; +import static org.jooq.impl.Keywords.K_PATH; +import static org.jooq.impl.Names.N_JSON_TABLE; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.jooq.Context; +import org.jooq.DataType; +import org.jooq.Field; +import org.jooq.JSONTableColumnPathStep; +import org.jooq.Name; +// ... +import org.jooq.Record; +import org.jooq.SQLDialect; +import org.jooq.Table; +import org.jooq.TableOptions; +import org.jooq.conf.ParamType; + +/** + * @author Lukas Eder + */ +final class JSONTable +extends AbstractTable +implements + JSONTableColumnPathStep { + + /** + * Generated UID + */ + private static final long serialVersionUID = -4881363881968319258L; + private static final Set REQUIRES_COLUMN_PATH = SQLDialect.supportedBy(MYSQL); + private static final Set REQUIRES_ALIASING = SQLDialect.supportedBy(MYSQL); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ctx.visit(path); + } + + @Override + public final Table as(Name alias) { + return new TableAlias<>(this, alias); + } + + @Override + public boolean declaresTables() { + return true; + } + + private static class JSONTableColumn extends AbstractQueryPart { + + /** + * Generated UID + */ + private static final long serialVersionUID = 783627375014050176L; + + final Field field; + final DataType type; + final boolean forOrdinality; + final String path; + + JSONTableColumn(Field field, DataType type, boolean forOrdinality, String path) { + this.field = field; + this.type = type; + this.forOrdinality = forOrdinality; + this.path = path; + } + + @Override + public final void accept(Context ctx) { + boolean previous = ctx.qualify(); + + ctx.qualify(false) + .visit(field) + .qualify(previous) + .sql(' '); + + if (forOrdinality) + ctx.visit(K_FOR).sql(' ').visit(K_ORDINALITY); + else + Tools.toSQLDDLTypeDeclaration(ctx, type); + + if (path != null) + ctx.sql(' ').visit(K_PATH).sql(' ').visit(inline(path)); + else if (!forOrdinality && REQUIRES_COLUMN_PATH.contains(ctx.dialect())) + ctx.sql(' ').visit(K_PATH).sql(' ').visit(inline("$." + field.getName())); + } + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/Keywords.java b/jOOQ/src/main/java/org/jooq/impl/Keywords.java index 19cb030ffa..058fa83707 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Keywords.java +++ b/jOOQ/src/main/java/org/jooq/impl/Keywords.java @@ -217,6 +217,7 @@ final class Keywords { static final Keyword K_JSON = keyword("json"); static final Keyword K_JSON_ARRAY = keyword("json_array"); static final Keyword K_JSON_EXISTS = keyword("json_exists"); + static final Keyword K_JSON_TABLE = keyword("json_table"); static final Keyword K_JSON_OBJECT = keyword("json_object"); static final Keyword K_KEEP = keyword("keep"); static final Keyword K_KEY = keyword("key"); diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index a7bef1e9e8..eee57afc54 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -123,6 +123,7 @@ final class Names { static final Name N_JSON_OBJECT = unquotedName("json_object"); static final Name N_JSON_OBJECT_AGG = unquotedName("json_object_agg"); static final Name N_JSON_OBJECTAGG = unquotedName("json_objectagg"); + static final Name N_JSON_TABLE = unquotedName("json_table"); static final Name N_JSON_VALUE = unquotedName("json_value"); static final Name N_JSONB_AGG = unquotedName("jsonb_agg"); static final Name N_JSONB_OBJECT = unquotedName("jsonb_object"); diff --git a/jOOQ/src/main/java/org/jooq/impl/XMLTable.java b/jOOQ/src/main/java/org/jooq/impl/XMLTable.java index 87cc587b36..414d8eea05 100644 --- a/jOOQ/src/main/java/org/jooq/impl/XMLTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/XMLTable.java @@ -140,7 +140,7 @@ implements @Override public final XMLTable column(String name) { - return column(DSL.field(name)); + return column(DSL.name(name)); } @Override @@ -155,7 +155,7 @@ implements @Override public final XMLTable column(String name, DataType type) { - return column(DSL.field(name), type); + return column(DSL.name(name), type); } @Override