Skip to content

Commit

Permalink
[CALCITE-6527] Add DATE_ADD function (enabled in Spark library)
Browse files Browse the repository at this point in the history
  • Loading branch information
caicancai committed Sep 15, 2024
1 parent 91fe118 commit 0067609
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,16 @@ private SqlLibraryOperators() {
public static final SqlFunction DATEADD =
new SqlTimestampAddFunction("DATEADD");

/** The "DATE_ADD(start_date, num_days)" function
* (Spark) Returns the date that is num_days after start_date. */
@LibraryOperator(libraries = {SPARK})
public static final SqlFunction DATE_ADD_SPARK =
SqlBasicFunction.create(SqlKind.DATE_ADD, ReturnTypes.DATE_NULLABLE,
OperandTypes.DATE_ANY)
.withFunctionType(SqlFunctionCategory.TIMEDATE);

/** The "ADD_MONTHS(start_date, num_months)" function
* (SPARK) Returns the date that is num_months after start_date. */
@LibraryOperator(libraries = {ORACLE, SPARK})
public static final SqlFunction ADD_MONTHS =
SqlBasicFunction.create(SqlKind.ADD_MONTHS, ReturnTypes.ARG0_NULLABLE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ private StandardConvertletTable() {
new TimestampAddConvertlet());
registerOp(SqlLibraryOperators.ADD_MONTHS,
new TimestampAddConvertlet());
registerOp(SqlLibraryOperators.DATE_ADD_SPARK,
new TimestampAddConvertlet());
registerOp(SqlLibraryOperators.DATE_DIFF,
new TimestampDiffConvertlet());
registerOp(SqlLibraryOperators.DATE_SUB,
Expand Down Expand Up @@ -2150,8 +2152,11 @@ private static class TimestampAddConvertlet implements SqlRexConvertlet {
switch (call.operandCount()) {
case 2:
// Oracle-style 'ADD_MONTHS(date, integer months)'
if (call.getOperator() == SqlLibraryOperators.ADD_MONTHS) {
qualifier = new SqlIntervalQualifier(TimeUnit.MONTH, null, SqlParserPos.ZERO);
if (call.getOperator() == SqlLibraryOperators.ADD_MONTHS
|| call.getOperator() == SqlLibraryOperators.DATE_ADD_SPARK) {
qualifier = call.getOperator() == SqlLibraryOperators.ADD_MONTHS
? new SqlIntervalQualifier(TimeUnit.MONTH, null, SqlParserPos.ZERO)
: new SqlIntervalQualifier(TimeUnit.DAY, null, SqlParserPos.ZERO);
RexNode opfirstparameter = cx.convertExpression(call.operand(0));
if (opfirstparameter.getType().getSqlTypeName() == SqlTypeName.TIMESTAMP) {
RelDataType timestampType = cx.getTypeFactory().createSqlType(SqlTypeName.DATE);
Expand Down
3 changes: 2 additions & 1 deletion site/_docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2721,7 +2721,7 @@ In the following:
| m | expr1 <=> expr2 | Whether two values are equal, treating null values as the same, and it's similar to `IS NOT DISTINCT FROM`
| p | ACOSD(numeric) | Returns the inverse cosine of *numeric* in degrees as a double. Returns NaN if *numeric* is NaN. Fails if *numeric* is less than -1.0 or greater than 1.0.
| * | ACOSH(numeric) | Returns the inverse hyperbolic cosine of *numeric*
| o s | ADD_MONTHS(start_date, num_months) | Returns the date that is *num_months* after *start_date*
| o s | ADD_MONTHS(date, num_months) | Returns the date that is *num_months* after *date*
| s | ARRAY([expr [, expr ]*]) | Construct an array in Apache Spark. The function allows users to use `ARRAY()` to create an empty array
| s | ARRAY_APPEND(array, element) | Appends an *element* to the end of the *array* and returns the result. Type of *element* should be similar to type of the elements of the *array*. If the *array* is null, the function will return null. If an *element* that is null, the null *element* will be added to the end of the *array*
| s | ARRAY_COMPACT(array) | Removes null values from the *array*
Expand Down Expand Up @@ -2804,6 +2804,7 @@ In the following:
| b s | DATE_FROM_UNIX_DATE(integer) | Returns the DATE that is *integer* days after 1970-01-01
| p r | DATE_PART(timeUnit, datetime) | Equivalent to `EXTRACT(timeUnit FROM datetime)`
| b | DATE_ADD(date, interval) | Returns the DATE value that occurs *interval* after *date*
| s | DATE_ADD(date, num_days) | Returns the DATE that is *num_days* after *date*
| b | DATE_DIFF(date, date2, timeUnit) | Returns the whole number of *timeUnit* between *date* and *date2*
| b | DATE_SUB(date, interval) | Returns the DATE value that occurs *interval* before *date*
| b | DATE_TRUNC(date, timeUnit) | Truncates *date* to the granularity of *timeUnit*, rounding to the beginning of the unit
Expand Down
57 changes: 57 additions & 0 deletions testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13906,6 +13906,63 @@ void testTimestampDiff(boolean coercionEnabled) {
f.checkNull("date_add(CAST(NULL AS DATE), interval 5 day)");
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-6527">[CALCITE-6527]
* Add DATE_ADD function (enabled in Spark library)</a>.
*/
@Test void testDateAddSpark() {
final SqlOperatorFixture f0 = fixture()
.setFor(SqlLibraryOperators.DATE_ADD_SPARK);
f0.checkFails("^date_add(date '2008-12-25', "
+ "5)^",
"No match found for function signature "
+ "DATE_ADD\\(<DATE>, <NUMERIC>\\)", false);

final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.SPARK);
f.checkScalar("date_add(date '2016-02-22', 2)",
"2016-02-24",
"DATE NOT NULL");
f.checkScalar("date_add(date '2016-02-28', 2)",
"2016-03-01",
"DATE NOT NULL");
f.checkScalar("date_add(date '2016-03-01', -2)",
"2016-02-28",
"DATE NOT NULL");
f.checkScalar("date_add(date '2016-03-01', -2)",
"2016-02-28",
"DATE NOT NULL");
f.checkScalar("date_add(date '2016-03-01', -2.0)",
"2016-02-28",
"DATE NOT NULL");
f.checkScalar("date_add(date '2016-02-28', 2.0)",
"2016-03-01",
"DATE NOT NULL");
f.checkScalar("date_add(date '2016-02-28', '2.0')",
"2016-03-01",
"DATE NOT NULL");
f.checkScalar("date_add(timestamp '2016-02-22 13:00:01', '-2.0')",
"2016-02-20",
"DATE NOT NULL");
f.checkScalar("date_add(timestamp '2016-02-22 13:00:01', -2)",
"2016-02-20",
"DATE NOT NULL");
f.checkScalar("date_add(timestamp '2016-02-22 13:00:01', -2.0)",
"2016-02-20",
"DATE NOT NULL");
f.checkScalar("date_add(date '0001-01-01', '-2.0')",
"0000-12-30",
"DATE NOT NULL");
f.checkScalar("date_add(date '0001-01-01', '-367')",
"000/-12-31",
"DATE NOT NULL");
f.checkScalar("date_add(date '0001-01-01', '-3')",
"0000-12-29",
"DATE NOT NULL");
f.checkNull("date_add(CAST(NULL AS DATE), 5)");
f.checkNull("date_add(date '2016-02-22', CAST(NULL AS INTEGER))");
f.checkNull("date_add(CAST(NULL AS DATE), CAST(NULL AS INTEGER))");
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-6396">[CALCITE-6396]
* Add ADD_MONTHS function (enabled in Oracle, Spark library)</a>.
Expand Down

0 comments on commit 0067609

Please sign in to comment.