Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions core/wren/src/wren/connector/mssql.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,12 @@ def _raw_cursor_sql(
) -> str:
"""Inject a ``LIMIT n`` into a Select so sqlglot emits the tsql
``OFFSET 0 ROWS FETCH NEXT n ROWS ONLY`` clause."""
# Unlimited path: strip trailing terminators so client-pasted SQL
# matches dry_run / limit composition (connector consistency; see #2595).
sql = strip_trailing_semicolon(sql)
if limit is None:
return sql

sql = strip_trailing_semicolon(sql)

try:
parsed = parse_one(sql, dialect=input_dialect)
except Exception:
Expand Down
11 changes: 8 additions & 3 deletions core/wren/tests/unit/test_mssql_semicolon.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ def test_raw_cursor_sql_injects_limit_after_multi_semicolon():
assert ";;" not in out


def test_raw_cursor_sql_no_limit_unchanged_except_strip_not_required():
# limit None returns original (including trailing ;) — execute path allows it
assert MSSqlConnector._raw_cursor_sql("SELECT 1;", None) == "SELECT 1;"
def test_raw_cursor_sql_no_limit_strips_trailing_semicolon():
"""Unlimited path strips terminators for connector consistency (#2595).

Not a pyodbc multi-statement claim: lone trailing ``;`` is accepted by
pyodbc. Strip keeps parse/execute input aligned with limit + dry_run.
"""
assert MSSqlConnector._raw_cursor_sql("SELECT 1;", None) == "SELECT 1"
assert MSSqlConnector._raw_cursor_sql("SELECT 1;;", None) == "SELECT 1"
Loading