Skip to content

Offset without limit fails on SQLite: LIMIT 18446744073709551615 is out of range #42

Open

Description

@simon-mundy

A Select with an offset and no limit fails on SQLite with General error: 20 datatype mismatch.

Cause

When only an offset is set, SelectDecorator::localizeVariables() replaces the LIMIT specification with a hard-coded MySQL value:

$this->setSpecification(self::LIMIT, 'LIMIT 18446744073709551615');

if ($this->limit === null && $this->offset !== null) {
    $this->setSpecification(self::LIMIT, 'LIMIT 18446744073709551615');
}

18446744073709551615 is 2^64 − 1, MySQL's documented "no limit" value. SQLite's LIMIT takes a signed 64-bit integer, so the number does not fit and SQLite rejects it.

Reproduction

Plain PDO, SQLite 3.53.4, PHP 8.3:

$pdo = new PDO('sqlite::memory:');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('CREATE TABLE t (id INTEGER)');
$pdo->exec('INSERT INTO t VALUES (1), (2), (3)');

$pdo->query('SELECT id FROM t LIMIT 18446744073709551615 OFFSET 1');
// SQLSTATE[HY000]: General error: 20 datatype mismatch

$pdo->query('SELECT id FROM t LIMIT -1 OFFSET 1')->fetchAll(PDO::FETCH_COLUMN);
// [2, 3]

Binding the value as a parameter gives the same error.

Suggested fix

Use SQLite's own idiom for "no limit", LIMIT -1, as documented in the SQLite SELECT documentation: "If the LIMIT expression evaluates to a negative value, then there is no upper bound on the number of rows returned". Add an integration test that runs an offset-only Select against a real SQLite database. The existing unit tests only compare SQL strings, so they did not catch this.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions