voonhous commented on code in PR #19583:
URL: https://github.com/apache/hudi/pull/19583#discussion_r3765208693


##########
hudi-spark-datasource/hudi-spark/src/test/scala/org/apache/spark/sql/hudi/dml/schema/TestVariantDataType.scala:
##########
@@ -448,6 +448,86 @@ class TestVariantDataType extends HoodieSparkSqlTestBase {
     })
   }
 
+  test("Test CDC captures VARIANT values from shredded base files") {
+    // #19578: CDC is the only default-config query path that builds the 
internal reader
+    // context without a catalyst schema, and its BASE_FILE_INSERT case 
additionally reads
+    // the new base file directly, bypassing the context, so it needs its own 
full-variant
+    // rewrite. One row only on purpose: a COW update rewrites the base file 
through the
+    // avro merge path, whose shredded-read fix is #19582 (in flight), and a 
single row
+    // leaves nothing for that path to carry over.
+    assume(HoodieSparkUtils.gteqSpark4_1, "Shredded variant base-file read 
requires Spark 4.1 or higher")
+
+    // OP_KEY_ONLY reconstructs both images by reading the (shredded) file 
slices;
+    // DATA_BEFORE_AFTER (the default) reads the update images from the cdc 
log instead.
+    // The insert leg takes BASE_FILE_INSERT in both modes.
+    Seq("OP_KEY_ONLY", "DATA_BEFORE_AFTER").foreach { loggingMode =>
+      withTempDir { tmp =>
+        val tableName = generateTableName
+        val tablePath = tmp.getCanonicalPath
+        spark.sql(
+          s"""
+             |create table $tableName (
+             |  id int,
+             |  v variant,
+             |  ts long
+             |) using hudi
+             | location '$tablePath'
+             | tblproperties (
+             |  primaryKey = 'id',
+             |  type = 'cow',
+             |  preCombineField = 'ts',
+             |  'hoodie.table.cdc.enabled' = 'true',
+             |  'hoodie.table.cdc.supplemental.logging.mode' = '$loggingMode',
+             |  hoodie.parquet.variant.write.shredding.enabled = 'true',

Review Comment:
   Addressed -- the CDC test now sweeps `Seq(true, false)` for shredding 
instead of gaining a second copy, with the layout pin flipped per leg.
   
   One nuance: unshredded-through-the-rewrite is already green via the 
unshredded clustering test from #19558, which drives the same helpers through 
the reader context. What genuinely had no coverage is the hand-rolled 
rewrite/restore block this PR added to `CDCFileGroupIterator`, and that is what 
the new leg hits.
   



##########
hudi-spark-datasource/hudi-spark/src/test/scala/org/apache/spark/sql/hudi/dml/schema/TestVariantDataType.scala:
##########
@@ -448,6 +448,86 @@ class TestVariantDataType extends HoodieSparkSqlTestBase {
     })
   }
 
+  test("Test CDC captures VARIANT values from shredded base files") {
+    // #19578: CDC is the only default-config query path that builds the 
internal reader
+    // context without a catalyst schema, and its BASE_FILE_INSERT case 
additionally reads
+    // the new base file directly, bypassing the context, so it needs its own 
full-variant
+    // rewrite. One row only on purpose: a COW update rewrites the base file 
through the
+    // avro merge path, whose shredded-read fix is #19582 (in flight), and a 
single row
+    // leaves nothing for that path to carry over.
+    assume(HoodieSparkUtils.gteqSpark4_1, "Shredded variant base-file read 
requires Spark 4.1 or higher")
+
+    // OP_KEY_ONLY reconstructs both images by reading the (shredded) file 
slices;
+    // DATA_BEFORE_AFTER (the default) reads the update images from the cdc 
log instead.
+    // The insert leg takes BASE_FILE_INSERT in both modes.
+    Seq("OP_KEY_ONLY", "DATA_BEFORE_AFTER").foreach { loggingMode =>
+      withTempDir { tmp =>
+        val tableName = generateTableName
+        val tablePath = tmp.getCanonicalPath
+        spark.sql(
+          s"""
+             |create table $tableName (
+             |  id int,
+             |  v variant,
+             |  ts long
+             |) using hudi
+             | location '$tablePath'
+             | tblproperties (
+             |  primaryKey = 'id',
+             |  type = 'cow',
+             |  preCombineField = 'ts',
+             |  'hoodie.table.cdc.enabled' = 'true',
+             |  'hoodie.table.cdc.supplemental.logging.mode' = '$loggingMode',
+             |  hoodie.parquet.variant.write.shredding.enabled = 'true',
+             |  hoodie.parquet.variant.force.shredding.schema.for.test = 'key 
string',
+             |  hoodie.index.type = 'INMEMORY'
+             | )
+         """.stripMargin)
+
+        spark.sql(s"""insert into $tableName values (1, 
parse_json('{"key":"value1"}'), 1000)""")
+
+        // Pin the trigger: the base file the CDC reads must actually be 
shredded.
+        val baseFiles = listDataParquetFiles(tablePath)
+        assert(baseFiles.nonEmpty, "Should have a base parquet file after the 
insert")
+        baseFiles.foreach { filePath =>
+          val parquetSchema = readParquetSchema(filePath)
+          val variantGroup = getFieldAsGroup(parquetSchema, "v")
+          assert(variantGroup.containsField("typed_value"),
+            s"Base file should carry typed_value. Schema:\n$variantGroup")
+        }
+
+        spark.sql(s"""update $tableName set v = 
parse_json('{"key":"value2"}'), ts = 1001 where id = 1""")

Review Comment:
   Addressed, and the diagnosis moves a bit. A cdc table is forced onto 
`FileGroupReaderBasedMergeHandle`, whose reader context follows the merger's 
record type, and this was the one test in the file not wrapped in 
`withRecordType` -- so it ran AVRO and hit the #19567 reconstruction gap. What 
fails is the CDC *before* image being written with `value = null`, not a 
carried-over row, so the single-row argument did not hold either way.
   
   Pinned to `HoodieRecordType.SPARK`, which routes that read through the 
context #19558 already fixed. The update leg and both logging modes stay, with 
no dependency on #19582 -- verified green on Spark 4.1 (all four legs). For the 
record, the half of #19582 that would have mattered here is the reconstruction 
detection, not the merge-helper alignment.
   



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

Reply via email to