Copilot commented on code in PR #12473:
URL: https://github.com/apache/gluten/pull/12473#discussion_r3541165679
##########
gluten-ut/spark40/src/test/scala/org/apache/spark/sql/GlutenSubquerySuite.scala:
##########
@@ -32,24 +37,81 @@ class GlutenSubquerySuite extends SubquerySuite with
GlutenSQLTestsTrait {
"SPARK-28441: COUNT bug with attribute ref in subquery input and output
with PythonUDF"
)
- // === Following cases override super class's cases ===
- // TODO: fix in Spark-4.0
- ignoreGluten("SPARK-26893 Allow pushdown of partition pruning subquery
filters to file source") {
+ testGluten("SPARK-26893: Allow pushdown of partition pruning subquery
filters to file source") {
withTable("a", "b") {
spark.range(4).selectExpr("id", "id % 2 AS
p").write.partitionBy("p").saveAsTable("a")
spark.range(2).write.saveAsTable("b")
- // need to execute the query before we can examine fs.inputRDDs()
val df = sql("SELECT * FROM a WHERE p <= (SELECT MIN(id) FROM b)")
checkAnswer(df, Seq(Row(0, 0), Row(2, 0)))
- assert(stripAQEPlan(df.queryExecution.executedPlan).collectFirst {
- case t: WholeStageTransformer => t
- } match {
- case Some(WholeStageTransformer(fs: FileSourceScanExecTransformer, _))
=>
- fs.dynamicallySelectedPartitions.toPartitionArray
- .exists(_.filePath.toString.contains("p=0"))
- case _ => false
+ // need to execute the query before we can examine fs.inputRDDs()
+ val fileSourceScanExec =
collect(stripAQEPlan(df.queryExecution.executedPlan)) {
+ case fs: FileSourceScanExecTransformer => fs
+ }
+ assert(fileSourceScanExec.size === 1)
+ val scan = fileSourceScanExec.head
+ assert(scan.partitionFilters.exists(ExecSubqueryExpression.hasSubquery))
+ val selectedPartitions =
scan.dynamicallySelectedPartitions.toPartitionArray
+ assert(selectedPartitions.nonEmpty)
+ assert(selectedPartitions.forall(_.filePath.toString.contains("p=0")))
+ }
+ }
+
+ testGluten("SPARK-36280: Remove redundant aliases after
RewritePredicateSubquery") {
+ withTable("t1", "t2") {
+ sql("CREATE TABLE t1 USING parquet AS SELECT id AS a, id AS b, id AS c
FROM range(10)")
+ sql("CREATE TABLE t2 USING parquet AS SELECT id AS x, id AS y FROM
range(8)")
+ val df = sql(
+ """
+ |SELECT *
+ |FROM t1
+ |WHERE a IN (SELECT x
+ | FROM (SELECT x AS x,
+ | RANK() OVER (PARTITION BY x ORDER BY
SUM(y) DESC) AS ranking
+ | FROM t2
+ | GROUP BY x) tmp1
+ | WHERE ranking <= 5)
+ |""".stripMargin)
+
+ df.collect()
+ val exchanges = collect(df.queryExecution.executedPlan) {
+ case s: ColumnarShuffleExchangeExec => s
+ }
+ assert(exchanges.size === 1)
+ }
+ }
+
+ testGluten(
+ "SPARK-43402: FileSourceScanExec supports push down data filter with
scalar subquery") {
+ def checkFileSourceScan(query: String, answer: Seq[Row]): Unit = {
+ val df = sql(query)
+ checkAnswer(df, answer)
+ val fileSourceScanExec = collect(df.queryExecution.executedPlan) {
+ case f: FileSourceScanExecTransformer => f
+ }
+ sparkContext.listenerBus.waitUntilEmpty()
+ assert(fileSourceScanExec.size === 1)
+ val scalarSubquery =
fileSourceScanExec.head.dataFilters.flatMap(_.collect {
+ case s: ScalarSubquery => s
})
+ assert(scalarSubquery.length === 1)
+ assert(scalarSubquery.head.plan.isInstanceOf[ReusedSubqueryExec])
+ assert(fileSourceScanExec.head.metrics("numFiles").value === 1)
+ assert(fileSourceScanExec.head.metrics("numOutputRows").value ===
answer.size)
Review Comment:
The SPARK-43402 test assumes the scalar subquery plan is always a
ReusedSubqueryExec and that scan metrics always contain
"numFiles"/"numOutputRows". In practice the scalar subquery can be a plain
SubqueryExec (no reuse when it appears once), and missing metric keys would
currently throw a NoSuchElementException, making the test flaky across Spark
configs/backends.
##########
gluten-ut/spark41/src/test/scala/org/apache/spark/sql/GlutenSubquerySuite.scala:
##########
@@ -32,24 +37,81 @@ class GlutenSubquerySuite extends SubquerySuite with
GlutenSQLTestsTrait {
"SPARK-28441: COUNT bug with attribute ref in subquery input and output
with PythonUDF"
)
- // === Following cases override super class's cases ===
- // TODO: fix in Spark-4.0
- ignoreGluten("SPARK-26893 Allow pushdown of partition pruning subquery
filters to file source") {
+ testGluten("SPARK-26893: Allow pushdown of partition pruning subquery
filters to file source") {
withTable("a", "b") {
spark.range(4).selectExpr("id", "id % 2 AS
p").write.partitionBy("p").saveAsTable("a")
spark.range(2).write.saveAsTable("b")
- // need to execute the query before we can examine fs.inputRDDs()
val df = sql("SELECT * FROM a WHERE p <= (SELECT MIN(id) FROM b)")
checkAnswer(df, Seq(Row(0, 0), Row(2, 0)))
- assert(stripAQEPlan(df.queryExecution.executedPlan).collectFirst {
- case t: WholeStageTransformer => t
- } match {
- case Some(WholeStageTransformer(fs: FileSourceScanExecTransformer, _))
=>
- fs.dynamicallySelectedPartitions.toPartitionArray
- .exists(_.filePath.toString.contains("p=0"))
- case _ => false
+ // need to execute the query before we can examine fs.inputRDDs()
+ val fileSourceScanExec =
collect(stripAQEPlan(df.queryExecution.executedPlan)) {
+ case fs: FileSourceScanExecTransformer => fs
+ }
+ assert(fileSourceScanExec.size === 1)
+ val scan = fileSourceScanExec.head
+ assert(scan.partitionFilters.exists(ExecSubqueryExpression.hasSubquery))
+ val selectedPartitions =
scan.dynamicallySelectedPartitions.toPartitionArray
+ assert(selectedPartitions.nonEmpty)
+ assert(selectedPartitions.forall(_.filePath.toString.contains("p=0")))
+ }
+ }
+
+ testGluten("SPARK-36280: Remove redundant aliases after
RewritePredicateSubquery") {
+ withTable("t1", "t2") {
+ sql("CREATE TABLE t1 USING parquet AS SELECT id AS a, id AS b, id AS c
FROM range(10)")
+ sql("CREATE TABLE t2 USING parquet AS SELECT id AS x, id AS y FROM
range(8)")
+ val df = sql(
+ """
+ |SELECT *
+ |FROM t1
+ |WHERE a IN (SELECT x
+ | FROM (SELECT x AS x,
+ | RANK() OVER (PARTITION BY x ORDER BY
SUM(y) DESC) AS ranking
+ | FROM t2
+ | GROUP BY x) tmp1
+ | WHERE ranking <= 5)
+ |""".stripMargin)
+
+ df.collect()
+ val exchanges = collect(df.queryExecution.executedPlan) {
+ case s: ColumnarShuffleExchangeExec => s
+ }
+ assert(exchanges.size === 1)
+ }
+ }
+
+ testGluten(
+ "SPARK-43402: FileSourceScanExec supports push down data filter with
scalar subquery") {
+ def checkFileSourceScan(query: String, answer: Seq[Row]): Unit = {
+ val df = sql(query)
+ checkAnswer(df, answer)
+ val fileSourceScanExec = collect(df.queryExecution.executedPlan) {
+ case f: FileSourceScanExecTransformer => f
+ }
+ sparkContext.listenerBus.waitUntilEmpty()
+ assert(fileSourceScanExec.size === 1)
+ val scalarSubquery =
fileSourceScanExec.head.dataFilters.flatMap(_.collect {
+ case s: ScalarSubquery => s
})
+ assert(scalarSubquery.length === 1)
+ assert(scalarSubquery.head.plan.isInstanceOf[ReusedSubqueryExec])
+ assert(fileSourceScanExec.head.metrics("numFiles").value === 1)
+ assert(fileSourceScanExec.head.metrics("numOutputRows").value ===
answer.size)
Review Comment:
The SPARK-43402 test assumes the scalar subquery plan is always a
ReusedSubqueryExec and that scan metrics always contain
"numFiles"/"numOutputRows". In practice the scalar subquery can be a plain
SubqueryExec (no reuse when it appears once), and missing metric keys would
currently throw a NoSuchElementException, making the test flaky across Spark
configs/backends.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]