Better-sqlite3 BigInt基本类型

来自泡泡学习笔记
跳到导航 跳到搜索

SQLite3 可以存储64位有符号整数,这用 JavaScript 的 number format 无法完全表示。为了支持这种数据类型,better-sqlite3BigInts 完全兼容。

const big = BigInt('1152735103331642317');
big === 1152735103331642317n; // 返回 true
big.toString(); // 返回 "1152735103331642317"
typeof big; // 返回 "bigint"


绑定 BigInts

BigInts 可以像普通数字一样绑定到 Statements。您还可以从用户自定义函数中返回 BigInts。但是,如果您提供的 BigInt 太大而无法成为64位有符号整数,您将获得错误,从而保护数据完整性。

db.prepare("SELECT * FROM users WHERE id=?").get(BigInt('1152735103331642317'));
db.prepare("INSERT INTO users (id) VALUES (?)").run(BigInt('1152735103331642317'));

db.prepare("SELECT ?").get(2n ** 63n - 1n); // 成功返回
db.prepare("SELECT ?").get(2n ** 63n); // 抛出 RangeError


从数据库获取 BigInts

默认情况下,从数据库返回的整数(包括 info.lastInsertRowid 属性)是普通的 JavaScript 数字。您可以随意更改此默认设置:

db.defaultSafeIntegers(); // 默认为 BigInts
db.defaultSafeIntegers(true); // 默认为 BigInts
db.defaultSafeIntegers(false); // 默认为 Numbers


此外,您可以像下面这样覆盖单个 Statements 的默认设置:

const stmt = db.prepare(SQL);

stmt.safeIntegers(); // 开启安全整数
stmt.safeIntegers(true); // 开启安全整数
stmt.safeIntegers(false); // 关闭安全整数


用户自定义函数可以接收 BigInts 作为参数。您可以像这样覆盖数据库的默认设置:

db.function('isInt', { safeIntegers: true }, (value) => {
  return String(typeof value === 'bigint');
});

db.prepare('SELECT isInt(?)').pluck().get(10); // => "false"
db.prepare('SELECT isInt(?)').pluck().get(10n); // => "true"


同样,用户自定义聚合和虚拟表也可以接收 BigInts 作为参数:

db.aggregate('addInts', {
  safeIntegers: true,
  start: 0n,
  step: (total, nextValue) => total + nextValue,
});


db.table('sequence', {
  safeIntegers: true,
  columns: ['value'],
  parameters: ['length', 'start'],
  rows: function* (length, start = 0n) {
    const end = start + length;
    for (let n = start; n < end; ++n) {
      yield { value: n };
    }
  },
});


值得注意的是,从数据库返回的 REAL(FLOAT)值始终表示为普通数字。