From 72b7d469a4d96af69c76a7a20c1884467f9cf89a Mon Sep 17 00:00:00 2001 From: ikatyal21 Date: Sun, 26 Jul 2026 14:37:29 +0000 Subject: [PATCH] Fix rows_where() crash when offset is given without limit SQLite requires LIMIT before OFFSET; omitting it raised OperationalError. When offset is set and limit is not, emit LIMIT -1 first so the SQL is valid. Same fix applied to search_sql(). Adds regression test. --- sqlite_utils/db.py | 4 ++++ tests/test_rows.py | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 713b11074..b7d65cd60 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -2003,6 +2003,8 @@ def rows_where( if limit is not None: sql += f" limit {limit}" if offset is not None: + if limit is None: + sql += " limit -1" sql += f" offset {offset}" cursor = self.db.execute(sql, where_args or []) columns = dedupe_keys(c[0] for c in cursor.description) @@ -3594,6 +3596,8 @@ def search_sql( if limit is not None: limit_offset += f" limit {limit}" if offset is not None: + if limit is None: + limit_offset += " limit -1" limit_offset += f" offset {offset}" return sql.format( dbtable=quote_identifier(self.name), diff --git a/tests/test_rows.py b/tests/test_rows.py index 46d4f5358..c32d5da50 100644 --- a/tests/test_rows.py +++ b/tests/test_rows.py @@ -70,6 +70,13 @@ def test_rows_where_offset_limit(fresh_db, offset, limit, expected): ] +def test_rows_where_offset_without_limit(fresh_db): + table = fresh_db["rows"] + table.insert_all([{"id": id} for id in range(1, 6)], pk="id") + ids = [r["id"] for r in table.rows_where(offset=2, order_by="id")] + assert ids == [3, 4, 5] + + def test_pks_and_rows_where_rowid(fresh_db): table = fresh_db["rowid_table"] table.insert_all({"number": i + 10} for i in range(3))