Socket
Socket
Sign inDemoInstall

better-sqlite3

Package Overview
Dependencies
Maintainers
1
Versions
129
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

better-sqlite3 - npm Package Compare versions

Comparing version 5.0.1 to 5.2.0

test/25.statement.columns.js

9

benchmark/benchmark.js

@@ -22,6 +22,11 @@ #!/usr/bin/env node

const ctx = JSON.parse(process.argv[2]);
const db = await require('./drivers').get(ctx.driver)(ctx.filename, ctx.pragma);
const fn = require(`./types/${ctx.type}`)[ctx.driver](db, ctx);
const type = require(`./types/${ctx.type}`);
const db = await require('./drivers').get(ctx.driver)('../temp/benchmark.db', ctx.pragma);
if (!type.readonly) {
for (const table of ctx.tables) await db.exec(`DELETE FROM ${table} WHERE rowid > 1;`);
await db.exec('VACUUM;');
}
const fn = type[ctx.driver](db, ctx);
if (typeof fn === 'function') setImmediate(sync, fn);
else setImmediate(async, await fn);
})();

@@ -9,3 +9,3 @@ #!/usr/bin/env node

if (!searchTerms.length) return require('./trials').default;
// With command-line arguments, the user can run specific groups of trials.

@@ -19,3 +19,2 @@ return require('./trials').searchable.filter(filterBySearchTerms(searchTerms));

trial.table,
trial.table.replace('_empty', ''),
`(${trial.columns.join(', ')})`,

@@ -29,2 +28,10 @@ `(${trial.columns.join(',')})`,

const sortTrials = (a, b) => {
const aRo = require(`./types/${a.type}`).readonly;
const bRo = require(`./types/${b.type}`).readonly;
if (typeof aRo !== 'boolean') throw new TypeError(`Missing readonly export in benchmark type ${a.type}`);
if (typeof bRo !== 'boolean') throw new TypeError(`Missing readonly export in benchmark type ${b.type}`);
return bRo - aRo;
};
const displayTrialName = (trial) => {

@@ -39,4 +46,3 @@ if (trial.description) return console.log(clc.magenta(`--- ${trial.description} ---`));

const { data: _unused, ...tableInfo } = tables.get(trial.table);
const ctx = { ...trial, ...tableInfo, driver, filename: `../temp/${iteration++}.db` };
return JSON.stringify(ctx);
return JSON.stringify({ ...trial, ...tableInfo, driver, tables: [...tables.keys()] });
};

@@ -50,3 +56,3 @@

