You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2016/03/08 07:13:21 UTC
[1/5] calcite git commit: Deprecate SqlLiteral.SqlSymbol;
SqlSymbol can now wrap any Enum
Repository: calcite
Updated Branches:
refs/heads/master a547222bd -> 4ac82a30b
Deprecate SqlLiteral.SqlSymbol; SqlSymbol can now wrap any Enum
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/9c62adac
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/9c62adac
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/9c62adac
Branch: refs/heads/master
Commit: 9c62adac2a218b428e322e8467263cec0ed9874b
Parents: a547222
Author: Julian Hyde <jh...@apache.org>
Authored: Fri Mar 4 13:51:02 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 7 21:20:51 2016 -0800
----------------------------------------------------------------------
.../calcite/rel/rel2sql/SqlImplementor.java | 3 +--
.../apache/calcite/sql/JoinConditionType.java | 2 +-
.../java/org/apache/calcite/sql/JoinType.java | 2 +-
.../org/apache/calcite/sql/SemiJoinType.java | 2 +-
.../java/org/apache/calcite/sql/SqlExplain.java | 6 ++---
.../org/apache/calcite/sql/SqlExplainLevel.java | 2 +-
.../java/org/apache/calcite/sql/SqlInsert.java | 6 +++--
.../apache/calcite/sql/SqlInsertKeyword.java | 2 +-
.../java/org/apache/calcite/sql/SqlJoin.java | 10 ++++----
.../java/org/apache/calcite/sql/SqlLiteral.java | 27 +++++++++++---------
.../java/org/apache/calcite/sql/SqlSelect.java | 3 ++-
.../apache/calcite/sql/SqlSelectKeyword.java | 2 +-
.../java/org/apache/calcite/sql/SqlWindow.java | 8 +++---
.../calcite/sql/fun/SqlBetweenOperator.java | 3 +--
.../apache/calcite/sql/fun/SqlTrimFunction.java | 2 +-
15 files changed, 42 insertions(+), 38 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
index 03cc708..1f116b2 100644
--- a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
+++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
@@ -452,8 +452,7 @@ public abstract class SqlImplementor {
case LITERAL:
final RexLiteral literal = (RexLiteral) rex;
if (literal.getTypeName() == SqlTypeName.SYMBOL) {
- final SqlLiteral.SqlSymbol symbol =
- (SqlLiteral.SqlSymbol) literal.getValue();
+ final Enum symbol = (Enum) literal.getValue();
return SqlLiteral.createSymbol(symbol, POS);
}
switch (literal.getTypeName().getFamily()) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/JoinConditionType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/JoinConditionType.java b/core/src/main/java/org/apache/calcite/sql/JoinConditionType.java
index 6521944..3b449b0 100644
--- a/core/src/main/java/org/apache/calcite/sql/JoinConditionType.java
+++ b/core/src/main/java/org/apache/calcite/sql/JoinConditionType.java
@@ -21,7 +21,7 @@ import org.apache.calcite.sql.parser.SqlParserPos;
/**
* Enumerates the types of condition in a join expression.
*/
-public enum JoinConditionType implements SqlLiteral.SqlSymbol {
+public enum JoinConditionType {
/**
* Join clause has no condition, for example "FROM EMP, DEPT"
*/
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/JoinType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/JoinType.java b/core/src/main/java/org/apache/calcite/sql/JoinType.java
index 993c279..0e4cc05 100644
--- a/core/src/main/java/org/apache/calcite/sql/JoinType.java
+++ b/core/src/main/java/org/apache/calcite/sql/JoinType.java
@@ -21,7 +21,7 @@ import org.apache.calcite.sql.parser.SqlParserPos;
/**
* Enumerates the types of join.
*/
-public enum JoinType implements SqlLiteral.SqlSymbol {
+public enum JoinType {
/**
* Inner join.
*/
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/SemiJoinType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SemiJoinType.java b/core/src/main/java/org/apache/calcite/sql/SemiJoinType.java
index 50b3659..38cabba 100644
--- a/core/src/main/java/org/apache/calcite/sql/SemiJoinType.java
+++ b/core/src/main/java/org/apache/calcite/sql/SemiJoinType.java
@@ -24,7 +24,7 @@ import org.apache.calcite.sql.parser.SqlParserPos;
* Enumeration representing different join types used in correlation
* relations.
*/
-public enum SemiJoinType implements SqlLiteral.SqlSymbol {
+public enum SemiJoinType {
/**
* Inner join
*/
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/SqlExplain.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlExplain.java b/core/src/main/java/org/apache/calcite/sql/SqlExplain.java
index 7004caf..fc0e710 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlExplain.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlExplain.java
@@ -40,7 +40,7 @@ public class SqlExplain extends SqlCall {
/**
* The level of abstraction with which to display the plan.
*/
- public static enum Depth implements SqlLiteral.SqlSymbol {
+ public enum Depth {
TYPE, LOGICAL, PHYSICAL;
/**
@@ -120,14 +120,14 @@ public class SqlExplain extends SqlCall {
* @return detail level to be generated
*/
public SqlExplainLevel getDetailLevel() {
- return detailLevel.symbolValue();
+ return detailLevel.symbolValue(SqlExplainLevel.class);
}
/**
* Returns the level of abstraction at which this plan should be displayed.
*/
public Depth getDepth() {
- return depth.symbolValue();
+ return depth.symbolValue(Depth.class);
}
/**
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/SqlExplainLevel.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlExplainLevel.java b/core/src/main/java/org/apache/calcite/sql/SqlExplainLevel.java
index 4186393..0f3464f 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlExplainLevel.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlExplainLevel.java
@@ -21,7 +21,7 @@ import org.apache.calcite.sql.parser.SqlParserPos;
/**
* SqlExplainLevel defines detail levels for EXPLAIN PLAN.
*/
-public enum SqlExplainLevel implements SqlLiteral.SqlSymbol {
+public enum SqlExplainLevel {
/**
* Suppress all attributes.
*/
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/SqlInsert.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlInsert.java b/core/src/main/java/org/apache/calcite/sql/SqlInsert.java
index 7b58c8f..19472a7 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlInsert.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlInsert.java
@@ -80,7 +80,8 @@ public class SqlInsert extends SqlCall {
keywords = (SqlNodeList) operand;
break;
case 1:
- targetTable = (SqlIdentifier) operand;
+ assert operand instanceof SqlIdentifier;
+ targetTable = operand;
break;
case 2:
source = operand;
@@ -121,7 +122,8 @@ public class SqlInsert extends SqlCall {
public final SqlNode getModifierNode(SqlInsertKeyword modifier) {
for (SqlNode keyword : keywords) {
- SqlInsertKeyword keyword2 = ((SqlLiteral) keyword).symbolValue();
+ SqlInsertKeyword keyword2 =
+ ((SqlLiteral) keyword).symbolValue(SqlInsertKeyword.class);
if (keyword2 == modifier) {
return keyword;
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/SqlInsertKeyword.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlInsertKeyword.java b/core/src/main/java/org/apache/calcite/sql/SqlInsertKeyword.java
index e4704c7..68b3629 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlInsertKeyword.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlInsertKeyword.java
@@ -23,7 +23,7 @@ import org.apache.calcite.sql.parser.SqlParserPos;
*
* <p>Standard SQL has no such keywords, but extension projects may define them.
*/
-public enum SqlInsertKeyword implements SqlLiteral.SqlSymbol {
+public enum SqlInsertKeyword {
UPSERT;
/**
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/SqlJoin.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlJoin.java b/core/src/main/java/org/apache/calcite/sql/SqlJoin.java
index 12b1fb0..104d315 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlJoin.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlJoin.java
@@ -66,9 +66,9 @@ public class SqlJoin extends SqlCall {
this.conditionType = Preconditions.checkNotNull(conditionType);
this.condition = condition;
- assert natural.getTypeName() == SqlTypeName.BOOLEAN;
- assert conditionType.symbolValue() instanceof JoinConditionType;
- assert joinType.symbolValue() instanceof JoinType;
+ Preconditions.checkArgument(natural.getTypeName() == SqlTypeName.BOOLEAN);
+ Preconditions.checkNotNull(conditionType.symbolValue(JoinConditionType.class));
+ Preconditions.checkNotNull(joinType.symbolValue(JoinType.class));
}
//~ Methods ----------------------------------------------------------------
@@ -117,7 +117,7 @@ public class SqlJoin extends SqlCall {
/** Returns a {@link JoinConditionType}, never null. */
public final JoinConditionType getConditionType() {
- return conditionType.symbolValue();
+ return conditionType.symbolValue(JoinConditionType.class);
}
public SqlLiteral getConditionTypeNode() {
@@ -126,7 +126,7 @@ public class SqlJoin extends SqlCall {
/** Returns a {@link JoinType}, never null. */
public final JoinType getJoinType() {
- return joinType.symbolValue();
+ return joinType.symbolValue(JoinType.class);
}
public SqlLiteral getJoinTypeNode() {
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/SqlLiteral.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlLiteral.java b/core/src/main/java/org/apache/calcite/sql/SqlLiteral.java
index f535c53..347ea1a 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlLiteral.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlLiteral.java
@@ -126,7 +126,7 @@ import static org.apache.calcite.util.Static.RESOURCE;
* the SQL standard, and is not exposed to end-users. It is used to hold a
* symbol, such as the LEADING flag in a call to the function <code>
* TRIM([LEADING|TRAILING|BOTH] chars FROM string)</code>.</td>
- * <td>A class which implements the {@link SqlSymbol} interface</td>
+ * <td>An {@link Enum}</td>
* </tr>
* <tr>
* <td>{@link SqlTypeName#INTERVAL_DAY_TIME}</td>
@@ -205,9 +205,8 @@ public class SqlLiteral extends SqlNode {
case CHAR:
return value instanceof NlsString;
case SYMBOL:
- return (value instanceof SqlSymbol)
- || (value instanceof SqlSampleSpec)
- || (value instanceof TimeUnitRange);
+ return (value instanceof Enum)
+ || (value instanceof SqlSampleSpec);
case MULTISET:
return true;
case INTEGER: // not allowed -- use Decimal
@@ -234,18 +233,24 @@ public class SqlLiteral extends SqlNode {
* do.
*
* @see #booleanValue()
- * @see #symbolValue()
+ * @see #symbolValue(Class)
*/
public Object getValue() {
return value;
}
/** Returns the value as a symbol. */
- public <E extends SqlSymbol> E symbolValue() {
+ @Deprecated // to be removed before 2.0
+ public <E extends Enum<E>> E symbolValue_() {
//noinspection unchecked
return (E) value;
}
+ /** Returns the value as a symbol. */
+ public <E extends Enum<E>> E symbolValue(Class<E> class_) {
+ return class_.cast(value);
+ }
+
/** Returns the value as a boolean. */
public boolean booleanValue() {
return (Boolean) value;
@@ -255,7 +260,7 @@ public class SqlLiteral extends SqlNode {
* Extracts the {@link SqlSampleSpec} value from a symbol literal.
*
* @throws ClassCastException if the value is not a symbol literal
- * @see #createSymbol(SqlSymbol, SqlParserPos)
+ * @see #createSymbol(Enum, SqlParserPos)
*/
public static SqlSampleSpec sampleValue(SqlNode node) {
return (SqlSampleSpec) ((SqlLiteral) node).value;
@@ -450,11 +455,9 @@ public class SqlLiteral extends SqlNode {
* <code>TRAILING</code> keyword in the call <code>Trim(TRAILING 'x' FROM
* 'Hello world!')</code>.
*
- * @see #symbolValue()
+ * @see #symbolValue(Class)
*/
- public static SqlLiteral createSymbol(
- SqlLiteral.SqlSymbol o,
- SqlParserPos pos) {
+ public static SqlLiteral createSymbol(Enum<?> o, SqlParserPos pos) {
return new SqlLiteral(o, SqlTypeName.SYMBOL, pos);
}
@@ -580,7 +583,6 @@ public class SqlLiteral extends SqlNode {
case DECIMAL:
case DOUBLE:
case BINARY:
-
// should be handled in subtype
throw Util.unexpected(typeName);
@@ -876,6 +878,7 @@ public class SqlLiteral extends SqlNode {
* unparsed, which is sometimes not the same as the enumerated value's name
* (e.g. "UNBOUNDED PRECEDING" versus "UnboundedPreceeding").
*/
+ @Deprecated // to be removed before 2.0
public interface SqlSymbol {
String name();
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/SqlSelect.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlSelect.java b/core/src/main/java/org/apache/calcite/sql/SqlSelect.java
index 2fa09e5..d1cb249 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlSelect.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlSelect.java
@@ -131,7 +131,8 @@ public class SqlSelect extends SqlCall {
public final SqlNode getModifierNode(SqlSelectKeyword modifier) {
for (SqlNode keyword : keywordList) {
- SqlSelectKeyword keyword2 = ((SqlLiteral) keyword).symbolValue();
+ SqlSelectKeyword keyword2 =
+ ((SqlLiteral) keyword).symbolValue(SqlSelectKeyword.class);
if (keyword2 == modifier) {
return keyword;
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/SqlSelectKeyword.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlSelectKeyword.java b/core/src/main/java/org/apache/calcite/sql/SqlSelectKeyword.java
index 1ca4158..b83c832 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlSelectKeyword.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlSelectKeyword.java
@@ -21,7 +21,7 @@ import org.apache.calcite.sql.parser.SqlParserPos;
/**
* Defines the keywords which can occur immediately after the "SELECT" keyword.
*/
-public enum SqlSelectKeyword implements SqlLiteral.SqlSymbol {
+public enum SqlSelectKeyword {
DISTINCT,
ALL,
STREAM;
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/SqlWindow.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlWindow.java b/core/src/main/java/org/apache/calcite/sql/SqlWindow.java
index a4150c4..86adcc6 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlWindow.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlWindow.java
@@ -362,7 +362,7 @@ public class SqlWindow extends SqlCall {
*/
public static boolean isCurrentRow(SqlNode node) {
return (node instanceof SqlLiteral)
- && ((SqlLiteral) node).symbolValue() == Bound.CURRENT_ROW;
+ && ((SqlLiteral) node).symbolValue(Bound.class) == Bound.CURRENT_ROW;
}
/**
@@ -370,7 +370,7 @@ public class SqlWindow extends SqlCall {
*/
public static boolean isUnboundedPreceding(SqlNode node) {
return (node instanceof SqlLiteral)
- && ((SqlLiteral) node).symbolValue() == Bound.UNBOUNDED_PRECEDING;
+ && ((SqlLiteral) node).symbolValue(Bound.class) == Bound.UNBOUNDED_PRECEDING;
}
/**
@@ -378,7 +378,7 @@ public class SqlWindow extends SqlCall {
*/
public static boolean isUnboundedFollowing(SqlNode node) {
return (node instanceof SqlLiteral)
- && ((SqlLiteral) node).symbolValue() == Bound.UNBOUNDED_FOLLOWING;
+ && ((SqlLiteral) node).symbolValue(Bound.class) == Bound.UNBOUNDED_FOLLOWING;
}
/**
@@ -772,7 +772,7 @@ public class SqlWindow extends SqlCall {
* An enumeration of types of bounds in a window: <code>CURRENT ROW</code>,
* <code>UNBOUNDED PRECEDING</code>, and <code>UNBOUNDED FOLLOWING</code>.
*/
- enum Bound implements SqlLiteral.SqlSymbol {
+ enum Bound {
CURRENT_ROW("CURRENT ROW"),
UNBOUNDED_PRECEDING("UNBOUNDED PRECEDING"),
UNBOUNDED_FOLLOWING("UNBOUNDED FOLLOWING");
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/fun/SqlBetweenOperator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlBetweenOperator.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlBetweenOperator.java
index 4dff351..c4358d1 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlBetweenOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlBetweenOperator.java
@@ -23,7 +23,6 @@ import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlCallBinding;
import org.apache.calcite.sql.SqlInfixOperator;
import org.apache.calcite.sql.SqlKind;
-import org.apache.calcite.sql.SqlLiteral;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlOperatorBinding;
@@ -93,7 +92,7 @@ public class SqlBetweenOperator extends SqlInfixOperator {
/**
* Defines the "SYMMETRIC" and "ASYMMETRIC" keywords.
*/
- public enum Flag implements SqlLiteral.SqlSymbol {
+ public enum Flag {
ASYMMETRIC, SYMMETRIC
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/9c62adac/core/src/main/java/org/apache/calcite/sql/fun/SqlTrimFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlTrimFunction.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlTrimFunction.java
index 606c21e..629d954 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlTrimFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlTrimFunction.java
@@ -63,7 +63,7 @@ public class SqlTrimFunction extends SqlFunction {
/**
* Defines the enumerated values "LEADING", "TRAILING", "BOTH".
*/
- public enum Flag implements SqlLiteral.SqlSymbol {
+ public enum Flag {
BOTH(1, 1), LEADING(1, 0), TRAILING(0, 1);
private final int left;
[3/5] calcite git commit: In TimeUnit add WEEK, QUARTER,
MICROSECOND values, and change type of multiplier
Posted by jh...@apache.org.
In TimeUnit add WEEK, QUARTER, MICROSECOND values, and change type of multiplier
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/cf5d07bd
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/cf5d07bd
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/cf5d07bd
Branch: refs/heads/master
Commit: cf5d07bde81a7c6a82bdab34ec798d0bf01ac01c
Parents: eead3d2
Author: Julian Hyde <jh...@apache.org>
Authored: Mon Mar 7 15:46:31 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 7 21:25:01 2016 -0800
----------------------------------------------------------------------
.../apache/calcite/avatica/util/TimeUnit.java | 38 +++++++++++++-------
.../calcite/avatica/util/TimeUnitRange.java | 8 ++++-
.../java/org/apache/calcite/rex/RexBuilder.java | 11 +++---
.../sql2rel/StandardConvertletTable.java | 33 ++++++++---------
4 files changed, 52 insertions(+), 38 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/cf5d07bd/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnit.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnit.java b/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnit.java
index b249232..574aa45 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnit.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnit.java
@@ -20,28 +20,42 @@ import java.math.BigDecimal;
/**
* Enumeration of time units used to construct an interval.
+ *
+ * <p>Only {@link #YEAR}, {@link #YEAR}, {@link #MONTH}, {@link #DAY},
+ * {@link #HOUR}, {@link #MINUTE}, {@link #SECOND} can be the unit of a SQL
+ * interval.
+ *
+ * <p>The others ({@link #QUARTER}, {@link #WEEK}, {@link #MILLISECOND} and
+ * {@link #MICROSECOND}) are convenient to use it internally, when converting to
+ * and from UNIX timestamps. And also may be arguments to the
+ * {@code TIMESTAMPADD} and {@code TIMESTAMPDIFF} functions.
*/
public enum TimeUnit {
- YEAR(true, ' ', 12 /* months */, null),
- MONTH(true, '-', 1 /* months */, BigDecimal.valueOf(12)),
- DAY(false, '-', DateTimeUtils.MILLIS_PER_DAY, null),
- HOUR(false, ' ', DateTimeUtils.MILLIS_PER_HOUR, BigDecimal.valueOf(24)),
- MINUTE(false, ':', DateTimeUtils.MILLIS_PER_MINUTE, BigDecimal.valueOf(60)),
- SECOND(false, ':', DateTimeUtils.MILLIS_PER_SECOND, BigDecimal.valueOf(60)),
+ YEAR(true, ' ', BigDecimal.valueOf(12) /* months */, null),
+ MONTH(true, '-', BigDecimal.ONE /* months */, BigDecimal.valueOf(12)),
+ DAY(false, '-', BigDecimal.valueOf(DateTimeUtils.MILLIS_PER_DAY), null),
+ HOUR(false, ' ', BigDecimal.valueOf(DateTimeUtils.MILLIS_PER_HOUR),
+ BigDecimal.valueOf(24)),
+ MINUTE(false, ':', BigDecimal.valueOf(DateTimeUtils.MILLIS_PER_MINUTE),
+ BigDecimal.valueOf(60)),
+ SECOND(false, ':', BigDecimal.valueOf(DateTimeUtils.MILLIS_PER_SECOND),
+ BigDecimal.valueOf(60)),
- /** Unlike the other units, MILLISECOND may not be the unit of a SQL interval.
- * Still, it is convenient to use it internally, when converting to and from
- * UNIX timestamps. */
- MILLISECOND(false, '.', 1, BigDecimal.valueOf(1));
+ QUARTER(true, '*', BigDecimal.valueOf(3) /* months */, BigDecimal.valueOf(4)),
+ WEEK(false, '*', BigDecimal.valueOf(DateTimeUtils.MILLIS_PER_DAY * 7),
+ BigDecimal.valueOf(53)),
+ MILLISECOND(false, '.', BigDecimal.ONE, BigDecimal.valueOf(1000)),
+ MICROSECOND(false, '.', BigDecimal.ONE.scaleByPowerOfTen(-3),
+ BigDecimal.valueOf(1000000));
public final boolean yearMonth;
public final char separator;
- public final long multiplier;
+ public final BigDecimal multiplier;
private final BigDecimal limit;
private static final TimeUnit[] CACHED_VALUES = values();
- TimeUnit(boolean yearMonth, char separator, long multiplier,
+ TimeUnit(boolean yearMonth, char separator, BigDecimal multiplier,
BigDecimal limit) {
this.yearMonth = yearMonth;
this.separator = separator;
http://git-wip-us.apache.org/repos/asf/calcite/blob/cf5d07bd/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnitRange.java
----------------------------------------------------------------------
diff --git a/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnitRange.java b/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnitRange.java
index 4d9b322..ddfe9f7 100644
--- a/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnitRange.java
+++ b/avatica/core/src/main/java/org/apache/calcite/avatica/util/TimeUnitRange.java
@@ -36,7 +36,13 @@ public enum TimeUnitRange {
HOUR_TO_SECOND(TimeUnit.HOUR, TimeUnit.SECOND),
MINUTE(TimeUnit.MINUTE, null),
MINUTE_TO_SECOND(TimeUnit.MINUTE, TimeUnit.SECOND),
- SECOND(TimeUnit.SECOND, null);
+ SECOND(TimeUnit.SECOND, null),
+
+ // non-standard time units cannot participate in ranges
+ QUARTER(TimeUnit.QUARTER, null),
+ WEEK(TimeUnit.WEEK, null),
+ MILLISECOND(TimeUnit.MILLISECOND, null),
+ MICROSECOND(TimeUnit.MICROSECOND, null);
public final TimeUnit startUnit;
public final TimeUnit endUnit;
http://git-wip-us.apache.org/repos/asf/calcite/blob/cf5d07bd/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
index dd147a5..b0cc27e 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
@@ -525,7 +525,7 @@ public class RexBuilder {
case INTERVAL_DAY_TIME:
assert value instanceof BigDecimal;
BigDecimal value2 = (BigDecimal) value;
- final long multiplier =
+ final BigDecimal multiplier =
literal.getType().getIntervalQualifier().getStartUnit()
.multiplier;
typeName = type.getSqlTypeName();
@@ -534,8 +534,7 @@ public class RexBuilder {
case INTEGER:
typeName = SqlTypeName.BIGINT;
}
- value = value2.divide(BigDecimal.valueOf(multiplier), 0,
- BigDecimal.ROUND_HALF_DOWN);
+ value = value2.divide(multiplier, 0, BigDecimal.ROUND_HALF_DOWN);
}
final RexLiteral literal2 =
makeLiteral(value, type, typeName);
@@ -595,8 +594,7 @@ public class RexBuilder {
.getFractionalSecondPrecision(typeFactory.getTypeSystem()),
3);
}
- BigDecimal multiplier = BigDecimal.valueOf(endUnit.multiplier)
- .divide(BigDecimal.TEN.pow(scale));
+ BigDecimal multiplier = endUnit.multiplier.scaleByPowerOfTen(-scale);
RexNode value = decodeIntervalOrDecimal(exp);
if (multiplier.longValue() != 1) {
value = makeCall(
@@ -627,8 +625,7 @@ public class RexBuilder {
.getFractionalSecondPrecision(typeFactory.getTypeSystem()),
3);
}
- BigDecimal multiplier = BigDecimal.valueOf(endUnit.multiplier)
- .divide(BigDecimal.TEN.pow(scale));
+ BigDecimal multiplier = endUnit.multiplier.scaleByPowerOfTen(-scale);
RelDataType decimalType =
getTypeFactory().createSqlType(SqlTypeName.DECIMAL,
scale + intervalType.getPrecision(),
http://git-wip-us.apache.org/repos/asf/calcite/blob/cf5d07bd/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
index 99452bf..5d1957f 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
@@ -16,7 +16,6 @@
*/
package org.apache.calcite.sql2rel;
-import org.apache.calcite.avatica.util.DateTimeUtils;
import org.apache.calcite.avatica.util.TimeUnit;
import org.apache.calcite.avatica.util.TimeUnitRange;
import org.apache.calcite.plan.RelOptUtil;
@@ -465,8 +464,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
RexLiteral castedInterval =
cx.getRexBuilder().makeIntervalLiteral(
sourceValue.multiply(
- BigDecimal.valueOf(
- intervalQualifier.getStartUnit().multiplier),
+ intervalQualifier.getStartUnit().multiplier,
MathContext.UNLIMITED),
intervalQualifier);
return castToValidatedType(cx, call, castedInterval);
@@ -515,7 +513,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
final SqlIntervalLiteral literal = call.operand(0);
SqlIntervalLiteral.IntervalValue interval =
(SqlIntervalLiteral.IntervalValue) literal.getValue();
- long val =
+ BigDecimal val =
interval.getIntervalQualifier().getStartUnit().multiplier;
RexNode rexInterval = cx.convertExpression(literal);
@@ -530,7 +528,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
zero);
RexNode pad =
- rexBuilder.makeExactLiteral(BigDecimal.valueOf(val - 1));
+ rexBuilder.makeExactLiteral(val.subtract(BigDecimal.ONE));
RexNode cast = rexBuilder.makeReinterpretCast(
rexInterval.getType(), pad, rexBuilder.makeLiteral(false));
SqlOperator op =
@@ -545,8 +543,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
: rexBuilder.makeCall(SqlStdOperatorTable.CASE,
cond, sum, rexInterval);
- RexNode factor =
- rexBuilder.makeExactLiteral(BigDecimal.valueOf(val));
+ RexNode factor = rexBuilder.makeExactLiteral(val);
RexNode div =
rexBuilder.makeCall(
SqlStdOperatorTable.DIVIDE_INTEGER,
@@ -596,7 +593,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
case INTERVAL_DAY_TIME:
break;
case TIMESTAMP:
- res = divide(rexBuilder, res, DateTimeUtils.MILLIS_PER_DAY);
+ res = divide(rexBuilder, res, TimeUnit.DAY.multiplier);
// fall through
case DATE:
return rexBuilder.makeCall(resType, SqlStdOperatorTable.EXTRACT_DATE,
@@ -636,16 +633,16 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
ImmutableList.of(rexBuilder.makeFlag(TimeUnitRange.MONTH), x));
res = rexBuilder.makeCall(SqlStdOperatorTable.MINUS, res,
rexBuilder.makeExactLiteral(BigDecimal.ONE));
- res = divide(rexBuilder, res, 3);
+ res = divide(rexBuilder, res, TimeUnit.QUARTER.multiplier);
res = rexBuilder.makeCall(SqlStdOperatorTable.PLUS, res,
rexBuilder.makeExactLiteral(BigDecimal.ONE));
return res;
}
- private static long getFactor(TimeUnit unit) {
+ private static BigDecimal getFactor(TimeUnit unit) {
switch (unit) {
case DAY:
- return 1;
+ return BigDecimal.ONE;
case HOUR:
return TimeUnit.DAY.multiplier;
case MINUTE:
@@ -653,7 +650,7 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
case SECOND:
return TimeUnit.MINUTE.multiplier;
case YEAR:
- return 1;
+ return BigDecimal.ONE;
case MONTH:
return TimeUnit.YEAR.multiplier;
default:
@@ -662,20 +659,20 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
}
private RexNode mod(RexBuilder rexBuilder, RelDataType resType, RexNode res,
- long val) {
- if (val == 1L) {
+ BigDecimal val) {
+ if (val.equals(BigDecimal.ONE)) {
return res;
}
return rexBuilder.makeCall(SqlStdOperatorTable.MOD, res,
- rexBuilder.makeExactLiteral(BigDecimal.valueOf(val), resType));
+ rexBuilder.makeExactLiteral(val, resType));
}
- private RexNode divide(RexBuilder rexBuilder, RexNode res, long val) {
- if (val == 1L) {
+ private RexNode divide(RexBuilder rexBuilder, RexNode res, BigDecimal val) {
+ if (val.equals(BigDecimal.ONE)) {
return res;
}
return rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE_INTEGER, res,
- rexBuilder.makeExactLiteral(BigDecimal.valueOf(val)));
+ rexBuilder.makeExactLiteral(val));
}
public RexNode convertDatetimeMinus(
[4/5] calcite git commit: [CALCITE-1124] Add TIMESTAMPADD,
TIMESTAMPDIFF functions (Arina Ielchiieva)
Posted by jh...@apache.org.
[CALCITE-1124] Add TIMESTAMPADD, TIMESTAMPDIFF functions (Arina Ielchiieva)
Close apache/calcite#204
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/0b9ea986
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/0b9ea986
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/0b9ea986
Branch: refs/heads/master
Commit: 0b9ea986b847c325da009376d3b9031c9303090e
Parents: cf5d07b
Author: Arina Ielchiieva <ar...@gmail.com>
Authored: Thu Mar 3 17:07:10 2016 +0200
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 7 21:26:48 2016 -0800
----------------------------------------------------------------------
core/src/main/codegen/templates/Parser.jj | 135 +++++++++++++++++++
.../apache/calcite/sql/TimestampInterval.java | 47 +++++++
.../calcite/sql/fun/SqlStdOperatorTable.java | 63 +++++++++
.../calcite/sql/parser/SqlParserTest.java | 41 ++++++
.../calcite/sql/test/SqlOperatorBaseTest.java | 15 +++
.../apache/calcite/test/SqlValidatorTest.java | 48 +++++++
site/_docs/reference.md | 16 +++
7 files changed, 365 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/0b9ea986/core/src/main/codegen/templates/Parser.jj
----------------------------------------------------------------------
diff --git a/core/src/main/codegen/templates/Parser.jj b/core/src/main/codegen/templates/Parser.jj
index ce4920b..01c35bb 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -82,6 +82,7 @@ import org.apache.calcite.sql.SqlUtil;
import org.apache.calcite.sql.SqlWindow;
import org.apache.calcite.sql.SqlWith;
import org.apache.calcite.sql.SqlWithItem;
+import org.apache.calcite.sql.TimestampInterval;
import org.apache.calcite.sql.fun.SqlCase;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.fun.SqlTrimFunction;
@@ -3438,6 +3439,64 @@ TimeUnit TimeUnit() :
}
}
+SqlLiteral TimestampInterval() :
+{
+SqlLiteral.SqlSymbol symbol = null;
+}
+{
+ (
+ ( <FRAC_SECOND> | <MICROSECOND> | <SQL_TSI_FRAC_SECOND> | <SQL_TSI_MICROSECOND> )
+ {
+ symbol = TimestampInterval.MICROSECOND;
+ }
+ |
+ ( <SECOND> | <SQL_TSI_SECOND> )
+ {
+ symbol = TimestampInterval.SECOND;
+ }
+ |
+ ( <MINUTE> | <SQL_TSI_MINUTE> )
+ {
+ symbol = TimestampInterval.MINUTE;
+ }
+ |
+ ( <HOUR> | <SQL_TSI_HOUR> )
+ {
+ symbol = TimestampInterval.HOUR;
+ }
+ |
+ ( <DAY> | <SQL_TSI_DAY> )
+ {
+ symbol = TimestampInterval.DAY;
+ }
+ |
+ (<WEEK> | <SQL_TSI_WEEK> )
+ {
+ symbol = TimestampInterval.WEEK;
+ }
+ |
+ ( <MONTH> | <SQL_TSI_MONTH> )
+ {
+ symbol = TimestampInterval.MONTH;
+ }
+ |
+ ( <QUARTER> | <SQL_TSI_QUARTER> )
+ {
+ symbol = TimestampInterval.QUARTER;
+ }
+ |
+ ( <YEAR> | <SQL_TSI_YEAR> )
+ {
+ symbol = TimestampInterval.YEAR;
+ }
+ )
+ {
+ return SqlLiteral.createSymbol(symbol, getPos());
+ }
+}
+
+
+
/**
* Parses a dynamic parameter marker.
*/
@@ -4143,6 +4202,50 @@ SqlNode BuiltinFunctionCall() :
}
)
|
+ (
+ <TIMESTAMPADD>
+ {
+ pos = getPos();
+ SqlLiteral interval;
+ }
+ <LPAREN>
+ interval = TimestampInterval()
+ { args = startList(interval); }
+ <COMMA>
+ e = Expression(ExprContext.ACCEPT_SUBQUERY)
+ { args.add(e); }
+ <COMMA>
+ e = Expression(ExprContext.ACCEPT_SUBQUERY)
+ { args.add(e); }
+ <RPAREN>
+ {
+ return SqlStdOperatorTable.TIMESTAMP_ADD.createCall(
+ pos, SqlParserUtil.toNodeArray(args));
+ }
+ )
+ |
+ (
+ <TIMESTAMPDIFF>
+ {
+ pos = getPos();
+ SqlLiteral interval;
+ }
+ <LPAREN>
+ interval = TimestampInterval()
+ { args = startList(interval); }
+ <COMMA>
+ e = Expression(ExprContext.ACCEPT_SUBQUERY)
+ { args.add(e); }
+ <COMMA>
+ e = Expression(ExprContext.ACCEPT_SUBQUERY)
+ { args.add(e); }
+ <RPAREN>
+ {
+ return SqlStdOperatorTable.TIMESTAMP_DIFF.createCall(
+ pos, SqlParserUtil.toNodeArray(args));
+ }
+ )
+ |
{
SqlNode node;
}
@@ -4810,6 +4913,7 @@ SqlPostfixOperator PostfixRowOperator() :
| < FOREIGN: "FOREIGN" >
| < FORTRAN: "FORTRAN" >
| < FOUND: "FOUND" >
+ | < FRAC_SECOND: "FRAC_SECOND" >
| < FREE: "FREE" >
| < FROM: "FROM" >
| < FULL: "FULL" >
@@ -4892,6 +4996,7 @@ SqlPostfixOperator PostfixRowOperator() :
| < MESSAGE_OCTET_LENGTH: "MESSAGE_OCTET_LENGTH" >
| < MESSAGE_TEXT: "MESSAGE_TEXT" >
| < METHOD: "METHOD" >
+ | < MICROSECOND: "MICROSECOND" >
| < MIN: "MIN" >
| < MINUTE: "MINUTE" >
| < MINVALUE: "MINVALUE" >
@@ -4975,6 +5080,7 @@ SqlPostfixOperator PostfixRowOperator() :
| < PRIVILEGES: "PRIVILEGES" >
| < PROCEDURE: "PROCEDURE" >
| < PUBLIC: "PUBLIC" >
+ | < QUARTER: "QUARTER" >
| < RANGE: "RANGE" >
| < RANK: "RANK" >
| < READ: "READ" >
@@ -5057,6 +5163,16 @@ SqlPostfixOperator PostfixRowOperator() :
| < SQLEXCEPTION: "SQLEXCEPTION" >
| < SQLSTATE: "SQLSTATE" >
| < SQLWARNING: "SQLWARNING" >
+ | < SQL_TSI_DAY: "SQL_TSI_DAY" >
+ | < SQL_TSI_FRAC_SECOND: "SQL_TSI_FRAC_SECOND" >
+ | < SQL_TSI_HOUR: "SQL_TSI_HOUR" >
+ | < SQL_TSI_MICROSECOND: "SQL_TSI_MICROSECOND" >
+ | < SQL_TSI_MINUTE: "SQL_TSI_MINUTE" >
+ | < SQL_TSI_MONTH: "SQL_TSI_MONTH" >
+ | < SQL_TSI_QUARTER: "SQL_TSI_QUARTER" >
+ | < SQL_TSI_SECOND: "SQL_TSI_SECOND" >
+ | < SQL_TSI_WEEK: "SQL_TSI_WEEK" >
+ | < SQL_TSI_YEAR: "SQL_TSI_YEAR" >
| < SQRT: "SQRT" >
| < START: "START" >
| < STATE: "STATE" >
@@ -5083,6 +5199,8 @@ SqlPostfixOperator PostfixRowOperator() :
| < TIES: "TIES" >
| < TIME: "TIME" >
| < TIMESTAMP: "TIMESTAMP" >
+ | < TIMESTAMPADD: "TIMESTAMPADD" >
+ | < TIMESTAMPDIFF: "TIMESTAMPDIFF" >
| < TIMEZONE_HOUR: "TIMEZONE_HOUR" >
| < TIMEZONE_MINUTE: "TIMEZONE_MINUTE" >
| < TINYINT: "TINYINT" >
@@ -5133,6 +5251,7 @@ SqlPostfixOperator PostfixRowOperator() :
| < VARYING: "VARYING" >
| < VERSION: "VERSION" >
| < VIEW: "VIEW" >
+ | < WEEK: "WEEK" >
| < WHEN: "WHEN" >
| < WHENEVER: "WHENEVER" >
| < WHERE: "WHERE" >
@@ -5254,6 +5373,7 @@ String CommonNonReservedKeyWord() :
| <FOLLOWING>
| <FORTRAN>
| <FOUND>
+ | <FRAC_SECOND>
| <G>
| <GENERAL>
| <GENERATED>
@@ -5286,6 +5406,7 @@ String CommonNonReservedKeyWord() :
| <MAP>
| <MATCHED>
| <MAXVALUE>
+ | <MICROSECOND>
| <MESSAGE_LENGTH>
| <MESSAGE_OCTET_LENGTH>
| <MESSAGE_TEXT>
@@ -5327,6 +5448,7 @@ String CommonNonReservedKeyWord() :
| <PRIOR>
| <PRIVILEGES>
| <PUBLIC>
+ | <QUARTER>
| <READ>
| <RELATIVE>
| <REPEATABLE>
@@ -5362,6 +5484,16 @@ String CommonNonReservedKeyWord() :
| <SOURCE>
| <SPACE>
| <SPECIFIC_NAME>
+ | <SQL_TSI_DAY>
+ | <SQL_TSI_FRAC_SECOND>
+ | <SQL_TSI_HOUR>
+ | <SQL_TSI_MICROSECOND>
+ | <SQL_TSI_MINUTE>
+ | <SQL_TSI_MONTH>
+ | <SQL_TSI_QUARTER>
+ | <SQL_TSI_SECOND>
+ | <SQL_TSI_WEEK>
+ | <SQL_TSI_YEAR>
| <STATE>
| <STATEMENT>
| <STRUCTURE>
@@ -5371,6 +5503,8 @@ String CommonNonReservedKeyWord() :
| <TABLE_NAME>
| <TEMPORARY>
| <TIES>
+ | <TIMESTAMPADD>
+ | <TIMESTAMPDIFF>
| <TOP_LEVEL_COUNT>
| <TRANSACTION>
| <TRANSACTIONS_ACTIVE>
@@ -5393,6 +5527,7 @@ String CommonNonReservedKeyWord() :
| <USER_DEFINED_TYPE_SCHEMA>
| <VERSION>
| <VIEW>
+ | <WEEK>
| <WRAPPER>
| <WORK>
| <WRITE>
http://git-wip-us.apache.org/repos/asf/calcite/blob/0b9ea986/core/src/main/java/org/apache/calcite/sql/TimestampInterval.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/TimestampInterval.java b/core/src/main/java/org/apache/calcite/sql/TimestampInterval.java
new file mode 100644
index 0000000..d586d4a
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/sql/TimestampInterval.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.sql;
+
+import org.apache.calcite.sql.parser.SqlParserPos;
+
+/**
+ * Enumerates the timestamp intervals.
+ */
+public enum TimestampInterval implements SqlLiteral.SqlSymbol {
+
+ MICROSECOND,
+ SECOND,
+ MINUTE,
+ HOUR,
+ DAY,
+ WEEK,
+ MONTH,
+ QUARTER,
+ YEAR;
+
+ /**
+ * Creates a parse-tree node representing an occurrence of this
+ * condition type keyword at a particular position in the parsed
+ * text.
+ */
+ public SqlLiteral symbol(SqlParserPos pos) {
+ return SqlLiteral.createSymbol(this, pos);
+ }
+
+}
+
+// End TimestampInterval.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/0b9ea986/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
index ece34a5..98d2e85 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
@@ -46,6 +46,7 @@ import org.apache.calcite.sql.type.InferTypes;
import org.apache.calcite.sql.type.OperandTypes;
import org.apache.calcite.sql.type.ReturnTypes;
import org.apache.calcite.sql.type.SqlOperandCountRanges;
+import org.apache.calcite.sql.type.SqlTypeFamily;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.sql.util.ReflectiveSqlOperatorTable;
import org.apache.calcite.sql.validate.SqlModality;
@@ -1315,6 +1316,68 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
new SqlCurrentDateFunction();
/**
+ * <p>Timestamp modifying or calculating difference functions.
+ * As first parameter take timestamp interval.
+ * </p>
+ *
+ * <p>Interval can one of the following literals:<br>
+ * <i>FRAC_SECOND, MICROSECOND, SQL_TSI_FRAC_SECOND, SQL_TSI_MICROSECOND</i><br>
+ * <i>SECOND, SQL_TSI_SECOND</i><br>
+ * <i>MINUTE, SQL_TSI_MINUTE</i><br>
+ * <i>HOUR, SQL_TSI_HOUR</i><br>
+ * <i>DAY, SQL_TSI_DAY</i><br>
+ * <i>WEEK, SQL_TSI_WEEK</i><br>
+ * <i>MONTH, SQL_TSI_MONTH</i><br>
+ * <i>QUARTER, SQL_TSI_QUARTER</i><br>
+ * <i>YEAR, SQL_TSI_YEAR</i><br>
+ * </p>
+ */
+
+ /**
+ * <p>The SQL <code>TIMESTAMP_ADD</code> function.
+ * Adds interval to timestamp.</p>
+ *
+ * <p>The SQL syntax is
+ *
+ * <blockquote>
+ * <code>TIMESTAMP_ADD(<i>timestamp interval</i>,<i>quantity</i>,<i>timestamp</i>)</code>
+ * </blockquote><br>
+ *
+ * Returns modified timestamp.</p>
+ */
+ public static final SqlFunction TIMESTAMP_ADD =
+ new SqlFunction(
+ "TIMESTAMPADD",
+ SqlKind.OTHER_FUNCTION,
+ ReturnTypes.ARG2,
+ null,
+ OperandTypes.family(
+ SqlTypeFamily.ANY, SqlTypeFamily.INTEGER, SqlTypeFamily.DATETIME),
+ SqlFunctionCategory.TIMEDATE);
+
+ /**
+ * <p>The SQL <code>TIMESTAMP_DIFF</code> function.
+ * Calculates difference between two timestamps.</p>
+ *
+ * <p>The SQL syntax is
+ *
+ * <blockquote>
+ * <code>TIMESTAMP_DIFF(<i>timestamp interval</i>,<i>timestamp</i>,<i>timestamp</i>)</code>
+ * </blockquote><br>
+ *
+ * Returns difference between two timestamps in indicated timestamp interval.</p>
+ */
+ public static final SqlFunction TIMESTAMP_DIFF = new SqlFunction(
+ "TIMESTAMPDIFF",
+ SqlKind.OTHER_FUNCTION,
+ ReturnTypes.INTEGER_NULLABLE,
+ null,
+ OperandTypes.family(
+ SqlTypeFamily.ANY, SqlTypeFamily.DATETIME, SqlTypeFamily.DATETIME),
+ SqlFunctionCategory.TIMEDATE);
+
+
+ /**
* Use of the <code>IN_FENNEL</code> operator forces the argument to be
* evaluated in Fennel. Otherwise acts as identity function.
*/
http://git-wip-us.apache.org/repos/asf/calcite/blob/0b9ea986/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
index 31dbd58..858e8a0 100644
--- a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
@@ -29,6 +29,9 @@ import org.apache.calcite.util.ConversionUtil;
import org.apache.calcite.util.TestUtil;
import org.apache.calcite.util.Util;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
import org.junit.Ignore;
import org.junit.Test;
@@ -39,7 +42,10 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
import java.util.Locale;
+import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
@@ -5525,6 +5531,41 @@ public class SqlParserTest {
"CAST(INTERVAL '3-2' YEAR TO MONTH AS CHAR(5))");
}
+ @Test public void testTimestampAddAndDiff() {
+ Map<String, List<String>> tsi = ImmutableMap.<String, List<String>>builder()
+ .put("MICROSECOND",
+ Arrays.asList("FRAC_SECOND", "MICROSECOND",
+ "SQL_TSI_FRAC_SECOND", "SQL_TSI_MICROSECOND"))
+ .put("SECOND", Arrays.asList("SECOND", "SQL_TSI_SECOND"))
+ .put("MINUTE", Arrays.asList("MINUTE", "SQL_TSI_MINUTE"))
+ .put("HOUR", Arrays.asList("HOUR", "SQL_TSI_HOUR"))
+ .put("DAY", Arrays.asList("DAY", "SQL_TSI_DAY"))
+ .put("WEEK", Arrays.asList("WEEK", "SQL_TSI_WEEK"))
+ .put("MONTH", Arrays.asList("MONTH", "SQL_TSI_MONTH"))
+ .put("QUARTER", Arrays.asList("QUARTER", "SQL_TSI_QUARTER"))
+ .put("YEAR", Arrays.asList("YEAR", "SQL_TSI_YEAR"))
+ .build();
+
+ List<String> functions = ImmutableList.<String>builder()
+ .add("timestampadd(%1$s, 12, %2$scurrent_timestamp%2$s)")
+ .add("timestampdiff(%1$s, %2$scurrent_timestamp%2$s, %2$scurrent_timestamp%2$s)")
+ .build();
+
+ for (Map.Entry<String, List<String>> intervalGroup : tsi.entrySet()) {
+ for (String function : functions) {
+ for (String interval : intervalGroup.getValue()) {
+ checkExp(String.format(function, interval, ""),
+ String.format(function, intervalGroup.getKey(), "`").toUpperCase());
+ }
+ }
+ }
+
+ checkExpFails("timestampadd(^incorrect^, 1, current_timestamp)",
+ "(?s).*Was expecting one of.*");
+ checkExpFails("timestampdiff(^incorrect^, current_timestamp, current_timestamp)",
+ "(?s).*Was expecting one of.*");
+ }
+
@Test public void testUnnest() {
check(
"select*from unnest(x)",
http://git-wip-us.apache.org/repos/asf/calcite/blob/0b9ea986/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
index 81bfeed..48311dd 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
@@ -4599,6 +4599,21 @@ public abstract class SqlOperatorBaseTest {
"floor(cast(null as interval year))");
}
+ @Test public void testTimestampAddAdnDiff() {
+ if (!enable) {
+ return;
+ }
+ tester.checkScalar(
+ "timestampadd(MINUTE, 2, timestamp '2016-02-24 12:42:25')",
+ "2016-02-24 12:42:27",
+ "TIMESTAMP(0) NOT NULL");
+ tester.checkScalar(
+ "timestampdiff(YEAR, "
+ + "timestamp '2014-02-24 12:42:25', "
+ + "timestamp '2016-02-24 12:42:25')",
+ "2", "INTEGER NOT NULL");
+ }
+
@Test public void testDenseRankFunc() {
tester.setFor(
SqlStdOperatorTable.DENSE_RANK, VM_FENNEL, VM_JAVA);
http://git-wip-us.apache.org/repos/asf/calcite/blob/0b9ea986/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index b3a8699..c8ba8e9 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -3589,6 +3589,54 @@ public class SqlValidatorTest extends SqlValidatorTestCase {
"(?s).*Cannot apply '/' to arguments of type '<DECIMAL.4, 3.> / <INTERVAL DAY TO SECOND>'.*");
}
+ @Test public void testTimestampAddAndDiff() {
+ List<String> tsi = ImmutableList.<String>builder()
+ .add("FRAC_SECOND")
+ .add("MICROSECOND")
+ .add("MINUTE")
+ .add("HOUR")
+ .add("DAY")
+ .add("WEEK")
+ .add("MONTH")
+ .add("QUARTER")
+ .add("YEAR")
+ .add("SQL_TSI_FRAC_SECOND")
+ .add("SQL_TSI_MICROSECOND")
+ .add("SQL_TSI_MINUTE")
+ .add("SQL_TSI_HOUR")
+ .add("SQL_TSI_DAY")
+ .add("SQL_TSI_WEEK")
+ .add("SQL_TSI_MONTH")
+ .add("SQL_TSI_QUARTER")
+ .add("SQL_TSI_YEAR")
+ .build();
+
+ List<String> functions = ImmutableList.<String>builder()
+ .add("timestampadd(%s, 12, current_timestamp)")
+ .add("timestampdiff(%s, current_timestamp, current_timestamp)")
+ .build();
+
+ for (String interval : tsi) {
+ for (String function : functions) {
+ checkExp(String.format(function, interval));
+ }
+ }
+
+ checkExpType(
+ "timestampadd(SQL_TSI_WEEK, 2, current_timestamp)", "TIMESTAMP(0) NOT NULL");
+ checkExpType(
+ "timestampadd(SQL_TSI_WEEK, 2, cast(null as timestamp))", "TIMESTAMP(0)");
+ checkExpType(
+ "timestampdiff(SQL_TSI_WEEK, current_timestamp, current_timestamp)", "INTEGER NOT NULL");
+ checkExpType(
+ "timestampdiff(SQL_TSI_WEEK, cast(null as timestamp), current_timestamp)", "INTEGER");
+
+ checkWholeExpFails("timestampadd(incorrect, 1, current_timestamp)",
+ "(?s).*Was expecting one of.*");
+ checkWholeExpFails("timestampdiff(incorrect, current_timestamp, current_timestamp)",
+ "(?s).*Was expecting one of.*");
+ }
+
@Test public void testNumericOperators() {
// unary operator
checkExpType("- cast(1 as TINYINT)", "TINYINT NOT NULL");
http://git-wip-us.apache.org/repos/asf/calcite/blob/0b9ea986/site/_docs/reference.md
----------------------------------------------------------------------
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index 7bc9bc3..8785bd5 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -379,6 +379,7 @@ FOLLOWING,
**FOREIGN**,
FORTRAN,
FOUND,
+FRAC_SECOND,
**FREE**,
**FROM**,
**FULL**,
@@ -461,6 +462,7 @@ MESSAGE_LENGTH,
MESSAGE_OCTET_LENGTH,
MESSAGE_TEXT,
**METHOD**,
+MICROSECOND,
**MIN**,
**MINUTE**,
MINVALUE,
@@ -544,6 +546,7 @@ PRIOR,
PRIVILEGES,
**PROCEDURE**,
PUBLIC,
+QUARTER,
**RANGE**,
**RANK**,
READ,
@@ -626,6 +629,16 @@ SPECIFIC_NAME,
**SQLEXCEPTION**,
**SQLSTATE**,
**SQLWARNING**,
+SQL_TSI_DAY,
+SQL_TSI_FRAC_SECOND,
+SQL_TSI_HOUR,
+SQL_TSI_MICROSECOND,
+SQL_TSI_MINUTE,
+SQL_TSI_MONTH,
+SQL_TSI_QUARTER,
+SQL_TSI_SECOND,
+SQL_TSI_WEEK,
+SQL_TSI_YEAR,
**SQRT**,
**START**,
STATE,
@@ -652,6 +665,8 @@ TEMPORARY,
TIES,
**TIME**,
**TIMESTAMP**,
+TIMESTAMPADD,
+TIMESTAMPDIFF,
**TIMEZONE_HOUR**,
**TIMEZONE_MINUTE**,
**TINYINT**,
@@ -702,6 +717,7 @@ USER_DEFINED_TYPE_SCHEMA,
**VAR_SAMP**,
VERSION,
VIEW,
+WEEK,
**WHEN**,
**WHENEVER**,
**WHERE**,
[5/5] calcite git commit: Further to [CALCITE-1124],
add implementation of TIMESTAMPADD, TIMESTAMPDIFF
Posted by jh...@apache.org.
Further to [CALCITE-1124], add implementation of TIMESTAMPADD, TIMESTAMPDIFF
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/4ac82a30
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/4ac82a30
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/4ac82a30
Branch: refs/heads/master
Commit: 4ac82a30b8ee7ae1afcd83c6f3ef687761536f2e
Parents: 0b9ea98
Author: Julian Hyde <jh...@apache.org>
Authored: Mon Mar 7 21:23:34 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 7 21:26:49 2016 -0800
----------------------------------------------------------------------
core/src/main/codegen/templates/Parser.jj | 224 +++++++-------
.../calcite/adapter/enumerable/RexImpTable.java | 10 +-
.../apache/calcite/sql/SqlJdbcFunctionCall.java | 294 ++++++++-----------
.../java/org/apache/calcite/sql/SqlKind.java | 11 +
.../apache/calcite/sql/TimestampInterval.java | 47 ---
.../calcite/sql/fun/SqlStdOperatorTable.java | 88 +++---
.../sql2rel/StandardConvertletTable.java | 72 ++++-
.../calcite/sql/parser/SqlParserTest.java | 18 ++
.../calcite/sql/test/SqlOperatorBaseTest.java | 64 ++--
.../org/apache/calcite/sql/test/SqlTests.java | 90 +-----
.../apache/calcite/test/SqlValidatorTest.java | 7 +-
site/_docs/reference.md | 37 +--
site/community/index.md | 1 +
13 files changed, 452 insertions(+), 511 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/core/src/main/codegen/templates/Parser.jj
----------------------------------------------------------------------
diff --git a/core/src/main/codegen/templates/Parser.jj b/core/src/main/codegen/templates/Parser.jj
index 01c35bb..c1df4cb 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -82,7 +82,6 @@ import org.apache.calcite.sql.SqlUtil;
import org.apache.calcite.sql.SqlWindow;
import org.apache.calcite.sql.SqlWith;
import org.apache.calcite.sql.SqlWithItem;
-import org.apache.calcite.sql.TimestampInterval;
import org.apache.calcite.sql.fun.SqlCase;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.fun.SqlTrimFunction;
@@ -3439,60 +3438,29 @@ TimeUnit TimeUnit() :
}
}
-SqlLiteral TimestampInterval() :
-{
-SqlLiteral.SqlSymbol symbol = null;
-}
+TimeUnit TimestampInterval() :
+{}
{
- (
- ( <FRAC_SECOND> | <MICROSECOND> | <SQL_TSI_FRAC_SECOND> | <SQL_TSI_MICROSECOND> )
- {
- symbol = TimestampInterval.MICROSECOND;
- }
- |
- ( <SECOND> | <SQL_TSI_SECOND> )
- {
- symbol = TimestampInterval.SECOND;
- }
- |
- ( <MINUTE> | <SQL_TSI_MINUTE> )
- {
- symbol = TimestampInterval.MINUTE;
- }
- |
- ( <HOUR> | <SQL_TSI_HOUR> )
- {
- symbol = TimestampInterval.HOUR;
- }
- |
- ( <DAY> | <SQL_TSI_DAY> )
- {
- symbol = TimestampInterval.DAY;
- }
- |
- (<WEEK> | <SQL_TSI_WEEK> )
- {
- symbol = TimestampInterval.WEEK;
- }
- |
- ( <MONTH> | <SQL_TSI_MONTH> )
- {
- symbol = TimestampInterval.MONTH;
- }
- |
- ( <QUARTER> | <SQL_TSI_QUARTER> )
- {
- symbol = TimestampInterval.QUARTER;
- }
- |
- ( <YEAR> | <SQL_TSI_YEAR> )
- {
- symbol = TimestampInterval.YEAR;
- }
- )
- {
- return SqlLiteral.createSymbol(symbol, getPos());
- }
+ <FRAC_SECOND> { return TimeUnit.MICROSECOND; }
+| <MICROSECOND> { return TimeUnit.MICROSECOND; }
+| <SQL_TSI_FRAC_SECOND> { return TimeUnit.MICROSECOND; }
+| <SQL_TSI_MICROSECOND> { return TimeUnit.MICROSECOND; }
+| <SECOND> { return TimeUnit.SECOND; }
+| <SQL_TSI_SECOND> { return TimeUnit.SECOND; }
+| <MINUTE> { return TimeUnit.MINUTE; }
+| <SQL_TSI_MINUTE> { return TimeUnit.MINUTE; }
+| <HOUR> { return TimeUnit.HOUR; }
+| <SQL_TSI_HOUR> { return TimeUnit.HOUR; }
+| <DAY> { return TimeUnit.DAY; }
+| <SQL_TSI_DAY> { return TimeUnit.DAY; }
+| <WEEK> { return TimeUnit.WEEK; }
+| <SQL_TSI_WEEK> { return TimeUnit.WEEK; }
+| <MONTH> { return TimeUnit.MONTH; }
+| <SQL_TSI_MONTH> { return TimeUnit.MONTH; }
+| <QUARTER> { return TimeUnit.QUARTER; }
+| <SQL_TSI_QUARTER> { return TimeUnit.QUARTER; }
+| <YEAR> { return TimeUnit.YEAR; }
+| <SQL_TSI_YEAR> { return TimeUnit.YEAR; }
}
@@ -3962,6 +3930,8 @@ SqlNode BuiltinFunctionCall() :
SqlParserPos starPos;
SqlParserPos namePos;
SqlDataTypeSpec dt;
+ TimeUnit interval;
+ SqlNode node;
}
{
//~ FUNCTIONS WITH SPECIAL SYNTAX ---------------------------------------
@@ -4202,56 +4172,68 @@ SqlNode BuiltinFunctionCall() :
}
)
|
- (
- <TIMESTAMPADD>
- {
- pos = getPos();
- SqlLiteral interval;
- }
- <LPAREN>
- interval = TimestampInterval()
- { args = startList(interval); }
- <COMMA>
- e = Expression(ExprContext.ACCEPT_SUBQUERY)
- { args.add(e); }
- <COMMA>
- e = Expression(ExprContext.ACCEPT_SUBQUERY)
- { args.add(e); }
- <RPAREN>
- {
- return SqlStdOperatorTable.TIMESTAMP_ADD.createCall(
- pos, SqlParserUtil.toNodeArray(args));
- }
- )
+ node = TimestampAddFunctionCall() { return node; }
|
- (
- <TIMESTAMPDIFF>
- {
- pos = getPos();
- SqlLiteral interval;
- }
- <LPAREN>
- interval = TimestampInterval()
- { args = startList(interval); }
- <COMMA>
- e = Expression(ExprContext.ACCEPT_SUBQUERY)
- { args.add(e); }
- <COMMA>
- e = Expression(ExprContext.ACCEPT_SUBQUERY)
- { args.add(e); }
- <RPAREN>
- {
- return SqlStdOperatorTable.TIMESTAMP_DIFF.createCall(
- pos, SqlParserUtil.toNodeArray(args));
- }
- )
+ node = TimestampDiffFunctionCall() { return node; }
|
- {
- SqlNode node;
+ node = ExtendedBuiltinFunctionCall() { return node; }
+}
+
+/**
+ * Parses a call to TIMESTAMPADD.
+ */
+SqlCall TimestampAddFunctionCall() :
+{
+ List<SqlNode> args;
+ SqlNode e;
+ SqlParserPos pos;
+ TimeUnit interval;
+ SqlNode node;
+}
+{
+ <TIMESTAMPADD> {
+ pos = getPos();
}
- node = ExtendedBuiltinFunctionCall()
- {
- return node;
+ <LPAREN>
+ interval = TimestampInterval() {
+ args = startList(SqlLiteral.createSymbol(interval, getPos()));
+ }
+ <COMMA>
+ e = Expression(ExprContext.ACCEPT_SUBQUERY) { args.add(e); }
+ <COMMA>
+ e = Expression(ExprContext.ACCEPT_SUBQUERY) { args.add(e); }
+ <RPAREN> {
+ return SqlStdOperatorTable.TIMESTAMP_ADD.createCall(
+ pos.plus(getPos()), SqlParserUtil.toNodeArray(args));
+ }
+}
+
+/**
+ * Parses a call to TIMESTAMPDIFF.
+ */
+SqlCall TimestampDiffFunctionCall() :
+{
+ List<SqlNode> args;
+ SqlNode e;
+ SqlParserPos pos;
+ TimeUnit interval;
+ SqlNode node;
+}
+{
+ <TIMESTAMPDIFF> {
+ pos = getPos();
+ }
+ <LPAREN>
+ interval = TimestampInterval() {
+ args = startList(SqlLiteral.createSymbol(interval, getPos()));
+ }
+ <COMMA>
+ e = Expression(ExprContext.ACCEPT_SUBQUERY) { args.add(e); }
+ <COMMA>
+ e = Expression(ExprContext.ACCEPT_SUBQUERY) { args.add(e); }
+ <RPAREN> {
+ return SqlStdOperatorTable.TIMESTAMP_DIFF.createCall(
+ pos.plus(getPos()), SqlParserUtil.toNodeArray(args));
}
}
@@ -4529,25 +4511,37 @@ SqlNode JdbcFunctionCall() :
String name;
SqlIdentifier id;
SqlNodeList args;
+ SqlCall call;
SqlParserPos pos;
SqlParserPos starPos;
}
{
+ <LBRACE_FN>
+ {
+ pos = getPos();
+ }
(
- <LBRACE_FN>
- {
- pos = getPos();
+ LOOKAHEAD(1)
+ call = TimestampAddFunctionCall() {
+ name = call.getOperator().getName();
+ args = new SqlNodeList(call.getOperandList(), getPos());
+ }
+ |
+ call = TimestampDiffFunctionCall() {
+ name = call.getOperator().getName();
+ args = new SqlNodeList(call.getOperandList(), getPos());
}
+ |
(
// INSERT is a reserved word, but we need to handle {fn insert}
<INSERT> { name = unquotedIdentifier(); }
- |
+ |
// For cases like {fn power(1,2)} and {fn lower('a')}
id = ReservedFunctionName() { name = id.getSimple(); }
- |
+ |
// For cases like {fn substring('foo', 1,2)}
name = NonReservedJdbcFunctionName()
- |
+ |
name = Identifier()
)
(
@@ -4556,16 +4550,16 @@ SqlNode JdbcFunctionCall() :
args = new SqlNodeList(starPos);
args.add(SqlIdentifier.star(starPos));
}
- | LOOKAHEAD(2) <LPAREN> <RPAREN>
- { args = new SqlNodeList(pos); }
- | args = ParenthesizedQueryOrCommaList(ExprContext.ACCEPT_SUBQUERY)
+ |
+ LOOKAHEAD(2) <LPAREN> <RPAREN> { args = new SqlNodeList(pos); }
+ |
+ args = ParenthesizedQueryOrCommaList(ExprContext.ACCEPT_SUBQUERY)
)
- <RBRACE>
- {
- return new SqlJdbcFunctionCall(name).createCall(
- pos.plus(getPos()), SqlParserUtil.toNodeArray(args));
- }
)
+ <RBRACE> {
+ return new SqlJdbcFunctionCall(name).createCall(
+ pos.plus(getPos()), SqlParserUtil.toNodeArray(args));
+ }
}
/**
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index 2633490..e03f6b8 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -142,6 +142,7 @@ import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MAP_VALUE_CONSTRUCT
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MAX;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MIN;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MINUS;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MINUS_DATE;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MOD;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.MULTIPLY;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.NEXT_VALUE;
@@ -245,6 +246,8 @@ public class RexImpTable {
// datetime
defineImplementor(DATETIME_PLUS, NullPolicy.STRICT,
new DatetimeArithmeticImplementor(), false);
+ defineImplementor(MINUS_DATE, NullPolicy.STRICT,
+ new DatetimeArithmeticImplementor(), false);
defineMethod(EXTRACT_DATE, BuiltInMethod.UNIX_DATE_EXTRACT.method,
NullPolicy.STRICT);
defineImplementor(FLOOR, NullPolicy.STRICT,
@@ -1930,7 +1933,12 @@ public class RexImpTable {
trop1 = Expressions.convert_(trop1, int.class);
break;
}
- return Expressions.add(trop0, trop1);
+ switch (call.getKind()) {
+ case MINUS:
+ return Expressions.subtract(trop0, trop1);
+ default:
+ return Expressions.add(trop0, trop1);
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/core/src/main/java/org/apache/calcite/sql/SqlJdbcFunctionCall.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlJdbcFunctionCall.java b/core/src/main/java/org/apache/calcite/sql/SqlJdbcFunctionCall.java
index f6849b7..77bb478 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlJdbcFunctionCall.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlJdbcFunctionCall.java
@@ -23,9 +23,10 @@ import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.type.OperandTypes;
import org.apache.calcite.sql.validate.SqlValidator;
import org.apache.calcite.sql.validate.SqlValidatorScope;
-import org.apache.calcite.util.Util;
-import java.util.HashMap;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+
import java.util.Map;
import static org.apache.calcite.util.Static.RESOURCE;
@@ -435,13 +436,13 @@ public class SqlJdbcFunctionCall extends SqlFunction {
public SqlCall getLookupCall() {
if (null == lookupCall) {
lookupCall =
- lookupMakeCallObj.createCall(thisOperands, SqlParserPos.ZERO);
+ lookupMakeCallObj.createCall(SqlParserPos.ZERO, thisOperands);
}
return lookupCall;
}
public String getAllowedSignatures(String name) {
- return lookupMakeCallObj.operator.getAllowedSignatures(name);
+ return lookupMakeCallObj.getOperator().getAllowedSignatures(name);
}
public RelDataType deriveType(
@@ -470,37 +471,25 @@ public class SqlJdbcFunctionCall extends SqlFunction {
RESOURCE.functionUndefined(getName()));
}
- if (!lookupMakeCallObj.checkNumberOfArg(opBinding.getOperandCount())) {
+ final String message = lookupMakeCallObj.isValidArgCount(callBinding);
+ if (message != null) {
throw callBinding.newValidationError(
RESOURCE.wrongNumberOfParam(getName(), thisOperands.length,
- getArgCountMismatchMsg()));
+ message));
}
- if (!lookupMakeCallObj.operator.checkOperandTypes(
- new SqlCallBinding(
- callBinding.getValidator(),
- callBinding.getScope(),
- getLookupCall()),
- false)) {
+ final SqlCall newCall = getLookupCall();
+ final SqlCallBinding newBinding =
+ new SqlCallBinding(callBinding.getValidator(), callBinding.getScope(),
+ newCall);
+
+ final SqlOperator operator = lookupMakeCallObj.getOperator();
+ if (!operator.checkOperandTypes(newBinding, false)) {
throw callBinding.newValidationSignatureError();
}
- return lookupMakeCallObj.operator.validateOperands(
- callBinding.getValidator(),
- callBinding.getScope(),
- getLookupCall());
- }
- private String getArgCountMismatchMsg() {
- StringBuilder ret = new StringBuilder();
- int[] possible = lookupMakeCallObj.getPossibleArgCounts();
- for (int i = 0; i < possible.length; i++) {
- if (i > 0) {
- ret.append(" or ");
- }
- ret.append(possible[i]);
- }
- ret.append(" parameter(s)");
- return ret.toString();
+ return operator.validateOperands(callBinding.getValidator(),
+ callBinding.getScope(), newCall);
}
public void unparse(
@@ -549,59 +538,84 @@ public class SqlJdbcFunctionCall extends SqlFunction {
//~ Inner Classes ----------------------------------------------------------
- /**
- * Represent a Strategy Object to create a {@link SqlCall} by providing the
- * feature of reording, adding/dropping operands.
- */
- private static class MakeCall {
- final SqlOperator operator;
- final int[] order;
-
+ /** Converts a call to a JDBC function to a call to a regular function. */
+ private interface MakeCall {
/**
- * List of the possible numbers of operands this function can take.
+ * Creates and return a {@link SqlCall}. If the MakeCall strategy object
+ * was created with a reording specified the call will be created with
+ * the operands reordered, otherwise no change of ordering is applied
+ *
+ * @param operands Operands
*/
- final int[] argCounts;
+ SqlCall createCall(SqlParserPos pos, SqlNode... operands);
+
+ SqlOperator getOperator();
+
+ String isValidArgCount(SqlCallBinding binding);
+ }
- private MakeCall(
- SqlOperator operator,
- int argCount) {
+ /** Converter that calls a built-in function with the same arguments. */
+ public static class SimpleMakeCall implements SqlJdbcFunctionCall.MakeCall {
+ final SqlOperator operator;
+
+ public SimpleMakeCall(SqlOperator operator) {
this.operator = operator;
- this.order = null;
- this.argCounts = new int[]{argCount};
}
+ public SqlOperator getOperator() {
+ return operator;
+ }
+
+ public SqlCall createCall(SqlParserPos pos, SqlNode... operands) {
+ return operator.createCall(pos, operands);
+ }
+
+ public String isValidArgCount(SqlCallBinding binding) {
+ return null; // any number of arguments is valid
+ }
+ }
+
+ /** Implementation of {@link MakeCall} that can re-order or ignore operands. */
+ private static class PermutingMakeCall extends SimpleMakeCall {
+ final int[] order;
+
/**
* Creates a MakeCall strategy object with reordering of operands.
*
* <p>The reordering is specified by an int array where the value of
* element at position <code>i</code> indicates to which element in a
* new SqlNode[] array the operand goes.
- *
- * @param operator Operator
+ * @param operator Operator
* @param order Order
- * @pre order != null
- * @pre order[i] < order.length
- * @pre order.length > 0
- * @pre argCounts == order.length
*/
- MakeCall(SqlOperator operator, int argCount, int[] order) {
- assert order != null && order.length > 0;
+ PermutingMakeCall(SqlOperator operator, int[] order) {
+ super(operator);
+ this.order = Preconditions.checkNotNull(order);
+ }
- // Currently operation overloading when reordering is necessary is
- // NOT implemented
- Util.pre(argCount == order.length, "argCounts==order.length");
- this.operator = operator;
- this.order = order;
- this.argCounts = new int[]{order.length};
+ @Override public SqlCall createCall(SqlParserPos pos,
+ SqlNode... operands) {
+ return super.createCall(pos, reorder(operands));
+ }
- // sanity checking ...
- for (int anOrder : order) {
- assert anOrder < order.length;
+ @Override public String isValidArgCount(SqlCallBinding binding) {
+ if (order.length == binding.getOperandCount()) {
+ return null; // operand count is valid
+ } else {
+ return getArgCountMismatchMsg(order.length);
}
}
- final int[] getPossibleArgCounts() {
- return this.argCounts;
+ private String getArgCountMismatchMsg(int... possible) {
+ StringBuilder ret = new StringBuilder();
+ for (int i = 0; i < possible.length; i++) {
+ if (i > 0) {
+ ret.append(" or ");
+ }
+ ret.append(possible[i]);
+ }
+ ret.append(" parameter(s)");
+ return ret.toString();
}
/**
@@ -620,37 +634,6 @@ public class SqlJdbcFunctionCall extends SqlFunction {
}
return newOrder;
}
-
- /**
- * Creates and return a {@link SqlCall}. If the MakeCall strategy object
- * was created with a reording specified the call will be created with
- * the operands reordered, otherwise no change of ordering is applied
- *
- * @param operands Operands
- */
- SqlCall createCall(
- SqlNode[] operands,
- SqlParserPos pos) {
- if (null == order) {
- return operator.createCall(pos, operands);
- }
- return operator.createCall(pos, reorder(operands));
- }
-
- /**
- * Returns false if number of arguments are unexpected, otherwise true.
- * This function is supposed to be called with an {@link SqlNode} array
- * of operands direct from the oven, e.g no reording or adding/dropping
- * of operands...else it would make much sense to have this methods
- */
- boolean checkNumberOfArg(int length) {
- for (int argCount : argCounts) {
- if (argCount == length) {
- return true;
- }
- }
- return false;
- }
}
/**
@@ -663,99 +646,62 @@ public class SqlJdbcFunctionCall extends SqlFunction {
*/
static final JdbcToInternalLookupTable INSTANCE =
new JdbcToInternalLookupTable();
- private final Map<String, MakeCall> map = new HashMap<String, MakeCall>();
+
+ private final Map<String, MakeCall> map;
private JdbcToInternalLookupTable() {
// A table of all functions can be found at
// http://java.sun.com/products/jdbc/driverdevs.html
// which is also provided in the javadoc for this class.
// See also SqlOperatorTests.testJdbcFn, which contains the list.
- map.put(
- "ABS",
- new MakeCall(SqlStdOperatorTable.ABS, 1));
- map.put(
- "EXP",
- new MakeCall(SqlStdOperatorTable.EXP, 1));
- map.put(
- "LOG",
- new MakeCall(SqlStdOperatorTable.LN, 1));
- map.put(
- "LOG10",
- new MakeCall(SqlStdOperatorTable.LOG10, 1));
- map.put(
- "MOD",
- new MakeCall(SqlStdOperatorTable.MOD, 2));
- map.put(
- "POWER",
- new MakeCall(SqlStdOperatorTable.POWER, 2));
-
- map.put(
- "CONCAT",
- new MakeCall(SqlStdOperatorTable.CONCAT, 2));
- map.put(
- "INSERT",
- new MakeCall(
- SqlStdOperatorTable.OVERLAY,
- 4,
- new int[]{0, 2, 3, 1}));
- map.put(
- "LCASE",
- new MakeCall(SqlStdOperatorTable.LOWER, 1));
- map.put(
- "LENGTH",
- new MakeCall(SqlStdOperatorTable.CHARACTER_LENGTH, 1));
- map.put(
- "LOCATE",
- new MakeCall(SqlStdOperatorTable.POSITION, 2));
- map.put(
- "LTRIM",
- new MakeCall(SqlStdOperatorTable.TRIM, 1) {
- @Override SqlCall createCall(
- SqlNode[] operands, SqlParserPos pos) {
+ ImmutableMap.Builder<String, MakeCall> map = ImmutableMap.builder();
+ map.put("ABS", simple(SqlStdOperatorTable.ABS));
+ map.put("EXP", simple(SqlStdOperatorTable.EXP));
+ map.put("LOG", simple(SqlStdOperatorTable.LN));
+ map.put("LOG10", simple(SqlStdOperatorTable.LOG10));
+ map.put("MOD", simple(SqlStdOperatorTable.MOD));
+ map.put("POWER", simple(SqlStdOperatorTable.POWER));
+ map.put("CONCAT", simple(SqlStdOperatorTable.CONCAT));
+ map.put("INSERT",
+ new PermutingMakeCall(SqlStdOperatorTable.OVERLAY, new int[]{0, 2, 3, 1}));
+ map.put("LCASE", simple(SqlStdOperatorTable.LOWER));
+ map.put("LENGTH", simple(SqlStdOperatorTable.CHARACTER_LENGTH));
+ map.put("LOCATE", simple(SqlStdOperatorTable.POSITION));
+ map.put("LTRIM",
+ new SimpleMakeCall(SqlStdOperatorTable.TRIM) {
+ @Override public SqlCall createCall(SqlParserPos pos,
+ SqlNode... operands) {
assert 1 == operands.length;
- return super.createCall(
- new SqlNode[]{
- SqlTrimFunction.Flag.LEADING.symbol(SqlParserPos.ZERO),
- SqlLiteral.createCharString(" ", null),
- operands[0]
- },
- pos);
+ return super.createCall(pos,
+ SqlTrimFunction.Flag.LEADING.symbol(SqlParserPos.ZERO),
+ SqlLiteral.createCharString(" ", null),
+ operands[0]);
}
});
- map.put(
- "QUARTER",
- new MakeCall(SqlStdOperatorTable.QUARTER, 1));
- map.put(
- "RTRIM",
- new MakeCall(SqlStdOperatorTable.TRIM, 1) {
- @Override SqlCall createCall(
- SqlNode[] operands, SqlParserPos pos) {
+ map.put("QUARTER", simple(SqlStdOperatorTable.QUARTER));
+ map.put("RTRIM",
+ new SimpleMakeCall(SqlStdOperatorTable.TRIM) {
+ @Override public SqlCall createCall(SqlParserPos pos,
+ SqlNode... operands) {
assert 1 == operands.length;
- return super.createCall(
- new SqlNode[] {
- SqlTrimFunction.Flag.TRAILING.symbol(SqlParserPos.ZERO),
- SqlLiteral.createCharString(" ", null),
- operands[0]
- },
- pos);
+ return super.createCall(pos,
+ SqlTrimFunction.Flag.TRAILING.symbol(SqlParserPos.ZERO),
+ SqlLiteral.createCharString(" ", null),
+ operands[0]);
}
});
- map.put(
- "SUBSTRING",
- new MakeCall(SqlStdOperatorTable.SUBSTRING, 3));
- map.put(
- "UCASE",
- new MakeCall(SqlStdOperatorTable.UPPER, 1));
-
- map.put(
- "CURDATE",
- new MakeCall(SqlStdOperatorTable.CURRENT_DATE, 0));
- map.put(
- "CURTIME",
- new MakeCall(SqlStdOperatorTable.LOCALTIME, 0));
- map.put(
- "NOW",
- new MakeCall(SqlStdOperatorTable.CURRENT_TIMESTAMP, 0));
+ map.put("SUBSTRING", simple(SqlStdOperatorTable.SUBSTRING));
+ map.put("UCASE", simple(SqlStdOperatorTable.UPPER));
+ map.put("CURDATE", simple(SqlStdOperatorTable.CURRENT_DATE));
+ map.put("CURTIME", simple(SqlStdOperatorTable.LOCALTIME));
+ map.put("NOW", simple(SqlStdOperatorTable.CURRENT_TIMESTAMP));
+ map.put("TIMESTAMPADD", simple(SqlStdOperatorTable.TIMESTAMP_ADD));
+ map.put("TIMESTAMPDIFF", simple(SqlStdOperatorTable.TIMESTAMP_DIFF));
+ this.map = map.build();
+ }
+
+ private MakeCall simple(SqlOperator operator) {
+ return new SimpleMakeCall(operator);
}
/**
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/core/src/main/java/org/apache/calcite/sql/SqlKind.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlKind.java b/core/src/main/java/org/apache/calcite/sql/SqlKind.java
index 7f34162..07d2bca 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlKind.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlKind.java
@@ -361,6 +361,16 @@ public enum SqlKind {
*/
LEAST,
+ /**
+ * The "TIMESTAMP_ADD" function (ODBC, SQL Server, MySQL).
+ */
+ TIMESTAMP_ADD,
+
+ /**
+ * The "TIMESTAMP_DIFF" function (ODBC, SQL Server, MySQL).
+ */
+ TIMESTAMP_DIFF,
+
// prefix operators
/**
@@ -858,6 +868,7 @@ public enum SqlKind {
EnumSet.of(AS, ARGUMENT_ASSIGNMENT, DEFAULT,
DESCENDING, CUBE, ROLLUP, GROUPING_SETS, EXTEND,
SELECT, JOIN, OTHER_FUNCTION, CAST, TRIM, FLOOR, CEIL,
+ TIMESTAMP_ADD, TIMESTAMP_DIFF,
LITERAL_CHAIN, JDBC_FN, PRECEDING, FOLLOWING, ORDER_BY,
NULLS_FIRST, NULLS_LAST, COLLECTION_TABLE, TABLESAMPLE,
VALUES, WITH, WITH_ITEM),
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/core/src/main/java/org/apache/calcite/sql/TimestampInterval.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/TimestampInterval.java b/core/src/main/java/org/apache/calcite/sql/TimestampInterval.java
deleted file mode 100644
index d586d4a..0000000
--- a/core/src/main/java/org/apache/calcite/sql/TimestampInterval.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.sql;
-
-import org.apache.calcite.sql.parser.SqlParserPos;
-
-/**
- * Enumerates the timestamp intervals.
- */
-public enum TimestampInterval implements SqlLiteral.SqlSymbol {
-
- MICROSECOND,
- SECOND,
- MINUTE,
- HOUR,
- DAY,
- WEEK,
- MONTH,
- QUARTER,
- YEAR;
-
- /**
- * Creates a parse-tree node representing an occurrence of this
- * condition type keyword at a particular position in the parsed
- * text.
- */
- public SqlLiteral symbol(SqlParserPos pos) {
- return SqlLiteral.createSymbol(this, pos);
- }
-
-}
-
-// End TimestampInterval.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
index 98d2e85..c075363 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
@@ -1316,66 +1316,66 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
new SqlCurrentDateFunction();
/**
- * <p>Timestamp modifying or calculating difference functions.
- * As first parameter take timestamp interval.
- * </p>
- *
- * <p>Interval can one of the following literals:<br>
- * <i>FRAC_SECOND, MICROSECOND, SQL_TSI_FRAC_SECOND, SQL_TSI_MICROSECOND</i><br>
- * <i>SECOND, SQL_TSI_SECOND</i><br>
- * <i>MINUTE, SQL_TSI_MINUTE</i><br>
- * <i>HOUR, SQL_TSI_HOUR</i><br>
- * <i>DAY, SQL_TSI_DAY</i><br>
- * <i>WEEK, SQL_TSI_WEEK</i><br>
- * <i>MONTH, SQL_TSI_MONTH</i><br>
- * <i>QUARTER, SQL_TSI_QUARTER</i><br>
- * <i>YEAR, SQL_TSI_YEAR</i><br>
- * </p>
- */
-
- /**
- * <p>The SQL <code>TIMESTAMP_ADD</code> function.
- * Adds interval to timestamp.</p>
+ * <p>The <code>TIMESTAMPADD</code> function, which adds an interval to a
+ * timestamp.
*
* <p>The SQL syntax is
*
* <blockquote>
- * <code>TIMESTAMP_ADD(<i>timestamp interval</i>,<i>quantity</i>,<i>timestamp</i>)</code>
- * </blockquote><br>
+ * <code>TIMESTAMPADD(<i>timestamp interval</i>, <i>quantity</i>, <i>timestamp</i>)</code>
+ * </blockquote>
*
- * Returns modified timestamp.</p>
+ * <p>The interval time unit can one of the following literals:<ul>
+ * <li>MICROSECOND (and synonyms SQL_TSI_MICROSECOND, FRAC_SECOND,
+ * SQL_TSI_FRAC_SECOND)
+ * <li>SECOND (and synonym SQL_TSI_SECOND)
+ * <li>MINUTE (and synonym SQL_TSI_MINUTE)
+ * <li>HOUR (and synonym SQL_TSI_HOUR)
+ * <li>DAY (and synonym SQL_TSI_DAY)
+ * <li>WEEK (and synonym SQL_TSI_WEEK)
+ * <li>MONTH (and synonym SQL_TSI_MONTH)
+ * <li>QUARTER (and synonym SQL_TSI_QUARTER)
+ * <li>YEAR (and synonym SQL_TSI_YEAR)
+ * </ul>
+ *
+ * <p>Returns modified timestamp.
*/
public static final SqlFunction TIMESTAMP_ADD =
- new SqlFunction(
- "TIMESTAMPADD",
- SqlKind.OTHER_FUNCTION,
- ReturnTypes.ARG2,
+ new SqlFunction("TIMESTAMPADD", SqlKind.TIMESTAMP_ADD, ReturnTypes.ARG2,
null,
- OperandTypes.family(
- SqlTypeFamily.ANY, SqlTypeFamily.INTEGER, SqlTypeFamily.DATETIME),
- SqlFunctionCategory.TIMEDATE);
+ OperandTypes.family(SqlTypeFamily.ANY, SqlTypeFamily.INTEGER,
+ SqlTypeFamily.DATETIME), SqlFunctionCategory.TIMEDATE);
/**
- * <p>The SQL <code>TIMESTAMP_DIFF</code> function.
- * Calculates difference between two timestamps.</p>
+ * <p>The <code>TIMESTAMPDIFF</code> function, which calculates the difference
+ * between two timestamps.
*
* <p>The SQL syntax is
*
* <blockquote>
- * <code>TIMESTAMP_DIFF(<i>timestamp interval</i>,<i>timestamp</i>,<i>timestamp</i>)</code>
- * </blockquote><br>
+ * <code>TIMESTAMPDIFF(<i>timestamp interval</i>, <i>timestamp</i>, <i>timestamp</i>)</code>
+ * </blockquote>
*
- * Returns difference between two timestamps in indicated timestamp interval.</p>
+ * <p>The interval time unit can one of the following literals:<ul>
+ * <li>MICROSECOND (and synonyms SQL_TSI_MICROSECOND, FRAC_SECOND,
+ * SQL_TSI_FRAC_SECOND)
+ * <li>SECOND (and synonym SQL_TSI_SECOND)
+ * <li>MINUTE (and synonym SQL_TSI_MINUTE)
+ * <li>HOUR (and synonym SQL_TSI_HOUR)
+ * <li>DAY (and synonym SQL_TSI_DAY)
+ * <li>WEEK (and synonym SQL_TSI_WEEK)
+ * <li>MONTH (and synonym SQL_TSI_MONTH)
+ * <li>QUARTER (and synonym SQL_TSI_QUARTER)
+ * <li>YEAR (and synonym SQL_TSI_YEAR)
+ * </ul>
+ *
+ * <p>Returns difference between two timestamps in indicated timestamp interval.
*/
- public static final SqlFunction TIMESTAMP_DIFF = new SqlFunction(
- "TIMESTAMPDIFF",
- SqlKind.OTHER_FUNCTION,
- ReturnTypes.INTEGER_NULLABLE,
- null,
- OperandTypes.family(
- SqlTypeFamily.ANY, SqlTypeFamily.DATETIME, SqlTypeFamily.DATETIME),
- SqlFunctionCategory.TIMEDATE);
-
+ public static final SqlFunction TIMESTAMP_DIFF =
+ new SqlFunction("TIMESTAMPDIFF", SqlKind.TIMESTAMP_DIFF,
+ ReturnTypes.INTEGER_NULLABLE, null,
+ OperandTypes.family(SqlTypeFamily.ANY, SqlTypeFamily.DATETIME,
+ SqlTypeFamily.DATETIME), SqlFunctionCategory.TIMEDATE);
/**
* Use of the <code>IN_FENNEL</code> operator forces the argument to be
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
index 5d1957f..44d6fe5 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/StandardConvertletTable.java
@@ -285,10 +285,13 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
SqlStdOperatorTable.VAR_SAMP,
new AvgVarianceConvertlet(SqlKind.VAR_SAMP));
- registerOp(
- SqlStdOperatorTable.FLOOR, new FloorCeilConvertlet(true));
- registerOp(
- SqlStdOperatorTable.CEIL, new FloorCeilConvertlet(false));
+ final SqlRexConvertlet floorCeilConvertlet = new FloorCeilConvertlet();
+ registerOp(SqlStdOperatorTable.FLOOR, floorCeilConvertlet);
+ registerOp(SqlStdOperatorTable.CEIL, floorCeilConvertlet);
+
+ registerOp(SqlStdOperatorTable.TIMESTAMP_ADD,
+ new TimestampAddConvertlet());
+ registerOp(SqlStdOperatorTable.TIMESTAMP_DIFF, new TimestampDiffConvertlet());
// Convert "element(<expr>)" to "$element_slice(<expr>)", if the
// expression is a multiset of scalars.
@@ -503,10 +506,8 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
return cx.getRexBuilder().makeCast(type, arg);
}
- protected RexNode convertFloorCeil(
- SqlRexContext cx,
- SqlCall call,
- boolean floor) {
+ protected RexNode convertFloorCeil(SqlRexContext cx, SqlCall call) {
+ final boolean floor = call.getKind() == SqlKind.FLOOR;
// Rewrite floor, ceil of interval
if (call.operandCount() == 1
&& call.operand(0) instanceof SqlIntervalLiteral) {
@@ -671,6 +672,19 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
if (val.equals(BigDecimal.ONE)) {
return res;
}
+ // If val is between 0 and 1, rather than divide by val, multiply by its
+ // reciprocal. For example, rather than divide by 0.001 multiply by 1000.
+ if (val.compareTo(BigDecimal.ONE) < 0
+ && val.signum() == 1) {
+ try {
+ final BigDecimal reciprocal =
+ BigDecimal.ONE.divide(val, BigDecimal.ROUND_UNNECESSARY);
+ return rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY, res,
+ rexBuilder.makeExactLiteral(reciprocal));
+ } catch (ArithmeticException e) {
+ // ignore - reciprocal is not an integer
+ }
+ }
return rexBuilder.makeCall(SqlStdOperatorTable.DIVIDE_INTEGER, res,
rexBuilder.makeExactLiteral(val));
}
@@ -1323,14 +1337,48 @@ public class StandardConvertletTable extends ReflectiveConvertletTable {
/** Convertlet that handles {@code FLOOR} and {@code CEIL} functions. */
private class FloorCeilConvertlet implements SqlRexConvertlet {
- private final boolean floor;
+ public RexNode convertCall(SqlRexContext cx, SqlCall call) {
+ return convertFloorCeil(cx, call);
+ }
+ }
- public FloorCeilConvertlet(boolean floor) {
- this.floor = floor;
+ /** Convertlet that handles the {@code TIMESTAMPADD} function. */
+ private class TimestampAddConvertlet implements SqlRexConvertlet {
+ public RexNode convertCall(SqlRexContext cx, SqlCall call) {
+ // TIMESTAMPADD(unit, count, timestamp)
+ // => timestamp + count * INTERVAL '1' UNIT
+ final RexBuilder rexBuilder = cx.getRexBuilder();
+ final SqlLiteral unitLiteral = call.operand(0);
+ final TimeUnit unit = unitLiteral.symbolValue(TimeUnit.class);
+ return rexBuilder.makeCall(SqlStdOperatorTable.DATETIME_PLUS,
+ cx.convertExpression(call.operand(2)),
+ rexBuilder.makeCall(SqlStdOperatorTable.MULTIPLY,
+ rexBuilder.makeIntervalLiteral(unit.multiplier,
+ new SqlIntervalQualifier(unit, null,
+ unitLiteral.getParserPosition())),
+ cx.convertExpression(call.operand(1))));
}
+ }
+ /** Convertlet that handles the {@code TIMESTAMPDIFF} function. */
+ private class TimestampDiffConvertlet implements SqlRexConvertlet {
public RexNode convertCall(SqlRexContext cx, SqlCall call) {
- return convertFloorCeil(cx, call, floor);
+ // TIMESTAMPDIFF(unit, t1, t2)
+ // => (t1 - t2) UNIT
+ final RexBuilder rexBuilder = cx.getRexBuilder();
+ final SqlLiteral unitLiteral = call.operand(0);
+ final TimeUnit unit = unitLiteral.symbolValue(TimeUnit.class);
+ final RelDataType intType =
+ cx.getTypeFactory().createSqlType(SqlTypeName.INTEGER);
+ final SqlIntervalQualifier qualifier =
+ new SqlIntervalQualifier(unit, null, SqlParserPos.ZERO);
+ return divide(cx.getRexBuilder(),
+ rexBuilder.makeCast(intType,
+ rexBuilder.makeCall(SqlStdOperatorTable.MINUS_DATE,
+ cx.convertExpression(call.operand(1)),
+ cx.convertExpression(call.operand(2)),
+ cx.getRexBuilder().makeIntervalLiteral(qualifier))),
+ unit.multiplier);
}
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
index 858e8a0..0d7d614 100644
--- a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
@@ -5566,6 +5566,24 @@ public class SqlParserTest {
"(?s).*Was expecting one of.*");
}
+ @Test public void testTimestampAdd() {
+ final String sql = "select * from t\n"
+ + "where timestampadd(sql_tsi_month, 5, hiredate) < curdate";
+ final String expected = "SELECT *\n"
+ + "FROM `T`\n"
+ + "WHERE (TIMESTAMPADD(MONTH, 5, `HIREDATE`) < `CURDATE`)";
+ sql(sql).ok(expected);
+ }
+
+ @Test public void testTimestampDiff() {
+ final String sql = "select * from t\n"
+ + "where timestampdiff(frac_second, 5, hiredate) < curdate";
+ final String expected = "SELECT *\n"
+ + "FROM `T`\n"
+ + "WHERE (TIMESTAMPDIFF(MICROSECOND, 5, `HIREDATE`) < `CURDATE`)";
+ sql(sql).ok(expected);
+ }
+
@Test public void testUnnest() {
check(
"select*from unnest(x)",
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
index 48311dd..1c5ec79 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java
@@ -1727,18 +1727,12 @@ public abstract class SqlOperatorBaseTest {
if (false) {
tester.checkScalar("{fn SECOND(time)}", null, "");
}
- if (false) {
- tester.checkScalar(
- "{fn TIMESTAMPADD(interval, count, timestamp)}",
- null,
- "");
- }
- if (false) {
- tester.checkScalar(
- "{fn TIMESTAMPDIFF(interval, timestamp1, timestamp2)}",
- null,
- "");
- }
+ tester.checkScalar("{fn TIMESTAMPADD(HOUR, 5,"
+ + " TIMESTAMP '2014-03-29 12:34:56')}",
+ "2014-03-29 17:34:56", "TIMESTAMP(0) NOT NULL");
+ tester.checkScalar("{fn TIMESTAMPDIFF(HOUR,"
+ + " TIMESTAMP '2014-03-29 12:34:56',"
+ + " TIMESTAMP '2014-03-29 12:34:56')}", "0", "INTEGER NOT NULL");
if (false) {
tester.checkScalar("{fn WEEK(date)}", null, "");
}
@@ -4599,18 +4593,48 @@ public abstract class SqlOperatorBaseTest {
"floor(cast(null as interval year))");
}
- @Test public void testTimestampAddAdnDiff() {
- if (!enable) {
- return;
- }
+ @Test public void testTimestampAdd() {
+ tester.setFor(SqlStdOperatorTable.TIMESTAMP_ADD);
tester.checkScalar(
- "timestampadd(MINUTE, 2, timestamp '2016-02-24 12:42:25')",
+ "timestampadd(SQL_TSI_SECOND, 2, timestamp '2016-02-24 12:42:25')",
"2016-02-24 12:42:27",
"TIMESTAMP(0) NOT NULL");
tester.checkScalar(
- "timestampdiff(YEAR, "
- + "timestamp '2014-02-24 12:42:25', "
- + "timestamp '2016-02-24 12:42:25')",
+ "timestampadd(MINUTE, 2, timestamp '2016-02-24 12:42:25')",
+ "2016-02-24 12:44:25",
+ "TIMESTAMP(0) NOT NULL");
+ tester.checkScalar(
+ "timestampadd(HOUR, -2000, timestamp '2016-02-24 12:42:25')",
+ "2015-12-03 04:42:25",
+ "TIMESTAMP(0) NOT NULL");
+ if (!INTERVAL) {
+ return;
+ }
+ tester.checkNull("timestampadd(HOUR, CAST(NULL AS INTEGER),"
+ + " timestamp '2016-02-24 12:42:25')");
+ tester.checkNull(
+ "timestampadd(HOUR, -200, CAST(NULL AS TIMESTAMP))");
+ tester.checkScalar(
+ "timestampadd(MONTH, 3, timestamp '2016-02-24 12:42:25')",
+ "2016-05-24 12:42:25", "TIMESTAMP(0) NOT NULL");
+ }
+
+ @Test public void testTimestampDiff() {
+ tester.setFor(SqlStdOperatorTable.TIMESTAMP_DIFF);
+ tester.checkScalar("timestampdiff(HOUR, "
+ + "timestamp '2016-02-24 12:42:25', "
+ + "timestamp '2016-02-24 15:42:25')",
+ "-3", "INTEGER NOT NULL");
+ tester.checkScalar("timestampdiff(MICROSECOND, "
+ + "timestamp '2016-02-24 12:42:25', "
+ + "timestamp '2016-02-24 12:42:20')",
+ "5000000", "INTEGER NOT NULL");
+ if (!INTERVAL) {
+ return;
+ }
+ tester.checkScalar("timestampdiff(YEAR, "
+ + "timestamp '2014-02-24 12:42:25', "
+ + "timestamp '2016-02-24 12:42:25')",
"2", "INTEGER NOT NULL");
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/core/src/test/java/org/apache/calcite/sql/test/SqlTests.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlTests.java b/core/src/test/java/org/apache/calcite/sql/test/SqlTests.java
index 4f15f7d..d5889fb 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlTests.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlTests.java
@@ -22,10 +22,8 @@ import org.apache.calcite.sql.type.SqlTypeName;
import java.sql.ResultSet;
import java.sql.Types;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
@@ -135,7 +133,7 @@ public abstract class SqlTests {
public static void compareResultSet(
ResultSet resultSet,
Set<String> refSet) throws Exception {
- Set<String> actualSet = new HashSet<String>();
+ Set<String> actualSet = new HashSet<>();
final int columnType = resultSet.getMetaData().getColumnType(1);
final ColumnMetaData.Rep rep = rep(columnType);
while (resultSet.next()) {
@@ -151,7 +149,13 @@ public abstract class SqlTests {
case SHORT:
case INTEGER:
case LONG:
- final long l = Long.parseLong(s0);
+ long l;
+ try {
+ l = Long.parseLong(s0);
+ } catch (NumberFormatException e) {
+ // Large integers come out in scientific format, say "5E+06"
+ l = (long) Double.parseDouble(s0);
+ }
assertThat(resultSet.getByte(1), equalTo((byte) l));
assertThat(resultSet.getShort(1), equalTo((short) l));
assertThat(resultSet.getInt(1), equalTo((int) l));
@@ -256,78 +260,6 @@ public abstract class SqlTests {
}
}
- /**
- * Compares the first column of a result set against a String-valued
- * reference set, taking order into account.
- *
- * @param resultSet Result set
- * @param refList Expected results
- * @throws Exception .
- */
- public static void compareResultList(
- ResultSet resultSet,
- List<String> refList) throws Exception {
- List<String> actualSet = new ArrayList<String>();
- while (resultSet.next()) {
- String s = resultSet.getString(1);
- actualSet.add(s);
- }
- resultSet.close();
- assertEquals(refList, actualSet);
- }
-
- /**
- * Compares the columns of a result set against several String-valued
- * reference lists, taking order into account.
- *
- * @param resultSet Result set
- * @param refLists vararg of List<String>. The first list is compared
- * to the first column, the second list to the second column
- * and so on
- */
- public static void compareResultLists(
- ResultSet resultSet,
- List<String>... refLists) throws Exception {
- int numExpectedColumns = refLists.length;
-
- assertTrue(numExpectedColumns > 0);
-
- assertTrue(
- resultSet.getMetaData().getColumnCount() >= numExpectedColumns);
-
- int numExpectedRows = -1;
-
- List<List<String>> actualLists = new ArrayList<List<String>>();
- for (int i = 0; i < numExpectedColumns; i++) {
- actualLists.add(new ArrayList<String>());
-
- if (i == 0) {
- numExpectedRows = refLists[i].size();
- } else {
- assertEquals(
- "num rows differ across ref lists",
- numExpectedRows,
- refLists[i].size());
- }
- }
-
- while (resultSet.next()) {
- for (int i = 0; i < numExpectedColumns; i++) {
- String s = resultSet.getString(i + 1);
-
- actualLists.get(i).add(s);
- }
- }
- resultSet.close();
-
- for (int i = 0; i < numExpectedColumns; i++) {
- assertEquals(
- "column mismatch in column " + (i + 1),
- refLists[i],
- actualLists.get(i));
- }
- }
-
//~ Inner Classes ----------------------------------------------------------
/**
@@ -382,11 +314,13 @@ public abstract class SqlTests {
assertTrue(result instanceof Number);
return new ApproximateResultChecker((Number) result, delta);
} else {
- Set<String> refSet = new HashSet<String>();
+ Set<String> refSet = new HashSet<>();
if (result == null) {
refSet.add(null);
} else if (result instanceof Collection) {
- refSet.addAll((Collection<String>) result);
+ //noinspection unchecked
+ final Collection<String> collection = (Collection<String>) result;
+ refSet.addAll(collection);
} else {
refSet.add(result.toString());
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index c8ba8e9..a56237c 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -1133,9 +1133,10 @@ public class SqlValidatorTest extends SqlValidatorTestCase {
checkWholeExpFails(
"{fn log10('1')}",
"(?s).*Cannot apply.*fn LOG10..<CHAR.1.>.*");
- checkWholeExpFails(
- "{fn log10(1,1)}",
- "(?s).*Encountered .fn LOG10. with 2 parameter.s.; was expecting 1 parameter.s.*");
+ final String expected = "Cannot apply '\\{fn LOG10\\}' to arguments of"
+ + " type '\\{fn LOG10\\}\\(<INTEGER>, <INTEGER>\\)'\\. "
+ + "Supported form\\(s\\): '\\{fn LOG10\\}\\(<NUMERIC>\\)'";
+ checkWholeExpFails("{fn log10(1,1)}", expected);
checkWholeExpFails(
"{fn fn(1)}",
"(?s).*Function '.fn FN.' is not defined.*");
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/site/_docs/reference.md
----------------------------------------------------------------------
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index 8785bd5..af05ad2 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -979,12 +979,15 @@ See also: UNNEST relational operator converts a collection to a relation.
| Operator syntax | Description
|:------------------------------ |:-----------
+| {fn ABS(numeric)} | Returns the absolute value of *numeric*
+| {fn EXP(numeric)} | Returns *e* raised to the power of *numeric*
+| {fn LOG(numeric)} | Returns the natural logarithm (base *e*) of *numeric*
| {fn LOG10(numeric)} | Returns the base-10 logarithm of *numeric*
+| {fn MOD(numeric1, numeric2)} | Returns the remainder (modulus) of *numeric1* divided by *numeric2*. The result is negative only if *numeric1* is negative
| {fn POWER(numeric1, numeric2)} | Returns *numeric1* raised to the power of *numeric2*
Not implemented:
-* {fn ABS(numeric)} - Returns the absolute value of *numeric*
* {fn ACOS(numeric)} - Returns the arc cosine of *numeric*
* {fn ASIN(numeric)} - Returns the arc sine of *numeric*
* {fn ATAN(numeric)} - Returns the arc tangent of *numeric*
@@ -993,10 +996,7 @@ Not implemented:
* {fn COS(numeric)} - Returns the cosine of *numeric*
* {fn COT(numeric)}
* {fn DEGREES(numeric)} - Converts *numeric* from radians to degrees
-* {fn EXP(numeric)} - Returns *e* raised to the power of *numeric*
* {fn FLOOR(numeric)} - Rounds *numeric* down, and returns the largest number that is less than or equal to *numeric*
-* {fn LOG(numeric)} - Returns the natural logarithm (base *e*) of *numeric*
-* {fn MOD(numeric1, numeric2)} - Returns the remainder (modulus) of *numeric1* divided by *numeric2*. The result is negative only if *numeric1* is negative
* {fn PI()} - Returns a value that is closer than any other value to *pi*
* {fn RADIANS(numeric)} - Converts *numeric* from degrees to radians
* {fn RAND(numeric)}
@@ -1011,35 +1011,42 @@ Not implemented:
| Operator syntax | Description
|:--------------- |:-----------
+| {fn CONCAT(character, character)} | Returns the concatenation of character strings
| {fn LOCATE(string1, string2)} | Returns the position in *string2* of the first occurrence of *string1*. Searches from the beginning of the second CharacterExpression, unless the startIndex parameter is specified.
| {fn INSERT(string1, start, length, string2)} | Inserts *string2* into a slot in *string1*
| {fn LCASE(string)} | Returns a string in which all alphabetic characters in *string* have been converted to lower case
+| {fn LENGTH(string)} | Returns the number of characters in a string
+| {fn LOCATE(string1, string2 [, integer])} | Returns the position in *string2* of the first occurrence of *string1*. Searches from the beginning of *string2*, unless *integer* is specified.
+| {fn LTRIM(string)} | Returns *string* with leading space characters removed
+| {fn RTRIM(string)} | Returns *string* with trailing space characters removed
+| {fn SUBSTRING(string, offset, length)} | Returns a character string that consists of *length* characters from *string* starting at the *offset* position
+| {fn UCASE(string)} | Returns a string in which all alphabetic characters in *string* have been converted to upper case
Not implemented:
* {fn ASCII(string)} - Convert a single-character string to the corresponding ASCII code, an integer between 0 and 255
* {fn CHAR(string)}
-* {fn CONCAT(character, character)} - Returns the concatenation of character strings
* {fn DIFFERENCE(string, string)}
* {fn LEFT(string, integer)}
-* {fn LENGTH(string)}
-* {fn LOCATE(string1, string2 [, integer])} - Returns the position in *string2* of the first occurrence of *string1*. Searches from the beginning of *string2*, unless *integer* is specified.
-* {fn LTRIM(string)}
* {fn REPEAT(string, integer)}
* {fn REPLACE(string, string, string)}
* {fn RIGHT(string, integer)}
-* {fn RTRIM(string)}
* {fn SOUNDEX(string)}
* {fn SPACE(integer)}
-* {fn SUBSTRING(string, integer, integer)}
-* {fn UCASE(string)} - Returns a string in which all alphabetic characters in *string* have been converted to upper case
#### Date/time
+| Operator syntax | Description
+|:--------------- |:-----------
+| {fn CURDATE()} | Equivalent to `CURRENT_DATE`
+| {fn CURTIME()} | Equivalent to `LOCALTIME`
+| {fn NOW()} | Equivalent to `LOCALTIMESTAMP`
+| {fn QUARTER(date)} | Equivalent to `EXTRACT(QUARTER FROM date)`. Returns an integer between 1 and 4.
+| {fn TIMESTAMPADD(interval, count, timestamp)} | Adds an interval to a timestamp
+| {fn TIMESTAMPDIFF(interval, timestamp, timestamp)} | Subtracts two timestamps
+
Not implemented:
-* {fn CURDATE()}
-* {fn CURTIME()}
* {fn DAYNAME(date)}
* {fn DAYOFMONTH(date)}
* {fn DAYOFWEEK(date)}
@@ -1048,11 +1055,7 @@ Not implemented:
* {fn MINUTE(time)}
* {fn MONTH(date)}
* {fn MONTHNAME(date)}
-* {fn NOW()}
-* {fn QUARTER(date)}
* {fn SECOND(time)}
-* {fn TIMESTAMPADD(interval, count, timestamp)}
-* {fn TIMESTAMPDIFF(interval, timestamp, timestamp)}
* {fn WEEK(date)}
* {fn YEAR(date)}
http://git-wip-us.apache.org/repos/asf/calcite/blob/4ac82a30/site/community/index.md
----------------------------------------------------------------------
diff --git a/site/community/index.md b/site/community/index.md
index 82aa4ce..ceacb76 100644
--- a/site/community/index.md
+++ b/site/community/index.md
@@ -26,6 +26,7 @@ limitations under the License.
# Upcoming talks
+* 2016/03/30 <a href="http://conferences.oreilly.com/strata/hadoop-big-data-ca/public/schedule/detail/48180">Strata + Hadoop World</a>, San Jose (developer showcase)
* 2016/04/13 <a href="http://hadoopsummit.org/dublin/agenda/">Hadoop Summit</a>, Dublin
* 2016/04/26 <a href="http://kafka-summit.org/schedule/">Kafka Summit</a>, San Francisco
* 2016/05/10 <a href="http://events.linuxfoundation.org/events/apache-big-data-north-america/program/schedule">ApacheCon Big Data North America</a>, Vancouver
[2/5] calcite git commit: Update groupId when Calcite POMs reference
Avatica modules
Posted by jh...@apache.org.
Update groupId when Calcite POMs reference Avatica modules
Remove Conjars from Avatica's repository list
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/eead3d21
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/eead3d21
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/eead3d21
Branch: refs/heads/master
Commit: eead3d21b0ef18f05029cefbb6b4fb888e75c548
Parents: 9c62ada
Author: Julian Hyde <jh...@apache.org>
Authored: Mon Mar 7 15:45:01 2016 -0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Mar 7 21:21:11 2016 -0800
----------------------------------------------------------------------
avatica/pom.xml | 11 -----------
core/pom.xml | 4 ++--
example/csv/pom.xml | 2 +-
mongodb/pom.xml | 4 ++--
piglet/pom.xml | 2 +-
pom.xml | 23 ++++++++++++-----------
splunk/pom.xml | 2 +-
7 files changed, 19 insertions(+), 29 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/eead3d21/avatica/pom.xml
----------------------------------------------------------------------
diff --git a/avatica/pom.xml b/avatica/pom.xml
index 7a747fe..42a72ee 100644
--- a/avatica/pom.xml
+++ b/avatica/pom.xml
@@ -583,17 +583,6 @@ limitations under the License.
<enabled>false</enabled>
</snapshots>
</repository>
- <repository>
- <releases>
- <enabled>true</enabled>
- <updatePolicy>always</updatePolicy>
- <checksumPolicy>warn</checksumPolicy>
- </releases>
- <id>conjars</id>
- <name>Conjars</name>
- <url>http://conjars.org/repo</url>
- <layout>default</layout>
- </repository>
</repositories>
<profiles>
http://git-wip-us.apache.org/repos/asf/calcite/blob/eead3d21/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index 8a548dd..9b50ba3 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -38,7 +38,7 @@ limitations under the License.
<!-- Sorted by groupId, artifactId; calcite dependencies first. Put versions
in dependencyManagement in the root POM, not here. -->
<dependency>
- <groupId>org.apache.calcite</groupId>
+ <groupId>org.apache.calcite.avatica</groupId>
<artifactId>calcite-avatica</artifactId>
</dependency>
<dependency>
@@ -46,7 +46,7 @@ limitations under the License.
<artifactId>calcite-linq4j</artifactId>
</dependency>
<dependency>
- <groupId>org.apache.calcite</groupId>
+ <groupId>org.apache.calcite.avatica</groupId>
<artifactId>calcite-avatica-server</artifactId>
<scope>test</scope>
</dependency>
http://git-wip-us.apache.org/repos/asf/calcite/blob/eead3d21/example/csv/pom.xml
----------------------------------------------------------------------
diff --git a/example/csv/pom.xml b/example/csv/pom.xml
index 8b0f8de..cee4b53 100644
--- a/example/csv/pom.xml
+++ b/example/csv/pom.xml
@@ -36,7 +36,7 @@ limitations under the License.
<dependencies>
<dependency>
- <groupId>org.apache.calcite</groupId>
+ <groupId>org.apache.calcite.avatica</groupId>
<artifactId>calcite-avatica</artifactId>
</dependency>
<dependency>
http://git-wip-us.apache.org/repos/asf/calcite/blob/eead3d21/mongodb/pom.xml
----------------------------------------------------------------------
diff --git a/mongodb/pom.xml b/mongodb/pom.xml
index 3e65fd3..0efaa4f 100644
--- a/mongodb/pom.xml
+++ b/mongodb/pom.xml
@@ -37,7 +37,7 @@ limitations under the License.
<!-- Sorted by groupId, artifactId; calcite dependencies first. Put versions
in dependencyManagement in the root POM, not here. -->
<dependency>
- <groupId>org.apache.calcite</groupId>
+ <groupId>org.apache.calcite.avatica</groupId>
<artifactId>calcite-avatica</artifactId>
</dependency>
<dependency>
@@ -101,7 +101,7 @@ limitations under the License.
<failOnWarning>true</failOnWarning>
<!-- ignore "unused but declared" warnings -->
<ignoredUnusedDeclaredDependencies>
- <ignoredUnusedDeclaredDependency>org.apache.calcite:calcite-avatica</ignoredUnusedDeclaredDependency>
+ <ignoredUnusedDeclaredDependency>org.apache.calcite.avatica:calcite-avatica</ignoredUnusedDeclaredDependency>
<ignoredUnusedDeclaredDependency>org.slf4j:slf4j-api</ignoredUnusedDeclaredDependency>
<ignoredUnusedDeclaredDependency>org.slf4j:slf4j-log4j12</ignoredUnusedDeclaredDependency>
</ignoredUnusedDeclaredDependencies>
http://git-wip-us.apache.org/repos/asf/calcite/blob/eead3d21/piglet/pom.xml
----------------------------------------------------------------------
diff --git a/piglet/pom.xml b/piglet/pom.xml
index 790910e..37e07cd 100644
--- a/piglet/pom.xml
+++ b/piglet/pom.xml
@@ -37,7 +37,7 @@ limitations under the License.
<!-- Sorted by groupId, artifactId; calcite dependencies first. Put versions
in dependencyManagement in the root POM, not here. -->
<dependency>
- <groupId>org.apache.calcite</groupId>
+ <groupId>org.apache.calcite.avatica</groupId>
<artifactId>calcite-avatica</artifactId>
</dependency>
<dependency>
http://git-wip-us.apache.org/repos/asf/calcite/blob/eead3d21/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index a94707e..0642df4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -53,6 +53,7 @@ limitations under the License.
<!-- This list is in alphabetical order. -->
<airlift-tpch.version>0.1</airlift-tpch.version>
+ <avatica.version>1.7.0-SNAPSHOT</avatica.version>
<build-helper-maven-plugin.version>1.9</build-helper-maven-plugin.version>
<cassandra-driver-core.version>2.1.9</cassandra-driver-core.version>
<checksum-maven-plugin.version>1.2</checksum-maven-plugin.version>
@@ -148,32 +149,32 @@ limitations under the License.
<dependencyManagement>
<dependencies>
- <!-- Sorted by groupId, artifactId; calcite dependencies first. -->
+ <!-- Sorted by groupId, artifactId; calcite (and avatica) dependencies first. -->
<dependency>
- <groupId>org.apache.calcite</groupId>
+ <groupId>org.apache.calcite.avatica</groupId>
<artifactId>calcite-avatica-metrics</artifactId>
- <version>${project.version}</version>
+ <version>${avatica.version}</version>
</dependency>
<dependency>
- <groupId>org.apache.calcite</groupId>
+ <groupId>org.apache.calcite.avatica</groupId>
<artifactId>calcite-avatica</artifactId>
- <version>${project.version}</version>
+ <version>${avatica.version}</version>
</dependency>
<dependency>
- <groupId>org.apache.calcite</groupId>
+ <groupId>org.apache.calcite.avatica</groupId>
<artifactId>calcite-avatica-noop</artifactId>
- <version>${project.version}</version>
+ <version>${avatica.version}</version>
</dependency>
<dependency>
- <groupId>org.apache.calcite</groupId>
+ <groupId>org.apache.calcite.avatica</groupId>
<artifactId>calcite-avatica</artifactId>
- <version>${project.version}</version>
+ <version>${avatica.version}</version>
<type>test-jar</type>
</dependency>
<dependency>
- <groupId>org.apache.calcite</groupId>
+ <groupId>org.apache.calcite.avatica</groupId>
<artifactId>calcite-avatica-server</artifactId>
- <version>${project.version}</version>
+ <version>${avatica.version}</version>
</dependency>
<dependency>
<groupId>org.apache.calcite</groupId>
http://git-wip-us.apache.org/repos/asf/calcite/blob/eead3d21/splunk/pom.xml
----------------------------------------------------------------------
diff --git a/splunk/pom.xml b/splunk/pom.xml
index 5b955b5..7c3fa20 100644
--- a/splunk/pom.xml
+++ b/splunk/pom.xml
@@ -37,7 +37,7 @@ limitations under the License.
<!-- Sorted by groupId, artifactId; calcite dependencies first. Put versions
in dependencyManagement in the root POM, not here. -->
<dependency>
- <groupId>org.apache.calcite</groupId>
+ <groupId>org.apache.calcite.avatica</groupId>
<artifactId>calcite-avatica</artifactId>
</dependency>
<dependency>