diff --git a/jOOQ/src/main/java/org/jooq/JSONTableColumnForOrdinalityStep.java b/jOOQ/src/main/java/org/jooq/JSONTableColumnForOrdinalityStep.java
index 22d4e98910..b95fc9b989 100644
--- a/jOOQ/src/main/java/org/jooq/JSONTableColumnForOrdinalityStep.java
+++ b/jOOQ/src/main/java/org/jooq/JSONTableColumnForOrdinalityStep.java
@@ -39,6 +39,7 @@ package org.jooq;
import static org.jooq.SQLDialect.MYSQL;
// ...
+import static org.jooq.SQLDialect.POSTGRES;
/**
* A step in the construction of an JSON_TABLE expression.
@@ -51,7 +52,7 @@ public interface JSONTableColumnForOrdinalityStep {
* Specify the FOR ORDINALITY clause on a column in the
* COLUMNS clause of the JSON_TABLE predicate.
*/
- @Support({ MYSQL })
+ @Support({ MYSQL, POSTGRES })
JSONTableColumnsStep forOrdinality();
}
diff --git a/jOOQ/src/main/java/org/jooq/JSONTableColumnPathStep.java b/jOOQ/src/main/java/org/jooq/JSONTableColumnPathStep.java
index f389b233d3..7c8631f39d 100644
--- a/jOOQ/src/main/java/org/jooq/JSONTableColumnPathStep.java
+++ b/jOOQ/src/main/java/org/jooq/JSONTableColumnPathStep.java
@@ -40,6 +40,7 @@ package org.jooq;
// ...
import static org.jooq.SQLDialect.MYSQL;
// ...
+import static org.jooq.SQLDialect.POSTGRES;
/**
* A step in the construction of an JSON_TABLE expression.
@@ -52,7 +53,7 @@ public interface JSONTableColumnPathStep extends JSONTableColumnForOrdinalitySte
* Specify the PATH of a column in the COLUMNS
* clause of the JSON_TABLE predicate.
*/
- @Support({ MYSQL })
+ @Support({ MYSQL, POSTGRES })
JSONTableColumnsStep path(String path);
}
diff --git a/jOOQ/src/main/java/org/jooq/JSONTableColumnsFirstStep.java b/jOOQ/src/main/java/org/jooq/JSONTableColumnsFirstStep.java
index 3c80e7f2a6..28cccff58d 100644
--- a/jOOQ/src/main/java/org/jooq/JSONTableColumnsFirstStep.java
+++ b/jOOQ/src/main/java/org/jooq/JSONTableColumnsFirstStep.java
@@ -40,6 +40,7 @@ package org.jooq;
// ...
import static org.jooq.SQLDialect.MYSQL;
// ...
+import static org.jooq.SQLDialect.POSTGRES;
/**
* A step in the construction of an JSON_TABLE expression.
@@ -52,42 +53,42 @@ public interface JSONTableColumnsFirstStep {
* Add a column to the COLUMNS clause of the
* JSON_TABLE expression.
*/
- @Support({ MYSQL })
+ @Support({ MYSQL, POSTGRES })
JSONTableColumnForOrdinalityStep column(String name);
/**
* Add a column to the COLUMNS clause of the
* JSON_TABLE expression.
*/
- @Support({ MYSQL })
+ @Support({ MYSQL, POSTGRES })
JSONTableColumnForOrdinalityStep column(Name name);
/**
* Add a column to the COLUMNS clause of the
* JSON_TABLE expression.
*/
- @Support({ MYSQL })
+ @Support({ MYSQL, POSTGRES })
JSONTableColumnPathStep column(Field> name);
/**
* Add a column to the COLUMNS clause of the
* JSON_TABLE expression.
*/
- @Support({ MYSQL })
+ @Support({ MYSQL, POSTGRES })
JSONTableColumnPathStep column(String name, DataType> type);
/**
* Add a column to the COLUMNS clause of the
* JSON_TABLE expression.
*/
- @Support({ MYSQL })
+ @Support({ MYSQL, POSTGRES })
JSONTableColumnPathStep column(Name name, DataType> type);
/**
* Add a column to the COLUMNS clause of the
* JSON_TABLE expression.
*/
- @Support({ MYSQL })
+ @Support({ MYSQL, POSTGRES })
JSONTableColumnPathStep column(Field> name, DataType> type);
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/DSL.java b/jOOQ/src/main/java/org/jooq/impl/DSL.java
index ca046ad839..18052ed198 100644
--- a/jOOQ/src/main/java/org/jooq/impl/DSL.java
+++ b/jOOQ/src/main/java/org/jooq/impl/DSL.java
@@ -18769,7 +18769,7 @@ public class DSL {
/**
* The JSON table function.
*/
- @Support({ MYSQL })
+ @Support({ MYSQL, POSTGRES })
public static JSONTableColumnsFirstStep jsonTable(JSON json, String path) {
return jsonTable(Tools.field(json), Tools.field(path));
}
@@ -18777,7 +18777,7 @@ public class DSL {
/**
* The JSON table function.
*/
- @Support({ MYSQL })
+ @Support({ MYSQL, POSTGRES })
public static JSONTableColumnsFirstStep jsonTable(Field json, Field path) {
return new JSONTable(nullSafe(json), nullSafe(path));
}
@@ -18785,7 +18785,7 @@ public class DSL {
/**
* The JSON table function.
*/
- @Support({ MYSQL })
+ @Support({ MYSQL, POSTGRES })
public static JSONTableColumnsFirstStep jsonbTable(JSONB json, String path) {
return jsonbTable(Tools.field(json), Tools.field(path));
}
@@ -18793,7 +18793,7 @@ public class DSL {
/**
* The JSON table function.
*/
- @Support({ MYSQL })
+ @Support({ MYSQL, POSTGRES })
public static JSONTableColumnsFirstStep jsonbTable(Field json, Field path) {
return new JSONTable(nullSafe(json), nullSafe(path));
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONTable.java b/jOOQ/src/main/java/org/jooq/impl/JSONTable.java
index 0cff1d3873..02fcae36f0 100644
--- a/jOOQ/src/main/java/org/jooq/impl/JSONTable.java
+++ b/jOOQ/src/main/java/org/jooq/impl/JSONTable.java
@@ -42,6 +42,10 @@ 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.DSL.keyword;
+import static org.jooq.impl.DSL.rowNumber;
+import static org.jooq.impl.DSL.select;
+import static org.jooq.impl.DSL.val;
import static org.jooq.impl.Keywords.K_COLUMNS;
import static org.jooq.impl.Keywords.K_ERROR;
import static org.jooq.impl.Keywords.K_FOR;
@@ -50,6 +54,7 @@ import static org.jooq.impl.Keywords.K_ON;
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 static org.jooq.impl.SQLDataType.JSONB;
import java.util.ArrayList;
import java.util.List;
@@ -58,11 +63,13 @@ import java.util.Set;
import org.jooq.Context;
import org.jooq.DataType;
import org.jooq.Field;
+import org.jooq.JSONB;
import org.jooq.JSONTableColumnPathStep;
import org.jooq.Name;
// ...
import org.jooq.Record;
import org.jooq.SQLDialect;
+import org.jooq.SelectField;
import org.jooq.Table;
import org.jooq.TableOptions;
import org.jooq.conf.ParamType;
@@ -80,141 +87,177 @@ implements
*/
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.formatIndentEnd()
- .formatNewLine()
- .sql(')');
+ private final Field path;
+ private final Field> json;
+ private final QueryPartList columns;
+ private transient Fields fields;
+
+ JSONTable(Field> json, Field path) {
+ this(json, path, null);
+ }
+
+ private JSONTable(
+ Field> json,
+ Field path,
+ QueryPartList columns
+ ) {
+ super(TableOptions.expression(), N_JSON_TABLE);
+
+ this.json = json;
+ this.path = path;
+ this.columns = columns == null ? new QueryPartList<>() : columns;
+ }
+
+ // -------------------------------------------------------------------------
+ // XXX: DSL API
+ // -------------------------------------------------------------------------
+
+ @Override
+ public final JSONTable column(String name) {
+ return column(DSL.name(name));
+ }
+
+ @Override
+ public final JSONTable column(Name name) {
+ return column(DSL.field(name));
+ }
+
+ @Override
+ public final JSONTable column(Field> name) {
+ return column(name, name.getDataType());
+ }
+
+ @Override
+ public final JSONTable column(String name, DataType> type) {
+ return column(DSL.name(name), type);
+ }
+
+ @Override
+ public final JSONTable column(Name name, DataType> type) {
+ return column(DSL.field(name), type);
+ }
+
+ @Override
+ public final JSONTable column(Field> name, DataType> type) {
+ QueryPartList c = new QueryPartList<>(columns);
+ c.add(new JSONTableColumn(name, type, false, null));
+ return new JSONTable(json, path, c);
+ }
+
+ @Override
+ public final JSONTable forOrdinality() {
+ return path0(true, null);
+ }
+
+ @Override
+ public final JSONTable path(String p) {
+ return path0(false, p);
+ }
+
+ private final JSONTable path0(boolean forOrdinality, String p) {
+ QueryPartList c = new QueryPartList<>(columns);
+ int i = c.size() - 1;
+ JSONTableColumn last = c.get(i);
+ c.set(i, new JSONTableColumn(last.field, last.type, forOrdinality, p));
+ return new JSONTable(json, path, c);
+ }
+
+ // -------------------------------------------------------------------------
+ // XXX: Table API
+ // -------------------------------------------------------------------------
+
+ @Override
+ public final Class extends Record> getRecordType() {
+ return RecordImplN.class;
+ }
+
+ @Override
+ final Fields fields0() {
+ if (fields == null) {
+ List> f = new ArrayList<>();
+
+ for (JSONTableColumn c : columns)
+ f.add(c.field.getDataType() == c.type ? c.field : field(c.field.getQualifiedName(), c.type));
+
+ fields = new Fields<>(f);
+ }
+
+ return fields;
+ }
+
+ // -------------------------------------------------------------------------
+ // XXX: QueryPart API
+ // -------------------------------------------------------------------------
+
+ @Override
+ public final void accept(Context> ctx) {
+ switch (ctx.family()) {
+ case POSTGRES:
+ acceptPostgres(ctx);
+ break;
+
+ default:
+ acceptStandard(ctx);
+ break;
}
}
- private void acceptJSONPath(Context> ctx) {
+ private final void acceptPostgres(Context> ctx) {
+ List> cols = new ArrayList<>();
+
+ for (JSONTableColumn col : columns)
+ if (col.forOrdinality)
+ cols.add(rowNumber().over().as(col.field));
+ else
+ cols.add(
+ DSL.field("(jsonb_path_query_first(j, {0}::jsonpath)->>0)::{1}",
+ col.path != null ? val(col.path) : inline("$." + col.field.getName()),
+ keyword(col.type.getCastTypeName(ctx.configuration()))
+ ).as(col.field)
+ );
+
+ ctx.sql('(')
+ .formatIndentStart()
+ .formatNewLine()
+ .subquery(true)
+ .visit(
+ select(cols).from("jsonb_path_query({0}, {1}::jsonpath) as t(j)",
+ json.getType() == JSONB.class ? json : json.cast(JSONB),
+ path
+ )
+ )
+ .subquery(false)
+ .formatIndentEnd()
+ .formatNewLine()
+ .sql(')');
+ }
+
+ private final void acceptStandard(Context> ctx) {
+ ctx.visit(K_JSON_TABLE).sql('(')
+ .formatIndentStart()
+ .formatNewLine();
+
+ ctx.visit(json).sql(',').formatSeparator();
+ acceptJSONPath(ctx);
+
+ ctx.formatSeparator().visit(K_COLUMNS).sql(" (").visit(columns).sql(')');
+
+
+
+
+
+
+ ctx.formatIndentEnd()
+ .formatNewLine()
+ .sql(')');
+ }
+
+ private final void acceptJSONPath(Context> ctx) {