better-sqlite3-multiple-ciphers 7.4.6-beta.0 → 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 +14 -7
  2. package/deps/download.sh +111 -108
  3. package/deps/setup.ps1 +10 -12
  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 -31
  81. package/test/50.misc.js +0 -44
@@ -1,159 +0,0 @@
1
- #define NODE_ARGUMENTS const v8::FunctionCallbackInfo<v8::Value>&
2
- #define NODE_ARGUMENTS_POINTER const v8::FunctionCallbackInfo<v8::Value>*
3
- #define NODE_METHOD(name) static void name(NODE_ARGUMENTS info)
4
- #define NODE_GETTER(name) static void name(v8::Local<v8::String> _, const v8::PropertyCallbackInfo<v8::Value>& info)
5
- #define INIT(name) static v8::Local<v8::Function> name(v8::Isolate* isolate, v8::Local<v8::External> data)
6
-
7
- #define EasyIsolate v8::Isolate* isolate = v8::Isolate::GetCurrent()
8
- #define OnlyIsolate info.GetIsolate()
9
- #define OnlyContext isolate->GetCurrentContext()
10
- #define OnlyAddon static_cast<Addon*>(info.Data().As<v8::External>()->Value())
11
- #define UseIsolate v8::Isolate* isolate = OnlyIsolate
12
- #define UseContext v8::Local<v8::Context> ctx = OnlyContext
13
- #define UseAddon Addon* addon = OnlyAddon
14
- #define Unwrap node::ObjectWrap::Unwrap
15
-
16
- inline v8::Local<v8::String> StringFromUtf8(v8::Isolate* isolate, const char* data, int length) {
17
- return v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal, length).ToLocalChecked();
18
- }
19
- inline v8::Local<v8::String> InternalizedFromUtf8(v8::Isolate* isolate, const char* data, int length) {
20
- return v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kInternalized, length).ToLocalChecked();
21
- }
22
- inline v8::Local<v8::Value> InternalizedFromUtf8OrNull(v8::Isolate* isolate, const char* data, int length) {
23
- if (data == NULL) return v8::Null(isolate);
24
- return InternalizedFromUtf8(isolate, data, length);
25
- }
26
- inline v8::Local<v8::String> InternalizedFromLatin1(v8::Isolate* isolate, const char* str) {
27
- return v8::String::NewFromOneByte(isolate, reinterpret_cast<const uint8_t*>(str), v8::NewStringType::kInternalized).ToLocalChecked();
28
- }
29
-
30
- #hdr
31
- template <class T> using CopyablePersistent = v8::Persistent<T, v8::CopyablePersistentTraits<T>>;
32
- #end
33
- inline void SetFrozen(v8::Isolate* isolate, v8::Local<v8::Context> ctx, v8::Local<v8::Object> obj, CopyablePersistent<v8::String>& key, v8::Local<v8::Value> value) {
34
- obj->DefineOwnProperty(ctx, key.Get(isolate), value, static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)).FromJust();
35
- }
36
-
37
- void ThrowError(const char* message) { EasyIsolate; isolate->ThrowException(v8::Exception::Error(StringFromUtf8(isolate, message, -1))); }
38
- void ThrowTypeError(const char* message) { EasyIsolate; isolate->ThrowException(v8::Exception::TypeError(StringFromUtf8(isolate, message, -1))); }
39
- void ThrowRangeError(const char* message) { EasyIsolate; isolate->ThrowException(v8::Exception::RangeError(StringFromUtf8(isolate, message, -1))); }
40
-
41
- #define REQUIRE_ARGUMENT_ANY(at, var) \
42
- if (info.Length() <= (at())) \
43
- return ThrowTypeError("Expected a "#at" argument"); \
44
- var = info[at()]
45
-
46
- #define _REQUIRE_ARGUMENT(at, var, Type, message, ...) \
47
- if (info.Length() <= (at()) || !info[at()]->Is##Type()) \
48
- return ThrowTypeError("Expected "#at" argument to be "#message); \
49
- var = (info[at()].As<v8::Type>())__VA_ARGS__
50
-
51
- #define REQUIRE_ARGUMENT_INT32(at, var) \
52
- _REQUIRE_ARGUMENT(at, var, Int32, a 32-bit signed integer, ->Value())
53
- #define REQUIRE_ARGUMENT_BOOLEAN(at, var) \
54
- _REQUIRE_ARGUMENT(at, var, Boolean, a boolean, ->Value())
55
- #define REQUIRE_ARGUMENT_STRING(at, var) \
56
- _REQUIRE_ARGUMENT(at, var, String, a string)
57
- #define REQUIRE_ARGUMENT_OBJECT(at, var) \
58
- _REQUIRE_ARGUMENT(at, var, Object, an object)
59
- #define REQUIRE_ARGUMENT_FUNCTION(at, var) \
60
- _REQUIRE_ARGUMENT(at, var, Function, a function)
61
-
62
- #define REQUIRE_DATABASE_OPEN(db) \
63
- if (!db->open) \
64
- return ThrowTypeError("The database connection is not open")
65
- #define REQUIRE_DATABASE_NOT_BUSY(db) \
66
- if (db->busy) \
67
- return ThrowTypeError("This database connection is busy executing a query")
68
- #define REQUIRE_DATABASE_NO_ITERATORS(db) \
69
- if (db->iterators) \
70
- return ThrowTypeError("This database connection is busy executing a query")
71
- #define REQUIRE_DATABASE_NO_ITERATORS_UNLESS_UNSAFE(db) \
72
- if (!db->unsafe_mode) { \
73
- REQUIRE_DATABASE_NO_ITERATORS(db); \
74
- } ((void)0)
75
- #define REQUIRE_STATEMENT_NOT_LOCKED(stmt) \
76
- if (stmt->locked) \
77
- return ThrowTypeError("This statement is busy executing a query")
78
-
79
- #define first() 0
80
- #define second() 1
81
- #define third() 2
82
- #define fourth() 3
83
- #define fifth() 4
84
- #define sixth() 5
85
- #define seventh() 6
86
- #define eighth() 7
87
- #define ninth() 8
88
- #define tenth() 9
89
-
90
- // Determines whether to skip the given character at the start of an SQL string.
91
- inline bool IS_SKIPPED(char c) {
92
- return c == ' ' || c == ';' || (c >= '\t' && c <= '\r');
93
- }
94
-
95
- // Allocates an empty array, without calling constructors/initializers.
96
- template<class T> inline T* ALLOC_ARRAY(size_t count) {
97
- return static_cast<T*>(::operator new[](count * sizeof(T)));
98
- }
99
-
100
- // Deallocates an array, without calling destructors.
101
- template<class T> inline void FREE_ARRAY(T* array_pointer) {
102
- ::operator delete[](array_pointer);
103
- }
104
-
105
- v8::Local<v8::FunctionTemplate> NewConstructorTemplate(
106
- v8::Isolate* isolate,
107
- v8::Local<v8::External> data,
108
- v8::FunctionCallback func,
109
- const char* name
110
- ) {
111
- v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate, func, data);
112
- t->InstanceTemplate()->SetInternalFieldCount(1);
113
- t->SetClassName(InternalizedFromLatin1(isolate, name));
114
- return t;
115
- }
116
- void SetPrototypeMethod(
117
- v8::Isolate* isolate,
118
- v8::Local<v8::External> data,
119
- v8::Local<v8::FunctionTemplate> recv,
120
- const char* name,
121
- v8::FunctionCallback func
122
- ) {
123
- v8::HandleScope scope(isolate);
124
- recv->PrototypeTemplate()->Set(
125
- InternalizedFromLatin1(isolate, name),
126
- v8::FunctionTemplate::New(isolate, func, data, v8::Signature::New(isolate, recv))
127
- );
128
- }
129
- void SetPrototypeSymbolMethod(
130
- v8::Isolate* isolate,
131
- v8::Local<v8::External> data,
132
- v8::Local<v8::FunctionTemplate> recv,
133
- v8::Local<v8::Symbol> symbol,
134
- v8::FunctionCallback func
135
- ) {
136
- v8::HandleScope scope(isolate);
137
- recv->PrototypeTemplate()->Set(
138
- symbol,
139
- v8::FunctionTemplate::New(isolate, func, data, v8::Signature::New(isolate, recv))
140
- );
141
- }
142
- void SetPrototypeGetter(
143
- v8::Isolate* isolate,
144
- v8::Local<v8::External> data,
145
- v8::Local<v8::FunctionTemplate> recv,
146
- const char* name,
147
- v8::AccessorGetterCallback func
148
- ) {
149
- v8::HandleScope scope(isolate);
150
- recv->InstanceTemplate()->SetAccessor(
151
- InternalizedFromLatin1(isolate, name),
152
- func,
153
- 0,
154
- data,
155
- v8::AccessControl::DEFAULT,
156
- v8::PropertyAttribute::None,
157
- v8::AccessorSignature::New(isolate, recv)
158
- );
159
- }
@@ -1,71 +0,0 @@
1
- #define STATEMENT_BIND(handle) \
2
- Binder binder(handle); \
3
- if (!binder.Bind(info, info.Length(), stmt)) { \
4
- sqlite3_clear_bindings(handle); \
5
- return; \
6
- } ((void)0)
7
-
8
- #define STATEMENT_THROW_LOGIC() \
9
- db->ThrowDatabaseError(); \
10
- if (!bound) { sqlite3_clear_bindings(handle); } \
11
- return
12
-
13
- #define STATEMENT_RETURN_LOGIC(return_value) \
14
- info.GetReturnValue().Set(return_value); \
15
- if (!bound) { sqlite3_clear_bindings(handle); } \
16
- return
17
-
18
- #define STATEMENT_START_LOGIC(RETURNS_DATA_CHECK, MUTATE_CHECK) \
19
- Statement* stmt = Unwrap<Statement>(info.This()); \
20
- RETURNS_DATA_CHECK(); \
21
- sqlite3_stmt* handle = stmt->handle; \
22
- Database* db = stmt->db; \
23
- REQUIRE_DATABASE_OPEN(db->GetState()); \
24
- REQUIRE_DATABASE_NOT_BUSY(db->GetState()); \
25
- MUTATE_CHECK(); \
26
- const bool bound = stmt->bound; \
27
- if (!bound) { \
28
- STATEMENT_BIND(handle); \
29
- } else if (info.Length() > 0) { \
30
- return ThrowTypeError("This statement already has bound parameters"); \
31
- } ((void)0)
32
-
33
-
34
- #define STATEMENT_THROW() db->GetState()->busy = false; STATEMENT_THROW_LOGIC()
35
- #define STATEMENT_RETURN(x) db->GetState()->busy = false; STATEMENT_RETURN_LOGIC(x)
36
- #define STATEMENT_START(x, y) \
37
- STATEMENT_START_LOGIC(x, y); \
38
- db->GetState()->busy = true; \
39
- UseIsolate; \
40
- if (db->Log(isolate, handle)) { \
41
- STATEMENT_THROW(); \
42
- } ((void)0)
43
-
44
-
45
- #define DOES_NOT_MUTATE() REQUIRE_STATEMENT_NOT_LOCKED(stmt)
46
- #define DOES_MUTATE() \
47
- assert(!stmt->locked); \
48
- REQUIRE_DATABASE_NO_ITERATORS_UNLESS_UNSAFE(db->GetState())
49
- #define DOES_ADD_ITERATOR() \
50
- DOES_NOT_MUTATE(); \
51
- if (db->GetState()->iterators == USHRT_MAX) \
52
- return ThrowRangeError("Too many active database iterators")
53
- #define REQUIRE_STATEMENT_RETURNS_DATA() \
54
- if (!stmt->returns_data) \
55
- return ThrowTypeError("This statement does not return data. Use run() instead")
56
- #define ALLOW_ANY_STATEMENT() \
57
- ((void)0)
58
-
59
-
60
- #define _FUNCTION_START(type) \
61
- type* self = static_cast<type*>(sqlite3_user_data(invocation)); \
62
- v8::Isolate* isolate = self->isolate; \
63
- v8::HandleScope scope(isolate)
64
-
65
- #define FUNCTION_START() \
66
- _FUNCTION_START(CustomFunction)
67
-
68
- #define AGGREGATE_START() \
69
- _FUNCTION_START(CustomAggregate); \
70
- Accumulator* acc = self->GetAccumulator(invocation); \
71
- if (acc->value.IsEmpty()) return
package/test/00.setup.js DELETED
@@ -1,25 +0,0 @@
1
- 'use strict';
2
- const fs = require('fs-extra');
3
- const path = require('path');
4
- const os = require('os');
5
- const chai = require('chai');
6
-
7
- const isWindows = os.platform().startsWith('win');
8
- const tempDir = path.join(__dirname, '..', 'temp');
9
- let dbId = 0;
10
-
11
- global.expect = chai.expect;
12
- global.util = {
13
- current: () => path.join(tempDir, `${dbId}.db`),
14
- next: () => (++dbId, global.util.current()),
15
- itUnix: isWindows ? it.skip : it,
16
- };
17
-
18
- before(function () {
19
- fs.removeSync(tempDir);
20
- fs.ensureDirSync(tempDir);
21
- });
22
-
23
- after(function () {
24
- fs.removeSync(tempDir);
25
- });
@@ -1,27 +0,0 @@
1
- 'use strict';
2
- const { expect } = require('chai');
3
- const { SqliteError } = require('../.');
4
-
5
- describe('SqliteError', function () {
6
- it('should be a subclass of Error', function () {
7
- expect(SqliteError).to.be.a('function');
8
- expect(SqliteError).to.not.equal(Error);
9
- expect(SqliteError.prototype).to.be.an.instanceof(Error);
10
- expect(SqliteError('foo', 'bar')).to.be.an.instanceof(Error);
11
- expect(new SqliteError('foo', 'bar')).to.be.an.instanceof(Error);
12
- });
13
- it('should have the correct name', function () {
14
- expect(SqliteError.prototype.name).to.equal('SqliteError');
15
- });
16
- it('should accept two arguments for setting the message and error code', function () {
17
- const err = SqliteError('foobar', 'baz');
18
- expect(err.message).to.equal('foobar');
19
- expect(err.code).to.equal('baz');
20
- expect(SqliteError(123, 'baz').message).to.equal('123');
21
- expect(() => SqliteError('foo')).to.throw(TypeError);
22
- expect(() => SqliteError('foo', 123)).to.throw(TypeError);
23
- });
24
- it('should capture stack traces', function () {
25
- expect(SqliteError(null, 'baz').stack).to.be.a('string');
26
- });
27
- });
@@ -1,159 +0,0 @@
1
- 'use strict';
2
- const { existsSync } = require('fs');
3
- const Database = require('../.');
4
-
5
- describe('new Database()', function () {
6
- afterEach(function () {
7
- if (this.db) this.db.close();
8
- });
9
-
10
- it('should throw when given invalid argument types', function () {
11
- expect(() => (this.db = new Database('', ''))).to.throw(TypeError);
12
- expect(() => (this.db = new Database({}, ''))).to.throw(TypeError);
13
- expect(() => (this.db = new Database({}, {}))).to.throw(TypeError);
14
- expect(() => (this.db = new Database({}))).to.throw(TypeError);
15
- expect(() => (this.db = new Database(0))).to.throw(TypeError);
16
- expect(() => (this.db = new Database(123))).to.throw(TypeError);
17
- expect(() => (this.db = new Database(new String(util.next())))).to.throw(TypeError);
18
- expect(() => (this.db = new Database(() => util.next()))).to.throw(TypeError);
19
- expect(() => (this.db = new Database([util.next()]))).to.throw(TypeError);
20
- });
21
- it('should throw when boolean options are provided as non-booleans', function () {
22
- expect(() => (this.db = new Database(util.next(), { readOnly: false }))).to.throw(TypeError);
23
- expect(() => (this.db = new Database(util.next(), { readonly: undefined }))).to.throw(TypeError);
24
- expect(() => (this.db = new Database(util.next(), { fileMustExist: undefined }))).to.throw(TypeError);
25
- });
26
- it('should allow anonymous temporary databases to be created', function () {
27
- for (const args of [[''], [], [null], [undefined], ['', { timeout: 2000 }]]) {
28
- const db = this.db = new Database(...args);
29
- expect(db.name).to.equal('');
30
- expect(db.memory).to.be.true;
31
- expect(db.readonly).to.be.false;
32
- expect(db.open).to.be.true;
33
- expect(db.inTransaction).to.be.false;
34
- expect(existsSync('')).to.be.false;
35
- expect(existsSync('null')).to.be.false;
36
- expect(existsSync('undefined')).to.be.false;
37
- expect(existsSync('[object Object]')).to.be.false;
38
- db.close();
39
- }
40
- });
41
- it('should allow anonymous in-memory databases to be created', function () {
42
- const db = this.db = new Database(':memory:');
43
- expect(db.name).to.equal(':memory:');
44
- expect(db.memory).to.be.true;
45
- expect(db.readonly).to.be.false;
46
- expect(db.open).to.be.true;
47
- expect(db.inTransaction).to.be.false;
48
- expect(existsSync(':memory:')).to.be.false;
49
- });
50
- it('should allow disk-bound databases to be created', function () {
51
- expect(existsSync(util.next())).to.be.false;
52
- const db = this.db = new Database(util.current());
53
- expect(db.name).to.equal(util.current());
54
- expect(db.memory).to.be.false;
55
- expect(db.readonly).to.be.false;
56
- expect(db.open).to.be.true;
57
- expect(db.inTransaction).to.be.false;
58
- expect(existsSync(util.current())).to.be.true;
59
- });
60
- it('should allow readonly database connections to be created', function () {
61
- expect(existsSync(util.next())).to.be.false;
62
- expect(() => (this.db = new Database(util.current(), { readonly: true }))).to.throw(Database.SqliteError).with.property('code', 'SQLITE_CANTOPEN');
63
- (new Database(util.current())).close();
64
- expect(existsSync(util.current())).to.be.true;
65
- const db = this.db = new Database(util.current(), { readonly: true });
66
- expect(db.name).to.equal(util.current());
67
- expect(db.memory).to.be.false;
68
- expect(db.readonly).to.be.true;
69
- expect(db.open).to.be.true;
70
- expect(db.inTransaction).to.be.false;
71
- expect(existsSync(util.current())).to.be.true;
72
- });
73
- it('should not allow the "readonly" option for in-memory databases', function () {
74
- expect(existsSync(util.next())).to.be.false;
75
- expect(() => (this.db = new Database(':memory:', { readonly: true }))).to.throw(TypeError);
76
- expect(() => (this.db = new Database('', { readonly: true }))).to.throw(TypeError);
77
- expect(existsSync(util.current())).to.be.false;
78
- });
79
- it('should accept the "fileMustExist" option', function () {
80
- expect(existsSync(util.next())).to.be.false;
81
- expect(() => (this.db = new Database(util.current(), { fileMustExist: true }))).to.throw(Database.SqliteError).with.property('code', 'SQLITE_CANTOPEN');
82
- (new Database(util.current())).close();
83
- expect(existsSync(util.current())).to.be.true;
84
- const db = this.db = new Database(util.current(), { fileMustExist: true });
85
- expect(db.name).to.equal(util.current());
86
- expect(db.memory).to.be.false;
87
- expect(db.readonly).to.be.false;
88
- expect(db.open).to.be.true;
89
- expect(db.inTransaction).to.be.false;
90
- expect(existsSync(util.current())).to.be.true;
91
- });
92
- util.itUnix('should accept the "timeout" option', function () {
93
- this.slow(4000);
94
- const testTimeout = (timeout) => {
95
- const db = new Database(util.current(), { timeout });
96
- try {
97
- const start = Date.now();
98
- expect(() => db.exec('BEGIN EXCLUSIVE')).to.throw(Database.SqliteError).with.property('code', 'SQLITE_BUSY');
99
- const end = Date.now();
100
- expect(end - start).to.be.closeTo(timeout, 200);
101
- } finally {
102
- db.close();
103
- }
104
- };
105
- const blocker = this.db = new Database(util.next(), { timeout: 0x7fffffff });
106
- blocker.exec('BEGIN EXCLUSIVE');
107
- testTimeout(0);
108
- testTimeout(1000);
109
- blocker.close();
110
- expect(() => (this.db = new Database(util.current(), { timeout: undefined }))).to.throw(TypeError);
111
- expect(() => (this.db = new Database(util.current(), { timeout: null }))).to.throw(TypeError);
112
- expect(() => (this.db = new Database(util.current(), { timeout: NaN }))).to.throw(TypeError);
113
- expect(() => (this.db = new Database(util.current(), { timeout: '75' }))).to.throw(TypeError);
114
- expect(() => (this.db = new Database(util.current(), { timeout: -1 }))).to.throw(TypeError);
115
- expect(() => (this.db = new Database(util.current(), { timeout: 75.01 }))).to.throw(TypeError);
116
- expect(() => (this.db = new Database(util.current(), { timeout: 0x80000000 }))).to.throw(RangeError);
117
- });
118
- it('should throw an Error if the directory does not exist', function () {
119
- expect(existsSync(util.next())).to.be.false;
120
- const filepath = `temp/nonexistent/abcfoobar123/${util.current()}`;
121
- expect(() => (this.db = new Database(filepath))).to.throw(TypeError);
122
- expect(existsSync(filepath)).to.be.false;
123
- expect(existsSync(util.current())).to.be.false;
124
- });
125
- it('should have a proper prototype chain', function () {
126
- const db = this.db = new Database(util.next());
127
- expect(db).to.be.an.instanceof(Database);
128
- expect(db.constructor).to.equal(Database);
129
- expect(Database.prototype.constructor).to.equal(Database);
130
- expect(Database.prototype.close).to.be.a('function');
131
- expect(Database.prototype.close).to.equal(db.close);
132
- expect(Database.prototype).to.equal(Object.getPrototypeOf(db));
133
- });
134
- it('should work properly when called as a function', function () {
135
- const db = this.db = Database(util.next());
136
- expect(db).to.be.an.instanceof(Database);
137
- expect(db.constructor).to.equal(Database);
138
- expect(Database.prototype.close).to.equal(db.close);
139
- expect(Database.prototype).to.equal(Object.getPrototypeOf(db));
140
- });
141
- it('should work properly when subclassed', function () {
142
- class MyDatabase extends Database {
143
- foo() {
144
- return 999;
145
- }
146
- }
147
- const db = this.db = new MyDatabase(util.next());
148
- expect(db).to.be.an.instanceof(Database);
149
- expect(db).to.be.an.instanceof(MyDatabase);
150
- expect(db.constructor).to.equal(MyDatabase);
151
- expect(Database.prototype.close).to.equal(db.close);
152
- expect(MyDatabase.prototype.close).to.equal(db.close);
153
- expect(Database.prototype.foo).to.be.undefined;
154
- expect(MyDatabase.prototype.foo).to.equal(db.foo);
155
- expect(Database.prototype).to.equal(Object.getPrototypeOf(MyDatabase.prototype));
156
- expect(MyDatabase.prototype).to.equal(Object.getPrototypeOf(db));
157
- expect(db.foo()).to.equal(999);
158
- });
159
- });
@@ -1,68 +0,0 @@
1
- 'use strict';
2
- const { existsSync } = require('fs');
3
- const Database = require('../.');
4
-
5
- describe('Database#close()', function () {
6
- beforeEach(function () {
7
- this.db = new Database(util.next());
8
- });
9
- afterEach(function () {
10
- this.db.close();
11
- });
12
-
13
- it('should cause db.open to return false', function () {
14
- expect(this.db.open).to.be.true;
15
- this.db.close();
16
- expect(this.db.open).to.be.false;
17
- });
18
- it('should return the database object', function () {
19
- expect(this.db.open).to.be.true;
20
- expect(this.db.close()).to.equal(this.db);
21
- expect(this.db.open).to.be.false;
22
- expect(this.db.close()).to.equal(this.db);
23
- expect(this.db.open).to.be.false;
24
- });
25
- it('should prevent any further database operations', function () {
26
- this.db.close();
27
- expect(() => this.db.exec('CREATE TABLE people (name TEXT)')).to.throw(TypeError);
28
- expect(() => this.db.prepare('CREATE TABLE cats (name TEXT)')).to.throw(TypeError);
29
- expect(() => this.db.transaction(() => {})).to.throw(TypeError);
30
- expect(() => this.db.pragma('cache_size')).to.throw(TypeError);
31
- expect(() => this.db.function('foo', () => {})).to.throw(TypeError);
32
- expect(() => this.db.aggregate('foo', { step: () => {} })).to.throw(TypeError);
33
- expect(() => this.db.table('foo', () => {})).to.throw(TypeError);
34
- });
35
- it('should prevent any existing statements from running', function () {
36
- this.db.prepare('CREATE TABLE people (name TEXT)').run();
37
- const stmt1 = this.db.prepare('SELECT * FROM people');
38
- const stmt2 = this.db.prepare("INSERT INTO people VALUES ('foobar')");
39
-
40
- this.db.prepare('SELECT * FROM people').bind();
41
- this.db.prepare("INSERT INTO people VALUES ('foobar')").bind();
42
- this.db.prepare('SELECT * FROM people').get();
43
- this.db.prepare('SELECT * FROM people').all();
44
- this.db.prepare('SELECT * FROM people').iterate().return();
45
- this.db.prepare("INSERT INTO people VALUES ('foobar')").run();
46
-
47
- this.db.close();
48
-
49
- expect(() => stmt1.bind()).to.throw(TypeError);
50
- expect(() => stmt2.bind()).to.throw(TypeError);
51
- expect(() => stmt1.get()).to.throw(TypeError);
52
- expect(() => stmt1.all()).to.throw(TypeError);
53
- expect(() => stmt1.iterate()).to.throw(TypeError);
54
- expect(() => stmt2.run()).to.throw(TypeError);
55
- });
56
- it('should delete the database\'s associated temporary files', function () {
57
- expect(existsSync(util.current())).to.be.true;
58
- this.db.pragma('journal_mode = WAL');
59
- this.db.prepare('CREATE TABLE people (name TEXT)').run();
60
- this.db.prepare('INSERT INTO people VALUES (?)').run('foobar');
61
- expect(existsSync(`${util.current()}-wal`)).to.be.true;
62
-
63
- this.db.close();
64
-
65
- expect(existsSync(util.current())).to.be.true;
66
- expect(existsSync(`${util.current()}-wal`)).to.be.false;
67
- });
68
- });
@@ -1,65 +0,0 @@
1
- 'use strict';
2
- const Database = require('../.');
3
-
4
- describe('Database#pragma()', function () {
5
- beforeEach(function () {
6
- this.db = new Database(util.next());
7
- });
8
- afterEach(function () {
9
- this.db.close();
10
- });
11
-
12
- it('should throw an exception if a string is not provided', function () {
13
- expect(() => this.db.pragma(123)).to.throw(TypeError);
14
- expect(() => this.db.pragma(0)).to.throw(TypeError);
15
- expect(() => this.db.pragma(null)).to.throw(TypeError);
16
- expect(() => this.db.pragma()).to.throw(TypeError);
17
- expect(() => this.db.pragma(new String('cache_size'))).to.throw(TypeError);
18
- });
19
- it('should throw an exception if boolean options are provided as non-booleans', function () {
20
- expect(() => this.db.pragma('cache_size', { simple: undefined })).to.throw(TypeError);
21
- });
22
- it('should throw an exception if invalid/redundant SQL is provided', function () {
23
- expect(() => this.db.pragma('PRAGMA cache_size')).to.throw(Database.SqliteError).with.property('code', 'SQLITE_ERROR');
24
- expect(() => this.db.pragma('cache_size; PRAGMA cache_size')).to.throw(RangeError);
25
- });
26
- it('should execute the pragma, returning rows of results', function () {
27
- const rows = this.db.pragma('cache_size');
28
- expect(rows).to.be.an('array');
29
- expect(rows[0]).to.be.an('object');
30
- expect(rows[0].cache_size).to.be.a('number');
31
- expect(rows[0].cache_size).to.equal(-16000);
32
- });
33
- it('should optionally return simpler results', function () {
34
- expect(this.db.pragma('cache_size', { simple: false })).to.be.an('array');
35
- const cache_size = this.db.pragma('cache_size', { simple: true });
36
- expect(cache_size).to.be.a('number');
37
- expect(cache_size).to.equal(-16000);
38
- expect(() => this.db.pragma('cache_size', true)).to.throw(TypeError);
39
- expect(() => this.db.pragma('cache_size', 123)).to.throw(TypeError);
40
- expect(() => this.db.pragma('cache_size', function () {})).to.throw(TypeError);
41
- expect(() => this.db.pragma('cache_size', NaN)).to.throw(TypeError);
42
- expect(() => this.db.pragma('cache_size', 'true')).to.throw(TypeError);
43
- });
44
- it('should obey PRAGMA changes', function () {
45
- expect(this.db.pragma('cache_size', { simple: true })).to.equal(-16000);
46
- this.db.pragma('cache_size = -8000');
47
- expect(this.db.pragma('cache_size', { simple: true })).to.equal(-8000);
48
- expect(this.db.pragma('journal_mode', { simple: true })).to.equal('delete');
49
- this.db.pragma('journal_mode = wal');
50
- expect(this.db.pragma('journal_mode', { simple: true })).to.equal('wal');
51
- });
52
- it('should respect readonly connections', function () {
53
- this.db.close();
54
- this.db = new Database(util.current(), { readonly: true, fileMustExist: true });
55
- expect(this.db.pragma('cache_size', { simple: true })).to.equal(-16000);
56
- this.db.pragma('cache_size = -8000');
57
- expect(this.db.pragma('cache_size', { simple: true })).to.equal(-8000);
58
- expect(this.db.pragma('journal_mode', { simple: true })).to.equal('delete');
59
- expect(() => this.db.pragma('journal_mode = wal')).to.throw(Database.SqliteError).with.property('code', 'SQLITE_READONLY');
60
- expect(this.db.pragma('journal_mode', { simple: true })).to.equal('delete');
61
- });
62
- it('should return undefined if no rows exist and simpler results are desired', function () {
63
- expect(this.db.pragma('table_info', { simple: true })).to.be.undefined;
64
- });
65
- });
@@ -1,60 +0,0 @@
1
- 'use strict';
2
- const Database = require('../.');
3
-
4
- describe('Database#prepare()', function () {
5
- beforeEach(function () {
6
- this.db = new Database(util.next());
7
- });
8
- afterEach(function () {
9
- this.db.close();
10
- });
11
-
12
- function assertStmt(stmt, source, db, reader, readonly) {
13
- expect(stmt.source).to.equal(source);
14
- expect(stmt.constructor.name).to.equal('Statement');
15
- expect(stmt.database).to.equal(db);
16
- expect(stmt.reader).to.equal(reader);
17
- expect(stmt.readonly).to.equal(readonly);
18
- expect(() => new stmt.constructor(source)).to.throw(TypeError);
19
- }
20
-
21
- it('should throw an exception if a string is not provided', function () {
22
- expect(() => this.db.prepare(123)).to.throw(TypeError);
23
- expect(() => this.db.prepare(0)).to.throw(TypeError);
24
- expect(() => this.db.prepare(null)).to.throw(TypeError);
25
- expect(() => this.db.prepare()).to.throw(TypeError);
26
- expect(() => this.db.prepare(new String('CREATE TABLE people (name TEXT)'))).to.throw(TypeError);
27
- });
28
- it('should throw an exception if invalid SQL is provided', function () {
29
- expect(() => this.db.prepare('CREATE TABLE people (name TEXT')).to.throw(Database.SqliteError).with.property('code', 'SQLITE_ERROR');
30
- expect(() => this.db.prepare('INSERT INTO people VALUES (?)')).to.throw(Database.SqliteError).with.property('code', 'SQLITE_ERROR');
31
- });
32
- it('should throw an exception if no statements are provided', function () {
33
- expect(() => this.db.prepare('')).to.throw(RangeError);
34
- expect(() => this.db.prepare(';')).to.throw(RangeError);
35
- });
36
- it('should throw an exception if more than one statement is provided', function () {
37
- expect(() => this.db.prepare('CREATE TABLE people (name TEXT);CREATE TABLE animals (name TEXT)')).to.throw(RangeError);
38
- expect(() => this.db.prepare('CREATE TABLE people (name TEXT);/')).to.throw(RangeError);
39
- expect(() => this.db.prepare('CREATE TABLE people (name TEXT);-')).to.throw(RangeError);
40
- });
41
- it('should create a prepared Statement object', function () {
42
- const stmt1 = this.db.prepare('CREATE TABLE people (name TEXT) ');
43
- const stmt2 = this.db.prepare('CREATE TABLE people (name TEXT); ');
44
- assertStmt(stmt1, 'CREATE TABLE people (name TEXT) ', this.db, false, false);
45
- assertStmt(stmt2, 'CREATE TABLE people (name TEXT); ', this.db, false, false);
46
- expect(stmt1).to.not.equal(stmt2);
47
- expect(stmt1).to.not.equal(this.db.prepare('CREATE TABLE people (name TEXT) '));
48
- });
49
- it('should create a prepared Statement object with just an expression', function () {
50
- const stmt = this.db.prepare('SELECT 555');
51
- assertStmt(stmt, 'SELECT 555', this.db, true, true);
52
- });
53
- it('should set the correct values for "reader" and "readonly"', function () {
54
- this.db.exec('CREATE TABLE data (value)');
55
- assertStmt(this.db.prepare('SELECT 555'), 'SELECT 555', this.db, true, true);
56
- assertStmt(this.db.prepare('BEGIN'), 'BEGIN', this.db, false, true);
57
- assertStmt(this.db.prepare('BEGIN EXCLUSIVE'), 'BEGIN EXCLUSIVE', this.db, false, false);
58
- assertStmt(this.db.prepare('DELETE FROM data RETURNING *'), 'DELETE FROM data RETURNING *', this.db, true, false);
59
- });
60
- });