Skip to content

Commit 0c9ebcf

Browse files
committed
fixup: address review comments
1 parent eed0731 commit 0c9ebcf

File tree

4 files changed

+38
-17
lines changed

4 files changed

+38
-17
lines changed

core/trino-grammar/src/main/antlr4/io/trino/grammar/sql/SqlBase.g4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ primaryExpression
607607
| TRY_CAST '(' expression AS type ')' #cast
608608
// the target is a primaryExpression to support PostgreSQL-style casts
609609
// of the form <complex expression>::<type>, which are syntactically ambiguous with
610-
// static method calls
610+
// static method calls defined by the SQL spec (and we reserve it for future use)
611611
| primaryExpression DOUBLE_COLON identifier ('(' (expression (',' expression)*)? ')')? #staticMethodCall
612612
| ARRAY '[' (expression (',' expression)*)? ']' #arrayConstructor
613613
| '[' (expression (',' expression)*)? ']' #arrayConstructor

core/trino-main/src/main/java/io/trino/sql/analyzer/ExpressionAnalyzer.java

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,31 +1708,30 @@ private void analyzeFrameRangeOffset(Expression offsetValue, FrameBound.Type bou
17081708
@Override
17091709
protected Type visitStaticMethodCall(StaticMethodCall node, Context context)
17101710
{
1711-
// PostgreSQL-style are syntactically ambiguous with static method calls. So, static method call semantics take precendence.
1711+
// PostgreSQL-style casts are syntactically ambiguous with static method calls. So, static method call semantics take precendence.
17121712
// A static method call is characterized by the target being an expression whose type is "type". This not yet supported
17131713
// as a first-class concept, so we fake it by analyzing the expression normally. If the analysis succeeds, we treat it as
1714-
// the target of a cast. If the analysis fails, check whether the target is an identifier matching a known type name.
1715-
try {
1716-
process(node.getTarget(), context);
1717-
}
1718-
catch (TrinoException e) {
1719-
// assume it might be a type name, so check if it's an identifier matching a known type
1720-
if (node.getTarget() instanceof Identifier target) {
1721-
try {
1722-
plannerContext.getTypeManager().fromSqlType(target.getValue());
1723-
}
1724-
catch (TypeNotFoundException typeException) {
1725-
// since the type is not found, treat the expression as normal expression that failed analysis
1726-
throw e;
1727-
}
1714+
// the target of a cast.
1715+
1716+
// Trino allows resolving column names that match type names, so we need to check explicitly
1717+
// if this is a type reference in the context of a static method call
1718+
if (node.getTarget() instanceof Identifier target) {
1719+
try {
1720+
plannerContext.getTypeManager().fromSqlType(target.getValue());
1721+
throw semanticException(NOT_SUPPORTED, node, "Static method calls are not supported");
1722+
}
1723+
catch (TypeNotFoundException typeException) {
1724+
// since the type is not found, this must be a normal value-producing expression. Treat it as a candidate for
1725+
// resolving the PostgreSQL-style cast, as explained above.
17281726
}
1729-
throw semanticException(NOT_SUPPORTED, node, "Static method calls are not supported");
17301727
}
17311728

17321729
if (!node.getArguments().isEmpty()) {
17331730
throw semanticException(NOT_SUPPORTED, node, "Static method calls are not supported");
17341731
}
17351732

1733+
process(node.getTarget(), context);
1734+
17361735
// assume it's a PostgreSQL-style cast unless result type is not a known type
17371736
try {
17381737
Type type = plannerContext.getTypeManager().fromSqlType(node.getMethod().getValue());

core/trino-main/src/test/java/io/trino/operator/scalar/TestStaticMethodCall.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package io.trino.operator.scalar;
1515

1616
import io.trino.spi.type.DoubleType;
17+
import io.trino.spi.type.VarcharType;
1718
import io.trino.sql.query.QueryAssertions;
1819
import org.junit.jupiter.api.AfterAll;
1920
import org.junit.jupiter.api.BeforeAll;
@@ -52,11 +53,18 @@ void testPostgreSqlStyleCast()
5253
.hasType(DoubleType.DOUBLE)
5354
.isEqualTo(1.0);
5455

56+
assertThat(assertions.expression("1::varchar"))
57+
.hasType(VarcharType.VARCHAR)
58+
.isEqualTo("1");
59+
5560
assertThat(assertions.expression("(a + b)::double")
5661
.binding("a", "1")
5762
.binding("b", "2"))
5863
.hasType(DoubleType.DOUBLE)
5964
.isEqualTo(3.0);
65+
66+
assertThatThrownBy(() -> assertions.expression("1::decimal(3, 2)").evaluate())
67+
.hasMessage("line 1:13: Static method calls are not supported");
6068
}
6169

6270
@Test
@@ -73,5 +81,9 @@ void testCall()
7381

7482
assertThatThrownBy(() -> assertions.expression("integer::foo(1, 2)").evaluate())
7583
.hasMessage("line 1:19: Static method calls are not supported");
84+
85+
assertThat(assertions.query("SELECT bigint::real FROM (VALUES 1) AS t(bigint)"))
86+
.failure()
87+
.hasMessage("line 1:14: Static method calls are not supported");
7688
}
7789
}

core/trino-parser/src/test/java/io/trino/sql/parser/TestSqlParser.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,16 @@ void testStaticMethodCall()
850850
new Identifier(location(1, 6), "b", false)),
851851
new Identifier(location(1, 10), "double", false),
852852
emptyList()));
853+
854+
855+
assertThatThrownBy(() -> SQL_PARSER.createExpression("1::double precision"))
856+
.hasMessageMatching(".*mismatched input.*");
857+
858+
assertThatThrownBy(() -> SQL_PARSER.createExpression("'abc'::timestamp with time zone"))
859+
.hasMessageMatching(".*mismatched input.*");
860+
861+
assertThatThrownBy(() -> SQL_PARSER.createExpression("'abc'::interval year to month"))
862+
.hasMessageMatching(".*mismatched input.*");
853863
}
854864

855865
@Test

0 commit comments

Comments
 (0)