This is an automated email from the ASF dual-hosted git repository.
tanner pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new ee4cb3581c [CALCITE-6172] Allow aliased operators to re-use existing
tests
ee4cb3581c is described below
commit ee4cb3581cfa346a5dab40cc5b53a1571b6191a4
Author: Sergey Nuyanzin <[email protected]>
AuthorDate: Fri Dec 22 00:27:32 2023 +0100
[CALCITE-6172] Allow aliased operators to re-use existing tests
Co-authored-by: Tanner Clary <[email protected]>
Co-authored-by: Julian Hyde <[email protected]>
Co-authored-by: Sergey Nuyanzin <[email protected]>
---
.../org/apache/calcite/test/SqlOperatorTest.java | 461 +++++++++++----------
1 file changed, 237 insertions(+), 224 deletions(-)
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 1d88d52915..09311731dd 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -45,6 +45,7 @@ import org.apache.calcite.sql.SqlOperandCountRange;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlSyntax;
import org.apache.calcite.sql.dialect.AnsiSqlDialect;
+import org.apache.calcite.sql.fun.LibraryOperator;
import org.apache.calcite.sql.fun.SqlLibrary;
import org.apache.calcite.sql.fun.SqlLibraryOperators;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
@@ -3303,20 +3304,6 @@ public class SqlOperatorTest {
f.setFor(SqlStdOperatorTable.DESC, VM_EXPAND);
}
- @Test void testIsNotNullOperator() {
- final SqlOperatorFixture f = fixture();
- f.setFor(SqlStdOperatorTable.IS_NOT_NULL, VmName.EXPAND);
- f.checkBoolean("true is not null", true);
- f.checkBoolean("cast(null as boolean) is not null", false);
- }
-
- @Test void testIsNullOperator() {
- final SqlOperatorFixture f = fixture();
- f.setFor(SqlStdOperatorTable.IS_NULL, VmName.EXPAND);
- f.checkBoolean("true is null", false);
- f.checkBoolean("cast(null as boolean) is null", true);
- }
-
@Test void testIsNotTrueOperator() {
final SqlOperatorFixture f = fixture();
f.setFor(SqlStdOperatorTable.IS_NOT_TRUE, VmName.EXPAND);
@@ -3354,28 +3341,51 @@ public class SqlOperatorTest {
f.checkBoolean("cast(null as boolean) is false", false);
}
+ @Test void testIsNotNullOperator() {
+ final SqlOperatorFixture f = fixture();
+ f.setFor(SqlStdOperatorTable.IS_NOT_NULL, VmName.EXPAND);
+ checkIsNotNull(f, SqlStdOperatorTable.IS_NOT_NULL);
+ }
+
@Test void testIsNotUnknownOperator() {
final SqlOperatorFixture f = fixture();
f.setFor(SqlStdOperatorTable.IS_NOT_UNKNOWN, VM_EXPAND);
- f.checkBoolean("false is not unknown", true);
- f.checkBoolean("true is not unknown", true);
- f.checkBoolean("cast(null as boolean) is not unknown", false);
- f.checkBoolean("unknown is not unknown", false);
f.checkFails("^'abc' IS NOT UNKNOWN^",
"(?s).*Cannot apply 'IS NOT UNKNOWN'.*",
false);
+ checkIsNotNull(f, SqlStdOperatorTable.IS_NOT_UNKNOWN);
+ }
+
+ /** Tests the {@code IS NOT NULL} and {@code IS NOT UNKNOWN} operators. */
+ void checkIsNotNull(SqlOperatorFixture f, SqlOperator operator) {
+ final String fn = operator.getName();
+ f.checkBoolean("false " + fn, true);
+ f.checkBoolean("true " + fn, true);
+ f.checkBoolean("cast(null as boolean) " + fn, false);
+ f.checkBoolean("unknown " + fn, false);
+ }
+
+ @Test void testIsNullOperator() {
+ final SqlOperatorFixture f = fixture();
+ f.setFor(SqlStdOperatorTable.IS_NULL, VmName.EXPAND);
+ checkIsNull(f, SqlStdOperatorTable.IS_NULL);
}
@Test void testIsUnknownOperator() {
final SqlOperatorFixture f = fixture();
- f.setFor(SqlStdOperatorTable.IS_UNKNOWN, VM_EXPAND);
- f.checkBoolean("false is unknown", false);
- f.checkBoolean("true is unknown", false);
- f.checkBoolean("cast(null as boolean) is unknown", true);
- f.checkBoolean("unknown is unknown", true);
+ f.setFor(SqlStdOperatorTable.IS_UNKNOWN, VmName.EXPAND);
f.checkFails("0 = 1 AND ^2 IS UNKNOWN^ AND 3 > 4",
"(?s).*Cannot apply 'IS UNKNOWN'.*",
false);
+ checkIsNull(f, SqlStdOperatorTable.IS_UNKNOWN);
+ }
+
+ /** Tests the {@code IS NULL} and {@code IS UNKNOWN} operators. */
+ void checkIsNull(SqlOperatorFixture f, SqlOperator operator) {
+ final String fn = operator.getName();
+ f.checkBoolean("false " + fn, false);
+ f.checkBoolean("true " + fn, false);
+ f.checkBoolean("cast(null as boolean) " + fn, true);
}
@Test void testIsASetOperator() {
@@ -4107,6 +4117,7 @@ public class SqlOperatorTest {
f.setFor(SqlStdOperatorTable.CHAR_LENGTH, VmName.EXPAND);
f.checkScalarExact("char_length('abc')", 3);
f.checkNull("char_length(cast(null as varchar(1)))");
+ checkCharLength(f, FunctionAlias.of(SqlStdOperatorTable.CHAR_LENGTH));
}
@Test void testCharacterLengthFunc() {
@@ -4114,40 +4125,38 @@ public class SqlOperatorTest {
f.setFor(SqlStdOperatorTable.CHARACTER_LENGTH, VmName.EXPAND);
f.checkScalarExact("CHARACTER_LENGTH('abc')", 3);
f.checkNull("CHARACTER_LENGTH(cast(null as varchar(1)))");
+ checkCharLength(f, FunctionAlias.of(SqlStdOperatorTable.CHARACTER_LENGTH));
}
- /** Tests {@code LEN} function from Snowflake. {@code LEN} is a
- * Snowflake-specific alias for {@code CHAR_LENGTH}. */
@Test void testLenFunc() {
final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.LEN);
f0.checkFails("^len('hello')^",
"No match found for function signature LEN\\(<CHARACTER>\\)",
false);
- final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.SNOWFLAKE);
- f.checkScalar("len('hello')", "5", "INTEGER NOT NULL");
- f.checkScalar("len('')", "0", "INTEGER NOT NULL");
- f.checkScalar("len(CAST('x' as CHAR(3)))", "3", "INTEGER NOT NULL");
- f.checkScalar("len(CAST('x' as VARCHAR(4)))", "1", "INTEGER NOT NULL");
- f.checkNull("len(CAST(NULL as CHAR(5)))");
+ checkCharLength(f0, FunctionAlias.of(SqlLibraryOperators.LEN));
}
- /** Tests {@code LENGTH} function from Big Query/Snowflake. {@code LENGTH}
is a
- * BQ/Snowflake-specific alias for {@code CHAR_LENGTH}. */
@Test void testLengthFunc() {
final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.LENGTH);
f0.checkFails("^length('hello')^",
"No match found for function signature LENGTH\\(<CHARACTER>\\)",
false);
+ checkCharLength(f0, FunctionAlias.of(SqlLibraryOperators.LENGTH));
+ }
+ /** Common tests for {@code CHAR_LENGTH}, {@code CHARACTER_LENGTH}, {@code
LEN},
+ * and {@code LENGTH} functions. */
+ void checkCharLength(SqlOperatorFixture f0, FunctionAlias functionAlias) {
+ final SqlFunction function = functionAlias.function;
+ final String fn = function.getName();
final Consumer<SqlOperatorFixture> consumer = f -> {
- f.checkScalar("length('hello')", "5", "INTEGER NOT NULL");
- f.checkScalar("length('')", "0", "INTEGER NOT NULL");
- f.checkScalar("length(CAST('x' as CHAR(3)))", "3", "INTEGER NOT NULL");
- f.checkScalar("length(CAST('x' as VARCHAR(4)))", "1", "INTEGER NOT
NULL");
- f.checkNull("length(CAST(NULL as CHAR(5)))");
+ f.checkScalarExact(fn + "('abc')", 3);
+ f.checkNull(fn + "(cast(null as varchar(1)))");
+ f.checkScalar(fn + "('')", "0", "INTEGER NOT NULL");
+ f.checkScalar(fn + "(CAST('x' as CHAR(3)))", "3", "INTEGER NOT NULL");
+ f.checkScalar(fn + "(CAST('x' as VARCHAR(4)))", "1", "INTEGER NOT NULL");
};
-
- f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.SNOWFLAKE),
consumer);
+ f0.forEachLibrary(functionAlias.libraries, consumer);
}
@Test void testOctetLengthFunc() {
@@ -4885,36 +4894,6 @@ public class SqlOperatorTest {
f.checkNull("regexp_contains(cast(null as varchar), cast(null as
varchar))");
}
- @Test void testRegexpExtractFunc() {
- final SqlOperatorFixture f =
-
fixture().setFor(SqlLibraryOperators.REGEXP_EXTRACT).withLibrary(SqlLibrary.BIG_QUERY);
-
- f.checkString("regexp_extract('abc def ghi', 'def')", "def", "VARCHAR NOT
NULL");
- f.checkString("regexp_extract('abcadcaecghi', 'a.c', 1, 3)", "aec",
"VARCHAR NOT NULL");
- f.checkString("regexp_extract('abcadcaecghi', 'abc(a.c)')", "adc",
"VARCHAR NOT NULL");
- f.checkString("regexp_extract('55as56664as422', '\\d{3}')", "566",
"VARCHAR NOT NULL");
- f.checkString("regexp_extract('abcadcabcaecghi', 'c(a.c)', 4)", "abc",
"VARCHAR NOT NULL");
- f.checkString("regexp_extract('abcadcabcaecghi', 'a.c(a.c)', 1, 2)",
"aec", "VARCHAR NOT NULL");
- f.checkString("regexp_extract('a9cadca5c4aecghi', 'a[0-9]c', 6)", "a5c",
"VARCHAR NOT NULL");
- f.checkString("regexp_extract('a9cadca5ca4cecghi', 'a[0-9]c', 1, 3)",
"a4c", "VARCHAR NOT "
- + "NULL");
-
- f.checkNull("regexp_extract('abc def ghi', 'asd')");
- f.checkNull("regexp_extract('abc def ghi', 'abc', 25)");
- f.checkNull("regexp_extract('abc def ghi', 'abc', 1, 4)");
- f.checkNull("regexp_extract('abc def ghi', cast(null as varchar))");
- f.checkNull("regexp_extract(cast(null as varchar), 'abc')");
- f.checkNull("regexp_extract(cast(null as varchar), cast(null as
varchar))");
- f.checkNull("regexp_extract('abc def ghi', 'abc', cast(null as integer))");
- f.checkNull("regexp_extract('abc def ghi', 'abc', 1, cast(null as
integer))");
-
- f.checkQuery("select regexp_extract('abc def ghi', 'abc')");
- f.checkQuery("select regexp_extract('[email protected]',
'@[a-zA-Z0-9-]+\\\\.[a-zA-Z0-9-.]+')");
- f.checkQuery("select regexp_extract('55as56664as422', '\\d{10}')");
- f.checkQuery("select regexp_extract('abcadcabcaecghi', 'c(a.c)', 4)");
- f.checkQuery("select regexp_extract('a9cadca5c4aecghi', 'a[0-9]c', 1, 3)");
- }
-
@Test void testRegexpExtractAllFunc() {
final SqlOperatorFixture f =
fixture().setFor(SqlLibraryOperators.REGEXP_EXTRACT_ALL).withLibrary(SqlLibrary.BIG_QUERY);
@@ -5034,27 +5013,49 @@ public class SqlOperatorTest {
"VARCHAR NOT NULL");
}
- @Test void testRegexpSubstrFunc() {
- final SqlOperatorFixture f =
fixture().setFor(SqlLibraryOperators.REGEXP_SUBSTR)
- .withLibrary(SqlLibrary.BIG_QUERY);
-
- f.checkString("regexp_substr('abc def ghi', 'ghi')", "ghi",
- "VARCHAR NOT NULL");
- f.checkString("regexp_substr('abcadcaecghi', 'a.c', 1, 2)", "adc",
- "VARCHAR NOT NULL");
- f.checkString("regexp_substr('abcadcabcaecghi', 'abc(a.c)', 1, 2)", "aec",
- "VARCHAR NOT NULL");
- f.checkString("regexp_substr('55as56664as422', '\\d{3}')", "566",
- "VARCHAR NOT NULL");
+ @Test void testRegexpExtractFunc() {
+ final SqlOperatorFixture f = fixture();
+ f.setFor(SqlLibraryOperators.REGEXP_EXTRACT, VmName.EXPAND);
+ checkRegexpExtract(f,
FunctionAlias.of(SqlLibraryOperators.REGEXP_EXTRACT));
+ }
- f.checkNull("regexp_substr('abc def ghi', 'bqi')");
- f.checkNull("regexp_substr('abc def ghi', cast(null as varchar))");
- f.checkNull("regexp_substr(cast(null as varchar), 'bqi')");
- f.checkNull("regexp_substr(cast(null as varchar), cast(null as varchar))");
+ @Test void testRegexpSubstrFunc() {
+ final SqlOperatorFixture f = fixture();
+ f.setFor(SqlLibraryOperators.REGEXP_SUBSTR, VmName.EXPAND);
+ checkRegexpExtract(f, FunctionAlias.of(SqlLibraryOperators.REGEXP_SUBSTR));
+ }
- f.checkQuery("select regexp_substr('abcdefghi', 'abc')");
- f.checkQuery("select regexp_substr('[email protected]',
'@[a-zA-Z0-9-]+\\\\.[a-zA-Z0-9-.]+')");
- f.checkQuery("select regexp_substr('55as56664as422', '\\d{10}')");
+ /** Tests the {@code REGEXP_EXTRACT} and {@code REGEXP_SUBSTR} operators. */
+ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) {
+ final SqlFunction function = functionAlias.function;
+ final String fn = function.getName();
+ final Consumer<SqlOperatorFixture> consumer = f -> {
+ f.checkString(fn + "('abc def ghi', 'def')", "def", "VARCHAR NOT NULL");
+ f.checkString(fn + "('abcadcaecghi', 'a.c', 1, 3)", "aec", "VARCHAR NOT
NULL");
+ f.checkString(fn + "('abcadcaecghi', 'abc(a.c)')", "adc", "VARCHAR NOT
NULL");
+ f.checkString(fn + "('55as56664as422', '\\d{3}')", "566", "VARCHAR NOT
NULL");
+ f.checkString(fn + "('abcadcabcaecghi', 'c(a.c)', 4)", "abc", "VARCHAR
NOT NULL");
+ f.checkString(fn + "('abcadcabcaecghi', 'a.c(a.c)', 1, 2)", "aec",
"VARCHAR NOT NULL");
+ f.checkString(fn + "('a9cadca5c4aecghi', 'a[0-9]c', 6)", "a5c", "VARCHAR
NOT NULL");
+ f.checkString(fn + "('a9cadca5ca4cecghi', 'a[0-9]c', 1, 3)", "a4c",
"VARCHAR NOT "
+ + "NULL");
+
+ f.checkNull(fn + "('abc def ghi', 'asd')");
+ f.checkNull(fn + "('abc def ghi', 'abc', 25)");
+ f.checkNull(fn + "('abc def ghi', 'abc', 1, 4)");
+ f.checkNull(fn + "('abc def ghi', cast(null as varchar))");
+ f.checkNull(fn + "(cast(null as varchar), 'abc')");
+ f.checkNull(fn + "(cast(null as varchar), cast(null as varchar))");
+ f.checkNull(fn + "('abc def ghi', 'abc', cast(null as integer))");
+ f.checkNull(fn + "('abc def ghi', 'abc', 1, cast(null as integer))");
+
+ f.checkQuery("select " + fn + "('abc def ghi', 'abc')");
+ f.checkQuery("select " + fn + "('[email protected]',
'@[a-zA-Z0-9-]+\\\\.[a-zA-Z0-9-.]+')");
+ f.checkQuery("select " + fn + "('55as56664as422', '\\d{10}')");
+ f.checkQuery("select " + fn + "('abcadcabcaecghi', 'c(a.c)', 4)");
+ f.checkQuery("select " + fn + "('a9cadca5c4aecghi', 'a[0-9]c', 1, 3)");
+ };
+ f0.forEachLibrary(list(functionAlias.libraries), consumer);
}
@Test void testJsonExists() {
@@ -8994,107 +8995,84 @@ public class SqlOperatorTest {
f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE), consumer);
}
- @Test void testStartsWithFunction() {
- final SqlOperatorFixture f0 = fixture();
- f0.setFor(SqlLibraryOperators.STARTS_WITH);
+ @Test void testSnowflakeStartsWithFunc() {
+ final SqlOperatorFixture f = fixture();
+ f.setFor(SqlLibraryOperators.STARTSWITH, VmName.EXPAND);
+ checkStartsWith(f, FunctionAlias.of(SqlLibraryOperators.STARTSWITH));
+ }
+
+ @Test void testStartsWithFunc() {
+ final SqlOperatorFixture f = fixture();
+ f.setFor(SqlLibraryOperators.STARTS_WITH, VmName.EXPAND);
+ checkStartsWith(f, FunctionAlias.of(SqlLibraryOperators.STARTS_WITH));
+ }
+
+ /** Tests the {@code STARTS_WITH} and {@code STARTSWITH} operators. */
+ void checkStartsWith(SqlOperatorFixture f0, FunctionAlias functionAlias) {
+ final SqlFunction function = functionAlias.function;
+ final String fn = function.getName();
final Consumer<SqlOperatorFixture> consumer = f -> {
- f.checkBoolean("starts_with('12345', '123')", true);
- f.checkBoolean("starts_with('12345', '1243')", false);
- f.checkBoolean("starts_with(x'11', x'11')", true);
- f.checkBoolean("starts_with(x'112211', x'33')", false);
- f.checkFails("^starts_with('aabbcc', x'aa')^",
- "Cannot apply 'STARTS_WITH' to arguments of type "
- + "'STARTS_WITH\\(<CHAR\\(6\\)>, <BINARY\\(1\\)>\\)'\\.
Supported "
- + "form\\(s\\): 'STARTS_WITH\\(<STRING>, <STRING>\\)'",
+ f.checkBoolean(fn + "('12345', '123')", true);
+ f.checkBoolean(fn + "('12345', '1243')", false);
+ f.checkBoolean(fn + "(x'11', x'11')", true);
+ f.checkBoolean(fn + "(x'112211', x'33')", false);
+ f.checkFails("^" + fn + "('aabbcc', x'aa')^",
+ "Cannot apply '" + fn + "' to arguments of type "
+ + "'" + fn + "\\(<CHAR\\(6\\)>, <BINARY\\(1\\)>\\)'\\. Supported
"
+ + "form\\(s\\): '" + fn + "\\(<STRING>, <STRING>\\)'",
false);
- f.checkNull("starts_with(null, null)");
- f.checkNull("starts_with('12345', null)");
- f.checkNull("starts_with(null, '123')");
- f.checkBoolean("starts_with('', '123')", false);
- f.checkBoolean("starts_with('', '')", true);
- f.checkNull("starts_with(x'aa', null)");
- f.checkNull("starts_with(null, x'aa')");
- f.checkBoolean("starts_with(x'1234', x'')", true);
- f.checkBoolean("starts_with(x'', x'123456')", false);
- f.checkBoolean("starts_with(x'', x'')", true);
+ f.checkNull(fn + "(null, null)");
+ f.checkNull(fn + "('12345', null)");
+ f.checkNull(fn + "(null, '123')");
+ f.checkBoolean(fn + "('', '123')", false);
+ f.checkBoolean(fn + "('', '')", true);
+ f.checkNull(fn + "(x'aa', null)");
+ f.checkNull(fn + "(null, x'aa')");
+ f.checkBoolean(fn + "(x'1234', x'')", true);
+ f.checkBoolean(fn + "(x'', x'123456')", false);
+ f.checkBoolean(fn + "(x'', x'')", true);
};
- f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.POSTGRESQL),
consumer);
- }
-
- /** Tests for Snowflake's {@code STARTSWITH} function. */
- @Test void testSnowflakeStartsWithFunction() {
- final SqlOperatorFixture f = fixture().withLibrary(SqlLibrary.SNOWFLAKE);
- f.setFor(SqlLibraryOperators.STARTSWITH);
- f.checkBoolean("startswith('12345', '123')", true);
- f.checkBoolean("startswith('12345', '1243')", false);
- f.checkBoolean("startswith(x'11', x'11')", true);
- f.checkBoolean("startswith(x'112211', x'33')", false);
- f.checkFails("^startswith('aabbcc', x'aa')^",
- "Cannot apply 'STARTSWITH' to arguments of type "
- + "'STARTSWITH\\(<CHAR\\(6\\)>, <BINARY\\(1\\)>\\)'\\. Supported "
- + "form\\(s\\): 'STARTSWITH\\(<STRING>, <STRING>\\)'",
- false);
- f.checkNull("startswith(null, null)");
- f.checkNull("startswith('12345', null)");
- f.checkNull("startswith(null, '123')");
- f.checkBoolean("startswith('', '123')", false);
- f.checkBoolean("startswith('', '')", true);
- f.checkNull("startswith(x'aa', null)");
- f.checkNull("startswith(null, x'aa')");
- f.checkBoolean("startswith(x'1234', x'')", true);
- f.checkBoolean("startswith(x'', x'123456')", false);
- f.checkBoolean("startswith(x'', x'')", true);
- }
-
- @Test void testEndsWithFunction() {
- final SqlOperatorFixture f0 = fixture();
- f0.setFor(SqlLibraryOperators.ENDS_WITH);
+ f0.forEachLibrary(list(functionAlias.libraries), consumer);
+ }
+
+ @Test void testSnowflakeEndsWithFunc() {
+ final SqlOperatorFixture f = fixture();
+ f.setFor(SqlLibraryOperators.ENDSWITH, VmName.EXPAND);
+ checkEndsWith(f, FunctionAlias.of(SqlLibraryOperators.ENDSWITH));
+ }
+
+ @Test void testEndsWithFunc() {
+ final SqlOperatorFixture f = fixture();
+ f.setFor(SqlLibraryOperators.ENDS_WITH, VmName.EXPAND);
+ checkEndsWith(f, FunctionAlias.of(SqlLibraryOperators.ENDS_WITH));
+ }
+
+ /** Tests the {@code ENDS_WITH} and {@code ENDSWITH} operators. */
+ void checkEndsWith(SqlOperatorFixture f0, FunctionAlias functionAlias) {
+ final SqlFunction function = functionAlias.function;
+ final String fn = function.getName();
final Consumer<SqlOperatorFixture> consumer = f -> {
- f.checkBoolean("ends_with('12345', '345')", true);
- f.checkBoolean("ends_with('12345', '123')", false);
- f.checkBoolean("ends_with(x'11', x'11')", true);
- f.checkBoolean("ends_with(x'112211', x'33')", false);
- f.checkFails("^ends_with('aabbcc', x'aa')^",
- "Cannot apply 'ENDS_WITH' to arguments of type "
- + "'ENDS_WITH\\(<CHAR\\(6\\)>, <BINARY\\(1\\)>\\)'\\. Supported "
- + "form\\(s\\): 'ENDS_WITH\\(<STRING>, <STRING>\\)'",
+ f.checkBoolean(fn + "('12345', '345')", true);
+ f.checkBoolean(fn + "('12345', '123')", false);
+ f.checkBoolean(fn + "(x'11', x'11')", true);
+ f.checkBoolean(fn + "(x'112211', x'33')", false);
+ f.checkFails("^" + fn + "('aabbcc', x'aa')^",
+ "Cannot apply '" + fn + "' to arguments of type "
+ + "'" + fn + "\\(<CHAR\\(6\\)>, <BINARY\\(1\\)>\\)'\\. Supported
"
+ + "form\\(s\\): '" + fn + "\\(<STRING>, <STRING>\\)'",
false);
- f.checkNull("ends_with(null, null)");
- f.checkNull("ends_with('12345', null)");
- f.checkNull("ends_with(null, '123')");
- f.checkBoolean("ends_with('', '123')", false);
- f.checkBoolean("ends_with('', '')", true);
- f.checkNull("ends_with(x'aa', null)");
- f.checkNull("ends_with(null, x'aa')");
- f.checkBoolean("ends_with(x'1234', x'')", true);
- f.checkBoolean("ends_with(x'', x'123456')", false);
- f.checkBoolean("ends_with(x'', x'')", true);
+ f.checkNull(fn + "(null, null)");
+ f.checkNull(fn + "('12345', null)");
+ f.checkNull(fn + "(null, '123')");
+ f.checkBoolean(fn + "('', '123')", false);
+ f.checkBoolean(fn + "('', '')", true);
+ f.checkNull(fn + "(x'aa', null)");
+ f.checkNull(fn + "(null, x'aa')");
+ f.checkBoolean(fn + "(x'1234', x'')", true);
+ f.checkBoolean(fn + "(x'', x'123456')", false);
+ f.checkBoolean(fn + "(x'', x'')", true);
};
- f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.POSTGRESQL),
consumer);
- }
-
- @Test void testSnowflakeEndsWithFunction() {
- final SqlOperatorFixture f = fixture().withLibrary(SqlLibrary.SNOWFLAKE);
- f.setFor(SqlLibraryOperators.ENDS_WITH);
- f.checkBoolean("endswith('12345', '345')", true);
- f.checkBoolean("endswith('12345', '123')", false);
- f.checkBoolean("endswith(x'11', x'11')", true);
- f.checkBoolean("endswith(x'112211', x'33')", false);
- f.checkFails("^endswith('aabbcc', x'aa')^",
- "Cannot apply 'ENDSWITH' to arguments of type "
- + "'ENDSWITH\\(<CHAR\\(6\\)>, <BINARY\\(1\\)>\\)'\\. Supported "
- + "form\\(s\\): 'ENDSWITH\\(<STRING>, <STRING>\\)'",
- false);
- f.checkNull("endswith(null, null)");
- f.checkNull("endswith('12345', null)");
- f.checkNull("endswith(null, '123')");
- f.checkBoolean("endswith('', '123')", false);
- f.checkBoolean("endswith('', '')", true);
- f.checkNull("endswith(x'aa', null)");
- f.checkNull("endswith(null, x'aa')");
- f.checkBoolean("endswith(x'1234', x'')", true);
- f.checkBoolean("endswith(x'', x'123456')", false);
- f.checkBoolean("endswith(x'', x'')", true);
+ f0.forEachLibrary(list(functionAlias.libraries), consumer);
}
/** Tests the {@code SPLIT} operator. */
@@ -9652,24 +9630,18 @@ public class SqlOperatorTest {
f0.forEachLibrary(list(SqlLibrary.BIG_QUERY, SqlLibrary.ORACLE), consumer);
}
- @Test void testNvlFunc() {
- final SqlOperatorFixture f = fixture()
- .setFor(SqlLibraryOperators.NVL, VmName.EXPAND)
- .withLibrary(SqlLibrary.ORACLE);
- f.checkScalar("nvl(1, 2)", "1", "INTEGER NOT NULL");
- f.checkFails("^nvl(1, true)^", "Parameters must be of the same type",
- false);
- f.checkScalar("nvl(true, false)", true, "BOOLEAN NOT NULL");
- f.checkScalar("nvl(false, true)", false, "BOOLEAN NOT NULL");
- f.checkString("nvl('abc', 'de')", "abc", "CHAR(3) NOT NULL");
- f.checkString("nvl('abc', 'defg')", "abc ", "CHAR(4) NOT NULL");
- f.checkString("nvl('abc', CAST(NULL AS VARCHAR(20)))", "abc",
- "VARCHAR(20) NOT NULL");
- f.checkString("nvl(CAST(NULL AS VARCHAR(20)), 'abc')", "abc",
- "VARCHAR(20) NOT NULL");
- f.checkNull("nvl(CAST(NULL AS VARCHAR(6)), cast(NULL AS VARCHAR(4)))");
+ @Test void testIfNullFunc() {
+ final SqlOperatorFixture f = fixture();
+ f.setFor(SqlLibraryOperators.IFNULL, VmName.EXPAND);
+ checkNvl(f, FunctionAlias.of(SqlLibraryOperators.IFNULL));
+ }
- final SqlOperatorFixture f12 = f.forOracle(SqlConformanceEnum.ORACLE_12);
+ @Test void testNvlFunc() {
+ final SqlOperatorFixture f = fixture();
+ f.setFor(SqlLibraryOperators.NVL, VmName.EXPAND);
+ final SqlOperatorFixture f12 = f
+ .withLibrary(SqlLibrary.ORACLE)
+ .forOracle(SqlConformanceEnum.ORACLE_12);
f12.checkString("nvl('abc', 'de')", "abc", "VARCHAR(3) NOT NULL");
f12.checkString("nvl('abc', 'defg')", "abc", "VARCHAR(4) NOT NULL");
f12.checkString("nvl('abc', CAST(NULL AS VARCHAR(20)))", "abc",
@@ -9677,31 +9649,28 @@ public class SqlOperatorTest {
f12.checkString("nvl(CAST(NULL AS VARCHAR(20)), 'abc')", "abc",
"VARCHAR(20) NOT NULL");
f12.checkNull("nvl(CAST(NULL AS VARCHAR(6)), cast(NULL AS VARCHAR(4)))");
+ checkNvl(f, FunctionAlias.of(SqlLibraryOperators.NVL));
}
- /** Tests {@code IFNULL}, which is a synonym for {@code NVL}, and is related
to
- * {@code COALESCE} but requires precisely two arguments. */
- @Test void testIfnullFunc() {
- final SqlOperatorFixture f = fixture()
- .withLibrary(SqlLibrary.BIG_QUERY)
- .setFor(SqlLibraryOperators.IFNULL, VM_EXPAND);
-
- f.checkString("ifnull('a','b')", "a", "CHAR(1) NOT NULL");
- f.checkString("ifnull(null,'b')", "b", "CHAR(1) NOT NULL");
- f.checkScalar("ifnull(4,3)", 4, "INTEGER NOT NULL");
- f.checkScalar("ifnull(null, 4)", 4, "INTEGER NOT NULL");
- f.enableTypeCoercion(false)
- .checkFails("1 + ifnull('a', 1) + 2",
- "Cannot infer return type for IFNULL; operand types:
\\[CHAR\\(1\\), INTEGER\\]",
- false);
- f.checkType("1 + ifnull(1, null) + 2",
- "INTEGER NOT NULL");
- f.checkFails("^ifnull(1,2,3)^",
- "Invalid number of arguments to function 'IFNULL'. Was expecting 2
arguments",
- false);
- f.checkFails("^ifnull(1)^",
- "Invalid number of arguments to function 'IFNULL'. Was expecting 2
arguments",
- false);
+ /** Tests the {@code NVL} and {@code IFNULL} operators. */
+ void checkNvl(SqlOperatorFixture f0, FunctionAlias functionAlias) {
+ final SqlFunction function = functionAlias.function;
+ final String fn = function.getName();
+ final Consumer<SqlOperatorFixture> consumer = f -> {
+ f.checkScalar(fn + "(1, 2)", "1", "INTEGER NOT NULL");
+ f.checkFails("^" + fn + "(1, true)^",
+ "Parameters must be of the same type", false);
+ f.checkScalar(fn + "(true, false)", true, "BOOLEAN NOT NULL");
+ f.checkScalar(fn + "(false, true)", false, "BOOLEAN NOT NULL");
+ f.checkString(fn + "('abc', 'de')", "abc", "CHAR(3) NOT NULL");
+ f.checkString(fn + "('abc', 'defg')", "abc ", "CHAR(4) NOT NULL");
+ f.checkString(fn + "('abc', CAST(NULL AS VARCHAR(20)))", "abc",
+ "VARCHAR(20) NOT NULL");
+ f.checkString(fn + "(CAST(NULL AS VARCHAR(20)), 'abc')", "abc",
+ "VARCHAR(20) NOT NULL");
+ f.checkNull(fn + "(CAST(NULL AS VARCHAR(6)), cast(NULL AS VARCHAR(4)))");
+ };
+ f0.forEachLibrary(list(functionAlias.libraries), consumer);
}
@Test void testDecodeFunc() {
@@ -14071,4 +14040,48 @@ public class SqlOperatorTest {
.replace("$3", values[3]);
}
}
+
+ /** Contains alias data to re-use tests for aliased operators. */
+ static class FunctionAlias {
+ final SqlFunction function;
+ final List<SqlLibrary> libraries;
+
+ private FunctionAlias(SqlFunction function, List<SqlLibrary> libraries) {
+ this.function = function;
+ this.libraries = libraries;
+ }
+
+ static FunctionAlias of(SqlFunction function) {
+ Field field =
+ lookupField(function.getName(), SqlStdOperatorTable.class,
+ SqlLibraryOperators.class);
+ List<SqlLibrary> libraries = new ArrayList<SqlLibrary>();
+ LibraryOperator libraryOperator =
field.getAnnotation(LibraryOperator.class);
+ if (libraryOperator == null) {
+ libraries.add(SqlLibrary.STANDARD);
+ } else {
+ libraries.addAll(Arrays.asList(libraryOperator.libraries()));
+ }
+ return new FunctionAlias(function, libraries);
+ }
+
+ @SuppressWarnings("rawtypes")
+ static Field lookupField(String name, Class... classes) {
+ for (Class aClass : classes) {
+ try {
+ return aClass.getField(name);
+ } catch (NoSuchFieldException e) {
+ // ignore, and try the next class
+ }
+ }
+ throw new AssertionError("field " + name
+ + " not found in classes" + Arrays.toString(classes));
+ }
+
+ // Used for test naming while running tests in IDE
+ @Override public String toString() {
+ return "function=" + function
+ + ", libraries=" + libraries;
+ }
+ }
}