mirror of
https://github.com/hanzoai/better-sqlite3-multiple-ciphers.git
synced 2026-09-24 16:57:19 +00:00
implemented "nativeBinding" database option
(cherry picked from commit 9f6050a5620ffaaa032846e5daf558777db2a95b)
This commit is contained in:
committed by
Mahesh Bandara Wijerathna
parent
3c5d4ac6f0
commit
928b2c582b
@@ -37,6 +37,8 @@ Various options are accepted:
|
||||
|
||||
- `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/146#issue-337752663), you can solve it by using this option to provide the file path of `better_sqlite3.node` (relative to the current working directory).
|
||||
|
||||
```js
|
||||
const Database = require('better-sqlite3-multiple-ciphers');
|
||||
const db = new Database('foobar.db', { verbose: console.log });
|
||||
|
||||
+17
-6
@@ -2,11 +2,9 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const util = require('./util');
|
||||
const SqliteError = require('./sqlite-error');
|
||||
|
||||
const {
|
||||
Database: CPPDatabase,
|
||||
setErrorConstructor,
|
||||
} = require('bindings')('better_sqlite3.node');
|
||||
let DEFAULT_ADDON;
|
||||
|
||||
function Database(filenameGiven, options) {
|
||||
if (new.target == null) {
|
||||
@@ -35,12 +33,26 @@ function Database(filenameGiven, options) {
|
||||
const fileMustExist = util.getBooleanOption(options, 'fileMustExist');
|
||||
const timeout = 'timeout' in options ? options.timeout : 5000;
|
||||
const verbose = 'verbose' in options ? options.verbose : null;
|
||||
const nativeBindingPath = 'nativeBinding' in options ? options.nativeBinding : 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 (nativeBindingPath != null && typeof nativeBindingPath !== 'string') throw new TypeError('Expected the "nativeBinding" option to be a string');
|
||||
|
||||
// Load the native addon
|
||||
let addon;
|
||||
if (nativeBindingPath == null) {
|
||||
addon = DEFAULT_ADDON || (DEFAULT_ADDON = require('bindings')('better_sqlite3.node'));
|
||||
} else {
|
||||
addon = require(path.resolve(nativeBindingPath).replace(/(\.node)?$/, '.node'));
|
||||
}
|
||||
if (!addon.isInitialized) {
|
||||
addon.setErrorConstructor(SqliteError);
|
||||
addon.isInitialized = true;
|
||||
}
|
||||
|
||||
// Make sure the specified directory exists
|
||||
if (!anonymous && !fs.existsSync(path.dirname(filename))) {
|
||||
@@ -48,7 +60,7 @@ function Database(filenameGiven, options) {
|
||||
}
|
||||
|
||||
Object.defineProperties(this, {
|
||||
[util.cppdb]: { value: new CPPDatabase(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null) },
|
||||
[util.cppdb]: { value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null) },
|
||||
...wrappers.getters,
|
||||
});
|
||||
}
|
||||
@@ -70,4 +82,3 @@ Database.prototype.unsafeMode = wrappers.unsafeMode;
|
||||
Database.prototype[util.inspect] = require('./methods/inspect');
|
||||
|
||||
module.exports = Database;
|
||||
setErrorConstructor(require('./sqlite-error'));
|
||||
|
||||
+46
-19
@@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
const { existsSync } = require('fs');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const Database = require('../.');
|
||||
|
||||
describe('new Database()', function () {
|
||||
@@ -31,10 +32,10 @@ describe('new Database()', function () {
|
||||
expect(db.readonly).to.be.false;
|
||||
expect(db.open).to.be.true;
|
||||
expect(db.inTransaction).to.be.false;
|
||||
expect(existsSync('')).to.be.false;
|
||||
expect(existsSync('null')).to.be.false;
|
||||
expect(existsSync('undefined')).to.be.false;
|
||||
expect(existsSync('[object Object]')).to.be.false;
|
||||
expect(fs.existsSync('')).to.be.false;
|
||||
expect(fs.existsSync('null')).to.be.false;
|
||||
expect(fs.existsSync('undefined')).to.be.false;
|
||||
expect(fs.existsSync('[object Object]')).to.be.false;
|
||||
db.close();
|
||||
}
|
||||
});
|
||||
@@ -45,49 +46,49 @@ describe('new Database()', function () {
|
||||
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(fs.existsSync(':memory:')).to.be.false;
|
||||
});
|
||||
it('should allow disk-bound databases to be created', function () {
|
||||
expect(existsSync(util.next())).to.be.false;
|
||||
expect(fs.existsSync(util.next())).to.be.false;
|
||||
const db = this.db = new 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(util.current())).to.be.true;
|
||||
expect(fs.existsSync(util.current())).to.be.true;
|
||||
});
|
||||
it('should allow readonly database connections to be created', function () {
|
||||
expect(existsSync(util.next())).to.be.false;
|
||||
expect(fs.existsSync(util.next())).to.be.false;
|
||||
expect(() => (this.db = new Database(util.current(), { readonly: true }))).to.throw(Database.SqliteError).with.property('code', 'SQLITE_CANTOPEN');
|
||||
(new Database(util.current())).close();
|
||||
expect(existsSync(util.current())).to.be.true;
|
||||
expect(fs.existsSync(util.current())).to.be.true;
|
||||
const db = this.db = new Database(util.current(), { readonly: true });
|
||||
expect(db.name).to.equal(util.current());
|
||||
expect(db.memory).to.be.false;
|
||||
expect(db.readonly).to.be.true;
|
||||
expect(db.open).to.be.true;
|
||||
expect(db.inTransaction).to.be.false;
|
||||
expect(existsSync(util.current())).to.be.true;
|
||||
expect(fs.existsSync(util.current())).to.be.true;
|
||||
});
|
||||
it('should not allow the "readonly" option for in-memory databases', function () {
|
||||
expect(existsSync(util.next())).to.be.false;
|
||||
expect(fs.existsSync(util.next())).to.be.false;
|
||||
expect(() => (this.db = new Database(':memory:', { readonly: true }))).to.throw(TypeError);
|
||||
expect(() => (this.db = new Database('', { readonly: true }))).to.throw(TypeError);
|
||||
expect(existsSync(util.current())).to.be.false;
|
||||
expect(fs.existsSync(util.current())).to.be.false;
|
||||
});
|
||||
it('should accept the "fileMustExist" option', function () {
|
||||
expect(existsSync(util.next())).to.be.false;
|
||||
expect(fs.existsSync(util.next())).to.be.false;
|
||||
expect(() => (this.db = new Database(util.current(), { fileMustExist: true }))).to.throw(Database.SqliteError).with.property('code', 'SQLITE_CANTOPEN');
|
||||
(new Database(util.current())).close();
|
||||
expect(existsSync(util.current())).to.be.true;
|
||||
expect(fs.existsSync(util.current())).to.be.true;
|
||||
const db = this.db = new Database(util.current(), { fileMustExist: true });
|
||||
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(util.current())).to.be.true;
|
||||
expect(fs.existsSync(util.current())).to.be.true;
|
||||
});
|
||||
util.itUnix('should accept the "timeout" option', function () {
|
||||
this.slow(4000);
|
||||
@@ -115,12 +116,38 @@ describe('new Database()', function () {
|
||||
expect(() => (this.db = new Database(util.current(), { timeout: 75.01 }))).to.throw(TypeError);
|
||||
expect(() => (this.db = new Database(util.current(), { timeout: 0x80000000 }))).to.throw(RangeError);
|
||||
});
|
||||
it('should accept the "nativeBinding" option', function () {
|
||||
this.slow(500);
|
||||
const oldBinding = require('bindings')({ bindings: 'better_sqlite3.node', path: true });
|
||||
const newBinding = path.join(__dirname, '..', 'temp', 'foo.node');
|
||||
expect(oldBinding).to.be.a('string');
|
||||
fs.copyFileSync(oldBinding, newBinding);
|
||||
const getBinding = db => db[Object.getOwnPropertySymbols(db)[0]].constructor;
|
||||
let db1;
|
||||
let db2;
|
||||
let db3;
|
||||
try {
|
||||
db1 = new Database('');
|
||||
db2 = new Database('', { nativeBinding: oldBinding });
|
||||
db3 = new Database('', { nativeBinding: newBinding });
|
||||
expect(db1.open).to.be.true;
|
||||
expect(db2.open).to.be.true;
|
||||
expect(db3.open).to.be.true;
|
||||
expect(getBinding(db1)).to.equal(getBinding(db2));
|
||||
expect(getBinding(db1)).to.not.equal(getBinding(db3));
|
||||
expect(getBinding(db2)).to.not.equal(getBinding(db3));
|
||||
} finally {
|
||||
if (db1) db1.close();
|
||||
if (db2) db2.close();
|
||||
if (db3) db3.close();
|
||||
}
|
||||
});
|
||||
it('should throw an Error if the directory does not exist', function () {
|
||||
expect(existsSync(util.next())).to.be.false;
|
||||
expect(fs.existsSync(util.next())).to.be.false;
|
||||
const filepath = `temp/nonexistent/abcfoobar123/${util.current()}`;
|
||||
expect(() => (this.db = new Database(filepath))).to.throw(TypeError);
|
||||
expect(existsSync(filepath)).to.be.false;
|
||||
expect(existsSync(util.current())).to.be.false;
|
||||
expect(fs.existsSync(filepath)).to.be.false;
|
||||
expect(fs.existsSync(util.current())).to.be.false;
|
||||
});
|
||||
it('should have a proper prototype chain', function () {
|
||||
const db = this.db = new Database(util.next());
|
||||
|
||||
Reference in New Issue
Block a user