Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to set the default transaction behavior #1248

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Various options are accepted:

- `options.timeout`: the number of milliseconds to wait when executing queries on a locked database, before throwing a `SQLITE_BUSY` error (default: `5000`).

- `options.defaultTransactionBehaviour`: Set the default transaction behavior when calling [Database#transaction()](#transactionfunction---function). Can be set as `null` (SQLite Default), `'deferred'`, `'immediate'` or `'exclusive'` (default: `null`).

- `options.verbose`: provide a function that gets called with every SQL string executed by the database connection (default: `null`).

- `options.nativeBinding`: if you're using a complicated build system that moves, transforms, or concatenates your JS files, `better-sqlite3` might have trouble locating its native C++ addon (`better_sqlite3.node`). If you get an error that looks like [this](https://github.com/JoshuaWise/better-sqlite3/issues/534#issuecomment-757907190), you can solve it by using this option to provide the file path of `better_sqlite3.node` (relative to the current working directory).
Expand Down Expand Up @@ -86,7 +88,8 @@ const adopt = db.transaction((cats) => {
Transactions also come with `deferred`, `immediate`, and `exclusive` versions.

```js
insertMany(cats); // uses "BEGIN"
insertMany(cats) // uses the default set by options.defaultTransactionBehavior
insertMany.default(cats); // uses "BEGIN"
insertMany.deferred(cats); // uses "BEGIN DEFERRED"
insertMany.immediate(cats); // uses "BEGIN IMMEDIATE"
insertMany.exclusive(cats); // uses "BEGIN EXCLUSIVE"
Expand Down
7 changes: 6 additions & 1 deletion lib/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,18 @@ function Database(filenameGiven, options) {
const timeout = 'timeout' in options ? options.timeout : 5000;
const verbose = 'verbose' in options ? options.verbose : null;
const nativeBinding = 'nativeBinding' in options ? options.nativeBinding : null;
const defaultTransactionBehavior = 'defaultTransactionBehavior' in options ? options.defaultTransactionBehavior : null;

// Validate interpreted options
if (readonly && anonymous && !buffer) throw new TypeError('In-memory/temporary databases cannot be readonly');
if (!Number.isInteger(timeout) || timeout < 0) throw new TypeError('Expected the "timeout" option to be a positive integer');
if (timeout > 0x7fffffff) throw new RangeError('Option "timeout" cannot be greater than 2147483647');
if (verbose != null && typeof verbose !== 'function') throw new TypeError('Expected the "verbose" option to be a function');
if (nativeBinding != null && typeof nativeBinding !== 'string' && typeof nativeBinding !== 'object') throw new TypeError('Expected the "nativeBinding" option to be a string or addon object');
if (defaultTransactionBehavior != null) {
if (typeof defaultTransactionBehavior !== 'string') throw new TypeError('Expected the "defaultTransactionBehavior" option to be a string, expected "deferred", "immediate", or "exclusive"')
if (!["deferred", "immediate", "exclusive"].includes(defaultTransactionBehavior)) throw new Error('Invalid value for "defaultTransactionBehavior", expected "deferred", "immediate", or "exclusive"')
}

// Load the native addon
let addon;
Expand All @@ -66,7 +71,7 @@ function Database(filenameGiven, options) {
}

Object.defineProperties(this, {
[util.cppdb]: { value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null) },
[util.cppdb]: { value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, defaultTransactionBehavior, verbose || null, buffer || null) },
...wrappers.getters,
});
}
Expand Down
4 changes: 3 additions & 1 deletion lib/methods/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ module.exports = function transaction(fn) {

// Each version of the transaction function has these same properties
const properties = {
default: { value: wrapTransaction(apply, fn, db, controller.default) },
deferred: { value: wrapTransaction(apply, fn, db, controller.deferred) },
immediate: { value: wrapTransaction(apply, fn, db, controller.immediate) },
exclusive: { value: wrapTransaction(apply, fn, db, controller.exclusive) },
database: { value: this, enumerable: true },
};
properties.default = db.defaultTransactionBehavior == null ?
{ value: wrapTransaction(apply, fn, db, controller.default) } :
properties[db.defaultTransactionBehavior];

Object.defineProperties(properties.default.value, properties);
Object.defineProperties(properties.deferred.value, properties);
Expand Down
4 changes: 4 additions & 0 deletions lib/methods/wrappers.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,8 @@ exports.getters = {
get: function memory() { return this[cppdb].memory; },
enumerable: true,
},
defaultTransactionBehavior: {
get: function defaultTransactionBehavior() { return this[cppdb].defaultTransactionBehavior; },
enumerable: true
}
};
Loading