diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala index bd5a7975299f..89454c252af5 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala @@ -200,16 +200,16 @@ class Analyzer( val postHocResolutionRules: Seq[Rule[LogicalPlan]] = Nil lazy val batches: Seq[Batch] = Seq( - Batch("Hints", fixedPoint, - new ResolveHints.ResolveJoinStrategyHints(conf), - new ResolveHints.ResolveCoalesceHints(conf)), - Batch("Simple Sanity Check", Once, - LookupFunctions), Batch("Substitution", fixedPoint, CTESubstitution, WindowsSubstitution, EliminateUnions, new SubstituteUnresolvedOrdinals(conf)), + Batch("Hints", fixedPoint, + new ResolveHints.ResolveJoinStrategyHints(conf), + new ResolveHints.ResolveCoalesceHints(conf)), + Batch("Simple Sanity Check", Once, + LookupFunctions), Batch("Resolution", fixedPoint, ResolveTableValuedFunctions :: ResolveNamespace(catalogManager) :: diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnalysisSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnalysisSuite.scala index 8db2036496bf..453a4e6aa51c 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnalysisSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnalysisSuite.scala @@ -25,7 +25,7 @@ import org.apache.log4j.Level import org.scalatest.Matchers import org.apache.spark.api.python.PythonEvalType -import org.apache.spark.sql.catalyst.TableIdentifier +import org.apache.spark.sql.catalyst.{AliasIdentifier, TableIdentifier} import org.apache.spark.sql.catalyst.catalog.{CatalogStorageFormat, CatalogTable, CatalogTableType, InMemoryCatalog, SessionCatalog} import org.apache.spark.sql.catalyst.dsl.expressions._ import org.apache.spark.sql.catalyst.dsl.plans._ @@ -879,4 +879,27 @@ class AnalysisSuite extends AnalysisTest with Matchers { Seq("Intersect can only be performed on tables with the compatible column types. " + "timestamp <> double at the second column of the second table")) } + + test("SPARK-32237: Hint in CTE") { + val plan = With( + Project( + Seq(UnresolvedAttribute("cte.a")), + UnresolvedRelation(TableIdentifier("cte")) + ), + Seq( + ( + "cte", + SubqueryAlias( + AliasIdentifier("cte"), + UnresolvedHint( + "REPARTITION", + Seq(Literal(3)), + Project(testRelation.output, testRelation) + ) + ) + ) + ) + ) + assertAnalysisSuccess(plan) + } } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala index 6fab47d15e44..f5dba4c1af26 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/SQLQuerySuite.scala @@ -3468,6 +3468,18 @@ class SQLQuerySuite extends QueryTest with SharedSparkSession with AdaptiveSpark } } + test("SPARK-32237: Hint in CTE") { + withTable("t") { + sql("CREATE TABLE t USING PARQUET AS SELECT 1 AS id") + checkAnswer( + sql(""" + |WITH cte AS (SELECT /*+ REPARTITION(3) */ * FROM t) + |SELECT * FROM cte + """.stripMargin), + Row(1) :: Nil) + } + } + test("SPARK-32372: ResolveReferences.dedupRight should only rewrite attributes for ancestor " + "plans of the conflict plan") { sql("SELECT name, avg(age) as avg_age FROM person GROUP BY name")