andygrove opened a new issue, #1423:
URL: https://github.com/apache/arrow-java/issues/1423

   ### Describe the enhancement requested
   
   `Data.importField` (and therefore `Data.importVector` / 
`Data.importIntoVector`) creates a new `SchemaImporter` on every call:
   
   ```java
   public static Field importField(BufferAllocator allocator, ArrowSchema 
schema,
       CDataDictionaryProvider provider, boolean closeImportedStructs) {
     try {
       SchemaImporter importer = new SchemaImporter(allocator);
       return importer.importField(schema, provider);
     } ...
   ```
   
   `SchemaImporter` owns the dictionary id counter (`private long 
nextDictionaryID = 0L`), so every top-level `importField` call starts numbering 
dictionaries from 0. When a caller imports several columns one at a time (one 
`ArrowArray`/`ArrowSchema` pair per column) into the same 
`CDataDictionaryProvider`, the second dictionary-encoded column gets 
`DictionaryEncoding` id 0 again. `CDataDictionaryProvider.put` then replaces 
the first column's dictionary and closes its vector:
   
   ```java
   void put(Dictionary dictionary) {
     Dictionary previous = map.put(dictionary.getEncoding().getId(), 
dictionary);
     if (previous != null) {
       previous.getVector().close();
     }
   }
   ```
   
   The first column's indices now resolve against the wrong dictionary (or a 
closed one), which corrupts data silently.
   
   Importing the columns as a single struct via `Data.importSchema` / 
`Data.importVectorSchemaRoot` avoids this because one `SchemaImporter` handles 
all children, but that is not always an option. In Apache DataFusion Comet, the 
native side exports each column separately, so Comet had to work around this by 
shipping its own `ArrowImporter` class in the `org.apache.arrow.c` package 
(https://github.com/apache/datafusion-comet/blob/main/spark/src/main/java/org/apache/arrow/c/ArrowImporter.java).
 It holds one `SchemaImporter` for the lifetime of a batch so dictionary ids 
stay unique across columns. It has to live in `org.apache.arrow.c` because 
`SchemaImporter` and `ArrayImporter` are package-private.
   
   ### Proposal
   
   Expose a public API that lets a caller import multiple fields/arrays with 
shared dictionary id state, for example one of:
   
   1. Make `SchemaImporter` (or a new wrapper around it) public so a caller can 
construct one and call `importField` repeatedly, with the dictionary counter 
carried across calls.
   2. Add overloads of `Data.importField` / `Data.importVector` that accept a 
reusable importer or an explicit starting dictionary id.
   3. Have `Data.importField` derive the dictionary id from the ids already 
present in the supplied `CDataDictionaryProvider` (e.g. `max(existing ids) + 
1`) instead of a fresh counter, so repeated calls against the same provider 
never collide.
   
   Option 3 is the least invasive and fixes existing callers without an API 
change, though it changes the ids that get assigned. Option 1 or 2 would let 
Comet delete its copy of the importer and stop depending on package-private 
classes.
   
   Happy to put up a PR if there is agreement on the approach.
   


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