From 02603d5c8610379fbeaecbf062880ee8093a900b Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 9 Jul 2019 17:53:47 +0200 Subject: [PATCH] [jOOQ/jOOQ#4498] Fetch also trigger generated values in SQL Server --- .../src/main/java/org/jooq/conf/Settings.java | 57 ++++++++++++++ .../java/org/jooq/impl/AbstractDMLQuery.java | 74 ++++++++++++++++--- jOOQ/src/main/java/org/jooq/impl/Tools.java | 20 +++++ .../resources/xsd/jooq-runtime-3.12.0.xsd | 15 ++++ 4 files changed, 157 insertions(+), 9 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java index d5ca831074..d4cac7ad4d 100644 --- a/jOOQ/src/main/java/org/jooq/conf/Settings.java +++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java @@ -69,6 +69,8 @@ public class Settings protected Boolean renderOrderByRownumberForEmulatedPagination = true; @XmlElement(defaultValue = "true") protected Boolean renderOutputForSQLServerReturningClause = true; + @XmlElement(defaultValue = "true") + protected Boolean fetchTriggerValuesAfterSQLServerOutput = true; @XmlElement(defaultValue = "false") protected Boolean transformTableListsToAnsiJoin = false; @XmlElement(defaultValue = "DEFAULT") @@ -577,6 +579,10 @@ public class Settings * to revert to jOOQ calling {@code java.sql.Statement#getGeneratedKeys()} instead, which * is only supported for single row inserts. *

+ * This OUTPUT clause does not support fetching trigger generated values. In order + * to fetch trigger generated values, {@link #fetchTriggerValuesAfterSQLServerOutput} needs to + * be enabled as well. + *

* For details, see https://github.com/jOOQ/jOOQ/issues/4498. * * @return @@ -600,6 +606,37 @@ public class Settings this.renderOutputForSQLServerReturningClause = value; } + /** + * Fetch trigger values after SQL Server OUTPUT clause. + *

+ * SQL Server OUTPUT statements do not support fetching trigger generated values. + * This is a limitation of the {@link #renderOutputForSQLServerReturningClause}. An additional + * MERGE statement can run a second query if (and only if) the primary key has been + * included in the OUTPUT clause. + *

+ * For details, see https://github.com/jOOQ/jOOQ/issues/4498. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isFetchTriggerValuesAfterSQLServerOutput() { + return fetchTriggerValuesAfterSQLServerOutput; + } + + /** + * Sets the value of the fetchTriggerValuesAfterSQLServerOutput property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setFetchTriggerValuesAfterSQLServerOutput(Boolean value) { + this.fetchTriggerValuesAfterSQLServerOutput = value; + } + /** * Transform table lists to ANSI join if possible *

@@ -1855,6 +1892,11 @@ public class Settings return this; } + public Settings withFetchTriggerValuesAfterSQLServerOutput(Boolean value) { + setFetchTriggerValuesAfterSQLServerOutput(value); + return this; + } + public Settings withTransformTableListsToAnsiJoin(Boolean value) { setTransformTableListsToAnsiJoin(value); return this; @@ -2189,6 +2231,11 @@ public class Settings sb.append(renderOutputForSQLServerReturningClause); sb.append(""); } + if (fetchTriggerValuesAfterSQLServerOutput!= null) { + sb.append(""); + sb.append(fetchTriggerValuesAfterSQLServerOutput); + sb.append(""); + } if (transformTableListsToAnsiJoin!= null) { sb.append(""); sb.append(transformTableListsToAnsiJoin); @@ -2583,6 +2630,15 @@ public class Settings return false; } } + if (fetchTriggerValuesAfterSQLServerOutput == null) { + if (other.fetchTriggerValuesAfterSQLServerOutput!= null) { + return false; + } + } else { + if (!fetchTriggerValuesAfterSQLServerOutput.equals(other.fetchTriggerValuesAfterSQLServerOutput)) { + return false; + } + } if (transformTableListsToAnsiJoin == null) { if (other.transformTableListsToAnsiJoin!= null) { return false; @@ -3037,6 +3093,7 @@ public class Settings result = ((prime*result)+((renderScalarSubqueriesForStoredFunctions == null)? 0 :renderScalarSubqueriesForStoredFunctions.hashCode())); result = ((prime*result)+((renderOrderByRownumberForEmulatedPagination == null)? 0 :renderOrderByRownumberForEmulatedPagination.hashCode())); result = ((prime*result)+((renderOutputForSQLServerReturningClause == null)? 0 :renderOutputForSQLServerReturningClause.hashCode())); + result = ((prime*result)+((fetchTriggerValuesAfterSQLServerOutput == null)? 0 :fetchTriggerValuesAfterSQLServerOutput.hashCode())); result = ((prime*result)+((transformTableListsToAnsiJoin == null)? 0 :transformTableListsToAnsiJoin.hashCode())); result = ((prime*result)+((backslashEscaping == null)? 0 :backslashEscaping.hashCode())); result = ((prime*result)+((paramType == null)? 0 :paramType.hashCode())); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java index 4104809075..cd521c4289 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java @@ -50,6 +50,7 @@ import static org.jooq.SQLDialect.HSQLDB; // ... // ... import static org.jooq.conf.SettingsTools.renderLocale; +import static org.jooq.impl.DSL.name; import static org.jooq.impl.DSL.select; import static org.jooq.impl.DSL.unquotedName; import static org.jooq.impl.Keywords.K_BEGIN; @@ -86,11 +87,16 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import org.jooq.Asterisk; import org.jooq.Binding; import org.jooq.CommonTableExpression; +import org.jooq.Condition; import org.jooq.Configuration; import org.jooq.Context; import org.jooq.DSLContext; @@ -110,6 +116,7 @@ import org.jooq.SQLDialect; import org.jooq.Select; import org.jooq.SelectFieldOrAsterisk; import org.jooq.Table; +import org.jooq.UniqueKey; import org.jooq.conf.ExecuteWithoutWhere; import org.jooq.conf.RenderNameCase; import org.jooq.conf.SettingsTools; @@ -475,6 +482,42 @@ abstract class AbstractDMLQuery extends AbstractRowCountQuery + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -565,6 +608,28 @@ abstract class AbstractDMLQuery extends AbstractRowCountQuery + + + + + + + + + + + + + + + + + + + + + + @@ -645,15 +710,6 @@ abstract class AbstractDMLQuery extends AbstractRowCountQuery - - - - - - - - - diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index eb0275e26c..628e6f761b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -4876,6 +4876,26 @@ final class Tools { return false; } + @SuppressWarnings("serial") + static final QueryPartList qualify(Table table, SelectFieldList fields) { + QueryPartList result = new QueryPartList() { + @Override + protected void toSQLEmptyList(Context context) { + table.asterisk(); + } + + @Override + public boolean declaresFields() { + return true; + } + }; + + for (SelectFieldOrAsterisk field : fields) + result.add(qualify(table, field)); + + return result; + } + static final SelectFieldOrAsterisk qualify(Table table, SelectFieldOrAsterisk field) { if (field instanceof Field) return qualify(table, (Field) field); diff --git a/jOOQ/src/main/resources/xsd/jooq-runtime-3.12.0.xsd b/jOOQ/src/main/resources/xsd/jooq-runtime-3.12.0.xsd index 1cceb15642..ef632e80e2 100644 --- a/jOOQ/src/main/resources/xsd/jooq-runtime-3.12.0.xsd +++ b/jOOQ/src/main/resources/xsd/jooq-runtime-3.12.0.xsd @@ -122,6 +122,21 @@ want to prevent jOOQ from rendering this OUTPUT clause can deactiva to revert to jOOQ calling {@code java.sql.Statement#getGeneratedKeys()} instead, which is only supported for single row inserts.

+This OUTPUT clause does not support fetching trigger generated values. In order +to fetch trigger generated values, {@link #fetchTriggerValuesAfterSQLServerOutput} needs to +be enabled as well. +

+For details, see https://github.com/jOOQ/jOOQ/issues/4498.]]> + + + + OUTPUT clause. +

+SQL Server OUTPUT statements do not support fetching trigger generated values. +This is a limitation of the {@link #renderOutputForSQLServerReturningClause}. An additional +MERGE statement can run a second query if (and only if) the primary key has been +included in the OUTPUT clause. +

For details, see https://github.com/jOOQ/jOOQ/issues/4498.]]>