diff --git a/jOOQ/src/main/java/org/jooq/JoinType.java b/jOOQ/src/main/java/org/jooq/JoinType.java
index 83c6da6b16..d8ce734a51 100644
--- a/jOOQ/src/main/java/org/jooq/JoinType.java
+++ b/jOOQ/src/main/java/org/jooq/JoinType.java
@@ -76,7 +76,7 @@ public enum JoinType {
* INNER JOIN two tables.
*/
@Support
- JOIN("join", true),
+ JOIN("join", "inner join", "join", true),
/**
* CROSS JOIN two tables.
@@ -88,43 +88,43 @@ public enum JoinType {
* LEFT OUTER JOIN two tables.
*/
@Support
- LEFT_OUTER_JOIN("left outer join", true),
+ LEFT_OUTER_JOIN("left outer join", "left outer join", "left join", true),
/**
* RIGHT OUTER JOIN two tables.
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
- RIGHT_OUTER_JOIN("right outer join", true),
+ RIGHT_OUTER_JOIN("right outer join", "right outer join", "right join", true),
/**
* FULL OUTER JOIN two tables.
*/
@Support({ FIREBIRD, HSQLDB, POSTGRES })
- FULL_OUTER_JOIN("full outer join", true),
+ FULL_OUTER_JOIN("full outer join", "full outer join", "full join", true),
/**
* NATURAL INNER JOIN two tables.
*/
@Support
- NATURAL_JOIN("natural join", false),
+ NATURAL_JOIN("natural join", "natural inner join", "natural join", false),
/**
* NATURAL LEFT OUTER JOIN two tables.
*/
@Support
- NATURAL_LEFT_OUTER_JOIN("natural left outer join", false),
+ NATURAL_LEFT_OUTER_JOIN("natural left outer join", "natural left outer join", "natural left join", false),
/**
* NATURAL RIGHT OUTER JOIN two tables.
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
- NATURAL_RIGHT_OUTER_JOIN("natural right outer join", false),
+ NATURAL_RIGHT_OUTER_JOIN("natural right outer join", "natural right outer join", "natural right join", false),
/**
* NATURAL FULL OUTER JOIN two tables.
*/
@Support({ FIREBIRD, HSQLDB, POSTGRES })
- NATURAL_FULL_OUTER_JOIN("natural full outer join", false),
+ NATURAL_FULL_OUTER_JOIN("natural full outer join", "natural full outer join", "natural full join", false),
/**
* CROSS APPLY two tables.
@@ -158,22 +158,34 @@ public enum JoinType {
;
- private final String sql;
- private final Keyword keyword;
+ private final String defaultSql;
+ private final Keyword defaultKeyword;
+ private final Keyword includingOptionalKeywords;
+ private final Keyword excludingOptionalKeywords;
private final boolean qualified;
private JoinType(String sql, boolean qualified) {
- this.sql = sql;
- this.keyword = DSL.keyword(sql);
+ this(sql, sql, sql, qualified);
+ }
+
+ private JoinType(String defaultSql, String includingOptionalKeywords, String excludingOptionalKeywords, boolean qualified) {
+ this.defaultSql = defaultSql;
+ this.includingOptionalKeywords = DSL.keyword(includingOptionalKeywords);
+ this.excludingOptionalKeywords = DSL.keyword(excludingOptionalKeywords);
+ this.defaultKeyword = DSL.keyword(defaultSql);
this.qualified = qualified;
}
public final String toSQL() {
- return sql;
+ return defaultSql;
}
public final Keyword toKeyword() {
- return keyword;
+ return defaultKeyword;
+ }
+
+ public final Keyword toKeyword(boolean includeOptionalKeywords) {
+ return includeOptionalKeywords ? includingOptionalKeywords : excludingOptionalKeywords;
}
/**
diff --git a/jOOQ/src/main/java/org/jooq/conf/RenderOptionalKeyword.java b/jOOQ/src/main/java/org/jooq/conf/RenderOptionalKeyword.java
new file mode 100644
index 0000000000..19e9d2867a
--- /dev/null
+++ b/jOOQ/src/main/java/org/jooq/conf/RenderOptionalKeyword.java
@@ -0,0 +1,40 @@
+
+package org.jooq.conf;
+
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ *
Java class for RenderOptionalKeyword. + * + *
The following schema fragment specifies the expected content contained within this class. + *
+ *
+ * <simpleType name="RenderOptionalKeyword">
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ * <enumeration value="OFF"/>
+ * <enumeration value="ON"/>
+ * <enumeration value="DEFAULT"/>
+ * </restriction>
+ * </simpleType>
+ *
+ *
+ */
+@XmlType(name = "RenderOptionalKeyword")
+@XmlEnum
+public enum RenderOptionalKeyword {
+
+ OFF,
+ ON,
+ DEFAULT;
+
+ public String value() {
+ return name();
+ }
+
+ public static RenderOptionalKeyword fromValue(String v) {
+ return valueOf(v);
+ }
+
+}
diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java
index 0858df2b63..4bc6103a24 100644
--- a/jOOQ/src/main/java/org/jooq/conf/Settings.java
+++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java
@@ -65,6 +65,12 @@ public class Settings
@XmlElement(defaultValue = "false")
protected Boolean renderFormatted = false;
protected RenderFormatting renderFormatting;
+ @XmlElement(defaultValue = "DEFAULT")
+ @XmlSchemaType(name = "string")
+ protected RenderOptionalKeyword renderOptionalInnerKeyword = RenderOptionalKeyword.DEFAULT;
+ @XmlElement(defaultValue = "DEFAULT")
+ @XmlSchemaType(name = "string")
+ protected RenderOptionalKeyword renderOptionalOuterKeyword = RenderOptionalKeyword.DEFAULT;
@XmlElement(defaultValue = "false")
protected Boolean renderScalarSubqueriesForStoredFunctions = false;
@XmlElement(defaultValue = "true")
@@ -473,6 +479,38 @@ public class Settings
this.renderFormatting = value;
}
+ /**
+ * Whether to render the optional INNER keyword in INNER JOIN, if it is optional in the output dialect.
+ *
+ */
+ public RenderOptionalKeyword getRenderOptionalInnerKeyword() {
+ return renderOptionalInnerKeyword;
+ }
+
+ /**
+ * Whether to render the optional INNER keyword in INNER JOIN, if it is optional in the output dialect.
+ *
+ */
+ public void setRenderOptionalInnerKeyword(RenderOptionalKeyword value) {
+ this.renderOptionalInnerKeyword = value;
+ }
+
+ /**
+ * Whether to render the optional OUTER keyword in OUTER JOIN, if it is optional in the output dialect.
+ *
+ */
+ public RenderOptionalKeyword getRenderOptionalOuterKeyword() {
+ return renderOptionalOuterKeyword;
+ }
+
+ /**
+ * Whether to render the optional OUTER keyword in OUTER JOIN, if it is optional in the output dialect.
+ *
+ */
+ public void setRenderOptionalOuterKeyword(RenderOptionalKeyword value) {
+ this.renderOptionalOuterKeyword = value;
+ }
+
/**
* Whether stored function calls should be wrapped in scalar subqueries.
*
@@ -1765,6 +1803,24 @@ public class Settings
return this;
}
+ /**
+ * Whether to render the optional INNER keyword in INNER JOIN, if it is optional in the output dialect.
+ *
+ */
+ public Settings withRenderOptionalInnerKeyword(RenderOptionalKeyword value) {
+ setRenderOptionalInnerKeyword(value);
+ return this;
+ }
+
+ /**
+ * Whether to render the optional OUTER keyword in OUTER JOIN, if it is optional in the output dialect.
+ *
+ */
+ public Settings withRenderOptionalOuterKeyword(RenderOptionalKeyword value) {
+ setRenderOptionalOuterKeyword(value);
+ return this;
+ }
+
public Settings withRenderScalarSubqueriesForStoredFunctions(Boolean value) {
setRenderScalarSubqueriesForStoredFunctions(value);
return this;
@@ -2208,6 +2264,8 @@ public class Settings
builder.append("renderLocale", renderLocale);
builder.append("renderFormatted", renderFormatted);
builder.append("renderFormatting", renderFormatting);
+ builder.append("renderOptionalInnerKeyword", renderOptionalInnerKeyword);
+ builder.append("renderOptionalOuterKeyword", renderOptionalOuterKeyword);
builder.append("renderScalarSubqueriesForStoredFunctions", renderScalarSubqueriesForStoredFunctions);
builder.append("renderOrderByRownumberForEmulatedPagination", renderOrderByRownumberForEmulatedPagination);
builder.append("renderOutputForSQLServerReturningClause", renderOutputForSQLServerReturningClause);
@@ -2392,6 +2450,24 @@ public class Settings
return false;
}
}
+ if (renderOptionalInnerKeyword == null) {
+ if (other.renderOptionalInnerKeyword!= null) {
+ return false;
+ }
+ } else {
+ if (!renderOptionalInnerKeyword.equals(other.renderOptionalInnerKeyword)) {
+ return false;
+ }
+ }
+ if (renderOptionalOuterKeyword == null) {
+ if (other.renderOptionalOuterKeyword!= null) {
+ return false;
+ }
+ } else {
+ if (!renderOptionalOuterKeyword.equals(other.renderOptionalOuterKeyword)) {
+ return false;
+ }
+ }
if (renderScalarSubqueriesForStoredFunctions == null) {
if (other.renderScalarSubqueriesForStoredFunctions!= null) {
return false;
@@ -2906,6 +2982,8 @@ public class Settings
result = ((prime*result)+((renderLocale == null)? 0 :renderLocale.hashCode()));
result = ((prime*result)+((renderFormatted == null)? 0 :renderFormatted.hashCode()));
result = ((prime*result)+((renderFormatting == null)? 0 :renderFormatting.hashCode()));
+ 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)+((renderOrderByRownumberForEmulatedPagination == null)? 0 :renderOrderByRownumberForEmulatedPagination.hashCode()));
result = ((prime*result)+((renderOutputForSQLServerReturningClause == null)? 0 :renderOutputForSQLServerReturningClause.hashCode()));
diff --git a/jOOQ/src/main/java/org/jooq/impl/JoinTable.java b/jOOQ/src/main/java/org/jooq/impl/JoinTable.java
index c2b220dc4b..386c4947fe 100755
--- a/jOOQ/src/main/java/org/jooq/impl/JoinTable.java
+++ b/jOOQ/src/main/java/org/jooq/impl/JoinTable.java
@@ -90,7 +90,7 @@ import static org.jooq.impl.DSL.exists;
import static org.jooq.impl.DSL.notExists;
import static org.jooq.impl.DSL.selectOne;
import static org.jooq.impl.Keywords.K_CROSS_JOIN_LATERAL;
-import static org.jooq.impl.Keywords.K_INNER_JOIN;
+import static org.jooq.impl.Keywords.K_LEFT_JOIN_LATERAL;
import static org.jooq.impl.Keywords.K_LEFT_OUTER_JOIN_LATERAL;
import static org.jooq.impl.Keywords.K_ON;
import static org.jooq.impl.Keywords.K_PARTITION_BY;
@@ -126,6 +126,7 @@ import org.jooq.TableOnConditionStep;
import org.jooq.TableOptionalOnStep;
import org.jooq.TableOuterJoinStep;
import org.jooq.TablePartitionByStep;
+import org.jooq.conf.RenderOptionalKeyword;
import org.jooq.exception.DataAccessException;
/**
@@ -205,19 +206,7 @@ implements
public final void accept(Context> ctx) {
JoinType translatedType = translateType(ctx);
Clause translatedClause = translateClause(translatedType);
-
- Keyword keyword = translatedType.toKeyword();
-
- if (translatedType == CROSS_APPLY && EMULATE_APPLY.contains(ctx.family()))
- keyword = K_CROSS_JOIN_LATERAL;
- else if (translatedType == OUTER_APPLY && EMULATE_APPLY.contains(ctx.family()))
- keyword = K_LEFT_OUTER_JOIN_LATERAL;
-
-
-
-
-
-
+ Keyword keyword = translateKeyword(ctx, translatedType);
toSQLTable(ctx, lhs);
@@ -308,6 +297,63 @@ implements
.formatIndentEnd();
}
+ private final Keyword translateKeyword(Context> ctx, JoinType translatedType) {
+ Keyword keyword;
+
+ switch (translatedType) {
+ case JOIN:
+ case NATURAL_JOIN:
+ if (ctx.settings().getRenderOptionalInnerKeyword() == RenderOptionalKeyword.ON)
+ keyword = translatedType.toKeyword(true);
+
+
+
+
+
+
+
+ else
+ keyword = translatedType.toKeyword();
+
+ break;
+
+ case LEFT_OUTER_JOIN:
+ case NATURAL_LEFT_OUTER_JOIN:
+ case RIGHT_OUTER_JOIN:
+ case NATURAL_RIGHT_OUTER_JOIN:
+ case FULL_OUTER_JOIN:
+ case NATURAL_FULL_OUTER_JOIN:
+ if (ctx.settings().getRenderOptionalOuterKeyword() == RenderOptionalKeyword.OFF)
+ keyword = translatedType.toKeyword(false);
+
+
+
+
+
+
+
+ else
+ keyword = translatedType.toKeyword();
+
+ break;
+
+ default:
+ keyword = translatedType.toKeyword();
+ break;
+ }
+
+ if (translatedType == CROSS_APPLY && EMULATE_APPLY.contains(ctx.family()))
+ keyword = K_CROSS_JOIN_LATERAL;
+ else if (translatedType == OUTER_APPLY && EMULATE_APPLY.contains(ctx.family()))
+ if (ctx.settings().getRenderOptionalOuterKeyword() == RenderOptionalKeyword.OFF)
+ keyword = K_LEFT_JOIN_LATERAL;
+ else
+ keyword = K_LEFT_OUTER_JOIN_LATERAL;
+
+
+ return keyword;
+ }
+
private void toSQLTable(Context> ctx, Table> table) {
// [#671] Some databases formally require nested JOINS on the right hand
diff --git a/jOOQ/src/main/java/org/jooq/impl/Keywords.java b/jOOQ/src/main/java/org/jooq/impl/Keywords.java
index d9fb76d736..bf1e260b13 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Keywords.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Keywords.java
@@ -205,6 +205,7 @@ final class Keywords {
static final Keyword K_LATERAL = keyword("lateral");
static final Keyword K_LEADING = keyword("leading");
static final Keyword K_LEAVE = keyword("leave");
+ static final Keyword K_LEFT_JOIN_LATERAL = keyword("left join lateral");
static final Keyword K_LEFT_OUTER_JOIN_LATERAL = keyword("left outer join lateral");
static final Keyword K_LIKE = keyword("like");
static final Keyword K_LIKE_REGEX = keyword("like_regex");
diff --git a/jOOQ/src/main/resources/xsd/jooq-runtime-3.13.0.xsd b/jOOQ/src/main/resources/xsd/jooq-runtime-3.13.0.xsd
index 14d906308a..482af7b32d 100644
--- a/jOOQ/src/main/resources/xsd/jooq-runtime-3.13.0.xsd
+++ b/jOOQ/src/main/resources/xsd/jooq-runtime-3.13.0.xsd
@@ -110,6 +110,14 @@ providing a name to parameters, resulting in :1 or @1
INNER JOIN, if it is optional in the output dialect.]]>OUTER JOIN, if it is optional in the output dialect.]]>