Skip to content

fix(redshift): parser issue for TOP N DISTINCT - #7594

Merged
fivetran-kwoodbeck merged 5 commits into
mainfrom
fix/redshift-top_n_distinct
May 5, 2026
Merged

fivetran-kwoodbeck merged 5 commits into
mainfrom
fix/redshift-top_n_distinct

Conversation

@fivetran-kwoodbeck

@fivetran-kwoodbeck fivetran-kwoodbeck commented May 1, 2026

Copy link
Copy Markdown
Collaborator

Redshift supports SELECT TOP N DISTINCT ... where TOP N precedes DISTINCT. The base parser checks for DISTINCT immediately after SELECT before consuming TOP N

The fix adds two overrides to RedshiftParser. _parse_limit detects a DISTINCT token immediately following TOP N, consumes it, and temporarily stashes an exp.Distinct() on the exp.Limit node as a carrier. Redshift's _parse_select_query then promotes that value up to exp.Select.distinct and removes it from the limit once the exp.Select is fully built.

I don't see a more elegant way to handle it because distinct is resolved as a local variable in the base _parse_select_query before _parse_limit is ever called. There's no obvious way to reach back, so the limit node acts as a handoff point between the two.

@github-actions

github-actions Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

SQLGlot Integration Test Results

Comparing:

  • this branch (sqlglot:fix/redshift-top_n_distinct, sqlglot version: fix/redshift-top_n_distinct)
  • baseline (main, sqlglot version: 0.0.1.dev1)

By Dialect

dialect main sqlglot:fix/redshift-top_n_distinct transitions links
bigquery -> bigquery 24647/24652 passed (100.0%) 23497/23497 passed (100.0%) No change full result / delta
bigquery -> duckdb 867/1154 passed (75.1%) 0/0 passed (0.0%) Results not found full result / delta
duckdb -> duckdb 5823/5823 passed (100.0%) 0/0 passed (0.0%) Results not found full result / delta
snowflake -> duckdb 1129/1935 passed (58.3%) 0/0 passed (0.0%) Results not found full result / delta
snowflake -> snowflake 65133/65133 passed (100.0%) 63027/63027 passed (100.0%) No change full result / delta
databricks -> databricks 1370/1370 passed (100.0%) 1370/1370 passed (100.0%) No change full result / delta
postgres -> postgres 6042/6042 passed (100.0%) 6042/6042 passed (100.0%) No change full result / delta
redshift -> redshift 7101/7101 passed (100.0%) 7101/7101 passed (100.0%) No change full result / delta

Overall

main: 113210 total, 112112 passed (pass rate: 99.0%), sqlglot version: 0.0.1.dev1

sqlglot:fix/redshift-top_n_distinct: 101037 total, 101037 passed (pass rate: 100.0%), sqlglot version: fix/redshift-top_n_distinct

Transitions:
No change

Dialect pair changes: 0 previous results not found, 3 current results not found

✅ 42 test(s) passed

@geooo109

geooo109 commented May 4, 2026

Copy link
Copy Markdown
Collaborator

@fivetran-kwoodbeck Yeah, PR description makes sense.

Is it possible to put the fix in the base parser for this ? and avoid doing this post change on the AST. When we parse the SELECT this should be fine.

I think TOP is used in redshift, t-sql, oracle, snowflake, and teradata. So, if we add the logic for this in the base parser and cover these dialects (avoid breaking anything) we can push it there.

@fivetran-kwoodbeck

Copy link
Copy Markdown
Collaborator Author

@geooo109 I didn't realize other dialects supported it, then yes, it makes sense to put it into the base parser. That will be cleaner overall, will update.

@fivetran-kwoodbeck
fivetran-kwoodbeck force-pushed the fix/redshift-top_n_distinct branch from f11597a to 2b606fe Compare May 5, 2026 13:30
Comment thread sqlglot/parser.py
@fivetran-kwoodbeck
fivetran-kwoodbeck merged commit 1206bea into main May 5, 2026
8 checks passed
@fivetran-kwoodbeck
fivetran-kwoodbeck deleted the fix/redshift-top_n_distinct branch May 5, 2026 21:33
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.

3 participants