hudi-agent commented on code in PR #19283:
URL: https://github.com/apache/hudi/pull/19283#discussion_r3578371148


##########
hudi-client/hudi-spark-client/src/main/scala/org/apache/hudi/SparkFileFormatInternalRowReaderContext.scala:
##########
@@ -144,10 +144,9 @@ class 
SparkFileFormatInternalRowReaderContext(baseFileReader: SparkColumnarFileR
     // Parquet stores VECTOR as FIXED_LEN_BYTE_ARRAY, so the reader needs 
BinaryType
     // and we decode back to ArrayType below. Lance returns ArrayType 
natively, so skip
     // the rewrite only for Lance base files; log files always go through the 
rewrite path.

Review Comment:
   🤖 nit: this comment now contradicts the code below it — `isLanceFile` (line 
148) is `!isInlineLog && tableConfig.getBaseFileFormat == LANCE`, so native 
Lance log files also skip the vector rewrite, but the comment still says "log 
files always go through the rewrite path". Could you update it to something 
like "the rewrite only for Lance files (base and native log); inline log files 
always go through the rewrite path" so future readers aren't misled?
   
   <sub><i>⚠️ AI-generated; verify before applying. React 👍/👎 to flag 
quality.</i></sub>



##########
hudi-client/hudi-client-common/src/main/java/org/apache/hudi/table/action/compact/HoodieCompactor.java:
##########
@@ -174,8 +174,7 @@ public List<WriteStatus> logCompact(HoodieWriteConfig 
writeConfig,
                                       TaskContextSupplier taskContextSupplier) 
throws IOException {
     HoodieReaderContext<IndexedRecord> readerContext = new 
HoodieAvroReaderContext(
         table.getStorageConf(), table.getMetaClient().getTableConfig(), 
instantRange, Option.empty(), writeConfig.getProps());
-    HoodieAppendHandle<IndexedRecord, ?, ?, ?> appendHandle = 
CommonClientUtils.shouldWriteNativeLogs(
-        writeConfig, table.getMetaClient().getTableConfig())
+    HoodieAppendHandle<IndexedRecord, ?, ?, ?> appendHandle = 
CommonClientUtils.shouldWriteNativeLogs(writeConfig)
         ? new FileGroupReaderBasedNativeLogAppendHandle<>(writeConfig, 
instantTime, table, operation, taskContextSupplier, readerContext)

Review Comment:
   🤖 Now that Lance passes shouldWriteNativeLogs, this builds a 
FileGroupReaderBasedNativeLogAppendHandle with a hardcoded 
HoodieAvroReaderContext, but unlike the delta-commit path it doesn't get the 
Spark record-context override that SparkNativeLogAppendHandle adds. On Spark 
executors the handle's record context degrades to Avro (the same degradation 
your comment in SparkNativeLogAppendHandle describes), so 
HoodieNativeLogFormatWriter.ensureDeleteFileWriter creates the .deletes.lance 
writer with record type AVRO -- and HoodieAvroFileWriterFactory has no Lance 
writer, so it throws LANCE_UNSUPPORTED_ERROR_MSG. Have you been able to run 
Lance MOR log compaction end-to-end? @nsivabalan could you sanity-check this 
path?
   
   <sub><i>⚠️ AI-generated; verify before applying. React 👍/👎 to flag 
quality.</i></sub>



##########
hudi-client/hudi-spark-client/src/main/scala/org/apache/hudi/SparkFileFormatInternalRowReaderContext.scala:
##########
@@ -144,10 +144,9 @@ class 
SparkFileFormatInternalRowReaderContext(baseFileReader: SparkColumnarFileR
     // Parquet stores VECTOR as FIXED_LEN_BYTE_ARRAY, so the reader needs 
BinaryType
     // and we decode back to ArrayType below. Lance returns ArrayType 
natively, so skip
     // the rewrite only for Lance base files; log files always go through the 
rewrite path.
-    val isLogFile = FSUtils.isLogFile(filePath)
-    val isLanceBaseFile = !isLogFile && FSUtils.isBaseFile(filePath) &&
-      tableConfig.getBaseFileFormat == HoodieFileFormat.LANCE
-    val vectorColumnInfo: Map[Int, HoodieSchema.Vector] = if (isLanceBaseFile) 
{
+    val isInlineLog = FSUtils.isInlineLogFile(filePath.getName)
+    val isLanceFile = !isInlineLog && tableConfig.getBaseFileFormat == 
HoodieFileFormat.LANCE

Review Comment:
   🤖 I traced this and the mismatch looks real. A native Lance log is named 
`<fileId>_<writeToken>_<instant>_<version>.log.lance` (see 
`FileNameParser.NATIVE_LOG_FILE_PATTERN`), so `filePath.getFileExtension()` 
returns `.lance` and `fromFileExtension` at line 174 does dispatch it to the 
Lance reader by extension. But at line 148 `isLanceFile` keys off 
`tableConfig.getBaseFileFormat`, so in a non-Lance-default multi-format table 
it's `false` → `vectorColumnInfo` gets populated and the schema is 
binary-rewritten. Worth noting the `wrapWithVectorConversion` post-processing 
at line 207 only runs in the non-log branch, so nothing converts it back on the 
log path either. Keying `isLanceFile` off `filePath.getFileExtension` 
(consistent with line 174) would keep the two decisions aligned.



##########
hudi-client/hudi-spark-client/src/main/java/org/apache/hudi/io/SparkAppendHandleFactory.java:
##########
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hudi.io;
+
+import org.apache.hudi.common.engine.TaskContextSupplier;
+import org.apache.hudi.common.model.HoodieRecord;
+import org.apache.hudi.config.HoodieWriteConfig;
+import org.apache.hudi.table.HoodieTable;
+import org.apache.hudi.util.CommonClientUtils;
+
+import java.util.Iterator;
+
+/**
+ * Spark-specific append-handle factory for native logs.
+ *
+ * <p>It selects {@link SparkNativeLogAppendHandle} only after native logs are 
enabled. The handle then uses the
+ * write config's record type to decide whether delete records must be 
represented as Spark rows or Avro records.</p>

Review Comment:
   🤖 nit: "only after native logs are enabled" reads like a temporal sequence 
("after some enabling event") rather than a condition — could you change it to 
"only when native logs are enabled"?
   
   <sub><i>⚠️ AI-generated; verify before applying. React 👍/👎 to flag 
quality.</i></sub>



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