Skip to content

fix(sqlite): support INSERT IGNORE and offset-only limits [CODEX]#7674

Merged
georgesittas merged 5 commits into
tobymao:mainfrom
russellromney:codex/sqlite-valid-transpilation
May 27, 2026
Merged

fix(sqlite): support INSERT IGNORE and offset-only limits [CODEX]#7674
georgesittas merged 5 commits into
tobymao:mainfrom
russellromney:codex/sqlite-valid-transpilation

Conversation

@russellromney
Copy link
Copy Markdown
Contributor

@russellromney russellromney commented May 23, 2026

Summary

Fix SQLite-targeted transpilation for three cases that currently produce SQL SQLite rejects:

  • MySQL INSERT IGNORE ... -> SQLite INSERT OR IGNORE ...
  • Postgres LIMIT ALL -> no SQLite LIMIT clause
  • Postgres offset-only OFFSET n -> SQLite LIMIT -1 OFFSET n

These are represented directly in SQLite syntax rather than unsupported semantics.

Examples

sqlglot.transpile(
    "INSERT IGNORE INTO t (id, a) VALUES (1, 2)",
    read="mysql",
    write="sqlite",
)[0]
# before: INSERT IGNORE INTO t (id, a) VALUES (1, 2)
# after:  INSERT OR IGNORE INTO t (id, a) VALUES (1, 2)
sqlglot.transpile("SELECT x FROM t LIMIT ALL", read="postgres", write="sqlite")[0]
# before: SELECT x FROM t LIMIT ALL
# after:  SELECT x FROM t
sqlglot.transpile("SELECT x FROM t OFFSET 1", read="postgres", write="sqlite")[0]
# before: SELECT x FROM t OFFSET 1
# after:  SELECT x FROM t LIMIT -1 OFFSET 1

I also checked the combined case:

sqlglot.transpile("SELECT x FROM t LIMIT ALL OFFSET 1", read="postgres", write="sqlite")[0]
# after: SELECT x FROM t LIMIT -1 OFFSET 1

Why

SQLite uses INSERT OR IGNORE for this conflict behavior, not MySQL's INSERT IGNORE. SQLite's INSERT docs describe the INSERT OR action form for choosing a constraint conflict algorithm: https://www.sqlite.org/lang_insert.html

SQLite also requires OFFSET to appear as part of a LIMIT clause; LIMIT -1 OFFSET n is the common SQLite spelling for offset without an upper row bound. Related prior art/background on emulating MySQL conflict behavior in other dialects: https://stackoverflow.com/questions/1009584/how-to-emulate-insert-ignore-and-on-duplicate-key-update-sql-merge-with-po

I searched for existing SQLGlot issues/PRs mentioning these exact SQLite-target gaps and did not find an existing report.

Tests

  • python3 -m unittest tests.dialects.test_sqlite.TestSQLite.test_sqlite
  • python3 -m unittest tests.dialects.test_dialect.TestDialect.test_limit tests.dialects.test_mysql.TestMySQL.test_mysql
  • python3 -m unittest tests.dialects.test_sqlite
  • python3 -m ruff check sqlglot/generators/sqlite.py tests/dialects/test_sqlite.py
  • git diff --check

@russellromney russellromney changed the title Fix SQLite output for INSERT IGNORE and offset limits fix(sqlite): support INSERT IGNORE and offset-only limits [CODEX] May 23, 2026
Copy link
Copy Markdown
Collaborator

@georgesittas georgesittas left a comment

Choose a reason for hiding this comment

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

Thank you for the PR!

Comment thread sqlglot/generators/sqlite.py Outdated
Comment thread sqlglot/generators/sqlite.py
Comment thread sqlglot/generators/sqlite.py Outdated
Comment on lines +215 to +218
if expression.args.get("ignore"):
expression.set("ignore", False)
expression.set("alternative", "IGNORE")

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.

Hmm... this is fine for now, but looks like a code smell to me. Having two ways to represent the IGNORE semantics doesn't look right. Perhaps something to clean up in the future...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

good catch here. let me think about a better way to do this

Copy link
Copy Markdown
Collaborator

@georgesittas georgesittas May 25, 2026

Choose a reason for hiding this comment

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

This is fine for now, let's not deal with it in this PR. Just wanted to leave a note for future reference.

@georgesittas georgesittas self-assigned this May 25, 2026
Comment thread sqlglot/parser.py Outdated
Comment thread tests/dialects/test_dialect.py Outdated
Comment thread tests/dialects/test_sqlite.py Outdated
Comment thread tests/dialects/test_sqlite.py Outdated
Comment thread tests/dialects/test_sqlite.py Outdated
Comment thread sqlglot/dialects/postgres.py
@russellromney
Copy link
Copy Markdown
Contributor Author

All feedback addressed, thanks. Should have checked tests a little more thoroughly

Comment thread tests/dialects/test_dialect.py Outdated
@georgesittas georgesittas merged commit 3c7f42c into tobymao:main May 27, 2026
7 checks passed
georgesittas added a commit that referenced this pull request May 27, 2026
…7674)

* Fix SQLite output for ignore and offset limits

* Address SQLite limit review feedback

* Scope LIMIT ALL parsing to supporting dialects

* Address LIMIT ALL review feedback

* Update tests/dialects/test_dialect.py

---------

Co-authored-by: Jo <46752250+georgesittas@users.noreply.github.com>
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.

2 participants