parthchandra commented on PR #4633:
URL: 
https://github.com/apache/datafusion-comet/pull/4633#issuecomment-4940130267

   @wirybeaver thank you for this contribution and sorry for not getting to 
this sooner. The general direction we are now recommending for Comet data 
sources is to add them in a contrib directory until they are mature and/or have 
regular maintainers  who can maintain them.
   To that end, @schenksj 's PR #4700 merged an SPI (`CometScanWithPlanData` 
trait + `ServiceLoader`-based `PlanDataInjector` discovery + generalized 
`foreachUntilCometInput` / `findAllPlanData`) specifically so that contribs 
like this one don't need to touch core. This PR predates that merge so it still 
wires Lance in the old way
    
    — below are the concrete changes to adopt the SPI, significantly shrinking 
the core footprint.
    
     ---
   
     #### 1. Delete `CometLanceNativeScanLike` — use `CometScanWithPlanData` 
instead
   
     `CometLanceNativeScanLike` duplicates what the now-merged 
`CometScanWithPlanData` trait already provides (`sourceKey`, `commonData`, 
`perPartitionData`, plus optional `dynamicPruningFilters` / 
`withDynamicPruningFilters`).
   
     In `CometLanceNativeScanExec` (contrib), change:
   
     ```scala
     // Before
     extends CometLeafExec with CometLanceNativeScanLike
   
     // After
     extends CometLeafExec with CometScanWithPlanData
   ```
   
     Delete CometLanceNativeScanLike.scala from core entirely.
   
     This single change makes the operators.scala modifications unnecessary:
     - `foreachUntilCometInput` now matches case _: `CometLeafExec` as its 
first arm — any `CometLeafExec` is recognized as an input boundary so no 
enumeration entry is needed.
     - `findAllPlanData` has a generic arm `case s: CometLeafExec with 
CometScanWithPlanData => ...` that calls `ensureSubqueriesResolved()` and 
collects data keyed by sourceKey and no Lance-specific case is needed.
     
     Delete both the `_: CometLanceNativeScanLike` and `case lance: 
CometLanceNativeScanLike` additions from operators.scala.
   
     ---
    #### 2. Move `LancePlanDataInjector` to contrib via `ServiceLoader`
     
     The merged SPI discovers contrib `PlanDataInjectors` via 
`java.util.ServiceLoader`. Instead of adding `LancePlanDataInjector` to the 
hardcoded injectors list in core:
   
     1. Move `LancePlanDataInjector` into `spark/src/contrib-lance/scala/...` 
(make it a class, not an `object`, so `ServiceLoader` can instantiate it via 
no-arg ctor).
     2. Add a service file at 
`spark/src/contrib-lance/resources/META-INF/services/org.apache.spark.sql.comet.PlanDataInjector`
 containing:
     org.apache.comet.lance.LancePlanDataInjector
     3. Remove the `LancePlanDataInjector` definition and registry entry from 
`operators.scala`.
   
     ---
     #### 3. Move `LanceIntegration` + `CometScanRule` hook to contrib
     
     `spark/src/main/scala/org/apache/comet/lance/LanceIntegration.scala` is a 
reflection bridge in core. The pattern established by the Delta SPI is: core 
does not reference contrib, not even reflectively.
   
     Recommended approach:
     - Keep `COMET_LANCE_NATIVE_ENABLED` in `CometConf.scala` (config entries 
in core are fine — Iceberg does this too).
     - Move scan detection (`isLanceScan`, `nativeScanPlan`, 
`tryCreateNativeScan`) into `contrib`, e.g. 
`org.apache.comet.lance.LanceScanRuleExtension`.
     - For the `CometScanRule` hook: define a tiny trait `CometScanContrib { 
def tryTransform(scanExec: BatchScanExec): Option[SparkPlan] }` in core, 
discover implementations via `ServiceLoader` in `CometScanRule` at the case 
`scanExec: BatchScanExec =>` match before the Iceberg arm, and let contrib
     provide the implementation. This way core gets a ~3-line generic dispatch, 
not a Lance-specific case.
     
     Delete `LanceIntegration.scala` from core and the 
`LanceIntegration.isLanceScan / tryCreateNativeScan` case from 
`CometScanRule.scala`.
   
     ---
   ####  4. What remains in core after these changes
   
     | File | What stays |
     |------|-----------|
     | `CometConf.scala` | `COMET_LANCE_NATIVE_ENABLED` config entry |
     | `operator.proto` | `LanceScan`, `LanceScanCommon`, `LanceScanPartition` 
messages + `lance_scan = 118` |
     | `planner.rs` | `OpStruct::LanceScan` arm with `#[cfg(feature = 
"contrib-lance")]` gate |
     | `operators/lance_scan.rs` | Rust `LanceScanExec` behind `#[cfg(feature = 
"contrib-lance")]` |
     | `operators/mod.rs` | Feature-gated `mod lance_scan` + `pub use` |
     | `operator_registry.rs` | `LanceScan` variant in the enum |
     | `jni_api.rs` | `OpStruct::LanceScan(_) => "LanceScan"` name |
     | `pom.xml` / `spark/pom.xml` | `contrib-lance` profile + source dir 
wiring |
   
     Everything else (`LanceIntegration.scala`, 
`CometLanceNativeScanLike.scala`, `LancePlanDataInjector`, the 
`operators.scala` modifications to `foreachUntilCometInput / findAllPlanData`, 
the Lance case in `CometScanRule`) moves to `spark/src/contrib-lance/`.
   
     ---
    #### 5. MSRV bump
     
     The PR bumps rust-version from 1.88 to 1.92 for the entire workspace. If 
the Lance crate requires 1.92, gate it behind the feature flag or pin a lance 
rev that compiles on 1.88. 
   
     ---
     The net/desired result: a default build (no `-Pcontrib-lance`) that sees 
only the config entry and proto message on the Scala side, plus 
feature-gated-dead Rust code — identical to the Delta SPI pattern.
     ```
   
   


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