diff --git a/common/utils/src/main/resources/error/error-conditions.json b/common/utils/src/main/resources/error/error-conditions.json index 31c10f9b9aaca..af19abba725f2 100644 --- a/common/utils/src/main/resources/error/error-conditions.json +++ b/common/utils/src/main/resources/error/error-conditions.json @@ -5129,6 +5129,11 @@ "Referencing lateral column alias in the aggregate query both with window expressions and with having clause. Please rewrite the aggregate query by removing the having clause or removing lateral alias reference in the SELECT list." ] }, + "LATERAL_COLUMN_ALIAS_IN_GENERATOR" : { + "message" : [ + "Referencing a lateral column alias in generator expression ." + ] + }, "LATERAL_COLUMN_ALIAS_IN_GROUP_BY" : { "message" : [ "Referencing a lateral column alias via GROUP BY alias/ALL is not supported yet." diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala index 16899b656f304..38b1f0251cce4 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala @@ -340,6 +340,21 @@ trait CheckAnalysis extends PredicateHelper with LookupCatalog with QueryErrorsB // surrounded with single quotes, or there is a typo in the attribute name. case GetMapValue(map, key: Attribute) if isMapWithStringKey(map) && !key.resolved => failUnresolvedAttribute(operator, key, "UNRESOLVED_MAP_KEY") + + case e: Expression if e.containsPattern(LATERAL_COLUMN_ALIAS_REFERENCE) && + operator.expressions.exists { + case a: Alias + if e.collect { case l: LateralColumnAliasReference => l.nameParts.head } + .contains(a.name) => + a.exists(_.isInstanceOf[Generator]) + case _ => false + } => + val lcaRefNames = + e.collect { case lcaRef: LateralColumnAliasReference => lcaRef.name }.distinct + failAnalysis( + errorClass = "UNSUPPORTED_FEATURE.LATERAL_COLUMN_ALIAS_IN_GENERATOR", + messageParameters = + Map("lca" -> toSQLId(lcaRefNames), "generatorExpr" -> toSQLExpr(e))) } // Fail if we still have an unresolved all in group by. This needs to run before the diff --git a/sql/core/src/test/scala/org/apache/spark/sql/LateralColumnAliasSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/LateralColumnAliasSuite.scala index d7177e19a6177..3def42cd7ee55 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/LateralColumnAliasSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/LateralColumnAliasSuite.scala @@ -1365,4 +1365,41 @@ class LateralColumnAliasSuite extends LateralColumnAliasSuiteBase { // the states are cleared - a subsequent correct query should succeed sql("select 1 as a, a").queryExecution.assertAnalyzed() } + + test("SPARK-49349: Improve error message for LCA with Generate") { + checkError( + exception = intercept[AnalysisException] { + sql( + s""" + |SELECT + | explode(split(name , ',')) AS new_name, + | new_name like 'a%' + |FROM $testTable + |""".stripMargin) + }, + condition = "UNSUPPORTED_FEATURE.LATERAL_COLUMN_ALIAS_IN_GENERATOR", + sqlState = "0A000", + parameters = Map( + "lca" -> "`new_name`", + "generatorExpr" -> "\"unresolvedalias(lateralAliasReference(new_name) LIKE a%)\"")) + + checkError( + exception = intercept[AnalysisException] { + sql( + s""" + |SELECT + | explode_outer(from_json(name,'array>')) as newName, + | size(from_json(newName.values,'array')) + + | size(array(from_json(newName.values,'map'))) as size + |FROM $testTable + |""".stripMargin) + }, + condition = "UNSUPPORTED_FEATURE.LATERAL_COLUMN_ALIAS_IN_GENERATOR", + sqlState = "0A000", + parameters = Map( + "lca" -> "`newName.values`", + "generatorExpr" -> ("\"(size(from_json(lateralAliasReference(newName.values), " + + "array)) + size(array(from_json(lateralAliasReference(newName.values), " + + "map)))) AS size\""))) + } }