Skip to content

fix(go): scope SHOW COLUMNS to the requested object in GetObjects - #170

Merged
zeroshade merged 2 commits into
mainfrom
fix/getobjects-show-columns-scope
Jul 20, 2026
Merged

fix(go): scope SHOW COLUMNS to the requested object in GetObjects#170
zeroshade merged 2 commits into
mainfrom
fix/getobjects-show-columns-scope

Conversation

@zeroshade

Copy link
Copy Markdown
Contributor

Summary

Fixes #169.

GetObjects at ObjectDepthColumns / ObjectDepthAll dispatched a SHOW COLUMNS command whose scope resolved to IN ACCOUNT whenever the catalog name contained an underscore, because isWildcardStr treats _ and % as wildcards. Since SHOW COLUMNS has no table-level LIKE filter, SHOW COLUMNS ... IN ACCOUNT scans every column in the entire account — 80–150s on large accounts — even for a single-table request like DB_NAME.TEST_SCHEMA.LINEITEM.

Changes

  • Add scopeIdentifier / showColumnsScope and scope the SHOW COLUMNS query to the narrowest concrete object (IN TABLE / IN SCHEMA / IN DATABASE), treating _ as a literal and only % / .* / nil as broadening.
  • Limit the 2003 (object does not exist / not authorized) empty-result fallback to only the optional SHOW COLUMNS enrichment query, via a new variadic alsoEmptyOn parameter on getQueryID. Required object/constraint discovery keeps its prior 2043-only behavior.
  • Add a unit test for scope selection.

Why this is safe

SHOW COLUMNS is only a best-effort source for BINARY xdbc_column_size in get_objects_all.sql (a LEFT JOIN for byte_length). The authoritative column list comes from information_schema.columns filtered by ILIKE, so a narrower SHOW COLUMNS scope never drops columns or alters non-BINARY metadata.

Tradeoff: a BINARY column reached only through a genuine _-as-wildcard match (or a case-insensitive pattern differing from the stored identifier) may report a NULL xdbc_column_size, matching the behavior before SHOW COLUMNS enrichment was added in #152. This is documented on scopeIdentifier / showColumnsScope.

Scope timing (small test account; worse on large accounts)

SHOW COLUMNS scope Elapsed
IN ACCOUNT 18.4 s
IN DATABASE 4.8 s
IN SCHEMA 0.52 s
IN TABLE 0.39 s

Testing

  • go build, go vet, gofmt: clean.
  • TestShowColumnsScope: passes (concrete underscore names → IN TABLE; % / .* / nil → broader; quote escaping).
  • Live check against a real account: GetObjects(Columns, "SNOWFLAKE_SAMPLE_DATA", "TPCH_SF1", "LINEITEM") returns correctly and drops from the ~18s IN ACCOUNT floor to a table-scoped query; a non-existent table returns an empty result rather than erroring.

zeroshade added 2 commits July 3, 2026 22:39
GetObjects at Columns and All depth dispatched a SHOW COLUMNS command
whose scope resolved to IN ACCOUNT whenever the catalog name contained
an underscore, because isWildcardStr treats '_' and '%' as wildcards.
For an ordinary database name such as DB_NAME this scanned every column
in the entire account, taking 80+ seconds on large accounts, even though
the request targeted a single table.

Scope the SHOW COLUMNS query to the narrowest concrete object
(IN TABLE / IN SCHEMA / IN DATABASE), treating '_' as a literal and only
'%', '.*', and nil as broad. The column list still comes from
information_schema.columns and the downstream ILIKE filtering is
unchanged, so the returned metadata is identical; SHOW COLUMNS is only
used to enrich xdbc_column_size for BINARY columns.

Also treat Snowflake error 2003 (object does not exist or not
authorized) like 2043 (no match) so a narrowly scoped query for a
missing object falls back to an empty result set instead of failing.

Add a unit test covering the new scope selection.
Address review feedback on the SHOW COLUMNS scoping change:

- Limit the "object does not exist" (2003) empty-result fallback to the
  optional SHOW COLUMNS enrichment query via getQueryID's new variadic
  alsoEmptyOn parameter, instead of applying it to every getQueryID caller.
  Required object and constraint discovery keep their prior 2043-only
  behavior so genuine errors there are not masked.
- Document that scopeIdentifier/showColumnsScope treat '_' as a literal by
  design: SHOW COLUMNS is only a best-effort source for BINARY
  xdbc_column_size, the column list still comes from information_schema.columns
  via ILIKE, so a narrow scope never drops columns or changes non-BINARY
  metadata.
- Add a test case covering underscore-as-literal scope selection.
@zeroshade
zeroshade requested a review from lidavidm as a code owner July 13, 2026 16:02
@zeroshade zeroshade added lang-go The Go Snowflake driver. go Pull requests that update go code labels Jul 13, 2026
@zeroshade

Copy link
Copy Markdown
Contributor Author

@frbvianna can you take a look and test this out with your config?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes a performance regression in GetObjects at ObjectDepthColumns / ObjectDepthAll where SHOW COLUMNS could incorrectly broaden to IN ACCOUNT (notably when catalog names contain underscores), causing extremely slow metadata fetches on large Snowflake accounts. The change introduces scope narrowing specifically for the optional SHOW COLUMNS enrichment query while preserving existing behavior for required discovery queries.

Changes:

  • Add scopeIdentifier and showColumnsScope to choose the narrowest valid SHOW COLUMNS ... IN {TABLE|SCHEMA|DATABASE|ACCOUNT} suffix, treating _ as literal and only % / .* / nil as broadening signals.
  • Extend getQueryID with an alsoEmptyOn variadic parameter so only the optional SHOW COLUMNS enrichment can treat error 2003 as an empty-result fallback (required queries keep prior behavior).
  • Add TestShowColumnsScope to validate scoping rules and identifier quoting/escaping.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
go/connection.go Introduces showColumnsScope and applies it to the SHOW COLUMNS enrichment query; refines empty-result fallback behavior via alsoEmptyOn.
go/get_objects_scope_test.go Adds unit coverage for SHOW COLUMNS scope selection and quote escaping.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@lidavidm lidavidm left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should probably specify the option(s) to disable and/or escape wildcards for these pattern arguments (upstream)

@zeroshade

Copy link
Copy Markdown
Contributor Author

I agree, but I don't think that should block this change, should it?

@lidavidm

Copy link
Copy Markdown
Contributor

Didn't say it was blocking :) But ideally @frbvianna can confirm that this actually fixes the problem.

@zeroshade

Copy link
Copy Markdown
Contributor Author

I was able to reproduce the issue reported and prove this fixed it for myself, but I agree that it would be better for @frbvianna to confirm

@frbvianna

Copy link
Copy Markdown

Hey @zeroshade. Thanks for the fix. I gave it a test, and now it's taking a reasonable ~12 seconds to get objects at column depth.

@zeroshade
zeroshade merged commit b08c3af into main Jul 20, 2026
17 of 18 checks passed
@zeroshade
zeroshade deleted the fix/getobjects-show-columns-scope branch July 20, 2026 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

go Pull requests that update go code lang-go The Go Snowflake driver.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GetObjects at Columns depth runs SHOW COLUMNS IN ACCOUNT (80-150s) for underscore catalog names

4 participants