[#585] Add support for DATE, TIME and INTERVAL arithmetic - Implementation done for HSQLDB, implementation attempts for Ingres, Postgres
This commit is contained in:
parent
26c7a3090a
commit
a0dacbcc0e
@ -82,10 +82,12 @@ class DateDiff extends AbstractFunction<Integer> {
|
||||
getDataType(), field("SQL_TSI_DAY"), date2, date1);
|
||||
|
||||
case H2:
|
||||
case HSQLDB:
|
||||
return function("datediff", getDataType(), literal("'day'"), date2, date1);
|
||||
|
||||
case CUBRID:
|
||||
case ORACLE:
|
||||
case POSTGRES:
|
||||
|
||||
// TODO [#585] This cast shouldn't be necessary
|
||||
return date1.sub(date2).cast(Integer.class);
|
||||
|
||||
@ -66,6 +66,7 @@ import static org.jooq.impl.Factory.function;
|
||||
import static org.jooq.impl.Factory.literal;
|
||||
import static org.jooq.impl.Factory.val;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -220,6 +221,9 @@ class Expression<T> extends AbstractFunction<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the expression to be rendered when the RHS is an interval type
|
||||
*/
|
||||
private final Field<T> getIntervalExpression(Configuration configuration) {
|
||||
SQLDialect dialect = configuration.getDialect();
|
||||
|
||||
@ -266,8 +270,7 @@ class Expression<T> extends AbstractFunction<T> {
|
||||
}
|
||||
}
|
||||
|
||||
case DB2:
|
||||
case HSQLDB: {
|
||||
case DB2: {
|
||||
if (rhs.get(0).getType() == YearToMonth.class) {
|
||||
YearToMonth interval = ((Param<YearToMonth>) rhs.get(0)).getValue();
|
||||
|
||||
@ -280,7 +283,6 @@ class Expression<T> extends AbstractFunction<T> {
|
||||
}
|
||||
else {
|
||||
DayToSecond interval = ((Param<DayToSecond>) rhs.get(0)).getValue();
|
||||
|
||||
if (operator == ADD) {
|
||||
return (Field) lhs.cast(Timestamp.class).add(new IntervalLiteral(val(interval.getTotalMicro()), "microseconds"));
|
||||
}
|
||||
@ -290,7 +292,8 @@ class Expression<T> extends AbstractFunction<T> {
|
||||
}
|
||||
}
|
||||
|
||||
case DERBY: {
|
||||
case DERBY:
|
||||
case HSQLDB: {
|
||||
if (rhs.get(0).getType() == YearToMonth.class) {
|
||||
YearToMonth interval = ((Param<YearToMonth>) rhs.get(0)).getValue();
|
||||
|
||||
@ -349,11 +352,15 @@ class Expression<T> extends AbstractFunction<T> {
|
||||
}
|
||||
}
|
||||
|
||||
case ORACLE:
|
||||
default:
|
||||
return new DefaultExpression();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the expression to be rendered when the RHS is a number type
|
||||
*/
|
||||
private final Field<T> getNumberExpression(Configuration configuration) {
|
||||
switch (configuration.getDialect()) {
|
||||
case ASE: {
|
||||
@ -396,6 +403,26 @@ class Expression<T> extends AbstractFunction<T> {
|
||||
}
|
||||
}
|
||||
|
||||
// That implementation seems a bit off...
|
||||
case INGRES: {
|
||||
if (operator == ADD) {
|
||||
return lhs.add(field("date('" + rhsAsNumber() + " days')", Object.class));
|
||||
}
|
||||
else {
|
||||
return lhs.sub(field("date('" + rhsAsNumber() + " days')", Object.class));
|
||||
}
|
||||
}
|
||||
|
||||
// Postgres can add / subtract days using +/- operators only to DATE
|
||||
case POSTGRES: {
|
||||
if (getType() == Date.class) {
|
||||
return new DefaultExpression();
|
||||
}
|
||||
else {
|
||||
return new Expression(operator, lhs.cast(Date.class), rhsAsNumber());
|
||||
}
|
||||
}
|
||||
|
||||
// These dialects can add / subtract days using +/- operators
|
||||
case H2:
|
||||
case ORACLE:
|
||||
|
||||
@ -4637,59 +4637,6 @@ public class Factory implements FactoryOperations {
|
||||
return new TimestampDiff(timestamp1, timestamp2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timestamp difference as a <code>INTERVAL DAY TO SECOND</code>
|
||||
* type
|
||||
* <p>
|
||||
* This translates into any dialect
|
||||
*
|
||||
* @see Field#sub(Field)
|
||||
*/
|
||||
@Support
|
||||
public static Field<DayToSecond> timeDiff(Time time1, Time time2) {
|
||||
return timeDiff(val(time1), val(time2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timestamp difference as a <code>INTERVAL DAY TO SECOND</code>
|
||||
* type
|
||||
* <p>
|
||||
* This translates into any dialect
|
||||
*
|
||||
* @see Field#sub(Field)
|
||||
*/
|
||||
@Support
|
||||
public static Field<DayToSecond> timeDiff(Field<Time> time1, Time time2) {
|
||||
return timeDiff(nullSafe(time1), val(time2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timestamp difference as a <code>INTERVAL DAY TO SECOND</code>
|
||||
* type
|
||||
* <p>
|
||||
* This translates into any dialect
|
||||
*
|
||||
* @see Field#sub(Field)
|
||||
*/
|
||||
@Support
|
||||
public static Field<DayToSecond> timeDiff(Time time1, Field<Time> time2) {
|
||||
return timeDiff(val(time1), nullSafe(time2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timestamp difference as a <code>INTERVAL DAY TO SECOND</code>
|
||||
* type
|
||||
* <p>
|
||||
* This translates into any dialect
|
||||
*
|
||||
* @see Field#sub(Field)
|
||||
*/
|
||||
@Support
|
||||
public static Field<DayToSecond> timeDiff(Field<Time> time1, Field<Time> time2) {
|
||||
// TODO [#585] This cast shouldn't be necessary
|
||||
return nullSafe(time1).sub(nullSafe(time2)).cast(DayToSecond.class);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// XXX other functions
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -93,6 +93,7 @@ class TimestampDiff extends AbstractFunction<DayToSecond> {
|
||||
SQLDataType.INTEGER, field("SQL_TSI_SECOND"), timestamp2, timestamp1).div(literal(86400.0));
|
||||
|
||||
case H2:
|
||||
case HSQLDB:
|
||||
return function("datediff", getDataType(), literal("'ms'"), timestamp2, timestamp1).div(literal(86400000.0));
|
||||
|
||||
// MySQL's datetime operations operate on a microsecond level
|
||||
@ -100,6 +101,7 @@ class TimestampDiff extends AbstractFunction<DayToSecond> {
|
||||
return function("timestampdiff", getDataType(), literal("microsecond"), timestamp2, timestamp1).div(new DayToSecond(1).getTotalMicro());
|
||||
|
||||
case ORACLE:
|
||||
case POSTGRES:
|
||||
|
||||
// TODO [#585] This cast shouldn't be necessary
|
||||
return timestamp1.sub(timestamp2).cast(DayToSecond.class);
|
||||
|
||||
@ -185,7 +185,7 @@ class Val<T> extends AbstractField<T> implements Param<T>, BindingProvider {
|
||||
// [#566] JDBC doesn't explicitly support interval data types. To be on
|
||||
// the safe side, always cast these types in those dialects that support
|
||||
// them
|
||||
else if (getDataType().isInterval()) {
|
||||
if (getDataType().isInterval()) {
|
||||
switch (context.getDialect()) {
|
||||
case ORACLE:
|
||||
case POSTGRES:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user