process.chdir(__dirname);
const trials = getTrials(process.argv.slice(2));
const trials = getTrials(process.argv.slice(2)).sort(sortTrials);
if (!trials.length) {

@@ -57,10 +63,9 @@ console.log(clc.yellow('No matching benchmarks found!'));

// Create the temporary databases needed to run the benchmark trials.
// Create the temporary database needed to run the benchmark trials.
console.log('Generating tables...');
const drivers = require('./drivers');
const tables = require('./seed')(drivers.size * trials.length);
const tables = require('./seed')();
process.stdout.write(erase());
// Execute each trial for each available driver.
let iteration = 0;
const drivers = require('./drivers');
const nameLength = [...drivers.keys()].reduce((m, d) => Math.max(m, d.length), 0);

@@ -67,0 +72,0 @@ for (const trial of trials) {

@@ -11,25 +11,20 @@ 'use strict';

}],
['small_empty', {
schema: '(nul, integer INTEGER, real REAL, text TEXT, blob BLOB)',
data: [null, 0x7fffffff, 1 / 3, 'this is the text', Buffer.from('this is the blob')],
count: 1,
['large_text', {
schema: '(text TEXT)',
data: ['this is the text'.repeat(2048)],
count: 10000,
}],
['large', {
schema: '(text TEXT, blob BLOB)',
data: ['this is the text'.repeat(2048), Buffer.from('this is the blob'.repeat(2048))],
['large_blob', {
schema: '(blob BLOB)',
data: [Buffer.from('this is the blob'.repeat(2048))],
count: 10000,
}],
['large_empty', {
schema: '(text TEXT, blob BLOB)',
data: ['this is the text'.repeat(2048), Buffer.from('this is the blob'.repeat(2048))],
count: 1,
}],
]);
/*
This function creates a number of pre-populated databases that are deleted
when the process exits.
This function creates a pre-populated database that is deleted when the
process exits.
*/
module.exports = (numberOfDatabases = 2) => {
module.exports = () => {
const tempDir = path.join(__dirname, '..', 'temp');

@@ -39,7 +34,7 @@ process.on('exit', () => fs.removeSync(tempDir));

fs.ensureDirSync(tempDir);
const db = require('../.')(path.join(tempDir, '0.db'));
const db = require('../.')(path.join(tempDir, 'benchmark.db'));
db.pragma('journal_mode = OFF');
db.pragma('synchronous = OFF');
for (const [name, ctx] of tables.entries()) {

@@ -51,6 +46,5 @@ db.exec(`CREATE TABLE ${name} ${ctx.schema}`);

}
db.close();
for (let i = 1; i < numberOfDatabases; ++i) fs.copySync(db.name, path.join(tempDir, `${i}.db`));
return tables;
};

@@ -10,5 +10,5 @@ 'use strict';

description: 'iterating over 100 rows' },
{ type: 'insert', table: 'small_empty', columns: ['nul', 'integer', 'real', 'text'],
{ type: 'insert', table: 'small', columns: ['nul', 'integer', 'real', 'text'],
description: 'inserting rows individually' },
{ type: 'transaction', table: 'small_empty', columns: ['nul', 'integer', 'real', 'text'],
{ type: 'transaction', table: 'small', columns: ['nul', 'integer', 'real', 'text'],
description: 'inserting 100 rows in a single transaction' },

@@ -23,4 +23,4 @@ ];

{ type: 'select', table: 'small', columns: ['blob'] },
{ type: 'select', table: 'large', columns: ['text'] },
{ type: 'select', table: 'large', columns: ['blob'] },
{ type: 'select', table: 'large_text', columns: ['text'] },
{ type: 'select', table: 'large_blob', columns: ['blob'] },
{ type: 'select-all', table: 'small', columns: ['nul'] },

@@ -31,4 +31,4 @@ { type: 'select-all', table: 'small', columns: ['integer'] },

{ type: 'select-all', table: 'small', columns: ['blob'] },
{ type: 'select-all', table: 'large', columns: ['text'] },
{ type: 'select-all', table: 'large', columns: ['blob'] },
{ type: 'select-all', table: 'large_text', columns: ['text'] },
{ type: 'select-all', table: 'large_blob', columns: ['blob'] },
{ type: 'select-iterate', table: 'small', columns: ['nul'] },

@@ -39,18 +39,18 @@ { type: 'select-iterate', table: 'small', columns: ['integer'] },

{ type: 'select-iterate', table: 'small', columns: ['blob'] },
{ type: 'select-iterate', table: 'large', columns: ['text'] },
{ type: 'select-iterate', table: 'large', columns: ['blob'] },
{ type: 'insert', table: 'small_empty', columns: ['nul'] },
{ type: 'insert', table: 'small_empty', columns: ['integer'] },
{ type: 'insert', table: 'small_empty', columns: ['real'] },
{ type: 'insert', table: 'small_empty', columns: ['text'] },
{ type: 'insert', table: 'small_empty', columns: ['blob'] },
{ type: 'insert', table: 'large_empty', columns: ['text'] },
{ type: 'insert', table: 'large_empty', columns: ['blob'] },
{ type: 'transaction', table: 'small_empty', columns: ['nul'] },
{ type: 'transaction', table: 'small_empty', columns: ['integer'] },
{ type: 'transaction', table: 'small_empty', columns: ['real'] },
{ type: 'transaction', table: 'small_empty', columns: ['text'] },
{ type: 'transaction', table: 'small_empty', columns: ['blob'] },
{ type: 'transaction', table: 'large_empty', columns: ['text'] },
{ type: 'transaction', table: 'large_empty', columns: ['blob'] },
{ type: 'select-iterate', table: 'large_text', columns: ['text'] },
{ type: 'select-iterate', table: 'large_blob', columns: ['blob'] },
{ type: 'insert', table: 'small', columns: ['nul'] },
{ type: 'insert', table: 'small', columns: ['integer'] },
{ type: 'insert', table: 'small', columns: ['real'] },
{ type: 'insert', table: 'small', columns: ['text'] },
{ type: 'insert', table: 'small', columns: ['blob'] },
{ type: 'insert', table: 'large_text', columns: ['text'] },
{ type: 'insert', table: 'large_blob', columns: ['blob'] },
{ type: 'transaction', table: 'small', columns: ['nul'] },
{ type: 'transaction', table: 'small', columns: ['integer'] },
{ type: 'transaction', table: 'small', columns: ['real'] },
{ type: 'transaction', table: 'small', columns: ['text'] },
{ type: 'transaction', table: 'small', columns: ['blob'] },
{ type: 'transaction', table: 'large_text', columns: ['text'] },
{ type: 'transaction', table: 'large_blob', columns: ['blob'] },
];

@@ -57,0 +57,0 @@

'use strict';
// Inserting rows individually (`.run()`)
exports.readonly = false; // Inserting rows individually (`.run()`)

@@ -4,0 +4,0 @@ exports['better-sqlite3'] = (db, { table, columns }) => {

'use strict';
// Reading 100 rows into an array (`.all()`)
exports.readonly = true; // Reading 100 rows into an array (`.all()`)

@@ -4,0 +4,0 @@ exports['better-sqlite3'] = (db, { table, columns, count }) => {

'use strict';
// Iterating over 100 rows (`.iterate()`)
exports.readonly = true; // Iterating over 100 rows (`.iterate()`)

@@ -4,0 +4,0 @@ exports['better-sqlite3'] = (db, { table, columns, count }) => {

'use strict';
// Reading rows individually (`.get()`)
exports.readonly = true; // Reading rows individually (`.get()`)

@@ -4,0 +4,0 @@ exports['better-sqlite3'] = (db, { table, columns, count }) => {

'use strict';
// Inserting 100 rows in a single transaction
exports.readonly = false; // Inserting 100 rows in a single transaction

@@ -13,3 +13,3 @@ exports['better-sqlite3'] = (db, { table, columns }) => {

exports['node-sqlite3'] = async (db, { table, columns, driver, filename, pragma }) => {
exports['node-sqlite3'] = async (db, { table, columns, driver, pragma }) => {
const sql = `INSERT INTO ${table} (${columns.join(', ')}) VALUES (${columns.map(x => '@' + x).join(', ')})`;

@@ -26,3 +26,3 @@ const row = Object.assign({}, ...Object.entries(await db.get(`SELECT * FROM ${table} LIMIT 1`))

*/
return () => open(filename, pragma).then(async (db) => {
return () => open('../temp/benchmark.db', pragma).then(async (db) => {
try {

@@ -29,0 +29,0 @@ await db.run('BEGIN');

@@ -86,3 +86,3 @@ # API

Transaction functions do not work with async functions. Technically speaking, async functions always return immediately, which means the transaction will already be committed before any code executes. Also, because SQLite3 serializes all transactions, it's generally a very bad idea to keep a transaction open across event loop ticks anyways.
Transaction functions do not work with async functions. Technically speaking, async functions always return after the first `await`, which means the transaction will already be committed before any async code executes. Also, because SQLite3 serializes all transactions, it's generally a very bad idea to keep a transaction open across event loop ticks anyways.

@@ -261,2 +261,4 @@ It's important to know that SQLite3 may sometimes rollback a transaction without us asking it to. This can happen either because of an [`ON CONFLICT`](https://sqlite.org/lang_conflict.html) clause, the [`RAISE()`](https://www.sqlite.org/lang_createtrigger.html) trigger function, or certain errors such as `SQLITE_FULL` or `SQLITE_BUSY`. When this occurs, transaction functions will automatically detect the situation and handle it appropriately. However, if you catch one of these errors with a try-catch statement, you become responsible for handling the case. In other words, all catch statements within transaction functions should look like this:

- [Statement#expand()](#expandtogglestate---this)
- [Statement#raw()](#rawtogglestate---this)
- [Statement#columns()](#columns---array-of-objects)
- [Statement#bind()](#bindbindparameters---this)

@@ -354,3 +356,3 @@ - [Properties](#properties-1)

> When plucking is turned on, [expansion](#expandtogglestate---this) is turned off (they are mutually exclusive options).
> When plucking is turned on, [expansion](#expandtogglestate---this) and [raw mode](#rawtogglestate---this) are turned off (they are mutually exclusive options).

@@ -371,4 +373,55 @@ ### .expand([toggleState]) -> *this*

> When expansion is turned on, [plucking](#plucktogglestate---this) is turned off (they are mutually exclusive options).
> When expansion is turned on, [plucking](#plucktogglestate---this) and [raw mode](#rawtogglestate---this) are turned off (they are mutually exclusive options).
### .raw([toggleState]) -> *this*
**(only on statements that return data)*
Causes the prepared statement to return rows as arrays instead of objects. This is primarily used as a performance optimization when retrieving a very high number of rows. Column names can be recovered by using the [`.columns()`](#columns---array-of-objects) method.
You can toggle this on/off as you please:
```js
stmt.raw(); // raw mode ON
stmt.raw(true); // raw mode ON
stmt.raw(false); // raw mode OFF
```
> When raw mode is turned on, [plucking](#plucktogglestate---this) and [expansion](#expandtogglestate---this) are turned off (they are mutually exclusive options).
### .columns() -> *array of objects*
**(only on statements that return data)*
Provides introspection of the prepared statement's result columns. This method is primarily used in conjunction with [raw mode](#rawtogglestate---this). It returns an array of objects, where each object represents a result column of the prepared statement. Each object has the following properties:
- `.name`: the name (or alias) of the result column.
- `.column`: the name of the originating table column, or `null` if it's an expression or subquery.
- `.table`: the name of the originating table, or `null` if it's an expression or subquery.
- `.database`: the name of the originating database, or `null` if it's an
expression or subquery.
- `.type`: the name of the [declared type](https://www.sqlite.org/datatype3.html#determination_of_column_affinity), or `null` if it's an expression or subquery.
```js
const fs = require('fs');
function* toRows(stmt) {
yield stmt.columns().map(column => column.name);
yield* stmt.raw().iterate();
}
function writeToCSV(filename, stmt) {
return new Promise((resolve, reject) => {
const stream = fs.createWriteStream(filename);
for (const row of toRows(stmt)) {
stream.write(row.join(',') + '\n');
}
stream.on('error', reject);
stream.end(resolve);
});
}
```
> When a table's schema is altered, the result columns of existing prepared statements can also change. However, such changes will not be reflected by this method until the prepared statement is re-executed. For this reason, it's perhaps better to invoke `.columns()` _after_ `.get()`, `.all()`, or `.iterate()`.
### .bind([*...bindParameters*]) -> *this*

@@ -375,0 +428,0 @@

@@ -13,3 +13,3 @@ # Custom configuration

By default, this distribution currently uses SQLite3 **version 3.25.2** with the following [compilation options](https://www.sqlite.org/compile.html):
By default, this distribution currently uses SQLite3 **version 3.26.0** with the following [compilation options](https://www.sqlite.org/compile.html):

@@ -16,0 +16,0 @@ ```

@@ -36,2 +36,1 @@ # Helpful tips for SQLite3

- `CASCADE`: if the parent row is deleted, the child row is deleted; if the parent column is updated, the new value is propogated to the child column.

@@ -9,3 +9,3 @@ 'use strict';

if (!name) throw new TypeError('User-defined function name cannot be an empty string');
const start = 'start' in options ? options.start : null;

@@ -19,3 +19,3 @@ const step = getFunctionOption(options, 'step', true);

let argCount = -1;
if (!varargs) {

@@ -26,3 +26,3 @@ argCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);

}
return createAggregate.call(this, start, step, inverse, result, name, argCount, safeIntegers, deterministic);

@@ -29,0 +29,0 @@ };

@@ -11,3 +11,3 @@ 'use strict';

if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
let filename = filenameGiven.trim();

@@ -17,3 +17,3 @@ if (!filename) throw new TypeError('Database filename cannot be an empty string');

if ('readOnly' in options) throw new TypeError('Misspelled option "readOnly" should be "readonly"');
const anonymous = filename === ':memory:';

@@ -24,3 +24,3 @@ const memory = util.getBooleanOption(options, 'memory');

const timeout = 'timeout' in options ? options.timeout : 5000;
if (readonly && (memory || anonymous)) throw new TypeError('In-memory databases cannot be readonly');

@@ -30,7 +30,7 @@ if (anonymous && !memory && 'memory' in options) throw new TypeError('Option "memory" conflicts with :memory: filename');

if (timeout > 0x7fffffff) throw new RangeError('Option "timeout" cannot be greater than 2147483647');
if (!memory && !anonymous && !fs.existsSync(path.dirname(filename))) {
throw new TypeError('Cannot open database because the directory does not exist');
}
if (memory && !anonymous) {

@@ -37,0 +37,0 @@ if (process.platform === 'win32') {

@@ -12,3 +12,3 @@ 'use strict';

if (!name) throw new TypeError('User-defined function name cannot be an empty string');
const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;

@@ -18,3 +18,3 @@ const deterministic = getBooleanOption(options, 'deterministic');

let argCount = -1;
if (!varargs) {

@@ -25,5 +25,5 @@ argCount = fn.length;

}
return createFunction.call(this, fn, name, argCount, safeIntegers, deterministic);
};
};

@@ -10,3 +10,3 @@ 'use strict';

const simple = getBooleanOption(options, 'simple');
setPragmaMode.call(this, true);

@@ -13,0 +13,0 @@ try {

@@ -8,3 +8,3 @@ 'use strict';

const { apply } = Function.prototype;
const properties = {

@@ -17,3 +17,3 @@ default: { value: wrapTransaction(apply, fn, this, controller.default) },

};
Object.defineProperties(properties.default.value, properties);

@@ -23,3 +23,3 @@ Object.defineProperties(properties.deferred.value, properties);

Object.defineProperties(properties.exclusive.value, properties);
return properties.default.value;

@@ -26,0 +26,0 @@ };

{
"name": "better-sqlite3",
"version": "5.0.1",
"version": "5.2.0",
"description": "The fastest and simplest library for SQLite3 in Node.js.",

@@ -5,0 +5,0 @@ "homepage": "http://github.com/JoshuaWise/better-sqlite3",

@@ -51,3 +51,3 @@ # better-sqlite3 [![Build Status](https://travis-ci.org/JoshuaWise/better-sqlite3.svg?branch=master)](https://travis-ci.org/JoshuaWise/better-sqlite3)

- If you expect a high volume of concurrent reads each returning hundreds of megabytes of data (i.e., videos)
- If you expect a high volume of concurrent reads each returning many megabytes of data (i.e., videos)
- If you expect a high volume of concurrent writes (i.e., a social media site)

@@ -54,0 +54,0 @@ - If your database's size is near the terabyte range

@@ -29,11 +29,10 @@ 'use strict';

});
it('should allow disk-bound databases to be created', function () {
expect(existsSync(util.next())).to.be.false;
const db = Database(util.current());
expect(db.name).to.equal(util.current());
expect(db.memory).to.be.false;
it('should allow anonymous in-memory databases to be created', function () {
const db = new Database(':memory:');
expect(db.name).to.equal(':memory:');
expect(db.memory).to.be.true;
expect(db.readonly).to.be.false;
expect(db.open).to.be.true;
expect(db.inTransaction).to.be.false;
expect(existsSync(util.current())).to.be.true;
expect(existsSync(':memory:')).to.be.false;
});

@@ -50,10 +49,11 @@ it('should allow named in-memory databases to be created', function () {

});
it('should allow anonymous in-memory databases to be created', function () {
const db = new Database(':memory:');
expect(db.name).to.equal(':memory:');
expect(db.memory).to.be.true;
it('should allow disk-bound databases to be created', function () {
expect(existsSync(util.next())).to.be.false;
const db = Database(util.current());
expect(db.name).to.equal(util.current());
expect(db.memory).to.be.false;
expect(db.readonly).to.be.false;
expect(db.open).to.be.true;
expect(db.inTransaction).to.be.false;
expect(existsSync(':memory:')).to.be.false;
expect(existsSync(util.current())).to.be.true;
});

@@ -60,0 +60,0 @@ it('should not allow conflicting in-memory options', function () {

@@ -12,3 +12,3 @@ 'use strict';

});
it('should cause db.open to return false', function () {

@@ -40,3 +40,3 @@ expect(this.db.open).to.be.true;

const stmt2 = this.db.prepare("INSERT INTO people VALUES ('foobar')");
this.db.prepare('SELECT * FROM people').bind();

@@ -48,5 +48,5 @@ this.db.prepare("INSERT INTO people VALUES ('foobar')").bind();

this.db.prepare("INSERT INTO people VALUES ('foobar')").run();
this.db.close();
expect(() => stmt1.bind()).to.throw(TypeError);

@@ -65,5 +65,5 @@ expect(() => stmt2.bind()).to.throw(TypeError);

expect(existsSync(`${util.current()}-wal`)).to.be.true;
this.db.close();
expect(existsSync(util.current())).to.be.true;

@@ -70,0 +70,0 @@ expect(existsSync(`${util.current()}-wal`)).to.be.false;

@@ -11,3 +11,3 @@ 'use strict';

});
it('should throw an exception if a string is not provided', function () {

@@ -14,0 +14,0 @@ expect(() => this.db.pragma(123)).to.throw(TypeError);

@@ -18,3 +18,3 @@ 'use strict';

};
it('should throw an exception if a string is not provided', function () {

@@ -21,0 +21,0 @@ expect(() => this.db.prepare(123)).to.throw(TypeError);

@@ -11,3 +11,3 @@ 'use strict';

});
it('should throw an exception if a string is not provided', function () {

@@ -31,11 +31,11 @@ expect(() => this.db.exec(123)).to.throw(TypeError);

const returnValues = [];
const r1 = this.db.exec('CREATE TABLE entries (a TEXT, b INTEGER)');
const r2 = this.db.exec("INSERT INTO entries VALUES ('foobar', 44); INSERT INTO entries VALUES ('baz', NULL);");
const r3 = this.db.exec('SELECT * FROM entries');
expect(r1).to.equal(this.db);
expect(r2).to.equal(this.db);
expect(r3).to.equal(this.db);
const rows = this.db.prepare('SELECT * FROM entries ORDER BY rowid').all();

@@ -42,0 +42,0 @@ expect(rows.length).to.equal(2);

@@ -21,3 +21,3 @@ 'use strict';

});
it('should throw an exception when used on a statement that returns data', function () {

@@ -43,7 +43,7 @@ const stmt = this.db.prepare('SELECT 555');

expect(info.lastInsertRowid).to.equal(1);
info = stmt.run();
expect(info.changes).to.equal(1);
expect(info.lastInsertRowid).to.equal(2);
stmt = this.db.prepare("INSERT INTO entries VALUES ('foo', 25, 3.14, x'1133ddff'), ('foo', 25, 3.14, x'1133ddff')");

@@ -61,3 +61,3 @@ info = stmt.run();

expect(stmt.run().changes).to.equal(3);
stmt = this.db.prepare("INSERT INTO entries VALUES ('foo', 25, 3.14, x'1133ddff')");

@@ -162,3 +162,3 @@ stmt.run();

).to.throw(TypeError);
// This part of the test may fail is Statement#get() does not work.

@@ -165,0 +165,0 @@ let i = 0;

@@ -13,3 +13,3 @@ 'use strict';

});
it('should throw an exception when used on a statement that returns no data', function () {

@@ -19,7 +19,7 @@ let stmt = this.db.prepare("INSERT INTO entries VALUES ('foo', 1, 3.14, x'dddddddd', NULL)");

expect(() => stmt.get()).to.throw(TypeError);
stmt = this.db.prepare("CREATE TABLE IF NOT EXISTS entries (a TEXT, b INTEGER, c REAL, d BLOB, e TEXT)");
expect(stmt.reader).to.be.false;
expect(() => stmt.get()).to.throw(TypeError);
stmt = this.db.prepare("BEGIN TRANSACTION");

@@ -33,3 +33,3 @@ expect(stmt.reader).to.be.false;

expect(stmt.get()).to.deep.equal({ a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xdd), e: null });
stmt = this.db.prepare("SELECT * FROM entries WHERE b > 5 ORDER BY rowid");

@@ -43,9 +43,10 @@ expect(stmt.get()).to.deep.equal({ a: 'foo', b: 6, c: 3.14, d: Buffer.alloc(4).fill(0xdd), e: null });

const plucked = expanded.entries.a;
const raw = Object.values(expanded.entries).concat(expanded.$.c);
expect(stmt.get()).to.deep.equal(row);
expect(stmt.pluck(true).get()).to.equal(plucked);
expect(stmt.get()).to.equal(plucked);
expect(stmt.pluck(true).get()).to.deep.equal(plucked);
expect(stmt.get()).to.deep.equal(plucked);
expect(stmt.pluck(false).get()).to.deep.equal(row);
expect(stmt.get()).to.deep.equal(row);
expect(stmt.pluck().get()).to.equal(plucked);
expect(stmt.get()).to.equal(plucked);
expect(stmt.pluck().get()).to.deep.equal(plucked);
expect(stmt.get()).to.deep.equal(plucked);
expect(stmt.expand().get()).to.deep.equal(expanded);

@@ -57,4 +58,12 @@ expect(stmt.get()).to.deep.equal(expanded);

expect(stmt.get()).to.deep.equal(expanded);
expect(stmt.pluck(true).get()).to.equal(plucked);
expect(stmt.get()).to.equal(plucked);
expect(stmt.pluck(true).get()).to.deep.equal(plucked);
expect(stmt.get()).to.deep.equal(plucked);
expect(stmt.raw().get()).to.deep.equal(raw);
expect(stmt.get()).to.deep.equal(raw);
expect(stmt.raw(false).get()).to.deep.equal(row);
expect(stmt.get()).to.deep.equal(row);
expect(stmt.raw(true).get()).to.deep.equal(raw);
expect(stmt.get()).to.deep.equal(raw);
expect(stmt.expand(true).get()).to.deep.equal(expanded);
expect(stmt.get()).to.deep.equal(expanded);
});

@@ -72,23 +81,23 @@ it('should return undefined when no rows were found', function () {

expect(result).to.deep.equal(row);
result = this.db.prepare(SQL1).get(['foo', 1, 3.14, Buffer.alloc(4).fill(0xdd), null]);
expect(result).to.deep.equal(row);
result = this.db.prepare(SQL1).get(['foo', 1], [3.14], Buffer.alloc(4).fill(0xdd), [,]);
expect(result).to.deep.equal(row);
result = this.db.prepare(SQL2).get({ a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xdd), e: undefined });
expect(result).to.deep.equal(row);
result = this.db.prepare(SQL2).get({ a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xaa), e: undefined });
expect(result).to.be.undefined;
expect(() =>
this.db.prepare(SQL2).get({ a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xdd) })
).to.throw(RangeError);
expect(() =>
this.db.prepare(SQL1).get()
).to.throw(RangeError);
expect(() =>

@@ -95,0 +104,0 @@ this.db.prepare(SQL2).get({})

@@ -13,3 +13,3 @@ 'use strict';

});
it('should throw an exception when used on a statement that returns no data', function () {

@@ -19,7 +19,7 @@ let stmt = this.db.prepare("INSERT INTO entries VALUES ('foo', 1, 3.14, x'dddddddd', NULL)");

expect(() => stmt.all()).to.throw(TypeError);
stmt = this.db.prepare("CREATE TABLE IF NOT EXISTS entries (a TEXT, b INTEGER, c REAL, d BLOB, e TEXT)");
expect(stmt.reader).to.be.false;
expect(() => stmt.all()).to.throw(TypeError);
stmt = this.db.prepare("BEGIN TRANSACTION");

@@ -31,10 +31,10 @@ expect(stmt.reader).to.be.false;

const row = { a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xdd), e: null };
let stmt = this.db.prepare("SELECT * FROM entries ORDER BY rowid");
expect(stmt.reader).to.be.true;
matchesFrom(stmt.all(), 1);
stmt = this.db.prepare("SELECT * FROM entries WHERE b > 5 ORDER BY rowid");
matchesFrom(stmt.all(), 6);
function matchesFrom(rows, i) {

@@ -57,2 +57,3 @@ let index = 0;

const plucked = expanded.map(x => x.entries.a);
const raw = expanded.map(x => Object.values(x.entries).concat(x.$.c))
expect(stmt.all()).to.deep.equal(rows);

@@ -73,2 +74,10 @@ expect(stmt.pluck(true).all()).to.deep.equal(plucked);

expect(stmt.all()).to.deep.equal(plucked);
expect(stmt.raw().all()).to.deep.equal(raw);
expect(stmt.all()).to.deep.equal(raw);
expect(stmt.raw(false).all()).to.deep.equal(rows);
expect(stmt.all()).to.deep.equal(rows);
expect(stmt.raw(true).all()).to.deep.equal(raw);
expect(stmt.all()).to.deep.equal(raw);
expect(stmt.expand(true).all()).to.deep.equal(expanded);
expect(stmt.all()).to.deep.equal(expanded);
});

@@ -86,23 +95,23 @@ it('should return an empty array when no rows were found', function () {

expect(result).to.deep.equal(rows);
result = this.db.prepare(SQL1).all(['foo', 1, 3.14, Buffer.alloc(4).fill(0xdd), null]);
expect(result).to.deep.equal(rows);
result = this.db.prepare(SQL1).all(['foo', 1], [3.14], Buffer.alloc(4).fill(0xdd), [,]);
expect(result).to.deep.equal(rows);
result = this.db.prepare(SQL2).all({ a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xdd), e: undefined });
expect(result).to.deep.equal(rows);
result = this.db.prepare(SQL2).all({ a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xaa), e: undefined });
expect(result).to.deep.equal([]);
expect(() =>
this.db.prepare(SQL2).all({ a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xdd) })
).to.throw(RangeError);
expect(() =>
this.db.prepare(SQL1).all()
).to.throw(RangeError);
expect(() =>

@@ -109,0 +118,0 @@ this.db.prepare(SQL2).all({})

@@ -7,3 +7,3 @@ 'use strict';

this.db = new Database(util.next());
this.db.prepare('CREATE TABLE entries (a TEXT, b INTEGER, c REAL, d BLOB, e TEXT)').run();
this.db.prepare("CREATE TABLE entries (a TEXT, b INTEGER, c REAL, d BLOB, e TEXT)").run();
this.db.prepare("INSERT INTO entries WITH RECURSIVE temp(a, b, c, d, e) AS (SELECT 'foo', 1, 3.14, x'dddddddd', NULL UNION ALL SELECT a, b + 1, c, d, e FROM temp LIMIT 10) SELECT * FROM temp").run();

@@ -14,3 +14,3 @@ });

});
it('should throw an exception when used on a statement that returns no data', function () {

@@ -20,11 +20,11 @@ let stmt = this.db.prepare("INSERT INTO entries VALUES ('foo', 1, 3.14, x'dddddddd', NULL)");

expect(() => stmt.iterate()).to.throw(TypeError);
stmt = this.db.prepare("CREATE TABLE IF NOT EXISTS entries (a TEXT, b INTEGER, c REAL, d BLOB, e TEXT)");
expect(stmt.reader).to.be.false;
expect(() => stmt.iterate()).to.throw(TypeError);
stmt = this.db.prepare("BEGIN TRANSACTION");
expect(stmt.reader).to.be.false;
expect(() => stmt.iterate()).to.throw(TypeError);
this.db.prepare("INSERT INTO entries WITH RECURSIVE temp(a, b, c, d, e) AS (SELECT 'foo', 1, 3.14, x'dddddddd', NULL UNION ALL SELECT a, b + 1, c, d, e FROM temp LIMIT 10) SELECT * FROM temp").run();

@@ -34,7 +34,7 @@ });

const row = { a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xdd), e: null };
let count = 0;
let stmt = this.db.prepare("SELECT * FROM entries ORDER BY rowid");
expect(stmt.reader).to.be.true;
const iterator = stmt.iterate();

@@ -48,3 +48,3 @@ expect(iterator).to.not.be.null;

expect(iterator[Symbol.iterator]()).to.equal(iterator);
for (const data of iterator) {

@@ -55,3 +55,3 @@ row.b = ++count;

expect(count).to.equal(10);
count = 0;

@@ -73,3 +73,5 @@ stmt = this.db.prepare("SELECT * FROM entries WHERE b > 5 ORDER BY rowid");

if (typeof desiredData === 'object' && desiredData !== null) {
if (typeof desiredData.entries === 'object' && desiredData.entries !== null) {
if (Array.isArray(desiredData)) {
desiredData[1] = i;
} else if (typeof desiredData.entries === 'object' && desiredData.entries !== null) {
desiredData.entries.b = i;

@@ -90,2 +92,3 @@ } else {

const plucked = expanded.entries.a;
const raw = Object.values(expanded.entries).concat(expanded.$.c);
const stmt = this.db.prepare("SELECT *, 2 + 3.5 AS c FROM entries ORDER BY rowid");

@@ -114,2 +117,14 @@ shouldHave(row);

shouldHave(plucked);
stmt.raw();
shouldHave(raw);
shouldHave(raw);
stmt.raw(false);
shouldHave(row);
shouldHave(row);
stmt.raw(true);
shouldHave(raw);
shouldHave(raw);
stmt.expand(true);
shouldHave(expanded);
shouldHave(expanded);
});

@@ -214,7 +229,7 @@ it('should not be able to invoke .pluck() while the database is busy', function () {

};
const row = { a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xdd), e: null };
const SQL1 = 'SELECT * FROM entries WHERE a=? AND b=? AND c=? AND d=? AND e IS ?';
const SQL2 = 'SELECT * FROM entries WHERE a=@a AND b=@b AND c=@c AND d=@d AND e IS @e';
shouldHave(SQL1, row, ['foo', 1, 3.14, Buffer.alloc(4).fill(0xdd), null]);

@@ -224,31 +239,31 @@ shouldHave(SQL1, row, [['foo', 1, 3.14, Buffer.alloc(4).fill(0xdd), null]]);

shouldHave(SQL2, row, [{ a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xdd), e: undefined }]);
for (const data of this.db.prepare(SQL2).iterate({ a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xaa), e: undefined })) {
throw new Error('This callback should not have been invoked');
}
expect(() =>
this.db.prepare(SQL2).iterate(row, () => {})
).to.throw(TypeError);
expect(() =>
this.db.prepare(SQL2).iterate({ a: 'foo', b: 1, c: 3.14, d: Buffer.alloc(4).fill(0xdd) })
).to.throw(RangeError);
expect(() =>
this.db.prepare(SQL1).iterate()
).to.throw(RangeError);
expect(() =>
this.db.prepare(SQL2).iterate()
).to.throw(TypeError);
expect(() =>
this.db.prepare(SQL2).iterate(row, {})
).to.throw(TypeError);
expect(() =>
this.db.prepare(SQL2).iterate({})
).to.throw(RangeError);
this.db.prepare(SQL1).iterate('foo', 1, 3.14, Buffer.alloc(4).fill(0xdd), null).return();

@@ -255,0 +270,0 @@ expect(() =>

@@ -12,3 +12,3 @@ 'use strict';

});
it('should permanently bind the given parameters', function () {

@@ -40,3 +40,3 @@ const stmt = this.db.prepare('INSERT INTO entries VALUES (?, ?, ?)');

expect(() => stmt.bind()).to.throw(TypeError);
stmt = this.db.prepare('SELECT * FROM entries');

@@ -48,37 +48,37 @@ stmt.bind();

let stmt = this.db.prepare('INSERT INTO entries VALUES (?, ?, ?)');
expect(() =>
stmt.bind('foo', 25)
).to.throw(RangeError);
expect(() =>
stmt.bind('foo', 25, null, null)
).to.throw(RangeError);
expect(() =>
stmt.bind('foo', new Number(25), null)
).to.throw(TypeError);
expect(() =>
stmt.bind()
).to.throw(RangeError);
stmt.bind('foo', 25, null);
stmt = this.db.prepare('INSERT INTO entries VALUES (@a, @a, ?)');
expect(() =>
stmt.bind({ a: '123' })
).to.throw(RangeError);
expect(() =>
stmt.bind({ a: '123', 1: null })
).to.throw(RangeError);
expect(() =>
stmt.bind({ a: '123' }, null, null)
).to.throw(RangeError);
stmt.bind({ a: '123' }, null);
stmt = this.db.prepare('INSERT INTO entries VALUES (@a, @a, ?)');

@@ -85,0 +85,0 @@ stmt.bind({ a: '123', b: null }, null);

@@ -13,3 +13,3 @@ 'use strict';

});
it('should throw an exception if a function is not provided', function () {

@@ -16,0 +16,0 @@ expect(() => this.db.transaction(123)).to.throw(TypeError);

@@ -26,3 +26,3 @@ 'use strict';

}
describe('when used without a specified database', function () {

@@ -29,0 +29,0 @@ specify('every insert should increase the size of the WAL file', function () {

@@ -12,3 +12,3 @@ 'use strict';

});
it('should throw an exception if the correct arguments are not provided', function () {

@@ -62,3 +62,3 @@ expect(() => this.db.function()).to.throw(TypeError);

expect(this.get('a(?, ?, ?)', 'foo', 'z', 12)).to.equal('fooz12');
// undefined is interpreted as null

@@ -69,3 +69,3 @@ this.db.function('b', (a, b) => null);

expect(this.get('c(?, ?)', 2, 10)).to.equal(null);
// buffers

@@ -78,6 +78,6 @@ this.db.function('d', function foo(x) { return x; });

expect(output.equals(Buffer.alloc(8).fill(0xdd))).to.be.true;
// should not register based on function.name
expect(() => this.get('foo(?)', input)).to.throw(Database.SqliteError).with.property('code', 'SQLITE_ERROR');
// zero arguments

@@ -123,10 +123,10 @@ this.db.function('e', () => 12);

});
expect(this.get('b()')).to.equal(null);
expect(ranOnce).to.be.true;
ranOnce = false;
expect(this.db.exec('SELECT b()')).to.equal(this.db);
expect(ranOnce).to.be.true;
this.db.exec('SELECT a()')

@@ -163,3 +163,3 @@ this.db.prepare('SELECT 555');

this.db.prepare('INSERT INTO iterable WITH RECURSIVE temp(x) AS (SELECT 1 UNION ALL SELECT x * 2 FROM temp LIMIT 10) SELECT * FROM temp').run();
let i = 0;

@@ -169,3 +169,3 @@ const err = new Error('foo');

const iterator = this.db.prepare('SELECT fn(value) FROM iterable').pluck().iterate();
let total = 0;

@@ -178,3 +178,3 @@ expect(() => {

}).to.throw(err);
expect(total).to.equal(1 + 2 + 4 + 8);

@@ -233,6 +233,6 @@ expect(iterator.next()).to.deep.equal({ value: undefined, done: true });

this.db.prepare('DROP TABLE data').run();
const err = new Error('foo');
this.db.function('fn', () => { throw err; });
expect(() => this.db.prepare('SELECT fn()').get()).to.throw(err);

@@ -239,0 +239,0 @@ try { stmt.get(); } catch (ex) {

@@ -18,3 +18,3 @@ 'use strict';

});
it('should throw an exception if the correct arguments are not provided', function () {

@@ -98,7 +98,7 @@ expect(() => this.db.aggregate()).to.throw(TypeError);

expect(this.get('a(_, ?) FROM ints', 2)).to.equal(150);
// strings
this.db.aggregate('b', { step: (ctx, a, b) => a + b + ctx });
expect(this.get('b(_, ?) FROM texts', '!')).to.equal('g!f!e!d!c!b!a!null');
// starting value is null

@@ -111,3 +111,3 @@ this.db.aggregate('c', { step: (ctx, x) => null });

expect(this.get('e(_) FROM ints')).to.equal(null);
// buffers

@@ -120,3 +120,3 @@ this.db.aggregate('f', { step: (ctx, x) => x });

expect(output.equals(Buffer.alloc(8).fill(0xdd))).to.be.true;
// zero arguments

@@ -159,7 +159,7 @@ this.db.aggregate('g', { step: (ctx) => 'z' + ctx });

expect(this.get('a(_, ?) FROM ints', 2)).to.equal(10157);
this.db.aggregate('b', { start: { foo: 1000 }, step: (ctx, a, b) => a * b + (ctx.foo ? ++ctx.foo : ++ctx) });
expect(this.get('b(_, ?) FROM ints', 2)).to.equal(1157);
expect(this.get('b(_, ?) FROM ints', 2)).to.equal(1158);
let ranOnce = false;

@@ -180,3 +180,3 @@ this.db.aggregate('c', { start: undefined, step: (ctx, a, b) => {

let start = 10000;
this.db.aggregate('a', { start: () => start++, step: (ctx, a, b) => a * b + ctx });

@@ -186,3 +186,3 @@ expect(this.get('a(_, ?) FROM ints', 2)).to.equal(10150);

expect(this.get('a(_, ?) FROM ints', 2)).to.equal(10152);
this.db.aggregate('b', { start: () => ({ foo: start-- }), step: (ctx, a, b) => a * b + (ctx.foo || ctx) });

@@ -192,3 +192,3 @@ expect(this.get('b(_, ?) FROM ints', 2)).to.equal(10153);

expect(this.get('b(_, ?) FROM ints', 2)).to.equal(10151);
let ranOnce = false;

@@ -373,10 +373,10 @@ this.db.aggregate('c', { start: () => undefined, step: (ctx, a, b) => {

this.db.aggregate('b', { start: expectBusy, step: expectBusy, inverse: expectBusy, result: expectBusy });
expect(this.all('b(*) OVER win FROM ints')).to.deep.equal([null, null, null, null, null, null, null]);
expect(checkCount).to.equal(20);
checkCount = 0;
expect(this.db.exec('SELECT b(*) OVER win FROM ints WINDOW win AS (ORDER BY rowid ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) ORDER BY rowid')).to.equal(this.db);
expect(checkCount).to.equal(20);
this.db.exec('SELECT a()');

@@ -419,3 +419,3 @@ this.db.prepare('SELECT 555');

this.db.prepare('INSERT INTO iterable WITH RECURSIVE temp(x) AS (SELECT 1 UNION ALL SELECT x * 2 FROM temp LIMIT 10) SELECT * FROM temp').run();
let i = 0;

@@ -428,3 +428,3 @@ const err = new Error('foo');

const iterator = this.db.prepare('SELECT wn(value) OVER (ROWS CURRENT ROW) FROM iterable').pluck().iterate();
let total = 0;

@@ -437,3 +437,3 @@ expect(() => {

}).to.throw(err);
expect(total).to.equal(1 + 2 + 4 + 8);

@@ -491,3 +491,3 @@ expect(iterator.next()).to.deep.equal({ value: undefined, done: true });

};
specify('thrown in the start() function', function () {

@@ -597,6 +597,6 @@ exceptions.forEach((exception, index) => {

this.db.prepare('DROP TABLE data').run();
const err = new Error('foo');
this.db.aggregate('agg', { step: () => { throw err; } });
expect(() => this.db.prepare('SELECT agg()').get()).to.throw(err);

@@ -603,0 +603,0 @@ try { stmt.get(); } catch (ex) {

@@ -12,3 +12,3 @@ 'use strict';

});
it('should throw an exception if a string argument is not given', function () {

@@ -15,0 +15,0 @@ expect(() => this.db.loadExtension()).to.throw(TypeError);

@@ -13,3 +13,3 @@ 'use strict';

});
it('should bind to prepared statements', function () {

@@ -19,3 +19,3 @@ const int = Integer.fromBits(4243423, 234234234);

this.db.prepare('INSERT INTO entries VALUES (?, ?, ?)').bind(int, int, int).run();
const db2 = new Database(util.next());

@@ -35,3 +35,3 @@ db2.prepare('CREATE TABLE entries (a INTEGER, b REAL, c TEXT)').run();

this.db.prepare('INSERT INTO entries VALUES (?, ?, ?)').run(int, int, int);
let stmt = this.db.prepare('SELECT a FROM entries').pluck();

@@ -45,11 +45,11 @@ expect(stmt.get()).to.equal(1006028374637854700);

expect(stmt.get()).to.deep.equal(int);
stmt = this.db.prepare('SELECT b FROM entries').pluck();
expect(stmt.get()).to.equal(1006028374637854700);
expect(stmt.safeIntegers().get()).to.equal(1006028374637854700);
stmt = this.db.prepare('SELECT c FROM entries').pluck();
expect(stmt.get()).to.equal('1006028374637854687');
expect(stmt.safeIntegers().get()).to.equal('1006028374637854687');
let lastRowid = this.db.prepare('SELECT rowid FROM entries ORDER BY rowid DESC').pluck().get();

@@ -77,3 +77,3 @@ stmt = this.db.prepare('INSERT INTO entries VALUES (?, ?, ?)');

this.db.defaultSafeIntegers(true);
const stmt = this.db.prepare('SELECT a FROM entries').pluck();

@@ -84,5 +84,5 @@ expect(stmt.get()).to.deep.equal(int);

expect(customFunctionArg('a2', { safeIntegers: false })).to.equal(1006028374637854700);
this.db.defaultSafeIntegers(false);
const stmt2 = this.db.prepare('SELECT a FROM entries').pluck();

@@ -93,5 +93,5 @@ expect(stmt2.get()).to.equal(1006028374637854700);

expect(customFunctionArg('a4', { safeIntegers: true })).to.deep.equal(int);
this.db.defaultSafeIntegers();
expect(stmt.get()).to.equal(1006028374637854700);

@@ -103,3 +103,3 @@ expect(stmt2.get()).to.deep.equal(int);

expect(customFunctionArg('a4', {}, true)).to.deep.equal(int);
const stmt3 = this.db.prepare('SELECT a FROM entries').pluck();

@@ -115,3 +115,3 @@ expect(stmt3.get()).to.deep.equal(int);

this.db.prepare('INSERT INTO entries VALUES (?, ?, ?)').run(int, int, int);
let ranOnce = false;

@@ -118,0 +118,0 @@ const stmt1 = this.db.prepare('SELECT * FROM entries LIMIT 10');

@@ -26,3 +26,3 @@ 'use strict';

`;
it('should close all databases when the process exits gracefully', async function () {

@@ -29,0 +29,0 @@ const filename1 = util.next();

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc