From e35f0e017eb5628760d2048215d7de7ef87f041a Mon Sep 17 00:00:00 2001
From: ChengJie1053 <18033291053@163.com>
Date: Fri, 20 Sep 2024 12:53:17 +0800
Subject: [PATCH] [CALCITE-6241] Enable a few existing functions to hive
library
---
.../calcite/sql/fun/SqlLibraryOperators.java | 38 ++--
site/_docs/reference.md | 39 ++--
.../apache/calcite/test/SqlOperatorTest.java | 201 +++++++++---------
3 files changed, 143 insertions(+), 135 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
index 131ac7c3a759..4a118807686a 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
@@ -113,7 +113,7 @@ private SqlLibraryOperators() {
/** THE "DATE_ADD(date, interval)" function
* (BigQuery) adds the interval to the date. */
- @LibraryOperator(libraries = {BIG_QUERY})
+ @LibraryOperator(libraries = {BIG_QUERY, HIVE})
public static final SqlFunction DATE_ADD =
SqlBasicFunction.create(SqlKind.DATE_ADD, ReturnTypes.ARG0_NULLABLE,
OperandTypes.DATE_INTERVAL)
@@ -132,7 +132,7 @@ private SqlLibraryOperators() {
public static final SqlFunction DATEADD =
new SqlTimestampAddFunction("DATEADD");
- @LibraryOperator(libraries = {ORACLE, SPARK})
+ @LibraryOperator(libraries = {ORACLE, SPARK, HIVE})
public static final SqlFunction ADD_MONTHS =
SqlBasicFunction.create(SqlKind.ADD_MONTHS, ReturnTypes.ARG0_NULLABLE,
OperandTypes.DATE_ANY)
@@ -144,7 +144,7 @@ private SqlLibraryOperators() {
*
MySQL has "DATEDIFF(date, date2)" and "TIMEDIFF(time, time2)" functions
* but Calcite does not implement these because they have no "timeUnit"
* argument. */
- @LibraryOperator(libraries = {MSSQL, POSTGRESQL})
+ @LibraryOperator(libraries = {MSSQL, POSTGRESQL, HIVE})
public static final SqlFunction DATEDIFF =
new SqlTimestampDiffFunction("DATEDIFF",
OperandTypes.family(SqlTypeFamily.ANY, SqlTypeFamily.DATE,
@@ -207,7 +207,7 @@ private static SqlCall transformConvert(SqlValidator validator, SqlCall call) {
/** The "DATE_SUB(date, interval)" function (BigQuery);
* subtracts interval from the date, independent of any time zone. */
- @LibraryOperator(libraries = {BIG_QUERY})
+ @LibraryOperator(libraries = {BIG_QUERY, HIVE})
public static final SqlFunction DATE_SUB =
SqlBasicFunction.create(SqlKind.DATE_SUB, ReturnTypes.ARG0_NULLABLE,
OperandTypes.DATE_INTERVAL)
@@ -243,7 +243,7 @@ private static SqlCall transformConvert(SqlValidator validator, SqlCall call) {
};
/** The "DECODE(v, v1, result1, [v2, result2, ...], resultN)" function. */
- @LibraryOperator(libraries = {ORACLE, REDSHIFT, SPARK})
+ @LibraryOperator(libraries = {ORACLE, REDSHIFT, SPARK, HIVE})
public static final SqlFunction DECODE =
SqlBasicFunction.create(SqlKind.DECODE, DECODE_RETURN_TYPE,
OperandTypes.VARIADIC);
@@ -274,7 +274,7 @@ private static SqlCall transformConvert(SqlValidator validator, SqlCall call) {
}
/** The "NVL(value, value)" function. */
- @LibraryOperator(libraries = {ORACLE, REDSHIFT, SPARK})
+ @LibraryOperator(libraries = {ORACLE, REDSHIFT, SPARK, HIVE})
public static final SqlBasicFunction NVL =
SqlBasicFunction.create(SqlKind.NVL,
ReturnTypes.LEAST_RESTRICTIVE
@@ -319,7 +319,7 @@ private static RelDataType deriveTypePad(SqlOperatorBinding binding, RelDataType
SqlFunctionCategory.STRING);
/** The "RPAD(original_value, return_length[, pattern])" function. */
- @LibraryOperator(libraries = {BIG_QUERY, ORACLE, POSTGRESQL, SPARK})
+ @LibraryOperator(libraries = {BIG_QUERY, ORACLE, POSTGRESQL, SPARK, HIVE})
public static final SqlFunction RPAD =
SqlBasicFunction.create(
"RPAD",
@@ -328,7 +328,7 @@ private static RelDataType deriveTypePad(SqlOperatorBinding binding, RelDataType
SqlFunctionCategory.STRING);
/** The "LTRIM(string)" function. */
- @LibraryOperator(libraries = {BIG_QUERY, ORACLE, POSTGRESQL, SPARK})
+ @LibraryOperator(libraries = {BIG_QUERY, ORACLE, POSTGRESQL, SPARK, HIVE})
public static final SqlFunction LTRIM =
SqlBasicFunction.create(SqlKind.LTRIM,
ReturnTypes.ARG0.andThen(SqlTypeTransforms.TO_NULLABLE)
@@ -337,7 +337,7 @@ private static RelDataType deriveTypePad(SqlOperatorBinding binding, RelDataType
.withFunctionType(SqlFunctionCategory.STRING);
/** The "RTRIM(string)" function. */
- @LibraryOperator(libraries = {BIG_QUERY, ORACLE, POSTGRESQL, SPARK})
+ @LibraryOperator(libraries = {BIG_QUERY, ORACLE, POSTGRESQL, SPARK, HIVE})
public static final SqlFunction RTRIM =
SqlBasicFunction.create(SqlKind.RTRIM,
ReturnTypes.ARG0.andThen(SqlTypeTransforms.TO_NULLABLE)
@@ -376,7 +376,7 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding,
public static final SqlFunction STRPOS = new SqlPositionFunction("STRPOS");
/** The "INSTR(string, substring [, position [, occurrence]])" function. */
- @LibraryOperator(libraries = {BIG_QUERY, MYSQL, ORACLE})
+ @LibraryOperator(libraries = {BIG_QUERY, MYSQL, ORACLE, HIVE})
public static final SqlFunction INSTR = new SqlPositionFunction("INSTR");
/** Generic "SUBSTR(string, position [, substringLength ])" function. */
@@ -455,7 +455,7 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding,
SqlFunctionCategory.STRING);
/** The "GREATEST(value, value)" function. */
- @LibraryOperator(libraries = {BIG_QUERY, ORACLE, SPARK})
+ @LibraryOperator(libraries = {BIG_QUERY, ORACLE, SPARK, HIVE})
public static final SqlFunction GREATEST =
SqlBasicFunction.create(SqlKind.GREATEST,
ReturnTypes.LEAST_RESTRICTIVE.andThen(SqlTypeTransforms.TO_NULLABLE),
@@ -469,7 +469,7 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding,
OperandTypes.SAME_VARIADIC);
/** The "LEAST(value, value)" function. */
- @LibraryOperator(libraries = {BIG_QUERY, ORACLE, SPARK})
+ @LibraryOperator(libraries = {BIG_QUERY, ORACLE, SPARK, HIVE})
public static final SqlFunction LEAST =
SqlBasicFunction.create(SqlKind.LEAST,
ReturnTypes.LEAST_RESTRICTIVE.andThen(SqlTypeTransforms.TO_NULLABLE),
@@ -584,7 +584,7 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding,
/** The "REGEXP_REPLACE(value, regexp, rep)"
* function. Replaces all substrings of value that match regexp with
* {@code rep} and returns modified value. */
- @LibraryOperator(libraries = {MYSQL, ORACLE, REDSHIFT})
+ @LibraryOperator(libraries = {MYSQL, ORACLE, REDSHIFT, HIVE})
public static final SqlFunction REGEXP_REPLACE_3 =
SqlBasicFunction.create("REGEXP_REPLACE", ReturnTypes.VARCHAR_NULLABLE,
OperandTypes.STRING_STRING_STRING, SqlFunctionCategory.STRING);
@@ -1057,7 +1057,7 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding,
ReturnTypes.ARG0_NULLABLE_VARYING,
OperandTypes.CBSTRING_INTEGER, SqlFunctionCategory.STRING);
- @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL, SPARK})
+ @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL, SPARK, HIVE})
public static final SqlFunction REPEAT =
SqlBasicFunction.create("REPEAT",
ReturnTypes.VARCHAR_NULLABLE,
@@ -1069,7 +1069,7 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding,
SqlBasicFunction.create("RIGHT", ReturnTypes.ARG0_NULLABLE_VARYING,
OperandTypes.CBSTRING_INTEGER, SqlFunctionCategory.STRING);
- @LibraryOperator(libraries = {MYSQL, SPARK})
+ @LibraryOperator(libraries = {MYSQL, SPARK, HIVE})
public static final SqlFunction SPACE =
SqlBasicFunction.create("SPACE",
ReturnTypes.VARCHAR_NULLABLE,
@@ -1083,7 +1083,7 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding,
OperandTypes.STRING_STRING,
SqlFunctionCategory.STRING);
- @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL, ORACLE})
+ @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL, ORACLE, HIVE})
public static final SqlFunction SOUNDEX =
SqlBasicFunction.create("SOUNDEX",
ReturnTypes.VARCHAR_4_NULLABLE,
@@ -1858,7 +1858,7 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding
/** The "TO_DATE(string1, string2)" function; casts string1
* to a DATE using the format specified in string2. */
- @LibraryOperator(libraries = {ORACLE, REDSHIFT})
+ @LibraryOperator(libraries = {ORACLE, REDSHIFT, HIVE})
public static final SqlFunction TO_DATE =
SqlBasicFunction.create("TO_DATE",
ReturnTypes.DATE_NULLABLE,
@@ -2427,7 +2427,7 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding
OperandTypes.STRING.or(OperandTypes.BINARY),
SqlFunctionCategory.STRING);
- @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL, SPARK})
+ @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL, SPARK, HIVE})
public static final SqlFunction SHA1 =
SqlBasicFunction.create("SHA1",
ReturnTypes.VARCHAR_NULLABLE,
@@ -2478,7 +2478,7 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding
/** The "LOG(numeric1 [, numeric2 ]) " function. Returns the logarithm of numeric2
* to base numeric1.*/
- @LibraryOperator(libraries = {MYSQL, SPARK})
+ @LibraryOperator(libraries = {MYSQL, SPARK, HIVE})
public static final SqlFunction LOG_MYSQL =
SqlBasicFunction.create(SqlKind.LOG,
ReturnTypes.DOUBLE_FORCE_NULLABLE,
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index 0288d1f88d99..73eee47d3e25 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -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 h | ADD_MONTHS(start_date, num_months) | Returns the date that is *num_months* after *start_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*
@@ -2784,7 +2784,7 @@ In the following:
| b | DATE(string) | Equivalent to `CAST(string AS DATE)`
| b | DATE(year, month, day) | Returns a DATE value for *year*, *month*, and *day* (all of type INTEGER)
| p q r | DATEADD(timeUnit, integer, datetime) | Equivalent to `TIMESTAMPADD(timeUnit, integer, datetime)`
-| p q r | DATEDIFF(timeUnit, datetime, datetime2) | Equivalent to `TIMESTAMPDIFF(timeUnit, datetime, datetime2)`
+| p q r h | DATEDIFF(timeUnit, datetime, datetime2) | Equivalent to `TIMESTAMPDIFF(timeUnit, datetime, datetime2)`
| q | DATEPART(timeUnit, datetime) | Equivalent to `EXTRACT(timeUnit FROM datetime)`
| b | DATETIME(date, time) | Converts *date* and *time* to a TIMESTAMP
| b | DATETIME(date) | Converts *date* to a TIMESTAMP value (at midnight)
@@ -2796,11 +2796,11 @@ In the following:
| b | DATETIME_TRUNC(timestamp, timeUnit) | Truncates *timestamp* to the granularity of *timeUnit*, rounding to the beginning of the unit
| 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*
+| b h | DATE_ADD(date, interval) | Returns the DATE value that occurs *interval* 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 h | 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
-| o r s | DECODE(value, value1, result1 [, valueN, resultN ]* [, default ]) | Compares *value* to each *valueN* value one by one; if *value* is equal to a *valueN*, returns the corresponding *resultN*, else returns *default*, or NULL if *default* is not specified
+| o r s h | DECODE(value, value1, result1 [, valueN, resultN ]* [, default ]) | Compares *value* to each *valueN* value one by one; if *value* is equal to a *valueN*, returns the corresponding *resultN*, else returns *default*, or NULL if *default* is not specified
| p r | DIFFERENCE(string, string) | Returns a measure of the similarity of two strings, namely the number of character positions that their `SOUNDEX` values have in common: 4 if the `SOUNDEX` values are same and 0 if the `SOUNDEX` values are totally different
| f s | ENDSWITH(string1, string2) | Returns whether *string2* is a suffix of *string1*
| b | ENDS_WITH(string1, string2) | Equivalent to `ENDSWITH(string1, string2)`
@@ -2818,12 +2818,12 @@ In the following:
| b | FORMAT_TIME(string, time) | Formats *time* according to the specified format *string*
| b | FORMAT_TIMESTAMP(string timestamp) | Formats *timestamp* according to the specified format *string*
| s | GETBIT(value, position) | Equivalent to `BIT_GET(value, position)`
-| b o p r s | GREATEST(expr [, expr ]*) | Returns the greatest of the expressions
+| b o p r s h | GREATEST(expr [, expr ]*) | Returns the greatest of the expressions
| b h s | IF(condition, value1, value2) | Returns *value1* if *condition* is TRUE, *value2* otherwise
| b s | IFNULL(value1, value2) | Equivalent to `NVL(value1, value2)`
| p | string1 ILIKE string2 [ ESCAPE string3 ] | Whether *string1* matches pattern *string2*, ignoring case (similar to `LIKE`)
| p | string1 NOT ILIKE string2 [ ESCAPE string3 ] | Whether *string1* does not match pattern *string2*, ignoring case (similar to `NOT LIKE`)
-| b o | INSTR(string, substring [, from [, occurrence ] ]) | Returns the position of *substring* in *string*, searching starting at *from* (default 1), and until locating the nth *occurrence* (default 1) of *substring*
+| b o h | INSTR(string, substring [, from [, occurrence ] ]) | Returns the position of *substring* in *string*, searching starting at *from* (default 1), and until locating the nth *occurrence* (default 1) of *substring*
| b m o | INSTR(string, substring) | Equivalent to `POSITION(substring IN string)`
| b | IS_INF(value) | Returns whether *value* is infinite
| b | IS_NAN(value) | Returns whether *value* is NaN
@@ -2837,15 +2837,16 @@ In the following:
| m | JSON_REPLACE(jsonValue, path, val [, path, val ]*) | Returns a JSON document replace a data of *jsonValue*, *path*, *val*
| m | JSON_SET(jsonValue, path, val [, path, val ]*) | Returns a JSON document set a data of *jsonValue*, *path*, *val*
| m | JSON_STORAGE_SIZE(jsonValue) | Returns the number of bytes used to store the binary representation of *jsonValue*
-| b o p r s | LEAST(expr [, expr ]* ) | Returns the least of the expressions
+| b o p r s h | LEAST(expr [, expr ]* ) | Returns the least of the expressions
| b m p r s | LEFT(string, length) | Returns the leftmost *length* characters from the *string*
| f r s | LEN(string) | Equivalent to `CHAR_LENGTH(string)`
| b f h p r s | LENGTH(string) | Equivalent to `CHAR_LENGTH(string)`
| h s | LEVENSHTEIN(string1, string2) | Returns the Levenshtein distance between *string1* and *string2*
| b | LOG(numeric1 [, base ]) | Returns the logarithm of *numeric1* to base *base*, or base e if *base* is not present, or error if *numeric1* is 0 or negative
-| m s | LOG([, base ], numeric1) | Returns the logarithm of *numeric1* to base *base*, or base e if *base* is not present, or null if *numeric1* is 0 or negative
+| m s h | LOG([, base ], numeric1) | Returns the logarithm of *numeric1* to base *base*, or base e if *base* is not present, or null if *numeric1* is 0 or negative
| p | LOG([, base ], numeric1 ) | Returns the logarithm of *numeric1* to base *base*, or base 10 if *numeric1* is not present, or error if *numeric1* is 0 or negative
| m s | LOG2(numeric) | Returns the base 2 logarithm of *numeric*
+| s | LOG1P(numeric) | Returns the natural logarithm of 1 plus *numeric*
| b o p r s | LPAD(string, length [, pattern ]) | Returns a string or bytes value that consists of *string* prepended to *length* with *pattern*
| b | TO_BASE32(string) | Converts the *string* to base-32 encoded form and returns an encoded string
| b | FROM_BASE32(string) | Returns the decoded result of a base-32 *string* as a string
@@ -2853,7 +2854,7 @@ In the following:
| b m | FROM_BASE64(string) | Returns the decoded result of a base-64 *string* as a string
| b | TO_HEX(binary) | Converts *binary* into a hexadecimal varchar
| b | FROM_HEX(varchar) | Converts a hexadecimal-encoded *varchar* into bytes
-| b o p r s | LTRIM(string) | Returns *string* with all blanks removed from the start
+| b o p r s h | LTRIM(string) | Returns *string* with all blanks removed from the start
| s | MAP() | Returns an empty map
| s | MAP(key, value [, key, value]*) | Returns a map with the given *key*/*value* pairs
| s | MAP_CONCAT(map [, map]*) | Concatenates one or more maps. If any input argument is `NULL` the function returns `NULL`. Note that calcite is using the LAST_WIN strategy
@@ -2866,7 +2867,7 @@ In the following:
| s | STR_TO_MAP(string [, stringDelimiter [, keyValueDelimiter]]) | Returns a map after splitting the *string* into key/value pairs using delimiters. Default delimiters are ',' for *stringDelimiter* and ':' for *keyValueDelimiter*. Note that calcite is using the LAST_WIN strategy
| b m p r s | MD5(string) | Calculates an MD5 128-bit checksum of *string* and returns it as a hex string
| m | MONTHNAME(date) | Returns the name, in the connection's locale, of the month in *datetime*; for example, it returns '二月' for both DATE '2020-02-10' and TIMESTAMP '2020-02-10 10:10:10'
-| o r s | NVL(value1, value2) | Returns *value1* if *value1* is not null, otherwise *value2*
+| o r s h | NVL(value1, value2) | Returns *value1* if *value1* is not null, otherwise *value2*
| o r s | NVL2(value1, value2, value3) | Returns *value2* if *value1* is not null, otherwise *value3*
| b | OFFSET(index) | When indexing an array, wrapping *index* in `OFFSET` returns the value at the 0-based *index*; throws error if *index* is out of bounds
| b | ORDINAL(index) | Similar to `OFFSET` except *index* begins at 1
@@ -2885,17 +2886,17 @@ In the following:
| b | REGEXP_INSTR(string, regexp [, position [, occurrence [, occurrence_position]]]) | Returns the lowest 1-based position of the substring in *string* that matches the *regexp*, starting search at *position* (default 1), and until locating the nth *occurrence* (default 1). Setting occurrence_position (default 0) to 1 returns the end position of substring + 1. Returns 0 if there is no match
| m o p r s | REGEXP_LIKE(string, regexp [, flags]) | Equivalent to `string1 RLIKE string2` with an optional parameter for search flags. Supported flags are:
- i: case-insensitive matching
- c: case-sensitive matching
- n: newline-sensitive matching
- s: non-newline-sensitive matching
- m: multi-line
| r | REGEXP_REPLACE(string, regexp) | Replaces all substrings of *string* that match *regexp* with the empty string
-| b m o r | REGEXP_REPLACE(string, regexp, rep [, pos [, occurrence [, matchType]]]) | Replaces all substrings of *string* that match *regexp* with *rep* at the starting *pos* in expr (if omitted, the default is 1), *occurrence* specifies which occurrence of a match to search for (if omitted, the default is 1), *matchType* specifies how to perform matching
+| b m o r h | REGEXP_REPLACE(string, regexp, rep [, pos [, occurrence [, matchType]]]) | Replaces all substrings of *string* that match *regexp* with *rep* at the starting *pos* in expr (if omitted, the default is 1), *occurrence* specifies which occurrence of a match to search for (if omitted, the default is 1), *matchType* specifies how to perform matching
| p | REGEXP_REPLACE(string, regexp, rep [, matchType]) | Replaces substrings of *string* that match *regexp* with *rep* at the starting *pos* in expr, *matchType* specifies how to perform matching and whether to only replace first match or all
| b | REGEXP_SUBSTR(string, regexp [, position [, occurrence]]) | Synonym for REGEXP_EXTRACT
-| b m p r s | REPEAT(string, integer) | Returns a string consisting of *string* repeated of *integer* times; returns an empty string if *integer* is less than 1
+| b m p r s h | REPEAT(string, integer) | Returns a string consisting of *string* repeated of *integer* times; returns an empty string if *integer* is less than 1
| b m | REVERSE(string) | Returns *string* with the order of the characters reversed
| s | REVERSE(string | array) | Returns *string* with the characters in reverse order or array with elements in reverse order
| b m p r s | RIGHT(string, length) | Returns the rightmost *length* characters from the *string*
| h m s | string1 RLIKE string2 | Whether *string1* matches regex pattern *string2* (similar to `LIKE`, but uses Java regex)
| h m s | string1 NOT RLIKE string2 | Whether *string1* does not match regex pattern *string2* (similar to `NOT LIKE`, but uses Java regex)
-| b o p r s | RPAD(string, length[, pattern ]) | Returns a string or bytes value that consists of *string* appended to *length* with *pattern*
-| b o p r s | RTRIM(string) | Returns *string* with all blanks removed from the end
+| b o p r s h | RPAD(string, length[, pattern ]) | Returns a string or bytes value that consists of *string* appended to *length* with *pattern*
+| b o p r s h | RTRIM(string) | Returns *string* with all blanks removed from the end
| b | SAFE_ADD(numeric1, numeric2) | Returns *numeric1* + *numeric2*, or NULL on overflow. Arguments are implicitly cast to one of the types BIGINT, DOUBLE, or DECIMAL
| b | SAFE_CAST(value AS type) | Converts *value* to *type*, returning NULL if conversion fails
| b | SAFE_DIVIDE(numeric1, numeric2) | Returns *numeric1* / *numeric2*, or NULL on overflow or if *numeric2* is zero. Arguments implicitly are cast to one of the types BIGINT, DOUBLE, or DECIMAL
@@ -2906,14 +2907,14 @@ In the following:
| b | SAFE_SUBTRACT(numeric1, numeric2) | Returns *numeric1* - *numeric2*, or NULL on overflow. Arguments are implicitly cast to one of the types BIGINT, DOUBLE, or DECIMAL
| * | SEC(numeric) | Returns the secant of *numeric* in radians
| * | SECH(numeric) | Returns the hyperbolic secant of *numeric*
-| b m p r s | SHA1(string) | Calculates a SHA-1 hash value of *string* and returns it as a hex string
+| b m p r s h | SHA1(string) | Calculates a SHA-1 hash value of *string* and returns it as a hex string
| b p | SHA256(string) | Calculates a SHA-256 hash value of *string* and returns it as a hex string
| b p | SHA512(string) | Calculates a SHA-512 hash value of *string* and returns it as a hex string
| p | SIND(numeric) | Returns the sine of *numeric* in degrees as a double. Returns NaN if *numeric* is NaN. Fails if *numeric* is greater than the maximum double value.
| * | SINH(numeric) | Returns the hyperbolic sine of *numeric*
-| b m o p r | SOUNDEX(string) | Returns the phonetic representation of *string*; throws if *string* is encoded with multi-byte encoding such as UTF-8
+| b m o p r h | SOUNDEX(string) | Returns the phonetic representation of *string*; throws if *string* is encoded with multi-byte encoding such as UTF-8
| s | SOUNDEX(string) | Returns the phonetic representation of *string*; return original *string* if *string* is encoded with multi-byte encoding such as UTF-8
-| m s | SPACE(integer) | Returns a string of *integer* spaces; returns an empty string if *integer* is less than 1
+| m s h | SPACE(integer) | Returns a string of *integer* spaces; returns an empty string if *integer* is less than 1
| b | SPLIT(string [, delimiter ]) | Returns the string array of *string* split at *delimiter* (if omitted, default is comma). If the *string* is empty it returns an empty array, otherwise, if the *delimiter* is empty, it returns an array containing the original *string*.
| f s | STARTSWITH(string1, string2) | Returns whether *string2* is a prefix of *string1*
| b p | STARTS_WITH(string1, string2) | Equivalent to `STARTSWITH(string1, string2)`
@@ -2945,7 +2946,7 @@ In the following:
| b | TIME_TRUNC(time, timeUnit) | Truncates *time* to the granularity of *timeUnit*, rounding to the beginning of the unit
| m o p r | TO_CHAR(timestamp, format) | Converts *timestamp* to a string using the format *format*
| b | TO_CODE_POINTS(string) | Converts *string* to an array of integers that represent code points or extended ASCII character values
-| o p r | TO_DATE(string, format) | Converts *string* to a date using the format *format*
+| o p r h | TO_DATE(string, format) | Converts *string* to a date using the format *format*
| o p r | TO_TIMESTAMP(string, format) | Converts *string* to a timestamp using the format *format*
| b o p r s | TRANSLATE(expr, fromString, toString) | Returns *expr* with all occurrences of each character in *fromString* replaced by its corresponding character in *toString*. Characters in *expr* that are not in *fromString* are not replaced
| b | TRUNC(numeric1 [, integer2 ]) | Truncates *numeric1* to optionally *integer2* (if not specified 0) places right to the decimal point
diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
index 95b3ab979837..0e19c5eefce5 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -5198,7 +5198,7 @@ void testBitGetFunc(SqlOperatorFixture f, String functionName) {
f.checkNull("to_date(NULL, NULL)");
};
final List libraries =
- list(SqlLibrary.ORACLE, SqlLibrary.REDSHIFT);
+ list(SqlLibrary.ORACLE, SqlLibrary.REDSHIFT, SqlLibrary.HIVE);
f0.forEachLibrary(libraries, consumer);
}
@@ -5400,7 +5400,7 @@ void testBitGetFunc(SqlOperatorFixture f, String functionName) {
false);
final List libraries =
ImmutableList.of(SqlLibrary.BIG_QUERY, SqlLibrary.MYSQL,
- SqlLibrary.POSTGRESQL, SqlLibrary.REDSHIFT, SqlLibrary.SPARK);
+ SqlLibrary.POSTGRESQL, SqlLibrary.REDSHIFT, SqlLibrary.SPARK, SqlLibrary.HIVE);
final Consumer consumer = f -> {
f.checkString("sha1(x'')",
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
@@ -5419,7 +5419,7 @@ void testBitGetFunc(SqlOperatorFixture f, String functionName) {
}
@Test void testSha256() {
- final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.SHA1);
+ final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.SHA256);
f0.checkFails("^sha256(x'')^",
"No match found for function signature SHA256\\(\\)",
false);
@@ -5444,7 +5444,7 @@ void testBitGetFunc(SqlOperatorFixture f, String functionName) {
}
@Test void testSha512() {
- final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.SHA1);
+ final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.SHA512);
f0.checkFails("^sha512(x'')^",
"No match found for function signature SHA512\\(\\)",
false);
@@ -5522,7 +5522,7 @@ void testBitGetFunc(SqlOperatorFixture f, String functionName) {
};
final List libraries =
list(SqlLibrary.BIG_QUERY, SqlLibrary.MYSQL,
- SqlLibrary.POSTGRESQL, SqlLibrary.SPARK);
+ SqlLibrary.POSTGRESQL, SqlLibrary.SPARK, SqlLibrary.HIVE);
f0.forEachLibrary(libraries, consumer);
}
@@ -5537,7 +5537,7 @@ void testBitGetFunc(SqlOperatorFixture f, String functionName) {
f.checkString("SPACE(5)", " ", "VARCHAR NOT NULL");
f.checkNull("SPACE(cast(null as integer))");
};
- f0.forEachLibrary(list(SqlLibrary.MYSQL, SqlLibrary.SPARK), consumer);
+ f0.forEachLibrary(list(SqlLibrary.MYSQL, SqlLibrary.SPARK, SqlLibrary.HIVE), consumer);
}
@Test void testStrcmpFunc() {
@@ -5558,7 +5558,7 @@ void testBitGetFunc(SqlOperatorFixture f, String functionName) {
false);
final List libraries =
list(SqlLibrary.BIG_QUERY, SqlLibrary.MYSQL,
- SqlLibrary.ORACLE, SqlLibrary.POSTGRESQL, SqlLibrary.REDSHIFT);
+ SqlLibrary.ORACLE, SqlLibrary.POSTGRESQL, SqlLibrary.REDSHIFT, SqlLibrary.HIVE);
final Consumer consumer = f -> {
f.checkString("SOUNDEX('TECH ON THE NET')", "T253", "VARCHAR(4) NOT NULL");
f.checkString("SOUNDEX('Miller')", "M460", "VARCHAR(4) NOT NULL");
@@ -5901,7 +5901,8 @@ private static void checkIf(SqlOperatorFixture f) {
f.checkQuery("select regexp_replace('a b c', 'b', 'X')");
};
final List libraries =
- list(SqlLibrary.BIG_QUERY, SqlLibrary.MYSQL, SqlLibrary.ORACLE, SqlLibrary.REDSHIFT);
+ list(SqlLibrary.BIG_QUERY, SqlLibrary.MYSQL, SqlLibrary.ORACLE,
+ SqlLibrary.REDSHIFT, SqlLibrary.HIVE);
f0.forEachLibrary(libraries, consumer);
// Tests to verify double-backslashes are ignored for indexing in other dialects
@@ -7337,7 +7338,7 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) {
f.checkNull("log(0)");
f.checkNull("log(-1)");
};
- f0.forEachLibrary(list(SqlLibrary.MYSQL, SqlLibrary.SPARK), consumer);
+ f0.forEachLibrary(list(SqlLibrary.MYSQL, SqlLibrary.SPARK, SqlLibrary.HIVE), consumer);
}
/** Test case for
@@ -7563,15 +7564,15 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) {
final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.SPARK);
f.checkScalar("array_contains(array[1, 2], 1)", true,
- "BOOLEAN NOT NULL");
+ "BOOLEAN NOT NULL");
f.checkScalar("array_contains(array[1], 1)", true,
- "BOOLEAN NOT NULL");
+ "BOOLEAN NOT NULL");
f.checkScalar("array_contains(array(), 1)", false,
- "BOOLEAN NOT NULL");
+ "BOOLEAN NOT NULL");
f.checkScalar("array_contains(array[array[1, 2], array[3, 4]], array[1, 2])", true,
- "BOOLEAN NOT NULL");
+ "BOOLEAN NOT NULL");
f.checkScalar("array_contains(array[map[1, 'a'], map[2, 'b']], map[1, 'a'])", true,
- "BOOLEAN NOT NULL");
+ "BOOLEAN NOT NULL");
f.checkNull("array_contains(cast(null as integer array), 1)");
f.checkType("array_contains(cast(null as integer array), 1)", "BOOLEAN");
// Flink and Spark differ on the following. The expression
@@ -7582,7 +7583,7 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) {
f.checkNull("array_contains(array[1, null], cast(null as integer))");
f.checkType("array_contains(array[1, null], cast(null as integer))", "BOOLEAN");
f.checkFails("^array_contains(array[1, 2], true)^",
- "INTEGER is not comparable to BOOLEAN", false);
+ "INTEGER is not comparable to BOOLEAN", false);
// check null without cast
f.checkNull("array_contains(array[1, 2], null)");
@@ -8270,33 +8271,33 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function,
final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.SPARK);
f.checkScalar("sort_array(array[2, null, 1])", "[null, 1, 2]",
- "INTEGER ARRAY NOT NULL");
+ "INTEGER ARRAY NOT NULL");
f.checkScalar("sort_array(array(2, null, 1), false)", "[2, 1, null]",
- "INTEGER ARRAY NOT NULL");
+ "INTEGER ARRAY NOT NULL");
f.checkScalar("sort_array(array[true, false, null])", "[null, false, true]",
- "BOOLEAN ARRAY NOT NULL");
+ "BOOLEAN ARRAY NOT NULL");
f.checkScalar("sort_array(array[true, false, null], false)", "[true, false, null]",
- "BOOLEAN ARRAY NOT NULL");
+ "BOOLEAN ARRAY NOT NULL");
f.checkScalar("sort_array(array[null])", "[null]",
- "NULL ARRAY NOT NULL");
+ "NULL ARRAY NOT NULL");
f.checkScalar("sort_array(array())", "[]",
- "UNKNOWN NOT NULL ARRAY NOT NULL");
+ "UNKNOWN NOT NULL ARRAY NOT NULL");
f.checkNull("sort_array(null)");
// elements cast
f.checkScalar("sort_array(array[cast(1 as tinyint), 2])", "[1, 2]",
- "INTEGER NOT NULL ARRAY NOT NULL");
+ "INTEGER NOT NULL ARRAY NOT NULL");
f.checkScalar("sort_array(array[null, 1, cast(2 as tinyint)])", "[null, 1, 2]",
- "INTEGER ARRAY NOT NULL");
+ "INTEGER ARRAY NOT NULL");
f.checkScalar("sort_array(array[cast(1 as bigint), 2])", "[1, 2]",
- "BIGINT NOT NULL ARRAY NOT NULL");
+ "BIGINT NOT NULL ARRAY NOT NULL");
f.checkScalar("sort_array(array[cast(1 as decimal), 2])", "[1, 2]",
- "DECIMAL(19, 0) NOT NULL ARRAY NOT NULL");
+ "DECIMAL(19, 0) NOT NULL ARRAY NOT NULL");
f.checkFails("^sort_array(array[2, null, 1], cast(1 as boolean))^",
- "Argument to function 'SORT_ARRAY' must be a literal", false);
+ "Argument to function 'SORT_ARRAY' must be a literal", false);
f.checkFails("^sort_array(array[2, null, 1], 1)^",
- "Cannot apply 'SORT_ARRAY' to arguments of type "
+ "Cannot apply 'SORT_ARRAY' to arguments of type "
+ "'SORT_ARRAY\\(, \\)'\\."
+ " Supported form\\(s\\): 'SORT_ARRAY\\(\\)'\n"
+ "'SORT_ARRAY\\(, \\)'", false);
@@ -8697,27 +8698,27 @@ void checkArrayReverseFunc(SqlOperatorFixture f0, SqlFunction function,
final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.SPARK);
f.checkScalar("str_to_map('a=1,b=2', ',', '=')", "{a=1, b=2}",
- "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
+ "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
f.checkScalar("str_to_map('a:1,b:2')", "{a=1, b=2}",
- "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
+ "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
f.checkScalar("str_to_map('a:1,b:2', ',')", "{a=1, b=2}",
- "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
+ "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
f.checkScalar("str_to_map('a=1&b=2', '&', '=')", "{a=1, b=2}",
- "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
+ "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
f.checkScalar("str_to_map('k#2%v#3', '%', '#')", "{k=2, v=3}",
- "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
+ "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
f.checkScalar("str_to_map('a:1&b:2', '&')", "{a=1, b=2}",
- "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
+ "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
f.checkScalar("str_to_map('k:2%v:3', '%')", "{k=2, v=3}",
- "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
+ "(CHAR(7) NOT NULL, CHAR(7) NOT NULL) MAP NOT NULL");
f.checkScalar("str_to_map('a')", "{a=null}",
- "(CHAR(1) NOT NULL, CHAR(1) NOT NULL) MAP NOT NULL");
+ "(CHAR(1) NOT NULL, CHAR(1) NOT NULL) MAP NOT NULL");
f.checkScalar("str_to_map('a,b,c')", "{a=null, b=null, c=null}",
- "(CHAR(5) NOT NULL, CHAR(5) NOT NULL) MAP NOT NULL");
+ "(CHAR(5) NOT NULL, CHAR(5) NOT NULL) MAP NOT NULL");
f.checkScalar("str_to_map('a-b--c', '--')", "{a-b=null, c=null}",
- "(CHAR(6) NOT NULL, CHAR(6) NOT NULL) MAP NOT NULL");
+ "(CHAR(6) NOT NULL, CHAR(6) NOT NULL) MAP NOT NULL");
f.checkType("str_to_map(cast(null as varchar))",
- "(VARCHAR, VARCHAR) MAP");
+ "(VARCHAR, VARCHAR) MAP");
f.checkNull("str_to_map(cast(null as varchar))");
f.checkNull("str_to_map(null, ',', ':')");
f.checkNull("str_to_map('a:1,b:2,c:3', null, ':')");
@@ -10499,7 +10500,7 @@ private void testCurrentDateFunc(Pair pair) {
};
final List libraries =
list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.POSTGRESQL,
- SqlLibrary.REDSHIFT, SqlLibrary.SPARK);
+ SqlLibrary.REDSHIFT, SqlLibrary.SPARK, SqlLibrary.HIVE);
f0.forEachLibrary(libraries, consumer);
}
@@ -11245,7 +11246,7 @@ void assertSubFunReturns(boolean binary, String s, int start,
};
final List libraries =
list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.POSTGRESQL,
- SqlLibrary.REDSHIFT, SqlLibrary.SPARK);
+ SqlLibrary.REDSHIFT, SqlLibrary.SPARK, SqlLibrary.HIVE);
f0.forEachLibrary(libraries, consumer);
}
@@ -11261,7 +11262,7 @@ void assertSubFunReturns(boolean binary, String s, int start,
};
final List libraries =
list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.POSTGRESQL,
- SqlLibrary.REDSHIFT, SqlLibrary.SPARK);
+ SqlLibrary.REDSHIFT, SqlLibrary.SPARK, SqlLibrary.HIVE);
f0.forEachLibrary(libraries, consumer);
}
@@ -11285,7 +11286,7 @@ void assertSubFunReturns(boolean binary, String s, int start,
"VARCHAR(5) NOT NULL");
};
final List libraries =
- list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.SPARK);
+ list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.SPARK, SqlLibrary.HIVE);
f0.forEachLibrary(libraries, consumer);
}
@@ -11307,7 +11308,8 @@ void assertSubFunReturns(boolean binary, String s, int start,
f.checkScalar("greatest(CAST(NULL AS INTEGER), CAST(NULL AS INTEGER))", isNullValue(),
"INTEGER");
};
- final List libraries = list(SqlLibrary.POSTGRESQL, SqlLibrary.REDSHIFT);
+ final List libraries =
+ list(SqlLibrary.POSTGRESQL, SqlLibrary.REDSHIFT);
f0.forEachLibrary(libraries, consumer);
}
@@ -11331,7 +11333,7 @@ void assertSubFunReturns(boolean binary, String s, int start,
"VARCHAR(5) NOT NULL");
};
final List libraries =
- list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.SPARK);
+ list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.SPARK, SqlLibrary.HIVE);
f0.forEachLibrary(libraries, consumer);
}
@@ -11445,6 +11447,7 @@ void checkNvl(SqlOperatorFixture f0, FunctionAlias functionAlias) {
@Test void testDecodeFunc() {
checkDecodeFunc(fixture().withLibrary(SqlLibrary.ORACLE));
checkDecodeFunc(fixture().withLibrary(SqlLibrary.REDSHIFT));
+ checkDecodeFunc(fixture().withLibrary(SqlLibrary.HIVE));
checkDecodeFunc(fixture().withLibrary(SqlLibrary.SPARK));
}
@@ -13809,32 +13812,34 @@ void testTimestampDiff(boolean coercionEnabled) {
"No match found for function signature "
+ "DATE_ADD\\(, \\)", false);
- final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.BIG_QUERY);
- f.checkScalar("date_add(date '2016-02-22', interval 2 day)",
- "2016-02-24",
- "DATE NOT NULL");
- f.checkScalar("date_add(date '2016-02-17', interval 1 week)",
- "2016-02-24",
- "DATE NOT NULL");
- f.checkScalar("date_add(date '2016-02-10', interval 2 weeks)",
- "2016-02-24",
- "DATE NOT NULL");
- f.checkScalar("date_add(date '2020-10-17', interval 0 week)",
- "2020-10-17",
- "DATE NOT NULL");
- f.checkScalar("date_add(date '2016-11-24', interval 3 month)",
- "2017-02-24",
- "DATE NOT NULL");
- f.checkScalar("date_add(date '2015-11-24', interval 1 quarter)",
- "2016-02-24",
- "DATE NOT NULL");
- f.checkScalar("date_add(date '2015-08-24', interval 2 quarters)",
- "2016-02-24",
- "DATE NOT NULL");
- f.checkScalar("date_add(date '2011-02-24', interval 5 year)",
- "2016-02-24",
- "DATE NOT NULL");
- f.checkNull("date_add(CAST(NULL AS DATE), interval 5 day)");
+ final Consumer consumer = f -> {
+ f.checkScalar("date_add(date '2016-02-22', interval 2 day)",
+ "2016-02-24",
+ "DATE NOT NULL");
+ f.checkScalar("date_add(date '2016-02-17', interval 1 week)",
+ "2016-02-24",
+ "DATE NOT NULL");
+ f.checkScalar("date_add(date '2016-02-10', interval 2 weeks)",
+ "2016-02-24",
+ "DATE NOT NULL");
+ f.checkScalar("date_add(date '2020-10-17', interval 0 week)",
+ "2020-10-17",
+ "DATE NOT NULL");
+ f.checkScalar("date_add(date '2016-11-24', interval 3 month)",
+ "2017-02-24",
+ "DATE NOT NULL");
+ f.checkScalar("date_add(date '2015-11-24', interval 1 quarter)",
+ "2016-02-24",
+ "DATE NOT NULL");
+ f.checkScalar("date_add(date '2015-08-24', interval 2 quarters)",
+ "2016-02-24",
+ "DATE NOT NULL");
+ f.checkScalar("date_add(date '2011-02-24', interval 5 year)",
+ "2016-02-24",
+ "DATE NOT NULL");
+ f.checkNull("date_add(CAST(NULL AS DATE), interval 5 day)");
+ };
+ f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.HIVE), consumer);
}
/** Test case for
@@ -13901,7 +13906,7 @@ void testTimestampDiff(boolean coercionEnabled) {
f.checkNull("add_months(date '2016-02-22', CAST(NULL AS INTEGER))");
f.checkNull("add_months(CAST(NULL AS DATE), CAST(NULL AS INTEGER))");
};
- f0.forEachLibrary(list(SqlLibrary.ORACLE, SqlLibrary.SPARK), consumer);
+ f0.forEachLibrary(list(SqlLibrary.ORACLE, SqlLibrary.SPARK, SqlLibrary.HIVE), consumer);
}
@Test void testDateSub() {
@@ -13912,32 +13917,34 @@ void testTimestampDiff(boolean coercionEnabled) {
"No match found for function signature "
+ "DATE_SUB\\(, \\)", false);
- final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.BIG_QUERY);
- f.checkScalar("date_sub(date '2016-02-24', interval 2 day)",
- "2016-02-22",
- "DATE NOT NULL");
- f.checkScalar("date_sub(date '2016-02-24', interval 1 week)",
- "2016-02-17",
- "DATE NOT NULL");
- f.checkScalar("date_sub(date '2016-02-24', interval 2 weeks)",
- "2016-02-10",
- "DATE NOT NULL");
- f.checkScalar("date_sub(date '2020-10-17', interval 0 week)",
- "2020-10-17",
- "DATE NOT NULL");
- f.checkScalar("date_sub(date '2016-02-24', interval 3 month)",
- "2015-11-24",
- "DATE NOT NULL");
- f.checkScalar("date_sub(date '2016-02-24', interval 1 quarter)",
- "2015-11-24",
- "DATE NOT NULL");
- f.checkScalar("date_sub(date '2016-02-24', interval 2 quarters)",
- "2015-08-24",
- "DATE NOT NULL");
- f.checkScalar("date_sub(date '2016-02-24', interval 5 year)",
- "2011-02-24",
- "DATE NOT NULL");
- f.checkNull("date_sub(CAST(NULL AS DATE), interval 5 day)");
+ final Consumer consumer = f -> {
+ f.checkScalar("date_sub(date '2016-02-24', interval 2 day)",
+ "2016-02-22",
+ "DATE NOT NULL");
+ f.checkScalar("date_sub(date '2016-02-24', interval 1 week)",
+ "2016-02-17",
+ "DATE NOT NULL");
+ f.checkScalar("date_sub(date '2016-02-24', interval 2 weeks)",
+ "2016-02-10",
+ "DATE NOT NULL");
+ f.checkScalar("date_sub(date '2020-10-17', interval 0 week)",
+ "2020-10-17",
+ "DATE NOT NULL");
+ f.checkScalar("date_sub(date '2016-02-24', interval 3 month)",
+ "2015-11-24",
+ "DATE NOT NULL");
+ f.checkScalar("date_sub(date '2016-02-24', interval 1 quarter)",
+ "2015-11-24",
+ "DATE NOT NULL");
+ f.checkScalar("date_sub(date '2016-02-24', interval 2 quarters)",
+ "2015-08-24",
+ "DATE NOT NULL");
+ f.checkScalar("date_sub(date '2016-02-24', interval 5 year)",
+ "2011-02-24",
+ "DATE NOT NULL");
+ f.checkNull("date_sub(CAST(NULL AS DATE), interval 5 day)");
+ };
+ f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.HIVE), consumer);
}
/** Tests for BigQuery's DATETIME_SUB() function. Because the operator