diff --git a/core/trino-main/src/main/java/io/trino/sql/analyzer/ExpressionAnalyzer.java b/core/trino-main/src/main/java/io/trino/sql/analyzer/ExpressionAnalyzer.java index e792e99c7ecf..27da38e1a50c 100644 --- a/core/trino-main/src/main/java/io/trino/sql/analyzer/ExpressionAnalyzer.java +++ b/core/trino-main/src/main/java/io/trino/sql/analyzer/ExpressionAnalyzer.java @@ -249,6 +249,7 @@ import static io.trino.sql.analyzer.ExpressionTreeUtils.extractWindowExpressions; import static io.trino.sql.analyzer.PatternRecognitionAnalysis.NavigationAnchor.FIRST; import static io.trino.sql.analyzer.PatternRecognitionAnalysis.NavigationAnchor.LAST; +import static io.trino.sql.analyzer.SemanticExceptions.invalidReferenceException; import static io.trino.sql.analyzer.SemanticExceptions.missingAttributeException; import static io.trino.sql.analyzer.SemanticExceptions.semanticException; import static io.trino.sql.analyzer.TypeSignatureProvider.fromTypes; @@ -852,7 +853,8 @@ protected Type visitDereferenceExpression(DereferenceExpression node, Context co } if (rowFieldType == null) { - throw missingAttributeException(node, qualifiedName); + throw invalidReferenceException(node, Optional.ofNullable(qualifiedName) + .orElseGet(() -> QualifiedName.of(fieldName))); } return setExpressionType(node, rowFieldType); diff --git a/core/trino-main/src/main/java/io/trino/sql/analyzer/SemanticExceptions.java b/core/trino-main/src/main/java/io/trino/sql/analyzer/SemanticExceptions.java index db93edb8d510..559edac14afc 100644 --- a/core/trino-main/src/main/java/io/trino/sql/analyzer/SemanticExceptions.java +++ b/core/trino-main/src/main/java/io/trino/sql/analyzer/SemanticExceptions.java @@ -22,6 +22,7 @@ import static io.trino.spi.StandardErrorCode.AMBIGUOUS_NAME; import static io.trino.spi.StandardErrorCode.COLUMN_NOT_FOUND; +import static io.trino.spi.StandardErrorCode.INVALID_COLUMN_REFERENCE; import static io.trino.sql.analyzer.ExpressionTreeUtils.extractLocation; import static java.lang.String.format; @@ -34,6 +35,11 @@ public static TrinoException missingAttributeException(Expression node, Qualifie throw semanticException(COLUMN_NOT_FOUND, node, "Column '%s' cannot be resolved", name); } + public static TrinoException invalidReferenceException(Expression node, QualifiedName name) + { + throw semanticException(INVALID_COLUMN_REFERENCE, node, "Column reference '%s' is invalid", name); + } + public static TrinoException ambiguousAttributeException(Expression node, QualifiedName name) { throw semanticException(AMBIGUOUS_NAME, node, "Column '%s' is ambiguous", name); diff --git a/core/trino-main/src/test/java/io/trino/sql/analyzer/TestAnalyzer.java b/core/trino-main/src/test/java/io/trino/sql/analyzer/TestAnalyzer.java index ff5170289d75..944581bb351c 100644 --- a/core/trino-main/src/test/java/io/trino/sql/analyzer/TestAnalyzer.java +++ b/core/trino-main/src/test/java/io/trino/sql/analyzer/TestAnalyzer.java @@ -384,6 +384,14 @@ public void testHavingReferencesOutputAlias() .hasMessage("line 1:32: Column 'x' cannot be resolved"); } + @Test + public void testRowReferencesUnknownField() + { + assertFails("SELECT row('a', 'b', 'c').field") + .hasErrorCode(INVALID_COLUMN_REFERENCE) + .hasMessage("line 1:8: Column reference 'field' is invalid"); + } + @Test public void testSelectAllColumns() { diff --git a/plugin/trino-opensearch/src/test/java/io/trino/plugin/opensearch/BaseOpenSearchConnectorTest.java b/plugin/trino-opensearch/src/test/java/io/trino/plugin/opensearch/BaseOpenSearchConnectorTest.java index 650ecd9330de..25dc5fcfe106 100644 --- a/plugin/trino-opensearch/src/test/java/io/trino/plugin/opensearch/BaseOpenSearchConnectorTest.java +++ b/plugin/trino-opensearch/src/test/java/io/trino/plugin/opensearch/BaseOpenSearchConnectorTest.java @@ -43,10 +43,12 @@ import java.util.Map; import java.util.stream.Stream; +import static io.trino.spi.StandardErrorCode.INVALID_COLUMN_REFERENCE; import static io.trino.spi.type.DoubleType.DOUBLE; import static io.trino.spi.type.VarcharType.VARCHAR; import static io.trino.testing.MaterializedResult.resultBuilder; import static io.trino.testing.TestingNames.randomNameSuffix; +import static io.trino.testing.assertions.TrinoExceptionAssert.assertTrinoExceptionThrownBy; import static java.lang.String.format; import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; @@ -1047,8 +1049,9 @@ public void testNestedVariants() "SELECT a.b.c FROM nested_variants", "VALUES 'value1', 'value2', 'value3', 'value4'"); - assertThatThrownBy(() -> computeActual("SELECT a.\"b.c\" FROM nested_variants")) - .hasMessageContaining("Column 'a.b.c' cannot be resolved"); + assertTrinoExceptionThrownBy(() -> computeActual("SELECT a.\"b.c\" FROM nested_variants")) + .hasErrorCode(INVALID_COLUMN_REFERENCE) + .hasMessageContaining("Column reference 'a.b.c' is invalid"); } @Test