From defd15d92b9e90b2320ec64313e9fa4a3863c373 Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Tue, 5 May 2026 21:11:00 -0700 Subject: [PATCH 1/3] fix(csharp): set BUFFER_LENGTH to null in FlatColumnsResultBuilder; re-enable CanGetColumnsExtended for SEA (PECO-3008) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JDBC spec defines BUFFER_LENGTH as unused — it should always be null. FlatColumnsResultBuilder was computing non-null values for numeric types (INT=4, BIGINT=8, etc.) via ColumnMetadataHelper.GetBufferLength, causing CanGetColumnsExtended to fail for the SEA three-calls fallback path while Thrift (which reads directly from the server and returns null) passed. CreateExtendedColumnsResult (DESC TABLE EXTENDED path) already returned null unconditionally; this change makes FlatColumnsResultBuilder consistent. Removes the Skip.If(Protocol == "rest") guard from CanGetColumnsExtended. Co-Authored-By: Claude Sonnet 4.6 --- csharp/src/FlatColumnsResultBuilder.cs | 3 +-- csharp/test/E2E/StatementTests.cs | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/csharp/src/FlatColumnsResultBuilder.cs b/csharp/src/FlatColumnsResultBuilder.cs index 30ae73e03..79befb1bb 100644 --- a/csharp/src/FlatColumnsResultBuilder.cs +++ b/csharp/src/FlatColumnsResultBuilder.cs @@ -71,8 +71,7 @@ internal static QueryResult BuildFlatColumnsResult( if (info.Precision[i].HasValue) columnSizeBuilder.Append(info.Precision[i]!.Value); else columnSizeBuilder.AppendNull(); - int? bufLen = ColumnMetadataHelper.GetBufferLength(info.TypeName[i]); - if (bufLen.HasValue) bufferLengthBuilder.Append(bufLen.Value); else bufferLengthBuilder.AppendNull(); + bufferLengthBuilder.AppendNull(); // JDBC spec: BUFFER_LENGTH is unused, always null if (info.Scale[i].HasValue) decimalDigitsBuilder.Append(info.Scale[i]!.Value); else decimalDigitsBuilder.AppendNull(); diff --git a/csharp/test/E2E/StatementTests.cs b/csharp/test/E2E/StatementTests.cs index be3f28e44..17a6d92f5 100644 --- a/csharp/test/E2E/StatementTests.cs +++ b/csharp/test/E2E/StatementTests.cs @@ -476,13 +476,11 @@ public async Task CanGetColumnsWithBaseTypeName() Assert.Equal(TestConfiguration.Metadata.ExpectedColumnCount, actualBatchLength); } - // TODO: PECO-3008 - CanGetColumnsExtended fails for SEA; investigate catalog/schema metadata path in StatementExecutionConnection [SkippableTheory] [InlineData("all_column_types", "Resources/create_table_all_types.sql", "Resources/result_get_column_extended_all_types.json", true, new[] { "PK_IS_NULLABLE:NO" })] [InlineData("all_column_types", "Resources/create_table_all_types.sql", "Resources/result_get_column_extended_all_types.json", false, new[] { "PK_IS_NULLABLE:YES" })] public async Task CanGetColumnsExtended(string tableName, string createTableSqlLocation, string resultLocation, bool useDescTableExtended, string[]? extraPlaceholdsInResult = null) { - Skip.If(TestConfiguration.Protocol == "rest", "SEA CanGetColumnsExtended returns different BUFFER_LENGTH values (PECO-3008)"); var connectionParams = new Dictionary { ["adbc.databricks.use_desc_table_extended"] = $"{useDescTableExtended}" }; using AdbcConnection connection = NewConnection(TestConfiguration, connectionParams); From 699cebe78bed4f9a39a205328c37ddedc7e00371 Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Mon, 1 Jun 2026 00:00:51 -0700 Subject: [PATCH 2/3] docs(csharp): clarify why BUFFER_LENGTH is null in the getColumns result MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUFFER_LENGTH is a JDBC-compatibility column (ADBC's xdbc_buffer_length) defined as "not used", so it is consistently null across all paths — server-driven on Thrift and client-built on SEA. Reword the comment to reflect the ADBC/JDBC-compat framing rather than just "JDBC spec". Co-authored-by: Isaac --- csharp/src/FlatColumnsResultBuilder.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/csharp/src/FlatColumnsResultBuilder.cs b/csharp/src/FlatColumnsResultBuilder.cs index 79befb1bb..46e27467e 100644 --- a/csharp/src/FlatColumnsResultBuilder.cs +++ b/csharp/src/FlatColumnsResultBuilder.cs @@ -71,7 +71,11 @@ internal static QueryResult BuildFlatColumnsResult( if (info.Precision[i].HasValue) columnSizeBuilder.Append(info.Precision[i]!.Value); else columnSizeBuilder.AppendNull(); - bufferLengthBuilder.AppendNull(); // JDBC spec: BUFFER_LENGTH is unused, always null + // BUFFER_LENGTH is a JDBC-compatibility column in the getColumns metadata result + // (ADBC surfaces the same value as xdbc_buffer_length). It is defined as "not used" + // by the JDBC contract, so no driver populates it — always null here, matching the + // Thrift path (server leaves it unset) and the SEA DESC TABLE EXTENDED path. + bufferLengthBuilder.AppendNull(); if (info.Scale[i].HasValue) decimalDigitsBuilder.Append(info.Scale[i]!.Value); else decimalDigitsBuilder.AppendNull(); From 9ab8529c75c223b789fa72e77762996121bacc81 Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Mon, 1 Jun 2026 00:09:13 -0700 Subject: [PATCH 3/3] docs(csharp): explain BUFFER_LENGTH null as an ODBC carryover unused by managed/Arrow APIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expand the comment: BUFFER_LENGTH is ODBC's SQLColumns buffer-allocation hint (bytes to bind/fetch a column into a caller-owned C buffer). Managed APIs that own their buffers don't need it — JDBC marks it "not used", and ADBC even less so since Arrow results are self-describing (buffer sizes come from the type + data). Hence always null, on all paths. Co-authored-by: Isaac --- csharp/src/FlatColumnsResultBuilder.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/csharp/src/FlatColumnsResultBuilder.cs b/csharp/src/FlatColumnsResultBuilder.cs index 46e27467e..b412dc84c 100644 --- a/csharp/src/FlatColumnsResultBuilder.cs +++ b/csharp/src/FlatColumnsResultBuilder.cs @@ -71,10 +71,13 @@ internal static QueryResult BuildFlatColumnsResult( if (info.Precision[i].HasValue) columnSizeBuilder.Append(info.Precision[i]!.Value); else columnSizeBuilder.AppendNull(); - // BUFFER_LENGTH is a JDBC-compatibility column in the getColumns metadata result - // (ADBC surfaces the same value as xdbc_buffer_length). It is defined as "not used" - // by the JDBC contract, so no driver populates it — always null here, matching the - // Thrift path (server leaves it unset) and the SEA DESC TABLE EXTENDED path. + // BUFFER_LENGTH is an ODBC carryover (SQLColumns col 8): the byte size an ODBC + // application would allocate to bind/fetch the column into its own C buffer. + // Managed APIs that own their buffers have no use for it, so JDBC marks it + // "not used" — and ADBC even less so, since results are self-describing Arrow + // (buffer sizes come from the column's type + data, not from a metadata field). + // Always null here, matching the Thrift path and the SEA DESC TABLE EXTENDED path. + // (ADBC surfaces the same field as xdbc_buffer_length.) bufferLengthBuilder.AppendNull(); if (info.Scale[i].HasValue) decimalDigitsBuilder.Append(info.Scale[i]!.Value); else decimalDigitsBuilder.AppendNull();