better-sqlite3-multiple-ciphers 7.4.7-beta.1 → 7.5.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +1 -1
  2. package/deps/download.sh +111 -108
  3. package/deps/setup.ps1 +9 -11
  4. package/deps/sqlite3/sqlite3.c +272560 -0
  5. package/deps/sqlite3/sqlite3.h +12770 -0
  6. package/deps/sqlite3/sqlite3ext.h +675 -0
  7. package/deps/sqlite3.gyp +13 -7
  8. package/deps/symlink.js +7 -4
  9. package/lib/database.js +17 -6
  10. package/lib/sqlite-error.js +1 -2
  11. package/package.json +10 -4
  12. package/src/better_sqlite3.cpp +46 -35
  13. package/src/better_sqlite3.hpp +40 -38
  14. package/.gitattributes +0 -1
  15. package/.github/workflows/prebuild.yml +0 -49
  16. package/.github/workflows/test.yml +0 -59
  17. package/benchmark/benchmark.js +0 -31
  18. package/benchmark/drivers.js +0 -21
  19. package/benchmark/index.js +0 -83
  20. package/benchmark/seed.js +0 -47
  21. package/benchmark/trials.js +0 -65
  22. package/benchmark/types/insert.js +0 -16
  23. package/benchmark/types/select-all.js +0 -14
  24. package/benchmark/types/select-iterate.js +0 -23
  25. package/benchmark/types/select.js +0 -14
  26. package/benchmark/types/transaction.js +0 -40
  27. package/deps/extract.js +0 -16
  28. package/deps/sqlite3.tar.gz +0 -0
  29. package/docs/api.md +0 -645
  30. package/docs/benchmark.md +0 -38
  31. package/docs/compilation.md +0 -76
  32. package/docs/integer.md +0 -79
  33. package/docs/performance.md +0 -39
  34. package/docs/threads.md +0 -97
  35. package/docs/tips.md +0 -35
  36. package/docs/troubleshooting.md +0 -23
  37. package/docs/unsafe.md +0 -16
  38. package/src/better_sqlite3.lzz +0 -88
  39. package/src/objects/backup.lzz +0 -138
  40. package/src/objects/database.lzz +0 -468
  41. package/src/objects/statement-iterator.lzz +0 -138
  42. package/src/objects/statement.lzz +0 -323
  43. package/src/util/bind-map.lzz +0 -73
  44. package/src/util/binder.lzz +0 -190
  45. package/src/util/constants.lzz +0 -151
  46. package/src/util/custom-aggregate.lzz +0 -121
  47. package/src/util/custom-function.lzz +0 -59
  48. package/src/util/custom-table.lzz +0 -397
  49. package/src/util/data-converter.lzz +0 -17
  50. package/src/util/data.lzz +0 -145
  51. package/src/util/macros.lzz +0 -159
  52. package/src/util/query-macros.lzz +0 -71
  53. package/test/00.setup.js +0 -25
  54. package/test/01.sqlite-error.js +0 -27
  55. package/test/10.database.open.js +0 -159
  56. package/test/11.database.close.js +0 -68
  57. package/test/12.database.pragma.js +0 -65
  58. package/test/13.database.prepare.js +0 -60
  59. package/test/14.database.exec.js +0 -46
  60. package/test/20.statement.run.js +0 -170
  61. package/test/21.statement.get.js +0 -109
  62. package/test/22.statement.all.js +0 -129
  63. package/test/23.statement.iterate.js +0 -223
  64. package/test/24.statement.bind.js +0 -107
  65. package/test/25.statement.columns.js +0 -46
  66. package/test/30.database.transaction.js +0 -157
  67. package/test/31.database.checkpoint.js +0 -62
  68. package/test/32.database.function.js +0 -211
  69. package/test/33.database.aggregate.js +0 -603
  70. package/test/34.database.table.js +0 -671
  71. package/test/35.database.load-extension.js +0 -75
  72. package/test/36.database.backup.js +0 -240
  73. package/test/37.database.serialize.js +0 -81
  74. package/test/40.bigints.js +0 -145
  75. package/test/41.at-exit.js +0 -52
  76. package/test/42.integrity.js +0 -531
  77. package/test/43.verbose.js +0 -100
  78. package/test/44.worker-threads.js +0 -66
  79. package/test/45.unsafe-mode.js +0 -52
  80. package/test/46.encryption.js +0 -69
  81. package/test/50.misc.js +0 -44
