drizzle-team / drizzle-team/drizzle-orm

[BUG]: Negative limit not working in SQLite

Open
#2,992 4 comments 2 reactions 0 assignees View on GitHub
bug db/sqlite priority qb/crud
Dominant language
TypeScript
Stars
35.8k
Forks
1.6k
Avg merge
2d 7h
Merged PRs (30d)
4

Description

### What version of `drizzle-orm` are you using?

0.33.0

### What version of `drizzle-kit` are you using?

0.24.2

### Describe the Bug

It should be possible to set a negative limit in SQLite. I think it used to work in drizzle but recently my query stopped working.

I suspect it was [after this PR](https://github.com/drizzle-team/drizzle-orm/pull/2255/files#diff-adcc028702cd08186c718f5b4bd7ba08e9b009c71ce47ee0cf828d90f812c99c).

In SQLite, a negative limit may be used to skip the first `n` results and get all following results.

> If the LIMIT expression evaluates to a negative value, then there is no upper bound on the number of rows returned.

Source: https://www.sqlite.org/draft/lang_select.html#the_limit_clause

SQLite is unique is using negative limits for this purpose. Here is the equivalent functionality in different dialects:

| Dialect | Code |
|----------|----------------------------------------------------------------------------|
| Postgres | `SELECT * FROM mytable ORDER BY mycol ASC OFFSET 1` |
| SQLite | `SELECT * FROM mytable ORDER BY mycol ASC LIMIT -1 OFFSET 1` |
| MySQL | `SELECT * FROM tbl LIMIT 1, 18446744073709551615` |

Source: https://stackoverflow.com/a/70244586

### Expected behavior

Here is my Drizzle Query and Schema:

```ts
export const log = sqliteTable('log', {
id: text('id').primaryKey(),
message: text('message'),
createdAt: integer('created_at')
.default(sql`(cast(unixepoch('subsec') * 1000 as integer))`)
.notNull(),
});

await drizzle
.select({ id: log.id })
.from(log)
.orderBy(desc(log.createdAt))
.limit(-1)
.offset(50)
.all();
```

I expected it to generate SQL like this:

```sql
select
"id"
from
"log"
order by
"log"."created_at" desc
limit
-1
offset
50;
```

What I actual got was this:

```sql
select
"id"
from
"log"
order by
"log"."created_at" desc
offset
50;
```

Note that in SQLite, it is a syntax error to use `offset` without `limit` clause. So SQLite throws a syntax error like this:

```txt
Parse error: near "offset": syntax error
" from "log" order by "log"."created_at" desc offset 50;
error here ---^
```

### Environment & setup

_No response_

Contributor guide

Open the contributing guide

Research direction

Reproduce the SQLite query using `.limit(-1).offset(50)` and compare it with the generated SQL shown in the issue. Trace the SQLite query-generation entry point for limit and offset handling; done means the negative limit is preserved so SQLite receives a valid LIMIT/OFFSET query.

Written by the indexing model from the issue text.

Assessment

Tech stack
sqlite, typescript
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.