sequence) throws DataAccessException;
// -------------------------------------------------------------------------
diff --git a/jOOQ/src/main/java/org/jooq/SQLDialect.java b/jOOQ/src/main/java/org/jooq/SQLDialect.java
index 095879a15e..03355c20a3 100644
--- a/jOOQ/src/main/java/org/jooq/SQLDialect.java
+++ b/jOOQ/src/main/java/org/jooq/SQLDialect.java
@@ -37,14 +37,22 @@
package org.jooq;
/**
- * This enumeration lists all supported dialects.
+ * Dialects and dialect families as supported by jOOQ.
+ *
+ * jOOQ supports a variety of dialects, which are grouped into dialect families.
+ * For instance, the SQL Server dialect family {@link #SQLSERVER} is specialised
+ * by its dialects
+ *
+ * - {@link #SQLSERVER2008}
+ * - {@link #SQLSERVER2012}
+ *
*
* @author Lukas Eder
*/
public enum SQLDialect {
/**
- * The standard SQL dialect.
+ * The standard SQL dialect family.
*
* @deprecated - Do not reference this pseudo-dialect. It is only used for
* unit testing
@@ -53,79 +61,109 @@ public enum SQLDialect {
SQL99(null),
/**
- * The Sybase Adaptive Server SQL dialect
+ * The Sybase Adaptive Server SQL dialect family.
*/
ASE("ASE"),
/**
- * The CUBRID SQL dialect
+ * The CUBRID SQL dialect family.
*/
CUBRID("CUBRID"),
/**
- * The IBM DB2 SQL dialect
+ * The IBM DB2 SQL dialect family.
*/
DB2("DB2"),
/**
- * The Apache Derby SQL dialect
+ * The Apache Derby SQL dialect family.
*/
DERBY("Derby"),
/**
- * The Firebird SQL dialect
+ * The Firebird SQL dialect family.
*/
FIREBIRD("Firebird"),
/**
- * The H2 SQL dialect
+ * The H2 SQL dialect family.
*/
H2("H2"),
/**
- * The Hypersonic SQL dialect
+ * The Hypersonic SQL dialect family.
*/
HSQLDB("HSQLDB"),
/**
- * The Ingres dialect
+ * The Ingres dialect family.
*/
INGRES("Ingres"),
/**
- * The MySQL dialect
+ * The MySQL dialect family.
*/
MYSQL("MySQL"),
/**
- * The Oracle dialect
+ * The Oracle dialect family.
*/
ORACLE("Oracle"),
/**
- * The PostGres dialect
+ * The PostgreSQL dialect family.
*/
POSTGRES("Postgres"),
/**
- * The SQLite dialect
+ * The SQLite dialect family.
*/
SQLITE("SQLite"),
/**
- * The SQL Server dialect
+ * The SQL Server dialect family.
*/
SQLSERVER("SQLServer"),
/**
- * The Sybase dialect
+ * The SQL Server 2008 dialect.
+ */
+ SQLSERVER2008("SQLServer", SQLSERVER),
+
+ /**
+ * The SQL Server 2012 dialect.
+ */
+ SQLSERVER2012("SQLServer", SQLSERVER),
+
+ /**
+ * The Sybase SQL Anywhere dialect family.
*/
SYBASE("Sybase");
- private final String name;
+ private final String name;
+ private final SQLDialect family;
private SQLDialect(String name) {
+ this(name, null);
+ }
+
+ private SQLDialect(String name, SQLDialect family) {
this.name = name;
+ this.family = family;
+ }
+
+ /**
+ * The dialect family.
+ *
+ * This returns the dialect itself, if it has no "parent family". E.g.
+ *
+ * SQLSERVER == SQLSERVER2012.family();
+ * SQLSERVER == SQLSERVER2008.family();
+ * SQLSERVER == SQLSERVER.family();
+ *
+ */
+ public final SQLDialect family() {
+ return family == null ? this : family;
}
/**
@@ -143,7 +181,7 @@ public enum SQLDialect {
}
/**
- * The name of this dialect as it appears in related enum values
+ * The name of this dialect as it appears in related enum values.
*/
public final String getNameUC() {
return name.toUpperCase();
diff --git a/jOOQ/src/main/java/org/jooq/Sequence.java b/jOOQ/src/main/java/org/jooq/Sequence.java
index 332f896fa9..e3b2247bb1 100644
--- a/jOOQ/src/main/java/org/jooq/Sequence.java
+++ b/jOOQ/src/main/java/org/jooq/Sequence.java
@@ -44,7 +44,7 @@ import static org.jooq.SQLDialect.HSQLDB;
import static org.jooq.SQLDialect.INGRES;
import static org.jooq.SQLDialect.ORACLE;
import static org.jooq.SQLDialect.POSTGRES;
-import static org.jooq.SQLDialect.SQLSERVER;
+import static org.jooq.SQLDialect.SQLSERVER2012;
import static org.jooq.SQLDialect.SYBASE;
import java.io.Serializable;
@@ -74,12 +74,12 @@ public interface Sequence extends Serializable {
/**
* Get the current value of this sequence
*/
- @Support({ CUBRID, DB2, FIREBIRD, H2, INGRES, ORACLE, POSTGRES, SQLSERVER, SYBASE })
+ @Support({ CUBRID, DB2, FIREBIRD, H2, INGRES, ORACLE, POSTGRES, SQLSERVER2012, SYBASE })
Field currval();
/**
* Increment the sequence and get the next value
*/
- @Support({ CUBRID, DB2, DERBY, FIREBIRD, H2, HSQLDB, INGRES, ORACLE, POSTGRES, SQLSERVER, SYBASE })
+ @Support({ CUBRID, DB2, DERBY, FIREBIRD, H2, HSQLDB, INGRES, ORACLE, POSTGRES, SQLSERVER2012, SYBASE })
Field nextval();
}
diff --git a/jOOQ/src/main/java/org/jooq/WindowRowsAndStep.java b/jOOQ/src/main/java/org/jooq/WindowRowsAndStep.java
index 309aec2a43..9d173d5e90 100644
--- a/jOOQ/src/main/java/org/jooq/WindowRowsAndStep.java
+++ b/jOOQ/src/main/java/org/jooq/WindowRowsAndStep.java
@@ -38,7 +38,7 @@ package org.jooq;
import static org.jooq.SQLDialect.DB2;
import static org.jooq.SQLDialect.ORACLE;
import static org.jooq.SQLDialect.POSTGRES;
-import static org.jooq.SQLDialect.SQLSERVER;
+import static org.jooq.SQLDialect.SQLSERVER2012;
import static org.jooq.SQLDialect.SYBASE;
import org.jooq.api.annotation.State;
@@ -56,9 +56,6 @@ import org.jooq.api.annotation.Transition;
* .rowsBetweenUnboundedPreceding()
* .andUnboundedFollowing()
*
- *
- * Note, that the functionality provided by this interface is not supported in
- * {@link SQLDialect#SQLSERVER}
*
* @param The function return type
* @author Lukas Eder
@@ -70,7 +67,7 @@ public interface WindowRowsAndStep {
* Add a ... AND UNBOUNDED PRECEDING frame clause to the window
* function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "AND UNBOUNDED PRECEDING"
)
@@ -80,7 +77,7 @@ public interface WindowRowsAndStep {
* Add a ... AND [number] PRECEDING frame clause to the window
* function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "AND PRECEDING",
args = "Integer"
@@ -91,7 +88,7 @@ public interface WindowRowsAndStep {
* Add a ... AND CURRENT ROW frame clause to the window
* function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "AND CURRENT ROW"
)
@@ -101,7 +98,7 @@ public interface WindowRowsAndStep {
* Add a ... AND UNBOUNDED FOLLOWING frame clause to the window
* function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "AND UNBOUNDED FOLLOWING"
)
@@ -111,7 +108,7 @@ public interface WindowRowsAndStep {
* Add a ... AND [number] FOLLOWING frame clause to the window
* function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "AND FOLLOWING",
args = "Integer"
diff --git a/jOOQ/src/main/java/org/jooq/WindowRowsStep.java b/jOOQ/src/main/java/org/jooq/WindowRowsStep.java
index a63a63d718..2857691ec0 100644
--- a/jOOQ/src/main/java/org/jooq/WindowRowsStep.java
+++ b/jOOQ/src/main/java/org/jooq/WindowRowsStep.java
@@ -38,7 +38,7 @@ package org.jooq;
import static org.jooq.SQLDialect.DB2;
import static org.jooq.SQLDialect.ORACLE;
import static org.jooq.SQLDialect.POSTGRES;
-import static org.jooq.SQLDialect.SQLSERVER;
+import static org.jooq.SQLDialect.SQLSERVER2012;
import static org.jooq.SQLDialect.SYBASE;
import org.jooq.api.annotation.State;
@@ -56,9 +56,6 @@ import org.jooq.api.annotation.Transition;
* .rowsBetweenUnboundedPreceding()
* .andUnboundedFollowing()
*
- *
- * Note, that the functionality provided by this interface is not supported in
- * {@link SQLDialect#SQLSERVER}
*
* @param The function return type
* @author Lukas Eder
@@ -70,7 +67,7 @@ public interface WindowRowsStep extends WindowFinalStep {
* Add a ROWS UNBOUNDED PRECEDING frame clause to the window
* function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "ROWS UNBOUNDED PRECEDING"
)
@@ -80,7 +77,7 @@ public interface WindowRowsStep extends WindowFinalStep {
* Add a ROWS [number] PRECEDING frame clause to the window
* function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "ROWS PRECEDING",
args = "Integer"
@@ -90,7 +87,7 @@ public interface WindowRowsStep extends WindowFinalStep {
/**
* Add a ROWS CURRENT ROW frame clause to the window function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "ROWS CURRENT ROW"
)
@@ -100,7 +97,7 @@ public interface WindowRowsStep extends WindowFinalStep {
* Add a ROWS UNBOUNDED FOLLOWING frame clause to the window
* function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "ROWS UNBOUNDED FOLLOWING"
)
@@ -110,7 +107,7 @@ public interface WindowRowsStep extends WindowFinalStep {
* Add a ROWS [number] FOLLOWING frame clause to the window
* function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "ROWS FOLLOWING",
args = "Integer"
@@ -121,7 +118,7 @@ public interface WindowRowsStep extends WindowFinalStep {
* Add a ROWS BETWEEN UNBOUNDED PRECEDING ... frame clause to
* the window function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "ROWS BETWEEN UNBOUNDED PRECEDING"
)
@@ -131,7 +128,7 @@ public interface WindowRowsStep extends WindowFinalStep {
* Add a ROWS BETWEEN [number] PRECEDING ... frame clause to
* the window function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "ROWS BETWEEN PRECEDING",
args = "Integer"
@@ -142,7 +139,7 @@ public interface WindowRowsStep extends WindowFinalStep {
* Add a ROWS BETWEEN CURRENT ROW ... frame clause to
* the window function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "ROWS BETWEEN CURRENT ROW"
)
@@ -152,7 +149,7 @@ public interface WindowRowsStep extends WindowFinalStep {
* Add a ROWS BETWEEN UNBOUNDED FOLLOWING ... frame clause to
* the window function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "ROWS BETWEEN UNBOUNDED FOLLOWING"
)
@@ -162,7 +159,7 @@ public interface WindowRowsStep extends WindowFinalStep {
* Add a ROWS BETWEEN [number] FOLLOWING ... frame clause to
* the window function.
*/
- @Support({ DB2, POSTGRES, ORACLE, SQLSERVER, SYBASE })
+ @Support({ DB2, POSTGRES, ORACLE, SQLSERVER2012, SYBASE })
@Transition(
name = "ROWS BETWEEN FOLLOWING",
args = "Integer"
diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java
index 0081c60480..d15781de9c 100644
--- a/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java
+++ b/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java
@@ -237,7 +237,7 @@ abstract class AbstractResultQuery extends AbstractQuery imple
// [#1296] These dialects do not implement FOR UPDATE. But the same
// effect can be achieved using ResultSet.CONCUR_UPDATABLE
- else if (isForUpdate() && asList(CUBRID, SQLSERVER).contains(ctx.configuration().dialect())) {
+ else if (isForUpdate() && asList(CUBRID, SQLSERVER).contains(ctx.configuration().dialect().family())) {
ctx.data(DATA_LOCK_ROWS_FOR_UPDATE, true);
ctx.statement(ctx.connection().prepareStatement(ctx.sql(), TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE));
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java
index 5ccfee3a52..0fb828ddbb 100644
--- a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java
+++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java
@@ -35,6 +35,7 @@
*/
package org.jooq.impl;
+import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.impl.DSL.function;
import static org.jooq.impl.DSL.table;
import static org.jooq.impl.DSL.val;
@@ -66,7 +67,6 @@ import org.jooq.Parameter;
import org.jooq.RenderContext;
import org.jooq.Result;
import org.jooq.Routine;
-import org.jooq.SQLDialect;
import org.jooq.Schema;
import org.jooq.UDTField;
import org.jooq.UDTRecord;
@@ -353,7 +353,7 @@ public abstract class AbstractRoutine extends AbstractQueryPart implements Ro
Field> value = getInValues().get(parameter);
// Disambiguate overloaded procedure signatures
- if (SQLDialect.POSTGRES == context.configuration().dialect() && isOverloaded()) {
+ if (POSTGRES == context.configuration().dialect() && isOverloaded()) {
value = value.cast(parameter.getType());
}
@@ -705,7 +705,7 @@ public abstract class AbstractRoutine extends AbstractQueryPart implements Ro
for (Parameter> p : getInParameters()) {
// Disambiguate overloaded function signatures
- if (SQLDialect.POSTGRES == c.dialect() && isOverloaded()) {
+ if (POSTGRES == c.dialect() && isOverloaded()) {
array[i] = getInValues().get(p).cast(p.getType());
}
else {
diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractStoreQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractStoreQuery.java
index ec95ba206e..0f2e75fbb7 100644
--- a/jOOQ/src/main/java/org/jooq/impl/AbstractStoreQuery.java
+++ b/jOOQ/src/main/java/org/jooq/impl/AbstractStoreQuery.java
@@ -198,7 +198,7 @@ abstract class AbstractStoreQuery extends AbstractQuery implem
// Values should be returned from the INSERT
else {
- switch (ctx.configuration().dialect()) {
+ switch (ctx.configuration().dialect().family()) {
// Postgres uses the RETURNING clause in SQL
case FIREBIRD:
@@ -249,7 +249,7 @@ abstract class AbstractStoreQuery extends AbstractQuery implem
else {
int result = 1;
ResultSet rs;
- switch (ctx.configuration().dialect()) {
+ switch (ctx.configuration().dialect().family()) {
// SQLite can select _rowid_ after the insert
case SQLITE: {
diff --git a/jOOQ/src/main/java/org/jooq/impl/Alias.java b/jOOQ/src/main/java/org/jooq/impl/Alias.java
index e441cd8bd9..e62e55ce81 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Alias.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Alias.java
@@ -104,7 +104,7 @@ class Alias extends AbstractQueryPart {
// [#1801] Some databases don't allow "derived column names" in
// "simple class specifications". Hence, wrap the table reference in
// a subselect
- if (fieldAliases != null && asList(CUBRID, FIREBIRD, SQLSERVER, SYBASE).contains(dialect) && wrapped instanceof TableImpl) {
+ if (fieldAliases != null && asList(CUBRID, FIREBIRD, SQLSERVER, SYBASE).contains(dialect.family()) && wrapped instanceof TableImpl) {
@SuppressWarnings("unchecked")
Select select =
diff --git a/jOOQ/src/main/java/org/jooq/impl/BetweenCondition.java b/jOOQ/src/main/java/org/jooq/impl/BetweenCondition.java
index 78930a98d1..f9c9f2dc0e 100644
--- a/jOOQ/src/main/java/org/jooq/impl/BetweenCondition.java
+++ b/jOOQ/src/main/java/org/jooq/impl/BetweenCondition.java
@@ -106,7 +106,7 @@ class BetweenCondition extends AbstractCondition implements BetweenAndStep
}
private final QueryPartInternal delegate(Configuration configuration) {
- if (symmetric && asList(ASE, CUBRID, DB2, DERBY, FIREBIRD, H2, MYSQL, ORACLE, SQLSERVER, SQLITE, SYBASE).contains(configuration.dialect())) {
+ if (symmetric && asList(ASE, CUBRID, DB2, DERBY, FIREBIRD, H2, MYSQL, ORACLE, SQLSERVER, SQLITE, SYBASE).contains(configuration.dialect().family())) {
if (not) {
return (QueryPartInternal) field.notBetween(minValue, maxValue).and(field.notBetween(maxValue, minValue));
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/Ceil.java b/jOOQ/src/main/java/org/jooq/impl/Ceil.java
index c8b19a6df3..3e8762dd86 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Ceil.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Ceil.java
@@ -60,7 +60,7 @@ class Ceil extends AbstractFunction {
@Override
final Field getFunction0(Configuration configuration) {
- switch (configuration.dialect()) {
+ switch (configuration.dialect().family()) {
// evaluate "ceil" if unavailable
case SQLITE:
diff --git a/jOOQ/src/main/java/org/jooq/impl/Concat.java b/jOOQ/src/main/java/org/jooq/impl/Concat.java
index 196b0f3e0c..d3bc17ae4f 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Concat.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Concat.java
@@ -35,10 +35,10 @@
*/
package org.jooq.impl;
-import static org.jooq.impl.ExpressionOperator.ADD;
-import static org.jooq.impl.ExpressionOperator.CONCAT;
import static org.jooq.impl.DSL.castAll;
import static org.jooq.impl.DSL.function;
+import static org.jooq.impl.ExpressionOperator.ADD;
+import static org.jooq.impl.ExpressionOperator.CONCAT;
import org.jooq.Configuration;
import org.jooq.Field;
@@ -73,7 +73,7 @@ class Concat extends AbstractFunction {
Field[] others = new Field[cast.length - 1];
System.arraycopy(cast, 1, others, 0, others.length);
- switch (configuration.dialect()) {
+ switch (configuration.dialect().family()) {
case MYSQL:
return function("concat", SQLDataType.VARCHAR, cast);
diff --git a/jOOQ/src/main/java/org/jooq/impl/ConditionAsField.java b/jOOQ/src/main/java/org/jooq/impl/ConditionAsField.java
index 7ff13a2ef2..b92b509bf8 100644
--- a/jOOQ/src/main/java/org/jooq/impl/ConditionAsField.java
+++ b/jOOQ/src/main/java/org/jooq/impl/ConditionAsField.java
@@ -60,7 +60,7 @@ class ConditionAsField extends AbstractFunction {
@Override
final QueryPart getFunction0(Configuration configuration) {
- switch (configuration.dialect()) {
+ switch (configuration.dialect().family()) {
// Some databases don't accept predicates where column expressions
// are expected.
diff --git a/jOOQ/src/main/java/org/jooq/impl/Cosh.java b/jOOQ/src/main/java/org/jooq/impl/Cosh.java
index 5e4b970701..c7782f4f01 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Cosh.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Cosh.java
@@ -64,7 +64,7 @@ class Cosh extends AbstractFunction {
@Override
final Field getFunction0(Configuration configuration) {
- switch (configuration.dialect()) {
+ switch (configuration.dialect().family()) {
case ASE:
case CUBRID:
case HSQLDB:
diff --git a/jOOQ/src/main/java/org/jooq/impl/CurrentDate.java b/jOOQ/src/main/java/org/jooq/impl/CurrentDate.java
index a03e0c6d7e..a896ba37de 100644
--- a/jOOQ/src/main/java/org/jooq/impl/CurrentDate.java
+++ b/jOOQ/src/main/java/org/jooq/impl/CurrentDate.java
@@ -59,7 +59,7 @@ class CurrentDate extends AbstractFunction {
@Override
final Field getFunction0(Configuration configuration) {
- switch (configuration.dialect()) {
+ switch (configuration.dialect().family()) {
case ORACLE:
return field("sysdate", SQLDataType.DATE);
diff --git a/jOOQ/src/main/java/org/jooq/impl/CurrentTime.java b/jOOQ/src/main/java/org/jooq/impl/CurrentTime.java
index 4747121ff3..94e6b9eccc 100644
--- a/jOOQ/src/main/java/org/jooq/impl/CurrentTime.java
+++ b/jOOQ/src/main/java/org/jooq/impl/CurrentTime.java
@@ -59,7 +59,7 @@ class CurrentTime extends AbstractFunction