better-sqlite3-multiple-ciphers 12.4.1 → 12.5.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.
@@ -1,383 +1,383 @@
1
- Statement::Statement(
2
- Database* db,
3
- sqlite3_stmt* handle,
4
- sqlite3_uint64 id,
5
- bool returns_data
6
- ) :
7
- node::ObjectWrap(),
8
- db(db),
9
- handle(handle),
10
- extras(new Extras(id)),
11
- alive(true),
12
- locked(false),
13
- bound(false),
14
- has_bind_map(false),
15
- safe_ints(db->GetState()->safe_ints),
16
- mode(Data::FLAT),
17
- returns_data(returns_data) {
18
- assert(db != NULL);
19
- assert(handle != NULL);
20
- assert(db->GetState()->open);
21
- assert(!db->GetState()->busy);
22
- db->AddStatement(this);
23
- }
24
-
25
- Statement::~Statement() {
26
- if (alive) db->RemoveStatement(this);
27
- CloseHandles();
28
- delete extras;
29
- }
30
-
31
- // Whenever this is used, db->RemoveStatement must be invoked beforehand.
32
- void Statement::CloseHandles() {
33
- if (alive) {
34
- alive = false;
35
- sqlite3_finalize(handle);
36
- }
37
- }
38
-
39
- // Returns the Statement's bind map (creates it upon first execution).
40
- BindMap* Statement::GetBindMap(v8::Isolate* isolate) {
41
- if (has_bind_map) return &extras->bind_map;
42
- BindMap* bind_map = &extras->bind_map;
43
- int param_count = sqlite3_bind_parameter_count(handle);
44
- for (int i = 1; i <= param_count; ++i) {
45
- const char* name = sqlite3_bind_parameter_name(handle, i);
46
- if (name != NULL) bind_map->Add(isolate, name + 1, i);
47
- }
48
- has_bind_map = true;
49
- return bind_map;
50
- }
51
-
52
- Statement::Extras::Extras(sqlite3_uint64 id)
53
- : bind_map(0), id(id) {}
54
-
55
- INIT(Statement::Init) {
56
- v8::Local<v8::FunctionTemplate> t = NewConstructorTemplate(isolate, data, JS_new, "Statement");
57
- SetPrototypeMethod(isolate, data, t, "run", JS_run);
58
- SetPrototypeMethod(isolate, data, t, "get", JS_get);
59
- SetPrototypeMethod(isolate, data, t, "all", JS_all);
60
- SetPrototypeMethod(isolate, data, t, "iterate", JS_iterate);
61
- SetPrototypeMethod(isolate, data, t, "bind", JS_bind);
62
- SetPrototypeMethod(isolate, data, t, "pluck", JS_pluck);
63
- SetPrototypeMethod(isolate, data, t, "expand", JS_expand);
64
- SetPrototypeMethod(isolate, data, t, "raw", JS_raw);
65
- SetPrototypeMethod(isolate, data, t, "safeIntegers", JS_safeIntegers);
66
- SetPrototypeMethod(isolate, data, t, "columns", JS_columns);
67
- SetPrototypeGetter(isolate, data, t, "busy", JS_busy);
68
- return t->GetFunction(OnlyContext).ToLocalChecked();
69
- }
70
-
71
- NODE_METHOD(Statement::JS_new) {
72
- UseAddon;
73
- if (!addon->privileged_info) {
74
- return ThrowTypeError("Statements can only be constructed by the db.prepare() method");
75
- }
76
- assert(info.IsConstructCall());
77
- Database* db = Unwrap<Database>(addon->privileged_info->This());
78
- REQUIRE_DATABASE_OPEN(db->GetState());
79
- REQUIRE_DATABASE_NOT_BUSY(db->GetState());
80
-
81
- v8::Local<v8::String> source = (*addon->privileged_info)[0].As<v8::String>();
82
- v8::Local<v8::Object> database = (*addon->privileged_info)[1].As<v8::Object>();
83
- bool pragmaMode = (*addon->privileged_info)[2].As<v8::Boolean>()->Value();
84
- int flags = SQLITE_PREPARE_PERSISTENT;
85
-
86
- if (pragmaMode) {
87
- REQUIRE_DATABASE_NO_ITERATORS_UNLESS_UNSAFE(db->GetState());
88
- flags = 0;
89
- }
90
-
91
- UseIsolate;
92
- v8::String::Utf8Value utf8(isolate, source);
93
- sqlite3_stmt* handle;
94
- const char* tail;
95
-
96
- if (sqlite3_prepare_v3(db->GetHandle(), *utf8, utf8.length() + 1, flags, &handle, &tail) != SQLITE_OK) {
97
- return db->ThrowDatabaseError();
98
- }
99
- if (handle == NULL) {
100
- return ThrowRangeError("The supplied SQL string contains no statements");
101
- }
102
- // https://github.com/WiseLibs/better-sqlite3/issues/975#issuecomment-1520934678
103
- for (char c; (c = *tail); ) {
104
- if (IS_SKIPPED(c)) {
105
- ++tail;
106
- continue;
107
- }
108
- if (c == '/' && tail[1] == '*') {
109
- tail += 2;
110
- for (char c; (c = *tail); ++tail) {
111
- if (c == '*' && tail[1] == '/') {
112
- tail += 2;
113
- break;
114
- }
115
- }
116
- } else if (c == '-' && tail[1] == '-') {
117
- tail += 2;
118
- for (char c; (c = *tail); ++tail) {
119
- if (c == '\n') {
120
- ++tail;
121
- break;
122
- }
123
- }
124
- } else {
125
- sqlite3_finalize(handle);
126
- return ThrowRangeError("The supplied SQL string contains more than one statement");
127
- }
128
- }
129
-
130
- UseContext;
131
- bool returns_data = sqlite3_column_count(handle) >= 1 || pragmaMode;
132
- Statement* stmt = new Statement(db, handle, addon->NextId(), returns_data);
133
- stmt->Wrap(info.This());
134
- SetFrozen(isolate, ctx, info.This(), addon->cs.reader, v8::Boolean::New(isolate, returns_data));
135
- SetFrozen(isolate, ctx, info.This(), addon->cs.readonly, v8::Boolean::New(isolate, sqlite3_stmt_readonly(handle) != 0));
136
- SetFrozen(isolate, ctx, info.This(), addon->cs.source, source);
137
- SetFrozen(isolate, ctx, info.This(), addon->cs.database, database);
138
-
139
- info.GetReturnValue().Set(info.This());
140
- }
141
-
142
- NODE_METHOD(Statement::JS_run) {
143
- STATEMENT_START(ALLOW_ANY_STATEMENT, DOES_MUTATE);
144
- sqlite3* db_handle = db->GetHandle();
145
- int total_changes_before = sqlite3_total_changes(db_handle);
146
-
147
- sqlite3_step(handle);
148
- if (sqlite3_reset(handle) == SQLITE_OK) {
149
- int changes = sqlite3_total_changes(db_handle) == total_changes_before ? 0 : sqlite3_changes(db_handle);
150
- sqlite3_int64 id = sqlite3_last_insert_rowid(db_handle);
151
- Addon* addon = db->GetAddon();
152
- UseContext;
153
- v8::Local<v8::Object> result = v8::Object::New(isolate);
154
- result->Set(ctx, addon->cs.changes.Get(isolate), v8::Int32::New(isolate, changes)).FromJust();
155
- result->Set(ctx, addon->cs.lastInsertRowid.Get(isolate),
156
- stmt->safe_ints
157
- ? v8::BigInt::New(isolate, id).As<v8::Value>()
158
- : v8::Number::New(isolate, (double)id).As<v8::Value>()
159
- ).FromJust();
160
- STATEMENT_RETURN(result);
161
- }
162
- STATEMENT_THROW();
163
- }
164
-
165
- NODE_METHOD(Statement::JS_get) {
166
- STATEMENT_START(REQUIRE_STATEMENT_RETURNS_DATA, DOES_NOT_MUTATE);
167
- int status = sqlite3_step(handle);
168
- if (status == SQLITE_ROW) {
169
- v8::Local<v8::Value> result = Data::GetRowJS(isolate, OnlyContext, handle, stmt->safe_ints, stmt->mode);
170
- sqlite3_reset(handle);
171
- STATEMENT_RETURN(result);
172
- } else if (status == SQLITE_DONE) {
173
- sqlite3_reset(handle);
174
- STATEMENT_RETURN(v8::Undefined(isolate));
175
- }
176
- sqlite3_reset(handle);
177
- STATEMENT_THROW();
178
- }
179
-
180
- NODE_METHOD(Statement::JS_all) {
181
- STATEMENT_START(REQUIRE_STATEMENT_RETURNS_DATA, DOES_NOT_MUTATE);
182
- UseContext;
183
- const bool safe_ints = stmt->safe_ints;
184
- const char mode = stmt->mode;
185
-
186
- #if !defined(NODE_MODULE_VERSION) || NODE_MODULE_VERSION < 127
187
- bool js_error = false;
188
- uint32_t row_count = 0;
189
- v8::Local<v8::Array> result = v8::Array::New(isolate, 0);
190
-
191
- while (sqlite3_step(handle) == SQLITE_ROW) {
192
- if (row_count == 0xffffffff) { ThrowRangeError("Array overflow (too many rows returned)"); js_error = true; break; }
193
- result->Set(ctx, row_count++, Data::GetRowJS(isolate, ctx, handle, safe_ints, mode)).FromJust();
194
- }
195
-
196
- if (sqlite3_reset(handle) == SQLITE_OK && !js_error) {
197
- STATEMENT_RETURN(result);
198
- }
199
- if (js_error) db->GetState()->was_js_error = true;
200
- STATEMENT_THROW();
201
- #else
202
- v8::LocalVector<v8::Value> rows(isolate);
203
- rows.reserve(8);
204
-
205
- if (mode == Data::FLAT) {
206
- RowBuilder rowBuilder(isolate, handle, safe_ints);
207
- while (sqlite3_step(handle) == SQLITE_ROW) {
208
- rows.emplace_back(rowBuilder.GetRowJS());
209
- }
210
- } else {
211
- while (sqlite3_step(handle) == SQLITE_ROW) {
212
- rows.emplace_back(Data::GetRowJS(isolate, ctx, handle, safe_ints, mode));
213
- }
214
- }
215
-
216
- if (sqlite3_reset(handle) == SQLITE_OK) {
217
- if (rows.size() > 0xffffffff) {
218
- ThrowRangeError("Array overflow (too many rows returned)");
219
- db->GetState()->was_js_error = true;
220
- } else {
221
- STATEMENT_RETURN(v8::Array::New(isolate, rows.data(), rows.size()));
222
- }
223
- }
224
- STATEMENT_THROW();
225
- #endif
226
- }
227
-
228
- NODE_METHOD(Statement::JS_iterate) {
229
- UseAddon;
230
- UseIsolate;
231
- v8::Local<v8::Function> c = addon->StatementIterator.Get(isolate);
232
- addon->privileged_info = &info;
233
- v8::MaybeLocal<v8::Object> maybeIterator = c->NewInstance(OnlyContext, 0, NULL);
234
- addon->privileged_info = NULL;
235
- if (!maybeIterator.IsEmpty()) info.GetReturnValue().Set(maybeIterator.ToLocalChecked());
236
- }
237
-
238
- NODE_METHOD(Statement::JS_bind) {
239
- Statement* stmt = Unwrap<Statement>(info.This());
240
- if (stmt->bound) return ThrowTypeError("The bind() method can only be invoked once per statement object");
241
- REQUIRE_DATABASE_OPEN(stmt->db->GetState());
242
- REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
243
- REQUIRE_STATEMENT_NOT_LOCKED(stmt);
244
- STATEMENT_BIND(stmt->handle);
245
- stmt->bound = true;
246
- info.GetReturnValue().Set(info.This());
247
- }
248
-
249
- NODE_METHOD(Statement::JS_pluck) {
250
- Statement* stmt = Unwrap<Statement>(info.This());
251
- if (!stmt->returns_data) return ThrowTypeError("The pluck() method is only for statements that return data");
252
- REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
253
- REQUIRE_STATEMENT_NOT_LOCKED(stmt);
254
- bool use = true;
255
- if (info.Length() != 0) { REQUIRE_ARGUMENT_BOOLEAN(first, use); }
256
- stmt->mode = use ? Data::PLUCK : stmt->mode == Data::PLUCK ? Data::FLAT : stmt->mode;
257
- info.GetReturnValue().Set(info.This());
258
- }
259
-
260
- NODE_METHOD(Statement::JS_expand) {
261
- Statement* stmt = Unwrap<Statement>(info.This());
262
- if (!stmt->returns_data) return ThrowTypeError("The expand() method is only for statements that return data");
263
- REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
264
- REQUIRE_STATEMENT_NOT_LOCKED(stmt);
265
- bool use = true;
266
- if (info.Length() != 0) { REQUIRE_ARGUMENT_BOOLEAN(first, use); }
267
- stmt->mode = use ? Data::EXPAND : stmt->mode == Data::EXPAND ? Data::FLAT : stmt->mode;
268
- info.GetReturnValue().Set(info.This());
269
- }
270
-
271
- NODE_METHOD(Statement::JS_raw) {
272
- Statement* stmt = Unwrap<Statement>(info.This());
273
- if (!stmt->returns_data) return ThrowTypeError("The raw() method is only for statements that return data");
274
- REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
275
- REQUIRE_STATEMENT_NOT_LOCKED(stmt);
276
- bool use = true;
277
- if (info.Length() != 0) { REQUIRE_ARGUMENT_BOOLEAN(first, use); }
278
- stmt->mode = use ? Data::RAW : stmt->mode == Data::RAW ? Data::FLAT : stmt->mode;
279
- info.GetReturnValue().Set(info.This());
280
- }
281
-
282
- NODE_METHOD(Statement::JS_safeIntegers) {
283
- Statement* stmt = Unwrap<Statement>(info.This());
284
- REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
285
- REQUIRE_STATEMENT_NOT_LOCKED(stmt);
286
- if (info.Length() == 0) stmt->safe_ints = true;
287
- else { REQUIRE_ARGUMENT_BOOLEAN(first, stmt->safe_ints); }
288
- info.GetReturnValue().Set(info.This());
289
- }
290
-
291
- NODE_METHOD(Statement::JS_columns) {
292
- Statement* stmt = Unwrap<Statement>(info.This());
293
- if (!stmt->returns_data) return ThrowTypeError("The columns() method is only for statements that return data");
294
- REQUIRE_DATABASE_OPEN(stmt->db->GetState());
295
- REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
296
- Addon* addon = stmt->db->GetAddon();
297
- UseIsolate;
298
-
299
- #if !defined(NODE_MODULE_VERSION) || NODE_MODULE_VERSION < 127
300
- UseContext;
301
- int column_count = sqlite3_column_count(stmt->handle);
302
- v8::Local<v8::Array> columns = v8::Array::New(isolate);
303
-
304
- v8::Local<v8::String> name = addon->cs.name.Get(isolate);
305
- v8::Local<v8::String> columnName = addon->cs.column.Get(isolate);
306
- v8::Local<v8::String> tableName = addon->cs.table.Get(isolate);
307
- v8::Local<v8::String> databaseName = addon->cs.database.Get(isolate);
308
- v8::Local<v8::String> typeName = addon->cs.type.Get(isolate);
309
-
310
- for (int i = 0; i < column_count; ++i) {
311
- v8::Local<v8::Object> column = v8::Object::New(isolate);
312
-
313
- column->Set(ctx, name,
314
- InternalizedFromUtf8OrNull(isolate, sqlite3_column_name(stmt->handle, i), -1)
315
- ).FromJust();
316
- column->Set(ctx, columnName,
317
- InternalizedFromUtf8OrNull(isolate, sqlite3_column_origin_name(stmt->handle, i), -1)
318
- ).FromJust();
319
- column->Set(ctx, tableName,
320
- InternalizedFromUtf8OrNull(isolate, sqlite3_column_table_name(stmt->handle, i), -1)
321
- ).FromJust();
322
- column->Set(ctx, databaseName,
323
- InternalizedFromUtf8OrNull(isolate, sqlite3_column_database_name(stmt->handle, i), -1)
324
- ).FromJust();
325
- column->Set(ctx, typeName,
326
- InternalizedFromUtf8OrNull(isolate, sqlite3_column_decltype(stmt->handle, i), -1)
327
- ).FromJust();
328
-
329
- columns->Set(ctx, i, column).FromJust();
330
- }
331
-
332
- info.GetReturnValue().Set(columns);
333
- #else
334
- v8::LocalVector<v8::Name> keys(isolate);
335
- keys.reserve(5);
336
- keys.emplace_back(addon->cs.name.Get(isolate).As<v8::Name>());
337
- keys.emplace_back(addon->cs.column.Get(isolate).As<v8::Name>());
338
- keys.emplace_back(addon->cs.table.Get(isolate).As<v8::Name>());
339
- keys.emplace_back(addon->cs.database.Get(isolate).As<v8::Name>());
340
- keys.emplace_back(addon->cs.type.Get(isolate).As<v8::Name>());
341
-
342
- int column_count = sqlite3_column_count(stmt->handle);
343
- v8::LocalVector<v8::Value> columns(isolate);
344
- columns.reserve(column_count);
345
-
346
- for (int i = 0; i < column_count; ++i) {
347
- v8::LocalVector<v8::Value> values(isolate);
348
- keys.reserve(5);
349
- values.emplace_back(
350
- InternalizedFromUtf8OrNull(isolate, sqlite3_column_name(stmt->handle, i), -1)
351
- );
352
- values.emplace_back(
353
- InternalizedFromUtf8OrNull(isolate, sqlite3_column_origin_name(stmt->handle, i), -1)
354
- );
355
- values.emplace_back(
356
- InternalizedFromUtf8OrNull(isolate, sqlite3_column_table_name(stmt->handle, i), -1)
357
- );
358
- values.emplace_back(
359
- InternalizedFromUtf8OrNull(isolate, sqlite3_column_database_name(stmt->handle, i), -1)
360
- );
361
- values.emplace_back(
362
- InternalizedFromUtf8OrNull(isolate, sqlite3_column_decltype(stmt->handle, i), -1)
363
- );
364
- columns.emplace_back(
365
- v8::Object::New(isolate,
366
- v8::Object::New(isolate)->GetPrototype(),
367
- keys.data(),
368
- values.data(),
369
- keys.size()
370
- )
371
- );
372
- }
373
-
374
- info.GetReturnValue().Set(
375
- v8::Array::New(isolate, columns.data(), columns.size())
376
- );
377
- #endif
378
- }
379
-
380
- NODE_GETTER(Statement::JS_busy) {
381
- Statement* stmt = Unwrap<Statement>(info.This());
382
- info.GetReturnValue().Set(stmt->alive && stmt->locked);
383
- }
1
+ Statement::Statement(
2
+ Database* db,
3
+ sqlite3_stmt* handle,
4
+ sqlite3_uint64 id,
5
+ bool returns_data
6
+ ) :
7
+ node::ObjectWrap(),
8
+ db(db),
9
+ handle(handle),
10
+ extras(new Extras(id)),
11
+ alive(true),
12
+ locked(false),
13
+ bound(false),
14
+ has_bind_map(false),
15
+ safe_ints(db->GetState()->safe_ints),
16
+ mode(Data::FLAT),
17
+ returns_data(returns_data) {
18
+ assert(db != NULL);
19
+ assert(handle != NULL);
20
+ assert(db->GetState()->open);
21
+ assert(!db->GetState()->busy);
22
+ db->AddStatement(this);
23
+ }
24
+
25
+ Statement::~Statement() {
26
+ if (alive) db->RemoveStatement(this);
27
+ CloseHandles();
28
+ delete extras;
29
+ }
30
+
31
+ // Whenever this is used, db->RemoveStatement must be invoked beforehand.
32
+ void Statement::CloseHandles() {
33
+ if (alive) {
34
+ alive = false;
35
+ sqlite3_finalize(handle);
36
+ }
37
+ }
38
+
39
+ // Returns the Statement's bind map (creates it upon first execution).
40
+ BindMap* Statement::GetBindMap(v8::Isolate* isolate) {
41
+ if (has_bind_map) return &extras->bind_map;
42
+ BindMap* bind_map = &extras->bind_map;
43
+ int param_count = sqlite3_bind_parameter_count(handle);
44
+ for (int i = 1; i <= param_count; ++i) {
45
+ const char* name = sqlite3_bind_parameter_name(handle, i);
46
+ if (name != NULL) bind_map->Add(isolate, name + 1, i);
47
+ }
48
+ has_bind_map = true;
49
+ return bind_map;
50
+ }
51
+
52
+ Statement::Extras::Extras(sqlite3_uint64 id)
53
+ : bind_map(0), id(id) {}
54
+
55
+ INIT(Statement::Init) {
56
+ v8::Local<v8::FunctionTemplate> t = NewConstructorTemplate(isolate, data, JS_new, "Statement");
57
+ SetPrototypeMethod(isolate, data, t, "run", JS_run);
58
+ SetPrototypeMethod(isolate, data, t, "get", JS_get);
59
+ SetPrototypeMethod(isolate, data, t, "all", JS_all);
60
+ SetPrototypeMethod(isolate, data, t, "iterate", JS_iterate);
61
+ SetPrototypeMethod(isolate, data, t, "bind", JS_bind);
62
+ SetPrototypeMethod(isolate, data, t, "pluck", JS_pluck);
63
+ SetPrototypeMethod(isolate, data, t, "expand", JS_expand);
64
+ SetPrototypeMethod(isolate, data, t, "raw", JS_raw);
65
+ SetPrototypeMethod(isolate, data, t, "safeIntegers", JS_safeIntegers);
66
+ SetPrototypeMethod(isolate, data, t, "columns", JS_columns);
67
+ SetPrototypeGetter(isolate, data, t, "busy", JS_busy);
68
+ return t->GetFunction(OnlyContext).ToLocalChecked();
69
+ }
70
+
71
+ NODE_METHOD(Statement::JS_new) {
72
+ UseAddon;
73
+ if (!addon->privileged_info) {
74
+ return ThrowTypeError("Statements can only be constructed by the db.prepare() method");
75
+ }
76
+ assert(info.IsConstructCall());
77
+ Database* db = Unwrap<Database>(addon->privileged_info->This());
78
+ REQUIRE_DATABASE_OPEN(db->GetState());
79
+ REQUIRE_DATABASE_NOT_BUSY(db->GetState());
80
+
81
+ v8::Local<v8::String> source = (*addon->privileged_info)[0].As<v8::String>();
82
+ v8::Local<v8::Object> database = (*addon->privileged_info)[1].As<v8::Object>();
83
+ bool pragmaMode = (*addon->privileged_info)[2].As<v8::Boolean>()->Value();
84
+ int flags = SQLITE_PREPARE_PERSISTENT;
85
+
86
+ if (pragmaMode) {
87
+ REQUIRE_DATABASE_NO_ITERATORS_UNLESS_UNSAFE(db->GetState());
88
+ flags = 0;
89
+ }
90
+
91
+ UseIsolate;
92
+ v8::String::Utf8Value utf8(isolate, source);
93
+ sqlite3_stmt* handle;
94
+ const char* tail;
95
+
96
+ if (sqlite3_prepare_v3(db->GetHandle(), *utf8, utf8.length() + 1, flags, &handle, &tail) != SQLITE_OK) {
97
+ return db->ThrowDatabaseError();
98
+ }
99
+ if (handle == NULL) {
100
+ return ThrowRangeError("The supplied SQL string contains no statements");
101
+ }
102
+ // https://github.com/WiseLibs/better-sqlite3/issues/975#issuecomment-1520934678
103
+ for (char c; (c = *tail); ) {
104
+ if (IS_SKIPPED(c)) {
105
+ ++tail;
106
+ continue;
107
+ }
108
+ if (c == '/' && tail[1] == '*') {
109
+ tail += 2;
110
+ for (char c; (c = *tail); ++tail) {
111
+ if (c == '*' && tail[1] == '/') {
112
+ tail += 2;
113
+ break;
114
+ }
115
+ }
116
+ } else if (c == '-' && tail[1] == '-') {
117
+ tail += 2;
118
+ for (char c; (c = *tail); ++tail) {
119
+ if (c == '\n') {
120
+ ++tail;
121
+ break;
122
+ }
123
+ }
124
+ } else {
125
+ sqlite3_finalize(handle);
126
+ return ThrowRangeError("The supplied SQL string contains more than one statement");
127
+ }
128
+ }
129
+
130
+ UseContext;
131
+ bool returns_data = sqlite3_column_count(handle) >= 1 || pragmaMode;
132
+ Statement* stmt = new Statement(db, handle, addon->NextId(), returns_data);
133
+ stmt->Wrap(info.This());
134
+ SetFrozen(isolate, ctx, info.This(), addon->cs.reader, v8::Boolean::New(isolate, returns_data));
135
+ SetFrozen(isolate, ctx, info.This(), addon->cs.readonly, v8::Boolean::New(isolate, sqlite3_stmt_readonly(handle) != 0));
136
+ SetFrozen(isolate, ctx, info.This(), addon->cs.source, source);
137
+ SetFrozen(isolate, ctx, info.This(), addon->cs.database, database);
138
+
139
+ info.GetReturnValue().Set(info.This());
140
+ }
141
+
142
+ NODE_METHOD(Statement::JS_run) {
143
+ STATEMENT_START(ALLOW_ANY_STATEMENT, DOES_MUTATE);
144
+ sqlite3* db_handle = db->GetHandle();
145
+ int total_changes_before = sqlite3_total_changes(db_handle);
146
+
147
+ sqlite3_step(handle);
148
+ if (sqlite3_reset(handle) == SQLITE_OK) {
149
+ int changes = sqlite3_total_changes(db_handle) == total_changes_before ? 0 : sqlite3_changes(db_handle);
150
+ sqlite3_int64 id = sqlite3_last_insert_rowid(db_handle);
151
+ Addon* addon = db->GetAddon();
152
+ UseContext;
153
+ v8::Local<v8::Object> result = v8::Object::New(isolate);
154
+ result->Set(ctx, addon->cs.changes.Get(isolate), v8::Int32::New(isolate, changes)).FromJust();
155
+ result->Set(ctx, addon->cs.lastInsertRowid.Get(isolate),
156
+ stmt->safe_ints
157
+ ? v8::BigInt::New(isolate, id).As<v8::Value>()
158
+ : v8::Number::New(isolate, (double)id).As<v8::Value>()
159
+ ).FromJust();
160
+ STATEMENT_RETURN(result);
161
+ }
162
+ STATEMENT_THROW();
163
+ }
164
+
165
+ NODE_METHOD(Statement::JS_get) {
166
+ STATEMENT_START(REQUIRE_STATEMENT_RETURNS_DATA, DOES_NOT_MUTATE);
167
+ int status = sqlite3_step(handle);
168
+ if (status == SQLITE_ROW) {
169
+ v8::Local<v8::Value> result = Data::GetRowJS(isolate, OnlyContext, handle, stmt->safe_ints, stmt->mode);
170
+ sqlite3_reset(handle);
171
+ STATEMENT_RETURN(result);
172
+ } else if (status == SQLITE_DONE) {
173
+ sqlite3_reset(handle);
174
+ STATEMENT_RETURN(v8::Undefined(isolate));
175
+ }
176
+ sqlite3_reset(handle);
177
+ STATEMENT_THROW();
178
+ }
179
+
180
+ NODE_METHOD(Statement::JS_all) {
181
+ STATEMENT_START(REQUIRE_STATEMENT_RETURNS_DATA, DOES_NOT_MUTATE);
182
+ UseContext;
183
+ const bool safe_ints = stmt->safe_ints;
184
+ const char mode = stmt->mode;
185
+
186
+ #if !defined(NODE_MODULE_VERSION) || NODE_MODULE_VERSION < 127
187
+ bool js_error = false;
188
+ uint32_t row_count = 0;
189
+ v8::Local<v8::Array> result = v8::Array::New(isolate, 0);
190
+
191
+ while (sqlite3_step(handle) == SQLITE_ROW) {
192
+ if (row_count == 0xffffffff) { ThrowRangeError("Array overflow (too many rows returned)"); js_error = true; break; }
193
+ result->Set(ctx, row_count++, Data::GetRowJS(isolate, ctx, handle, safe_ints, mode)).FromJust();
194
+ }
195
+
196
+ if (sqlite3_reset(handle) == SQLITE_OK && !js_error) {
197
+ STATEMENT_RETURN(result);
198
+ }
199
+ if (js_error) db->GetState()->was_js_error = true;
200
+ STATEMENT_THROW();
201
+ #else
202
+ v8::LocalVector<v8::Value> rows(isolate);
203
+ rows.reserve(8);
204
+
205
+ if (mode == Data::FLAT) {
206
+ RowBuilder rowBuilder(isolate, handle, safe_ints);
207
+ while (sqlite3_step(handle) == SQLITE_ROW) {
208
+ rows.emplace_back(rowBuilder.GetRowJS());
209
+ }
210
+ } else {
211
+ while (sqlite3_step(handle) == SQLITE_ROW) {
212
+ rows.emplace_back(Data::GetRowJS(isolate, ctx, handle, safe_ints, mode));
213
+ }
214
+ }
215
+
216
+ if (sqlite3_reset(handle) == SQLITE_OK) {
217
+ if (rows.size() > 0xffffffff) {
218
+ ThrowRangeError("Array overflow (too many rows returned)");
219
+ db->GetState()->was_js_error = true;
220
+ } else {
221
+ STATEMENT_RETURN(v8::Array::New(isolate, rows.data(), rows.size()));
222
+ }
223
+ }
224
+ STATEMENT_THROW();
225
+ #endif
226
+ }
227
+
228
+ NODE_METHOD(Statement::JS_iterate) {
229
+ UseAddon;
230
+ UseIsolate;
231
+ v8::Local<v8::Function> c = addon->StatementIterator.Get(isolate);
232
+ addon->privileged_info = &info;
233
+ v8::MaybeLocal<v8::Object> maybeIterator = c->NewInstance(OnlyContext, 0, NULL);
234
+ addon->privileged_info = NULL;
235
+ if (!maybeIterator.IsEmpty()) info.GetReturnValue().Set(maybeIterator.ToLocalChecked());
236
+ }
237
+
238
+ NODE_METHOD(Statement::JS_bind) {
239
+ Statement* stmt = Unwrap<Statement>(info.This());
240
+ if (stmt->bound) return ThrowTypeError("The bind() method can only be invoked once per statement object");
241
+ REQUIRE_DATABASE_OPEN(stmt->db->GetState());
242
+ REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
243
+ REQUIRE_STATEMENT_NOT_LOCKED(stmt);
244
+ STATEMENT_BIND(stmt->handle);
245
+ stmt->bound = true;
246
+ info.GetReturnValue().Set(info.This());
247
+ }
248
+
249
+ NODE_METHOD(Statement::JS_pluck) {
250
+ Statement* stmt = Unwrap<Statement>(info.This());
251
+ if (!stmt->returns_data) return ThrowTypeError("The pluck() method is only for statements that return data");
252
+ REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
253
+ REQUIRE_STATEMENT_NOT_LOCKED(stmt);
254
+ bool use = true;
255
+ if (info.Length() != 0) { REQUIRE_ARGUMENT_BOOLEAN(first, use); }
256
+ stmt->mode = use ? Data::PLUCK : stmt->mode == Data::PLUCK ? Data::FLAT : stmt->mode;
257
+ info.GetReturnValue().Set(info.This());
258
+ }
259
+
260
+ NODE_METHOD(Statement::JS_expand) {
261
+ Statement* stmt = Unwrap<Statement>(info.This());
262
+ if (!stmt->returns_data) return ThrowTypeError("The expand() method is only for statements that return data");
263
+ REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
264
+ REQUIRE_STATEMENT_NOT_LOCKED(stmt);
265
+ bool use = true;
266
+ if (info.Length() != 0) { REQUIRE_ARGUMENT_BOOLEAN(first, use); }
267
+ stmt->mode = use ? Data::EXPAND : stmt->mode == Data::EXPAND ? Data::FLAT : stmt->mode;
268
+ info.GetReturnValue().Set(info.This());
269
+ }
270
+
271
+ NODE_METHOD(Statement::JS_raw) {
272
+ Statement* stmt = Unwrap<Statement>(info.This());
273
+ if (!stmt->returns_data) return ThrowTypeError("The raw() method is only for statements that return data");
274
+ REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
275
+ REQUIRE_STATEMENT_NOT_LOCKED(stmt);
276
+ bool use = true;
277
+ if (info.Length() != 0) { REQUIRE_ARGUMENT_BOOLEAN(first, use); }
278
+ stmt->mode = use ? Data::RAW : stmt->mode == Data::RAW ? Data::FLAT : stmt->mode;
279
+ info.GetReturnValue().Set(info.This());
280
+ }
281
+
282
+ NODE_METHOD(Statement::JS_safeIntegers) {
283
+ Statement* stmt = Unwrap<Statement>(info.This());
284
+ REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
285
+ REQUIRE_STATEMENT_NOT_LOCKED(stmt);
286
+ if (info.Length() == 0) stmt->safe_ints = true;
287
+ else { REQUIRE_ARGUMENT_BOOLEAN(first, stmt->safe_ints); }
288
+ info.GetReturnValue().Set(info.This());
289
+ }
290
+
291
+ NODE_METHOD(Statement::JS_columns) {
292
+ Statement* stmt = Unwrap<Statement>(info.This());
293
+ if (!stmt->returns_data) return ThrowTypeError("The columns() method is only for statements that return data");
294
+ REQUIRE_DATABASE_OPEN(stmt->db->GetState());
295
+ REQUIRE_DATABASE_NOT_BUSY(stmt->db->GetState());
296
+ Addon* addon = stmt->db->GetAddon();
297
+ UseIsolate;
298
+
299
+ #if !defined(NODE_MODULE_VERSION) || NODE_MODULE_VERSION < 127
300
+ UseContext;
301
+ int column_count = sqlite3_column_count(stmt->handle);
302
+ v8::Local<v8::Array> columns = v8::Array::New(isolate);
303
+
304
+ v8::Local<v8::String> name = addon->cs.name.Get(isolate);
305
+ v8::Local<v8::String> columnName = addon->cs.column.Get(isolate);
306
+ v8::Local<v8::String> tableName = addon->cs.table.Get(isolate);
307
+ v8::Local<v8::String> databaseName = addon->cs.database.Get(isolate);
308
+ v8::Local<v8::String> typeName = addon->cs.type.Get(isolate);
309
+
310
+ for (int i = 0; i < column_count; ++i) {
311
+ v8::Local<v8::Object> column = v8::Object::New(isolate);
312
+
313
+ column->Set(ctx, name,
314
+ InternalizedFromUtf8OrNull(isolate, sqlite3_column_name(stmt->handle, i), -1)
315
+ ).FromJust();
316
+ column->Set(ctx, columnName,
317
+ InternalizedFromUtf8OrNull(isolate, sqlite3_column_origin_name(stmt->handle, i), -1)
318
+ ).FromJust();
319
+ column->Set(ctx, tableName,
320
+ InternalizedFromUtf8OrNull(isolate, sqlite3_column_table_name(stmt->handle, i), -1)
321
+ ).FromJust();
322
+ column->Set(ctx, databaseName,
323
+ InternalizedFromUtf8OrNull(isolate, sqlite3_column_database_name(stmt->handle, i), -1)
324
+ ).FromJust();
325
+ column->Set(ctx, typeName,
326
+ InternalizedFromUtf8OrNull(isolate, sqlite3_column_decltype(stmt->handle, i), -1)
327
+ ).FromJust();
328
+
329
+ columns->Set(ctx, i, column).FromJust();
330
+ }
331
+
332
+ info.GetReturnValue().Set(columns);
333
+ #else
334
+ v8::LocalVector<v8::Name> keys(isolate);
335
+ keys.reserve(5);
336
+ keys.emplace_back(addon->cs.name.Get(isolate).As<v8::Name>());
337
+ keys.emplace_back(addon->cs.column.Get(isolate).As<v8::Name>());
338
+ keys.emplace_back(addon->cs.table.Get(isolate).As<v8::Name>());
339
+ keys.emplace_back(addon->cs.database.Get(isolate).As<v8::Name>());
340
+ keys.emplace_back(addon->cs.type.Get(isolate).As<v8::Name>());
341
+
342
+ int column_count = sqlite3_column_count(stmt->handle);
343
+ v8::LocalVector<v8::Value> columns(isolate);
344
+ columns.reserve(column_count);
345
+
346
+ for (int i = 0; i < column_count; ++i) {
347
+ v8::LocalVector<v8::Value> values(isolate);
348
+ keys.reserve(5);
349
+ values.emplace_back(
350
+ InternalizedFromUtf8OrNull(isolate, sqlite3_column_name(stmt->handle, i), -1)
351
+ );
352
+ values.emplace_back(
353
+ InternalizedFromUtf8OrNull(isolate, sqlite3_column_origin_name(stmt->handle, i), -1)
354
+ );
355
+ values.emplace_back(
356
+ InternalizedFromUtf8OrNull(isolate, sqlite3_column_table_name(stmt->handle, i), -1)
357
+ );
358
+ values.emplace_back(
359
+ InternalizedFromUtf8OrNull(isolate, sqlite3_column_database_name(stmt->handle, i), -1)
360
+ );
361
+ values.emplace_back(
362
+ InternalizedFromUtf8OrNull(isolate, sqlite3_column_decltype(stmt->handle, i), -1)
363
+ );
364
+ columns.emplace_back(
365
+ v8::Object::New(isolate,
366
+ GET_PROTOTYPE(v8::Object::New(isolate)),
367
+ keys.data(),
368
+ values.data(),
369
+ keys.size()
370
+ )
371
+ );
372
+ }
373
+
374
+ info.GetReturnValue().Set(
375
+ v8::Array::New(isolate, columns.data(), columns.size())
376
+ );
377
+ #endif
378
+ }
379
+
380
+ NODE_GETTER(Statement::JS_busy) {
381
+ Statement* stmt = Unwrap<Statement>(info.This());
382
+ info.GetReturnValue().Set(stmt->alive && stmt->locked);
383
+ }