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,468 +0,0 @@
1
- class Database : public node::ObjectWrap {
2
- public:
3
-
4
- INIT(Init) {
5
- v8::Local<v8::FunctionTemplate> t = NewConstructorTemplate(isolate, data, JS_new, "Database");
6
- SetPrototypeMethod(isolate, data, t, "prepare", JS_prepare);
7
- SetPrototypeMethod(isolate, data, t, "exec", JS_exec);
8
- SetPrototypeMethod(isolate, data, t, "backup", JS_backup);
9
- SetPrototypeMethod(isolate, data, t, "serialize", JS_serialize);
10
- SetPrototypeMethod(isolate, data, t, "function", JS_function);
11
- SetPrototypeMethod(isolate, data, t, "aggregate", JS_aggregate);
12
- SetPrototypeMethod(isolate, data, t, "table", JS_table);
13
- SetPrototypeMethod(isolate, data, t, "loadExtension", JS_loadExtension);
14
- SetPrototypeMethod(isolate, data, t, "close", JS_close);
15
- SetPrototypeMethod(isolate, data, t, "defaultSafeIntegers", JS_defaultSafeIntegers);
16
- SetPrototypeMethod(isolate, data, t, "unsafeMode", JS_unsafeMode);
17
- SetPrototypeGetter(isolate, data, t, "open", JS_open);
18
- SetPrototypeGetter(isolate, data, t, "inTransaction", JS_inTransaction);
19
- return t->GetFunction(OnlyContext).ToLocalChecked();
20
- }
21
-
22
- // Used to support ordered containers.
23
- class CompareDatabase { public:
24
- bool operator() (Database const * const a, Database const * const b) const {
25
- return a < b;
26
- }
27
- };
28
- class CompareStatement { public:
29
- bool operator() (Statement const * const a, Statement const * const b) const {
30
- return Statement::Compare(a, b);
31
- }
32
- };
33
- class CompareBackup { public:
34
- bool operator() (Backup const * const a, Backup const * const b) const {
35
- return Backup::Compare(a, b);
36
- }
37
- };
38
-
39
- // Proper error handling logic for when an sqlite3 operation fails.
40
- void ThrowDatabaseError() {
41
- if (was_js_error) was_js_error = false;
42
- else ThrowSqliteError(addon, db_handle);
43
- }
44
- static void ThrowSqliteError(Addon* addon, sqlite3* db_handle) {
45
- assert(db_handle != NULL);
46
- ThrowSqliteError(addon, sqlite3_errmsg(db_handle), sqlite3_extended_errcode(db_handle));
47
- }
48
- static void ThrowSqliteError(Addon* addon, const char* message, int code) {
49
- assert(message != NULL);
50
- assert((code & 0xff) != SQLITE_OK);
51
- assert((code & 0xff) != SQLITE_ROW);
52
- assert((code & 0xff) != SQLITE_DONE);
53
- EasyIsolate;
54
- v8::Local<v8::Value> args[2] = {
55
- StringFromUtf8(isolate, message, -1),
56
- addon->cs.Code(isolate, code)
57
- };
58
- isolate->ThrowException(addon->SqliteError.Get(isolate)
59
- ->NewInstance(OnlyContext, 2, args)
60
- .ToLocalChecked());
61
- }
62
-
63
- // Allows Statements to log their executed SQL.
64
- bool Log(v8::Isolate* isolate, sqlite3_stmt* handle) {
65
- assert(was_js_error == false);
66
- if (!has_logger) return false;
67
- char* expanded = sqlite3_expanded_sql(handle);
68
- v8::Local<v8::Value> arg = StringFromUtf8(isolate, expanded ? expanded : sqlite3_sql(handle), -1);
69
- was_js_error = logger.Get(isolate).As<v8::Function>()
70
- ->Call(OnlyContext, v8::Undefined(isolate), 1, &arg)
71
- .IsEmpty();
72
- if (expanded) sqlite3_free(expanded);
73
- return was_js_error;
74
- }
75
-
76
- // Allow Statements to manage themselves when created and garbage collected.
77
- inline void AddStatement(Statement* stmt) { stmts.insert(stmts.end(), stmt); }
78
- inline void RemoveStatement(Statement* stmt) { stmts.erase(stmt); }
79
-
80
- // Allow Backups to manage themselves when created and garbage collected.
81
- inline void AddBackup(Backup* backup) { backups.insert(backups.end(), backup); }
82
- inline void RemoveBackup(Backup* backup) { backups.erase(backup); }
83
-
84
- // A view for Statements to see and modify Database state.
85
- // The order of these fields must exactly match their actual order.
86
- struct State {
87
- const bool open;
88
- bool busy;
89
- const bool safe_ints;
90
- const bool unsafe_mode;
91
- bool was_js_error;
92
- const bool has_logger;
93
- unsigned short iterators;
94
- Addon* const addon;
95
- };
96
- inline State* GetState() {
97
- return reinterpret_cast<State*>(&open);
98
- }
99
- inline sqlite3* GetHandle() {
100
- return db_handle;
101
- }
102
- inline Addon* GetAddon() {
103
- return addon;
104
- }
105
-
106
- // Whenever this is used, addon->dbs.erase() must be invoked beforehand.
107
- void CloseHandles() {
108
- if (open) {
109
- open = false;
110
- for (Statement* stmt : stmts) stmt->CloseHandles();
111
- for (Backup* backup : backups) backup->CloseHandles();
112
- stmts.clear();
113
- backups.clear();
114
- int status = sqlite3_close(db_handle);
115
- assert(status == SQLITE_OK); ((void)status);
116
- }
117
- }
118
-
119
- ~Database() {
120
- if (open) addon->dbs.erase(this);
121
- CloseHandles();
122
- }
123
-
124
- private:
125
-
126
- explicit Database(
127
- v8::Isolate* isolate,
128
- Addon* addon,
129
- sqlite3* db_handle,
130
- v8::Local<v8::Value> logger
131
- ) :
132
- node::ObjectWrap(),
133
- db_handle(db_handle),
134
- open(true),
135
- busy(false),
136
- safe_ints(false),
137
- unsafe_mode(false),
138
- was_js_error(false),
139
- has_logger(logger->IsFunction()),
140
- iterators(0),
141
- addon(addon),
142
- logger(isolate, logger),
143
- stmts(),
144
- backups() {
145
- assert(db_handle != NULL);
146
- addon->dbs.insert(this);
147
- }
148
-
149
- NODE_METHOD(JS_new) {
150
- assert(info.IsConstructCall());
151
- REQUIRE_ARGUMENT_STRING(first, v8::Local<v8::String> filename);
152
- REQUIRE_ARGUMENT_STRING(second, v8::Local<v8::String> filenameGiven);
153
- REQUIRE_ARGUMENT_BOOLEAN(third, bool in_memory);
154
- REQUIRE_ARGUMENT_BOOLEAN(fourth, bool readonly);
155
- REQUIRE_ARGUMENT_BOOLEAN(fifth, bool must_exist);
156
- REQUIRE_ARGUMENT_INT32(sixth, int timeout);
157
- REQUIRE_ARGUMENT_ANY(seventh, v8::Local<v8::Value> logger);
158
- REQUIRE_ARGUMENT_ANY(eighth, v8::Local<v8::Value> buffer);
159
-
160
- UseAddon;
161
- UseIsolate;
162
- sqlite3* db_handle;
163
- v8::String::Utf8Value utf8(isolate, filename);
164
- int mask = readonly ? SQLITE_OPEN_READONLY
165
- : must_exist ? SQLITE_OPEN_READWRITE
166
- : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
167
-
168
- if (sqlite3_open_v2(*utf8, &db_handle, mask, NULL) != SQLITE_OK) {
169
- ThrowSqliteError(addon, db_handle);
170
- int status = sqlite3_close(db_handle);
171
- assert(status == SQLITE_OK); ((void)status);
172
- return;
173
- }
174
-
175
- assert(sqlite3_db_mutex(db_handle) == NULL);
176
- sqlite3_extended_result_codes(db_handle, 1);
177
- sqlite3_busy_timeout(db_handle, timeout);
178
- sqlite3_limit(db_handle, SQLITE_LIMIT_LENGTH, MAX_BUFFER_SIZE < MAX_STRING_SIZE ? MAX_BUFFER_SIZE : MAX_STRING_SIZE);
179
- sqlite3_limit(db_handle, SQLITE_LIMIT_SQL_LENGTH, MAX_STRING_SIZE);
180
- int status = sqlite3_db_config(db_handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL);
181
- assert(status == SQLITE_OK);
182
- status = sqlite3_db_config(db_handle, SQLITE_DBCONFIG_DEFENSIVE, 1, NULL);
183
- assert(status == SQLITE_OK);
184
-
185
- if (node::Buffer::HasInstance(buffer) && !Deserialize(buffer.As<v8::Object>(), addon, db_handle, readonly)) {
186
- int status = sqlite3_close(db_handle);
187
- assert(status == SQLITE_OK); ((void)status);
188
- return;
189
- }
190
-
191
- UseContext;
192
- Database* db = new Database(isolate, addon, db_handle, logger);
193
- db->Wrap(info.This());
194
- SetFrozen(isolate, ctx, info.This(), addon->cs.memory, v8::Boolean::New(isolate, in_memory));
195
- SetFrozen(isolate, ctx, info.This(), addon->cs.readonly, v8::Boolean::New(isolate, readonly));
196
- SetFrozen(isolate, ctx, info.This(), addon->cs.name, filenameGiven);
197
-
198
- info.GetReturnValue().Set(info.This());
199
- }
200
-
201
- NODE_METHOD(JS_prepare) {
202
- REQUIRE_ARGUMENT_STRING(first, v8::Local<v8::String> source);
203
- REQUIRE_ARGUMENT_OBJECT(second, v8::Local<v8::Object> database);
204
- REQUIRE_ARGUMENT_BOOLEAN(third, bool pragmaMode);
205
- (void)source;
206
- (void)database;
207
- (void)pragmaMode;
208
- UseAddon;
209
- UseIsolate;
210
- v8::Local<v8::Function> c = addon->Statement.Get(isolate);
211
- addon->privileged_info = &info;
212
- v8::MaybeLocal<v8::Object> maybeStatement = c->NewInstance(OnlyContext, 0, NULL);
213
- addon->privileged_info = NULL;
214
- if (!maybeStatement.IsEmpty()) info.GetReturnValue().Set(maybeStatement.ToLocalChecked());
215
- }
216
-
217
- NODE_METHOD(JS_exec) {
218
- Database* db = Unwrap<Database>(info.This());
219
- REQUIRE_ARGUMENT_STRING(first, v8::Local<v8::String> source);
220
- REQUIRE_DATABASE_OPEN(db);
221
- REQUIRE_DATABASE_NOT_BUSY(db);
222
- REQUIRE_DATABASE_NO_ITERATORS_UNLESS_UNSAFE(db);
223
- db->busy = true;
224
-
225
- UseIsolate;
226
- v8::String::Utf8Value utf8(isolate, source);
227
- const char* sql = *utf8;
228
- const char* tail;
229
-
230
- int status;
231
- const bool has_logger = db->has_logger;
232
- sqlite3* const db_handle = db->db_handle;
233
- sqlite3_stmt* handle;
234
-
235
- for (;;) {
236
- while (IS_SKIPPED(*sql)) ++sql;
237
- status = sqlite3_prepare_v2(db_handle, sql, -1, &handle, &tail);
238
- sql = tail;
239
- if (!handle) break;
240
- if (has_logger && db->Log(isolate, handle)) {
241
- sqlite3_finalize(handle);
242
- status = -1;
243
- break;
244
- }
245
- do status = sqlite3_step(handle);
246
- while (status == SQLITE_ROW);
247
- status = sqlite3_finalize(handle);
248
- if (status != SQLITE_OK) break;
249
- }
250
-
251
- db->busy = false;
252
- if (status != SQLITE_OK) {
253
- db->ThrowDatabaseError();
254
- }
255
- }
256
-
257
- NODE_METHOD(JS_backup) {
258
- REQUIRE_ARGUMENT_OBJECT(first, v8::Local<v8::Object> database);
259
- REQUIRE_ARGUMENT_STRING(second, v8::Local<v8::String> attachedName);
260
- REQUIRE_ARGUMENT_STRING(third, v8::Local<v8::String> destFile);
261
- REQUIRE_ARGUMENT_BOOLEAN(fourth, bool unlink);
262
- (void)database;
263
- (void)attachedName;
264
- (void)destFile;
265
- (void)unlink;
266
- UseAddon;
267
- UseIsolate;
268
- v8::Local<v8::Function> c = addon->Backup.Get(isolate);
269
- addon->privileged_info = &info;
270
- v8::MaybeLocal<v8::Object> maybeBackup = c->NewInstance(OnlyContext, 0, NULL);
271
- addon->privileged_info = NULL;
272
- if (!maybeBackup.IsEmpty()) info.GetReturnValue().Set(maybeBackup.ToLocalChecked());
273
- }
274
-
275
- NODE_METHOD(JS_serialize) {
276
- Database* db = Unwrap<Database>(info.This());
277
- REQUIRE_ARGUMENT_STRING(first, v8::Local<v8::String> attachedName);
278
- REQUIRE_DATABASE_OPEN(db);
279
- REQUIRE_DATABASE_NOT_BUSY(db);
280
- REQUIRE_DATABASE_NO_ITERATORS(db);
281
-
282
- UseIsolate;
283
- v8::String::Utf8Value attached_name(isolate, attachedName);
284
- sqlite3_int64 length = -1;
285
- unsigned char* data = sqlite3_serialize(db->db_handle, *attached_name, &length, 0);
286
-
287
- if (!data && length) {
288
- ThrowError("Out of memory");
289
- return;
290
- }
291
-
292
- info.GetReturnValue().Set(
293
- node::Buffer::New(isolate, reinterpret_cast<char*>(data), length, FreeSerialization, NULL).ToLocalChecked()
294
- );
295
- }
296
-
297
- NODE_METHOD(JS_function) {
298
- Database* db = Unwrap<Database>(info.This());
299
- REQUIRE_ARGUMENT_FUNCTION(first, v8::Local<v8::Function> fn);
300
- REQUIRE_ARGUMENT_STRING(second, v8::Local<v8::String> nameString);
301
- REQUIRE_ARGUMENT_INT32(third, int argc);
302
- REQUIRE_ARGUMENT_INT32(fourth, int safe_ints);
303
- REQUIRE_ARGUMENT_BOOLEAN(fifth, bool deterministic);
304
- REQUIRE_ARGUMENT_BOOLEAN(sixth, bool direct_only);
305
- REQUIRE_DATABASE_OPEN(db);
306
- REQUIRE_DATABASE_NOT_BUSY(db);
307
- REQUIRE_DATABASE_NO_ITERATORS(db);
308
-
309
- UseIsolate;
310
- v8::String::Utf8Value name(isolate, nameString);
311
- int mask = SQLITE_UTF8;
312
- if (deterministic) mask |= SQLITE_DETERMINISTIC;
313
- if (direct_only) mask |= SQLITE_DIRECTONLY;
314
- safe_ints = safe_ints < 2 ? safe_ints : static_cast<int>(db->safe_ints);
315
-
316
- if (sqlite3_create_function_v2(db->db_handle, *name, argc, mask, new CustomFunction(isolate, db, *name, fn, safe_ints), CustomFunction::xFunc, NULL, NULL, CustomFunction::xDestroy) != SQLITE_OK) {
317
- db->ThrowDatabaseError();
318
- }
319
- }
320
-
321
- NODE_METHOD(JS_aggregate) {
322
- Database* db = Unwrap<Database>(info.This());
323
- REQUIRE_ARGUMENT_ANY(first, v8::Local<v8::Value> start);
324
- REQUIRE_ARGUMENT_FUNCTION(second, v8::Local<v8::Function> step);
325
- REQUIRE_ARGUMENT_ANY(third, v8::Local<v8::Value> inverse);
326
- REQUIRE_ARGUMENT_ANY(fourth, v8::Local<v8::Value> result);
327
- REQUIRE_ARGUMENT_STRING(fifth, v8::Local<v8::String> nameString);
328
- REQUIRE_ARGUMENT_INT32(sixth, int argc);
329
- REQUIRE_ARGUMENT_INT32(seventh, int safe_ints);
330
- REQUIRE_ARGUMENT_BOOLEAN(eighth, bool deterministic);
331
- REQUIRE_ARGUMENT_BOOLEAN(ninth, bool direct_only);
332
- REQUIRE_DATABASE_OPEN(db);
333
- REQUIRE_DATABASE_NOT_BUSY(db);
334
- REQUIRE_DATABASE_NO_ITERATORS(db);
335
-
336
- UseIsolate;
337
- v8::String::Utf8Value name(isolate, nameString);
338
- auto xInverse = inverse->IsFunction() ? CustomAggregate::xInverse : NULL;
339
- auto xValue = xInverse ? CustomAggregate::xValue : NULL;
340
- int mask = SQLITE_UTF8;
341
- if (deterministic) mask |= SQLITE_DETERMINISTIC;
342
- if (direct_only) mask |= SQLITE_DIRECTONLY;
343
- safe_ints = safe_ints < 2 ? safe_ints : static_cast<int>(db->safe_ints);
344
-
345
- if (sqlite3_create_window_function(db->db_handle, *name, argc, mask, new CustomAggregate(isolate, db, *name, start, step, inverse, result, safe_ints), CustomAggregate::xStep, CustomAggregate::xFinal, xValue, xInverse, CustomAggregate::xDestroy) != SQLITE_OK) {
346
- db->ThrowDatabaseError();
347
- }
348
- }
349
-
350
- NODE_METHOD(JS_table) {
351
- Database* db = Unwrap<Database>(info.This());
352
- REQUIRE_ARGUMENT_FUNCTION(first, v8::Local<v8::Function> factory);
353
- REQUIRE_ARGUMENT_STRING(second, v8::Local<v8::String> nameString);
354
- REQUIRE_ARGUMENT_BOOLEAN(third, bool eponymous);
355
- REQUIRE_DATABASE_OPEN(db);
356
- REQUIRE_DATABASE_NOT_BUSY(db);
357
- REQUIRE_DATABASE_NO_ITERATORS(db);
358
-
359
- UseIsolate;
360
- v8::String::Utf8Value name(isolate, nameString);
361
- sqlite3_module* module = eponymous ? &CustomTable::EPONYMOUS_MODULE : &CustomTable::MODULE;
362
-
363
- db->busy = true;
364
- if (sqlite3_create_module_v2(db->db_handle, *name, module, new CustomTable(isolate, db, *name, factory), CustomTable::Destructor) != SQLITE_OK) {
365
- db->ThrowDatabaseError();
366
- }
367
- db->busy = false;
368
- }
369
-
370
- NODE_METHOD(JS_loadExtension) {
371
- Database* db = Unwrap<Database>(info.This());
372
- v8::Local<v8::String> entryPoint;
373
- REQUIRE_ARGUMENT_STRING(first, v8::Local<v8::String> filename);
374
- if (info.Length() > 1) { REQUIRE_ARGUMENT_STRING(second, entryPoint); }
375
- REQUIRE_DATABASE_OPEN(db);
376
- REQUIRE_DATABASE_NOT_BUSY(db);
377
- REQUIRE_DATABASE_NO_ITERATORS(db);
378
- UseIsolate;
379
- char* error;
380
- int status = sqlite3_load_extension(
381
- db->db_handle,
382
- *v8::String::Utf8Value(isolate, filename),
383
- entryPoint.IsEmpty() ? NULL : *v8::String::Utf8Value(isolate, entryPoint),
384
- &error
385
- );
386
- if (status != SQLITE_OK) {
387
- ThrowSqliteError(db->addon, error, status);
388
- }
389
- sqlite3_free(error);
390
- }
391
-
392
- NODE_METHOD(JS_close) {
393
- Database* db = Unwrap<Database>(info.This());
394
- if (db->open) {
395
- REQUIRE_DATABASE_NOT_BUSY(db);
396
- REQUIRE_DATABASE_NO_ITERATORS(db);
397
- db->addon->dbs.erase(db);
398
- db->CloseHandles();
399
- }
400
- }
401
-
402
- NODE_METHOD(JS_defaultSafeIntegers) {
403
- Database* db = Unwrap<Database>(info.This());
404
- if (info.Length() == 0) db->safe_ints = true;
405
- else { REQUIRE_ARGUMENT_BOOLEAN(first, db->safe_ints); }
406
- }
407
-
408
- NODE_METHOD(JS_unsafeMode) {
409
- Database* db = Unwrap<Database>(info.This());
410
- if (info.Length() == 0) db->unsafe_mode = true;
411
- else { REQUIRE_ARGUMENT_BOOLEAN(first, db->unsafe_mode); }
412
- sqlite3_db_config(db->db_handle, SQLITE_DBCONFIG_DEFENSIVE, static_cast<int>(!db->unsafe_mode), NULL);
413
- }
414
-
415
- NODE_GETTER(JS_open) {
416
- info.GetReturnValue().Set(Unwrap<Database>(info.This())->open);
417
- }
418
-
419
- NODE_GETTER(JS_inTransaction) {
420
- Database* db = Unwrap<Database>(info.This());
421
- info.GetReturnValue().Set(db->open && !static_cast<bool>(sqlite3_get_autocommit(db->db_handle)));
422
- }
423
-
424
- static bool Deserialize(v8::Local<v8::Object> buffer, Addon* addon, sqlite3* db_handle, bool readonly) {
425
- size_t length = node::Buffer::Length(buffer);
426
- unsigned char* data = (unsigned char*)sqlite3_malloc64(length);
427
- unsigned int flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE;
428
-
429
- if (readonly) {
430
- flags |= SQLITE_DESERIALIZE_READONLY;
431
- }
432
- if (length) {
433
- if (!data) {
434
- ThrowError("Out of memory");
435
- return false;
436
- }
437
- memcpy(data, node::Buffer::Data(buffer), length);
438
- }
439
-
440
- int status = sqlite3_deserialize(db_handle, "main", data, length, length, flags);
441
- if (status != SQLITE_OK) {
442
- ThrowSqliteError(addon, status == SQLITE_ERROR ? "unable to deserialize database" : sqlite3_errstr(status), status);
443
- return false;
444
- }
445
-
446
- return true;
447
- }
448
-
449
- static void FreeSerialization(char* data, void* _) {
450
- sqlite3_free(data);
451
- }
452
-
453
- static const int MAX_BUFFER_SIZE = node::Buffer::kMaxLength > INT_MAX ? INT_MAX : static_cast<int>(node::Buffer::kMaxLength);
454
- static const int MAX_STRING_SIZE = v8::String::kMaxLength > INT_MAX ? INT_MAX : static_cast<int>(v8::String::kMaxLength);
455
-
456
- sqlite3* const db_handle;
457
- bool open;
458
- bool busy;
459
- bool safe_ints;
460
- bool unsafe_mode;
461
- bool was_js_error;
462
- const bool has_logger;
463
- unsigned short iterators;
464
- Addon* const addon;
465
- const CopyablePersistent<v8::Value> logger;
466
- std::set<Statement*, CompareStatement> stmts;
467
- std::set<Backup*, CompareBackup> backups;
468
- };
@@ -1,138 +0,0 @@
1
- class StatementIterator : public node::ObjectWrap {
2
- public:
3
-
4
- INIT(Init) {
5
- v8::Local<v8::FunctionTemplate> t = NewConstructorTemplate(isolate, data, JS_new, "StatementIterator");
6
- SetPrototypeMethod(isolate, data, t, "next", JS_next);
7
- SetPrototypeMethod(isolate, data, t, "return", JS_return);
8
- SetPrototypeSymbolMethod(isolate, data, t, v8::Symbol::GetIterator(isolate), JS_symbolIterator);
9
- return t->GetFunction(OnlyContext).ToLocalChecked();
10
- }
11
-
12
- // The ~Statement destructor currently covers any state this object creates.
13
- // Additionally, we actually DON'T want to revert stmt->locked or db_state
14
- // ->iterators in this destructor, to ensure deterministic database access.
15
- ~StatementIterator() {}
16
-
17
- private:
18
-
19
- explicit StatementIterator(Statement* stmt, bool bound) : node::ObjectWrap(),
20
- stmt(stmt),
21
- handle(stmt->handle),
22
- db_state(stmt->db->GetState()),
23
- bound(bound),
24
- safe_ints(stmt->safe_ints),
25
- mode(stmt->mode),
26
- alive(true),
27
- logged(!db_state->has_logger) {
28
- assert(stmt != NULL);
29
- assert(handle != NULL);
30
- assert(stmt->bound == bound);
31
- assert(stmt->alive == true);
32
- assert(stmt->locked == false);
33
- assert(db_state->iterators < USHRT_MAX);
34
- stmt->locked = true;
35
- db_state->iterators += 1;
36
- }
37
-
38
- NODE_METHOD(JS_new) {
39
- UseAddon;
40
- if (!addon->privileged_info) return ThrowTypeError("Disabled constructor");
41
- assert(info.IsConstructCall());
42
-
43
- StatementIterator* iter;
44
- {
45
- NODE_ARGUMENTS info = *addon->privileged_info;
46
- STATEMENT_START_LOGIC(REQUIRE_STATEMENT_RETURNS_DATA, DOES_ADD_ITERATOR);
47
- iter = new StatementIterator(stmt, bound);
48
- }
49
- UseIsolate;
50
- UseContext;
51
- iter->Wrap(info.This());
52
- SetFrozen(isolate, ctx, info.This(), addon->cs.statement, addon->privileged_info->This());
53
-
54
- info.GetReturnValue().Set(info.This());
55
- }
56
-
57
- NODE_METHOD(JS_next) {
58
- StatementIterator* iter = Unwrap<StatementIterator>(info.This());
59
- REQUIRE_DATABASE_NOT_BUSY(iter->db_state);
60
- if (iter->alive) iter->Next(info);
61
- else info.GetReturnValue().Set(DoneRecord(OnlyIsolate, iter->db_state->addon));
62
- }
63
-
64
- NODE_METHOD(JS_return) {
65
- StatementIterator* iter = Unwrap<StatementIterator>(info.This());
66
- REQUIRE_DATABASE_NOT_BUSY(iter->db_state);
67
- if (iter->alive) iter->Return(info);
68
- else info.GetReturnValue().Set(DoneRecord(OnlyIsolate, iter->db_state->addon));
69
- }
70
-
71
- NODE_METHOD(JS_symbolIterator) {
72
- info.GetReturnValue().Set(info.This());
73
- }
74
-
75
- void Next(NODE_ARGUMENTS info) {
76
- assert(alive == true);
77
- db_state->busy = true;
78
- if (!logged) {
79
- logged = true;
80
- if (stmt->db->Log(OnlyIsolate, handle)) {
81
- db_state->busy = false;
82
- Throw();
83
- return;
84
- }
85
- }
86
- int status = sqlite3_step(handle);
87
- db_state->busy = false;
88
- if (status == SQLITE_ROW) {
89
- UseIsolate;
90
- UseContext;
91
- info.GetReturnValue().Set(
92
- NewRecord(isolate, ctx, Data::GetRowJS(isolate, ctx, handle, safe_ints, mode), db_state->addon, false)
93
- );
94
- } else {
95
- if (status == SQLITE_DONE) Return(info);
96
- else Throw();
97
- }
98
- }
99
-
100
- void Return(NODE_ARGUMENTS info) {
101
- Cleanup();
102
- STATEMENT_RETURN_LOGIC(DoneRecord(OnlyIsolate, db_state->addon));
103
- }
104
-
105
- void Throw() {
106
- Cleanup();
107
- Database* db = stmt->db;
108
- STATEMENT_THROW_LOGIC();
109
- }
110
-
111
- void Cleanup() {
112
- assert(alive == true);
113
- alive = false;
114
- stmt->locked = false;
115
- db_state->iterators -= 1;
116
- sqlite3_reset(handle);
117
- }
118
-
119
- static inline v8::Local<v8::Object> NewRecord(v8::Isolate* isolate, v8::Local<v8::Context> ctx, v8::Local<v8::Value> value, Addon* addon, bool done) {
120
- v8::Local<v8::Object> record = v8::Object::New(isolate);
121
- record->Set(ctx, addon->cs.value.Get(isolate), value).FromJust();
122
- record->Set(ctx, addon->cs.done.Get(isolate), v8::Boolean::New(isolate, done)).FromJust();
123
- return record;
124
- }
125
-
126
- static inline v8::Local<v8::Object> DoneRecord(v8::Isolate* isolate, Addon* addon) {
127
- return NewRecord(isolate, OnlyContext, v8::Undefined(isolate), addon, true);
128
- }
129
-
130
- Statement* const stmt;
131
- sqlite3_stmt* const handle;
132
- Database::State* const db_state;
133
- const bool bound;
134
- const bool safe_ints;
135
- const char mode;
136
- bool alive;
137
- bool logged;
138
- };