[jOOQ/jOOQ#8800] Add Settings.transformAnsiJoinToTableLists to support pre-ANSI join syntax

This commit is contained in:
Lukas Eder 2020-01-28 15:00:07 +01:00
parent 4c5b8b0c7e
commit 6033daafe0
7 changed files with 277 additions and 15 deletions

View File

@ -82,6 +82,8 @@ public class Settings
@XmlElement(defaultValue = "true")
protected Boolean fetchTriggerValuesAfterSQLServerOutput = true;
@XmlElement(defaultValue = "false")
protected Boolean transformAnsiJoinToTableLists = false;
@XmlElement(defaultValue = "false")
protected Boolean transformTableListsToAnsiJoin = false;
@XmlElement(defaultValue = "DEFAULT")
@XmlSchemaType(name = "string")
@ -705,6 +707,38 @@ public class Settings
this.fetchTriggerValuesAfterSQLServerOutput = value;
}
/**
* Transform ANSI join to table lists if possible
* <p>
* Historically, prior to ANSI join syntax, joins were implemented by listing tables in
* the FROM clause and providing join predicates in the WHERE clause, possibly using vendor specific
* operators like <code>(+)</code> (Oracle, DB2) or <code>*=</code> (SQL Server) for outer join
* support. For backwards compatibility with older RDBMS versions, ANSI joins in jOOQ code may be
* converted to equivalent table lists in generated SQL using this flag.
* <p>
* This feature is available in the commercial distribution only.
*
* @return
* possible object is
* {@link Boolean }
*
*/
public Boolean isTransformAnsiJoinToTableLists() {
return transformAnsiJoinToTableLists;
}
/**
* Sets the value of the transformAnsiJoinToTableLists property.
*
* @param value
* allowed object is
* {@link Boolean }
*
*/
public void setTransformAnsiJoinToTableLists(Boolean value) {
this.transformAnsiJoinToTableLists = value;
}
/**
* Transform table lists to ANSI join if possible
* <p>
@ -2123,6 +2157,11 @@ public class Settings
return this;
}
public Settings withTransformAnsiJoinToTableLists(Boolean value) {
setTransformAnsiJoinToTableLists(value);
return this;
}
public Settings withTransformTableListsToAnsiJoin(Boolean value) {
setTransformTableListsToAnsiJoin(value);
return this;
@ -2661,6 +2700,7 @@ public class Settings
builder.append("renderOutputForSQLServerReturningClause", renderOutputForSQLServerReturningClause);
builder.append("renderParenthesisAroundSetOperationQueries", renderParenthesisAroundSetOperationQueries);
builder.append("fetchTriggerValuesAfterSQLServerOutput", fetchTriggerValuesAfterSQLServerOutput);
builder.append("transformAnsiJoinToTableLists", transformAnsiJoinToTableLists);
builder.append("transformTableListsToAnsiJoin", transformTableListsToAnsiJoin);
builder.append("backslashEscaping", backslashEscaping);
builder.append("paramType", paramType);
@ -2916,6 +2956,15 @@ public class Settings
return false;
}
}
if (transformAnsiJoinToTableLists == null) {
if (other.transformAnsiJoinToTableLists!= null) {
return false;
}
} else {
if (!transformAnsiJoinToTableLists.equals(other.transformAnsiJoinToTableLists)) {
return false;
}
}
if (transformTableListsToAnsiJoin == null) {
if (other.transformTableListsToAnsiJoin!= null) {
return false;
@ -3509,6 +3558,7 @@ public class Settings
result = ((prime*result)+((renderOutputForSQLServerReturningClause == null)? 0 :renderOutputForSQLServerReturningClause.hashCode()));
result = ((prime*result)+((renderParenthesisAroundSetOperationQueries == null)? 0 :renderParenthesisAroundSetOperationQueries.hashCode()));
result = ((prime*result)+((fetchTriggerValuesAfterSQLServerOutput == null)? 0 :fetchTriggerValuesAfterSQLServerOutput.hashCode()));
result = ((prime*result)+((transformAnsiJoinToTableLists == null)? 0 :transformAnsiJoinToTableLists.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

@ -66,8 +66,8 @@ final class CombinedCondition extends AbstractCondition {
private static final Clause[] CLAUSES_AND = { CONDITION, CONDITION_AND };
private static final Clause[] CLAUSES_OR = { CONDITION, CONDITION_OR };
private final Operator operator;
private final List<Condition> conditions;
final Operator operator;
final List<Condition> conditions;
static Condition of(Operator operator, Condition left, Condition right) {
if (left instanceof NoCondition)

View File

@ -81,14 +81,14 @@ import org.jooq.conf.ParamType;
*/
final class CompareCondition extends AbstractCondition implements LikeEscapeStep {
private static final long serialVersionUID = -747240442279619486L;
private static final Clause[] CLAUSES = { CONDITION, CONDITION_COMPARISON };
private static final Set<SQLDialect> REQUIRES_CAST_ON_LIKE = SQLDialect.supportedBy(DERBY, POSTGRES);
private static final long serialVersionUID = -747240442279619486L;
private static final Clause[] CLAUSES = { CONDITION, CONDITION_COMPARISON };
private static final Set<SQLDialect> REQUIRES_CAST_ON_LIKE = SQLDialect.supportedBy(DERBY, POSTGRES);
private final Field<?> field1;
private final Field<?> field2;
private final Comparator comparator;
private Character escape;
final Field<?> field1;
final Field<?> field2;
final Comparator comparator;
private Character escape;
CompareCondition(Field<?> field1, Field<?> field2, Comparator comparator) {
this.field1 = field1;

View File

@ -167,9 +167,9 @@ implements
private final JoinType type;
private final ConditionProviderImpl condition;
private final QueryPartList<Field<?>> using;
final JoinType type;
final ConditionProviderImpl condition;
final QueryPartList<Field<?>> using;
JoinTable(TableLike<?> lhs, TableLike<?> rhs, JoinType type) {
@ -488,7 +488,7 @@ implements
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private final Condition naturalCondition() {
final Condition naturalCondition() {
List<Condition> conditions = new ArrayList<>(using.size());
for (Field<?> field : lhs.fields()) {
@ -502,7 +502,7 @@ implements
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private final Condition usingCondition() {
final Condition usingCondition() {
List<Condition> conditions = new ArrayList<>(using.size());
for (Field<?> field : using)

View File

@ -192,6 +192,8 @@ import org.jooq.WindowDefinition;
import org.jooq.exception.DataAccessException;
import org.jooq.impl.Tools.BooleanDataKey;
import org.jooq.impl.Tools.DataKey;
import org.jooq.impl.Transform.Transformer;
import org.jooq.tools.JooqLogger;
import org.jooq.tools.StringUtils;
/**
@ -207,6 +209,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
* Generated UID
*/
private static final long serialVersionUID = 1646393178384872967L;
private static final JooqLogger log = JooqLogger.getLogger(SelectQueryImpl.class);
private static final Clause[] CLAUSES = { SELECT };
private static final Set<SQLDialect> EMULATE_SELECT_INTO_AS_CTAS = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES, SQLITE);
private static final Set<SQLDialect> NO_SUPPORT_FOR_UPDATE = SQLDialect.supportedBy(CUBRID);
@ -911,7 +914,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
/**
* The default LIMIT / OFFSET clause in most dialects
*/
private void toSQLReferenceLimitDefault(Context<?> context) {
private final void toSQLReferenceLimitDefault(Context<?> context) {
Object data = context.data(DATA_RENDER_TRAILING_LIMIT_IF_APPLICABLE);
context.data(DATA_RENDER_TRAILING_LIMIT_IF_APPLICABLE, true);
@ -1355,6 +1358,9 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
context.formatSeparator()
.visit(K_FROM)
.sql(' ')
@ -1591,6 +1597,97 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
}
}
private final void toSQLOrderBy(
Context<?> ctx,
Field<?>[] originalFields,

View File

@ -0,0 +1,98 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;

View File

@ -177,6 +177,21 @@ included in the <code>OUTPUT</code> clause.
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="transformAnsiJoinToTableLists" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Transform ANSI join to table lists if possible
<p>
Historically, prior to ANSI join syntax, joins were implemented by listing tables in
the FROM clause and providing join predicates in the WHERE clause, possibly using vendor specific
operators like <code>(+)</code> (Oracle, DB2) or <code>*=</code> (SQL Server) for outer join
support. For backwards compatibility with older RDBMS versions, ANSI joins in jOOQ code may be
converted to equivalent table lists in generated SQL using this flag.
<p>
This flag has a limited implementation that supports inner joins (in most cases) and outer joins
(only for simple comparison predicates).
<p>
This feature is available in the commercial distribution only.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="transformTableListsToAnsiJoin" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Transform table lists to ANSI join if possible
<p>
@ -186,6 +201,8 @@ operators like <code>(+)</code> (Oracle, DB2) or <code>*=</code> (SQL Server) fo
support. Migrating such join syntax is tedious. The jOOQ parser can parse the old syntax and
this flag enables the transformation to ANSI join syntax.
<p>
This flag has not been implemented yet!
<p>
This feature is available in the commercial distribution only.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>