diff --git a/jOOQ/src/main/java/org/jooq/SQLDialect.java b/jOOQ/src/main/java/org/jooq/SQLDialect.java index c227572aa9..4cc5400d4b 100644 --- a/jOOQ/src/main/java/org/jooq/SQLDialect.java +++ b/jOOQ/src/main/java/org/jooq/SQLDialect.java @@ -135,6 +135,16 @@ public enum SQLDialect { */ DB2("DB2", true), + /** + * The IBM DB2 9.x SQL dialect. + */ + DB2_9("DB2", true, DB2), + + /** + * The IBM DB2 10.x SQL dialect. + */ + DB2_10("DB2", true, DB2), + /** * The Ingres dialect family. */ diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java index ace78b4197..201f811573 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java @@ -227,7 +227,7 @@ public abstract class AbstractRoutine extends AbstractQueryPart implements Ro return executeCallableStatement(); } else { - switch (configuration.dialect()) { + switch (configuration.dialect().family()) { // [#852] Some RDBMS don't allow for using JDBC procedure escape // syntax for functions. Select functions from DUAL instead diff --git a/jOOQ/src/main/java/org/jooq/impl/CompareCondition.java b/jOOQ/src/main/java/org/jooq/impl/CompareCondition.java index 50dd022320..f56ed3cca9 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CompareCondition.java +++ b/jOOQ/src/main/java/org/jooq/impl/CompareCondition.java @@ -92,7 +92,7 @@ class CompareCondition extends AbstractCondition { @Override public final void toSQL(RenderContext context) { - SQLDialect dialect = context.configuration().dialect(); + SQLDialect family = context.configuration().dialect().family(); Field lhs = field1; Field rhs = field2; Comparator op = comparator; @@ -102,7 +102,7 @@ class CompareCondition extends AbstractCondition { // [#293] TODO: This could apply to other operators, too if ((op == LIKE || op == NOT_LIKE) && field1.getType() != String.class - && asList(ASE, DERBY, POSTGRES).contains(dialect)) { + && asList(ASE, DERBY, POSTGRES).contains(family)) { lhs = lhs.cast(String.class); } @@ -110,7 +110,7 @@ class CompareCondition extends AbstractCondition { // [#1423] Only Postgres knows a true ILIKE operator. Other dialects // need to simulate this as LOWER(lhs) LIKE LOWER(rhs) else if ((op == LIKE_IGNORE_CASE || op == NOT_LIKE_IGNORE_CASE) - && POSTGRES != dialect) { + && POSTGRES != family) { lhs = lhs.lower(); rhs = rhs.lower(); @@ -126,7 +126,7 @@ class CompareCondition extends AbstractCondition { boolean castRhs = false; /* [pro] */ - if (dialect == DB2 && rhs instanceof Concat) + if (family == DB2 && rhs instanceof Concat) castRhs = true; /* [/pro] */ diff --git a/jOOQ/src/main/java/org/jooq/impl/Expression.java b/jOOQ/src/main/java/org/jooq/impl/Expression.java index 8ca99bd61a..c24c867966 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Expression.java +++ b/jOOQ/src/main/java/org/jooq/impl/Expression.java @@ -171,10 +171,10 @@ class Expression extends AbstractFunction { } // Many dialects don't support shifts. Use multiplication/division instead - else if (SHL == operator && asList(ASE, DB2, H2, HSQLDB, INGRES, ORACLE, SQLSERVER, SYBASE).contains(family.family())) { + else if (SHL == operator && asList(ASE, DB2, H2, HSQLDB, INGRES, ORACLE, SQLSERVER, SYBASE).contains(family)) { return lhs.mul(DSL.power(two(), rhsAsNumber())); } - else if (SHR == operator && asList(ASE, DB2, H2, HSQLDB, INGRES, ORACLE, SQLSERVER, SYBASE).contains(family.family())) { + else if (SHR == operator && asList(ASE, DB2, H2, HSQLDB, INGRES, ORACLE, SQLSERVER, SYBASE).contains(family)) { return lhs.div(DSL.power(two(), rhsAsNumber())); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Function.java b/jOOQ/src/main/java/org/jooq/impl/Function.java index 41aef969d9..9451b36a4a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Function.java +++ b/jOOQ/src/main/java/org/jooq/impl/Function.java @@ -214,7 +214,7 @@ class Function extends AbstractField implements toSQLStringAgg(context); } /* [pro] */ - else if (term == LIST_AGG && asList(DB2).contains(context.configuration().dialect())) { + else if (term == LIST_AGG && asList(DB2).contains(context.configuration().dialect().family())) { toSQLXMLAGG(context); } /* [/pro] */ @@ -433,7 +433,7 @@ class Function extends AbstractField implements if (ignoreNulls) { /* [pro] */ - if (context.configuration().dialect() == SQLDialect.DB2) { + if (context.configuration().dialect().family() == SQLDialect.DB2) { context.sql(", 'IGNORE NULLS'"); } else @@ -444,7 +444,7 @@ class Function extends AbstractField implements } else if (respectNulls) { /* [pro] */ - if (context.configuration().dialect() == SQLDialect.DB2) { + if (context.configuration().dialect().family() == SQLDialect.DB2) { context.sql(", 'RESPECT NULLS'"); } else diff --git a/jOOQ/src/main/java/org/jooq/impl/Limit.java b/jOOQ/src/main/java/org/jooq/impl/Limit.java index 57de9f1559..8943d90335 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Limit.java +++ b/jOOQ/src/main/java/org/jooq/impl/Limit.java @@ -176,7 +176,9 @@ class Limit extends AbstractQueryPart { // Only "TOP" support provided by the following dialects. // "OFFSET" support is simulated with nested selects // ----------------------------------------------------------------- - case DB2: { + case DB2: + case DB2_9: + case DB2_10: { if (offset != null) { throw new DataAccessException("DB2 does not support offsets in FETCH FIRST ROWS ONLY clause"); } @@ -294,7 +296,9 @@ class Limit extends AbstractQueryPart { // These dialects don't allow bind variables in their TOP clauses // -------------------------------------------------------------- - case DB2: + case DB2: + case DB2_9: + case DB2_10: case SQLSERVER2008: { // TOP clauses without bind variables diff --git a/jOOQ/src/main/java/org/jooq/impl/Neg.java b/jOOQ/src/main/java/org/jooq/impl/Neg.java index 8a4ec2ec7a..65b34bcafb 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Neg.java +++ b/jOOQ/src/main/java/org/jooq/impl/Neg.java @@ -76,21 +76,21 @@ class Neg extends AbstractField { @Override public final void toSQL(RenderContext context) { - SQLDialect dialect = context.configuration().dialect(); + SQLDialect family = context.configuration().dialect().family(); - if (operator == BIT_NOT && asList(H2, HSQLDB, INGRES, ORACLE).contains(dialect.family())) { + if (operator == BIT_NOT && asList(H2, HSQLDB, INGRES, ORACLE).contains(family)) { context.sql("(0 -") .visit(field) .sql(" - 1)"); } /* [pro] */ - else if (operator == BIT_NOT && dialect == DB2) { + else if (operator == BIT_NOT && family == DB2) { context.keyword("bitnot(") .visit(field) .sql(")"); } /* [/pro] */ - else if (operator == BIT_NOT && dialect == FIREBIRD) { + else if (operator == BIT_NOT && family == FIREBIRD) { context.keyword("bin_not(") .visit(field) .sql(")"); diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java index f00a874dfb..2fcada850e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java @@ -224,7 +224,9 @@ class SelectQueryImpl extends AbstractSelect implements Sel break; // With DB2, there are two possibilities - case DB2: { + case DB2: + case DB2_9: + case DB2_10: { // DB2 natively supports a "FIRST ROWS" clause, without // offset and without bind values diff --git a/jOOQ/src/main/java/org/jooq/impl/TruncateImpl.java b/jOOQ/src/main/java/org/jooq/impl/TruncateImpl.java index 7ec8ff9fbe..7d7cc9ca09 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TruncateImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/TruncateImpl.java @@ -124,7 +124,7 @@ class TruncateImpl extends AbstractQuery implements .visit(table); /* [pro] */ - if (context.configuration().dialect() == SQLDialect.DB2) { + if (context.configuration().dialect().family() == SQLDialect.DB2) { context.sql(" ").keyword("immediate"); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Val.java b/jOOQ/src/main/java/org/jooq/impl/Val.java index b65bf8d29a..39976a318c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Val.java +++ b/jOOQ/src/main/java/org/jooq/impl/Val.java @@ -149,7 +149,7 @@ class Val extends AbstractParam { // Generated enums should not be cast... if (!(value instanceof EnumType)) { - switch (context.configuration().dialect()) { + switch (context.configuration().dialect().family()) { // These dialects can hardly detect the type of a bound constant. /* [pro] */ @@ -200,17 +200,17 @@ class Val extends AbstractParam { private final void toSQLCast(RenderContext context) { DataType dataType = getDataType(context.configuration()); DataType type = dataType.getSQLDataType(); - SQLDialect dialect = context.configuration().dialect(); + SQLDialect family = context.configuration().dialect().family(); // [#822] Some RDBMS need precision / scale information on BigDecimals - if (value != null && getType() == BigDecimal.class && asList(CUBRID, DB2, DERBY, FIREBIRD, HSQLDB).contains(dialect)) { + if (value != null && getType() == BigDecimal.class && asList(CUBRID, DB2, DERBY, FIREBIRD, HSQLDB).contains(family)) { // Add precision / scale on BigDecimals int scale = ((BigDecimal) value).scale(); int precision = scale + ((BigDecimal) value).precision(); // Firebird's max precision is 18 - if (dialect == FIREBIRD) { + if (family == FIREBIRD) { precision = Math.min(precision, 18); } @@ -222,19 +222,19 @@ class Val extends AbstractParam { // If the bind value is set, it can be used to derive the cast type if (value != null) { - toSQLCast(context, DefaultDataType.getDataType(dialect, value.getClass()), 0, 0, 0); + toSQLCast(context, DefaultDataType.getDataType(family, value.getClass()), 0, 0, 0); } // [#632] [#722] Current integration tests show that Ingres and // Sybase can do without casting in most cases. - else if (asList(INGRES, SYBASE).contains(dialect)) { + else if (asList(INGRES, SYBASE).contains(family)) { context.sql(getBindVariable(context)); } // Derby and DB2 must have a type associated with NULL. Use VARCHAR // as a workaround. That's probably not correct in all cases, though else { - toSQLCast(context, DefaultDataType.getDataType(dialect, String.class), 0, 0, 0); + toSQLCast(context, DefaultDataType.getDataType(family, String.class), 0, 0, 0); } } @@ -242,13 +242,13 @@ class Val extends AbstractParam { // above case where the type is OTHER // [#1125] Also with temporal data types, casting is needed some times // [#1130] TODO type can be null for ARRAY types, etc. - else if (dialect == POSTGRES && (type == null || !type.isTemporal())) { + else if (family == POSTGRES && (type == null || !type.isTemporal())) { toSQL(context, value, getType()); } // [#1727] VARCHAR types should be cast to their actual lengths in some // dialects - else if ((type == SQLDataType.VARCHAR || type == SQLDataType.CHAR) && asList(FIREBIRD).contains(dialect)) { + else if ((type == SQLDataType.VARCHAR || type == SQLDataType.CHAR) && asList(FIREBIRD).contains(family)) { toSQLCast(context, dataType, getValueLength(), 0, 0); }