diff --git a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeCoercionRule.java b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeCoercionRule.java index c982572b1995..303d5bd1e09a 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeCoercionRule.java +++ b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeCoercionRule.java @@ -171,7 +171,7 @@ private SqlTypeCoercionRule(Map> map) { .add(SqlTypeName.UUID) .build()); - // VARCHAR is castable from BOOLEAN, DATE, TIME, TIMESTAMP, numeric types, binary and + // VARCHAR is castable from BOOLEAN, DATE, TIME, TIMESTAMP, numeric types, binary, uuid, and // intervals coerceRules.add(SqlTypeName.VARCHAR, coerceRules.copyValues(SqlTypeName.VARCHAR) @@ -190,7 +190,7 @@ private SqlTypeCoercionRule(Map> map) { .add(SqlTypeName.UUID) .build()); - // CHAR is castable from BOOLEAN, DATE, TIME, TIMESTAMP, numeric types, binary and + // CHAR is castable from BOOLEAN, DATE, TIME, TIMESTAMP, numeric types, binary, uuid, and // intervals coerceRules.add(SqlTypeName.CHAR, coerceRules.copyValues(SqlTypeName.CHAR) diff --git a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeName.java b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeName.java index d73408cdbed6..c984acbffe69 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/SqlTypeName.java +++ b/core/src/main/java/org/apache/calcite/sql/type/SqlTypeName.java @@ -175,7 +175,7 @@ public enum SqlTypeName { ImmutableList.of(BOOLEAN); public static final List BINARY_TYPES = - ImmutableList.of(BINARY, VARBINARY, UUID); + ImmutableList.of(BINARY, VARBINARY); public static final List INT_TYPES = ImmutableList.of(TINYINT, SMALLINT, INTEGER, BIGINT); diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java index 7d7166745540..aa054d9bb0cb 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java +++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java @@ -779,6 +779,35 @@ static SqlOperatorTable operatorTableFor(SqlLibrary library) { expr("_UTF16'a'||_UTF16'b'||_UTF16'c'").ok(); } + /** Test case for [CALCITE-6779] + * Casts from UUID to DATE should be invalid. */ + @Test void testUuidCasts() { + final String error = "Cast function cannot convert value of type UUID to type.*"; + expr("^CAST(UUID '123e4567-e89b-12d3-a456-426655440000' AS TIME)^").fails(error); + expr("^CAST(UUID '123e4567-e89b-12d3-a456-426655440000' AS DATE)^").fails(error); + expr("^CAST(UUID '123e4567-e89b-12d3-a456-426655440000' AS TIMESTAMP)^").fails(error); + expr("^CAST(UUID '123e4567-e89b-12d3-a456-426655440000' AS INT)^").fails(error); + expr("^CAST(UUID '123e4567-e89b-12d3-a456-426655440000' AS DOUBLE)^").fails(error); + + final String error2 = "Cast function cannot convert value of type.* to type UUID.*"; + expr("^CAST(TIME '10:00:00' AS UUID)^").fails(error2); + expr("^CAST(DATE '2024-01-01' AS UUID)^").fails(error2); + expr("^CAST(TIMESTAMP '2024-01-01 00:00:00' AS UUID)^").fails(error2); + expr("^CAST(2 AS UUID)^").fails(error2); + expr("^CAST(2.0e0 AS UUID)^").fails(error2); + + expr("CAST(UUID '123e4567-e89b-12d3-a456-426655440000' AS UUID)").ok(); + expr("CAST(UUID '123e4567-e89b-12d3-a456-426655440000' AS VARCHAR)").ok(); + expr("CAST(UUID '123e4567-e89b-12d3-a456-426655440000' AS CHAR(2))").ok(); + expr("CAST(UUID '123e4567-e89b-12d3-a456-426655440000' AS BINARY(2))").ok(); + expr("CAST(UUID '123e4567-e89b-12d3-a456-426655440000' AS VARBINARY)").ok(); + + expr("CAST('123e4567-e89b-12d3-a456-426655440000' AS UUID)").ok(); + expr("CAST(CAST('123e4567-e89b-12d3-a456-426655440000' AS VARCHAR) AS UUID)").ok(); + expr("CAST(x'123e4567e89b12d3a456426655440000' AS UUID)").ok(); + expr("CAST(CAST(x'123e4567e89b12d3a456426655440000' AS VARBINARY) AS UUID)").ok(); + } + @Test void testConcatWithCharset() { sql("_UTF16'a'||_UTF16'b'||_UTF16'c'") .assertCharset(isCharset("UTF-16LE")); 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 0df2aa670290..bc68c4b47caf 100644 --- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java +++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java @@ -11262,9 +11262,7 @@ void checkEndsWith(SqlOperatorFixture f0, FunctionAlias functionAlias) { + "'SUBSTRING\\( FROM \\)'\n" + "'SUBSTRING\\( FROM FOR \\)'\n" + "'SUBSTRING\\( FROM \\)'\n" - + "'SUBSTRING\\( FROM FOR \\)'\n" - + "'SUBSTRING\\( FROM \\)'\n" - + "'SUBSTRING\\( FROM FOR \\)'", false); + + "'SUBSTRING\\( FROM FOR \\)'", false); } /** Tests the {@code SUBSTRING} operator. Many test cases that used to be @@ -11320,12 +11318,12 @@ private static void checkSubstringFunction(SqlOperatorFixture f) { String.format(Locale.ROOT, "^substring('string', CAST(%d AS DOUBLE), " + "CAST(%d AS DOUBLE))^", Byte.MIN_VALUE, Byte.MAX_VALUE + 10), "Cannot apply 'SUBSTRING' to arguments of type " - + ".*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*", false); + + ".*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*", false); f.checkFails( String.format(Locale.ROOT, "^substring('string', CAST(%d AS DECIMAL), " + "CAST(%d AS DECIMAL))^", Byte.MIN_VALUE, Byte.MAX_VALUE + 10), "Cannot apply 'SUBSTRING' to arguments of type " - + ".*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*", + + ".*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*\\n.*", false); f.checkFails("substring('abc' from 1 for -1)", "Substring error: negative substring length not allowed",