diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/DataTypeTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/DataTypeTests.java index 291de3350a..f85eb8d0cd 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/DataTypeTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/DataTypeTests.java @@ -44,6 +44,8 @@ import static junit.framework.Assert.fail; import static org.jooq.SQLDialect.SQLITE; import static org.jooq.impl.Factory.cast; import static org.jooq.impl.Factory.castNull; +import static org.jooq.impl.Factory.dateDiff; +import static org.jooq.impl.Factory.timestampDiff; import static org.jooq.impl.Factory.val; import static org.jooq.tools.unsigned.Unsigned.ubyte; import static org.jooq.tools.unsigned.Unsigned.uint; @@ -1191,6 +1193,8 @@ extends BaseTest extends NamedTypeProviderQueryPart, AliasProvider - *
    - *
  • If this is a numeric field, then the value is added arithmetically
  • - *
  • If this is a date time field, then [value] days are added to this date
  • - *
+ * + * @see #add(Field) */ @Support Field add(Number value); /** - * An arithmetic expression adding this to value + * An arithmetic expression adding an interval to this. + * + * @see #add(Field) */ @Support - Field add(Field value); + Field add(Interval value); + + /** + * An arithmetic expression to add value to this. + *

+ * The behaviour of this operation is as follows: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Operand 1Operand 2Result Type
NumericNumericNumeric
Date / TimeNumericDate / Time
Date / TimeIntervalDate / Time
IntervalIntervalInterval
+ */ + @Support + Field add(Field value); /** * An arithmetic expression subtracting value from this. - *

- *

    - *
  • If this is a numeric field, then the value is subtracted - * arithmetically
  • - *
  • If this is a date time field, then [value] days are subtracted to - * this date
  • - *
+ * + * @see #sub(Field) */ @Support Field sub(Number value); /** - * An arithmetic expression subtracting value from this + * An arithmetic expression subtracting an interval from this. + * + * @see #sub(Field) */ @Support - Field sub(Field value); + Field sub(Interval value); + + /** + * An arithmetic expression subtracting value from this. + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Operand 1Operand 2Result Type
NumericNumericNumeric
Date / TimeNumericDate / Time
Date / TimeIntervalDate / Time
IntervalIntervalInterval
+ *

+ * In order to subtract one date time field from another, use any of these + * methods: + *

    + *
  • {@link Factory#dateDiff(Field, Field)}
  • + *
  • {@link Factory#timeDiff(Field, Field)}
  • + *
  • {@link Factory#timestampDiff(Field, Field)}
  • + *
+ */ + @Support + Field sub(Field value); /** * An arithmetic expression multiplying this with value + *

+ *

    + *
  • If this is a numeric field, then the result is a number of the same + * type as this field.
  • + *
  • If this is an INTERVAL field, then the result is also an + * INTERVAL field (see {@link Interval})
  • + *
*/ @Support Field mul(Number value); /** * An arithmetic expression multiplying this with value + *

+ *

    + *
  • If this is a numeric field, then the result is a number of the same + * type as this field.
  • + *
  • If this is an INTERVAL field, then the result is also an + * INTERVAL field (see {@link Interval})
  • + *
*/ @Support Field mul(Field value); /** * An arithmetic expression dividing this by value + *

+ *

    + *
  • If this is a numeric field, then the result is a number of the same + * type as this field.
  • + *
  • If this is an INTERVAL field, then the result is also an + * INTERVAL field (see {@link Interval})
  • + *
*/ @Support Field div(Number value); /** * An arithmetic expression dividing this by value + *

+ *

    + *
  • If this is a numeric field, then the result is a number of the same + * type as this field.
  • + *
  • If this is an INTERVAL field, then the result is also an + * INTERVAL field (see {@link Interval})
  • + *
*/ @Support Field div(Field value); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java index b457ace956..4d5ba2b556 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java @@ -71,6 +71,7 @@ import org.jooq.SortOrder; import org.jooq.WindowIgnoreNullsStep; import org.jooq.WindowPartitionByStep; import org.jooq.tools.Convert; +import org.jooq.types.Interval; abstract class AbstractField extends AbstractNamedTypeProviderQueryPart implements Field { @@ -225,12 +226,17 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im } } + @Override + public final Field add(Interval value) { + return add(val(value)); + } + /** * This default implementation is known to be overridden by * {@link Expression} to generate neater expressions */ @Override - public Field add(Field value) { + public Field add(Field value) { return new Expression(ADD, this, nullSafe(value)); } @@ -249,7 +255,12 @@ abstract class AbstractField extends AbstractNamedTypeProviderQueryPart im } @Override - public final Field sub(Field value) { + public final Field sub(Interval value) { + return sub(val(value)); + } + + @Override + public final Field sub(Field value) { return new Expression(SUBTRACT, this, nullSafe(value)); } diff --git a/jOOQ/src/main/java/org/jooq/impl/CustomField.java b/jOOQ/src/main/java/org/jooq/impl/CustomField.java index 2c2fa19580..ce30831572 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CustomField.java +++ b/jOOQ/src/main/java/org/jooq/impl/CustomField.java @@ -136,7 +136,7 @@ public abstract class CustomField extends AbstractField { } @Override - public final Field add(Field value) { + public final Field add(Field value) { return super.add(value); } diff --git a/jOOQ/src/main/java/org/jooq/impl/Expression.java b/jOOQ/src/main/java/org/jooq/impl/Expression.java index 5b3bcbba8e..8a6f344dd5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Expression.java +++ b/jOOQ/src/main/java/org/jooq/impl/Expression.java @@ -92,7 +92,7 @@ class Expression extends AbstractFunction { } @Override - public final Field add(Field value) { + public final Field add(Field value) { if (operator == ExpressionOperator.ADD) { rhs.add(value); return this; diff --git a/jOOQ/src/main/java/org/jooq/impl/Factory.java b/jOOQ/src/main/java/org/jooq/impl/Factory.java index 580c5f53e7..c1ab37a443 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Factory.java +++ b/jOOQ/src/main/java/org/jooq/impl/Factory.java @@ -131,6 +131,7 @@ import org.jooq.exception.DataAccessException; import org.jooq.exception.InvalidResultException; import org.jooq.exception.SQLDialectNotSupportedException; import org.jooq.tools.JooqLogger; +import org.jooq.types.DayToSecond; /** * A factory providing implementations to the org.jooq interfaces @@ -4450,7 +4451,7 @@ public class Factory implements FactoryOperations { } // ------------------------------------------------------------------------- - // XXX Pseudo fields and date time functions + // XXX date time functions // ------------------------------------------------------------------------- /** @@ -4483,6 +4484,165 @@ public class Factory implements FactoryOperations { return new CurrentTimestamp(); } + /** + * Get the date difference in number of days + *

+ * This translates into any dialect + * + * @see Field#sub(Field) + */ + @Support + public static Field dateDiff(Date date1, Date date2) { + return dateDiff(val(date1), val(date2)); + } + + /** + * Get the date difference in number of days + *

+ * This translates into any dialect + * + * @see Field#sub(Field) + */ + @Support + public static Field dateDiff(Field date1, Date date2) { + return dateDiff(nullSafe(date1), val(date2)); + } + + /** + * Get the date difference in number of days + *

+ * This translates into any dialect + * + * @see Field#sub(Field) + */ + @Support + public static Field dateDiff(Date date1, Field date2) { + return dateDiff(val(date1), nullSafe(date2)); + } + + /** + * Get the date difference in number of days + *

+ * This translates into any dialect + * + * @see Field#sub(Field) + */ + @Support + public static Field dateDiff(Field date1, Field date2) { + // TODO [#585] This cast shouldn't be necessary + return nullSafe(date1).sub(nullSafe(date2)).cast(Integer.class); + } + + /** + * Get the timestamp difference as a INTERVAL DAY TO SECOND + * type + *

+ * This translates into any dialect + * + * @see Field#sub(Field) + */ + @Support + public static Field timestampDiff(Timestamp timestamp1, Timestamp timestamp2) { + return timestampDiff(val(timestamp1), val(timestamp2)); + } + + /** + * Get the timestamp difference as a INTERVAL DAY TO SECOND + * type + *

+ * This translates into any dialect + * + * @see Field#sub(Field) + */ + @Support + public static Field timestampDiff(Field timestamp1, Timestamp timestamp2) { + return timestampDiff(nullSafe(timestamp1), val(timestamp2)); + } + + /** + * Get the timestamp difference as a INTERVAL DAY TO SECOND + * type + *

+ * This translates into any dialect + * + * @see Field#sub(Field) + */ + @Support + public static Field timestampDiff(Timestamp timestamp1, Field timestamp2) { + return timestampDiff(val(timestamp1), nullSafe(timestamp2)); + } + + /** + * Get the timestamp difference as a INTERVAL DAY TO SECOND + * type + *

+ * This translates into any dialect + * + * @see Field#sub(Field) + */ + @Support + public static Field timestampDiff(Field timestamp1, Field timestamp2) { + // TODO [#585] This cast shouldn't be necessary + return nullSafe(timestamp1).sub(nullSafe(timestamp2)).cast(DayToSecond.class); + } + + /** + * Get the timestamp difference as a INTERVAL DAY TO SECOND + * type + *

+ * This translates into any dialect + * + * @see Field#sub(Field) + */ + @Support + public static Field timeDiff(Time time1, Time time2) { + return timeDiff(val(time1), val(time2)); + } + + /** + * Get the timestamp difference as a INTERVAL DAY TO SECOND + * type + *

+ * This translates into any dialect + * + * @see Field#sub(Field) + */ + @Support + public static Field timeDiff(Field

+ * This translates into any dialect + * + * @see Field#sub(Field) + */ + @Support + public static Field timeDiff(Time time1, Field

+ * This translates into any dialect + * + * @see Field#sub(Field) + */ + @Support + public static Field timeDiff(Field

diff --git a/jOOQ/src/main/java/org/jooq/types/DayToSecond.java b/jOOQ/src/main/java/org/jooq/types/DayToSecond.java index d4a85aea39..58be33f5b7 100644 --- a/jOOQ/src/main/java/org/jooq/types/DayToSecond.java +++ b/jOOQ/src/main/java/org/jooq/types/DayToSecond.java @@ -133,6 +133,20 @@ public final class DayToSecond implements Interval { return null; } + // ------------------------------------------------------------------------- + // XXX Inteval API + // ------------------------------------------------------------------------- + + @Override + public final DayToSecond neg() { + return new DayToSecond(days, hours, minutes, seconds, nano, !negative); + } + + @Override + public final DayToSecond abs() { + return new DayToSecond(days, hours, minutes, seconds, nano, false); + } + // ------------------------------------------------------------------------- // XXX Comparable and Object API // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/types/Interval.java b/jOOQ/src/main/java/org/jooq/types/Interval.java index c7e6a58af6..0930b1b8ef 100644 --- a/jOOQ/src/main/java/org/jooq/types/Interval.java +++ b/jOOQ/src/main/java/org/jooq/types/Interval.java @@ -101,4 +101,13 @@ import java.io.Serializable; */ public interface Interval> extends Serializable, Comparable { + /** + * Negate the interval (change its sign) + */ + T neg(); + + /** + * Get the absolute value of the interval (set its sign to positive) + */ + T abs(); } diff --git a/jOOQ/src/main/java/org/jooq/types/YearToMonth.java b/jOOQ/src/main/java/org/jooq/types/YearToMonth.java index 142817c1b4..29ade2329e 100644 --- a/jOOQ/src/main/java/org/jooq/types/YearToMonth.java +++ b/jOOQ/src/main/java/org/jooq/types/YearToMonth.java @@ -101,6 +101,20 @@ public final class YearToMonth implements Interval { return null; } + // ------------------------------------------------------------------------- + // XXX Inteval API + // ------------------------------------------------------------------------- + + @Override + public final YearToMonth neg() { + return new YearToMonth(years, months, !negative); + } + + @Override + public final YearToMonth abs() { + return new YearToMonth(years, months, false); + } + // ------------------------------------------------------------------------- // XXX Comparable and Object API // -------------------------------------------------------------------------