Skip to content

refactor(snowflake): strip trailing semicolon on unlimited query path for connector consistency - #2593

Open
Bartok9 wants to merge 3 commits into
Canner:mainfrom
Bartok9:fix/snowflake-strip-semicolon-unlimited
Open

refactor(snowflake): strip trailing semicolon on unlimited query path for connector consistency#2593
Bartok9 wants to merge 3 commits into
Canner:mainfrom
Bartok9:fix/snowflake-strip-semicolon-unlimited

Conversation

@Bartok9

@Bartok9 Bartok9 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Strip trailing ; on Snowflake unlimited query() so it matches dry_run and other connectors (see merged #2595 mysql).

Motivation

Honest framing: this is connector consistency, not a proven snowflake-connector-python rejection of SELECT 1;. Limited path already stripped inside the subquery wrap; unlimited did not.

Review follow-through (@goldmedal)

  1. Restored LIMIT pushdown / subquery / ORDER BY rationale comments (kept alongside the strip).
  2. Softened rationale to alignment with dry_run + other connectors; retitled refactor(...).
  3. Preserved coerce_limit from main.
  4. Kept unit test for unlimited trailing-;.

Verification

cd core/wren && python -m pytest tests/unit/test_snowflake_limit_pushdown.py -q

Summary by CodeRabbit

  • Bug Fixes

    • Improved Snowflake query execution by correctly handling SQL statements with trailing semicolons.
    • Ensured limited queries continue to apply limits reliably.
  • Tests

    • Added coverage confirming semicolons are removed before executing unrestricted queries.

@github-actions github-actions Bot added python Pull requests that update Python code core labels Jul 27, 2026
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Snowflake query execution now strips trailing semicolons before limited and unlimited execution. The limit wrapper uses the normalized SQL, and a unit test verifies the unlimited execution statement.

Changes

Snowflake query execution

Layer / File(s) Summary
Query preprocessing and validation
core/wren/src/wren/connector/snowflake.py, core/wren/tests/unit/test_snowflake_limit_pushdown.py
SnowflakeConnector.query strips trailing semicolons before branching on limit, reuses the normalized SQL in the limit wrapper, and tests the unlimited execution path.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers: goldmedal

Poem

A rabbit trims SQL with care,
Snowflake receives cleaner queries there.
Limited paths wrap the stream,
Tests protect the execution scheme.
Hop, hop—semicolons disappear!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the Snowflake behavior change and its purpose of stripping trailing semicolons on unlimited queries.
Description check ✅ Passed The description explains the change, motivation, review follow-through, and test command; the duplicate-check section is not explicit but the content is mostly complete.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@goldmedal

Copy link
Copy Markdown
Collaborator

Code review

Two issues.

1. This deletes a comment that explains a non-obvious design decision.

self.connection = make_snowflake_connection(connection_info)
def query(self, sql: str, limit: int | None = None) -> pa.Table:
# Push LIMIT into Snowflake when requested so we do not download a
# full result set only to slice it in Python. Wrap as a subquery so a
# trailing semicolon in the user SQL cannot break composition, and so
# statements that already contain an ORDER BY keep their ordering
# under the outer LIMIT.
executed = sql
if limit is not None:
# Place the user SQL on its own line so a trailing line comment
# (`-- ...`) cannot swallow the closing paren, alias, or LIMIT.

The removed text records why the limited path wraps in a subquery — LIMIT pushdown to avoid downloading a full result set, and preserving an existing ORDER BY under the outer LIMIT. None of that is inferable from the code, and the replacement comment is about semicolons instead. The subquery wrap is still there after this PR, so its rationale should be too. Please keep both comments rather than swapping one for the other.

2. The new claim is unsubstantiated. "Snowflake rejects bare trailing terminators in some clients" — which clients, and under what conditions? snowflake-connector-python executes SELECT 1; without complaint as a single statement. If there's a real case, cite it; if the honest reason is alignment with bigquery, duckdb, redshift and mysql (#2595), say that and retitle to refactor(...), as #2595 was.

Also: #2556 is the same change to the same file. One of the two should close — this one's test is the better of the pair.

Rebase before merge — 3 commits behind main.

@Bartok9

Bartok9 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current main and addressed review:

  1. Restored the LIMIT pushdown / subquery / ORDER BY rationale comments (kept alongside the unlimited ; strip).
  2. Softened the semicolon rationale to alignment with dry_run + other connectors (not an unsubstantiated client claim).
  3. Preserved coerce_limit from main.
  4. Kept the unlimited trailing-; unit test.

Ready for another look.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

Keep LIMIT pushdown/subquery rationale comments and coerce_limit.
Align unlimited execute with dry_run and other connectors (Canner#2595).
@Bartok9 Bartok9 changed the title fix(snowflake): strip trailing semicolon on unlimited query path refactor(snowflake): strip trailing semicolon on unlimited query path for connector consistency Aug 7, 2026
@Bartok9
Bartok9 force-pushed the fix/snowflake-strip-semicolon-unlimited branch from 3a01b8d to 2e8dd2c Compare August 7, 2026 04:16
@Bartok9

Bartok9 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

@goldmedal rebased on current main and addressed your review:

  1. Kept the LIMIT pushdown / subquery / ORDER BY comments (not swapped away).
  2. Retitled to refactor(...) — consistency with dry_run + refactor(mysql): strip trailing semicolon on unlimited query path for connector consistency #2595-style connectors, not an unsubstantiated client claim.
  3. Preserved coerce_limit.
  4. Unlimited ; unit test retained.

Earlier CI reds on this branch looked like GitHub Actions “Service Unavailable” fetching actions, not test assertion failures — fresh push should re-run cleanly.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@goldmedal

Copy link
Copy Markdown
Collaborator

This one now matches the merged precedents — #2595 (mysql) and #2633 (mssql) — and the retitle to refactor(...) is the right call: there is no user-visible behaviour change, since every path into SnowflakeConnector.query goes through WrenEngine.querydry_plan_plan, whose output is sqlglot-generated and carries no terminator.

One leftover to tidy. The pre-existing comment above executed still reads:

Wrap as a subquery so a trailing semicolon in the user SQL cannot break composition, and so statements that already contain an ORDER BY keep their ordering under the outer LIMIT.

After this change the strip happens before the wrap, so the first half of that rationale no longer describes why the wrap exists — the semicolon is already gone by then. The ORDER BY half is still accurate. Please update that sentence so the comment matches the new ordering rather than leaving a documented rationale that the code has moved past.

With that, this is good to go from my side.

Drop the trailing-semicolon composition rationale from the subquery wrap
comment now that strip_trailing_semicolon runs before the wrap; keep the
ORDER BY / pushdown reason.
@Bartok9

Bartok9 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

@goldmedal Updated the LIMIT-wrap comment so it no longer cites trailing-semicolon composition (strip already runs first). Kept the ORDER BY / pushdown rationale. Ready for another look.

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

Labels

core python Pull requests that update Python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants