[jOOQ/jOOQ#10616] Add Settings.implicitJoinType to govern whether an INNER or LEFT JOIN is generated

This commit is contained in:
Lukas Eder 2020-09-10 16:49:31 +02:00
parent 4b8fcd9eff
commit e64a4279ff
4 changed files with 121 additions and 4 deletions

View File

@ -0,0 +1,40 @@
package org.jooq.conf;
import javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for RenderImplicitJoinType.
*
* <p>The following schema fragment specifies the expected content contained within this class.
* <p>
* <pre>
* &lt;simpleType name="RenderImplicitJoinType"&gt;
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string"&gt;
* &lt;enumeration value="DEFAULT"/&gt;
* &lt;enumeration value="INNER_JOIN"/&gt;
* &lt;enumeration value="LEFT_JOIN"/&gt;
* &lt;/restriction&gt;
* &lt;/simpleType&gt;
* </pre>
*
*/
@XmlType(name = "RenderImplicitJoinType")
@XmlEnum
public enum RenderImplicitJoinType {
DEFAULT,
INNER_JOIN,
LEFT_JOIN;
public String value() {
return name();
}
public static RenderImplicitJoinType fromValue(String v) {
return valueOf(v);
}
}

View File

@ -79,6 +79,9 @@ public class Settings
protected RenderOptionalKeyword renderOptionalOuterKeyword = RenderOptionalKeyword.DEFAULT;
@XmlElement(defaultValue = "false")
protected Boolean renderScalarSubqueriesForStoredFunctions = false;
@XmlElement(defaultValue = "DEFAULT")
@XmlSchemaType(name = "string")
protected RenderImplicitJoinType renderImplicitJoinType = RenderImplicitJoinType.DEFAULT;
@XmlElement(defaultValue = "true")
protected Boolean renderOrderByRownumberForEmulatedPagination = true;
@XmlElement(defaultValue = "true")
@ -626,6 +629,22 @@ public class Settings
this.renderScalarSubqueriesForStoredFunctions = value;
}
/**
* The join type to be generated by implicit joins.
*
*/
public RenderImplicitJoinType getRenderImplicitJoinType() {
return renderImplicitJoinType;
}
/**
* The join type to be generated by implicit joins.
*
*/
public void setRenderImplicitJoinType(RenderImplicitJoinType value) {
this.renderImplicitJoinType = value;
}
/**
* Whether an additional <code>ORDER BY rn</code> clause should be rendered on emulated paginated queries.
* <p>
@ -2347,6 +2366,15 @@ public class Settings
return this;
}
/**
* The join type to be generated by implicit joins.
*
*/
public Settings withRenderImplicitJoinType(RenderImplicitJoinType value) {
setRenderImplicitJoinType(value);
return this;
}
public Settings withRenderOrderByRownumberForEmulatedPagination(Boolean value) {
setRenderOrderByRownumberForEmulatedPagination(value);
return this;
@ -2942,6 +2970,7 @@ public class Settings
builder.append("renderOptionalInnerKeyword", renderOptionalInnerKeyword);
builder.append("renderOptionalOuterKeyword", renderOptionalOuterKeyword);
builder.append("renderScalarSubqueriesForStoredFunctions", renderScalarSubqueriesForStoredFunctions);
builder.append("renderImplicitJoinType", renderImplicitJoinType);
builder.append("renderOrderByRownumberForEmulatedPagination", renderOrderByRownumberForEmulatedPagination);
builder.append("renderOutputForSQLServerReturningClause", renderOutputForSQLServerReturningClause);
builder.append("renderParenthesisAroundSetOperationQueries", renderParenthesisAroundSetOperationQueries);
@ -3190,6 +3219,15 @@ public class Settings
return false;
}
}
if (renderImplicitJoinType == null) {
if (other.renderImplicitJoinType!= null) {
return false;
}
} else {
if (!renderImplicitJoinType.equals(other.renderImplicitJoinType)) {
return false;
}
}
if (renderOrderByRownumberForEmulatedPagination == null) {
if (other.renderOrderByRownumberForEmulatedPagination!= null) {
return false;
@ -3880,6 +3918,7 @@ public class Settings
result = ((prime*result)+((renderOptionalInnerKeyword == null)? 0 :renderOptionalInnerKeyword.hashCode()));
result = ((prime*result)+((renderOptionalOuterKeyword == null)? 0 :renderOptionalOuterKeyword.hashCode()));
result = ((prime*result)+((renderScalarSubqueriesForStoredFunctions == null)? 0 :renderScalarSubqueriesForStoredFunctions.hashCode()));
result = ((prime*result)+((renderImplicitJoinType == null)? 0 :renderImplicitJoinType.hashCode()));
result = ((prime*result)+((renderOrderByRownumberForEmulatedPagination == null)? 0 :renderOrderByRownumberForEmulatedPagination.hashCode()));
result = ((prime*result)+((renderOutputForSQLServerReturningClause == null)? 0 :renderOutputForSQLServerReturningClause.hashCode()));
result = ((prime*result)+((renderParenthesisAroundSetOperationQueries == null)? 0 :renderParenthesisAroundSetOperationQueries.hashCode()));

View File

@ -69,6 +69,7 @@ import org.jooq.Configuration;
import org.jooq.Context;
import org.jooq.DSLContext;
import org.jooq.ForeignKey;
import org.jooq.JoinType;
// ...
import org.jooq.QueryPart;
import org.jooq.QueryPartInternal;
@ -81,9 +82,11 @@ import org.jooq.VisitListener;
import org.jooq.VisitListenerProvider;
import org.jooq.conf.ParamCastMode;
import org.jooq.conf.ParamType;
import org.jooq.conf.RenderImplicitJoinType;
import org.jooq.conf.Settings;
import org.jooq.conf.SettingsTools;
import org.jooq.conf.StatementType;
import org.jooq.tools.StringUtils;
/**
* @author Lukas Eder
@ -774,7 +777,7 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
sb.append("]");
}
static class JoinNode {
class JoinNode {
final Table<?> table;
final Map<ForeignKey<?, ?>, JoinNode> children;
@ -786,8 +789,25 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
public Table<?> joinTree() {
Table<?> result = table;
for (Entry<ForeignKey<?, ?>, JoinNode> e : children.entrySet())
result = result.join(e.getValue().joinTree(), e.getKey().nullable() ? LEFT_OUTER_JOIN : JOIN).onKey(e.getKey());
for (Entry<ForeignKey<?, ?>, JoinNode> e : children.entrySet()) {
JoinType type;
switch (StringUtils.defaultIfNull(settings().getRenderImplicitJoinType(),
RenderImplicitJoinType.DEFAULT)) {
case INNER_JOIN:
type = JOIN;
break;
case LEFT_JOIN:
type = LEFT_OUTER_JOIN;
break;
case DEFAULT:
default:
type = e.getKey().nullable() ? LEFT_OUTER_JOIN : JOIN;
break;
}
result = result.join(e.getValue().joinTree(), type).onKey(e.getKey());
}
return result;
}
@ -798,7 +818,7 @@ abstract class AbstractContext<C extends Context<C>> extends AbstractScope imple
}
}
static class ScopeStackElement {
class ScopeStackElement {
final int scopeLevel;
int[] positions;
int indent;

View File

@ -133,6 +133,10 @@ Oracle 11g (and potentially, other databases too) implements scalar subquery cac
set to true, users can automatically profit from this feature in all SQL statements.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="renderImplicitJoinType" type="jooq-runtime:RenderImplicitJoinType" minOccurs="0" maxOccurs="1" default="DEFAULT">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The join type to be generated by implicit joins.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="renderOrderByRownumberForEmulatedPagination" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether an additional <code>ORDER BY rn</code> clause should be rendered on emulated paginated queries.
<p>
@ -953,6 +957,20 @@ Either &lt;input/&gt; or &lt;inputExpression/&gt; must be provided]]></jxb:javad
</restriction>
</simpleType>
<simpleType name="RenderImplicitJoinType">
<restriction base="string">
<!-- By default, render LEFT JOIN for nullable foreign keys, and INNER JOIN for non-nullable foreign keys -->
<enumeration value="DEFAULT"/>
<!-- Always render INNER JOIN -->
<enumeration value="INNER_JOIN"/>
<!-- Always render LEFT JOIN -->
<enumeration value="LEFT_JOIN"/>
</restriction>
</simpleType>
<simpleType name="RenderOptionalKeyword">
<restriction base="string">