From 345586e8db06132aa7d7438236d784cb32ac82a2 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 6 Mar 2020 15:16:40 +0100 Subject: [PATCH] [jOOQ/jOOQ#8945] [jOOQ/jOOQ#9923] Add support for FOR XML This includes support for the new org.jooq.XML type --- .../java/org/jooq/SelectForUpdateStep.java | 2 +- .../org/jooq/SelectForUpdateWaitStep.java | 8 +- jOOQ/src/main/java/org/jooq/SelectQuery.java | 57 ++++++++++ .../java/org/jooq/impl/DefaultBinding.java | 48 ++++++++ .../src/main/java/org/jooq/impl/Keywords.java | 5 + .../main/java/org/jooq/impl/SQLDataType.java | 9 ++ .../main/java/org/jooq/impl/SelectImpl.java | 103 ++++++++++++++++++ .../java/org/jooq/impl/SelectQueryImpl.java | 68 ++++++++++++ 8 files changed, 295 insertions(+), 5 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/SelectForUpdateStep.java b/jOOQ/src/main/java/org/jooq/SelectForUpdateStep.java index fc6f6f29a9..786a4b0446 100644 --- a/jOOQ/src/main/java/org/jooq/SelectForUpdateStep.java +++ b/jOOQ/src/main/java/org/jooq/SelectForUpdateStep.java @@ -118,7 +118,7 @@ import static org.jooq.SQLDialect.POSTGRES; * * @author Lukas Eder */ -public interface SelectForUpdateStep extends SelectOptionStep { +public interface SelectForUpdateStep extends SelectForStep { /** * Add a FOR UPDATE clause to the end of the query. diff --git a/jOOQ/src/main/java/org/jooq/SelectForUpdateWaitStep.java b/jOOQ/src/main/java/org/jooq/SelectForUpdateWaitStep.java index 19f1a7451f..539d67b4e4 100644 --- a/jOOQ/src/main/java/org/jooq/SelectForUpdateWaitStep.java +++ b/jOOQ/src/main/java/org/jooq/SelectForUpdateWaitStep.java @@ -104,7 +104,7 @@ import static org.jooq.SQLDialect.POSTGRES; * * @author Lukas Eder */ -public interface SelectForUpdateWaitStep extends SelectOptionStep { +public interface SelectForUpdateWaitStep extends SelectForStep { /** * Add a WAIT clause to the FOR <lock_mode> @@ -115,7 +115,7 @@ public interface SelectForUpdateWaitStep extends SelectOptionS * @see SelectQuery#setForLockModeWait(int) */ @Support({ MARIADB }) - SelectOptionStep wait(int seconds); + SelectForStep wait(int seconds); /** * Add a NOWAIT clause to the @@ -124,7 +124,7 @@ public interface SelectForUpdateWaitStep extends SelectOptionS * @see SelectQuery#setForLockModeNoWait() */ @Support({ MARIADB, MYSQL, POSTGRES }) - SelectOptionStep noWait(); + SelectForStep noWait(); /** * Add a WAIT clause to the FOR <lock_mode> @@ -133,5 +133,5 @@ public interface SelectForUpdateWaitStep extends SelectOptionS * @see SelectQuery#setForLockModeSkipLocked() */ @Support({ MYSQL, POSTGRES }) - SelectOptionStep skipLocked(); + SelectForStep skipLocked(); } diff --git a/jOOQ/src/main/java/org/jooq/SelectQuery.java b/jOOQ/src/main/java/org/jooq/SelectQuery.java index cc0a86d230..da7b7a511b 100644 --- a/jOOQ/src/main/java/org/jooq/SelectQuery.java +++ b/jOOQ/src/main/java/org/jooq/SelectQuery.java @@ -1197,4 +1197,61 @@ public interface SelectQuery extends Select, ConditionProvi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index 6790d1f28f..16aca5febc 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java @@ -169,6 +169,7 @@ import org.jooq.Schema; import org.jooq.Scope; import org.jooq.TableRecord; import org.jooq.UDTRecord; +import org.jooq.XML; import org.jooq.exception.ControlFlowSignal; import org.jooq.exception.DataTypeException; import org.jooq.exception.MappingException; @@ -251,6 +252,8 @@ public class DefaultBinding implements Binding { return new DefaultJSONBinding(converter, isLob); else if (type == JSONB.class) return new DefaultJSONBBinding(converter, isLob); + else if (type == XML.class) + return new DefaultXMLBinding(converter, isLob); else if (type == LocalDate.class) { DateToLocalDateConverter c1 = new DateToLocalDateConverter(); @@ -4381,6 +4384,51 @@ public class DefaultBinding implements Binding { + return Types.VARCHAR; + } + } + + static final class DefaultXMLBinding extends AbstractBinding { + + /** + * Generated UID + */ + private static final long serialVersionUID = 3430629127218407737L; + + DefaultXMLBinding(Converter converter, boolean isLob) { + super(converter, isLob); + } + + @Override + final void set0(BindingSetStatementContext ctx, XML value) throws SQLException { + ctx.statement().setString(ctx.index(), value.toString()); + } + + @Override + final void set0(BindingSetSQLOutputContext ctx, XML value) throws SQLException { + ctx.output().writeString(value.toString()); + } + + @Override + final XML get0(BindingGetResultSetContext ctx) throws SQLException { + String string = ctx.resultSet().getString(ctx.index()); + return string == null ? null : XML.valueOf(string); + } + + @Override + final XML get0(BindingGetStatementContext ctx) throws SQLException { + String string = ctx.statement().getString(ctx.index()); + return string == null ? null : XML.valueOf(string); + } + + @Override + final XML get0(BindingGetSQLInputContext ctx) throws SQLException { + String string = ctx.input().readString(); + return string == null ? null : XML.valueOf(string); + } + + @Override + final int sqltype(Statement statement, Configuration configuration) { return Types.VARCHAR; } } diff --git a/jOOQ/src/main/java/org/jooq/impl/Keywords.java b/jOOQ/src/main/java/org/jooq/impl/Keywords.java index b7a517cad1..01c74a8f14 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Keywords.java +++ b/jOOQ/src/main/java/org/jooq/impl/Keywords.java @@ -137,6 +137,7 @@ final class Keywords { static final Keyword K_DROP_SCHEMA = keyword("drop schema"); static final Keyword K_DROP_TABLE = keyword("drop table"); static final Keyword K_DROP_VIEW = keyword("drop view"); + static final Keyword K_ELEMENTS = keyword("elements"); static final Keyword K_ELSE = keyword("else"); static final Keyword K_ELSEIF = keyword("elseif"); static final Keyword K_ELSIF = keyword("elsif"); @@ -270,6 +271,7 @@ final class Keywords { static final Keyword K_OVERLAPS = keyword("overlaps"); static final Keyword K_PARTITION_BY = keyword("partition by"); static final Keyword K_PASSING = keyword("passing"); + static final Keyword K_PATH = keyword("path"); static final Keyword K_PERCENT = keyword("percent"); static final Keyword K_PERIOD = keyword("period"); static final Keyword K_PIVOT = keyword("pivot"); @@ -307,6 +309,8 @@ final class Keywords { static final Keyword K_RETURNING = keyword("returning"); static final Keyword K_REVERSE = keyword("reverse"); static final Keyword K_REVOKE = keyword("revoke"); + static final Keyword K_RAW = keyword("raw"); + static final Keyword K_ROOT = keyword("root"); static final Keyword K_ROW = keyword("row"); static final Keyword K_ROWCOUNT = keyword("rowcount"); static final Keyword K_ROWS = keyword("rows"); @@ -384,6 +388,7 @@ final class Keywords { static final Keyword K_WITH_TIES = keyword("with ties"); static final Keyword K_WITHIN_GROUP = keyword("within group"); static final Keyword K_WITHOUT_ARRAY_WRAPPER = keyword("without_array_wrapper"); + static final Keyword K_XML = keyword("xml"); static final Keyword K_XMLTABLE = keyword("xmltable"); static final Keyword K_YEAR = keyword("year"); static final Keyword K_YEAR_MONTH = keyword("year_month"); diff --git a/jOOQ/src/main/java/org/jooq/impl/SQLDataType.java b/jOOQ/src/main/java/org/jooq/impl/SQLDataType.java index 6296610663..c700d21637 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SQLDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/SQLDataType.java @@ -88,6 +88,7 @@ import org.jooq.Record; import org.jooq.Result; import org.jooq.RowId; import org.jooq.SQLDialect; +import org.jooq.XML; import org.jooq.types.DayToSecond; import org.jooq.types.UByte; import org.jooq.types.UInteger; @@ -676,6 +677,14 @@ public final class SQLDataType { */ public static final DataType JSONB = new DefaultDataType<>(null, JSONB.class, "jsonb"); + /** + * The {@link XML} type. + *

+ * This is not a SQL or JDBC standard. This type handles XML types where + * they are supported + */ + public static final DataType XML = new DefaultDataType<>(null, XML.class, "xml"); + // ------------------------------------------------------------------------- // Static initialisation of dialect-specific data types // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java index 7515b8ca73..1ae9c4c32f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java @@ -113,6 +113,9 @@ import org.jooq.SelectConnectByConditionStep; import org.jooq.SelectFieldOrAsterisk; import org.jooq.SelectFinalStep; import org.jooq.SelectForUpdateOfStep; +// ... +// ... +// ... import org.jooq.SelectHavingConditionStep; import org.jooq.SelectIntoStep; import org.jooq.SelectJoinStep; @@ -199,6 +202,12 @@ final class SelectImpl, SelectSeekLimitStep, SelectLimitPercentStep, @@ -244,6 +253,13 @@ final class SelectImpl offsetParam; + + + + + + + SelectImpl(Configuration configuration, WithImpl with) { this(configuration, with, false); } @@ -1834,6 +1850,93 @@ final class SelectImpl select) { return new SelectImpl(getDelegate().union(select)); diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java index a714ec8783..d48f12d453 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java @@ -38,6 +38,7 @@ package org.jooq.impl; import static java.lang.Boolean.TRUE; +import static java.util.Arrays.asList; import static org.jooq.Clause.SELECT; import static org.jooq.Clause.SELECT_CONNECT_BY; import static org.jooq.Clause.SELECT_EXCEPT; @@ -263,6 +264,8 @@ final class SelectQueryImpl extends AbstractResultQuery imp + + private final TableList from; private final ConditionProviderImpl condition; private final ConditionProviderImpl connectBy; @@ -489,6 +492,13 @@ final class SelectQueryImpl extends AbstractResultQuery imp // [#1808] TODO: Restrict this field list, in case a restricting fetch() // method was called to get here if (fields == null || fields.isEmpty()) + + + + + + + fields = getSelect(); // If no projection was specified explicitly, create fields from result @@ -831,6 +841,12 @@ final class SelectQueryImpl extends AbstractResultQuery imp + + + + + + // [#1952] SQL Server OPTION() clauses as well as many other optional // end-of-query clauses are appended to the end of a query if (!StringUtils.isBlank(option)) { @@ -2187,6 +2203,58 @@ final class SelectQueryImpl extends AbstractResultQuery imp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Override public final List> getSelect() { return getSelectResolveAllAsterisks(configuration() != null ? configuration().family() : SQLDialect.DEFAULT);