current commit
261016.6 · test: move large SQLite string cases to pummel
'use strict';

const { enoughTestMem, skipIfSQLiteMissing } = require('../common');
skipIfSQLiteMissing();
const { Database, constants: { SQLITE_OK } } = require('node:sqlite');
const { constants } = require('node:buffer');
const { suite, test } = require('node:test');

// These queries allocate strings and blobs of several hundred megabytes.
// Run them separately from the ordinary statement tests.
suite('values larger than the maximum string length', { skip: !enoughTestMem }, () => {
  // hex() doubles its input, so this is the smallest blob whose text form
  // exceeds what V8 can hold in a string.
  const blobSize = (constants.MAX_STRING_LENGTH >>> 1) + 1;
  // '\u20ac' is 1 UTF-16 code unit but 3 UTF-8 bytes, so this identifier is a
  // valid JS string whose UTF-8 form exceeds the limit.
  const longIdentifier = '\u20ac'.repeat(Math.ceil(constants.MAX_STRING_LENGTH / 3) + 10);
  const tooLong = { code: 'ERR_STRING_TOO_LONG', name: 'Error' };

  test('get() throws instead of returning undefined', (t) => {
    using db = new Database(':memory:');
    using stmt = db.prepare('SELECT hex(zeroblob(?))');
    t.assert.throws(() => {
      stmt.get(blobSize);
    }, tooLong);
  });

  test('prepare() throws when the SQLite error message is too long', (t) => {
    using db = new Database(':memory:');
    // SQLite repeats the identifier in the error.
    t.assert.throws(() => {
      db.prepare(`SELECT 1 FROM "${longIdentifier}"`);
    }, tooLong);
  });

  test('prepare() throws for an oversized authorizer argument', (t) => {
    using db = new Database(':memory:');
    db.setAuthorizer(() => SQLITE_OK);
    t.assert.throws(() => db.prepare(`CREATE TABLE "${longIdentifier}" (x)`), tooLong);
  });

  test('columns() throws for an oversized declared type', (t) => {
    using db = new Database(':memory:');
    db.exec(`CREATE TABLE t (x "${longIdentifier}")`);
    using stmt = db.prepare('SELECT x FROM t');
    t.assert.throws(() => stmt.columns(), tooLong);
  });

  test('exec() surfaces the error from a user-defined function', (t) => {
    using db = new Database(':memory:');
    db.exec('CREATE TABLE data(val TEXT)');
    db.function('identity', (val) => val);

    t.assert.throws(() => {
      db.exec(`INSERT INTO data (val) VALUES (identity(hex(zeroblob(${blobSize}))))`);
    }, tooLong);
    using stmt = db.prepare('SELECT count(*) AS count FROM data');
    t.assert.deepStrictEqual(stmt.get(), { __proto__: null, count: 0 });
  });
});