Description
What is the problem this feature would solve?
I'd like to propose an option for the sqlite API to go beyond the current 32-bit limit that is currently imposed on SELECT queries.
Background: Current API truncates integers to 32-bits when selecting (see below). Can be worked around by CASTing to REAL or TEXT (see below). Proposal objective: eliminate the CAST()
.
import { Database, constants } from "bun:sqlite";
const db = Database.open(":memory:");
db.exec("CREATE TABLE Test ( x INTEGER )")
const insert = db.prepare("INSERT INTO Test (x) VALUES (?)");
insert.run([2147483647]);
insert.run([2147483648]);
insert.run([2147483649]);
console.log(db.prepare("SELECT x FROM Test").all());
// >>>
// Actual: [ { x: 2147483647 }, { x: -2147483648 }, { x: -2147483647 } ]
// Desired: [ { x: 2147483647 }, { x: 2147483648 }, { x: 2147483649 } ]
console.log(db.prepare("SELECT CAST(x AS REAL) x FROM Test").all());
// >>>
// Got and expected (all good): [ { x: 2147483647 }, { x: 2147483648 }, { x: 2147483649 } ]
A common use case (for me): storage of epoch time values in milliseconds, which requires ~41-bits. The intended benefit of this proposal is that it would eliminate the need make query or schema alterations, helping to decouple runtime details of this API from sqlite.
What is the feature you are proposing to solve the problem?
An additional option is proposed to control integer conversion, perhaps as follows,
Choice | Behavior | Range |
---|---|---|
AS_INT32 | Select out as truncated to 32-bits (current behavior) | 32-bits (signed) |
AS_REAL | Select out as a double | + or - 53 bits (i.e. Number.MAX_SAFE_INTEGER / Number.MIN_SAFE_INTEGER ) |
AS_BIGINT | Select out as a 64-bit int, and assign to a JavaScript BigInt | 64-bits (signed) |
Examples of the concept:
const db = Database.open(":memory:", {
integerMode: constants.AS_INT32 | constants.AS_REAL | constants.AS_BIGINT });
// or, at query level:
const stmt = db.prepare("SELECT x FROM Test", {
integerMode: constants.AS_INT32 | constants.AS_REAL | constants.AS_BIGINT });
Relevant lines ultimately impacted by this option are found in constructResultObject()
and constructResultRow()
:
bun/src/bun.js/bindings/sqlite/JSSQLStatement.cpp
Lines 994 to 997 in a251669
bun/src/bun.js/bindings/sqlite/JSSQLStatement.cpp
Lines 1044 to 1047 in a251669
What alternatives have you considered?
Workarounds are possible:
- Use
REAL
typed columns in the schema. Or, CAST()
toREAL
. Or,CAST()
toTEXT
. And convert result to a BigInt in application code. (If up to the 64-bits is actually needed.)