Skip to content

fix(csharp): align SEA metadata error behavior with Thrift - #604

Merged
eric-wang-1990 merged 30 commits into
mainfrom
fix/revert-388-sea-object-not-found
Aug 3, 2026
Merged

fix(csharp): align SEA metadata error behavior with Thrift#604
eric-wang-1990 merged 30 commits into
mainfrom
fix/revert-388-sea-object-not-found

Conversation

@eric-wang-1990

@eric-wang-1990 eric-wang-1990 commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

Aligns SEA metadata behavior with the Thrift path so the Thrift-vs-SEA behavioral comparator converges. Policy: SEA must match Thrift on the ADBC-observable contract — result rows, and on error the Status + SqlState (not the concrete exception subclass).

Note: despite the branch name, this PR keeps #388's object-not-found behavior. An earlier iteration reverted #388 on the assumption "Thrift throws on object-not-found"; that was disproven by live measurement (Thrift returns 0 rows on a genuine missing catalog/schema/table, same as #388 and JDBC), so the revert was itself reverted. See §1.

1. Object-not-found → empty result (keep #388, verified)

SEA metadata methods catch NO_SUCH_CATALOG / SCHEMA_NOT_FOUND / TABLE_OR_VIEW_NOT_FOUND / INVALID_PARAMETER_VALUE and return an empty result — matching both the Thrift path (measured: 0 rows on object-not-found) and the JDBC reference driver (isObjectNotFoundException). DatabricksException.IsObjectNotFoundException + a catch on both the flat metadata methods (GetSchemas/GetTables/GetColumns/GetColumnsExtended/GetPrimaryKeys/GetCrossReference) and the GetObjects nested-shape path (IGetObjectsDataProvider).

This also subsumes issue #593 (%-catalog + escape): all four explicit #593 pre-SHOW short-circuits are removed as redundant. On a real server the %-catalog case produces an object-not-found error the catch swallows to empty — verified live for both the SHOW paths (SHOW … IN \%` → SCHEMA_NOT_FOUND) and the DESC-TABLE-EXTENDED path (DESC TABLE EXTENDED `%`.… → TABLE_OR_VIEW_NOT_FOUND). (An earlier iteration kept the GetColumnsExtended short-circuit believing its empty-resultFormatExceptionescaped the catch — but thatFormatException` was a test-mock artifact; the real server throws TABLE_OR_VIEW_NOT_FOUND, which the catch handles. The mock was corrected to the realistic failure.)

2. Literal-backslash escaping in the SEA LIKE path (two layers)

Under escape_pattern_wildcards=true the input is a literal name. EscapePatternWildcardsInName escapes \/_/% (backslash first, no idempotency); new LikePattern doubles backslashes for the SQL string literal (the glob is embedded in '…'; the server's string-literal parser consumes one layer before the LIKE regex). ConvertPattern stays byte-identical to JDBC jdbcPatternToHive. Same under-escaping exists in JDBC — filed databricks-jdbc#1598.

3. Exact-match ops validate required args client-side

GetPrimaryKeys / GetCrossReference are exact-match; SEA now validates their required args client-side before issuing the SHOW, mirroring the JDBC reference driver's resolveKeyBasedParams:

  • table null/empty → throw 42000 "tableName may not be null" (matches Thrift's clean 42000).
  • catalog set + schema null → throw 42000 "schema may not be null when catalog is specified" (matches JDBC). This also avoids the Thrift server's internal GET_FUNCTIONS assertion failed bug (SQLSTATE 08000) on schema-null — SEA gives a clean, deterministic error instead.

(The guards run before the SHOW, so §1's object-not-found catch does not apply.)

4. Exception type: DatabricksException, comparator compares the ADBC contract

SEA throws its own DatabricksException (natural REST/SEA type) on FAILED, on both sync + async-polling paths. The comparator's CompareException is relaxed to compare Status + SqlState and require both sides be AdbcException — not the concrete subclass — avoiding the semantically-odd HiveServer2Exception-from-SEA (PECO-3014). The JDBC comparator already accepts subclass differences.

Known residual (Thrift-side bugs — SEA is correct, handled comparator-side)

Two comparator diffs remain where SEA behaves correctly (matching JDBC) and Thrift has a server-side bug; both are addressed on the comparator side, not by making SEA replicate a Thrift quirk:

  • Empty-string catalog (catalog=""): Thrift throws INVALID_PARAMETER_VALUE ("name '' is not a valid name"); SEA + JDBC return empty. → comparator fixture uses a nonexistent named catalog instead of "".
  • schema-null on exact-match ops (§3): SEA throws a clean 42000; Thrift throws its internal 08000 "assertion failed" → residual sqlstate diff. → whitelist/skip on the comparator with a reason (Thrift server bug).

Tests

  • All 946 unit tests pass. not-found tests assert empty result; backslash + PK/XREF null-table + schema-null validation + FAILED-path + async-polling guards included.
  • E2E StringValueTests.TestVarcharExceptionDataDatabricks skipped for SEA (shared base asserts exact HiveServer2Exception in the hiveserver2 submodule; parity covered by comparator). PECO-3014.

Companion change

Comparator relax + the ""→nonexistent fixture change land in databricks-driver-test.

This pull request and its description were written by Isaac.

… + escape fix)

The Thrift-vs-SEA comparator reported 1045 deterministic metadata "outcome"
divergences (one protocol throws while the other returns). Policy: SEA must match
Thrift, not JDBC. Two changes:

1. Revert #388's object-not-found swallowing (885 diffs). #388 added
   IsObjectNotFoundException() + catch blocks that made SEA return EMPTY on
   NO_SUCH_CATALOG / SCHEMA_NOT_FOUND / TABLE_OR_VIEW_NOT_FOUND, to match JDBC.
   Thrift THROWS on these, so under the match-Thrift policy SEA must throw too.
   Removed the helper and all ~11 catch sites so the exception propagates; the
   co-located IsDescTableExtendedUnsupportedException catch is preserved. The two
   test files #388 added were later also edited by #456/#525/#566 — surgically
   removed only the object-not-found swallow tests, kept the rest.

2. Fix double-escaping in EscapePatternWildcardsInName (160 diffs). With
   escape_pattern_wildcards=true, a caller-supplied ALREADY-escaped pattern
   (e.g. "test\_result\_set\_types") was re-escaped to "test\\_..." which
   ConvertPattern then turned into invalid SHOW-command glob syntax, and the SEA
   server rejected it with a DatabricksException — while Thrift returned rows.
   The escape now passes already-escaped \_ \% \\ through unchanged and only
   escapes bare _ / %. Raw inputs (foo_bar -> foo\_bar) are unaffected.

Added 4 unit tests (raw + pre-escaped underscore/percent, and the exact
comparator fixture). All 929 unit tests pass. Expected comparator effect:
1280 -> ~250 diffs (the 885 + 160 collapse to matches; ORDINAL_POSITION /
nullable / PK-presence divergences remain, tracked separately).

Co-authored-by: Isaac
@eric-wang-1990 eric-wang-1990 added the review-bot reviewer-bot reviews this PR label Jul 31, 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 Medium

Mostly a clean, well-tested revert + escape fix. EscapePatternWildcardsInName pass-through logic is correct (including \\\\, trailing-backslash, and pre-escaped \\_/\\% cases), and the new tests are reasonable. One Medium concern: removing the object-not-found catches may reintroduce the Issue #593 divergence for catalog="%" + escape_pattern_wildcards=true, where Thrift returns 0 rows but SEA will now throw SCHEMA_NOT_FOUND (see inline). Nit: the reworked comment above HttpClientCapturingStatements in the test file is garbled by the merge — it duplicates "body of every ExecuteStatement call into" and uses a <paramref> doc tag inside a plain // comment; worth tidying.

Comment thread csharp/src/StatementExecution/StatementExecutionStatement.cs Outdated

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

The double-escaping fix in EscapePatternWildcardsInName is correct and well-tested (verified against ConvertPattern). One HIGH concern: the wholesale removal of the IsObjectNotFoundException catches appears to re-open issue #593 — the knowledge log records that for catalog="%" with escape_pattern_wildcards=true, Thrift returns 0 rows and SEA parity depended on those now-removed catches mapping SCHEMA_NOT_FOUND to empty; SEA will now throw. Worth confirming against the comparator before merge.

Comment thread csharp/src/StatementExecution/StatementExecutionStatement.cs Outdated
Clarify for reviewers: the "leave already-escaped \_ unchanged" behavior matches
the JDBC reference (WildcardUtil.escapeCatalogName), and ConvertPattern itself is
byte-identical to JDBC's jdbcPatternToHive — so the fix belongs in the escape step
(which JDBC lacks and which double-processed the input), not in ConvertPattern.

Co-authored-by: Isaac

@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

Mostly a clean, well-tested revert + escape-idempotency fix; the EscapePatternWildcardsInName rewrite is correct (already-escaped \\_/\\%/\\\\ pass through, bare _/% escaped) and no dangling references to the removed helper remain. One medium concern: removing the object-not-found catches reintroduces the #593-documented divergence for the escape_pattern_wildcards=true + catalog="%" case, where the learning log says Thrift returns empty rows but SEA will now throw.

Comment thread csharp/src/StatementExecution/StatementExecutionStatement.cs Outdated
@eric-wang-1990 eric-wang-1990 removed the engineer-bot engineer-bot may fix this issue / take over this PR label Jul 31, 2026
…Exception; preserve #593)

Reworks the earlier blanket #388 revert, which regressed issue #593. A Thrift-vs-SEA
comparator showed metadata errors must match Thrift PER-CASE:

- Genuine object-not-found: Thrift throws HiveServer2Exception/InternalError(+SqlState).
  SEA now throws the SAME at the FAILED throw site (StatementExecutionClient), with
  SqlState + NativeError populated from the server error (parity with Thrift's
  ThrowErrorResponse). Previously threw DatabricksException/UnknownError/null.
- catalog="%"/"*" + escape_pattern_wildcards=true (#593): Thrift escapes %→\% → 0 rows
  (no throw). SEA now short-circuits GetSchemas/GetTables/GetColumns to an empty result
  BEFORE emitting the doomed `SHOW ... IN `%`` that 404s — so no SCHEMA_NOT_FOUND is
  raised. This replaces the removed #388 catch that #593 had relied on. escape=false
  still routes %→null→"ALL CATALOGS" (#525 untouched).

Also: relocate IsDescTableExtendedUnsupportedException to a static helper over
AdbcException so the DESC-TABLE-EXTENDED fallback catch works now that the metadata
exception type is HiveServer2Exception; keep the idempotent EscapePatternWildcardsInName
fix; un-skip PECO-3014 (StringValueTests) now that SEA throws HiveServer2Exception.

934 unit tests pass (5 new #593 short-circuit tests). Comparator re-validation pending.

Co-authored-by: Isaac

@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 change: reverting #388's object-not-found swallowing and fixing the double-escape are both correct for the match-Thrift policy, and the IsDescTableExtendedUnsupported catch was correctly widened to AdbcException so the new HiveServer2Exception FAILED type is still caught. One Low: the explanatory comment on the FAILED throw in StatementExecutionClient contradicts the actual (intended) control flow that the un-skipped StringValueTests relies on. Note (not blocking): the %+escape short-circuit was added only to GetSchemas/GetTables/GetColumns; GetPrimaryKeys/FetchCrossReference still go through the literal-% → SCHEMA_NOT_FOUND path and now propagate an exception post-revert — likely fine given the PR's acknowledged separately-tracked residuals, but worth confirming against Thrift for wildcard-catalog PK/FK inputs.

Comment thread csharp/src/StatementExecution/StatementExecutionClient.cs Outdated
@eric-wang-1990 eric-wang-1990 added engineer-bot engineer-bot may fix this issue / take over this PR and removed review-bot reviewer-bot reviews this PR labels Jul 31, 2026
…patterns

Two complementary layers were under-escaping backslashes so that a schema/
table/column whose name literally contains '\' could never be matched via the
SEA metadata path (SHOW ... LIKE), and escape_pattern_wildcards=true silently
dropped literal backslashes:

1. EscapePatternWildcardsInName (escape=true path): now escapes '\' -> '\\'
   in addition to '_' and '%'. Under escape=true the input is a LITERAL name,
   so a literal backslash must be escaped for the LIKE matcher. (Also removes
   the unsound "already-escaped" idempotency guess: under escape=true there are
   no escape sequences in the input to preserve.)

2. New LikePattern() helper (all SHOW ... LIKE builders): runs ConvertPattern
   (unchanged, still byte-identical to JDBC WildcardUtil.jdbcPatternToHive) then
   doubles backslashes for the SQL string literal. The glob is embedded in a
   single-quoted SQL string, so the server's string-literal parser consumes one
   backslash layer before the LIKE regex matcher sees it; without this a literal
   backslash collapses and is consumed as a regex escape.

Verified live (thrift vs rest) against schemas named a_b / a\b / a\_b / a\\b:
all escape=on literal-name lookups now return exactly the named schema on SEA.

The JDBC reference driver has the same under-escaping (it interpolates
jdbcPatternToHive output straight into LIKE '%s'); filed as a databricks-jdbc
issue. Thrift's separate server-side exact-match doubling bug is tracked
independently and is not addressed here.

Co-authored-by: Isaac

@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 High · 1 Low

The revert of #388 and the exception-type unification are coherent and well-tested. However the core escape fix is internally contradictory: EscapePatternWildcardsInName's code body implements full unconditional escaping (with an explicit "no idempotency" comment), while its own docstring and the four new pre-escaped unit tests require already-escaped sequences to pass through unchanged — under the shipped code, pre-escaped foo\\_bar emits LIKE 'foo\\\\\\\\_bar', not the asserted LIKE 'foo_bar' (F1, high). One inaccurate comment about the FAILED-throw path (F2, low).

Comment thread csharp/src/StatementExecution/StatementExecutionStatement.cs
Comment thread csharp/src/StatementExecution/StatementExecutionClient.cs Outdated
Addresses:
  - #3687197436 at csharp/src/StatementExecution/StatementExecutionStatement.cs:1035
  - #3688145746 at csharp/src/StatementExecution/StatementExecutionClient.cs:247
  - #3692682966 at csharp/src/StatementExecution/StatementExecutionStatement.cs:1091

Signed-off-by: peco-engineer-bot[bot] <peco-engineer-bot[bot]@users.noreply.github.com>

@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

Looks solid overall — the #388 revert, the EscapePatternWildcardsInName idempotency fix, the LikePattern backslash-doubling, and the %+escape short-circuits are all intentional, internally consistent, and covered by new unit tests; no dangling references to the removed IsObjectNotFoundException helper. One medium concern: the HiveServer2Exception parity is only partial (HTTP-error failures still throw DatabricksException), which also gates the newly un-skipped VARCHAR E2E assertion on unverified server behavior.

Comment thread csharp/src/StatementExecution/StatementExecutionClient.cs Outdated
…h Thrift

GetPrimaryKeys and GetCrossReference are JDBC exact-match operations: the table
(resp. foreign/parent table) is required. On the Thrift path, TGetPrimaryKeysReq
/ TGetCrossReferenceReq are rejected server-side with a HiveServer2Exception
(AdbcStatusCode.InternalError, SqlState 42000) when the table is null. SEA
previously returned an EMPTY result in that case, so the two protocols disagreed
on outcome (one throws, one returns) — a large bucket of comparator diffs.

SEA now throws the SAME exception (type + Status + SqlState — the comparator's
exception identity; the message is not compared) when:
  - GetPrimaryKeys: table is null/empty  -> "tableName may not be null"
  - GetCrossReference: BOTH foreign table and parent table are null/empty
    -> "foreignTable and parentTableName are both null"

Scope: only the null-TABLE case, which is a stable, well-defined Thrift
validation (verified live on thrift + rest). The catalog-only and schema-null
cases are left as-is — Thrift's errors there are environment-specific server
quirks (assertion failed / SCHEMA_NOT_FOUND naming the live catalog) that are
not cleanly reproducible. The PKFK-disabled early-return
(ShouldReturnEmptyPKFKResult) is preserved unchanged.

Adds unit tests asserting both throws (type + status + sqlstate). Full unit
suite (934) green.

Co-authored-by: Isaac
…rdsInName

The engineer-bot's review-thread fix (b634bf0) re-introduced the "already-
escaped" idempotency heuristic in EscapePatternWildcardsInName, which this
change had deliberately removed. Restoring the correct behavior with the
empirical justification the review thread lacked.

Under escape_pattern_wildcards=true the input is a LITERAL object name, so
there is no such thing as an "already-escaped" sequence to preserve: a '\' in
the input is a literal backslash and must itself be escaped ('\' -> '\\'),
along with '_' and '%'. The idempotency guess ("if I see \_ , assume the
caller pre-escaped it and pass it through") is unsound — it cannot distinguish
a caller-intended literal backslash from a pre-escape, and it silently drops
literal backslashes.

Verified live (thrift vs rest) against schemas named a\b / a\_b / a\\b: with
the idempotency heuristic, escape=true lookups matched the WRONG object (or
nothing); with full escaping (this change) every escape=true literal-name
lookup returns exactly the named schema. Works together with the LikePattern
SQL-string-literal escaping (Option B) added in the same PR.

See databricks-jdbc#1598 for the parallel JDBC issue.

Co-authored-by: Isaac

@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 parity change (revert of #388's object-not-found swallowing + fixing the escape path + switching the FAILED throw to HiveServer2Exception). The escape logic is internally consistent and the tests pin it correctly; I traced foo\\_barLIKE 'foo\\\\\\\\_bar' and it matches. One medium concern: the XML <summary> on EscapePatternWildcardsInName still documents the abandoned "pass already-escaped sequences through unchanged" approach and contradicts both the code and its own inline comment.

Comment thread csharp/src/StatementExecution/StatementExecutionStatement.cs Outdated
Addresses:
  - #3692682966 at csharp/src/StatementExecution/StatementExecutionStatement.cs:1091

Signed-off-by: peco-engineer-bot[bot] <peco-engineer-bot[bot]@users.noreply.github.com>

@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

Looks solid overall — the #388 revert, the escape-doubling fix, and the %-catalog short-circuits are internally consistent and well-covered by the pinned unit tests; exception API surfaces and DTOs all check out. One medium concern: the FAILED-state exception type is now split (sync path throws HiveServer2Exception with SqlState, but the async polling path still throws bare AdbcException), so Thrift exception-identity parity for metadata only holds when the response resolves synchronously.

Nit (no anchor needed): the doc comment on HttpClientCapturingStatements in csharp/test/Unit/StatementExecution/StatementExecutionMetadataObjectNotFoundTests.cs has a garbled merge — the fragment "body of every ExecuteStatement call into" is duplicated across two lines. Cosmetic only.

Comment thread csharp/src/StatementExecution/StatementExecutionClient.cs
Addresses:
  - #3693651576 at csharp/src/StatementExecution/StatementExecutionClient.cs:266

Signed-off-by: peco-engineer-bot[bot] <peco-engineer-bot[bot]@users.noreply.github.com>

@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-documented change: reverts #388's object-not-found swallowing and fixes the escape logic, with the exception-type change (DatabricksException → HiveServer2Exception) correctly guarded by InternalsVisibleTo and not breaking any remaining catch sites (all downstream catches are on the AdbcException base). One medium concern: the HTTP-error failure path still throws DatabricksException with a null SqlState, which under the PR's match-Thrift exception-identity policy could leave a residual divergence if object-not-found ever surfaces as an HTTP status error rather than a FAILED state. Minor: the deleted tests removed the empty-result schema-shape assertions (JDBC field names / KEQ_SEQ) — that guard is now only implicitly covered.

Comment thread csharp/src/StatementExecution/StatementExecutionClient.cs Outdated
@eric-wang-1990 eric-wang-1990 added the integration-test Trigger integration tests in internal repo label Aug 1, 2026
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🚀 Integration tests triggered! View workflow run

…) for metadata errors

Reverts the cross-protocol exception-TYPE unification from earlier in this PR.
SEA now throws its own DatabricksException — the natural type for the REST/SEA
path — rather than constructing a HiveServer2Exception (a Thrift/HiveServer2
type) via InternalsVisibleTo, which was semantically odd for a path that never
touches HiveServer2 (the concern tracked by PECO-3014).

Parity with the Thrift path is preserved on the comparator side instead: the
comparator's CompareException is being relaxed to treat any AdbcException
subclass as equivalent and compare Status + SqlState (the ADBC contract that
consumers actually branch on), rather than requiring an identical concrete
class. Both throw sites keep the same Status (InternalError) + SqlState, so
behavioral parity is unchanged; only the concrete type differs, which is an
implementation detail.

Affected:
- StatementExecutionClient.cs: FAILED-state throw -> DatabricksException
- StatementExecutionStatement.cs: NewInvalidArgumentException (PK/XREF null
  guard) -> DatabricksException
- unit tests assert DatabricksException + Status + SqlState (unchanged
  load-bearing identity)

The IsDescTableExtendedUnsupported(AdbcException) static helper stays (accepts
the base type; works for either subclass).

Co-authored-by: Isaac

Also aligns NewFailedStateException (async FAILED polling path, added by the
review-thread follow-up) to DatabricksException for the same reason.
@github-actions github-actions Bot removed the integration-test Trigger integration tests in internal repo label Aug 1, 2026
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🔒 Integration test approval reset

New commits were pushed to this PR. The integration-test label has been automatically removed for security.

A maintainer must re-review the changes and re-add the label to trigger tests again.

Why is this necessary?
  • New code requires fresh security review
  • Prevents approved PRs from adding malicious code later
  • Ensures all tested code has been explicitly approved

Latest commit: 2751020

@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 High · 1 Low

Mostly sound revert + escape fix, but one high-severity inconsistency: the StringValueTests skip was removed with a comment claiming SEA now throws HiveServer2Exception, yet StatementExecutionClient still throws DatabricksException (a sibling type, not a HiveServer2Exception), so the SEA/rest E2E assertion Assert.ThrowsAsync<HiveServer2Exception> will fail. A stray unused using was added in the same file. The metadata revert and escape rewrite otherwise look internally consistent with the new unit tests.

Comment thread csharp/test/E2E/StringValueTests.cs Outdated
Comment thread csharp/src/StatementExecution/StatementExecutionClient.cs Outdated

@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 change; the escaping (two-layer backslash handling), catch-clause ordering (DESC-unsupported vs object-not-found are disjoint), and exception-type/Status/SqlState wiring all check out. One medium concern: GetCrossReferenceAsync validates args before the PKFK-disabled short-circuit while GetPrimaryKeysAsync does the reverse, so with EnablePKFK=false the two exact-match ops diverge (throw vs empty).

Comment thread csharp/src/StatementExecution/StatementExecutionStatement.cs Outdated
… stacked PR)

The exact-match argument validation for GetPrimaryKeys / GetCrossReference (throw
on null table, and on null schema when catalog is specified — mirroring JDBC's
resolveKeyBasedParams) is a distinct concern from this PR's object-not-found /
backslash / exception-type work. Moved to a stacked follow-up PR with its own
Thrift-vs-JDBC-vs-ADBC behavior matrix.

This PR now leaves PK/XREF returning an empty result when required args are missing
(consistent with the object-not-found path); the stacked PR adds the throws.

Removed: NewInvalidArgumentException helper, the validateArgs parameter, the
GetPrimaryKeysAsync / GetCrossReferenceAsync validation blocks, and the three
throw-asserting unit tests. Kept GetCrossReference_NullForeignTable_ReturnsEmpty
(that empty behavior is independent of the validation). 952 unit tests pass.

Co-authored-by: Isaac

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

✅ No issues identified by the review bot.

@eric-wang-1990 eric-wang-1990 added the integration-test Trigger integration tests in internal repo label Aug 2, 2026
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

🚀 Integration tests triggered! View workflow run

@eric-wang-1990
eric-wang-1990 disabled auto-merge August 2, 2026 17:13
@eric-wang-1990 eric-wang-1990 added integration-test Trigger integration tests in internal repo and removed integration-test Trigger integration tests in internal repo labels Aug 2, 2026
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

🚀 Integration tests triggered! View workflow run

@eric-wang-1990 eric-wang-1990 changed the title fix(csharp): align SEA metadata error behavior with Thrift fix(csharp): align SEA metadata error behavior with Thrift Aug 2, 2026
@eric-wang-1990
eric-wang-1990 added this pull request to the merge queue Aug 2, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 2, 2026
@eric-wang-1990
eric-wang-1990 added this pull request to the merge queue Aug 2, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 2, 2026
@eric-wang-1990
eric-wang-1990 added this pull request to the merge queue Aug 3, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 3, 2026
@eric-wang-1990
eric-wang-1990 added this pull request to the merge queue Aug 3, 2026
@eric-wang-1990
eric-wang-1990 removed this pull request from the merge queue due to the queue being cleared Aug 3, 2026
@eric-wang-1990
eric-wang-1990 added this pull request to the merge queue Aug 3, 2026
Merged via the queue into main with commit 20ee33f Aug 3, 2026
3 checks passed
@eric-wang-1990
eric-wang-1990 deleted the fix/revert-388-sea-object-not-found branch August 3, 2026 09:50
eric-wang-1990 added a commit that referenced this pull request Aug 3, 2026
…rossReference

Adds client-side argument validation for the SEA metadata exact-match operations,
mirroring the JDBC reference driver's resolveKeyBasedParams / listCrossReferences:

  GetPrimaryKeys:
    - table null/empty          -> throw "tableName may not be null" (42000)
    - catalog set + schema null -> throw "schema may not be null when catalog is specified" (42000)
  GetCrossReference:
    - foreign table null                       -> empty result (JDBC "unspecified")
    - foreign catalog set + foreign schema null -> throw (42000)

Validating client-side gives a clean, deterministic error and avoids the Thrift
server's internal "GET_FUNCTIONS assertion failed" (SQLSTATE 08000) bug on null
schema. Validation is on the user-facing command path only — GetColumnsExtended's
internal three-call fallback reuses the PK/FK fetch with a null schema on purpose
and bypasses the checks (GetPrimaryKeysAsync validateArgs:false; the shared
FetchCrossReferenceAsync is unvalidated).

Stacked on #604 (object-not-found → empty, backslash escaping, exception-type pivot);
this modifies the same SEA metadata methods that PR introduces, so it targets that
branch rather than main.

955 unit tests pass.

Co-authored-by: Isaac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integration-test Trigger integration tests in internal repo

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant