From b5091fe94d38ee952bde116ba6e04f00deb7308a Mon Sep 17 00:00:00 2001 From: YiwenWu Date: Sat, 3 Feb 2024 18:03:02 +0800 Subject: [PATCH] [CALCITE-6241] Enable a few existing functions to Spark library Functions List: DECODE, NVL, IFNULL, LEN, LENGTH, LPAD, RPAD, LTRIM, RTRIM, ENDSWITH, STARTSWITH, GREATEST, LEAST, TRANSLATE, BOOL_AND, BOOL_OR, DATE_FROM_UNIX_DATE, UNIX_DATE, LEFT, REPEAT, RIGHT, SPACE TIMESTAMP_SECONDS, TIMESTAMP_MILLIS, TIMESTAMP_MICROS, UNIX_SECONDS, UNIX_MILLIS, UNIX_MICROS, MD5, SHA1, POW --- .../calcite/sql/fun/SqlLibraryOperators.java | 62 +++---- site/_docs/reference.md | 62 +++---- .../apache/calcite/test/SqlOperatorTest.java | 159 ++++++++++-------- 3 files changed, 151 insertions(+), 132 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 d397f008b22..e8dac9d7a9c 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 @@ -232,7 +232,7 @@ private static SqlCall transformConvert(SqlValidator validator, SqlCall call) { }; /** The "DECODE(v, v1, result1, [v2, result2, ...], resultN)" function. */ - @LibraryOperator(libraries = {ORACLE}) + @LibraryOperator(libraries = {ORACLE, SPARK}) public static final SqlFunction DECODE = SqlBasicFunction.create(SqlKind.DECODE, DECODE_RETURN_TYPE, OperandTypes.VARIADIC); @@ -263,7 +263,7 @@ private static SqlCall transformConvert(SqlValidator validator, SqlCall call) { } /** The "NVL(value, value)" function. */ - @LibraryOperator(libraries = {ORACLE}) + @LibraryOperator(libraries = {ORACLE, SPARK}) public static final SqlBasicFunction NVL = SqlBasicFunction.create(SqlKind.NVL, ReturnTypes.LEAST_RESTRICTIVE @@ -271,16 +271,16 @@ private static SqlCall transformConvert(SqlValidator validator, SqlCall call) { OperandTypes.SAME_SAME); /** The "IFNULL(value, value)" function. */ - @LibraryOperator(libraries = {BIG_QUERY}) + @LibraryOperator(libraries = {BIG_QUERY, SPARK}) public static final SqlFunction IFNULL = NVL.withName("IFNULL"); /** The "LEN(string)" function. */ - @LibraryOperator(libraries = {SNOWFLAKE}) + @LibraryOperator(libraries = {SNOWFLAKE, SPARK}) public static final SqlFunction LEN = SqlStdOperatorTable.CHAR_LENGTH.withName("LEN"); /** The "LENGTH(string)" function. */ - @LibraryOperator(libraries = {BIG_QUERY, SNOWFLAKE}) + @LibraryOperator(libraries = {BIG_QUERY, SNOWFLAKE, SPARK}) public static final SqlFunction LENGTH = SqlStdOperatorTable.CHAR_LENGTH.withName("LENGTH"); @@ -291,7 +291,7 @@ private static RelDataType deriveTypePad(SqlOperatorBinding binding, RelDataType } /** The "LPAD(original_value, return_length[, pattern])" function. */ - @LibraryOperator(libraries = {BIG_QUERY, ORACLE}) + @LibraryOperator(libraries = {BIG_QUERY, ORACLE, SPARK}) public static final SqlFunction LPAD = SqlBasicFunction.create( "LPAD", @@ -300,7 +300,7 @@ private static RelDataType deriveTypePad(SqlOperatorBinding binding, RelDataType SqlFunctionCategory.STRING); /** The "RPAD(original_value, return_length[, pattern])" function. */ - @LibraryOperator(libraries = {BIG_QUERY, ORACLE}) + @LibraryOperator(libraries = {BIG_QUERY, ORACLE, SPARK}) public static final SqlFunction RPAD = SqlBasicFunction.create( "RPAD", @@ -309,7 +309,7 @@ private static RelDataType deriveTypePad(SqlOperatorBinding binding, RelDataType SqlFunctionCategory.STRING); /** The "LTRIM(string)" function. */ - @LibraryOperator(libraries = {BIG_QUERY, ORACLE}) + @LibraryOperator(libraries = {BIG_QUERY, ORACLE, SPARK}) public static final SqlFunction LTRIM = SqlBasicFunction.create(SqlKind.LTRIM, ReturnTypes.ARG0.andThen(SqlTypeTransforms.TO_NULLABLE) @@ -318,7 +318,7 @@ private static RelDataType deriveTypePad(SqlOperatorBinding binding, RelDataType .withFunctionType(SqlFunctionCategory.STRING); /** The "RTRIM(string)" function. */ - @LibraryOperator(libraries = {BIG_QUERY, ORACLE}) + @LibraryOperator(libraries = {BIG_QUERY, ORACLE, SPARK}) public static final SqlFunction RTRIM = SqlBasicFunction.create(SqlKind.RTRIM, ReturnTypes.ARG0.andThen(SqlTypeTransforms.TO_NULLABLE) @@ -373,7 +373,7 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding, OperandTypes.STRING_SAME_SAME); /** The "ENDSWITH(value1, value2)" function (Snowflake). */ - @LibraryOperator(libraries = {SNOWFLAKE}) + @LibraryOperator(libraries = {SNOWFLAKE, SPARK}) public static final SqlFunction ENDSWITH = ENDS_WITH.withName("ENDSWITH"); /** The "STARTS_WITH(value1, value2)" function (BigQuery, PostgreSQL). */ @@ -383,7 +383,7 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding, OperandTypes.STRING_SAME_SAME); /** The "STARTSWITH(value1, value2)" function (Snowflake). */ - @LibraryOperator(libraries = {SNOWFLAKE}) + @LibraryOperator(libraries = {SNOWFLAKE, SPARK}) public static final SqlFunction STARTSWITH = STARTS_WITH.withName("STARTSWITH"); /** BigQuery's "SUBSTR(string, position [, substringLength ])" function. */ @@ -436,14 +436,14 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding, SqlFunctionCategory.STRING); /** The "GREATEST(value, value)" function. */ - @LibraryOperator(libraries = {BIG_QUERY, ORACLE}) + @LibraryOperator(libraries = {BIG_QUERY, ORACLE, SPARK}) public static final SqlFunction GREATEST = SqlBasicFunction.create(SqlKind.GREATEST, ReturnTypes.LEAST_RESTRICTIVE.andThen(SqlTypeTransforms.TO_NULLABLE), OperandTypes.SAME_VARIADIC); /** The "LEAST(value, value)" function. */ - @LibraryOperator(libraries = {BIG_QUERY, ORACLE}) + @LibraryOperator(libraries = {BIG_QUERY, ORACLE, SPARK}) public static final SqlFunction LEAST = SqlBasicFunction.create(SqlKind.LEAST, ReturnTypes.LEAST_RESTRICTIVE.andThen(SqlTypeTransforms.TO_NULLABLE), @@ -472,7 +472,7 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding, *

It is not defined in the SQL standard, but occurs in Oracle and * PostgreSQL. */ - @LibraryOperator(libraries = {BIG_QUERY, ORACLE, POSTGRESQL}) + @LibraryOperator(libraries = {BIG_QUERY, ORACLE, POSTGRESQL, SPARK}) public static final SqlFunction TRANSLATE3 = new SqlTranslate3Function(); @LibraryOperator(libraries = {MYSQL}) @@ -602,13 +602,13 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding, /** The "BOOL_AND(condition)" aggregate function, PostgreSQL and Redshift's * equivalent to {@link SqlStdOperatorTable#EVERY}. */ - @LibraryOperator(libraries = {POSTGRESQL}) + @LibraryOperator(libraries = {POSTGRESQL, SPARK}) public static final SqlAggFunction BOOL_AND = new SqlMinMaxAggFunction("BOOL_AND", SqlKind.MIN, OperandTypes.BOOLEAN); /** The "BOOL_OR(condition)" aggregate function, PostgreSQL and Redshift's * equivalent to {@link SqlStdOperatorTable#SOME}. */ - @LibraryOperator(libraries = {POSTGRESQL}) + @LibraryOperator(libraries = {POSTGRESQL, SPARK}) public static final SqlAggFunction BOOL_OR = new SqlMinMaxAggFunction("BOOL_OR", SqlKind.MAX, OperandTypes.BOOLEAN); @@ -857,7 +857,7 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding, /** The "DATE_FROM_UNIX_DATE(integer)" function; returns a DATE value * a given number of seconds after 1970-01-01. */ - @LibraryOperator(libraries = {BIG_QUERY}) + @LibraryOperator(libraries = {BIG_QUERY, SPARK}) public static final SqlFunction DATE_FROM_UNIX_DATE = SqlBasicFunction.create("DATE_FROM_UNIX_DATE", ReturnTypes.DATE_NULLABLE, OperandTypes.INTEGER, @@ -865,7 +865,7 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding, /** The "UNIX_DATE(date)" function; returns the number of days since * 1970-01-01. */ - @LibraryOperator(libraries = {BIG_QUERY}) + @LibraryOperator(libraries = {BIG_QUERY, SPARK}) public static final SqlFunction UNIX_DATE = SqlBasicFunction.create("UNIX_DATE", ReturnTypes.INTEGER_NULLABLE, OperandTypes.DATE, @@ -896,25 +896,25 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding, ReturnTypes.VARCHAR_2000, OperandTypes.DATETIME, SqlFunctionCategory.TIMEDATE); - @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL}) + @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL, SPARK}) public static final SqlFunction LEFT = SqlBasicFunction.create("LEFT", ReturnTypes.ARG0_NULLABLE_VARYING, OperandTypes.CBSTRING_INTEGER, SqlFunctionCategory.STRING); - @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL}) + @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL, SPARK}) public static final SqlFunction REPEAT = SqlBasicFunction.create("REPEAT", ReturnTypes.VARCHAR_NULLABLE, OperandTypes.STRING_INTEGER, SqlFunctionCategory.STRING); - @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL}) + @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL, SPARK}) public static final SqlFunction RIGHT = SqlBasicFunction.create("RIGHT", ReturnTypes.ARG0_NULLABLE_VARYING, OperandTypes.CBSTRING_INTEGER, SqlFunctionCategory.STRING); - @LibraryOperator(libraries = {MYSQL}) + @LibraryOperator(libraries = {MYSQL, SPARK}) public static final SqlFunction SPACE = SqlBasicFunction.create("SPACE", ReturnTypes.VARCHAR_NULLABLE, @@ -1842,7 +1842,7 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding /** The "TIMESTAMP_SECONDS(bigint)" function; returns a TIMESTAMP value * a given number of seconds after 1970-01-01 00:00:00. */ - @LibraryOperator(libraries = {BIG_QUERY}) + @LibraryOperator(libraries = {BIG_QUERY, SPARK}) public static final SqlFunction TIMESTAMP_SECONDS = SqlBasicFunction.create("TIMESTAMP_SECONDS", ReturnTypes.TIMESTAMP_NULLABLE, OperandTypes.INTEGER, @@ -1850,7 +1850,7 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding /** The "TIMESTAMP_MILLIS(bigint)" function; returns a TIMESTAMP value * a given number of milliseconds after 1970-01-01 00:00:00. */ - @LibraryOperator(libraries = {BIG_QUERY}) + @LibraryOperator(libraries = {BIG_QUERY, SPARK}) public static final SqlFunction TIMESTAMP_MILLIS = SqlBasicFunction.create("TIMESTAMP_MILLIS", ReturnTypes.TIMESTAMP_NULLABLE, OperandTypes.INTEGER, @@ -1858,7 +1858,7 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding /** The "TIMESTAMP_MICROS(bigint)" function; returns a TIMESTAMP value * a given number of micro-seconds after 1970-01-01 00:00:00. */ - @LibraryOperator(libraries = {BIG_QUERY}) + @LibraryOperator(libraries = {BIG_QUERY, SPARK}) public static final SqlFunction TIMESTAMP_MICROS = SqlBasicFunction.create("TIMESTAMP_MICROS", ReturnTypes.TIMESTAMP_NULLABLE, OperandTypes.INTEGER, @@ -1866,14 +1866,14 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding /** The "UNIX_SECONDS(bigint)" function; returns the number of seconds * since 1970-01-01 00:00:00. */ - @LibraryOperator(libraries = {BIG_QUERY}) + @LibraryOperator(libraries = {BIG_QUERY, SPARK}) public static final SqlFunction UNIX_SECONDS = SqlBasicFunction.create("UNIX_SECONDS", ReturnTypes.BIGINT_NULLABLE, OperandTypes.TIMESTAMP, SqlFunctionCategory.TIMEDATE); /** The "UNIX_MILLIS(bigint)" function; returns the number of milliseconds * since 1970-01-01 00:00:00. */ - @LibraryOperator(libraries = {BIG_QUERY}) + @LibraryOperator(libraries = {BIG_QUERY, SPARK}) public static final SqlFunction UNIX_MILLIS = SqlBasicFunction.create("UNIX_MILLIS", ReturnTypes.BIGINT_NULLABLE, OperandTypes.TIMESTAMP, @@ -1881,7 +1881,7 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding /** The "UNIX_MICROS(bigint)" function; returns the number of microseconds * since 1970-01-01 00:00:00. */ - @LibraryOperator(libraries = {BIG_QUERY}) + @LibraryOperator(libraries = {BIG_QUERY, SPARK}) public static final SqlFunction UNIX_MICROS = SqlBasicFunction.create("UNIX_MICROS", ReturnTypes.BIGINT_NULLABLE, OperandTypes.TIMESTAMP, @@ -2093,14 +2093,14 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding OperandTypes.INTEGER, SqlFunctionCategory.NUMERIC); - @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL}) + @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL, SPARK}) public static final SqlFunction MD5 = SqlBasicFunction.create("MD5", ReturnTypes.VARCHAR_NULLABLE, OperandTypes.STRING.or(OperandTypes.BINARY), SqlFunctionCategory.STRING); - @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL}) + @LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL, SPARK}) public static final SqlFunction SHA1 = SqlBasicFunction.create("SHA1", ReturnTypes.VARCHAR_NULLABLE, @@ -2149,7 +2149,7 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding OperandTypes.NUMERIC_OPTIONAL_NUMERIC, SqlFunctionCategory.NUMERIC); - @LibraryOperator(libraries = {BIG_QUERY}) + @LibraryOperator(libraries = {BIG_QUERY, SPARK}) public static final SqlFunction POW = SqlStdOperatorTable.POWER.withName("POW"); diff --git a/site/_docs/reference.md b/site/_docs/reference.md index 6b9ba283057..433a62ad7f5 100644 --- a/site/_docs/reference.md +++ b/site/_docs/reference.md @@ -2734,15 +2734,15 @@ In the following: | b | DATETIME_DIFF(timestamp, timestamp2, timeUnit) | Returns the whole number of *timeUnit* between *timestamp* and *timestamp2* | b | DATETIME_SUB(timestamp, interval) | Returns the TIMESTAMP that occurs *interval* before *timestamp* | b | DATETIME_TRUNC(timestamp, timeUnit) | Truncates *timestamp* to the granularity of *timeUnit*, rounding to the beginning of the unit -| b | DATE_FROM_UNIX_DATE(integer) | Returns the DATE that is *integer* days after 1970-01-01 +| b s | DATE_FROM_UNIX_DATE(integer) | Returns the DATE that is *integer* days after 1970-01-01 | p | 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 | 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 -| o | 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 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 | p | 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 | ENDSWITH(string1, string2) | Returns whether *string2* is a suffix of *string1* +| f s | ENDSWITH(string1, string2) | Returns whether *string2* is a suffix of *string1* | b p | ENDS_WITH(string1, string2) | Equivalent to `ENDSWITH(string1, string2)` | s | EXISTS(array, func) | Returns whether a predicate *func* holds for one or more elements in the *array* | o | EXISTSNODE(xml, xpath, [, namespaces ]) | Determines whether traversal of a XML document using a specified xpath results in any nodes. Returns 0 if no nodes remain after applying the XPath traversal on the document fragment of the element or elements matched by the XPath expression. Returns 1 if any nodes remain. The optional namespace value that specifies a default mapping or namespace mapping for prefixes, which is used when evaluating the XPath expression. @@ -2758,9 +2758,9 @@ 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 | GREATEST(expr [, expr ]*) | Returns the greatest of the expressions +| b o s | 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 | IFNULL(value1, value2) | Equivalent to `NVL(value1, value2)` +| 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* @@ -2777,20 +2777,20 @@ 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 | LEAST(expr [, expr ]* ) | Returns the least of the expressions -| b m p | LEFT(string, length) | Returns the leftmost *length* characters from the *string* -| f | LEN(string) | Equivalent to `CHAR_LENGTH(string)` -| b f | LENGTH(string) | Equivalent to `CHAR_LENGTH(string)` +| b o s | LEAST(expr [, expr ]* ) | Returns the least of the expressions +| b m p s | LEFT(string, length) | Returns the leftmost *length* characters from the *string* +| f s | LEN(string) | Equivalent to `CHAR_LENGTH(string)` +| b f s | LENGTH(string) | Equivalent to `CHAR_LENGTH(string)` | h s | LEVENSHTEIN(string1, string2) | Returns the Levenshtein distance between *string1* and *string2* | b | LOG(numeric1 [, numeric2 ]) | Returns the logarithm of *numeric1* to base *numeric2*, or base e if *numeric2* is not present -| b o | LPAD(string, length [, pattern ]) | Returns a string or bytes value that consists of *string* prepended to *length* with *pattern* +| b o 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 | m | TO_BASE64(string) | Converts the *string* to base-64 encoded form and returns a encoded string | 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 | LTRIM(string) | Returns *string* with all blanks removed from the start +| b o s | 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 @@ -2801,9 +2801,9 @@ In the following: | s | MAP_FROM_ARRAYS(array1, array2) | Returns a map created from an *array1* and *array2*. Note that the lengths of two arrays should be the same and calcite is using the LAST_WIN strategy | s | MAP_FROM_ENTRIES(arrayOfRows) | Returns a map created from an arrays of row with two fields. Note that the number of fields in a row must be 2. Note that calcite is using the LAST_WIN strategy | 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 | MD5(string) | Calculates an MD5 128-bit checksum of *string* and returns it as a hex string +| b m p 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 | NVL(value1, value2) | Returns *value1* if *value1* is not null, otherwise *value2* +| o s | NVL(value1, value2) | Returns *value1* if *value1* is not null, otherwise *value2* | 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 | b | PARSE_DATE(format, string) | Uses format specified by *format* to convert *string* representation of date to a DATE value @@ -2811,20 +2811,20 @@ In the following: | b | PARSE_TIME(format, string) | Uses format specified by *format* to convert *string* representation of time to a TIME value | b | PARSE_TIMESTAMP(format, string[, timeZone]) | Uses format specified by *format* to convert *string* representation of timestamp to a TIMESTAMP WITH LOCAL TIME ZONE value in *timeZone* | h s | PARSE_URL(urlString, partToExtract [, keyToExtract] ) | Returns the specified *partToExtract* from the *urlString*. Valid values for *partToExtract* include HOST, PATH, QUERY, REF, PROTOCOL, AUTHORITY, FILE, and USERINFO. *keyToExtract* specifies which query to extract -| b | POW(numeric1, numeric2) | Returns *numeric1* raised to the power *numeric2* +| b s | POW(numeric1, numeric2) | Returns *numeric1* raised to the power *numeric2* | b | REGEXP_CONTAINS(string, regexp) | Returns whether *string* is a partial match for the *regexp* | b | REGEXP_EXTRACT(string, regexp [, position [, occurrence]]) | Returns the substring in *string* that matches the *regexp*, starting search at *position* (default 1), and until locating the nth *occurrence* (default 1). Returns NULL if there is no match | b | REGEXP_EXTRACT_ALL(string, regexp) | Returns an array of all substrings in *string* that matches the *regexp*. Returns an empty array if there is no match | 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 | b m o | 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 | REGEXP_SUBSTR(string, regexp [, position [, occurrence]]) | Synonym for REGEXP_EXTRACT -| b m p | 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 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 | REVERSE(string) | Returns *string* with the order of the characters reversed -| b m p | RIGHT(string, length) | Returns the rightmost *length* characters from the *string* +| b m p s | RIGHT(string, length) | Returns the rightmost *length* characters from the *string* | h s | string1 RLIKE string2 | Whether *string1* matches regex pattern *string2* (similar to `LIKE`, but uses Java regex) | h s | string1 NOT RLIKE string2 | Whether *string1* does not match regex pattern *string2* (similar to `NOT LIKE`, but uses Java regex) -| b o | RPAD(string, length[, pattern ]) | Returns a string or bytes value that consists of *string* appended to *length* with *pattern* -| b o | RTRIM(string) | Returns *string* with all blanks removed from the end +| b o s | RPAD(string, length[, pattern ]) | Returns a string or bytes value that consists of *string* appended to *length* with *pattern* +| b o s | RTRIM(string) | Returns *string* with all blanks removed from the end | b | SAFE_ADD(numeric1, numeric2) | Returns *numeric1* + *numeric2*, or NULL on overflow | 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 @@ -2835,15 +2835,15 @@ In the following: | b | SAFE_SUBTRACT(numeric1, numeric2) | Returns *numeric1* - *numeric2*, or NULL on overflow | * | SEC(numeric) | Returns the secant of *numeric* in radians | * | SECH(numeric) | Returns the hyperbolic secant of *numeric* -| b m p | SHA1(string) | Calculates a SHA-1 hash value of *string* and returns it as a hex string +| b m p s | 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 | * | SINH(numeric) | Returns the hyperbolic sine of *numeric* | b m o p | 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 | SPACE(integer) | Returns a string of *integer* spaces; returns an empty string if *integer* is less than 1 +| m s | 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 | STARTSWITH(string1, string2) | Returns whether *string2* is a prefix of *string1* +| f s | STARTSWITH(string1, string2) | Returns whether *string2* is a prefix of *string1* | b p | STARTS_WITH(string1, string2) | Equivalent to `STARTSWITH(string1, string2)` | m | STRCMP(string, string) | Returns 0 if both of the strings are same and returns -1 when the first argument is smaller than the second and 1 when the second one is smaller than the first one | b p | STRPOS(string, substring) | Equivalent to `POSITION(substring IN string)` @@ -2861,9 +2861,9 @@ In the following: | b | TIMESTAMP(timestamp, timeZone) | Converts *timestamp* to a TIMESTAMP WITH LOCAL TIME ZONE, in *timeZone* | b | TIMESTAMP_ADD(timestamp, interval) | Returns the TIMESTAMP value that occurs *interval* after *timestamp* | b | TIMESTAMP_DIFF(timestamp, timestamp2, timeUnit) | Returns the whole number of *timeUnit* between *timestamp* and *timestamp2*. Equivalent to `TIMESTAMPDIFF(timeUnit, timestamp2, timestamp)` and `(timestamp - timestamp2) timeUnit` -| b | TIMESTAMP_MICROS(integer) | Returns the TIMESTAMP that is *integer* microseconds after 1970-01-01 00:00:00 -| b | TIMESTAMP_MILLIS(integer) | Returns the TIMESTAMP that is *integer* milliseconds after 1970-01-01 00:00:00 -| b | TIMESTAMP_SECONDS(integer) | Returns the TIMESTAMP that is *integer* seconds after 1970-01-01 00:00:00 +| b s | TIMESTAMP_MICROS(integer) | Returns the TIMESTAMP that is *integer* microseconds after 1970-01-01 00:00:00 +| b s | TIMESTAMP_MILLIS(integer) | Returns the TIMESTAMP that is *integer* milliseconds after 1970-01-01 00:00:00 +| b s | TIMESTAMP_SECONDS(integer) | Returns the TIMESTAMP that is *integer* seconds after 1970-01-01 00:00:00 | b | TIMESTAMP_SUB(timestamp, interval) | Returns the TIMESTAMP value that is *interval* before *timestamp* | b | TIMESTAMP_TRUNC(timestamp, timeUnit) | Truncates *timestamp* to the granularity of *timeUnit*, rounding to the beginning of the unit | b | TIME_ADD(time, interval) | Adds *interval* to *time*, independent of any time zone @@ -2874,13 +2874,13 @@ In the following: | b | TO_CODE_POINTS(string) | Converts *string* to an array of integers that represent code points or extended ASCII character values | o p | TO_DATE(string, format) | Converts *string* to a date using the format *format* | o p | TO_TIMESTAMP(string, format) | Converts *string* to a timestamp using the format *format* -| b o p | 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 o p 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 [, numeric2 ]) | Truncates *numeric1* to optionally *numeric2* (if not specified 0) places right to the decimal point | q | TRY_CAST(value AS type) | Converts *value* to *type*, returning NULL if conversion fails -| b | UNIX_MICROS(timestamp) | Returns the number of microseconds since 1970-01-01 00:00:00 -| b | UNIX_MILLIS(timestamp) | Returns the number of milliseconds since 1970-01-01 00:00:00 -| b | UNIX_SECONDS(timestamp) | Returns the number of seconds since 1970-01-01 00:00:00 -| b | UNIX_DATE(date) | Returns the number of days since 1970-01-01 +| b s | UNIX_MICROS(timestamp) | Returns the number of microseconds since 1970-01-01 00:00:00 +| b s | UNIX_MILLIS(timestamp) | Returns the number of milliseconds since 1970-01-01 00:00:00 +| b s | UNIX_SECONDS(timestamp) | Returns the number of seconds since 1970-01-01 00:00:00 +| b s | UNIX_DATE(date) | Returns the number of days since 1970-01-01 | s | URL_DECODE(string) | Decodes a *string* in 'application/x-www-form-urlencoded' format using a specific encoding scheme, returns original *string* when decoded error | s | URL_ENCODE(string) | Translates a *string* into 'application/x-www-form-urlencoded' format using a specific encoding scheme | o | XMLTRANSFORM(xml, xslt) | Applies XSLT transform *xslt* to XML string *xml* and returns the result @@ -2920,8 +2920,8 @@ Dialect-specific aggregate functions. | c | AGGREGATE(m) | Computes measure *m* in the context of the current GROUP BY key | b p | ARRAY_AGG( [ ALL | DISTINCT ] value [ RESPECT NULLS | IGNORE NULLS ] [ ORDER BY orderItem [, orderItem ]* ] ) | Gathers values into arrays | b p | ARRAY_CONCAT_AGG( [ ALL | DISTINCT ] value [ ORDER BY orderItem [, orderItem ]* ] ) | Concatenates arrays into arrays -| p | BOOL_AND(condition) | Synonym for `EVERY` -| p | BOOL_OR(condition) | Synonym for `SOME` +| p s | BOOL_AND(condition) | Synonym for `EVERY` +| p s | BOOL_OR(condition) | Synonym for `SOME` | b | COUNTIF(condition) | Returns the number of rows for which *condition* is TRUE; equivalent to `COUNT(*) FILTER (WHERE condition)` | m | GROUP_CONCAT( [ ALL | DISTINCT ] value [, value ]* [ ORDER BY orderItem [, orderItem ]* ] [ SEPARATOR separator ] ) | MySQL-specific variant of `LISTAGG` | b | LOGICAL_AND(condition) | Synonym for `EVERY` 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 9f3898c221c..badde6f8897 100644 --- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java +++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java @@ -4022,7 +4022,7 @@ static void checkRlikeFails(SqlOperatorFixture f) { }; final List libraries = ImmutableList.of(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, - SqlLibrary.POSTGRESQL); + SqlLibrary.POSTGRESQL, SqlLibrary.SPARK); f0.forEachLibrary(libraries, consumer); } @@ -4520,7 +4520,7 @@ void testBitGetFunc(SqlOperatorFixture f, String functionName) { false); final List libraries = ImmutableList.of(SqlLibrary.BIG_QUERY, SqlLibrary.MYSQL, - SqlLibrary.POSTGRESQL); + SqlLibrary.POSTGRESQL, SqlLibrary.SPARK); final Consumer consumer = f -> { f.checkString("md5(x'')", "d41d8cd98f00b204e9800998ecf8427e", @@ -4545,7 +4545,7 @@ void testBitGetFunc(SqlOperatorFixture f, String functionName) { false); final List libraries = ImmutableList.of(SqlLibrary.BIG_QUERY, SqlLibrary.MYSQL, - SqlLibrary.POSTGRESQL); + SqlLibrary.POSTGRESQL, SqlLibrary.SPARK); final Consumer consumer = f -> { f.checkString("sha1(x'')", "da39a3ee5e6b4b0d3255bfef95601890afd80709", @@ -4665,19 +4665,23 @@ void testBitGetFunc(SqlOperatorFixture f, String functionName) { f.checkNull("REPEAT('abc', cast(null as integer))"); f.checkNull("REPEAT(cast(null as varchar(1)), cast(null as integer))"); }; - f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.MYSQL), consumer); + f0.forEachLibrary( + list(SqlLibrary.BIG_QUERY, SqlLibrary.MYSQL, + SqlLibrary.POSTGRESQL, SqlLibrary.SPARK), consumer); } @Test void testSpaceFunc() { - final SqlOperatorFixture f = fixture() - .setFor(SqlLibraryOperators.SPACE) - .withLibrary(SqlLibrary.MYSQL); - f.checkString("SPACE(-100)", "", "VARCHAR NOT NULL"); - f.checkString("SPACE(-1)", "", "VARCHAR NOT NULL"); - f.checkString("SPACE(0)", "", "VARCHAR NOT NULL"); - f.checkString("SPACE(2)", " ", "VARCHAR NOT NULL"); - f.checkString("SPACE(5)", " ", "VARCHAR NOT NULL"); - f.checkNull("SPACE(cast(null as integer))"); + final SqlOperatorFixture f0 = fixture() + .setFor(SqlLibraryOperators.SPACE); + final Consumer consumer = f -> { + f.checkString("SPACE(-100)", "", "VARCHAR NOT NULL"); + f.checkString("SPACE(-1)", "", "VARCHAR NOT NULL"); + f.checkString("SPACE(0)", "", "VARCHAR NOT NULL"); + f.checkString("SPACE(2)", " ", "VARCHAR NOT NULL"); + f.checkString("SPACE(5)", " ", "VARCHAR NOT NULL"); + f.checkNull("SPACE(cast(null as integer))"); + }; + f0.forEachLibrary(list(SqlLibrary.MYSQL, SqlLibrary.SPARK), consumer); } @Test void testStrcmpFunc() { @@ -4872,7 +4876,9 @@ private static void checkIf(SqlOperatorFixture f) { f.checkNull("left(cast(null as binary(1)), -2)"); f.checkNull("left(x'ABCdef', cast(null as Integer))"); }; - f0.forEachLibrary(list(SqlLibrary.MYSQL, SqlLibrary.POSTGRESQL), consumer); + f0.forEachLibrary( + list(SqlLibrary.BIG_QUERY, SqlLibrary.MYSQL, SqlLibrary.POSTGRESQL, + SqlLibrary.SPARK), consumer); } @Test void testRightFunc() { @@ -4896,7 +4902,9 @@ private static void checkIf(SqlOperatorFixture f) { f.checkNull("right(x'ABCdef', cast(null as Integer))"); }; - f0.forEachLibrary(list(SqlLibrary.MYSQL, SqlLibrary.POSTGRESQL), consumer); + f0.forEachLibrary( + list(SqlLibrary.BIG_QUERY, SqlLibrary.MYSQL, SqlLibrary.POSTGRESQL, + SqlLibrary.SPARK), consumer); } @Test void testRegexpContainsFunc() { @@ -7869,12 +7877,14 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) { } @Test void testPowFunc() { - final SqlOperatorFixture f = fixture() - .setFor(SqlLibraryOperators.POW) - .withLibrary(SqlLibrary.BIG_QUERY); - f.checkScalarApprox("pow(2,3)", "DOUBLE NOT NULL", isExactly("8.0")); - f.checkNull("pow(2, cast(null as integer))"); - f.checkNull("pow(cast(null as integer), 2)"); + final SqlOperatorFixture f0 = fixture() + .setFor(SqlLibraryOperators.POW); + final Consumer consumer = f -> { + f.checkScalarApprox("pow(2,3)", "DOUBLE NOT NULL", isExactly("8.0")); + f.checkNull("pow(2, cast(null as integer))"); + f.checkNull("pow(cast(null as integer), 2)"); + }; + f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.SPARK), consumer); } @Test void testInfinity() { @@ -8893,54 +8903,60 @@ private void testCurrentDateFunc(Pair pair) { } @Test void testLpadFunction() { - final SqlOperatorFixture f = fixture().withLibrary(SqlLibrary.BIG_QUERY); - f.setFor(SqlLibraryOperators.LPAD); - f.check("select lpad('12345', 8, 'a')", "VARCHAR NOT NULL", "aaa12345"); - f.checkString("lpad('12345', 8)", " 12345", "VARCHAR NOT NULL"); - f.checkString("lpad('12345', 8, 'ab')", "aba12345", "VARCHAR NOT NULL"); - f.checkString("lpad('12345', 3, 'a')", "123", "VARCHAR NOT NULL"); - f.checkFails("lpad('12345', -3, 'a')", - "Second argument for LPAD/RPAD must not be negative", true); - f.checkFails("lpad('12345', -3)", - "Second argument for LPAD/RPAD must not be negative", true); - f.checkFails("lpad('12345', 3, '')", - "Third argument \\(pad pattern\\) for LPAD/RPAD must not be empty", true); - f.checkString("lpad(x'aa', 4, x'bb')", "bbbbbbaa", "VARBINARY NOT NULL"); - f.checkString("lpad(x'aa', 4)", "202020aa", "VARBINARY NOT NULL"); - f.checkString("lpad(x'aaaaaa', 2)", "aaaa", "VARBINARY NOT NULL"); - f.checkString("lpad(x'aaaaaa', 2, x'bb')", "aaaa", "VARBINARY NOT NULL"); - f.checkFails("lpad(x'aa', -3, x'bb')", - "Second argument for LPAD/RPAD must not be negative", true); - f.checkFails("lpad(x'aa', -3)", - "Second argument for LPAD/RPAD must not be negative", true); - f.checkFails("lpad(x'aa', 3, x'')", - "Third argument \\(pad pattern\\) for LPAD/RPAD must not be empty", true); + final SqlOperatorFixture f0 = fixture(); + f0.setFor(SqlLibraryOperators.LPAD); + final Consumer consumer = f -> { + f.check("select lpad('12345', 8, 'a')", "VARCHAR NOT NULL", "aaa12345"); + f.checkString("lpad('12345', 8)", " 12345", "VARCHAR NOT NULL"); + f.checkString("lpad('12345', 8, 'ab')", "aba12345", "VARCHAR NOT NULL"); + f.checkString("lpad('12345', 3, 'a')", "123", "VARCHAR NOT NULL"); + f.checkFails("lpad('12345', -3, 'a')", + "Second argument for LPAD/RPAD must not be negative", true); + f.checkFails("lpad('12345', -3)", + "Second argument for LPAD/RPAD must not be negative", true); + f.checkFails("lpad('12345', 3, '')", + "Third argument \\(pad pattern\\) for LPAD/RPAD must not be empty", true); + f.checkString("lpad(x'aa', 4, x'bb')", "bbbbbbaa", "VARBINARY NOT NULL"); + f.checkString("lpad(x'aa', 4)", "202020aa", "VARBINARY NOT NULL"); + f.checkString("lpad(x'aaaaaa', 2)", "aaaa", "VARBINARY NOT NULL"); + f.checkString("lpad(x'aaaaaa', 2, x'bb')", "aaaa", "VARBINARY NOT NULL"); + f.checkFails("lpad(x'aa', -3, x'bb')", + "Second argument for LPAD/RPAD must not be negative", true); + f.checkFails("lpad(x'aa', -3)", + "Second argument for LPAD/RPAD must not be negative", true); + f.checkFails("lpad(x'aa', 3, x'')", + "Third argument \\(pad pattern\\) for LPAD/RPAD must not be empty", true); + }; + f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.SPARK), consumer); } @Test void testRpadFunction() { - final SqlOperatorFixture f = fixture().withLibrary(SqlLibrary.BIG_QUERY); - f.setFor(SqlLibraryOperators.RPAD); - f.check("select rpad('12345', 8, 'a')", "VARCHAR NOT NULL", "12345aaa"); - f.checkString("rpad('12345', 8)", "12345 ", "VARCHAR NOT NULL"); - f.checkString("rpad('12345', 8, 'ab')", "12345aba", "VARCHAR NOT NULL"); - f.checkString("rpad('12345', 3, 'a')", "123", "VARCHAR NOT NULL"); - f.checkFails("rpad('12345', -3, 'a')", - "Second argument for LPAD/RPAD must not be negative", true); - f.checkFails("rpad('12345', -3)", - "Second argument for LPAD/RPAD must not be negative", true); - f.checkFails("rpad('12345', 3, '')", - "Third argument \\(pad pattern\\) for LPAD/RPAD must not be empty", true); - - f.checkString("rpad(x'aa', 4, x'bb')", "aabbbbbb", "VARBINARY NOT NULL"); - f.checkString("rpad(x'aa', 4)", "aa202020", "VARBINARY NOT NULL"); - f.checkString("rpad(x'aaaaaa', 2)", "aaaa", "VARBINARY NOT NULL"); - f.checkString("rpad(x'aaaaaa', 2, x'bb')", "aaaa", "VARBINARY NOT NULL"); - f.checkFails("rpad(x'aa', -3, x'bb')", - "Second argument for LPAD/RPAD must not be negative", true); - f.checkFails("rpad(x'aa', -3)", - "Second argument for LPAD/RPAD must not be negative", true); - f.checkFails("rpad(x'aa', 3, x'')", - "Third argument \\(pad pattern\\) for LPAD/RPAD must not be empty", true); + final SqlOperatorFixture f0 = fixture(); + f0.setFor(SqlLibraryOperators.RPAD); + final Consumer consumer = f -> { + f.check("select rpad('12345', 8, 'a')", "VARCHAR NOT NULL", "12345aaa"); + f.checkString("rpad('12345', 8)", "12345 ", "VARCHAR NOT NULL"); + f.checkString("rpad('12345', 8, 'ab')", "12345aba", "VARCHAR NOT NULL"); + f.checkString("rpad('12345', 3, 'a')", "123", "VARCHAR NOT NULL"); + f.checkFails("rpad('12345', -3, 'a')", + "Second argument for LPAD/RPAD must not be negative", true); + f.checkFails("rpad('12345', -3)", + "Second argument for LPAD/RPAD must not be negative", true); + f.checkFails("rpad('12345', 3, '')", + "Third argument \\(pad pattern\\) for LPAD/RPAD must not be empty", true); + + f.checkString("rpad(x'aa', 4, x'bb')", "aabbbbbb", "VARBINARY NOT NULL"); + f.checkString("rpad(x'aa', 4)", "aa202020", "VARBINARY NOT NULL"); + f.checkString("rpad(x'aaaaaa', 2)", "aaaa", "VARBINARY NOT NULL"); + f.checkString("rpad(x'aaaaaa', 2, x'bb')", "aaaa", "VARBINARY NOT NULL"); + f.checkFails("rpad(x'aa', -3, x'bb')", + "Second argument for LPAD/RPAD must not be negative", true); + f.checkFails("rpad(x'aa', -3)", + "Second argument for LPAD/RPAD must not be negative", true); + f.checkFails("rpad(x'aa', 3, x'')", + "Third argument \\(pad pattern\\) for LPAD/RPAD must not be empty", true); + }; + f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.SPARK), consumer); } @Test void testContainsSubstrFunc() { @@ -9660,7 +9676,7 @@ void assertSubFunReturns(boolean binary, String s, int start, f.checkString("rtrim(' aAa ')", " aAa", "VARCHAR(6) NOT NULL"); f.checkNull("rtrim(CAST(NULL AS VARCHAR(6)))"); }; - f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE), consumer); + f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.SPARK), consumer); } @Test void testLtrimFunc() { @@ -9673,7 +9689,7 @@ void assertSubFunReturns(boolean binary, String s, int start, f.checkString("ltrim(' aAa ')", "aAa ", "VARCHAR(6) NOT NULL"); f.checkNull("ltrim(CAST(NULL AS VARCHAR(6)))"); }; - f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE), consumer); + f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.SPARK), consumer); } @Test void testGreatestFunc() { @@ -9695,7 +9711,7 @@ void assertSubFunReturns(boolean binary, String s, int start, f12.checkString("greatest('show', 'on', 'earth')", "show", "VARCHAR(5) NOT NULL"); }; - f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE), consumer); + f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.SPARK), consumer); } @Test void testLeastFunc() { @@ -9717,7 +9733,7 @@ void assertSubFunReturns(boolean binary, String s, int start, f12.checkString("least('show', 'on', 'earth')", "earth", "VARCHAR(5) NOT NULL"); }; - f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE), consumer); + f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE, SqlLibrary.SPARK), consumer); } @Test void testIfNullFunc() { @@ -9765,6 +9781,7 @@ void checkNvl(SqlOperatorFixture f0, FunctionAlias functionAlias) { @Test void testDecodeFunc() { checkDecodeFunc(fixture().withLibrary(SqlLibrary.ORACLE)); + checkDecodeFunc(fixture().withLibrary(SqlLibrary.SPARK)); } private static void checkDecodeFunc(SqlOperatorFixture f) { @@ -13490,6 +13507,7 @@ void testTimestampDiff(boolean coercionEnabled) { "No match found for function signature BOOL_AND\\(\\)", false); checkBoolAndFunc(f.withLibrary(SqlLibrary.POSTGRESQL)); + checkBoolAndFunc(f.withLibrary(SqlLibrary.SPARK)); } private static void checkBoolAndFunc(SqlOperatorFixture f) { @@ -13537,6 +13555,7 @@ private static void checkBoolAndFunc(SqlOperatorFixture f) { "No match found for function signature BOOL_OR\\(\\)", false); checkBoolOrFunc(f.withLibrary(SqlLibrary.POSTGRESQL)); + checkBoolOrFunc(f.withLibrary(SqlLibrary.SPARK)); } private static void checkBoolOrFunc(SqlOperatorFixture f) {