Skip to content

fix(csharp): metadata(csharp): empty-string catalog/schema/table arg throws HiveServer2Exception on Thrift, returns on SEA (#524)#577

Open
peco-engineer-bot[bot] wants to merge 6 commits into
mainfrom
ai/bugfix-524
Open

fix(csharp): metadata(csharp): empty-string catalog/schema/table arg throws HiveServer2Exception on Thrift, returns on SEA (#524)#577
peco-engineer-bot[bot] wants to merge 6 commits into
mainfrom
ai/bugfix-524

Conversation

@peco-engineer-bot

Copy link
Copy Markdown
Contributor

Summary

Automated fix for #524 — metadata(csharp): empty-string catalog/schema/table arg throws HiveServer2Exception on Thrift, returns on SEA.

Added MetadataUtilities.HasEmptyStringIdentifier and short-circuited each Thrift metadata override (GetTables/GetColumns/GetPrimaryKeys/GetCrossReference/GetCrossReferenceAsForeignTable) in DatabricksStatement.cs to return an empty result set when any identifier arg is an empty string, before calling the base HiveServer2 RPC — matching SEA so empty-string args no longer throw HiveServer2Exception. All 8 E2E tests pass against the live endpoint (0 failed, 8 passed).

Files changed

  • csharp/test/E2E/StatementExecution/SeaMetadataE2ETests.cs
  • csharp/src/MetadataUtilities.cs
  • csharp/src/DatabricksStatement.cs
  • .claude/knowledge/learning.md

Test plan

  • AdbcDrivers.Databricks.Tests.E2E.StatementExecution.EmptyStringMetadataArgE2ETest.GetColumns_EmptyCatalog_ReturnsEmptyWithoutThrowing — fails (red) against the original code, passes (green) after the fix
  • AdbcDrivers.Databricks.Tests.E2E.StatementExecution.EmptyStringMetadataArgE2ETest.GetColumns_EmptySchema_ReturnsEmptyWithoutThrowing — fails (red) against the original code, passes (green) after the fix
  • AdbcDrivers.Databricks.Tests.E2E.StatementExecution.EmptyStringMetadataArgE2ETest.GetTables_EmptyCatalog_ReturnsEmptyWithoutThrowing — fails (red) against the original code, passes (green) after the fix
  • AdbcDrivers.Databricks.Tests.E2E.StatementExecution.EmptyStringMetadataArgE2ETest.GetTables_EmptySchema_ReturnsEmptyWithoutThrowing — fails (red) against the original code, passes (green) after the fix
  • AdbcDrivers.Databricks.Tests.E2E.StatementExecution.EmptyStringMetadataArgE2ETest.GetPrimaryKeys_EmptySchema_ReturnsEmptyWithoutThrowing — fails (red) against the original code, passes (green) after the fix
  • AdbcDrivers.Databricks.Tests.E2E.StatementExecution.EmptyStringMetadataArgE2ETest.GetPrimaryKeys_EmptyTable_ReturnsEmptyWithoutThrowing — fails (red) against the original code, passes (green) after the fix
  • AdbcDrivers.Databricks.Tests.E2E.StatementExecution.EmptyStringMetadataArgE2ETest.GetCrossReference_EmptyForeignSchema_ReturnsEmptyWithoutThrowing — fails (red) against the original code, passes (green) after the fix
  • AdbcDrivers.Databricks.Tests.E2E.StatementExecution.EmptyStringMetadataArgE2ETest.GetCrossReference_EmptyForeignTable_ReturnsEmptyWithoutThrowing — fails (red) against the original code, passes (green) after the fix

Fixes #524

🤖 Generated by engineer-bot (bug-fix flow)

@peco-engineer-bot peco-engineer-bot Bot added engineer-bot engineer-bot may fix this issue / take over this PR review-bot reviewer-bot reviews this PR labels Jul 8, 2026

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 1 Low

Looks good — a focused, correct parity fix. HasEmptyStringIdentifier properly treats null as "no filter" and only short-circuits on non-null zero-length strings, and the guards are placed before each base RPC across the five overrides. Two low-severity notes: the GetColumns guard also checks ColumnName (beyond issue scope, unverified against SEA), and the sibling GetColumnsExtendedAsync override was left unguarded despite the "uniform" claim in the knowledge log.

Comment thread csharp/src/DatabricksStatement.cs Outdated
Addresses:
  - #3543375469 at csharp/src/DatabricksStatement.cs:869

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 1 Low

Looks good — a small, well-contained parity fix. The HasEmptyStringIdentifier helper correctly treats only non-null zero-length strings as empty (null passes through as "no filter"), and each Thrift metadata override short-circuits to the same empty-result helpers already used elsewhere, before the base RPC that would throw. One Low note on CI-runnable unit coverage for the new pure helper.

Comment thread csharp/src/MetadataUtilities.cs
Addresses:
  - #3543448305 at csharp/src/MetadataUtilities.cs:44

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 1 Low

Looks good — a clean, conservative parity fix. Empty-string identifier args now short-circuit to an empty result before hitting the Thrift RPC, matching SEA; the HasEmptyStringIdentifier helper (null = no filter, only zero-length triggers) is correct and well unit-tested, and the guards are placed before HandleSparkCatalog so empty catalog is caught. One low note: the GetCrossReferenceAsForeignTable guard lacks a dedicated E2E test.

Comment thread csharp/test/E2E/StatementExecution/SeaMetadataE2ETests.cs
Addresses:
  - #3543504258 at csharp/test/E2E/StatementExecution/SeaMetadataE2ETests.cs:492

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 1 Medium

Solid, well-tested fix — the new HasEmptyStringIdentifier guard correctly short-circuits GetTables/GetColumns/GetPrimaryKeys/GetCrossReference(+ AsForeignTable) before the base RPC, and the null-vs-empty distinction is right. One medium parity gap: GetColumnsExtendedAsync's primary DESC path is unguarded, so empty catalog/schema still return real columns instead of empty (only empty-table is covered via the base fallback).

Comment thread csharp/src/DatabricksStatement.cs
Addresses:
  - #3543665730 at csharp/src/DatabricksStatement.cs:1047

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 1 Low

Solid, well-tested parity fix — HasEmptyStringIdentifier correctly treats only non-null zero-length strings as empty (null passes through), and the guards run before the base HiveServer2 RPCs that would throw. One low-severity note: the GetColumnsExtendedAsync guard is outside the scope described in the PR/learning.md and may introduce a Thrift↔SEA divergence for empty catalog/schema rather than remove one — worth confirming SEA's GetColumnsExtended returns empty for the same inputs. The five repeated guard blocks are near-identical boilerplate (nit — could be a small helper, not blocking).

Comment thread csharp/src/DatabricksStatement.cs
Addresses:
  - #3543721922 at csharp/src/DatabricksStatement.cs:1091

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 1 Low

Looks good — solid, well-tested parity fix. The new HasEmptyStringIdentifier helper is correct (non-null zero-length only; null passes through as "no filter"), and each guard returns an empty result whose schema matches the method's existing empty path. One low note: the GetColumnsExtended guard turns a previously-succeeding empty-catalog/empty-schema call into an empty result (a deliberate parity change with GetColumnsAsync, not an exception fix) — worth confirming that contract. Minor observation not worth a separate finding: GetSchemasAsync is the one metadata override left unguarded, which is consistent with issue #524's reported outcome diffs (list_schemas was not among them), so likely intentional.

// On the primary DESC TABLE EXTENDED path, BuildTableName drops an empty catalog/schema, so
// an empty catalog or schema would otherwise produce a valid identifier and return real rows,
// diverging from GetColumnsAsync. Guard here so both column APIs behave identically.
if (MetadataUtilities.HasEmptyStringIdentifier(CatalogName, SchemaName, TableName))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Low — This guard changes GetColumnsExtended behavior for the empty-catalog / empty-schema cases (with a non-empty table) from returning real rows to returning an empty result. Unlike GetTables/GetPrimaryKeys/GetCrossReference — where issue #524's actual defect was a thrown HiveServer2Exception — the DESC TABLE EXTENDED path did not throw here: BuildTableName() drops an empty catalog/schema and would resolve `schema`.`table` (or the default namespace) and return columns. The PR (correctly) makes this match GetColumnsAsync, which already returns empty for these args, so this is a deliberate parity change rather than a pure exception fix. Flagging only so a reviewer confirms the intent: callers that previously passed catalog="" expecting "use current catalog" resolution will now silently get zero rows. The change is documented in the inline comment and covered by tests, so no code change is required if the parity semantics are the desired contract.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NEEDS HUMAN DECISION — the bots can't resolve this thread; a maintainer's input is required.

This thread asks a human reviewer to confirm that the empty-string→empty-result parity semantics (matching GetColumnsAsync / SEA) are the intended public contract for GetColumnsExtended, accepting that catalog=""/schema="" with a non-empty table no longer resolves to the current namespace but returns zero rows. The code is intentional, documented inline, and test-covered, so there is nothing to change here; the remaining decision is a semantic-contract judgment (is "empty string means no filter → empty result" the desired behavior, vs. "empty string means use current catalog") that needs human sign-off rather than further bot discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

engineer-bot engineer-bot may fix this issue / take over this PR review-bot reviewer-bot reviews this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

metadata(csharp): empty-string catalog/schema/table arg throws HiveServer2Exception on Thrift, returns on SEA

0 participants