[jOOQ/jOOQ#4498] Fetch also trigger generated values in SQL Server

This commit is contained in:
Lukas Eder 2019-07-09 17:53:47 +02:00
parent 8c69160983
commit 02603d5c86
4 changed files with 157 additions and 9 deletions

View File

@ -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.
* <p>
* This <code>OUTPUT</code> clause does not support fetching trigger generated values. In order
* to fetch trigger generated values, {@link #fetchTriggerValuesAfterSQLServerOutput} needs to
* be enabled as well.
* <p>
* For details, see <a href="https://github.com/jOOQ/jOOQ/issues/4498">https://github.com/jOOQ/jOOQ/issues/4498</a>.
*
* @return
@ -600,6 +606,37 @@ public class Settings
this.renderOutputForSQLServerReturningClause = value;
}
/**
* Fetch trigger values after SQL Server <code>OUTPUT</code> clause.
* <p>
* SQL Server <code>OUTPUT</code> statements do not support fetching trigger generated values.
* This is a limitation of the {@link #renderOutputForSQLServerReturningClause}. An additional
* <code>MERGE</code> statement can run a second query if (and only if) the primary key has been
* included in the <code>OUTPUT</code> clause.
* <p>
* For details, see <a href="https://github.com/jOOQ/jOOQ/issues/4498">https://github.com/jOOQ/jOOQ/issues/4498</a>.
*
* @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
* <p>
@ -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("</renderOutputForSQLServerReturningClause>");
}
if (fetchTriggerValuesAfterSQLServerOutput!= null) {
sb.append("<fetchTriggerValuesAfterSQLServerOutput>");
sb.append(fetchTriggerValuesAfterSQLServerOutput);
sb.append("</fetchTriggerValuesAfterSQLServerOutput>");
}
if (transformTableListsToAnsiJoin!= null) {
sb.append("<transformTableListsToAnsiJoin>");
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()));

View File

@ -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<R extends Record> extends AbstractRowCountQuery
@ -565,6 +608,28 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractRowCountQuery
@ -645,15 +710,6 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractRowCountQuery

View File

@ -4876,6 +4876,26 @@ final class Tools {
return false;
}
@SuppressWarnings("serial")
static final QueryPartList<SelectFieldOrAsterisk> qualify(Table<?> table, SelectFieldList<SelectFieldOrAsterisk> fields) {
QueryPartList<SelectFieldOrAsterisk> result = new QueryPartList<SelectFieldOrAsterisk>() {
@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);

View File

@ -122,6 +122,21 @@ want to prevent jOOQ from rendering this <code>OUTPUT</code> clause can deactiva
to revert to jOOQ calling {@code java.sql.Statement#getGeneratedKeys()} instead, which
is only supported for single row inserts.
<p>
This <code>OUTPUT</code> clause does not support fetching trigger generated values. In order
to fetch trigger generated values, {@link #fetchTriggerValuesAfterSQLServerOutput} needs to
be enabled as well.
<p>
For details, see <a href="https://github.com/jOOQ/jOOQ/issues/4498">https://github.com/jOOQ/jOOQ/issues/4498</a>.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="fetchTriggerValuesAfterSQLServerOutput" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Fetch trigger values after SQL Server <code>OUTPUT</code> clause.
<p>
SQL Server <code>OUTPUT</code> statements do not support fetching trigger generated values.
This is a limitation of the {@link #renderOutputForSQLServerReturningClause}. An additional
<code>MERGE</code> statement can run a second query if (and only if) the primary key has been
included in the <code>OUTPUT</code> clause.
<p>
For details, see <a href="https://github.com/jOOQ/jOOQ/issues/4498">https://github.com/jOOQ/jOOQ/issues/4498</a>.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>