package/docs/benchmark.md DELETED
@@ -1,38 +0,0 @@
1
- # Benchmark
2
-
3
- To run the benchmark yourself:
4
-
5
- ```bash
6
- git clone https://github.com/JoshuaWise/better-sqlite3.git
7
- cd better-sqlite3
8
- npm install # if you're doing this as the root user, --unsafe-perm is required
9
- node benchmark
10
- ```
11
-
12
- # Results
13
-
14
- These results are from 03/29/2020, on a MacBook Pro (Retina, 15-inch, Mid 2014, OSX 10.11.6), using nodejs v12.16.1.
15
-
16
- ```
17
- --- reading rows individually ---
18
- better-sqlite3 x 313,899 ops/sec ±0.13%
19
- node-sqlite3 x 26,780 ops/sec ±2.9%
20
-
21
- --- reading 100 rows into an array ---
22
- better-sqlite3 x 8,508 ops/sec ±0.27%
23
- node-sqlite3 x 2,930 ops/sec ±0.37%
24
-
25
- --- iterating over 100 rows ---
26
- better-sqlite3 x 6,532 ops/sec ±0.32%
27
- node-sqlite3 x 268 ops/sec ±3.4%
28
-
29
- --- inserting rows individually ---
30
- better-sqlite3 x 62,554 ops/sec ±7.33%
31
- node-sqlite3 x 22,637 ops/sec ±4.37%
32
-
33
- --- inserting 100 rows in a single transaction ---
34
- better-sqlite3 x 4,141 ops/sec ±4.57%
35
- node-sqlite3 x 265 ops/sec ±4.87%
36
- ```
37
-
38
- > All benchmarks are executed in [WAL mode](./performance.md).
@@ -1,76 +0,0 @@
1
- # Custom configuration
2
-
3
- If you want to use a customized version of [SQLite3](https://www.sqlite.org) with `better-sqlite3-multiple-ciphers`, you can do so by specifying the directory of your [custom amalgamation](https://www.sqlite.org/amalgamation.html) during installation.
4
-
5
- ```bash
6
- npm install better-sqlite3-multiple-ciphers --build-from-source --sqlite3=/path/to/sqlite-amalgamation
7
- ```
8
-
9
- However, if you simply run `npm install` while `better-sqlite3-multiple-ciphers` is listed as a dependency in your `package.json`, the required flags above will *not* be applied. Therefore, it's recommended that you remove `better-sqlite3-multiple-ciphers` from your dependency list, and instead add a [`preinstall` script](https://docs.npmjs.com/misc/scripts) like the one shown below.
10
-
11
- ```json
12
- {
13
- "scripts": {
14
- "preinstall": "npm install better-sqlite3-multiple-ciphers@'^7.0.0' --no-save --build-from-source --sqlite3=\"$(pwd)/sqlite-amalgamation\""
15
- }
16
- }
17
- ```
18
-
19
- Your amalgamation directory must contain `sqlite3.c` and `sqlite3.h`. Any desired [compile time options](https://www.sqlite.org/compile.html) must be defined directly within `sqlite3.c`.
20
-
21
- ### Step by step example
22
-
23
- If you're creating a package that relies on a custom build of `better-sqlite3-multiple-ciphers`, you can follow these steps to get started.
24
-
25
- 1. Download the SQLite3 source code from [their website](https://sqlite.com/download.html) (e.g., `sqlite-amalgamation-1234567.zip`)
26
- 2. Unzip the compressed archive
27
- 3. Move the `sqlite3.c` and `sqlite3.h` files to your project folder
28
- 4. Add a `preinstall` script to your `package.json`, like the one shown above
29
- 5. Make sure the `--sqlite3` flag points to the location of your `sqlite3.c` and `sqlite3.h` files
30
- 6. Define your preferred [compile time options](https://www.sqlite.org/compile.html) at the top of `sqlite3.c`
31
- 7. Run `npm install` in your project folder
32
-
33
- If you're using a SQLite3 encryption extension that is a drop-in replacement for SQLite3 (such as [SEE](https://www.sqlite.org/see/doc/release/www/readme.wiki) or [sqleet](https://github.com/resilar/sqleet)), then simply replace `sqlite3.c` and `sqlite3.h` with the source files of your encryption extension.
34
-
35
- # Bundled configuration
36
-
37
- By default, this distribution currently uses SQLite3 **version 3.37.2** with the following [compilation options](https://www.sqlite.org/compile.html):
38
-
39
- ```
40
- SQLITE_DQS=0
41
- SQLITE_LIKE_DOESNT_MATCH_BLOBS
42
- SQLITE_THREADSAFE=2
43
- SQLITE_USE_URI=0
44
- SQLITE_DEFAULT_MEMSTATUS=0
45
- SQLITE_OMIT_DEPRECATED
46
- SQLITE_OMIT_GET_TABLE
47
- SQLITE_OMIT_TCL_VARIABLE
48
- SQLITE_OMIT_PROGRESS_CALLBACK
49
- SQLITE_OMIT_SHARED_CACHE
50
- SQLITE_TRACE_SIZE_LIMIT=32
51
- SQLITE_DEFAULT_CACHE_SIZE=-16000
52
- SQLITE_DEFAULT_FOREIGN_KEYS=1
53
- SQLITE_DEFAULT_WAL_SYNCHRONOUS=1
54
- SQLITE_ENABLE_MATH_FUNCTIONS
55
- SQLITE_ENABLE_DESERIALIZE
56
- SQLITE_ENABLE_COLUMN_METADATA
57
- SQLITE_ENABLE_UPDATE_DELETE_LIMIT
58
- SQLITE_ENABLE_STAT4
59
- SQLITE_ENABLE_FTS3_PARENTHESIS
60
- SQLITE_ENABLE_FTS3
61
- SQLITE_ENABLE_FTS4
62
- SQLITE_ENABLE_FTS5
63
- SQLITE_ENABLE_JSON1
64
- SQLITE_ENABLE_RTREE
65
- SQLITE_ENABLE_GEOPOLY
66
- SQLITE_INTROSPECTION_PRAGMAS
67
- SQLITE_SOUNDEX
68
- HAVE_STDINT_H=1
69
- HAVE_INT8_T=1
70
- HAVE_INT16_T=1
71
- HAVE_INT32_T=1
72
- HAVE_UINT8_T=1
73
- HAVE_UINT16_T=1
74
- HAVE_UINT32_T=1
75
- SQLITE_USER_AUTHENTICATION=0
76
- ```
package/docs/integer.md DELETED
@@ -1,79 +0,0 @@
1
- # The `BigInt` primitive type
2
-
3
- SQLite3 can store data in 64-bit signed integers, which are too big for JavaScript's [number format](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) to fully represent. To support this data type, `better-sqlite3` is fully compatible with [BigInts](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
4
-
5
- ```js
6
- const big = BigInt('1152735103331642317');
7
- big === 1152735103331642317n; // returns true
8
- big.toString(); // returns "1152735103331642317"
9
- typeof big; // returns "bigint"
10
- ```
11
-
12
- ## Binding BigInts
13
-
14
- `BigInts` can bind to [`Statements`](./api.md#class-statement) just like regular numbers. You can also return `BigInts` from [user-defined functions](./api.md#functionname-options-function---this). However, if you provide a `BigInt` that's too large to be a 64-bit signed integer, you'll get an error so that data integrity is protected.
15
-
16
- ```js
17
- db.prepare("SELECT * FROM users WHERE id=?").get(BigInt('1152735103331642317'));
18
- db.prepare("INSERT INTO users (id) VALUES (?)").run(BigInt('1152735103331642317'));
19
-
20
- db.prepare("SELECT ?").get(2n ** 63n - 1n); // returns successfully
21
- db.prepare("SELECT ?").get(2n ** 63n); // throws a RangeError
22
- ```
23
-
24
- ## Getting BigInts from the database
25
-
26
- By default, integers returned from the database (including the [`info.lastInsertRowid`](./api.md#runbindparameters---object) property) are normal JavaScript numbers. You can change this default as you please:
27
-
28
- ```js
29
- db.defaultSafeIntegers(); // BigInts by default
30
- db.defaultSafeIntegers(true); // BigInts by default
31
- db.defaultSafeIntegers(false); // Numbers by default
32
- ```
33
-
34
- Additionally, you can override the default for individual [`Statements`](./api.md#class-statement) like so:
35
-
36
- ```js
37
- const stmt = db.prepare(SQL);
38
-
39
- stmt.safeIntegers(); // Safe integers ON
40
- stmt.safeIntegers(true); // Safe integers ON
41
- stmt.safeIntegers(false); // Safe integers OFF
42
- ```
43
-
44
- [User-defined functions](./api.md#functionname-options-function---this) can receive `BigInts` as arguments. You can override the database's default setting like so:
45
-
46
- ```js
47
- db.function('isInt', { safeIntegers: true }, (value) => {
48
- return String(typeof value === 'bigint');
49
- });
50
-
51
- db.prepare('SELECT isInt(?)').pluck().get(10); // => "false"
52
- db.prepare('SELECT isInt(?)').pluck().get(10n); // => "true"
53
- ```
54
-
55
- Likewise, [user-defined aggregates](./api.md#aggregatename-options---this) and [virtual tables](./api.md#tablename-definition---this) can also receive `BigInts` as arguments:
56
-
57
- ```js
58
- db.aggregate('addInts', {
59
- safeIntegers: true,
60
- start: 0n,
61
- step: (total, nextValue) => total + nextValue,
62
- });
63
- ```
64
-
65
- ```js
66
- db.table('sequence', {
67
- safeIntegers: true,
68
- columns: ['value'],
69
- parameters: ['length', 'start'],
70
- rows: function* (length, start = 0n) {
71
- const end = start + length;
72
- for (let n = start; n < end; ++n) {
73
- yield { value: n };
74
- }
75
- },
76
- });
77
- ```
78
-
79
- It's worth noting that REAL (FLOAT) values returned from the database will always be represented as normal numbers.
@@ -1,39 +0,0 @@
1
- # Performance
2
-
3
- Concurrently reading and writing from an SQLite3 database can be very slow in some cases. Since concurrency is usually very important in web applications, it's recommended to turn on [WAL mode](https://www.sqlite.org/wal.html) to greatly increase overall performance.
4
-
5
- ```js
6
- db.pragma('journal_mode = WAL');
7
- ```
8
-
9
- WAL mode has a *few* disadvantages to consider:
10
-
11
- - Transactions that involve ATTACHed databases are atomic for each individual database, but are not atomic across all databases as a set.
12
- - Under rare circumstances, the [WAL file](https://www.sqlite.org/wal.html) may experience "checkpoint starvation" (see below).
13
- - There are some hardware/system limitations that may affect some users, [listed here](https://www.sqlite.org/wal.html).
14
-
15
- However, you trade those disadvantages for extremely fast performance in most web applications.
16
-
17
- ## Checkpoint starvation
18
-
19
- Checkpoint starvation is when SQLite3 is unable to recycle the [WAL file](https://www.sqlite.org/wal.html) due to everlasting concurrent reads to the database. If this happens, the WAL file will grow without bound, leading to unacceptable amounts of disk usage and deteriorating performance.
20
-
21
- If you don't access the database from multiple processes or threads simultaneously, you'll never encounter this issue.
22
-
23
- If you do access the database from multiple processes or threads simultaneously, just use the [`wal_checkpoint(RESTART)`](https://www.sqlite.org/pragma.html#pragma_wal_checkpoint) pragma when the WAL file gets too big.
24
-
25
- ```js
26
- setInterval(fs.stat.bind(null, 'foobar.db-wal', (err, stat) => {
27
- if (err) {
28
- if (err.code !== 'ENOENT') throw err;
29
- } else if (stat.size > someUnacceptableSize) {
30
- db.pragma('wal_checkpoint(RESTART)');
31
- }
32
- }), 5000).unref();
33
- ```
34
-
35
- ## A note about durability
36
-
37
- This distribution of SQLite3 uses the `SQLITE_DEFAULT_WAL_SYNCHRONOUS=1` [compile-time option](https://sqlite.org/compile.html#default_wal_synchronous), which makes databases in WAL mode default to the ["NORMAL" synchronous setting](https://sqlite.org/pragma.html#pragma_synchronous). This allows applications to achieve extreme performance, but introduces a slight loss of [durability](https://en.wikipedia.org/wiki/Durability_(database_systems)) while in WAL mode.
38
-
39
- You can override this setting by running `db.pragma('synchronous = FULL')`.
package/docs/threads.md DELETED
@@ -1,97 +0,0 @@
1
- # Worker threads
2
-
3
- For most applications, `better-sqlite3` is fast enough to use in the main thread without blocking for a noticeable amount of time. However, if you need to perform very slow queries, you have the option of using [worker threads](https://nodejs.org/api/worker_threads.html) to keep things running smoothly. Below is an example of using a thread pool to perform queries in the background.
4
-
5
- ### worker.js
6
-
7
- The worker logic is very simple in our case. It accepts messages from the master thread, executes each message's SQL (with any given parameters), and sends back the query results.
8
-
9
- ```js
10
- const { parentPort } = require('worker_threads');
11
- const db = require('better-sqlite3-multiple-ciphers')('foobar.db');
12
-
13
- parentPort.on('message', ({ sql, parameters }) => {
14
- const result = db.prepare(sql).all(...parameters);
15
- parentPort.postMessage(result);
16
- });
17
- ```
18
-
19
- ### master.js
20
-
21
- The master thread is responsible for spawning workers, respawning threads that crash, and accepting query jobs.
22
-
23
- ```js
24
- const { Worker } = require('worker_threads');
25
- const os = require('os');
26
-
27
- /*
28
- Export a function that queues pending work.
29
- */
30
-
31
- const queue = [];
32
- exports.asyncQuery = (sql, ...parameters) => {
33
- return new Promise((resolve, reject) => {
34
- queue.push({
35
- resolve,
36
- reject,
37
- message: { sql, parameters },
38
- });
39
- drainQueue();
40
- });
41
- };
42
-
43
- /*
44
- Instruct workers to drain the queue.
45
- */
46
-
47
- let workers = [];
48
- function drainQueue() {
49
- for (const worker of workers) {
50
- worker.takeWork();
51
- }
52
- }
53
-
54
- /*
55
- Spawn workers that try to drain the queue.
56
- */
57
-
58
- os.cpus().forEach(function spawn() {
59
- const worker = new Worker('./worker.js');
60
-
61
- let job = null; // Current item from the queue
62
- let error = null; // Error that caused the worker to crash
63
-
64
- function takeWork() {
65
- if (!job && queue.length) {
66
- // If there's a job in the queue, send it to the worker
67
- job = queue.shift();
68
- worker.postMessage(job.message);
69
- }
70
- }
71
-
72
- worker
73
- .on('online', () => {
74
- workers.push({ takeWork });
75
- takeWork();
76
- })
77
- .on('message', (result) => {
78
- job.resolve(result);
79
- job = null;
80
- takeWork(); // Check if there's more work to do
81
- })
82
- .on('error', (err) => {
83
- console.error(err);
84
- error = err;
85
- })
86
- .on('exit', (code) => {
87
- workers = workers.filter(w => w.takeWork !== takeWork);
88
- if (job) {
89
- job.reject(error || new Error('worker died'));
90
- }
91
- if (code !== 0) {
92
- console.error(`worker exited with code ${code}`);
93
- spawn(); // Worker died, so spawn a new one
94
- }
95
- });
96
- });
97
- ```
package/docs/tips.md DELETED
@@ -1,35 +0,0 @@
1
- # Helpful tips for SQLite3
2
-
3
- ## Creating good tables
4
-
5
- It's a good idea to use `INTEGER PRIMARY KEY AUTOINCREMENT` as one of the columns in a table. This ensures two things:
6
-
7
- - `INTEGER PRIMARY KEY`: improved performance by reusing SQLite3's built-in `rowid` column.
8
- - `AUTOINCREMENT`: no future row will have the same ID as an old one that was deleted. This can prevent potential bugs and security breaches.
9
-
10
- If you don't use `INTEGER PRIMARY KEY`, then you *must* use `NOT NULL` in all of your your primary key columns. Otherwise you'll be victim to an SQLite3 bug that allows primary keys to be `NULL`.
11
-
12
- Any column with `INTEGER PRIMARY KEY` will automatically increment when setting its value to `NULL`. But without `AUTOINCREMENT`, the behavior only ensures uniqueness from currently existing rows.
13
-
14
- It should be noted that `NULL` values count as unique from each other. This has implications when using the `UNIQUE` contraint or any other equality test.
15
-
16
- ## Default values
17
-
18
- When a column has a `DEFAULT` value, it only gets applied when no value is specified for an `INSERT` statement. If the `INSERT` statement specifies a `NULL` value, the `DEFAULT` value is **NOT** used.
19
-
20
- ## Foreign keys
21
-
22
- Foreign key constraints are not enforced if the child's column value is `NULL`. To ensure that a relationship is always enforced, use `NOT NULL` on the child column.
23
-
24
- Example:
25
- ```sql
26
- CREATE TABLE comments (value TEXT, user_id INTEGER NOT NULL REFERENCES users);
27
- ```
28
-
29
- Foreign key clauses can be followed by `ON DELETE` and/or `ON UPDATE`, with the following possible values:
30
-
31
- - `SET NULL`: if the parent column is deleted or updated, the child column becomes `NULL`.
32
- - *NOTE: This still causes a constraint violation if the child column has `NOT NULL`*.
33
- - `SET DEFAULT`: if the parent column is updated or deleted, the child column becomes its `DEFAULT` value.
34
- - *NOTE: This still causes a constraint violation if the child column's `DEFAULT` value does not correspond with an actual parent row*.
35
- - `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.
@@ -1,23 +0,0 @@
1
- # Troubleshooting installation
2
-
3
- If you have trouble installing `better-sqlite3-multiple-ciphers`, follow this checklist:
4
-
5
- 1. Make sure you're using nodejs v10.20.1 or later
6
-
7
- 2. Make sure you have [`node-gyp`](https://github.com/nodejs/node-gyp#installation) globally installed, including all of [its dependencies](https://github.com/nodejs/node-gyp#on-unix). On Windows you may need to [configure some things manually](https://github.com/nodejs/node-gyp#on-windows). Use `npm ls node-gyp` to make sure none of your local packages installed an outdated version of `node-gyp` that is used over the global one.
8
-
9
- 3. If you're using [Electron](https://github.com/electron/electron), try running [`electron-rebuild`](https://www.npmjs.com/package/electron-rebuild)
10
-
11
- 4. If you're using Windows, follow these steps. Do them **in this order**, and **don't skip steps**.
12
-
13
- 1. Install the **latest** of node 10, 12, or 14.
14
- 2. Install **latest** Visual Studio Community and Desktop Development with C++ extension.
15
- 3. Install **latest** Python.
16
- 4. Run following commands:
17
- ```
18
- npm config set msvs_version 2019
19
- npm config set msbuild_path "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe"
20
- ```
21
- 5. Run `npm install`
22
-
23
- If none of these solved your problem, try browsing [previous issues](https://github.com/JoshuaWise/better-sqlite3/issues?q=is%3Aissue) or open a [new issue](https://github.com/JoshuaWise/better-sqlite3/issues/new).
package/docs/unsafe.md DELETED
@@ -1,16 +0,0 @@
1
- # Unsafe mode
2
-
3
- By default, `better-sqlite3` prevents you from doing things that might corrupt your database or cause undefined behavior. Such unsafe operations include:
4
-
5
- - Anything blocked by [`SQLITE_DBCONFIG_DEFENSIVE`](https://www.sqlite.org/c3ref/c_dbconfig_defensive.html#sqlitedbconfigdefensive)
6
- - Mutating the database while [iterating](https://github.com/JoshuaWise/better-sqlite3/blob/master/docs/api.md#iteratebindparameters---iterator) through a query's result set
7
-
8
- However, some advanced users might want to use these functionalities at their own risk. For this reason, users have the option of enabling "unsafe mode".
9
-
10
- ```js
11
- db.unsafeMode(); // Unsafe mode ON
12
- db.unsafeMode(true); // Unsafe mode ON
13
- db.unsafeMode(false); // Unsafe mode OFF
14
- ```
15
-
16
- Unsafe mode can be toggled at any time, and independently for each database connection. While toggled on, `better-sqlite3` will not prevent you from performing the dangerous operations listed above.
@@ -1,88 +0,0 @@
1
- #hdr
2
- #include <climits>
3
- #include <cstdio>
4
- #include <cstring>
5
- #include <string>
6
- #include <vector>
7
- #include <set>
8
- #include <unordered_map>
9
- #include <algorithm>
10
- #include <sqlite3.h>
11
- #include <node.h>
12
- #include <node_object_wrap.h>
13
- #include <node_buffer.h>
14
- #end
15
-
16
- #insert "util/macros.lzz"
17
- #insert "util/query-macros.lzz"
18
- #insert "util/constants.lzz"
19
- #insert "util/bind-map.lzz"
20
- struct Addon;
21
- class Statement;
22
- class Backup;
23
- #insert "objects/database.lzz"
24
- #insert "objects/statement.lzz"
25
- #insert "objects/statement-iterator.lzz"
26
- #insert "objects/backup.lzz"
27
- #insert "util/data-converter.lzz"
28
- #insert "util/custom-function.lzz"
29
- #insert "util/custom-aggregate.lzz"
30
- #insert "util/custom-table.lzz"
31
- #insert "util/data.lzz"
32
- #insert "util/binder.lzz"
33
-
34
- struct Addon {
35
- NODE_METHOD(JS_setErrorConstructor) {
36
- REQUIRE_ARGUMENT_FUNCTION(first, v8::Local<v8::Function> SqliteError);
37
- OnlyAddon->SqliteError.Reset(OnlyIsolate, SqliteError);
38
- }
39
-
40
- static void Cleanup(void* ptr) {
41
- Addon* addon = static_cast<Addon*>(ptr);
42
- for (Database* db : addon->dbs) db->CloseHandles();
43
- addon->dbs.clear();
44
- delete addon;
45
- }
46
-
47
- explicit Addon(v8::Isolate* isolate) :
48
- privileged_info(NULL),
49
- next_id(0),
50
- cs(isolate) {}
51
-
52
- inline sqlite3_uint64 NextId() {
53
- return next_id++;
54
- }
55
-
56
- CopyablePersistent<v8::Function> Statement;
57
- CopyablePersistent<v8::Function> StatementIterator;
58
- CopyablePersistent<v8::Function> Backup;
59
- CopyablePersistent<v8::Function> SqliteError;
60
- NODE_ARGUMENTS_POINTER privileged_info;
61
- sqlite3_uint64 next_id;
62
- CS cs;
63
- std::set<Database*, Database::CompareDatabase> dbs;
64
- };
65
-
66
- #src
67
- NODE_MODULE_INIT(/* exports, context */) {
68
- v8::Isolate* isolate = context->GetIsolate();
69
- v8::HandleScope scope(isolate);
70
-
71
- // Initialize addon instance.
72
- Addon* addon = new Addon(isolate);
73
- v8::Local<v8::External> data = v8::External::New(isolate, addon);
74
- node::AddEnvironmentCleanupHook(isolate, Addon::Cleanup, addon);
75
-
76
- // Create and export native-backed classes and functions.
77
- exports->Set(context, InternalizedFromLatin1(isolate, "Database"), Database::Init(isolate, data)).FromJust();
78
- exports->Set(context, InternalizedFromLatin1(isolate, "Statement"), Statement::Init(isolate, data)).FromJust();
79
- exports->Set(context, InternalizedFromLatin1(isolate, "StatementIterator"), StatementIterator::Init(isolate, data)).FromJust();
80
- exports->Set(context, InternalizedFromLatin1(isolate, "Backup"), Backup::Init(isolate, data)).FromJust();
81
- exports->Set(context, InternalizedFromLatin1(isolate, "setErrorConstructor"), v8::FunctionTemplate::New(isolate, Addon::JS_setErrorConstructor, data)->GetFunction(context).ToLocalChecked()).FromJust();
82
-
83
- // Store addon instance data.
84
- addon->Statement.Reset(isolate, exports->Get(context, InternalizedFromLatin1(isolate, "Statement")).ToLocalChecked().As<v8::Function>());
85
- addon->StatementIterator.Reset(isolate, exports->Get(context, InternalizedFromLatin1(isolate, "StatementIterator")).ToLocalChecked().As<v8::Function>());
86
- addon->Backup.Reset(isolate, exports->Get(context, InternalizedFromLatin1(isolate, "Backup")).ToLocalChecked().As<v8::Function>());
87
- }
88
- #end
@@ -1,138 +0,0 @@
1
- class Backup : public node::ObjectWrap {
2
- public:
3
-
4
- INIT(Init) {
5
- v8::Local<v8::FunctionTemplate> t = NewConstructorTemplate(isolate, data, JS_new, "Backup");
6
- SetPrototypeMethod(isolate, data, t, "transfer", JS_transfer);
7
- SetPrototypeMethod(isolate, data, t, "close", JS_close);
8
- return t->GetFunction(OnlyContext).ToLocalChecked();
9
- }
10
-
11
- // Used to support ordered containers.
12
- static inline bool Compare(Backup const * const a, Backup const * const b) {
13
- return a->id < b->id;
14
- }
15
-
16
- // Whenever this is used, db->RemoveBackup must be invoked beforehand.
17
- void CloseHandles() {
18
- if (alive) {
19
- alive = false;
20
- std::string filename(sqlite3_db_filename(dest_handle, "main"));
21
- sqlite3_backup_finish(backup_handle);
22
- int status = sqlite3_close(dest_handle);
23
- assert(status == SQLITE_OK); ((void)status);
24
- if (unlink) remove(filename.c_str());
25
- }
26
- }
27
-
28
- ~Backup() {
29
- if (alive) db->RemoveBackup(this);
30
- CloseHandles();
31
- }
32
-
33
- private:
34
-
35
- explicit Backup(
36
- Database* db,
37
- sqlite3* dest_handle,
38
- sqlite3_backup* backup_handle,
39
- sqlite3_uint64 id,
40
- bool unlink
41
- ) :
42
- node::ObjectWrap(),
43
- db(db),
44
- dest_handle(dest_handle),
45
- backup_handle(backup_handle),
46
- id(id),
47
- alive(true),
48
- unlink(unlink) {
49
- assert(db != NULL);
50
- assert(dest_handle != NULL);
51
- assert(backup_handle != NULL);
52
- db->AddBackup(this);
53
- }
54
-
55
- NODE_METHOD(JS_new) {
56
- UseAddon;
57
- if (!addon->privileged_info) return ThrowTypeError("Disabled constructor");
58
- assert(info.IsConstructCall());
59
- Database* db = Unwrap<Database>(addon->privileged_info->This());
60
- REQUIRE_DATABASE_OPEN(db->GetState());
61
- REQUIRE_DATABASE_NOT_BUSY(db->GetState());
62
-
63
- v8::Local<v8::Object> database = (*addon->privileged_info)[0].As<v8::Object>();
64
- v8::Local<v8::String> attachedName = (*addon->privileged_info)[1].As<v8::String>();
65
- v8::Local<v8::String> destFile = (*addon->privileged_info)[2].As<v8::String>();
66
- bool unlink = (*addon->privileged_info)[3].As<v8::Boolean>()->Value();
67
-
68
- UseIsolate;
69
- sqlite3* dest_handle;
70
- v8::String::Utf8Value dest_file(isolate, destFile);
71
- v8::String::Utf8Value attached_name(isolate, attachedName);
72
- int mask = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
73
-
74
- if (sqlite3_open_v2(*dest_file, &dest_handle, mask, NULL) != SQLITE_OK) {
75
- Database::ThrowSqliteError(addon, dest_handle);
76
- int status = sqlite3_close(dest_handle);
77
- assert(status == SQLITE_OK); ((void)status);
78
- return;
79
- }
80
-
81
- sqlite3_extended_result_codes(dest_handle, 1);
82
- sqlite3_limit(dest_handle, SQLITE_LIMIT_LENGTH, INT_MAX);
83
- sqlite3_backup* backup_handle = sqlite3_backup_init(dest_handle, "main", db->GetHandle(), *attached_name);
84
- if (backup_handle == NULL) {
85
- Database::ThrowSqliteError(addon, dest_handle);
86
- int status = sqlite3_close(dest_handle);
87
- assert(status == SQLITE_OK); ((void)status);
88
- return;
89
- }
90
-
91
- Backup* backup = new Backup(db, dest_handle, backup_handle, addon->NextId(), unlink);
92
- backup->Wrap(info.This());
93
- SetFrozen(isolate, OnlyContext, info.This(), addon->cs.database, database);
94
-
95
- info.GetReturnValue().Set(info.This());
96
- }
97
-
98
- NODE_METHOD(JS_transfer) {
99
- Backup* backup = Unwrap<Backup>(info.This());
100
- REQUIRE_ARGUMENT_INT32(first, int pages);
101
- REQUIRE_DATABASE_OPEN(backup->db->GetState());
102
- assert(backup->db->GetState()->busy == false);
103
- assert(backup->alive == true);
104
-
105
- sqlite3_backup* backup_handle = backup->backup_handle;
106
- int status = sqlite3_backup_step(backup_handle, pages) & 0xff;
107
-
108
- Addon* addon = backup->db->GetAddon();
109
- if (status == SQLITE_OK || status == SQLITE_DONE || status == SQLITE_BUSY) {
110
- int total_pages = sqlite3_backup_pagecount(backup_handle);
111
- int remaining_pages = sqlite3_backup_remaining(backup_handle);
112
- UseIsolate;
113
- UseContext;
114
- v8::Local<v8::Object> result = v8::Object::New(isolate);
115
- result->Set(ctx, addon->cs.totalPages.Get(isolate), v8::Int32::New(isolate, total_pages)).FromJust();
116
- result->Set(ctx, addon->cs.remainingPages.Get(isolate), v8::Int32::New(isolate, remaining_pages)).FromJust();
117
- info.GetReturnValue().Set(result);
118
- if (status == SQLITE_DONE) backup->unlink = false;
119
- } else {
120
- Database::ThrowSqliteError(addon, sqlite3_errstr(status), status);
121
- }
122
- }
123
-
124
- NODE_METHOD(JS_close) {
125
- Backup* backup = Unwrap<Backup>(info.This());
126
- assert(backup->db->GetState()->busy == false);
127
- if (backup->alive) backup->db->RemoveBackup(backup);
128
- backup->CloseHandles();
129
- info.GetReturnValue().Set(info.This());
130
- }
131
-
132
- Database* const db;
133
- sqlite3* const dest_handle;
134
- sqlite3_backup* const backup_handle;
135
- const sqlite3_uint64 id;
136
- bool alive;
137
- bool unlink;
138
- };