Skip to content

Commit 5ce0c23

Browse files
author
Daniele Briggi
committed
feat(bigInt): support to 64 bit integers
1 parent 8276aab commit 5ce0c23

17 files changed

+171
-41
lines changed

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11

2+
# support to 64bit integers: number, bigint or mixed
3+
SAFE_INTEGER_MODE=number
4+
25
# chinook database used in non-destructive tests
36
CHINOOK_DATABASE_URL="sqlitecloud://user:password@xxx.sqlite.cloud:8860/chinook.sqlite"
47

lib/drivers/protocol.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { SQLiteCloudCommand, type SQLCloudRowsetMetadata, type SQLiteCloudDataTypes } from './types';
21
import { SQLiteCloudRowset } from './rowset';
2+
import { SQLiteCloudCommand, type SQLCloudRowsetMetadata, type SQLiteCloudDataTypes } from './types';
33
import { Buffer } from 'buffer';
44
export declare const CMD_STRING = "+";
55
export declare const CMD_ZEROSTRING = "!";

lib/drivers/protocol.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ exports.bufferEndsWith = bufferEndsWith;
1515
exports.parseRowsetChunks = parseRowsetChunks;
1616
exports.popData = popData;
1717
exports.formatCommand = formatCommand;
18-
const types_1 = require("./types");
1918
const rowset_1 = require("./rowset");
19+
const types_1 = require("./types");
2020
// explicitly importing buffer library to allow cross-platform support by replacing it
2121
const buffer_1 = require("buffer");
2222
// https://www.npmjs.com/package/lz4js
@@ -272,7 +272,17 @@ function popData(buffer) {
272272
// console.debug(`popData - dataType: ${dataType}, spaceIndex: ${spaceIndex}, commandLength: ${commandLength}, commandEnd: ${commandEnd}`)
273273
switch (dataType) {
274274
case exports.CMD_INT:
275-
return popResults(parseInt(buffer.subarray(1, spaceIndex).toString()));
275+
// SQLite uses 64-bit INTEGER, but JS uses 53-bit Number
276+
const value = BigInt(buffer.subarray(1, spaceIndex).toString());
277+
if (types_1.SAFE_INTEGER_MODE === 'bigint') {
278+
return popResults(value);
279+
}
280+
if (types_1.SAFE_INTEGER_MODE === 'mixed') {
281+
if (value <= BigInt(Number.MIN_SAFE_INTEGER) || BigInt(Number.MAX_SAFE_INTEGER) <= value) {
282+
return popResults(value);
283+
}
284+
}
285+
return popResults(Number(value));
276286
case exports.CMD_FLOAT:
277287
return popResults(parseFloat(buffer.subarray(1, spaceIndex).toString()));
278288
case exports.CMD_NULL:
@@ -342,6 +352,9 @@ function serializeData(data, zeroString = false) {
342352
return buffer_1.Buffer.from(`${exports.CMD_FLOAT}${data} `);
343353
}
344354
}
355+
if (typeof data === 'bigint') {
356+
return buffer_1.Buffer.from(`${exports.CMD_INT}${data} `);
357+
}
345358
if (buffer_1.Buffer.isBuffer(data)) {
346359
const header = `${exports.CMD_BLOB}${data.byteLength} `;
347360
return buffer_1.Buffer.concat([buffer_1.Buffer.from(header), data]);

lib/drivers/types.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ import tls from 'tls';
66
export declare const DEFAULT_TIMEOUT: number;
77
/** Default tls connection port */
88
export declare const DEFAULT_PORT = 8860;
9+
/**
10+
* Support to SQLite 64bit integer
11+
*
12+
* number - (default) always return Number type (max: 2^53 - 1)
13+
* Precision is lost when selecting greater numbers from SQLite
14+
* bigint - always return BigInt type (max: 2^63 - 1) for all numbers from SQLite
15+
* (inlcuding `lastID` from WRITE statements)
16+
* mixed - use BigInt and Number types depending on the value size
17+
*/
18+
export declare const SAFE_INTEGER_MODE: string | undefined;
919
/**
1020
* Configuration for SQLite cloud connection
1121
* @note Options are all lowecase so they 1:1 compatible with C SDK

lib/drivers/types.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,29 @@
22
/**
33
* types.ts - shared types and interfaces
44
*/
5+
var _a;
56
Object.defineProperty(exports, "__esModule", { value: true });
6-
exports.SQLiteCloudArrayType = exports.SQLiteCloudError = exports.DEFAULT_PORT = exports.DEFAULT_TIMEOUT = void 0;
7+
exports.SQLiteCloudArrayType = exports.SQLiteCloudError = exports.SAFE_INTEGER_MODE = exports.DEFAULT_PORT = exports.DEFAULT_TIMEOUT = void 0;
78
/** Default timeout value for queries */
89
exports.DEFAULT_TIMEOUT = 300 * 1000;
910
/** Default tls connection port */
1011
exports.DEFAULT_PORT = 8860;
12+
/**
13+
* Support to SQLite 64bit integer
14+
*
15+
* number - (default) always return Number type (max: 2^53 - 1)
16+
* Precision is lost when selecting greater numbers from SQLite
17+
* bigint - always return BigInt type (max: 2^63 - 1) for all numbers from SQLite
18+
* (inlcuding `lastID` from WRITE statements)
19+
* mixed - use BigInt and Number types depending on the value size
20+
*/
21+
exports.SAFE_INTEGER_MODE = (_a = process.env['SAFE_INTEGER_MODE']) === null || _a === void 0 ? void 0 : _a.toLowerCase();
22+
if (exports.SAFE_INTEGER_MODE == 'bigint') {
23+
console.debug('BigInt mode: Using Number for all INTEGER values from SQLite, including meta information from WRITE statements.');
24+
}
25+
if (exports.SAFE_INTEGER_MODE == 'mixed') {
26+
console.debug('Mixed mode: Using BigInt for INTEGER values from SQLite (including meta information from WRITE statements) bigger then 2^53, Number otherwise.');
27+
}
1128
/** Custom error reported by SQLiteCloud drivers */
1229
class SQLiteCloudError extends Error {
1330
constructor(message, args) {

lib/drivers/utilities.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,12 @@ function getUpdateResults(results) {
106106
switch (results[0]) {
107107
case types_1.SQLiteCloudArrayType.ARRAY_TYPE_SQLITE_EXEC:
108108
return {
109-
type: results[0],
110-
index: results[1],
109+
type: Number(results[0]),
110+
index: Number(results[1]),
111111
lastID: results[2], // ROWID (sqlite3_last_insert_rowid)
112112
changes: results[3], // CHANGES(sqlite3_changes)
113113
totalChanges: results[4], // TOTAL_CHANGES (sqlite3_total_changes)
114-
finalized: results[5], // FINALIZED
115-
//
114+
finalized: Number(results[5]), // FINALIZED
116115
rowId: results[2] // same as lastId
117116
};
118117
}

lib/sqlitecloud.drivers.dev.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/sqlitecloud.drivers.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@sqlitecloud/drivers",
3-
"version": "1.0.494",
3+
"version": "1.0.505",
44
"description": "SQLiteCloud drivers for Typescript/Javascript in edge, web and node clients",
55
"main": "./lib/index.js",
66
"types": "./lib/index.d.ts",

0 commit comments

Comments
 (0)