From a9764e3dd2d26b01de71bb954bc732c4bbb8f36a Mon Sep 17 00:00:00 2001 From: Erin Dees Date: Tue, 28 Mar 2023 19:09:25 -0400 Subject: [PATCH 1/3] Add readonly option to Better-SQLite3 --- lib/dialects/better-sqlite3/index.js | 1 + test/db-less-test-suite.js | 4 ++++ test/unit/dialects/better-sqlite3.js | 31 ++++++++++++++++++++++++++++ types/index.d.ts | 1 + 4 files changed, 37 insertions(+) diff --git a/lib/dialects/better-sqlite3/index.js b/lib/dialects/better-sqlite3/index.js index 18cf15768d..85a5ba6922 100644 --- a/lib/dialects/better-sqlite3/index.js +++ b/lib/dialects/better-sqlite3/index.js @@ -13,6 +13,7 @@ class Client_BetterSQLite3 extends Client_SQLite3 { return new this.driver(this.connectionSettings.filename, { nativeBinding: options.nativeBinding, + readonly: !!options.readonly, }); } diff --git a/test/db-less-test-suite.js b/test/db-less-test-suite.js index 8cac595595..1100a29312 100644 --- a/test/db-less-test-suite.js +++ b/test/db-less-test-suite.js @@ -50,6 +50,10 @@ if (config.mysql) { require('./unit/dialects/mysql'); } +if (config['better-sqlite3']) { + require('./unit/dialects/better-sqlite3'); +} + describe('CLI tests', function () { this.timeout(process.env.KNEX_TEST_TIMEOUT || 5000); require('./cli/help.spec'); diff --git a/test/unit/dialects/better-sqlite3.js b/test/unit/dialects/better-sqlite3.js index dbf3dfe23e..c2d9847454 100644 --- a/test/unit/dialects/better-sqlite3.js +++ b/test/unit/dialects/better-sqlite3.js @@ -39,4 +39,35 @@ describe('better-sqlite3 unit tests', () => { expect(result.code).to.equal('MODULE_NOT_FOUND'); }); }); + + describe('readonly', () => { + it('should initialize the DB with the passed-in `readonly` option', async () => { + const knexInstance = knex({ + client: 'better-sqlite3', + useNullAsDefault: true, + connection: { + filename: __dirname + '/../test.sqlite3', + options: { + readonly: true, + }, + }, + }); + + const connection = await knexInstance.client.acquireConnection(); + expect(connection.readonly).to.equal(true); + }); + + it('should fall back on `readonly` = `false`', async () => { + const knexInstance = knex({ + client: 'better-sqlite3', + useNullAsDefault: true, + connection: { + filename: __dirname + '/../test.sqlite3', + }, + }); + + const connection = await knexInstance.client.acquireConnection(); + expect(connection.readonly).to.equal(false); + }); + }); }); diff --git a/types/index.d.ts b/types/index.d.ts index 87e9ca230f..0220a7cf48 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -3055,6 +3055,7 @@ export declare namespace Knex { filename: string; options?: { nativeBinding?: string; + readonly?: boolean; }; } From 40764a24add3fd02cf23b3e14a9a87a539e5d46e Mon Sep 17 00:00:00 2001 From: Erin Dees Date: Tue, 28 Mar 2023 19:10:06 -0400 Subject: [PATCH 2/3] Run the commit hook's formatter on existing code Co-authored-by: Adam Haglund --- test/unit/dialects/better-sqlite3.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/test/unit/dialects/better-sqlite3.js b/test/unit/dialects/better-sqlite3.js index c2d9847454..7c3b3ea00a 100644 --- a/test/unit/dialects/better-sqlite3.js +++ b/test/unit/dialects/better-sqlite3.js @@ -12,12 +12,18 @@ describe('better-sqlite3 unit tests', () => { connection: { filename: ':memory:', options: { - nativeBinding: path.resolve(__dirname, '../../../node_modules/better-sqlite3/build/Release/better_sqlite3.node'), + nativeBinding: path.resolve( + __dirname, + '../../../node_modules/better-sqlite3/build/Release/better_sqlite3.node' + ), }, }, }); - const result = await knexInstance.select(knexInstance.raw('2 + 2 as answer')).first().catch(err => err); + const result = await knexInstance + .select(knexInstance.raw('2 + 2 as answer')) + .first() + .catch((err) => err); expect(result.answer).to.equal(4); }); @@ -33,7 +39,10 @@ describe('better-sqlite3 unit tests', () => { }, }); - const result = await knexInstance.select(knexInstance.raw('2 + 2 as answer')).first().catch(err => err); + const result = await knexInstance + .select(knexInstance.raw('2 + 2 as answer')) + .first() + .catch((err) => err); console.dir(result); expect(result).to.be.an('error'); expect(result.code).to.equal('MODULE_NOT_FOUND'); From 0ee2778e9d6084a3817e91c598421ec2d3faa48f Mon Sep 17 00:00:00 2001 From: Erin Dees Date: Wed, 29 Mar 2023 08:37:28 -0400 Subject: [PATCH 3/3] Check that Better-SQLite3 can prevent writes --- test/unit/dialects/better-sqlite3.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/unit/dialects/better-sqlite3.js b/test/unit/dialects/better-sqlite3.js index 7c3b3ea00a..8f16cd716b 100644 --- a/test/unit/dialects/better-sqlite3.js +++ b/test/unit/dialects/better-sqlite3.js @@ -66,6 +66,23 @@ describe('better-sqlite3 unit tests', () => { expect(connection.readonly).to.equal(true); }); + it('should prevent writing to the DB', async () => { + const knexInstance = knex({ + client: 'better-sqlite3', + useNullAsDefault: true, + connection: { + filename: __dirname + '/../test.sqlite3', + options: { + readonly: true, + }, + }, + }); + + await expect( + knexInstance.raw('create table shouldFail (x integer)') + ).to.eventually.be.rejectedWith('attempt to write a readonly database'); + }); + it('should fall back on `readonly` = `false`', async () => { const knexInstance = knex({ client: 'better-sqlite3',