This is an automated email from the ASF dual-hosted git repository.
curth pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git
The following commit(s) were added to refs/heads/main by this push:
new 241477e92 feat(csharp/src/Drivers/Databricks): Remove redundant
CloseOperation for GetColumnsAsync (#3132)
241477e92 is described below
commit 241477e922b7c1ef32ff9618bb698f09b5059f20
Author: Todd Meng <[email protected]>
AuthorDate: Fri Jul 11 06:29:49 2025 -0700
feat(csharp/src/Drivers/Databricks): Remove redundant CloseOperation for
GetColumnsAsync (#3132)
[A previous PR](https://github.com/apache/arrow-adbc/pull/3093) fixed
redundant CloseOperations that were throwing errors and causing failure
for dbr 11.3 and below.
GetColumnsAsync uses a seperate response handling path, which does not
call GetQueryResults (where the previous fix was implemented), so this
operation still fails. This PR adds a fix
---
.../Drivers/Apache/Hive2/HiveServer2Statement.cs | 3 +
.../test/Drivers/Databricks/E2E/StatementTests.cs | 81 ++++++++++++++++++----
2 files changed, 70 insertions(+), 14 deletions(-)
diff --git a/csharp/src/Drivers/Apache/Hive2/HiveServer2Statement.cs
b/csharp/src/Drivers/Apache/Hive2/HiveServer2Statement.cs
index d25ae4fb1..3eebb5773 100644
--- a/csharp/src/Drivers/Apache/Hive2/HiveServer2Statement.cs
+++ b/csharp/src/Drivers/Apache/Hive2/HiveServer2Statement.cs
@@ -523,6 +523,9 @@ namespace Apache.Arrow.Adbc.Drivers.Apache.Hive2
cancellationToken);
OperationHandle = resp.OperationHandle;
+ // Set _directResults so that dispose logic can check if operation
was already closed
+ _directResults = resp.DirectResults;
+
// Common variables declared upfront
TGetResultSetMetadataResp metadata;
Schema schema;
diff --git a/csharp/test/Drivers/Databricks/E2E/StatementTests.cs
b/csharp/test/Drivers/Databricks/E2E/StatementTests.cs
index 3b67050d6..bc1e0e22a 100644
--- a/csharp/test/Drivers/Databricks/E2E/StatementTests.cs
+++ b/csharp/test/Drivers/Databricks/E2E/StatementTests.cs
@@ -133,25 +133,78 @@ namespace Apache.Arrow.Adbc.Tests.Drivers.Databricks
}
/// <summary>
- /// Verifies that Dispose() can be called on metadata query statements
without throwing
- /// "Invalid OperationHandle" errors. This tests the fix for the issue
where the server
- /// auto-closes operations but the client still tries to close them
during disposal.
+ /// Comprehensive test that verifies disposal works for all statement
types without throwing exceptions.
+ /// This prevents regressions like the GetColumns disposal bug where
_directResults wasn't set properly.
/// </summary>
- [SkippableFact]
- public async Task CanDisposeMetadataQueriesWithoutError()
+ [SkippableTheory]
+ [InlineData("ExecuteStatement", "SELECT 1 as test_column")]
+ [InlineData("GetCatalogs", "GetCatalogs")]
+ [InlineData("GetSchemas", "GetSchemas")]
+ [InlineData("GetTables", "GetTables")]
+ [InlineData("GetColumns", "GetColumns")]
+ [InlineData("GetPrimaryKeys", "GetPrimaryKeys")]
+ [InlineData("GetCrossReference", "GetCrossReference")]
+ [InlineData("GetColumnsExtended", "GetColumnsExtended")]
+ public async Task AllStatementTypesDisposeWithoutErrors(string
statementType, string sqlCommand)
{
- // Test a simple metadata command that's most likely to trigger
the issue
var statement = Connection.CreateStatement();
- statement.SetOption(ApacheParameters.IsMetadataCommand, "true");
- statement.SqlQuery = "GetSchemas";
- // Execute the metadata query
- QueryResult queryResult = await statement.ExecuteQueryAsync();
- Assert.NotNull(queryResult.Stream);
+ try
+ {
+ if (statementType == "ExecuteStatement")
+ {
+ // Regular SQL statement
+ statement.SqlQuery = sqlCommand;
+ }
+ else
+ {
+ // Metadata command
+ statement.SetOption(ApacheParameters.IsMetadataCommand,
"true");
+ statement.SqlQuery = sqlCommand;
+
+ // Set required parameters for specific metadata commands
+ if (sqlCommand is "GetColumns" or "GetPrimaryKeys" or
"GetCrossReference" or "GetColumnsExtended")
+ {
+ statement.SetOption(ApacheParameters.CatalogName,
TestConfiguration.Metadata.Catalog);
+ statement.SetOption(ApacheParameters.SchemaName,
TestConfiguration.Metadata.Schema);
+ statement.SetOption(ApacheParameters.TableName,
TestConfiguration.Metadata.Table);
+ }
+
+ if (sqlCommand == "GetCrossReference")
+ {
+ // GetCrossReference needs foreign table parameters too
+
statement.SetOption(ApacheParameters.ForeignCatalogName,
TestConfiguration.Metadata.Catalog);
+
statement.SetOption(ApacheParameters.ForeignSchemaName,
TestConfiguration.Metadata.Schema);
+ statement.SetOption(ApacheParameters.ForeignTableName,
TestConfiguration.Metadata.Table);
+ }
+ }
+
+ // Execute the statement
+ QueryResult queryResult = await statement.ExecuteQueryAsync();
+ Assert.NotNull(queryResult.Stream);
- // This should not throw "Invalid OperationHandle" errors
- // The fix ensures _directResults is set so dispose logic works
correctly
- statement.Dispose();
+ // Consume at least one batch to ensure the operation completes
+ var batch = await
queryResult.Stream.ReadNextRecordBatchAsync();
+ // Note: batch might be null for empty results, that's OK
+
+ // The critical test: disposal should not throw any exceptions
+ // This specifically tests the fix for the GetColumns bug
where _directResults wasn't set
+ var exception = Record.Exception(() => statement.Dispose());
+ Assert.Null(exception);
+ }
+ catch (Exception ex)
+ {
+ // If execution fails, we still want to test disposal
+ OutputHelper?.WriteLine($"Statement execution failed for
{statementType}: {ex.Message}");
+
+ // Even if execution failed, disposal should not throw
+ var disposalException = Record.Exception(() =>
statement.Dispose());
+ Assert.Null(disposalException);
+
+ // Re-throw the original exception if we want to investigate
execution failures
+ // For now, we'll skip the test if execution fails since
disposal is our main concern
+ Skip.If(true, $"Skipping disposal test for {statementType} due
to execution failure: {ex.Message}");
+ }
}
[SkippableFact]