Skip to content

fix(mssql): preserve outer CTEs and ORDER BY when flattening pagination wrap - #2579

Merged
goldmedal merged 4 commits into
Canner:mainfrom
abdullahharunozturk:fix/mssql-flatten-preserve-cte-order
Jul 28, 2026
Merged

fix(mssql): preserve outer CTEs and ORDER BY when flattening pagination wrap#2579
goldmedal merged 4 commits into
Canner:mainfrom
abdullahharunozturk:fix/mssql-flatten-preserve-cte-order

Conversation

@abdullahharunozturk

@abdullahharunozturk abdullahharunozturk commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Problem

MSSqlConnector._flatten_pagination_limit collapses the v4 paginate-wrap shape SELECT * FROM (inner) LIMIT n into the inner select, but it returns only the inner node. Two outer clauses are silently dropped:

  • an outer WITH (e.g. semantic-layer model CTEs emitted by dry_plan) — the flattened query then references CTEs that no longer exist and fails with Invalid object name;
  • an outer ORDER BYTOP n then returns arbitrary rows instead of the requested top-n, a silent correctness bug.

Repro (both shapes are produced by wrapping a cube/aggregate query for ordering + limit):

WITH m AS (SELECT a, b FROM dbo.t)
SELECT TOP 3 * FROM (SELECT a, SUM(b) AS s FROM m GROUP BY a) AS _c ORDER BY s DESC

flattens to SELECT TOP 3 a, SUM(b) AS s FROM m GROUP BY aInvalid object name 'm'; without the CTE the ORDER BY loss makes TOP 3 nondeterministic.

Fix

Bail out of flattening when the outer select carries WITH or ORDER BY — both are valid T-SQL next to TOP, so the original query runs correctly as-is. The bare paginate-wrap shape still collapses as before.

Tests

Three container-free unit tests in tests/connectors/test_mssql.py: CTE preserved, ORDER BY preserved, bare wrap still collapses. Verified end-to-end against SQL Server 2022 (real data): before the fix the CTE shape errors and the ORDER BY shape returns wrong rows; after the fix both return correct results.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved SQL Server pagination rewriting to preserve top-level WITH (CTEs) and ORDER BY when present.
    • Prevented outer pagination transformations from breaking query structure or result determinism.
    • Ensured LIMIT is correctly rewritten into valid T-SQL while keeping supported outer clauses intact.
  • Tests
    • Expanded unit-test coverage for pagination flattening, including outer WITH and outer ORDER BY scenarios, plus standard limit rewriting behavior.

…on wrap

_flatten_pagination_limit collapses SELECT * FROM (inner) LIMIT n into the
inner select, but returned only the inner node — silently dropping an outer
WITH (invalid object errors for CTE references) and an outer ORDER BY
(TOP-n then returns arbitrary rows). Bail out of flattening when the outer
select carries either clause; both are valid T-SQL next to TOP, so the
original query runs correctly as-is. The bare paginate-wrap shape keeps
collapsing. Adds container-free unit tests for all three shapes.
@github-actions github-actions Bot added python Pull requests that update Python code core labels Jul 24, 2026
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b5f79399-5f19-4d6b-ac54-0df7e8962098

📥 Commits

Reviewing files that changed from the base of the PR and between 6592007 and 08479f6.

📒 Files selected for processing (1)
  • core/wren/tests/connectors/test_mssql.py

Walkthrough

MSSQL pagination flattening now avoids collapsing queries with top-level WITH or ORDER BY clauses, re-rendering them as T-SQL. Tests cover clause preservation, valid limit conversion, and continued collapsing of simple wrappers.

Changes

MSSQL pagination rewrite

Layer / File(s) Summary
Guard pagination flattening
core/wren/src/wren/connector/mssql.py, core/wren/tests/connectors/test_mssql.py
The connector preserves top-level CTE and ordering clauses, converts LIMIT to T-SQL syntax, and retains bare-wrapper flattening; tests cover each behavior.

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

Possibly related PRs

  • Canner/WrenAI#2476: Both modify MSSQL pagination rewriting in _flatten_pagination_limit.

