Compare commits

...

3 Commits

Author SHA1 Message Date
rusackas
3265f42418 test(sql): cover mysql/snowflake in SHOW-statement FORCE_LIMIT regression test
Parametrize the regression test over engines whose sqlglot dialect
parses SHOW into a real exp.Show node (starrocks, mysql, snowflake),
not just starrocks, since the fix guards on AST node type rather than
dialect and any of these engines is equally exposed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 18:29:14 -07:00
rusackas
c62b9d6812 fix(sql): guard FORCE_LIMIT against SHOW statements
SQLStatement.set_limit_value's FORCE_LIMIT path unconditionally set
_parsed.args["limit"], but sqlglot's exp.Show has no real LIMIT slot:
forcing one renders a malformed statement with two LIMIT keywords,
which StarRocks (and other FORCE_LIMIT engines) reject outright.

Fixes #36939 (SHOW TABLES / SHOW DATABASES / SHOW CREATE TABLE portion).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-29 18:21:59 -07:00
Claude Code
b0fd51fe24 test(sql): SHOW statements must not get a forced LIMIT (#36939)
set_limit_value's FORCE_LIMIT path unconditionally sets
_parsed.args["limit"] on any statement, including SHOW TABLES/
DATABASES/CREATE TABLE. sqlglot's Show expression has no real LIMIT
slot to hold that value, so it renders a malformed statement with two
LIMIT keywords instead of rejecting cleanly. StarRocks (and likely
other engines using FORCE_LIMIT) reject the result outright, which is
exactly the "Unexpected input 'LIMIT'" error reported in #36939 for
SHOW TABLES / SHOW DATABASES / SHOW CREATE TABLE.

This is unrelated to the other two statements in that issue (REFRESH
EXTERNAL TABLE, DROP ... FORCE) — those fail to parse at the sqlglot
layer entirely, confirmed still true against the pinned sqlglot
30.12.0 for every dialect tried, not just starrocks. That's an
upstream sqlglot dialect gap, not something fixable in this repo, so
it's out of scope here.

This is a test-only PR; the test is expected to be RED (confirms the
bug, does not fix it). Not using a closing keyword since merging this
alone won't resolve #36939.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-29 16:31:09 -07:00
2 changed files with 53 additions and 0 deletions

View File

@@ -1274,6 +1274,13 @@ class SQLStatement(BaseSQLStatement[exp.Expression]):
Modify the `LIMIT` or `TOP` value of the SQL statement inplace.
"""
if method == LimitMethod.FORCE_LIMIT:
# `SHOW` statements (`SHOW TABLES`, `SHOW DATABASES`, `SHOW CREATE
# TABLE`, etc.) have no real `LIMIT` slot in sqlglot's expression
# tree: setting `args["limit"]` doesn't get rejected, it renders a
# malformed statement with two `LIMIT` keywords, which engines
# like StarRocks reject outright. Leave them untouched.
if isinstance(self._parsed, exp.Show):
return
self._parsed.args["limit"] = exp.Limit(
expression=exp.Literal(this=str(limit), is_string=False)
)

View File

@@ -2243,6 +2243,52 @@ def test_set_limit_value(
assert statement.format() == expected
@pytest.mark.parametrize(
"engine",
[
# Engines whose sqlglot dialect parses `SHOW` into a real `exp.Show`
# node (as opposed to falling back to an opaque `exp.Command`, which
# doesn't expose a `limit` arg and so was never affected by this bug).
"starrocks",
"mysql",
"snowflake",
],
)
@pytest.mark.parametrize(
"sql",
[
"SHOW TABLES",
"SHOW DATABASES",
"SHOW CREATE TABLE test.will_test1",
],
)
def test_set_limit_value_leaves_show_statements_unchanged(
sql: str, engine: str
) -> None:
"""
Regression for #36939: FORCE_LIMIT must not touch ``SHOW`` statements.
``SHOW`` statements have no `LIMIT` clause in sqlglot's expression tree,
so forcing one via ``args["limit"]`` doesn't reject cleanly, it produces
a malformed statement with two ``LIMIT`` keywords (one from a stray
rendering of the bare ``Limit`` expression, one from the forced value).
StarRocks (and presumably other engines) reject that outright: "Getting
syntax error ... Unexpected input 'LIMIT'". The statement should be
left untouched instead, matching how ``SELECT`` statements without a
scannable row source aren't force-limited either.
Covers multiple engines, not just StarRocks: the fix guards on the AST
node type (``exp.Show``), not the dialect, so any engine whose sqlglot
dialect parses ``SHOW`` into a real ``Show`` node (e.g. MySQL, Snowflake)
is equally exposed and must be equally protected.
"""
statement = SQLStatement(sql, engine)
original = statement.format()
statement.set_limit_value(1000, LimitMethod.FORCE_LIMIT)
assert statement.format() == original
assert "LIMIT" not in statement.format()
@pytest.mark.parametrize(
"kql, limit, expected",
[