comphead commented on code in PR #7347:
URL: https://github.com/apache/datafusion-comet/pull/7347#discussion_r4486202206


##########
spark/src/test/scala/org/apache/comet/exec/CometInMemoryCacheSuite.scala:
##########
@@ -112,6 +112,76 @@ class CometInMemoryCacheSuite extends CometTestBase {
   private def withConversions(pairs: (String, String)*)(f: => Unit): Unit =
     withSQLConf(pairs ++ sparkToArrowConversionConfs(enabled = true): _*)(f)
 
+  test("cache scan reports the concrete decoded vector types") {
+    withConversions(SQLConf.ADAPTIVE_EXECUTION_ENABLED.key -> "false") {
+      val cached = spark
+        .sql(
+          "SELECT 1 AS i, 'text' AS s, array(1, 2) AS a, " +
+            "named_struct('v', 3) AS st, map('k', 4) AS m, true AS b, " +
+            "CAST(1 AS TINYINT) AS ti, CAST(2 AS SMALLINT) AS sh, 3L AS l, " +
+            "CAST(1 AS FLOAT) AS f, CAST(2 AS DOUBLE) AS d, " +
+            "CAST(12.3 AS DECIMAL(10, 1)) AS dec, DATE '2024-01-02' AS day, " +
+            "TIMESTAMP '2024-01-02 03:04:05' AS ts, " +
+            "CAST('2024-01-02 03:04:05' AS TIMESTAMP_NTZ) AS ntz, " +
+            "CAST('bytes' AS BINARY) AS bin, NULL AS n, 42 AS unused")
+        .cache()
+      try {
+        cached.count()
+        // Reorder and prune the columns, so types follow scan output, not 
cache-schema order.
+        val query = cached.select(
+          "m",
+          "i",
+          "st",
+          "a",
+          "s",
+          "b",
+          "ti",
+          "sh",
+          "l",
+          "f",
+          "d",
+          "dec",
+          "day",
+          "ts",
+          "ntz",
+          "bin",
+          "n")
+        query.collect()
+        val scans = collect(query.queryExecution.executedPlan) {
+          case scan: CometInMemoryTableScanExec => scan
+        }
+        assert(scans.size == 1, query.queryExecution.executedPlan)
+        val scan = scans.head
+        val actual = scan
+          .executeColumnar()
+          .mapPartitions { batches =>
+            batches.map { batch =>
+              (0 until batch.numCols()).map(i => 
batch.column(i).getClass.getName).toArray
+            }
+          }
+          .collect()
+        assert(actual.nonEmpty)
+        val reported = scan.vectorTypes.getOrElse(fail("cache scan reported no 
vector types"))
+        actual.foreach(types => assert(types.toSeq == reported))
+      } finally {

Review Comment:
   This compares the batch classes with `vectorTypes`, but nothing shows the 
codegen cast runs: the result of `query.collect()` is not checked against an 
expected answer, and there is no assertion that a `CometColumnarToRowExec` 
inside a `WholeStageCodegenExec` reads this scan. The source is also one 
constant row. Could the test assert that plan shape and use a multi-batch 
cache, for example from Parquet with repeated strings?



##########
spark/src/main/scala/org/apache/spark/sql/comet/execution/arrow/ArrowCachedBatchSerializer.scala:
##########
@@ -543,6 +543,29 @@ class ArrowCachedBatchSerializer extends 
SimpleMetricsCachedBatchSerializer {
     }
   }
 
+  /**
+   * Report vector types for a cache scan whose full stored schema is known. 
Spark's serializer
+   * `vectorTypes` hook receives only the projected attributes, which is 
insufficient here: an
+   * unsupported unselected column makes the entire cached relation use 
Spark's fallback format.
+   */
+  def vectorTypesForScan(
+      cacheAttributes: Seq[Attribute],
+      selectedAttributes: Seq[Attribute],
+      conf: SQLConf): Option[Seq[String]] = {
+    if (!supportsSchema(cacheAttributes)) {
+      fallback.vectorTypes(selectedAttributes, conf)
+    } else {
+      Some(selectedAttributes.map { attr =>
+        attr.dataType match {
+          case _: StructType => classOf[CometStructVector].getName
+          case _: MapType => classOf[CometMapVector].getName
+          case _: ArrayType => classOf[CometListVector].getName
+          case _ => classOf[CometPlainVector].getName
+        }
+      })
+    }

Review Comment:
   I do not think the fallback branch or the `cacheAttributes` parameter can be 
reached from a planned scan. `CometExecRule.readsCometCacheFormat` builds a 
`CometInMemoryTableScanExec` only when the serializer is an 
`ArrowCachedBatchSerializer` and `supportsSchema(scan.relation.output)` holds, 
and `createExec` passes `relation.output` as `relationOutput`. So the 
unsupported unselected column case never produces this scan, and the `case 
other` arm in `CometInMemoryTableScanExec.vectorTypes` is unreachable for the 
same reason. Could the scan compute the names from `scanOutput` itself and 
leave the serializer unchanged? That would also drop the test around 
`CometInMemoryCacheSuite.scala` line 173 that compares `vectorTypesForScan` 
with the `fallback.vectorTypes` it delegates to.



-- 
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]

Reply via email to