diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/DataTypeTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/DataTypeTests.java index eb5dc54720..d725cc9b01 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/DataTypeTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/DataTypeTests.java @@ -48,6 +48,8 @@ import static org.jooq.SQLDialect.DERBY; import static org.jooq.SQLDialect.H2; import static org.jooq.SQLDialect.MYSQL; import static org.jooq.SQLDialect.SQLITE; +import static org.jooq.SQLDialect.SQLSERVER; +import static org.jooq.SQLDialect.SYBASE; import static org.jooq.impl.Factory.cast; import static org.jooq.impl.Factory.castNull; import static org.jooq.impl.Factory.dateDiff; @@ -533,6 +535,16 @@ extends BaseTest { final Field getFunction0(Configuration configuration) { switch (configuration.getDialect()) { case ASE: + case SQLSERVER: + case SYBASE: return function("datediff", getDataType(), literal("day"), date2, date1); case MYSQL: diff --git a/jOOQ/src/main/java/org/jooq/impl/Expression.java b/jOOQ/src/main/java/org/jooq/impl/Expression.java index f64dca8c2f..6adfc325d3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Expression.java +++ b/jOOQ/src/main/java/org/jooq/impl/Expression.java @@ -228,7 +228,9 @@ class Expression extends AbstractFunction { SQLDialect dialect = configuration.getDialect(); switch (dialect) { - case ASE: { + case ASE: + case SYBASE: + case SQLSERVER: { if (rhs.get(0).getType() == YearToMonth.class) { YearToMonth interval = ((Param) rhs.get(0)).getValue(); @@ -240,8 +242,9 @@ class Expression extends AbstractFunction { } } else { + // SQL Server needs this cast. + Field result = lhs.cast(Timestamp.class); DayToSecond interval = ((Param) rhs.get(0)).getValue(); - Field result = lhs; if (operator == ADD) { if (interval.getNano() != 0) { @@ -266,7 +269,7 @@ class Expression extends AbstractFunction { } } - return result; + return (Field) result; } } @@ -363,7 +366,9 @@ class Expression extends AbstractFunction { */ private final Field getNumberExpression(Configuration configuration) { switch (configuration.getDialect()) { - case ASE: { + case ASE: + case SQLSERVER: + case SYBASE: { if (operator == ADD) { return function("dateadd", getDataType(), literal("day"), rhsAsNumber(), lhs); } @@ -403,7 +408,7 @@ class Expression extends AbstractFunction { } } - // That implementation seems a bit off... + // Ingres is not working yet case INGRES: { if (operator == ADD) { return lhs.add(field("date('" + rhsAsNumber() + " days')", Object.class)); @@ -423,11 +428,17 @@ class Expression extends AbstractFunction { } } + case SQLITE: + if (operator == ADD) { + return function("datetime", getDataType(), lhs, literal("+" + rhsAsNumber() + " day")); + } + else { + return function("datetime", getDataType(), lhs, literal("-" + rhsAsNumber() + " day")); + } + // These dialects can add / subtract days using +/- operators case H2: case ORACLE: - case SYBASE: - case SQLSERVER: default: return new DefaultExpression(); } diff --git a/jOOQ/src/main/java/org/jooq/impl/TimestampDiff.java b/jOOQ/src/main/java/org/jooq/impl/TimestampDiff.java index 0fedc3b40e..53985c7da2 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TimestampDiff.java +++ b/jOOQ/src/main/java/org/jooq/impl/TimestampDiff.java @@ -86,19 +86,23 @@ class TimestampDiff extends AbstractFunction { return (Field) function("days", SQLDataType.INTEGER, timestamp1).sub( function("days", SQLDataType.INTEGER, timestamp2)).add( function("midnight_seconds", SQLDataType.INTEGER, timestamp1).sub( - function("midnight_seconds", SQLDataType.INTEGER, timestamp2)).div(literal(86400.0))); + function("midnight_seconds", SQLDataType.INTEGER, timestamp2)).div(literal(new DayToSecond(1).getTotalSeconds()))); case DERBY: return (Field) new FnPrefixFunction("timestampdiff", - SQLDataType.INTEGER, field("SQL_TSI_SECOND"), timestamp2, timestamp1).div(literal(86400.0)); + SQLDataType.INTEGER, field("SQL_TSI_SECOND"), timestamp2, timestamp1).div(literal(new DayToSecond(1).getTotalSeconds())); case H2: case HSQLDB: - return function("datediff", getDataType(), literal("'ms'"), timestamp2, timestamp1).div(literal(86400000.0)); + return function("datediff", getDataType(), literal("'ms'"), timestamp2, timestamp1).div(literal(new DayToSecond(1).getTotalMilli())); // MySQL's datetime operations operate on a microsecond level case MYSQL: - return function("timestampdiff", getDataType(), literal("microsecond"), timestamp2, timestamp1).div(new DayToSecond(1).getTotalMicro()); + return function("timestampdiff", getDataType(), literal("microsecond"), timestamp2, timestamp1).div(literal(new DayToSecond(1).getTotalMicro())); + + case SQLSERVER: + case SYBASE: + return function("datediff", getDataType(), literal("ms"), timestamp2, timestamp1).div(literal(new DayToSecond(1).getTotalMilli())); case ORACLE: case POSTGRES: diff --git a/jOOQ/src/main/java/org/jooq/types/Interval.java b/jOOQ/src/main/java/org/jooq/types/Interval.java index c85c66642d..66299f6a39 100644 --- a/jOOQ/src/main/java/org/jooq/types/Interval.java +++ b/jOOQ/src/main/java/org/jooq/types/Interval.java @@ -37,6 +37,9 @@ package org.jooq.types; import java.io.Serializable; +import org.jooq.Field; +import org.jooq.SQLDialect; + /** * A substitute for JDBC's missing java.sql.Interval data type. *

@@ -97,7 +100,17 @@ import java.io.Serializable; * * *

- * Interval implementations can be expected to also also extend {@link Number} + * Interval implementations can be expected to also also extend {@link Number}. + * True SQL standard INTERVAL data types have been observed to be supported by + * any of these dialects: + *

    + *
  • {@link SQLDialect#INGRES}
  • + *
  • {@link SQLDialect#ORACLE}
  • + *
  • {@link SQLDialect#POSTGRES}
  • + *
+ *

+ * In other dialects, jOOQ allows for using them for date time arithmetic. See + * {@link Field#add(Field)}, {@link Field#sub(Field)} * * @author Lukas Eder */