sunchao commented on code in PR #5898:
URL: https://github.com/apache/datafusion-comet/pull/5898#discussion_r4363594959


##########
native/Cargo.toml:
##########
@@ -85,8 +85,8 @@ aws-sdk-sts = { version = "1.114.0", default-features = false 
}
 # Pinned to a revision rather than a release because no published iceberg-rust
 # version is on our arrow: 0.10.1 requires arrow/parquet ^58. Move to a plain
 # version requirement once a release ships on arrow 59. Bump policy: #5645.
-iceberg = { git = "https://github.com/apache/iceberg-rust";, rev = 
"1f3bc34058e3f3e45336bc5428f37b92649a608b" }
-iceberg-storage-opendal = { git = "https://github.com/apache/iceberg-rust";, 
rev = "1f3bc34058e3f3e45336bc5428f37b92649a608b", features = ["opendal-memory", 
"opendal-fs", "opendal-s3", "opendal-gcs", "opendal-oss", "opendal-azdls"] }
+iceberg = { git = "https://github.com/apache/iceberg-rust";, rev = 
"ca21f1587c6caaeb88dd3a9e1cc245747e1aba08" }

Review Comment:
   [P2] Preserve compatible reads of pruned structs when updating this pin. 
Import a Parquet file containing `s STRUCT<a: INT, b: INT>` without field IDs 
or a name mapping, then run `SELECT s.b` with the default nested pruning 
enabled. The new revision throws `cannot reconcile struct fields by id`; Spark 
completes the query. With `b` containing only NULLs, the base also returns the 
same NULL rows as Spark, isolating a newly introduced failure. The changed test 
now expects this exception instead of preventing it. Please add compatible 
handling or a JVM fallback for this case and retain a Spark-parity assertion.
   
   Evidence: Executed standalone ArrowReader reproductions with iceberg-rust 
`1f3bc34058e3f3e45336bc5428f37b92649a608b` and 
`ca21f1587c6caaeb88dd3a9e1cc245747e1aba08`, both using Arrow/Parquet 59.3.1. 
For rows s=(10,NULL),(20,NULL), the pruned base read succeeds with two NULLs 
and the head read errors. Logs: `/tmp/5898-b493-base-exact-arrow.log` and 
`/tmp/5898-b493-head-exact-arrow-online.log`. Iceberg Java’s fallback schema 
assigns only top-level IDs and its optional-field reader supplies NULLs. The 
PR’s `CometIcebergNativeSuite.scala:2814` expects the same new failure.



##########
spark/src/main/scala/org/apache/comet/rules/CometScanRule.scala:
##########
@@ -898,6 +905,52 @@ case class CometScanRule(session: SparkSession)
           case None => true
         }
 
+        // iceberg-rust's HDFS client cannot use an executor's delegation 
tokens: opendal builds
+        // every client for a synthetic nameservice, and the client looks 
tokens up by that name.
+        // A portless authority must be a declared nameservice (see 
hadoopToIcebergHdfsProperties).
+        val hdfsSupported = taskValidation.hdfsAuthorities.isEmpty || {
+          val authentication = 
hadoopConf.getTrimmed("hadoop.security.authentication", "simple")
+          val secure = !authentication.equalsIgnoreCase("simple")
+          if (secure) {
+            fallbackReasons += "Iceberg scan reads HDFS with " +
+              s"hadoop.security.authentication=$authentication, but Comet's 
native Iceberg " +
+              "reader cannot authenticate to HDFS with delegation tokens"
+          }
+          val undeclared = CometIcebergNativeScan.undeclaredHdfsNameservice(
+            taskValidation.hdfsAuthorities,
+            metadata.catalogProperties)
+          undeclared.foreach { ns =>
+            fallbackReasons += s"Iceberg scan reads HDFS authority '$ns', 
which has no port and " +
+              "which the Hadoop configuration does not declare as a 
nameservice " +
+              s"(dfs.ha.namenodes.$ns, and a host:port 
dfs.namenode.rpc-address.$ns.<id> for " +
+              "each NameNode)"
+          }
+          !secure && undeclared.isEmpty

Review Comment:
   [P2] Retain JVM fallback for HDFS encryption-zone files until native 
decryption is supported. On a simple-auth cluster with a configured KMS, an 
authorized read of a table inside an encryption zone passes this 
authentication/nameservice gate. The selected client is built without the `kms` 
feature and rejects every encrypted file, whereas Hadoop’s reader decrypts it. 
Because native Iceberg scans default to enabled, this changes previously 
successful reads into failed tasks. Please add a conservative fallback or wire 
and validate KMS support before admitting these scans.
   
   Evidence: The lockfile pins hdfs-native 0.14.7. OpenDAL 0.58.2 depends on it 
without enabling `kms`, and Comet adds no feature activation. In hdfs-native 
`client.rs`, `read()` passes `file_encryption_info` to `build_crypto_codec`, 
whose non-KMS branch unconditionally returns `UnsupportedFeature` for an 
encrypted file. Hadoop 3.3.4 and 3.4.2 `DFSClient.createWrappedInputStream` 
instead invoke `HdfsKMSUtil` when that information is present. This failure 
path was source-verified; a live encryption-zone reproduction was not run.



##########
native/core/src/execution/operators/iceberg_common.rs:
##########
@@ -302,9 +306,10 @@ fn cached_file_io(
 /// mode; the JVM read and write gates load these lists over JNI. `memory` is 
write-only: an OpenDAL
 /// memory backend is a fresh empty in-process store the write path assembles 
manifests in, so a
 /// read finds nothing. `oss` is read-only: no `oss.*` property is forwarded 
and no test covers it.
+/// `hdfs` is read-only: the write path has not been tested against it.
 pub(crate) fn builtin_storage_schemes(access_mode: AccessMode) -> &'static 
[&'static str] {
     match access_mode {
-        AccessMode::Read => &["file", "gs", "oss", "s3", "s3a"],
+        AccessMode::Read => &["file", "gs", "hdfs", "oss", "s3", "s3a"],

Review Comment:
   [P2] Check filesystem consistency before admitting HDFS files. A 
Hadoop-catalog table can have local metadata and 
`write.data.path=hdfs://nn:8020/warehouse/data`. This allowlist change makes 
that scan eligible, but `IcebergScanExec` still selects its single FileIO 
backend from `metadata_location`, choosing `Fs`. Reading the HDFS file then 
attempts a local `dfs:/nn:8020/...` path and fails. Previously the HDFS scheme 
triggered JVM fallback, whose HadoopFileIO resolves each file’s filesystem. 
Please decline these combinations until the native FileIO can route every 
data/delete location correctly.
   
   Evidence: The new planner tests explicitly claim scans with local catalog 
metadata and HDFS data paths. Traced `IcebergScanExec` through 
`load_file_io(metadata_location)` and `storage_factory_for`. A reproduction 
using the exact head dependency and OpenDAL 0.58.2 calls an Fs-backed FileIO 
with `hdfs://nn:8020/warehouse/data.parquet` and receives `NotFound`, `service: 
fs`, `path: dfs:/nn:8020/warehouse/data.parquet`. Iceberg Java’s 
`HadoopInputFile.fromLocation` resolves `FileSystem` from each supplied 
location. No live HDFS connection was needed to demonstrate the incorrect 
dispatch.



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