From f44e9b4f894910645e2ab9c04bb4daf5bf28716a Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Wed, 22 Apr 2020 11:30:07 +0200 Subject: [PATCH] [jOOQ/jOOQ#10099] Emulate XMLTABLE in SQL Server with NODES() --- .../jooq/XMLTableColumnForOrdinalityStep.java | 1 + .../java/org/jooq/XMLTableColumnPathStep.java | 1 + .../org/jooq/XMLTableColumnsFirstStep.java | 1 + .../java/org/jooq/XMLTablePassingStep.java | 1 + .../main/java/org/jooq/impl/JSONTable.java | 2 +- jOOQ/src/main/java/org/jooq/impl/Names.java | 1 + .../src/main/java/org/jooq/impl/XMLTable.java | 79 +++++++++++++++++-- 7 files changed, 77 insertions(+), 9 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/XMLTableColumnForOrdinalityStep.java b/jOOQ/src/main/java/org/jooq/XMLTableColumnForOrdinalityStep.java index c7b39d4ba1..1bf7b4a120 100644 --- a/jOOQ/src/main/java/org/jooq/XMLTableColumnForOrdinalityStep.java +++ b/jOOQ/src/main/java/org/jooq/XMLTableColumnForOrdinalityStep.java @@ -40,6 +40,7 @@ package org.jooq; // ... // ... import static org.jooq.SQLDialect.POSTGRES; +// ... /** * A step in the construction of an XMLTABLE expression. diff --git a/jOOQ/src/main/java/org/jooq/XMLTableColumnPathStep.java b/jOOQ/src/main/java/org/jooq/XMLTableColumnPathStep.java index e8594a619e..d99185f885 100644 --- a/jOOQ/src/main/java/org/jooq/XMLTableColumnPathStep.java +++ b/jOOQ/src/main/java/org/jooq/XMLTableColumnPathStep.java @@ -40,6 +40,7 @@ package org.jooq; // ... // ... import static org.jooq.SQLDialect.POSTGRES; +// ... /** * A step in the construction of an XMLTABLE expression. diff --git a/jOOQ/src/main/java/org/jooq/XMLTableColumnsFirstStep.java b/jOOQ/src/main/java/org/jooq/XMLTableColumnsFirstStep.java index 39b52b426b..fc396b823c 100644 --- a/jOOQ/src/main/java/org/jooq/XMLTableColumnsFirstStep.java +++ b/jOOQ/src/main/java/org/jooq/XMLTableColumnsFirstStep.java @@ -40,6 +40,7 @@ package org.jooq; // ... // ... import static org.jooq.SQLDialect.POSTGRES; +// ... /** * A step in the construction of an XMLTABLE expression. diff --git a/jOOQ/src/main/java/org/jooq/XMLTablePassingStep.java b/jOOQ/src/main/java/org/jooq/XMLTablePassingStep.java index fb406df90f..33bbae6200 100644 --- a/jOOQ/src/main/java/org/jooq/XMLTablePassingStep.java +++ b/jOOQ/src/main/java/org/jooq/XMLTablePassingStep.java @@ -40,6 +40,7 @@ package org.jooq; // ... // ... import static org.jooq.SQLDialect.POSTGRES; +// ... /** * A step in the construction of an XMLTABLE expression. diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONTable.java b/jOOQ/src/main/java/org/jooq/impl/JSONTable.java index 6afe446b9a..facfc88c6a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONTable.java @@ -187,7 +187,7 @@ implements List> f = new ArrayList<>(); for (JSONTableColumn c : columns) - f.add(c.field.getDataType() == c.type ? c.field : field(c.field.getQualifiedName(), c.type)); + f.add(c.field.getDataType() == c.type ? c.field : DSL.field(c.field.getQualifiedName(), c.type)); fields = new Fields<>(f); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Names.java b/jOOQ/src/main/java/org/jooq/impl/Names.java index 2c4650736b..25ae3de5c6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Names.java +++ b/jOOQ/src/main/java/org/jooq/impl/Names.java @@ -157,6 +157,7 @@ final class Names { static final Name N_NVL = unquotedName("nvl"); static final Name N_NVL2 = unquotedName("nvl2"); static final Name N_OPENJSON = unquotedName("openjson"); + static final Name N_OPENXML = unquotedName("openxml"); static final Name N_OVERLAY = unquotedName("overlay"); static final Name N_PI = unquotedName("pi"); static final Name N_PIVOT = unquotedName("pivot"); diff --git a/jOOQ/src/main/java/org/jooq/impl/XMLTable.java b/jOOQ/src/main/java/org/jooq/impl/XMLTable.java index 414d8eea05..9e8fe93625 100644 --- a/jOOQ/src/main/java/org/jooq/impl/XMLTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/XMLTable.java @@ -39,7 +39,11 @@ package org.jooq.impl; // ... import static org.jooq.conf.ParamType.INLINED; +import static org.jooq.impl.DSL.cast; import static org.jooq.impl.DSL.inline; +import static org.jooq.impl.DSL.rowNumber; +import static org.jooq.impl.DSL.select; +import static org.jooq.impl.DSL.table; import static org.jooq.impl.Keywords.K_BY; import static org.jooq.impl.Keywords.K_COLUMNS; import static org.jooq.impl.Keywords.K_FOR; @@ -50,6 +54,7 @@ import static org.jooq.impl.Keywords.K_REF; import static org.jooq.impl.Keywords.K_VALUE; import static org.jooq.impl.Keywords.K_XMLTABLE; import static org.jooq.impl.Names.N_XMLTABLE; +import static org.jooq.impl.SQLDataType.XML; import static org.jooq.impl.XMLPassingMechanism.BY_REF; import static org.jooq.impl.XMLPassingMechanism.BY_VALUE; @@ -60,6 +65,7 @@ import org.jooq.Context; import org.jooq.DataType; import org.jooq.Field; import org.jooq.Name; +// ... import org.jooq.Record; import org.jooq.TableOptions; import org.jooq.XML; @@ -84,17 +90,19 @@ implements private final Field passing; private final XMLPassingMechanism passingMechanism; private final QueryPartList columns; + private final boolean hasOrdinality; private transient Fields fields; XMLTable(Field xpath) { - this(xpath, null, null, null); + this(xpath, null, null, null, false); } private XMLTable( Field xpath, Field passing, XMLPassingMechanism passingMechanism, - QueryPartList columns + QueryPartList columns, + boolean hasOrdinality ) { super(TableOptions.expression(), N_XMLTABLE); @@ -102,6 +110,7 @@ implements this.passing = passing; this.passingMechanism = passingMechanism; this.columns = columns == null ? new QueryPartList<>() : columns; + this.hasOrdinality = hasOrdinality; } // ------------------------------------------------------------------------- @@ -115,7 +124,7 @@ implements @Override public final XMLTable passing(Field xml) { - return new XMLTable(xpath, xml, null, columns); + return new XMLTable(xpath, xml, null, columns, hasOrdinality); } @Override @@ -125,7 +134,7 @@ implements @Override public final XMLTable passingByRef(Field xml) { - return new XMLTable(xpath, xml, BY_REF, columns); + return new XMLTable(xpath, xml, BY_REF, columns, hasOrdinality); } @Override @@ -135,7 +144,7 @@ implements @Override public final XMLTable passingByValue(Field xml) { - return new XMLTable(xpath, xml, BY_VALUE, columns); + return new XMLTable(xpath, xml, BY_VALUE, columns, hasOrdinality); } @Override @@ -167,7 +176,7 @@ implements public final XMLTable column(Field name, DataType type) { QueryPartList c = new QueryPartList<>(columns); c.add(new XMLTableColumn(name, type, false, null)); - return new XMLTable(xpath, passing, passingMechanism, c); + return new XMLTable(xpath, passing, passingMechanism, c, hasOrdinality); } @Override @@ -185,7 +194,7 @@ implements int i = c.size() - 1; XMLTableColumn last = c.get(i); c.set(i, new XMLTableColumn(last.field, last.type, forOrdinality, path)); - return new XMLTable(xpath, passing, passingMechanism, c); + return new XMLTable(xpath, passing, passingMechanism, c, hasOrdinality || forOrdinality); } // ------------------------------------------------------------------------- @@ -203,7 +212,7 @@ implements List> f = new ArrayList<>(); for (XMLTableColumn c : columns) - f.add(c.field.getDataType() == c.type ? c.field : field(c.field.getQualifiedName(), c.type)); + f.add(c.field.getDataType() == c.type ? c.field : DSL.field(c.field.getQualifiedName(), c.type)); fields = new Fields<>(f); } @@ -217,6 +226,60 @@ implements @Override public final void accept(Context ctx) { + switch (ctx.family()) { + + + + + + + default: + acceptStandard(ctx); + break; + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + private final void acceptStandard(Context ctx) { ctx.visit(K_XMLTABLE).sql('(') .formatIndentStart() .formatNewLine();