apatrida commented on issue #1439:
URL: https://github.com/apache/arrow-java/issues/1439#issuecomment-6586551115

   ### Where it happens
   
   
[`AvaticaParameterBinder`](https://github.com/apache/arrow-java/blob/b410fb26d01c7cefc4c6e3443a53562164001371/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/AvaticaParameterBinder.java#L71-L108)
 creates the parameter `VectorSchemaRoot` and fills it one value at a time. It 
hands the root to `preparedStatement.setParameters()` only after every value 
succeeds. If a value throws, nothing owns the root and nothing closes it. 
Closing the root before rethrowing would fix it. We have no patch.
   
   ### Reproducer
   
   `localBinder()` in 
[`FlightFailureProbe.java`](https://github.com/brikk/brikk-sql/blob/7e0db9a/tools/datafusion-reference/FlightFailureProbe.java)
 reproduces it without a server. A regression test could bind a valid value 
then a failing one (NULL into a non-nullable field, or a wrong type), repeat 
it, and assert the allocator is empty afterwards.
   
   <details>
   <summary>Server-free reproducer (Java)</summary>
   
   Tested with the classes shaded inside `flight-sql-jdbc-driver-19.0.0.jar`; 
imports are shown unshaded. No server or connection is needed.
   
   ```java
   static void failedBindLeaks() {
       var allocator = new RootAllocator();
       Schema schema = new Schema(List.of(
           new Field("text", FieldType.notNullable(new ArrowType.Utf8()), null),
           new Field("number", FieldType.notNullable(new ArrowType.Int(64, 
true)), null)));
       var stub = new ArrowFlightSqlClientHandler.PreparedStatement() {
           VectorSchemaRoot owned;
           public FlightInfo executeQuery() { throw new 
UnsupportedOperationException(); }
           public long executeUpdate() { throw new 
UnsupportedOperationException(); }
           public Meta.StatementType getType() { return 
Meta.StatementType.SELECT; }
           public Schema getDataSetSchema() { return new Schema(List.of()); }
           public Schema getParameterSchema() { return schema; }
           public void setParameters(VectorSchemaRoot root) { owned = root; }
           public void close() { if (owned != null) owned.close(); }
       };
       try {
           new AvaticaParameterBinder(stub, allocator)
               
.bind(Arrays.asList(TypedValue.ofLocal(ColumnMetaData.Rep.STRING, "text"), 
null));
       } catch (UnsupportedOperationException e) {
           System.out.println("bind: " + e.getMessage()); // Can't set null on 
non-nullable parameter
       }
       stub.close();
       System.out.println("still allocated: " + 
allocator.getAllocatedMemory()); // 16388 in our run
       try {
           allocator.close();
       } catch (IllegalStateException e) {
           System.out.println("close: " + 
e.getMessage().lines().findFirst().orElse("")); // Memory was leaked
       }
   }
   ```
   
   </details>
   
   ### Related
   
   #156 tracks broader parameter-binding improvements, including NULL handling. 
This leak is a separate issue.
   
   The non-nullable parameter schema in the example comes from 
spiceai/spiceai#15950.
   


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