Suggested reviewers: goldmedal

Poem

I’m a rabbit guarding SQL lines,
Keeping CTEs and order signs.
Bare wraps hop and fold just right,
T-SQL limits shine bright.
No clause vanishes from sight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: preserving outer CTE and ORDER BY clauses while flattening MSSQL pagination wrappers.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
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.

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/wren/src/wren/connector/mssql.py`:
- Around line 134-135: Update _flatten_pagination_limit() so guarded LIMIT
queries with outer WITH or ORDER BY are re-emitted through the T-SQL dialect
instead of returning raw SQL containing LIMIT. In
core/wren/tests/connectors/test_mssql.py lines 315-335, add equivalent LIMIT
regression cases for both CTE and ORDER BY scenarios, verifying the generated
queries are valid T-SQL.

In `@core/wren/tests/connectors/test_mssql.py`:
- Around line 315-335: Extend test_flatten_pagination_preserves_outer_cte and
test_flatten_pagination_preserves_outer_order_by with equivalent LIMIT 3 inputs,
asserting the outer WITH or ORDER BY remains present and the output uses valid
T-SQL pagination (TOP or FETCH) without any LIMIT clause. Keep the existing
TOP-based coverage intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ff967499-ff2d-4698-9aab-3e707c46d366

📥 Commits

Reviewing files that changed from the base of the PR and between d472877 and 26efea4.

📒 Files selected for processing (2)
  • core/wren/src/wren/connector/mssql.py
  • core/wren/tests/connectors/test_mssql.py

Comment thread core/wren/src/wren/connector/mssql.py Outdated
Comment thread core/wren/tests/connectors/test_mssql.py
…ll becomes TOP/FETCH

Addresses review feedback: returning the raw query on the WITH/ORDER BY
guard path would leave a literal LIMIT unrewritten (invalid T-SQL).
Re-emit the parsed statement via the tsql dialect instead — WITH and
ORDER BY survive and LIMIT is rewritten to TOP/FETCH. Adds two unit
tests covering LIMIT with an outer CTE and with an outer ORDER BY.
@abdullahharunozturk

Copy link
Copy Markdown
Contributor Author

Addressed the review feedback: the guard path now re-emits the parsed statement through the tsql dialect instead of returning the raw query, so a literal LIMIT on that path is still rewritten to TOP/FETCH while the outer WITH / ORDER BY survive. Added two unit tests for the LIMIT+CTE and LIMIT+ORDER BY variants.

Verified locally: all 5 flatten unit tests pass, and ruff check / ruff format --check are clean on both changed files. Also verified end-to-end against SQL Server 2022 with real data through the full engine path.

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/wren/tests/connectors/test_mssql.py`:
- Line 343: Update the pagination assertions in the affected MSSQL connector
tests to verify the numeric limit as an exact token, not a substring that can
match larger values such as 30. Apply this to both TOP and NEXT forms at the
assertions around the referenced cases, using token-boundary matching or parsed
SQL while preserving the existing expected values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3c0a7f96-ac1b-4e5f-8a92-af59d2ca644c

📥 Commits

Reviewing files that changed from the base of the PR and between 26efea4 and 6592007.

📒 Files selected for processing (2)
  • core/wren/src/wren/connector/mssql.py
  • core/wren/tests/connectors/test_mssql.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • core/wren/src/wren/connector/mssql.py

Comment thread core/wren/tests/connectors/test_mssql.py Outdated
Substring checks like 'TOP 3 in out' would also match TOP 30; use a
regex helper that verifies the numeric limit exactly for both the TOP
and FETCH NEXT forms.
@abdullahharunozturk

Copy link
Copy Markdown
Contributor Author

Also addressed the remaining minor comment in 08479f6: the pagination assertions now use a token-boundary-aware helper (_has_exact_limit) that matches the exact numeric limit for both the TOP and FETCH NEXT forms, so TOP 3 no longer matches TOP 30. All review feedback should be resolved now.

@goldmedal goldmedal left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks @abdullahharunozturk, nice catch 👍

@goldmedal
goldmedal merged commit a93184d into Canner:main Jul 28, 2026
10 checks passed
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