Skip to content

Fix CASE...END split-level tracking outside BEGIN blocks - #839

Open
lorenzhs wants to merge 2 commits into
andialbrecht:masterfrom
lorenzhs:fix/end-level
Open

lorenzhs wants to merge 2 commits into
andialbrecht:masterfrom
lorenzhs:fix/end-level

Conversation

@lorenzhs

@lorenzhs lorenzhs commented Feb 26, 2026 •

Copy link
Copy Markdown

Fix CASE...END split-level tracking in plain SELECT statements. CASE outside a BEGIN block did not increment the split level, but its matching END decremented it, leaving the level negative. Combined with the escaping issue in #838, this could split a query at a semicolon inside a literal.

The fix now tracks CASE using the current splitter's block stack. Existing handling of CASE inside BEGIN blocks is preserved, including nested CASE and END CASE.

Merged current master into the original PR branch to resolve conflicts while preserving the original commit history. Retained the original level-balancing and escaped-semicolon regression and added coverage for nested CASE expressions and a subsequent statement.

Validation: full suite passes (509 passed, 2 xfailed, 1 non-strict xpassed); Ruff passes. Added a changelog entry.

lorenzhs added a commit to firebolt-db/firebolt-python-sdk that referenced this pull request Mar 23, 2026
Replace git dependency on lorenzhs/sqlparse fork with a monkey-patch of
StatementSplitter._change_splitlevel in statement_formatter.py.

The upstream sqlparse project isn't very active and the fix for CASE...END level
tracking (andialbrecht/sqlparse#839) was not yet
released.  PyPI rejects packages with VCS dependencies, so vendoring the fix
inline unblocks publishing.
lorenzhs added a commit to firebolt-db/firebolt-python-sdk that referenced this pull request Mar 23, 2026
#494)

Replace git dependency on lorenzhs/sqlparse fork with a monkey-patch of StatementSplitter._change_splitlevel in statement_formatter.py.

The upstream sqlparse project isn't very active and the fix for CASE...END level tracking (andialbrecht/sqlparse#839) was not yet released. PyPI rejects packages with VCS dependencies, so vendoring the fix inline unblocks publishing.

The vendored code is identical to the fixed version from that PR, up to formatting, quote style, and comments.
@lorenzhs lorenzhs changed the title Fix end unconditionally decrementing the split level, but case not incrementing it in a plain select Fix CASE...END split-level tracking outside BEGIN blocks Oct 7, 2026
lorenzhs added a commit to firebolt-db/firebolt-python-sdk that referenced this pull request Oct 7, 2026
Now that the SDK requires Python 3.10, update dependencies and
development tools to their latest compatible releases.

Update sqlparse to 0.6.0, which includes parser denial-of-service fixes.
Adapt our CASE workaround to the new upstream block-stack splitter and
add regressions for escaped semicolons and nested CASE expressions. The
workaround is still needed pending [sqlparse PR
#839](andialbrecht/sqlparse#839).

Also update AnyIO, Trio, mypy, pyfakefs, pytest and its plugins,
pre-commit, Sphinx's Python 3.10-compatible floor, and formatting/lint
hooks. Remove two ineffective fixture marks that pytest 9 rejects; the
usage-tracker test retains its xdist grouping. Include the formatting
changes required by the new Black release.

Validation on Python 3.10:
- Unit suite: 780 passed, 1 skipped.
- Usage-tracker integration tests with 6 xdist workers: 8 passed.
- All 219 integration tests collect.
- All pre-commit checks pass, including mypy 2.4.
- Documentation build succeeds with 29 existing warnings.
- Dependency audit of the 90 resolved runtime/dev/docs packages reports
no known vulnerabilities.

Live database integration tests were not rerun locally.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Upgrading sqlparse and rewriting statement-splitting logic can change
how multi-statement queries are parsed; dependency bumps (mypy 2, pytest
9) affect CI only but runtime parsing is user-facing.
> 
> **Overview**
> Bumps **runtime and dev dependencies** for the Python 3.10+ baseline:
**sqlparse 0.6.0** (DoS fixes), AnyIO/Trio, mypy 2.x, pytest 9 and
plugins, pre-commit/Sphinx floors, and refreshed **pre-commit** hooks
(Black 26, isort 9, flake8 7.4, etc.). `setup.cfg` pins the new
versions; the example notebook picks up Black-driven formatting only.
> 
> The main product change is **adapting SQL statement splitting** after
the sqlparse upgrade: the old large `_change_splitlevel` monkeypatch is
replaced by a thin wrapper that delegates to sqlparse’s splitter and
only adds **CASE** tracking outside `BEGIN` blocks (still pending
upstream PR #839). New unit tests cover **CASE** expressions with
**escaped semicolons in literals** and nested CASE when splitting
multi-statement SQL.
> 
> Test harness cleanup drops **invalid `@mark.xdist_group` on module
fixtures** (pytest 9); usage-tracker parametrized tests keep their xdist
group. A trivial `# type: ignore` spacing fix in `base_cursor.py`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
845562c. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant