@rocicorp/zero-sqlite3 1.0.9 → 1.0.11
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.
- package/README.md +1 -0
- package/binding.gyp +1 -1
- package/deps/download.sh +4 -4
- package/deps/sqlite3.gyp +1 -1
- package/deps/test_extension.c +1 -1
- package/lib/database.js +1 -1
- package/lib/methods/transaction.js +3 -0
- package/package.json +9 -8
- package/src/addon.cpp +47 -0
- package/src/better_sqlite3.cpp +44 -2166
- package/src/objects/backup.cpp +120 -0
- package/src/objects/backup.hpp +36 -0
- package/src/objects/database.cpp +392 -0
- package/src/objects/database.hpp +102 -0
- package/src/objects/statement-iterator.cpp +113 -0
- package/src/objects/statement-iterator.hpp +50 -0
- package/src/objects/statement.cpp +456 -0
- package/src/objects/statement.hpp +59 -0
- package/src/util/bind-map.cpp +73 -0
- package/src/util/binder.cpp +193 -0
- package/src/util/constants.cpp +172 -0
- package/src/util/custom-aggregate.cpp +121 -0
- package/src/util/custom-function.cpp +59 -0
- package/src/util/custom-table.cpp +409 -0
- package/src/util/data-converter.cpp +17 -0
- package/src/util/data.cpp +194 -0
- package/src/util/helpers.cpp +109 -0
- package/src/util/macros.cpp +63 -0
- package/src/util/query-macros.cpp +71 -0
- package/src/util/row-builder.cpp +49 -0
- package/src/better_sqlite3.hpp +0 -1036
package/src/better_sqlite3.cpp
CHANGED
|
@@ -1,65 +1,54 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
#include <climits>
|
|
2
|
+
#include <cstdio>
|
|
3
|
+
#include <cstring>
|
|
4
|
+
#include <string>
|
|
5
|
+
#include <vector>
|
|
6
|
+
#include <set>
|
|
7
|
+
#include <unordered_map>
|
|
8
|
+
#include <algorithm>
|
|
9
|
+
#include <mutex>
|
|
10
|
+
#include <sqlite3.h>
|
|
11
|
+
#include <node.h>
|
|
12
|
+
#include <node_object_wrap.h>
|
|
13
|
+
#include <node_buffer.h>
|
|
14
|
+
|
|
15
|
+
struct Addon;
|
|
16
|
+
class Database;
|
|
17
|
+
class Statement;
|
|
18
|
+
class StatementIterator;
|
|
19
|
+
class Backup;
|
|
20
|
+
|
|
21
|
+
#include "util/macros.cpp"
|
|
22
|
+
#include "util/helpers.cpp"
|
|
23
|
+
#include "util/constants.cpp"
|
|
24
|
+
#include "util/bind-map.cpp"
|
|
25
|
+
#include "util/data-converter.cpp"
|
|
26
|
+
#include "util/data.cpp"
|
|
27
|
+
#if defined(NODE_MODULE_VERSION) && NODE_MODULE_VERSION >= 127
|
|
28
|
+
#include "util/row-builder.cpp"
|
|
29
|
+
#endif
|
|
3
30
|
|
|
4
|
-
#include "
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
v8::Local<v8::FunctionTemplate> recv,
|
|
10
|
-
const char* name,
|
|
11
|
-
v8::AccessorNameGetterCallback func
|
|
12
|
-
) {
|
|
13
|
-
v8::HandleScope scope(isolate);
|
|
31
|
+
#include "objects/backup.hpp"
|
|
32
|
+
#include "objects/statement.hpp"
|
|
33
|
+
#include "objects/database.hpp"
|
|
34
|
+
#include "addon.cpp"
|
|
35
|
+
#include "objects/statement-iterator.hpp"
|
|
14
36
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
data,
|
|
21
|
-
v8::AccessControl::DEFAULT,
|
|
22
|
-
v8::PropertyAttribute::None
|
|
23
|
-
);
|
|
24
|
-
#else
|
|
25
|
-
recv->InstanceTemplate()->SetNativeDataProperty(
|
|
26
|
-
InternalizedFromLatin1(isolate, name),
|
|
27
|
-
func,
|
|
28
|
-
0,
|
|
29
|
-
data
|
|
30
|
-
);
|
|
31
|
-
#endif
|
|
32
|
-
}
|
|
33
|
-
#line 184 "./src/util/macros.lzz"
|
|
34
|
-
#ifndef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
|
|
35
|
-
#define SAFE_NEW_BUFFER(env, data, length, finalizeCallback, finalizeHint) node::Buffer::New(env, data, length, finalizeCallback, finalizeHint)
|
|
36
|
-
#else
|
|
37
|
-
static inline v8::MaybeLocal<v8::Object> BufferSandboxNew(v8::Isolate* isolate, char* data, size_t length, void (*finalizeCallback)(char*, void*), void* finalizeHint) {
|
|
38
|
-
v8::MaybeLocal<v8::Object> buffer = node::Buffer::Copy(isolate, data, length);
|
|
39
|
-
finalizeCallback(data, finalizeHint);
|
|
40
|
-
return buffer;
|
|
41
|
-
}
|
|
42
|
-
#define SAFE_NEW_BUFFER(env, data, length, finalizeCallback, finalizeHint) BufferSandboxNew(env, data, length, finalizeCallback, finalizeHint)
|
|
43
|
-
#endif
|
|
44
|
-
#line 39 "./src/util/binder.lzz"
|
|
45
|
-
static bool IsPlainObject(v8::Isolate* isolate, v8::Local<v8::Object> obj) {
|
|
46
|
-
v8::Local<v8::Value> proto = obj->GetPrototype();
|
|
37
|
+
#include "util/query-macros.cpp"
|
|
38
|
+
#include "util/custom-function.cpp"
|
|
39
|
+
#include "util/custom-aggregate.cpp"
|
|
40
|
+
#include "util/custom-table.cpp"
|
|
41
|
+
#include "util/binder.cpp"
|
|
47
42
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
#endif
|
|
43
|
+
#include "objects/backup.cpp"
|
|
44
|
+
#include "objects/statement.cpp"
|
|
45
|
+
#include "objects/database.cpp"
|
|
46
|
+
#include "objects/statement-iterator.cpp"
|
|
53
47
|
|
|
54
|
-
ctx->Enter();
|
|
55
|
-
v8::Local<v8::Value> baseProto = v8::Object::New(isolate)->GetPrototype();
|
|
56
|
-
ctx->Exit();
|
|
57
|
-
return proto->StrictEquals(baseProto) || proto->StrictEquals(v8::Null(isolate));
|
|
58
|
-
}
|
|
59
|
-
#line 67 "./src/better_sqlite3.lzz"
|
|
60
48
|
NODE_MODULE_INIT(/* exports, context */) {
|
|
61
49
|
v8::Isolate* isolate = context->GetIsolate();
|
|
62
50
|
v8::HandleScope scope(isolate);
|
|
51
|
+
Addon::ConfigureURI();
|
|
63
52
|
|
|
64
53
|
// Initialize addon instance.
|
|
65
54
|
Addon* addon = new Addon(isolate);
|
|
@@ -89,2114 +78,3 @@ NODE_MODULE_INIT(/* exports, context */) {
|
|
|
89
78
|
addon->StatementIterator.Reset(isolate, exports->Get(context, InternalizedFromLatin1(isolate, "StatementIterator")).ToLocalChecked().As<v8::Function>());
|
|
90
79
|
addon->Backup.Reset(isolate, exports->Get(context, InternalizedFromLatin1(isolate, "Backup")).ToLocalChecked().As<v8::Function>());
|
|
91
80
|
}
|
|
92
|
-
#define LZZ_INLINE inline
|
|
93
|
-
#line 65 "./src/util/data.lzz"
|
|
94
|
-
namespace Data
|
|
95
|
-
{
|
|
96
|
-
#line 67 "./src/util/data.lzz"
|
|
97
|
-
static char const FLAT = 0;
|
|
98
|
-
}
|
|
99
|
-
#line 65 "./src/util/data.lzz"
|
|
100
|
-
namespace Data
|
|
101
|
-
{
|
|
102
|
-
#line 68 "./src/util/data.lzz"
|
|
103
|
-
static char const PLUCK = 1;
|
|
104
|
-
}
|
|
105
|
-
#line 65 "./src/util/data.lzz"
|
|
106
|
-
namespace Data
|
|
107
|
-
{
|
|
108
|
-
#line 69 "./src/util/data.lzz"
|
|
109
|
-
static char const EXPAND = 2;
|
|
110
|
-
}
|
|
111
|
-
#line 65 "./src/util/data.lzz"
|
|
112
|
-
namespace Data
|
|
113
|
-
{
|
|
114
|
-
#line 70 "./src/util/data.lzz"
|
|
115
|
-
static char const RAW = 3;
|
|
116
|
-
}
|
|
117
|
-
#line 38 "./src/util/macros.lzz"
|
|
118
|
-
void ThrowError (char const * message)
|
|
119
|
-
#line 38 "./src/util/macros.lzz"
|
|
120
|
-
{ v8 :: Isolate * isolate = v8 :: Isolate :: GetCurrent ( ) ; isolate->ThrowException(v8::Exception::Error(StringFromUtf8(isolate, message, -1)));
|
|
121
|
-
}
|
|
122
|
-
#line 39 "./src/util/macros.lzz"
|
|
123
|
-
void ThrowTypeError (char const * message)
|
|
124
|
-
#line 39 "./src/util/macros.lzz"
|
|
125
|
-
{ v8 :: Isolate * isolate = v8 :: Isolate :: GetCurrent ( ) ; isolate->ThrowException(v8::Exception::TypeError(StringFromUtf8(isolate, message, -1)));
|
|
126
|
-
}
|
|
127
|
-
#line 40 "./src/util/macros.lzz"
|
|
128
|
-
void ThrowRangeError (char const * message)
|
|
129
|
-
#line 40 "./src/util/macros.lzz"
|
|
130
|
-
{ v8 :: Isolate * isolate = v8 :: Isolate :: GetCurrent ( ) ; isolate->ThrowException(v8::Exception::RangeError(StringFromUtf8(isolate, message, -1)));
|
|
131
|
-
}
|
|
132
|
-
#line 106 "./src/util/macros.lzz"
|
|
133
|
-
v8::Local <v8::FunctionTemplate> NewConstructorTemplate (v8::Isolate * isolate, v8::Local <v8::External> data, v8::FunctionCallback func, char const * name)
|
|
134
|
-
#line 111 "./src/util/macros.lzz"
|
|
135
|
-
{
|
|
136
|
-
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate, func, data);
|
|
137
|
-
t->InstanceTemplate()->SetInternalFieldCount(1);
|
|
138
|
-
t->SetClassName(InternalizedFromLatin1(isolate, name));
|
|
139
|
-
return t;
|
|
140
|
-
}
|
|
141
|
-
#line 117 "./src/util/macros.lzz"
|
|
142
|
-
void SetPrototypeMethod (v8::Isolate * isolate, v8::Local <v8::External> data, v8::Local <v8::FunctionTemplate> recv, char const * name, v8::FunctionCallback func)
|
|
143
|
-
#line 123 "./src/util/macros.lzz"
|
|
144
|
-
{
|
|
145
|
-
v8::HandleScope scope(isolate);
|
|
146
|
-
recv->PrototypeTemplate()->Set(
|
|
147
|
-
InternalizedFromLatin1(isolate, name),
|
|
148
|
-
v8::FunctionTemplate::New(isolate, func, data, v8::Signature::New(isolate, recv))
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
#line 130 "./src/util/macros.lzz"
|
|
152
|
-
void SetPrototypeSymbolMethod (v8::Isolate * isolate, v8::Local <v8::External> data, v8::Local <v8::FunctionTemplate> recv, v8::Local <v8::Symbol> symbol, v8::FunctionCallback func)
|
|
153
|
-
#line 136 "./src/util/macros.lzz"
|
|
154
|
-
{
|
|
155
|
-
v8::HandleScope scope(isolate);
|
|
156
|
-
recv->PrototypeTemplate()->Set(
|
|
157
|
-
symbol,
|
|
158
|
-
v8::FunctionTemplate::New(isolate, func, data, v8::Signature::New(isolate, recv))
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
#line 4 "./src/util/constants.lzz"
|
|
162
|
-
v8::Local <v8::String> CS::Code (v8::Isolate * isolate, int code)
|
|
163
|
-
#line 4 "./src/util/constants.lzz"
|
|
164
|
-
{
|
|
165
|
-
auto element = codes.find(code);
|
|
166
|
-
if (element != codes.end()) return element->second.Get(isolate);
|
|
167
|
-
return StringFromUtf8(isolate, (std::string("UNKNOWN_SQLITE_ERROR_") + std::to_string(code)).c_str(), -1);
|
|
168
|
-
}
|
|
169
|
-
#line 10 "./src/util/constants.lzz"
|
|
170
|
-
CS::CS (v8::Isolate * isolate)
|
|
171
|
-
#line 10 "./src/util/constants.lzz"
|
|
172
|
-
{
|
|
173
|
-
SetString(isolate, database, "database");
|
|
174
|
-
SetString(isolate, reader, "reader");
|
|
175
|
-
SetString(isolate, source, "source");
|
|
176
|
-
SetString(isolate, memory, "memory");
|
|
177
|
-
SetString(isolate, readonly, "readonly");
|
|
178
|
-
SetString(isolate, name, "name");
|
|
179
|
-
SetString(isolate, next, "next");
|
|
180
|
-
SetString(isolate, length, "length");
|
|
181
|
-
SetString(isolate, done, "done");
|
|
182
|
-
SetString(isolate, value, "value");
|
|
183
|
-
SetString(isolate, changes, "changes");
|
|
184
|
-
SetString(isolate, lastInsertRowid, "lastInsertRowid");
|
|
185
|
-
SetString(isolate, statement, "statement");
|
|
186
|
-
SetString(isolate, column, "column");
|
|
187
|
-
SetString(isolate, table, "table");
|
|
188
|
-
SetString(isolate, type, "type");
|
|
189
|
-
SetString(isolate, totalPages, "totalPages");
|
|
190
|
-
SetString(isolate, remainingPages, "remainingPages");
|
|
191
|
-
|
|
192
|
-
SetCode(isolate, SQLITE_OK, "SQLITE_OK");
|
|
193
|
-
SetCode(isolate, SQLITE_ERROR, "SQLITE_ERROR");
|
|
194
|
-
SetCode(isolate, SQLITE_INTERNAL, "SQLITE_INTERNAL");
|
|
195
|
-
SetCode(isolate, SQLITE_PERM, "SQLITE_PERM");
|
|
196
|
-
SetCode(isolate, SQLITE_ABORT, "SQLITE_ABORT");
|
|
197
|
-
SetCode(isolate, SQLITE_BUSY, "SQLITE_BUSY");
|
|
198
|
-
SetCode(isolate, SQLITE_LOCKED, "SQLITE_LOCKED");
|
|
199
|
-
SetCode(isolate, SQLITE_NOMEM, "SQLITE_NOMEM");
|
|
200
|
-
SetCode(isolate, SQLITE_READONLY, "SQLITE_READONLY");
|
|
201
|
-
SetCode(isolate, SQLITE_INTERRUPT, "SQLITE_INTERRUPT");
|
|
202
|
-
SetCode(isolate, SQLITE_IOERR, "SQLITE_IOERR");
|
|
203
|
-
SetCode(isolate, SQLITE_CORRUPT, "SQLITE_CORRUPT");
|
|
204
|
-
SetCode(isolate, SQLITE_NOTFOUND, "SQLITE_NOTFOUND");
|
|
205
|
-
SetCode(isolate, SQLITE_FULL, "SQLITE_FULL");
|
|
206
|
-
SetCode(isolate, SQLITE_CANTOPEN, "SQLITE_CANTOPEN");
|
|
207
|
-
SetCode(isolate, SQLITE_PROTOCOL, "SQLITE_PROTOCOL");
|
|
208
|
-
SetCode(isolate, SQLITE_EMPTY, "SQLITE_EMPTY");
|
|
209
|
-
SetCode(isolate, SQLITE_SCHEMA, "SQLITE_SCHEMA");
|
|
210
|
-
SetCode(isolate, SQLITE_TOOBIG, "SQLITE_TOOBIG");
|
|
211
|
-
SetCode(isolate, SQLITE_CONSTRAINT, "SQLITE_CONSTRAINT");
|
|
212
|
-
SetCode(isolate, SQLITE_MISMATCH, "SQLITE_MISMATCH");
|
|
213
|
-
SetCode(isolate, SQLITE_MISUSE, "SQLITE_MISUSE");
|
|
214
|
-
SetCode(isolate, SQLITE_NOLFS, "SQLITE_NOLFS");
|
|
215
|
-
SetCode(isolate, SQLITE_AUTH, "SQLITE_AUTH");
|
|
216
|
-
SetCode(isolate, SQLITE_FORMAT, "SQLITE_FORMAT");
|
|
217
|
-
SetCode(isolate, SQLITE_RANGE, "SQLITE_RANGE");
|
|
218
|
-
SetCode(isolate, SQLITE_NOTADB, "SQLITE_NOTADB");
|
|
219
|
-
SetCode(isolate, SQLITE_NOTICE, "SQLITE_NOTICE");
|
|
220
|
-
SetCode(isolate, SQLITE_WARNING, "SQLITE_WARNING");
|
|
221
|
-
SetCode(isolate, SQLITE_ROW, "SQLITE_ROW");
|
|
222
|
-
SetCode(isolate, SQLITE_DONE, "SQLITE_DONE");
|
|
223
|
-
SetCode(isolate, SQLITE_IOERR_READ, "SQLITE_IOERR_READ");
|
|
224
|
-
SetCode(isolate, SQLITE_IOERR_SHORT_READ, "SQLITE_IOERR_SHORT_READ");
|
|
225
|
-
SetCode(isolate, SQLITE_IOERR_WRITE, "SQLITE_IOERR_WRITE");
|
|
226
|
-
SetCode(isolate, SQLITE_IOERR_FSYNC, "SQLITE_IOERR_FSYNC");
|
|
227
|
-
SetCode(isolate, SQLITE_IOERR_DIR_FSYNC, "SQLITE_IOERR_DIR_FSYNC");
|
|
228
|
-
SetCode(isolate, SQLITE_IOERR_TRUNCATE, "SQLITE_IOERR_TRUNCATE");
|
|
229
|
-
SetCode(isolate, SQLITE_IOERR_FSTAT, "SQLITE_IOERR_FSTAT");
|
|
230
|
-
SetCode(isolate, SQLITE_IOERR_UNLOCK, "SQLITE_IOERR_UNLOCK");
|
|
231
|
-
SetCode(isolate, SQLITE_IOERR_RDLOCK, "SQLITE_IOERR_RDLOCK");
|
|
232
|
-
SetCode(isolate, SQLITE_IOERR_DELETE, "SQLITE_IOERR_DELETE");
|
|
233
|
-
SetCode(isolate, SQLITE_IOERR_BLOCKED, "SQLITE_IOERR_BLOCKED");
|
|
234
|
-
SetCode(isolate, SQLITE_IOERR_NOMEM, "SQLITE_IOERR_NOMEM");
|
|
235
|
-
SetCode(isolate, SQLITE_IOERR_ACCESS, "SQLITE_IOERR_ACCESS");
|
|
236
|
-
SetCode(isolate, SQLITE_IOERR_CHECKRESERVEDLOCK, "SQLITE_IOERR_CHECKRESERVEDLOCK");
|
|
237
|
-
SetCode(isolate, SQLITE_IOERR_LOCK, "SQLITE_IOERR_LOCK");
|
|
238
|
-
SetCode(isolate, SQLITE_IOERR_CLOSE, "SQLITE_IOERR_CLOSE");
|
|
239
|
-
SetCode(isolate, SQLITE_IOERR_DIR_CLOSE, "SQLITE_IOERR_DIR_CLOSE");
|
|
240
|
-
SetCode(isolate, SQLITE_IOERR_SHMOPEN, "SQLITE_IOERR_SHMOPEN");
|
|
241
|
-
SetCode(isolate, SQLITE_IOERR_SHMSIZE, "SQLITE_IOERR_SHMSIZE");
|
|
242
|
-
SetCode(isolate, SQLITE_IOERR_SHMLOCK, "SQLITE_IOERR_SHMLOCK");
|
|
243
|
-
SetCode(isolate, SQLITE_IOERR_SHMMAP, "SQLITE_IOERR_SHMMAP");
|
|
244
|
-
SetCode(isolate, SQLITE_IOERR_SEEK, "SQLITE_IOERR_SEEK");
|
|
245
|
-
SetCode(isolate, SQLITE_IOERR_DELETE_NOENT, "SQLITE_IOERR_DELETE_NOENT");
|
|
246
|
-
SetCode(isolate, SQLITE_IOERR_MMAP, "SQLITE_IOERR_MMAP");
|
|
247
|
-
SetCode(isolate, SQLITE_IOERR_GETTEMPPATH, "SQLITE_IOERR_GETTEMPPATH");
|
|
248
|
-
SetCode(isolate, SQLITE_IOERR_CONVPATH, "SQLITE_IOERR_CONVPATH");
|
|
249
|
-
SetCode(isolate, SQLITE_IOERR_VNODE, "SQLITE_IOERR_VNODE");
|
|
250
|
-
SetCode(isolate, SQLITE_IOERR_AUTH, "SQLITE_IOERR_AUTH");
|
|
251
|
-
SetCode(isolate, SQLITE_LOCKED_SHAREDCACHE, "SQLITE_LOCKED_SHAREDCACHE");
|
|
252
|
-
SetCode(isolate, SQLITE_BUSY_RECOVERY, "SQLITE_BUSY_RECOVERY");
|
|
253
|
-
SetCode(isolate, SQLITE_BUSY_SNAPSHOT, "SQLITE_BUSY_SNAPSHOT");
|
|
254
|
-
SetCode(isolate, SQLITE_CANTOPEN_NOTEMPDIR, "SQLITE_CANTOPEN_NOTEMPDIR");
|
|
255
|
-
SetCode(isolate, SQLITE_CANTOPEN_ISDIR, "SQLITE_CANTOPEN_ISDIR");
|
|
256
|
-
SetCode(isolate, SQLITE_CANTOPEN_FULLPATH, "SQLITE_CANTOPEN_FULLPATH");
|
|
257
|
-
SetCode(isolate, SQLITE_CANTOPEN_CONVPATH, "SQLITE_CANTOPEN_CONVPATH");
|
|
258
|
-
SetCode(isolate, SQLITE_CORRUPT_VTAB, "SQLITE_CORRUPT_VTAB");
|
|
259
|
-
SetCode(isolate, SQLITE_READONLY_RECOVERY, "SQLITE_READONLY_RECOVERY");
|
|
260
|
-
SetCode(isolate, SQLITE_READONLY_CANTLOCK, "SQLITE_READONLY_CANTLOCK");
|
|
261
|
-
SetCode(isolate, SQLITE_READONLY_ROLLBACK, "SQLITE_READONLY_ROLLBACK");
|
|
262
|
-
SetCode(isolate, SQLITE_READONLY_DBMOVED, "SQLITE_READONLY_DBMOVED");
|
|
263
|
-
SetCode(isolate, SQLITE_ABORT_ROLLBACK, "SQLITE_ABORT_ROLLBACK");
|
|
264
|
-
SetCode(isolate, SQLITE_CONSTRAINT_CHECK, "SQLITE_CONSTRAINT_CHECK");
|
|
265
|
-
SetCode(isolate, SQLITE_CONSTRAINT_COMMITHOOK, "SQLITE_CONSTRAINT_COMMITHOOK");
|
|
266
|
-
SetCode(isolate, SQLITE_CONSTRAINT_FOREIGNKEY, "SQLITE_CONSTRAINT_FOREIGNKEY");
|
|
267
|
-
SetCode(isolate, SQLITE_CONSTRAINT_FUNCTION, "SQLITE_CONSTRAINT_FUNCTION");
|
|
268
|
-
SetCode(isolate, SQLITE_CONSTRAINT_NOTNULL, "SQLITE_CONSTRAINT_NOTNULL");
|
|
269
|
-
SetCode(isolate, SQLITE_CONSTRAINT_PRIMARYKEY, "SQLITE_CONSTRAINT_PRIMARYKEY");
|
|
270
|
-
SetCode(isolate, SQLITE_CONSTRAINT_TRIGGER, "SQLITE_CONSTRAINT_TRIGGER");
|
|
271
|
-
SetCode(isolate, SQLITE_CONSTRAINT_UNIQUE, "SQLITE_CONSTRAINT_UNIQUE");
|
|
272
|
-
SetCode(isolate, SQLITE_CONSTRAINT_VTAB, "SQLITE_CONSTRAINT_VTAB");
|
|
273
|
-
SetCode(isolate, SQLITE_CONSTRAINT_ROWID, "SQLITE_CONSTRAINT_ROWID");
|
|
274
|
-
SetCode(isolate, SQLITE_NOTICE_RECOVER_WAL, "SQLITE_NOTICE_RECOVER_WAL");
|
|
275
|
-
SetCode(isolate, SQLITE_NOTICE_RECOVER_ROLLBACK, "SQLITE_NOTICE_RECOVER_ROLLBACK");
|
|
276
|
-
SetCode(isolate, SQLITE_WARNING_AUTOINDEX, "SQLITE_WARNING_AUTOINDEX");
|
|
277
|
-
SetCode(isolate, SQLITE_AUTH_USER, "SQLITE_AUTH_USER");
|
|
278
|
-
SetCode(isolate, SQLITE_OK_LOAD_PERMANENTLY, "SQLITE_OK_LOAD_PERMANENTLY");
|
|
279
|
-
}
|
|
280
|
-
#line 140 "./src/util/constants.lzz"
|
|
281
|
-
void CS::SetString (v8::Isolate * isolate, v8::Global <v8::String> & constant, char const * str)
|
|
282
|
-
#line 140 "./src/util/constants.lzz"
|
|
283
|
-
{
|
|
284
|
-
constant.Reset(isolate, InternalizedFromLatin1(isolate, str));
|
|
285
|
-
}
|
|
286
|
-
#line 144 "./src/util/constants.lzz"
|
|
287
|
-
void CS::SetCode (v8::Isolate * isolate, int code, char const * str)
|
|
288
|
-
#line 144 "./src/util/constants.lzz"
|
|
289
|
-
{
|
|
290
|
-
codes.emplace(std::piecewise_construct,
|
|
291
|
-
std::forward_as_tuple(code),
|
|
292
|
-
std::forward_as_tuple(isolate, InternalizedFromLatin1(isolate, str)));
|
|
293
|
-
}
|
|
294
|
-
#line 19 "./src/util/bind-map.lzz"
|
|
295
|
-
BindMap::Pair::Pair (v8::Isolate * isolate, char const * name, int index)
|
|
296
|
-
#line 20 "./src/util/bind-map.lzz"
|
|
297
|
-
: name (isolate, InternalizedFromUtf8(isolate, name, -1)), index (index)
|
|
298
|
-
#line 20 "./src/util/bind-map.lzz"
|
|
299
|
-
{}
|
|
300
|
-
#line 22 "./src/util/bind-map.lzz"
|
|
301
|
-
BindMap::Pair::Pair (v8::Isolate * isolate, Pair * pair)
|
|
302
|
-
#line 23 "./src/util/bind-map.lzz"
|
|
303
|
-
: name (isolate, pair->name), index (pair->index)
|
|
304
|
-
#line 23 "./src/util/bind-map.lzz"
|
|
305
|
-
{}
|
|
306
|
-
#line 29 "./src/util/bind-map.lzz"
|
|
307
|
-
BindMap::BindMap (char _)
|
|
308
|
-
#line 29 "./src/util/bind-map.lzz"
|
|
309
|
-
{
|
|
310
|
-
assert(_ == 0);
|
|
311
|
-
pairs = NULL;
|
|
312
|
-
capacity = 0;
|
|
313
|
-
length = 0;
|
|
314
|
-
}
|
|
315
|
-
#line 36 "./src/util/bind-map.lzz"
|
|
316
|
-
BindMap::~ BindMap ()
|
|
317
|
-
#line 36 "./src/util/bind-map.lzz"
|
|
318
|
-
{
|
|
319
|
-
while (length) pairs[--length].~Pair();
|
|
320
|
-
FREE_ARRAY<Pair>(pairs);
|
|
321
|
-
}
|
|
322
|
-
#line 50 "./src/util/bind-map.lzz"
|
|
323
|
-
void BindMap::Add (v8::Isolate * isolate, char const * name, int index)
|
|
324
|
-
#line 50 "./src/util/bind-map.lzz"
|
|
325
|
-
{
|
|
326
|
-
assert(name != NULL);
|
|
327
|
-
if (capacity == length) Grow(isolate);
|
|
328
|
-
new (pairs + length++) Pair(isolate, name, index);
|
|
329
|
-
}
|
|
330
|
-
#line 58 "./src/util/bind-map.lzz"
|
|
331
|
-
void BindMap::Grow (v8::Isolate * isolate)
|
|
332
|
-
#line 58 "./src/util/bind-map.lzz"
|
|
333
|
-
{
|
|
334
|
-
assert(capacity == length);
|
|
335
|
-
capacity = (capacity << 1) | 2;
|
|
336
|
-
Pair* new_pairs = ALLOC_ARRAY<Pair>(capacity);
|
|
337
|
-
for (int i = 0; i < length; ++i) {
|
|
338
|
-
new (new_pairs + i) Pair(isolate, pairs + i);
|
|
339
|
-
pairs[i].~Pair();
|
|
340
|
-
}
|
|
341
|
-
FREE_ARRAY<Pair>(pairs);
|
|
342
|
-
pairs = new_pairs;
|
|
343
|
-
}
|
|
344
|
-
#line 4 "./src/objects/database.lzz"
|
|
345
|
-
v8::Local <v8 :: Function> Database::Init (v8::Isolate * isolate, v8::Local <v8 :: External> data)
|
|
346
|
-
#line 4 "./src/objects/database.lzz"
|
|
347
|
-
{
|
|
348
|
-
v8::Local<v8::FunctionTemplate> t = NewConstructorTemplate(isolate, data, JS_new, "Database");
|
|
349
|
-
SetPrototypeMethod(isolate, data, t, "prepare", JS_prepare);
|
|
350
|
-
SetPrototypeMethod(isolate, data, t, "exec", JS_exec);
|
|
351
|
-
SetPrototypeMethod(isolate, data, t, "backup", JS_backup);
|
|
352
|
-
SetPrototypeMethod(isolate, data, t, "serialize", JS_serialize);
|
|
353
|
-
SetPrototypeMethod(isolate, data, t, "function", JS_function);
|
|
354
|
-
SetPrototypeMethod(isolate, data, t, "aggregate", JS_aggregate);
|
|
355
|
-
SetPrototypeMethod(isolate, data, t, "table", JS_table);
|
|
356
|
-
SetPrototypeMethod(isolate, data, t, "close", JS_close);
|
|
357
|
-
SetPrototypeMethod(isolate, data, t, "defaultSafeIntegers", JS_defaultSafeIntegers);
|
|
358
|
-
SetPrototypeMethod(isolate, data, t, "unsafeMode", JS_unsafeMode);
|
|
359
|
-
SetPrototypeGetter(isolate, data, t, "open", JS_open);
|
|
360
|
-
SetPrototypeGetter(isolate, data, t, "inTransaction", JS_inTransaction);
|
|
361
|
-
return t->GetFunction( isolate -> GetCurrentContext ( ) ).ToLocalChecked();
|
|
362
|
-
}
|
|
363
|
-
#line 24 "./src/objects/database.lzz"
|
|
364
|
-
bool Database::CompareDatabase::operator () (Database const * const a, Database const * const b) const
|
|
365
|
-
#line 24 "./src/objects/database.lzz"
|
|
366
|
-
{
|
|
367
|
-
return a < b;
|
|
368
|
-
}
|
|
369
|
-
#line 29 "./src/objects/database.lzz"
|
|
370
|
-
bool Database::CompareStatement::operator () (Statement const * const a, Statement const * const b) const
|
|
371
|
-
#line 29 "./src/objects/database.lzz"
|
|
372
|
-
{
|
|
373
|
-
return Statement::Compare(a, b);
|
|
374
|
-
}
|
|
375
|
-
#line 34 "./src/objects/database.lzz"
|
|
376
|
-
bool Database::CompareBackup::operator () (Backup const * const a, Backup const * const b) const
|
|
377
|
-
#line 34 "./src/objects/database.lzz"
|
|
378
|
-
{
|
|
379
|
-
return Backup::Compare(a, b);
|
|
380
|
-
}
|
|
381
|
-
#line 40 "./src/objects/database.lzz"
|
|
382
|
-
void Database::ThrowDatabaseError ()
|
|
383
|
-
#line 40 "./src/objects/database.lzz"
|
|
384
|
-
{
|
|
385
|
-
if (was_js_error) was_js_error = false;
|
|
386
|
-
else ThrowSqliteError(addon, db_handle);
|
|
387
|
-
}
|
|
388
|
-
#line 44 "./src/objects/database.lzz"
|
|
389
|
-
void Database::ThrowSqliteError (Addon * addon, sqlite3 * db_handle)
|
|
390
|
-
#line 44 "./src/objects/database.lzz"
|
|
391
|
-
{
|
|
392
|
-
assert(db_handle != NULL);
|
|
393
|
-
ThrowSqliteError(addon, sqlite3_errmsg(db_handle), sqlite3_extended_errcode(db_handle));
|
|
394
|
-
}
|
|
395
|
-
#line 48 "./src/objects/database.lzz"
|
|
396
|
-
void Database::ThrowSqliteError (Addon * addon, char const * message, int code)
|
|
397
|
-
#line 48 "./src/objects/database.lzz"
|
|
398
|
-
{
|
|
399
|
-
assert(message != NULL);
|
|
400
|
-
assert((code & 0xff) != SQLITE_OK);
|
|
401
|
-
assert((code & 0xff) != SQLITE_ROW);
|
|
402
|
-
assert((code & 0xff) != SQLITE_DONE);
|
|
403
|
-
v8 :: Isolate * isolate = v8 :: Isolate :: GetCurrent ( ) ;
|
|
404
|
-
v8::Local<v8::Value> args[2] = {
|
|
405
|
-
StringFromUtf8(isolate, message, -1),
|
|
406
|
-
addon->cs.Code(isolate, code)
|
|
407
|
-
};
|
|
408
|
-
isolate->ThrowException(addon->SqliteError.Get(isolate)
|
|
409
|
-
->NewInstance( isolate -> GetCurrentContext ( ) , 2, args)
|
|
410
|
-
.ToLocalChecked());
|
|
411
|
-
}
|
|
412
|
-
#line 64 "./src/objects/database.lzz"
|
|
413
|
-
bool Database::Log (v8::Isolate * isolate, sqlite3_stmt * handle)
|
|
414
|
-
#line 64 "./src/objects/database.lzz"
|
|
415
|
-
{
|
|
416
|
-
assert(was_js_error == false);
|
|
417
|
-
if (!has_logger) return false;
|
|
418
|
-
char* expanded = sqlite3_expanded_sql(handle);
|
|
419
|
-
v8::Local<v8::Value> arg = StringFromUtf8(isolate, expanded ? expanded : sqlite3_sql(handle), -1);
|
|
420
|
-
was_js_error = logger.Get(isolate).As<v8::Function>()
|
|
421
|
-
->Call( isolate -> GetCurrentContext ( ) , v8::Undefined(isolate), 1, &arg)
|
|
422
|
-
.IsEmpty();
|
|
423
|
-
if (expanded) sqlite3_free(expanded);
|
|
424
|
-
return was_js_error;
|
|
425
|
-
}
|
|
426
|
-
#line 107 "./src/objects/database.lzz"
|
|
427
|
-
void Database::CloseHandles ()
|
|
428
|
-
#line 107 "./src/objects/database.lzz"
|
|
429
|
-
{
|
|
430
|
-
if (open) {
|
|
431
|
-
open = false;
|
|
432
|
-
for (Statement* stmt : stmts) stmt->CloseHandles();
|
|
433
|
-
for (Backup* backup : backups) backup->CloseHandles();
|
|
434
|
-
stmts.clear();
|
|
435
|
-
backups.clear();
|
|
436
|
-
int status = sqlite3_close(db_handle);
|
|
437
|
-
assert(status == SQLITE_OK); ((void)status);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
#line 119 "./src/objects/database.lzz"
|
|
441
|
-
Database::~ Database ()
|
|
442
|
-
#line 119 "./src/objects/database.lzz"
|
|
443
|
-
{
|
|
444
|
-
if (open) addon->dbs.erase(this);
|
|
445
|
-
CloseHandles();
|
|
446
|
-
}
|
|
447
|
-
#line 126 "./src/objects/database.lzz"
|
|
448
|
-
Database::Database (v8::Isolate * isolate, Addon * addon, sqlite3 * db_handle, v8::Local <v8::Value> logger)
|
|
449
|
-
#line 131 "./src/objects/database.lzz"
|
|
450
|
-
: node::ObjectWrap (), db_handle (db_handle), open (true), busy (false), safe_ints (false), unsafe_mode (false), was_js_error (false), has_logger (logger->IsFunction()), iterators (0), addon (addon), logger (isolate, logger), stmts (), backups ()
|
|
451
|
-
#line 144 "./src/objects/database.lzz"
|
|
452
|
-
{
|
|
453
|
-
assert(db_handle != NULL);
|
|
454
|
-
addon->dbs.insert(this);
|
|
455
|
-
}
|
|
456
|
-
#line 149 "./src/objects/database.lzz"
|
|
457
|
-
void Database::JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
458
|
-
#line 149 "./src/objects/database.lzz"
|
|
459
|
-
{
|
|
460
|
-
assert(info.IsConstructCall());
|
|
461
|
-
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > filename = ( info [ 0 ] . As < v8 :: String > ( ) ) ;
|
|
462
|
-
if ( info . Length ( ) <= ( 1 ) || ! info [ 1 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "second" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > filenameGiven = ( info [ 1 ] . As < v8 :: String > ( ) ) ;
|
|
463
|
-
if ( info . Length ( ) <= ( 2 ) || ! info [ 2 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "third" " argument to be " "a boolean" ) ; bool in_memory = ( info [ 2 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ;
|
|
464
|
-
if ( info . Length ( ) <= ( 3 ) || ! info [ 3 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "fourth" " argument to be " "a boolean" ) ; bool readonly = ( info [ 3 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ;
|
|
465
|
-
if ( info . Length ( ) <= ( 4 ) || ! info [ 4 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "fifth" " argument to be " "a boolean" ) ; bool must_exist = ( info [ 4 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ;
|
|
466
|
-
if ( info . Length ( ) <= ( 5 ) || ! info [ 5 ] -> IsInt32 ( ) ) return ThrowTypeError ( "Expected " "sixth" " argument to be " "a 32-bit signed integer" ) ; int timeout = ( info [ 5 ] . As < v8 :: Int32 > ( ) ) -> Value ( ) ;
|
|
467
|
-
if ( info . Length ( ) <= ( 6 ) ) return ThrowTypeError ( "Expected a " "seventh" " argument" ) ; v8 :: Local < v8 :: Value > logger = info [ 6 ] ;
|
|
468
|
-
if ( info . Length ( ) <= ( 7 ) ) return ThrowTypeError ( "Expected a " "eighth" " argument" ) ; v8 :: Local < v8 :: Value > buffer = info [ 7 ] ;
|
|
469
|
-
|
|
470
|
-
Addon * addon = static_cast < Addon * > ( info . Data ( ) . As < v8 :: External > ( ) -> Value ( ) ) ;
|
|
471
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
472
|
-
sqlite3* db_handle;
|
|
473
|
-
v8::String::Utf8Value utf8(isolate, filename);
|
|
474
|
-
int mask = readonly ? SQLITE_OPEN_READONLY
|
|
475
|
-
: must_exist ? SQLITE_OPEN_READWRITE
|
|
476
|
-
: (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
|
477
|
-
|
|
478
|
-
if (sqlite3_open_v2(*utf8, &db_handle, mask, NULL) != SQLITE_OK) {
|
|
479
|
-
ThrowSqliteError(addon, db_handle);
|
|
480
|
-
int status = sqlite3_close(db_handle);
|
|
481
|
-
assert(status == SQLITE_OK); ((void)status);
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
assert(sqlite3_db_mutex(db_handle) == NULL);
|
|
486
|
-
sqlite3_extended_result_codes(db_handle, 1);
|
|
487
|
-
sqlite3_busy_timeout(db_handle, timeout);
|
|
488
|
-
sqlite3_limit(db_handle, SQLITE_LIMIT_LENGTH, MAX_BUFFER_SIZE < MAX_STRING_SIZE ? MAX_BUFFER_SIZE : MAX_STRING_SIZE);
|
|
489
|
-
sqlite3_limit(db_handle, SQLITE_LIMIT_SQL_LENGTH, MAX_STRING_SIZE);
|
|
490
|
-
int status = sqlite3_db_config(db_handle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL);
|
|
491
|
-
assert(status == SQLITE_OK);
|
|
492
|
-
status = sqlite3_db_config(db_handle, SQLITE_DBCONFIG_DEFENSIVE, 1, NULL);
|
|
493
|
-
assert(status == SQLITE_OK);
|
|
494
|
-
|
|
495
|
-
if (node::Buffer::HasInstance(buffer) && !Deserialize(buffer.As<v8::Object>(), addon, db_handle, readonly)) {
|
|
496
|
-
int status = sqlite3_close(db_handle);
|
|
497
|
-
assert(status == SQLITE_OK); ((void)status);
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
502
|
-
Database* db = new Database(isolate, addon, db_handle, logger);
|
|
503
|
-
db->Wrap(info.This());
|
|
504
|
-
SetFrozen(isolate, ctx, info.This(), addon->cs.memory, v8::Boolean::New(isolate, in_memory));
|
|
505
|
-
SetFrozen(isolate, ctx, info.This(), addon->cs.readonly, v8::Boolean::New(isolate, readonly));
|
|
506
|
-
SetFrozen(isolate, ctx, info.This(), addon->cs.name, filenameGiven);
|
|
507
|
-
|
|
508
|
-
info.GetReturnValue().Set(info.This());
|
|
509
|
-
}
|
|
510
|
-
#line 201 "./src/objects/database.lzz"
|
|
511
|
-
void Database::JS_prepare (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
512
|
-
#line 201 "./src/objects/database.lzz"
|
|
513
|
-
{
|
|
514
|
-
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > source = ( info [ 0 ] . As < v8 :: String > ( ) ) ;
|
|
515
|
-
if ( info . Length ( ) <= ( 1 ) || ! info [ 1 ] -> IsObject ( ) ) return ThrowTypeError ( "Expected " "second" " argument to be " "an object" ) ; v8 :: Local < v8 :: Object > database = ( info [ 1 ] . As < v8 :: Object > ( ) ) ;
|
|
516
|
-
if ( info . Length ( ) <= ( 2 ) || ! info [ 2 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "third" " argument to be " "a boolean" ) ; bool pragmaMode = ( info [ 2 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ;
|
|
517
|
-
(void)source;
|
|
518
|
-
(void)database;
|
|
519
|
-
(void)pragmaMode;
|
|
520
|
-
Addon * addon = static_cast < Addon * > ( info . Data ( ) . As < v8 :: External > ( ) -> Value ( ) ) ;
|
|
521
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
522
|
-
v8::Local<v8::Function> c = addon->Statement.Get(isolate);
|
|
523
|
-
addon->privileged_info = &info;
|
|
524
|
-
v8::MaybeLocal<v8::Object> maybeStatement = c->NewInstance( isolate -> GetCurrentContext ( ) , 0, NULL);
|
|
525
|
-
addon->privileged_info = NULL;
|
|
526
|
-
if (!maybeStatement.IsEmpty()) info.GetReturnValue().Set(maybeStatement.ToLocalChecked());
|
|
527
|
-
}
|
|
528
|
-
#line 217 "./src/objects/database.lzz"
|
|
529
|
-
void Database::JS_exec (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
530
|
-
#line 217 "./src/objects/database.lzz"
|
|
531
|
-
{
|
|
532
|
-
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
|
|
533
|
-
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > source = ( info [ 0 ] . As < v8 :: String > ( ) ) ;
|
|
534
|
-
if ( ! db -> open ) return ThrowTypeError ( "The database connection is not open" ) ;
|
|
535
|
-
if ( db -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
536
|
-
if ( ! db -> unsafe_mode ) { if ( db -> iterators ) return ThrowTypeError ( "This database connection is busy executing a query" ) ; } ( ( void ) 0 ) ;
|
|
537
|
-
db->busy = true;
|
|
538
|
-
|
|
539
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
540
|
-
v8::String::Utf8Value utf8(isolate, source);
|
|
541
|
-
const char* sql = *utf8;
|
|
542
|
-
const char* tail;
|
|
543
|
-
|
|
544
|
-
int status;
|
|
545
|
-
const bool has_logger = db->has_logger;
|
|
546
|
-
sqlite3* const db_handle = db->db_handle;
|
|
547
|
-
sqlite3_stmt* handle;
|
|
548
|
-
|
|
549
|
-
for (;;) {
|
|
550
|
-
while (IS_SKIPPED(*sql)) ++sql;
|
|
551
|
-
status = sqlite3_prepare_v2(db_handle, sql, -1, &handle, &tail);
|
|
552
|
-
sql = tail;
|
|
553
|
-
if (!handle) break;
|
|
554
|
-
if (has_logger && db->Log(isolate, handle)) {
|
|
555
|
-
sqlite3_finalize(handle);
|
|
556
|
-
status = -1;
|
|
557
|
-
break;
|
|
558
|
-
}
|
|
559
|
-
do status = sqlite3_step(handle);
|
|
560
|
-
while (status == SQLITE_ROW);
|
|
561
|
-
status = sqlite3_finalize(handle);
|
|
562
|
-
if (status != SQLITE_OK) break;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
db->busy = false;
|
|
566
|
-
if (status != SQLITE_OK) {
|
|
567
|
-
db->ThrowDatabaseError();
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
#line 257 "./src/objects/database.lzz"
|
|
571
|
-
void Database::JS_backup (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
572
|
-
#line 257 "./src/objects/database.lzz"
|
|
573
|
-
{
|
|
574
|
-
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsObject ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "an object" ) ; v8 :: Local < v8 :: Object > database = ( info [ 0 ] . As < v8 :: Object > ( ) ) ;
|
|
575
|
-
if ( info . Length ( ) <= ( 1 ) || ! info [ 1 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "second" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > attachedName = ( info [ 1 ] . As < v8 :: String > ( ) ) ;
|
|
576
|
-
if ( info . Length ( ) <= ( 2 ) || ! info [ 2 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "third" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > destFile = ( info [ 2 ] . As < v8 :: String > ( ) ) ;
|
|
577
|
-
if ( info . Length ( ) <= ( 3 ) || ! info [ 3 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "fourth" " argument to be " "a boolean" ) ; bool unlink = ( info [ 3 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ;
|
|
578
|
-
(void)database;
|
|
579
|
-
(void)attachedName;
|
|
580
|
-
(void)destFile;
|
|
581
|
-
(void)unlink;
|
|
582
|
-
Addon * addon = static_cast < Addon * > ( info . Data ( ) . As < v8 :: External > ( ) -> Value ( ) ) ;
|
|
583
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
584
|
-
v8::Local<v8::Function> c = addon->Backup.Get(isolate);
|
|
585
|
-
addon->privileged_info = &info;
|
|
586
|
-
v8::MaybeLocal<v8::Object> maybeBackup = c->NewInstance( isolate -> GetCurrentContext ( ) , 0, NULL);
|
|
587
|
-
addon->privileged_info = NULL;
|
|
588
|
-
if (!maybeBackup.IsEmpty()) info.GetReturnValue().Set(maybeBackup.ToLocalChecked());
|
|
589
|
-
}
|
|
590
|
-
#line 275 "./src/objects/database.lzz"
|
|
591
|
-
void Database::JS_serialize (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
592
|
-
#line 275 "./src/objects/database.lzz"
|
|
593
|
-
{
|
|
594
|
-
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
|
|
595
|
-
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > attachedName = ( info [ 0 ] . As < v8 :: String > ( ) ) ;
|
|
596
|
-
if ( ! db -> open ) return ThrowTypeError ( "The database connection is not open" ) ;
|
|
597
|
-
if ( db -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
598
|
-
if ( db -> iterators ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
599
|
-
|
|
600
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
601
|
-
v8::String::Utf8Value attached_name(isolate, attachedName);
|
|
602
|
-
sqlite3_int64 length = -1;
|
|
603
|
-
unsigned char* data = sqlite3_serialize(db->db_handle, *attached_name, &length, 0);
|
|
604
|
-
|
|
605
|
-
if (!data && length) {
|
|
606
|
-
ThrowError("Out of memory");
|
|
607
|
-
return;
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
info.GetReturnValue().Set(
|
|
611
|
-
SAFE_NEW_BUFFER(isolate, reinterpret_cast<char*>(data), length, FreeSerialization, NULL).ToLocalChecked()
|
|
612
|
-
);
|
|
613
|
-
}
|
|
614
|
-
#line 297 "./src/objects/database.lzz"
|
|
615
|
-
void Database::JS_function (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
616
|
-
#line 297 "./src/objects/database.lzz"
|
|
617
|
-
{
|
|
618
|
-
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
|
|
619
|
-
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsFunction ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a function" ) ; v8 :: Local < v8 :: Function > fn = ( info [ 0 ] . As < v8 :: Function > ( ) ) ;
|
|
620
|
-
if ( info . Length ( ) <= ( 1 ) || ! info [ 1 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "second" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > nameString = ( info [ 1 ] . As < v8 :: String > ( ) ) ;
|
|
621
|
-
if ( info . Length ( ) <= ( 2 ) || ! info [ 2 ] -> IsInt32 ( ) ) return ThrowTypeError ( "Expected " "third" " argument to be " "a 32-bit signed integer" ) ; int argc = ( info [ 2 ] . As < v8 :: Int32 > ( ) ) -> Value ( ) ;
|
|
622
|
-
if ( info . Length ( ) <= ( 3 ) || ! info [ 3 ] -> IsInt32 ( ) ) return ThrowTypeError ( "Expected " "fourth" " argument to be " "a 32-bit signed integer" ) ; int safe_ints = ( info [ 3 ] . As < v8 :: Int32 > ( ) ) -> Value ( ) ;
|
|
623
|
-
if ( info . Length ( ) <= ( 4 ) || ! info [ 4 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "fifth" " argument to be " "a boolean" ) ; bool deterministic = ( info [ 4 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ;
|
|
624
|
-
if ( info . Length ( ) <= ( 5 ) || ! info [ 5 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "sixth" " argument to be " "a boolean" ) ; bool direct_only = ( info [ 5 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ;
|
|
625
|
-
if ( ! db -> open ) return ThrowTypeError ( "The database connection is not open" ) ;
|
|
626
|
-
if ( db -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
627
|
-
if ( db -> iterators ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
628
|
-
|
|
629
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
630
|
-
v8::String::Utf8Value name(isolate, nameString);
|
|
631
|
-
int mask = SQLITE_UTF8;
|
|
632
|
-
if (deterministic) mask |= SQLITE_DETERMINISTIC;
|
|
633
|
-
if (direct_only) mask |= SQLITE_DIRECTONLY;
|
|
634
|
-
safe_ints = safe_ints < 2 ? safe_ints : static_cast<int>(db->safe_ints);
|
|
635
|
-
|
|
636
|
-
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) {
|
|
637
|
-
db->ThrowDatabaseError();
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
#line 321 "./src/objects/database.lzz"
|
|
641
|
-
void Database::JS_aggregate (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
642
|
-
#line 321 "./src/objects/database.lzz"
|
|
643
|
-
{
|
|
644
|
-
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
|
|
645
|
-
if ( info . Length ( ) <= ( 0 ) ) return ThrowTypeError ( "Expected a " "first" " argument" ) ; v8 :: Local < v8 :: Value > start = info [ 0 ] ;
|
|
646
|
-
if ( info . Length ( ) <= ( 1 ) || ! info [ 1 ] -> IsFunction ( ) ) return ThrowTypeError ( "Expected " "second" " argument to be " "a function" ) ; v8 :: Local < v8 :: Function > step = ( info [ 1 ] . As < v8 :: Function > ( ) ) ;
|
|
647
|
-
if ( info . Length ( ) <= ( 2 ) ) return ThrowTypeError ( "Expected a " "third" " argument" ) ; v8 :: Local < v8 :: Value > inverse = info [ 2 ] ;
|
|
648
|
-
if ( info . Length ( ) <= ( 3 ) ) return ThrowTypeError ( "Expected a " "fourth" " argument" ) ; v8 :: Local < v8 :: Value > result = info [ 3 ] ;
|
|
649
|
-
if ( info . Length ( ) <= ( 4 ) || ! info [ 4 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "fifth" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > nameString = ( info [ 4 ] . As < v8 :: String > ( ) ) ;
|
|
650
|
-
if ( info . Length ( ) <= ( 5 ) || ! info [ 5 ] -> IsInt32 ( ) ) return ThrowTypeError ( "Expected " "sixth" " argument to be " "a 32-bit signed integer" ) ; int argc = ( info [ 5 ] . As < v8 :: Int32 > ( ) ) -> Value ( ) ;
|
|
651
|
-
if ( info . Length ( ) <= ( 6 ) || ! info [ 6 ] -> IsInt32 ( ) ) return ThrowTypeError ( "Expected " "seventh" " argument to be " "a 32-bit signed integer" ) ; int safe_ints = ( info [ 6 ] . As < v8 :: Int32 > ( ) ) -> Value ( ) ;
|
|
652
|
-
if ( info . Length ( ) <= ( 7 ) || ! info [ 7 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "eighth" " argument to be " "a boolean" ) ; bool deterministic = ( info [ 7 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ;
|
|
653
|
-
if ( info . Length ( ) <= ( 8 ) || ! info [ 8 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "ninth" " argument to be " "a boolean" ) ; bool direct_only = ( info [ 8 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ;
|
|
654
|
-
if ( ! db -> open ) return ThrowTypeError ( "The database connection is not open" ) ;
|
|
655
|
-
if ( db -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
656
|
-
if ( db -> iterators ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
657
|
-
|
|
658
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
659
|
-
v8::String::Utf8Value name(isolate, nameString);
|
|
660
|
-
auto xInverse = inverse->IsFunction() ? CustomAggregate::xInverse : NULL;
|
|
661
|
-
auto xValue = xInverse ? CustomAggregate::xValue : NULL;
|
|
662
|
-
int mask = SQLITE_UTF8;
|
|
663
|
-
if (deterministic) mask |= SQLITE_DETERMINISTIC;
|
|
664
|
-
if (direct_only) mask |= SQLITE_DIRECTONLY;
|
|
665
|
-
safe_ints = safe_ints < 2 ? safe_ints : static_cast<int>(db->safe_ints);
|
|
666
|
-
|
|
667
|
-
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) {
|
|
668
|
-
db->ThrowDatabaseError();
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
#line 350 "./src/objects/database.lzz"
|
|
672
|
-
void Database::JS_table (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
673
|
-
#line 350 "./src/objects/database.lzz"
|
|
674
|
-
{
|
|
675
|
-
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
|
|
676
|
-
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsFunction ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a function" ) ; v8 :: Local < v8 :: Function > factory = ( info [ 0 ] . As < v8 :: Function > ( ) ) ;
|
|
677
|
-
if ( info . Length ( ) <= ( 1 ) || ! info [ 1 ] -> IsString ( ) ) return ThrowTypeError ( "Expected " "second" " argument to be " "a string" ) ; v8 :: Local < v8 :: String > nameString = ( info [ 1 ] . As < v8 :: String > ( ) ) ;
|
|
678
|
-
if ( info . Length ( ) <= ( 2 ) || ! info [ 2 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "third" " argument to be " "a boolean" ) ; bool eponymous = ( info [ 2 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ;
|
|
679
|
-
if ( ! db -> open ) return ThrowTypeError ( "The database connection is not open" ) ;
|
|
680
|
-
if ( db -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
681
|
-
if ( db -> iterators ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
682
|
-
|
|
683
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
684
|
-
v8::String::Utf8Value name(isolate, nameString);
|
|
685
|
-
sqlite3_module* module = eponymous ? &CustomTable::EPONYMOUS_MODULE : &CustomTable::MODULE;
|
|
686
|
-
|
|
687
|
-
db->busy = true;
|
|
688
|
-
if (sqlite3_create_module_v2(db->db_handle, *name, module, new CustomTable(isolate, db, *name, factory), CustomTable::Destructor) != SQLITE_OK) {
|
|
689
|
-
db->ThrowDatabaseError();
|
|
690
|
-
}
|
|
691
|
-
db->busy = false;
|
|
692
|
-
}
|
|
693
|
-
#line 392 "./src/objects/database.lzz"
|
|
694
|
-
void Database::JS_close (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
695
|
-
#line 392 "./src/objects/database.lzz"
|
|
696
|
-
{
|
|
697
|
-
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
|
|
698
|
-
if (db->open) {
|
|
699
|
-
if ( db -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
700
|
-
if ( db -> iterators ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
701
|
-
db->addon->dbs.erase(db);
|
|
702
|
-
db->CloseHandles();
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
#line 402 "./src/objects/database.lzz"
|
|
706
|
-
void Database::JS_defaultSafeIntegers (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
707
|
-
#line 402 "./src/objects/database.lzz"
|
|
708
|
-
{
|
|
709
|
-
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
|
|
710
|
-
if (info.Length() == 0) db->safe_ints = true;
|
|
711
|
-
else { if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a boolean" ) ; db -> safe_ints = ( info [ 0 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ; }
|
|
712
|
-
}
|
|
713
|
-
#line 408 "./src/objects/database.lzz"
|
|
714
|
-
void Database::JS_unsafeMode (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
715
|
-
#line 408 "./src/objects/database.lzz"
|
|
716
|
-
{
|
|
717
|
-
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
|
|
718
|
-
if (info.Length() == 0) db->unsafe_mode = true;
|
|
719
|
-
else { if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a boolean" ) ; db -> unsafe_mode = ( info [ 0 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ; }
|
|
720
|
-
sqlite3_db_config(db->db_handle, SQLITE_DBCONFIG_DEFENSIVE, static_cast<int>(!db->unsafe_mode), NULL);
|
|
721
|
-
}
|
|
722
|
-
#line 415 "./src/objects/database.lzz"
|
|
723
|
-
void Database::JS_open (v8::Local <v8 :: Name> _, v8::PropertyCallbackInfo <v8 :: Value> const & info)
|
|
724
|
-
#line 415 "./src/objects/database.lzz"
|
|
725
|
-
{
|
|
726
|
-
info.GetReturnValue().Set( node :: ObjectWrap :: Unwrap <Database>(info.This())->open);
|
|
727
|
-
}
|
|
728
|
-
#line 419 "./src/objects/database.lzz"
|
|
729
|
-
void Database::JS_inTransaction (v8::Local <v8 :: Name> _, v8::PropertyCallbackInfo <v8 :: Value> const & info)
|
|
730
|
-
#line 419 "./src/objects/database.lzz"
|
|
731
|
-
{
|
|
732
|
-
Database* db = node :: ObjectWrap :: Unwrap <Database>(info.This());
|
|
733
|
-
info.GetReturnValue().Set(db->open && !static_cast<bool>(sqlite3_get_autocommit(db->db_handle)));
|
|
734
|
-
}
|
|
735
|
-
#line 424 "./src/objects/database.lzz"
|
|
736
|
-
bool Database::Deserialize (v8::Local <v8::Object> buffer, Addon * addon, sqlite3 * db_handle, bool readonly)
|
|
737
|
-
#line 424 "./src/objects/database.lzz"
|
|
738
|
-
{
|
|
739
|
-
size_t length = node::Buffer::Length(buffer);
|
|
740
|
-
unsigned char* data = (unsigned char*)sqlite3_malloc64(length);
|
|
741
|
-
unsigned int flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE;
|
|
742
|
-
|
|
743
|
-
if (readonly) {
|
|
744
|
-
flags |= SQLITE_DESERIALIZE_READONLY;
|
|
745
|
-
}
|
|
746
|
-
if (length) {
|
|
747
|
-
if (!data) {
|
|
748
|
-
ThrowError("Out of memory");
|
|
749
|
-
return false;
|
|
750
|
-
}
|
|
751
|
-
memcpy(data, node::Buffer::Data(buffer), length);
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
int status = sqlite3_deserialize(db_handle, "main", data, length, length, flags);
|
|
755
|
-
if (status != SQLITE_OK) {
|
|
756
|
-
ThrowSqliteError(addon, status == SQLITE_ERROR ? "unable to deserialize database" : sqlite3_errstr(status), status);
|
|
757
|
-
return false;
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
return true;
|
|
761
|
-
}
|
|
762
|
-
#line 449 "./src/objects/database.lzz"
|
|
763
|
-
void Database::FreeSerialization (char * data, void * _)
|
|
764
|
-
#line 449 "./src/objects/database.lzz"
|
|
765
|
-
{
|
|
766
|
-
sqlite3_free(data);
|
|
767
|
-
}
|
|
768
|
-
#line 453 "./src/objects/database.lzz"
|
|
769
|
-
int const Database::MAX_BUFFER_SIZE;
|
|
770
|
-
#line 454 "./src/objects/database.lzz"
|
|
771
|
-
int const Database::MAX_STRING_SIZE;
|
|
772
|
-
#line 4 "./src/objects/statement.lzz"
|
|
773
|
-
v8::Local <v8 :: Function> Statement::Init (v8::Isolate * isolate, v8::Local <v8 :: External> data)
|
|
774
|
-
#line 4 "./src/objects/statement.lzz"
|
|
775
|
-
{
|
|
776
|
-
v8::Local<v8::FunctionTemplate> t = NewConstructorTemplate(isolate, data, JS_new, "Statement");
|
|
777
|
-
SetPrototypeMethod(isolate, data, t, "run", JS_run);
|
|
778
|
-
SetPrototypeMethod(isolate, data, t, "get", JS_get);
|
|
779
|
-
SetPrototypeMethod(isolate, data, t, "all", JS_all);
|
|
780
|
-
SetPrototypeMethod(isolate, data, t, "iterate", JS_iterate);
|
|
781
|
-
SetPrototypeMethod(isolate, data, t, "bind", JS_bind);
|
|
782
|
-
SetPrototypeMethod(isolate, data, t, "pluck", JS_pluck);
|
|
783
|
-
SetPrototypeMethod(isolate, data, t, "expand", JS_expand);
|
|
784
|
-
SetPrototypeMethod(isolate, data, t, "raw", JS_raw);
|
|
785
|
-
SetPrototypeMethod(isolate, data, t, "safeIntegers", JS_safeIntegers);
|
|
786
|
-
SetPrototypeMethod(isolate, data, t, "columns", JS_columns);
|
|
787
|
-
SetPrototypeMethod(isolate, data, t, "scanStatusV2", JS_scanStatusV2);
|
|
788
|
-
SetPrototypeGetter(isolate, data, t, "busy", JS_busy);
|
|
789
|
-
return t->GetFunction( isolate -> GetCurrentContext ( ) ).ToLocalChecked();
|
|
790
|
-
}
|
|
791
|
-
#line 26 "./src/objects/statement.lzz"
|
|
792
|
-
BindMap * Statement::GetBindMap (v8::Isolate * isolate)
|
|
793
|
-
#line 26 "./src/objects/statement.lzz"
|
|
794
|
-
{
|
|
795
|
-
if (has_bind_map) return &extras->bind_map;
|
|
796
|
-
BindMap* bind_map = &extras->bind_map;
|
|
797
|
-
int param_count = sqlite3_bind_parameter_count(handle);
|
|
798
|
-
for (int i = 1; i <= param_count; ++i) {
|
|
799
|
-
const char* name = sqlite3_bind_parameter_name(handle, i);
|
|
800
|
-
if (name != NULL) bind_map->Add(isolate, name + 1, i);
|
|
801
|
-
}
|
|
802
|
-
has_bind_map = true;
|
|
803
|
-
return bind_map;
|
|
804
|
-
}
|
|
805
|
-
#line 39 "./src/objects/statement.lzz"
|
|
806
|
-
void Statement::CloseHandles ()
|
|
807
|
-
#line 39 "./src/objects/statement.lzz"
|
|
808
|
-
{
|
|
809
|
-
if (alive) {
|
|
810
|
-
alive = false;
|
|
811
|
-
sqlite3_finalize(handle);
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
#line 46 "./src/objects/statement.lzz"
|
|
815
|
-
Statement::~ Statement ()
|
|
816
|
-
#line 46 "./src/objects/statement.lzz"
|
|
817
|
-
{
|
|
818
|
-
if (alive) db->RemoveStatement(this);
|
|
819
|
-
CloseHandles();
|
|
820
|
-
delete extras;
|
|
821
|
-
}
|
|
822
|
-
#line 56 "./src/objects/statement.lzz"
|
|
823
|
-
Statement::Extras::Extras (sqlite3_uint64 id)
|
|
824
|
-
#line 56 "./src/objects/statement.lzz"
|
|
825
|
-
: bind_map (0), id (id)
|
|
826
|
-
#line 56 "./src/objects/statement.lzz"
|
|
827
|
-
{}
|
|
828
|
-
#line 61 "./src/objects/statement.lzz"
|
|
829
|
-
Statement::Statement (Database * db, sqlite3_stmt * handle, sqlite3_uint64 id, bool returns_data)
|
|
830
|
-
#line 66 "./src/objects/statement.lzz"
|
|
831
|
-
: node::ObjectWrap (), db (db), handle (handle), extras (new Extras(id)), alive (true), locked (false), bound (false), has_bind_map (false), safe_ints (db->GetState()->safe_ints), mode (Data::FLAT), returns_data (returns_data)
|
|
832
|
-
#line 77 "./src/objects/statement.lzz"
|
|
833
|
-
{
|
|
834
|
-
assert(db != NULL);
|
|
835
|
-
assert(handle != NULL);
|
|
836
|
-
assert(db->GetState()->open);
|
|
837
|
-
assert(!db->GetState()->busy);
|
|
838
|
-
db->AddStatement(this);
|
|
839
|
-
}
|
|
840
|
-
#line 85 "./src/objects/statement.lzz"
|
|
841
|
-
void Statement::JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
842
|
-
#line 85 "./src/objects/statement.lzz"
|
|
843
|
-
{
|
|
844
|
-
Addon * addon = static_cast < Addon * > ( info . Data ( ) . As < v8 :: External > ( ) -> Value ( ) ) ;
|
|
845
|
-
if (!addon->privileged_info) {
|
|
846
|
-
return ThrowTypeError("Statements can only be constructed by the db.prepare() method");
|
|
847
|
-
}
|
|
848
|
-
assert(info.IsConstructCall());
|
|
849
|
-
Database* db = node :: ObjectWrap :: Unwrap <Database>(addon->privileged_info->This());
|
|
850
|
-
if ( ! db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ;
|
|
851
|
-
if ( db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
852
|
-
|
|
853
|
-
v8::Local<v8::String> source = (*addon->privileged_info)[0].As<v8::String>();
|
|
854
|
-
v8::Local<v8::Object> database = (*addon->privileged_info)[1].As<v8::Object>();
|
|
855
|
-
bool pragmaMode = (*addon->privileged_info)[2].As<v8::Boolean>()->Value();
|
|
856
|
-
int flags = SQLITE_PREPARE_PERSISTENT;
|
|
857
|
-
|
|
858
|
-
if (pragmaMode) {
|
|
859
|
-
if ( ! db -> GetState ( ) -> unsafe_mode ) { if ( db -> GetState ( ) -> iterators ) return ThrowTypeError ( "This database connection is busy executing a query" ) ; } ( ( void ) 0 ) ;
|
|
860
|
-
flags = 0;
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
864
|
-
v8::String::Utf8Value utf8(isolate, source);
|
|
865
|
-
sqlite3_stmt* handle;
|
|
866
|
-
const char* tail;
|
|
867
|
-
|
|
868
|
-
if (sqlite3_prepare_v3(db->GetHandle(), *utf8, utf8.length() + 1, flags, &handle, &tail) != SQLITE_OK) {
|
|
869
|
-
return db->ThrowDatabaseError();
|
|
870
|
-
}
|
|
871
|
-
if (handle == NULL) {
|
|
872
|
-
return ThrowRangeError("The supplied SQL string contains no statements");
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
for (char c; (c = *tail); ) {
|
|
876
|
-
if (IS_SKIPPED(c)) {
|
|
877
|
-
++tail;
|
|
878
|
-
continue;
|
|
879
|
-
}
|
|
880
|
-
if (c == '/' && tail[1] == '*') {
|
|
881
|
-
tail += 2;
|
|
882
|
-
for (char c; (c = *tail); ++tail) {
|
|
883
|
-
if (c == '*' && tail[1] == '/') {
|
|
884
|
-
tail += 2;
|
|
885
|
-
break;
|
|
886
|
-
}
|
|
887
|
-
}
|
|
888
|
-
} else if (c == '-' && tail[1] == '-') {
|
|
889
|
-
tail += 2;
|
|
890
|
-
for (char c; (c = *tail); ++tail) {
|
|
891
|
-
if (c == '\n') {
|
|
892
|
-
++tail;
|
|
893
|
-
break;
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
} else {
|
|
897
|
-
sqlite3_finalize(handle);
|
|
898
|
-
return ThrowRangeError("The supplied SQL string contains more than one statement");
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
903
|
-
bool returns_data = sqlite3_column_count(handle) >= 1 || pragmaMode;
|
|
904
|
-
Statement* stmt = new Statement(db, handle, addon->NextId(), returns_data);
|
|
905
|
-
stmt->Wrap(info.This());
|
|
906
|
-
SetFrozen(isolate, ctx, info.This(), addon->cs.reader, v8::Boolean::New(isolate, returns_data));
|
|
907
|
-
SetFrozen(isolate, ctx, info.This(), addon->cs.readonly, v8::Boolean::New(isolate, sqlite3_stmt_readonly(handle) != 0));
|
|
908
|
-
SetFrozen(isolate, ctx, info.This(), addon->cs.source, source);
|
|
909
|
-
SetFrozen(isolate, ctx, info.This(), addon->cs.database, database);
|
|
910
|
-
|
|
911
|
-
info.GetReturnValue().Set(info.This());
|
|
912
|
-
}
|
|
913
|
-
#line 156 "./src/objects/statement.lzz"
|
|
914
|
-
void Statement::JS_run (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
915
|
-
#line 156 "./src/objects/statement.lzz"
|
|
916
|
-
{
|
|
917
|
-
Statement * stmt = node :: ObjectWrap :: Unwrap < Statement > ( info . This ( ) ) ; ( ( void ) 0 ) ; sqlite3_stmt * handle = stmt -> handle ; Database * db = stmt -> db ; if ( ! db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ; if ( db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ; if ( stmt -> locked ) return ThrowTypeError ( "This statement is busy executing a query" ) ; if ( ! db -> GetState ( ) -> unsafe_mode ) { if ( db -> GetState ( ) -> iterators ) return ThrowTypeError ( "This database connection is busy executing a query" ) ; } ( ( void ) 0 ) ; const bool bound = stmt -> bound ; if ( ! bound ) { Binder binder ( handle ) ; if ( ! binder . Bind ( info , info . Length ( ) , stmt ) ) { sqlite3_clear_bindings ( handle ) ; return ; } ( ( void ) 0 ) ; } else if ( info . Length ( ) > 0 ) { return ThrowTypeError ( "This statement already has bound parameters" ) ; } ( ( void ) 0 ) ; db -> GetState ( ) -> busy = true ; v8 :: Isolate * isolate = info . GetIsolate ( ) ; if ( db -> Log ( isolate , handle ) ) { db -> GetState ( ) -> busy = false ; db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ; } ( ( void ) 0 ) ;
|
|
918
|
-
sqlite3* db_handle = db->GetHandle();
|
|
919
|
-
int total_changes_before = sqlite3_total_changes(db_handle);
|
|
920
|
-
|
|
921
|
-
sqlite3_step(handle);
|
|
922
|
-
if (sqlite3_reset(handle) == SQLITE_OK) {
|
|
923
|
-
int changes = sqlite3_total_changes(db_handle) == total_changes_before ? 0 : sqlite3_changes(db_handle);
|
|
924
|
-
sqlite3_int64 id = sqlite3_last_insert_rowid(db_handle);
|
|
925
|
-
Addon* addon = db->GetAddon();
|
|
926
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
927
|
-
v8::Local<v8::Object> result = v8::Object::New(isolate);
|
|
928
|
-
result->Set(ctx, addon->cs.changes.Get(isolate), v8::Int32::New(isolate, changes)).FromJust();
|
|
929
|
-
result->Set(ctx, addon->cs.lastInsertRowid.Get(isolate),
|
|
930
|
-
stmt->safe_ints
|
|
931
|
-
? v8::BigInt::New(isolate, id).As<v8::Value>()
|
|
932
|
-
: v8::Number::New(isolate, (double)id).As<v8::Value>()
|
|
933
|
-
).FromJust();
|
|
934
|
-
db -> GetState ( ) -> busy = false ; info . GetReturnValue ( ) . Set ( result ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ;
|
|
935
|
-
}
|
|
936
|
-
db -> GetState ( ) -> busy = false ; db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ;
|
|
937
|
-
}
|
|
938
|
-
#line 179 "./src/objects/statement.lzz"
|
|
939
|
-
void Statement::JS_get (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
940
|
-
#line 179 "./src/objects/statement.lzz"
|
|
941
|
-
{
|
|
942
|
-
Statement * stmt = node :: ObjectWrap :: Unwrap < Statement > ( info . This ( ) ) ; if ( ! stmt -> returns_data ) return ThrowTypeError ( "This statement does not return data. Use run() instead" ) ; sqlite3_stmt * handle = stmt -> handle ; Database * db = stmt -> db ; if ( ! db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ; if ( db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ; if ( stmt -> locked ) return ThrowTypeError ( "This statement is busy executing a query" ) ; const bool bound = stmt -> bound ; if ( ! bound ) { Binder binder ( handle ) ; if ( ! binder . Bind ( info , info . Length ( ) , stmt ) ) { sqlite3_clear_bindings ( handle ) ; return ; } ( ( void ) 0 ) ; } else if ( info . Length ( ) > 0 ) { return ThrowTypeError ( "This statement already has bound parameters" ) ; } ( ( void ) 0 ) ; db -> GetState ( ) -> busy = true ; v8 :: Isolate * isolate = info . GetIsolate ( ) ; if ( db -> Log ( isolate , handle ) ) { db -> GetState ( ) -> busy = false ; db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ; } ( ( void ) 0 ) ;
|
|
943
|
-
int status = sqlite3_step(handle);
|
|
944
|
-
if (status == SQLITE_ROW) {
|
|
945
|
-
v8::Local<v8::Value> result = Data::GetRowJS(isolate, isolate -> GetCurrentContext ( ) , handle, stmt->safe_ints, stmt->mode);
|
|
946
|
-
sqlite3_reset(handle);
|
|
947
|
-
db -> GetState ( ) -> busy = false ; info . GetReturnValue ( ) . Set ( result ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ;
|
|
948
|
-
} else if (status == SQLITE_DONE) {
|
|
949
|
-
sqlite3_reset(handle);
|
|
950
|
-
db -> GetState ( ) -> busy = false ; info . GetReturnValue ( ) . Set ( v8 :: Undefined ( isolate ) ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ;
|
|
951
|
-
}
|
|
952
|
-
sqlite3_reset(handle);
|
|
953
|
-
db -> GetState ( ) -> busy = false ; db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ;
|
|
954
|
-
}
|
|
955
|
-
#line 194 "./src/objects/statement.lzz"
|
|
956
|
-
void Statement::JS_all (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
957
|
-
#line 194 "./src/objects/statement.lzz"
|
|
958
|
-
{
|
|
959
|
-
Statement * stmt = node :: ObjectWrap :: Unwrap < Statement > ( info . This ( ) ) ; if ( ! stmt -> returns_data ) return ThrowTypeError ( "This statement does not return data. Use run() instead" ) ; sqlite3_stmt * handle = stmt -> handle ; Database * db = stmt -> db ; if ( ! db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ; if ( db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ; if ( stmt -> locked ) return ThrowTypeError ( "This statement is busy executing a query" ) ; const bool bound = stmt -> bound ; if ( ! bound ) { Binder binder ( handle ) ; if ( ! binder . Bind ( info , info . Length ( ) , stmt ) ) { sqlite3_clear_bindings ( handle ) ; return ; } ( ( void ) 0 ) ; } else if ( info . Length ( ) > 0 ) { return ThrowTypeError ( "This statement already has bound parameters" ) ; } ( ( void ) 0 ) ; db -> GetState ( ) -> busy = true ; v8 :: Isolate * isolate = info . GetIsolate ( ) ; if ( db -> Log ( isolate , handle ) ) { db -> GetState ( ) -> busy = false ; db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ; } ( ( void ) 0 ) ;
|
|
960
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
961
|
-
v8::Local<v8::Array> result = v8::Array::New(isolate, 0);
|
|
962
|
-
uint32_t row_count = 0;
|
|
963
|
-
const bool safe_ints = stmt->safe_ints;
|
|
964
|
-
const char mode = stmt->mode;
|
|
965
|
-
bool js_error = false;
|
|
966
|
-
|
|
967
|
-
while (sqlite3_step(handle) == SQLITE_ROW) {
|
|
968
|
-
if (row_count == 0xffffffff) { ThrowRangeError("Array overflow (too many rows returned)"); js_error = true; break; }
|
|
969
|
-
result->Set(ctx, row_count++, Data::GetRowJS(isolate, ctx, handle, safe_ints, mode)).FromJust();
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
if (sqlite3_reset(handle) == SQLITE_OK && !js_error) {
|
|
973
|
-
db -> GetState ( ) -> busy = false ; info . GetReturnValue ( ) . Set ( result ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ;
|
|
974
|
-
}
|
|
975
|
-
if (js_error) db->GetState()->was_js_error = true;
|
|
976
|
-
db -> GetState ( ) -> busy = false ; db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ;
|
|
977
|
-
}
|
|
978
|
-
#line 215 "./src/objects/statement.lzz"
|
|
979
|
-
void Statement::JS_iterate (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
980
|
-
#line 215 "./src/objects/statement.lzz"
|
|
981
|
-
{
|
|
982
|
-
Addon * addon = static_cast < Addon * > ( info . Data ( ) . As < v8 :: External > ( ) -> Value ( ) ) ;
|
|
983
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
984
|
-
v8::Local<v8::Function> c = addon->StatementIterator.Get(isolate);
|
|
985
|
-
addon->privileged_info = &info;
|
|
986
|
-
v8::MaybeLocal<v8::Object> maybeIterator = c->NewInstance( isolate -> GetCurrentContext ( ) , 0, NULL);
|
|
987
|
-
addon->privileged_info = NULL;
|
|
988
|
-
if (!maybeIterator.IsEmpty()) info.GetReturnValue().Set(maybeIterator.ToLocalChecked());
|
|
989
|
-
}
|
|
990
|
-
#line 225 "./src/objects/statement.lzz"
|
|
991
|
-
void Statement::JS_bind (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
992
|
-
#line 225 "./src/objects/statement.lzz"
|
|
993
|
-
{
|
|
994
|
-
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
|
|
995
|
-
if (stmt->bound) return ThrowTypeError("The bind() method can only be invoked once per statement object");
|
|
996
|
-
if ( ! stmt -> db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ;
|
|
997
|
-
if ( stmt -> db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
998
|
-
if ( stmt -> locked ) return ThrowTypeError ( "This statement is busy executing a query" ) ;
|
|
999
|
-
Binder binder ( stmt -> handle ) ; if ( ! binder . Bind ( info , info . Length ( ) , stmt ) ) { sqlite3_clear_bindings ( stmt -> handle ) ; return ; } ( ( void ) 0 ) ;
|
|
1000
|
-
stmt->bound = true;
|
|
1001
|
-
info.GetReturnValue().Set(info.This());
|
|
1002
|
-
}
|
|
1003
|
-
#line 236 "./src/objects/statement.lzz"
|
|
1004
|
-
void Statement::JS_pluck (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1005
|
-
#line 236 "./src/objects/statement.lzz"
|
|
1006
|
-
{
|
|
1007
|
-
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
|
|
1008
|
-
if (!stmt->returns_data) return ThrowTypeError("The pluck() method is only for statements that return data");
|
|
1009
|
-
if ( stmt -> db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
1010
|
-
if ( stmt -> locked ) return ThrowTypeError ( "This statement is busy executing a query" ) ;
|
|
1011
|
-
bool use = true;
|
|
1012
|
-
if (info.Length() != 0) { if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a boolean" ) ; use = ( info [ 0 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ; }
|
|
1013
|
-
stmt->mode = use ? Data::PLUCK : stmt->mode == Data::PLUCK ? Data::FLAT : stmt->mode;
|
|
1014
|
-
info.GetReturnValue().Set(info.This());
|
|
1015
|
-
}
|
|
1016
|
-
#line 247 "./src/objects/statement.lzz"
|
|
1017
|
-
void Statement::JS_expand (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1018
|
-
#line 247 "./src/objects/statement.lzz"
|
|
1019
|
-
{
|
|
1020
|
-
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
|
|
1021
|
-
if (!stmt->returns_data) return ThrowTypeError("The expand() method is only for statements that return data");
|
|
1022
|
-
if ( stmt -> db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
1023
|
-
if ( stmt -> locked ) return ThrowTypeError ( "This statement is busy executing a query" ) ;
|
|
1024
|
-
bool use = true;
|
|
1025
|
-
if (info.Length() != 0) { if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a boolean" ) ; use = ( info [ 0 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ; }
|
|
1026
|
-
stmt->mode = use ? Data::EXPAND : stmt->mode == Data::EXPAND ? Data::FLAT : stmt->mode;
|
|
1027
|
-
info.GetReturnValue().Set(info.This());
|
|
1028
|
-
}
|
|
1029
|
-
#line 258 "./src/objects/statement.lzz"
|
|
1030
|
-
void Statement::JS_raw (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1031
|
-
#line 258 "./src/objects/statement.lzz"
|
|
1032
|
-
{
|
|
1033
|
-
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
|
|
1034
|
-
if (!stmt->returns_data) return ThrowTypeError("The raw() method is only for statements that return data");
|
|
1035
|
-
if ( stmt -> db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
1036
|
-
if ( stmt -> locked ) return ThrowTypeError ( "This statement is busy executing a query" ) ;
|
|
1037
|
-
bool use = true;
|
|
1038
|
-
if (info.Length() != 0) { if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a boolean" ) ; use = ( info [ 0 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ; }
|
|
1039
|
-
stmt->mode = use ? Data::RAW : stmt->mode == Data::RAW ? Data::FLAT : stmt->mode;
|
|
1040
|
-
info.GetReturnValue().Set(info.This());
|
|
1041
|
-
}
|
|
1042
|
-
#line 269 "./src/objects/statement.lzz"
|
|
1043
|
-
void Statement::JS_safeIntegers (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1044
|
-
#line 269 "./src/objects/statement.lzz"
|
|
1045
|
-
{
|
|
1046
|
-
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
|
|
1047
|
-
if ( stmt -> db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
1048
|
-
if ( stmt -> locked ) return ThrowTypeError ( "This statement is busy executing a query" ) ;
|
|
1049
|
-
if (info.Length() == 0) stmt->safe_ints = true;
|
|
1050
|
-
else { if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsBoolean ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a boolean" ) ; stmt -> safe_ints = ( info [ 0 ] . As < v8 :: Boolean > ( ) ) -> Value ( ) ; }
|
|
1051
|
-
info.GetReturnValue().Set(info.This());
|
|
1052
|
-
}
|
|
1053
|
-
#line 278 "./src/objects/statement.lzz"
|
|
1054
|
-
void Statement::JS_columns (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1055
|
-
#line 278 "./src/objects/statement.lzz"
|
|
1056
|
-
{
|
|
1057
|
-
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
|
|
1058
|
-
if (!stmt->returns_data) return ThrowTypeError("The columns() method is only for statements that return data");
|
|
1059
|
-
if ( ! stmt -> db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ;
|
|
1060
|
-
if ( stmt -> db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
1061
|
-
Addon* addon = stmt->db->GetAddon();
|
|
1062
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
1063
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
1064
|
-
|
|
1065
|
-
int column_count = sqlite3_column_count(stmt->handle);
|
|
1066
|
-
v8::Local<v8::Array> columns = v8::Array::New(isolate);
|
|
1067
|
-
|
|
1068
|
-
v8::Local<v8::String> name = addon->cs.name.Get(isolate);
|
|
1069
|
-
v8::Local<v8::String> columnName = addon->cs.column.Get(isolate);
|
|
1070
|
-
v8::Local<v8::String> tableName = addon->cs.table.Get(isolate);
|
|
1071
|
-
v8::Local<v8::String> databaseName = addon->cs.database.Get(isolate);
|
|
1072
|
-
v8::Local<v8::String> typeName = addon->cs.type.Get(isolate);
|
|
1073
|
-
|
|
1074
|
-
for (int i = 0; i < column_count; ++i) {
|
|
1075
|
-
v8::Local<v8::Object> column = v8::Object::New(isolate);
|
|
1076
|
-
|
|
1077
|
-
column->Set(ctx, name,
|
|
1078
|
-
InternalizedFromUtf8OrNull(isolate, sqlite3_column_name(stmt->handle, i), -1)
|
|
1079
|
-
).FromJust();
|
|
1080
|
-
column->Set(ctx, columnName,
|
|
1081
|
-
InternalizedFromUtf8OrNull(isolate, sqlite3_column_origin_name(stmt->handle, i), -1)
|
|
1082
|
-
).FromJust();
|
|
1083
|
-
column->Set(ctx, tableName,
|
|
1084
|
-
InternalizedFromUtf8OrNull(isolate, sqlite3_column_table_name(stmt->handle, i), -1)
|
|
1085
|
-
).FromJust();
|
|
1086
|
-
column->Set(ctx, databaseName,
|
|
1087
|
-
InternalizedFromUtf8OrNull(isolate, sqlite3_column_database_name(stmt->handle, i), -1)
|
|
1088
|
-
).FromJust();
|
|
1089
|
-
column->Set(ctx, typeName,
|
|
1090
|
-
InternalizedFromUtf8OrNull(isolate, sqlite3_column_decltype(stmt->handle, i), -1)
|
|
1091
|
-
).FromJust();
|
|
1092
|
-
|
|
1093
|
-
columns->Set(ctx, i, column).FromJust();
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
info.GetReturnValue().Set(columns);
|
|
1097
|
-
}
|
|
1098
|
-
#line 322 "./src/objects/statement.lzz"
|
|
1099
|
-
void Statement::JS_scanStatusV2 (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1100
|
-
#line 322 "./src/objects/statement.lzz"
|
|
1101
|
-
{
|
|
1102
|
-
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
|
|
1103
|
-
if (!stmt->db->GetState()->open) return ThrowTypeError("The database connection is not open");
|
|
1104
|
-
if (!stmt->alive) return ThrowTypeError("The statement has been finalized and can no longer be used");
|
|
1105
|
-
|
|
1106
|
-
int idx; if (info.Length() < (0 + 1) || !info[0]->IsInt32()) return ThrowTypeError("Expected " "first" " argument to be " "a 32-bit signed integer"); idx = (info[0].As<v8::Int32>()->Value());;
|
|
1107
|
-
int iScanStatusOp; if (info.Length() < (1 + 1) || !info[1]->IsInt32()) return ThrowTypeError("Expected " "second" " argument to be " "a 32-bit signed integer"); iScanStatusOp = (info[1].As<v8::Int32>()->Value());;
|
|
1108
|
-
int flags; if (info.Length() < (2 + 1) || !info[2]->IsInt32()) return ThrowTypeError("Expected " "third" " argument to be " "a 32-bit signed integer"); flags = (info[2].As<v8::Int32>()->Value());;
|
|
1109
|
-
|
|
1110
|
-
v8::Isolate* isolate = info.GetIsolate();;
|
|
1111
|
-
|
|
1112
|
-
// Based on iScanStatusOp, we know what type of output to expect
|
|
1113
|
-
int rc;
|
|
1114
|
-
if (iScanStatusOp == 0 || iScanStatusOp == 1 || iScanStatusOp == 5 || iScanStatusOp == 6 || iScanStatusOp == 7) {
|
|
1115
|
-
// NLOOP, NVISIT, SELECTID, PARENTID, NCYCLE - return sqlite3_int64
|
|
1116
|
-
sqlite3_int64 iOut;
|
|
1117
|
-
rc = sqlite3_stmt_scanstatus_v2(stmt->handle, idx, iScanStatusOp, flags, (void*)&iOut);
|
|
1118
|
-
if (rc == 0) {
|
|
1119
|
-
info.GetReturnValue().Set(stmt->safe_ints
|
|
1120
|
-
? v8::BigInt::New(isolate, iOut).As<v8::Value>()
|
|
1121
|
-
: v8::Number::New(isolate, (double)iOut).As<v8::Value>());
|
|
1122
|
-
return;
|
|
1123
|
-
}
|
|
1124
|
-
} else if (iScanStatusOp == 2) {
|
|
1125
|
-
// EST - return double
|
|
1126
|
-
double dOut;
|
|
1127
|
-
rc = sqlite3_stmt_scanstatus_v2(stmt->handle, idx, iScanStatusOp, flags, (void*)&dOut);
|
|
1128
|
-
if (rc == 0) {
|
|
1129
|
-
info.GetReturnValue().Set(v8::Number::New(isolate, dOut));
|
|
1130
|
-
return;
|
|
1131
|
-
}
|
|
1132
|
-
} else if (iScanStatusOp == 3 || iScanStatusOp == 4) {
|
|
1133
|
-
// NAME, EXPLAIN - return const char*
|
|
1134
|
-
const char* zOut;
|
|
1135
|
-
rc = sqlite3_stmt_scanstatus_v2(stmt->handle, idx, iScanStatusOp, flags, (void*)&zOut);
|
|
1136
|
-
if (rc == 0 && zOut != NULL) {
|
|
1137
|
-
info.GetReturnValue().Set(StringFromUtf8(isolate, zOut, -1));
|
|
1138
|
-
return;
|
|
1139
|
-
} else if (rc == 0) {
|
|
1140
|
-
info.GetReturnValue().Set(v8::Null(isolate));
|
|
1141
|
-
return;
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
// Error or invalid operation - return undefined
|
|
1146
|
-
info.GetReturnValue().Set(v8::Undefined(isolate));
|
|
1147
|
-
}
|
|
1148
|
-
#line 370 "./src/objects/statement.lzz"
|
|
1149
|
-
void Statement::JS_busy (v8::Local <v8 :: Name> _, v8::PropertyCallbackInfo <v8 :: Value> const & info)
|
|
1150
|
-
#line 370 "./src/objects/statement.lzz"
|
|
1151
|
-
{
|
|
1152
|
-
Statement* stmt = node :: ObjectWrap :: Unwrap <Statement>(info.This());
|
|
1153
|
-
info.GetReturnValue().Set(stmt->alive && stmt->locked);
|
|
1154
|
-
}
|
|
1155
|
-
#line 4 "./src/objects/statement-iterator.lzz"
|
|
1156
|
-
v8::Local <v8 :: Function> StatementIterator::Init (v8::Isolate * isolate, v8::Local <v8 :: External> data)
|
|
1157
|
-
#line 4 "./src/objects/statement-iterator.lzz"
|
|
1158
|
-
{
|
|
1159
|
-
v8::Local<v8::FunctionTemplate> t = NewConstructorTemplate(isolate, data, JS_new, "StatementIterator");
|
|
1160
|
-
SetPrototypeMethod(isolate, data, t, "next", JS_next);
|
|
1161
|
-
SetPrototypeMethod(isolate, data, t, "return", JS_return);
|
|
1162
|
-
SetPrototypeSymbolMethod(isolate, data, t, v8::Symbol::GetIterator(isolate), JS_symbolIterator);
|
|
1163
|
-
return t->GetFunction( isolate -> GetCurrentContext ( ) ).ToLocalChecked();
|
|
1164
|
-
}
|
|
1165
|
-
#line 15 "./src/objects/statement-iterator.lzz"
|
|
1166
|
-
StatementIterator::~ StatementIterator ()
|
|
1167
|
-
#line 15 "./src/objects/statement-iterator.lzz"
|
|
1168
|
-
{}
|
|
1169
|
-
#line 19 "./src/objects/statement-iterator.lzz"
|
|
1170
|
-
StatementIterator::StatementIterator (Statement * stmt, bool bound)
|
|
1171
|
-
#line 19 "./src/objects/statement-iterator.lzz"
|
|
1172
|
-
: node::ObjectWrap (), stmt (stmt), handle (stmt->handle), db_state (stmt->db->GetState()), bound (bound), safe_ints (stmt->safe_ints), mode (stmt->mode), alive (true), logged (!db_state->has_logger)
|
|
1173
|
-
#line 27 "./src/objects/statement-iterator.lzz"
|
|
1174
|
-
{
|
|
1175
|
-
assert(stmt != NULL);
|
|
1176
|
-
assert(handle != NULL);
|
|
1177
|
-
assert(stmt->bound == bound);
|
|
1178
|
-
assert(stmt->alive == true);
|
|
1179
|
-
assert(stmt->locked == false);
|
|
1180
|
-
assert(db_state->iterators < USHRT_MAX);
|
|
1181
|
-
stmt->locked = true;
|
|
1182
|
-
db_state->iterators += 1;
|
|
1183
|
-
}
|
|
1184
|
-
#line 38 "./src/objects/statement-iterator.lzz"
|
|
1185
|
-
void StatementIterator::JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1186
|
-
#line 38 "./src/objects/statement-iterator.lzz"
|
|
1187
|
-
{
|
|
1188
|
-
Addon * addon = static_cast < Addon * > ( info . Data ( ) . As < v8 :: External > ( ) -> Value ( ) ) ;
|
|
1189
|
-
if (!addon->privileged_info) return ThrowTypeError("Disabled constructor");
|
|
1190
|
-
assert(info.IsConstructCall());
|
|
1191
|
-
|
|
1192
|
-
StatementIterator* iter;
|
|
1193
|
-
{
|
|
1194
|
-
const v8 :: FunctionCallbackInfo < v8 :: Value > & info = *addon->privileged_info;
|
|
1195
|
-
Statement * stmt = node :: ObjectWrap :: Unwrap < Statement > ( info . This ( ) ) ; if ( ! stmt -> returns_data ) return ThrowTypeError ( "This statement does not return data. Use run() instead" ) ; sqlite3_stmt * handle = stmt -> handle ; Database * db = stmt -> db ; if ( ! db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ; if ( db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ; if ( stmt -> locked ) return ThrowTypeError ( "This statement is busy executing a query" ) ; if ( db -> GetState ( ) -> iterators == USHRT_MAX ) return ThrowRangeError ( "Too many active database iterators" ) ; const bool bound = stmt -> bound ; if ( ! bound ) { Binder binder ( handle ) ; if ( ! binder . Bind ( info , info . Length ( ) , stmt ) ) { sqlite3_clear_bindings ( handle ) ; return ; } ( ( void ) 0 ) ; } else if ( info . Length ( ) > 0 ) { return ThrowTypeError ( "This statement already has bound parameters" ) ; } ( ( void ) 0 ) ;
|
|
1196
|
-
iter = new StatementIterator(stmt, bound);
|
|
1197
|
-
}
|
|
1198
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
1199
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
1200
|
-
iter->Wrap(info.This());
|
|
1201
|
-
SetFrozen(isolate, ctx, info.This(), addon->cs.statement, addon->privileged_info->This());
|
|
1202
|
-
|
|
1203
|
-
info.GetReturnValue().Set(info.This());
|
|
1204
|
-
}
|
|
1205
|
-
#line 57 "./src/objects/statement-iterator.lzz"
|
|
1206
|
-
void StatementIterator::JS_next (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1207
|
-
#line 57 "./src/objects/statement-iterator.lzz"
|
|
1208
|
-
{
|
|
1209
|
-
StatementIterator* iter = node :: ObjectWrap :: Unwrap <StatementIterator>(info.This());
|
|
1210
|
-
if ( iter -> db_state -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
1211
|
-
if (iter->alive) iter->Next(info);
|
|
1212
|
-
else info.GetReturnValue().Set(DoneRecord( info . GetIsolate ( ) , iter->db_state->addon));
|
|
1213
|
-
}
|
|
1214
|
-
#line 64 "./src/objects/statement-iterator.lzz"
|
|
1215
|
-
void StatementIterator::JS_return (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1216
|
-
#line 64 "./src/objects/statement-iterator.lzz"
|
|
1217
|
-
{
|
|
1218
|
-
StatementIterator* iter = node :: ObjectWrap :: Unwrap <StatementIterator>(info.This());
|
|
1219
|
-
if ( iter -> db_state -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
1220
|
-
if (iter->alive) iter->Return(info);
|
|
1221
|
-
else info.GetReturnValue().Set(DoneRecord( info . GetIsolate ( ) , iter->db_state->addon));
|
|
1222
|
-
}
|
|
1223
|
-
#line 71 "./src/objects/statement-iterator.lzz"
|
|
1224
|
-
void StatementIterator::JS_symbolIterator (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1225
|
-
#line 71 "./src/objects/statement-iterator.lzz"
|
|
1226
|
-
{
|
|
1227
|
-
info.GetReturnValue().Set(info.This());
|
|
1228
|
-
}
|
|
1229
|
-
#line 75 "./src/objects/statement-iterator.lzz"
|
|
1230
|
-
void StatementIterator::Next (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1231
|
-
#line 75 "./src/objects/statement-iterator.lzz"
|
|
1232
|
-
{
|
|
1233
|
-
assert(alive == true);
|
|
1234
|
-
db_state->busy = true;
|
|
1235
|
-
if (!logged) {
|
|
1236
|
-
logged = true;
|
|
1237
|
-
if (stmt->db->Log( info . GetIsolate ( ) , handle)) {
|
|
1238
|
-
db_state->busy = false;
|
|
1239
|
-
Throw();
|
|
1240
|
-
return;
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1243
|
-
int status = sqlite3_step(handle);
|
|
1244
|
-
db_state->busy = false;
|
|
1245
|
-
if (status == SQLITE_ROW) {
|
|
1246
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
1247
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
1248
|
-
info.GetReturnValue().Set(
|
|
1249
|
-
NewRecord(isolate, ctx, Data::GetRowJS(isolate, ctx, handle, safe_ints, mode), db_state->addon, false)
|
|
1250
|
-
);
|
|
1251
|
-
} else {
|
|
1252
|
-
if (status == SQLITE_DONE) Return(info);
|
|
1253
|
-
else Throw();
|
|
1254
|
-
}
|
|
1255
|
-
}
|
|
1256
|
-
#line 100 "./src/objects/statement-iterator.lzz"
|
|
1257
|
-
void StatementIterator::Return (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1258
|
-
#line 100 "./src/objects/statement-iterator.lzz"
|
|
1259
|
-
{
|
|
1260
|
-
Cleanup();
|
|
1261
|
-
info . GetReturnValue ( ) . Set ( DoneRecord ( info . GetIsolate ( ) , db_state -> addon ) ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ;
|
|
1262
|
-
}
|
|
1263
|
-
#line 105 "./src/objects/statement-iterator.lzz"
|
|
1264
|
-
void StatementIterator::Throw ()
|
|
1265
|
-
#line 105 "./src/objects/statement-iterator.lzz"
|
|
1266
|
-
{
|
|
1267
|
-
Cleanup();
|
|
1268
|
-
Database* db = stmt->db;
|
|
1269
|
-
db -> ThrowDatabaseError ( ) ; if ( ! bound ) { sqlite3_clear_bindings ( handle ) ; } return ;
|
|
1270
|
-
}
|
|
1271
|
-
#line 111 "./src/objects/statement-iterator.lzz"
|
|
1272
|
-
void StatementIterator::Cleanup ()
|
|
1273
|
-
#line 111 "./src/objects/statement-iterator.lzz"
|
|
1274
|
-
{
|
|
1275
|
-
assert(alive == true);
|
|
1276
|
-
alive = false;
|
|
1277
|
-
stmt->locked = false;
|
|
1278
|
-
db_state->iterators -= 1;
|
|
1279
|
-
sqlite3_reset(handle);
|
|
1280
|
-
}
|
|
1281
|
-
#line 4 "./src/objects/backup.lzz"
|
|
1282
|
-
v8::Local <v8 :: Function> Backup::Init (v8::Isolate * isolate, v8::Local <v8 :: External> data)
|
|
1283
|
-
#line 4 "./src/objects/backup.lzz"
|
|
1284
|
-
{
|
|
1285
|
-
v8::Local<v8::FunctionTemplate> t = NewConstructorTemplate(isolate, data, JS_new, "Backup");
|
|
1286
|
-
SetPrototypeMethod(isolate, data, t, "transfer", JS_transfer);
|
|
1287
|
-
SetPrototypeMethod(isolate, data, t, "close", JS_close);
|
|
1288
|
-
return t->GetFunction( isolate -> GetCurrentContext ( ) ).ToLocalChecked();
|
|
1289
|
-
}
|
|
1290
|
-
#line 17 "./src/objects/backup.lzz"
|
|
1291
|
-
void Backup::CloseHandles ()
|
|
1292
|
-
#line 17 "./src/objects/backup.lzz"
|
|
1293
|
-
{
|
|
1294
|
-
if (alive) {
|
|
1295
|
-
alive = false;
|
|
1296
|
-
std::string filename(sqlite3_db_filename(dest_handle, "main"));
|
|
1297
|
-
sqlite3_backup_finish(backup_handle);
|
|
1298
|
-
int status = sqlite3_close(dest_handle);
|
|
1299
|
-
assert(status == SQLITE_OK); ((void)status);
|
|
1300
|
-
if (unlink) remove(filename.c_str());
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
#line 28 "./src/objects/backup.lzz"
|
|
1304
|
-
Backup::~ Backup ()
|
|
1305
|
-
#line 28 "./src/objects/backup.lzz"
|
|
1306
|
-
{
|
|
1307
|
-
if (alive) db->RemoveBackup(this);
|
|
1308
|
-
CloseHandles();
|
|
1309
|
-
}
|
|
1310
|
-
#line 35 "./src/objects/backup.lzz"
|
|
1311
|
-
Backup::Backup (Database * db, sqlite3 * dest_handle, sqlite3_backup * backup_handle, sqlite3_uint64 id, bool unlink)
|
|
1312
|
-
#line 41 "./src/objects/backup.lzz"
|
|
1313
|
-
: node::ObjectWrap (), db (db), dest_handle (dest_handle), backup_handle (backup_handle), id (id), alive (true), unlink (unlink)
|
|
1314
|
-
#line 48 "./src/objects/backup.lzz"
|
|
1315
|
-
{
|
|
1316
|
-
assert(db != NULL);
|
|
1317
|
-
assert(dest_handle != NULL);
|
|
1318
|
-
assert(backup_handle != NULL);
|
|
1319
|
-
db->AddBackup(this);
|
|
1320
|
-
}
|
|
1321
|
-
#line 55 "./src/objects/backup.lzz"
|
|
1322
|
-
void Backup::JS_new (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1323
|
-
#line 55 "./src/objects/backup.lzz"
|
|
1324
|
-
{
|
|
1325
|
-
Addon * addon = static_cast < Addon * > ( info . Data ( ) . As < v8 :: External > ( ) -> Value ( ) ) ;
|
|
1326
|
-
if (!addon->privileged_info) return ThrowTypeError("Disabled constructor");
|
|
1327
|
-
assert(info.IsConstructCall());
|
|
1328
|
-
Database* db = node :: ObjectWrap :: Unwrap <Database>(addon->privileged_info->This());
|
|
1329
|
-
if ( ! db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ;
|
|
1330
|
-
if ( db -> GetState ( ) -> busy ) return ThrowTypeError ( "This database connection is busy executing a query" ) ;
|
|
1331
|
-
|
|
1332
|
-
v8::Local<v8::Object> database = (*addon->privileged_info)[0].As<v8::Object>();
|
|
1333
|
-
v8::Local<v8::String> attachedName = (*addon->privileged_info)[1].As<v8::String>();
|
|
1334
|
-
v8::Local<v8::String> destFile = (*addon->privileged_info)[2].As<v8::String>();
|
|
1335
|
-
bool unlink = (*addon->privileged_info)[3].As<v8::Boolean>()->Value();
|
|
1336
|
-
|
|
1337
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
1338
|
-
sqlite3* dest_handle;
|
|
1339
|
-
v8::String::Utf8Value dest_file(isolate, destFile);
|
|
1340
|
-
v8::String::Utf8Value attached_name(isolate, attachedName);
|
|
1341
|
-
int mask = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
|
1342
|
-
|
|
1343
|
-
if (sqlite3_open_v2(*dest_file, &dest_handle, mask, NULL) != SQLITE_OK) {
|
|
1344
|
-
Database::ThrowSqliteError(addon, dest_handle);
|
|
1345
|
-
int status = sqlite3_close(dest_handle);
|
|
1346
|
-
assert(status == SQLITE_OK); ((void)status);
|
|
1347
|
-
return;
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
sqlite3_extended_result_codes(dest_handle, 1);
|
|
1351
|
-
sqlite3_limit(dest_handle, SQLITE_LIMIT_LENGTH, INT_MAX);
|
|
1352
|
-
sqlite3_backup* backup_handle = sqlite3_backup_init(dest_handle, "main", db->GetHandle(), *attached_name);
|
|
1353
|
-
if (backup_handle == NULL) {
|
|
1354
|
-
Database::ThrowSqliteError(addon, dest_handle);
|
|
1355
|
-
int status = sqlite3_close(dest_handle);
|
|
1356
|
-
assert(status == SQLITE_OK); ((void)status);
|
|
1357
|
-
return;
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
Backup* backup = new Backup(db, dest_handle, backup_handle, addon->NextId(), unlink);
|
|
1361
|
-
backup->Wrap(info.This());
|
|
1362
|
-
SetFrozen(isolate, isolate -> GetCurrentContext ( ) , info.This(), addon->cs.database, database);
|
|
1363
|
-
|
|
1364
|
-
info.GetReturnValue().Set(info.This());
|
|
1365
|
-
}
|
|
1366
|
-
#line 98 "./src/objects/backup.lzz"
|
|
1367
|
-
void Backup::JS_transfer (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1368
|
-
#line 98 "./src/objects/backup.lzz"
|
|
1369
|
-
{
|
|
1370
|
-
Backup* backup = node :: ObjectWrap :: Unwrap <Backup>(info.This());
|
|
1371
|
-
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsInt32 ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a 32-bit signed integer" ) ; int pages = ( info [ 0 ] . As < v8 :: Int32 > ( ) ) -> Value ( ) ;
|
|
1372
|
-
if ( ! backup -> db -> GetState ( ) -> open ) return ThrowTypeError ( "The database connection is not open" ) ;
|
|
1373
|
-
assert(backup->db->GetState()->busy == false);
|
|
1374
|
-
assert(backup->alive == true);
|
|
1375
|
-
|
|
1376
|
-
sqlite3_backup* backup_handle = backup->backup_handle;
|
|
1377
|
-
int status = sqlite3_backup_step(backup_handle, pages) & 0xff;
|
|
1378
|
-
|
|
1379
|
-
Addon* addon = backup->db->GetAddon();
|
|
1380
|
-
if (status == SQLITE_OK || status == SQLITE_DONE || status == SQLITE_BUSY) {
|
|
1381
|
-
int total_pages = sqlite3_backup_pagecount(backup_handle);
|
|
1382
|
-
int remaining_pages = sqlite3_backup_remaining(backup_handle);
|
|
1383
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
1384
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
1385
|
-
v8::Local<v8::Object> result = v8::Object::New(isolate);
|
|
1386
|
-
result->Set(ctx, addon->cs.totalPages.Get(isolate), v8::Int32::New(isolate, total_pages)).FromJust();
|
|
1387
|
-
result->Set(ctx, addon->cs.remainingPages.Get(isolate), v8::Int32::New(isolate, remaining_pages)).FromJust();
|
|
1388
|
-
info.GetReturnValue().Set(result);
|
|
1389
|
-
if (status == SQLITE_DONE) backup->unlink = false;
|
|
1390
|
-
} else {
|
|
1391
|
-
Database::ThrowSqliteError(addon, sqlite3_errstr(status), status);
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
#line 124 "./src/objects/backup.lzz"
|
|
1395
|
-
void Backup::JS_close (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
1396
|
-
#line 124 "./src/objects/backup.lzz"
|
|
1397
|
-
{
|
|
1398
|
-
Backup* backup = node :: ObjectWrap :: Unwrap <Backup>(info.This());
|
|
1399
|
-
assert(backup->db->GetState()->busy == false);
|
|
1400
|
-
if (backup->alive) backup->db->RemoveBackup(backup);
|
|
1401
|
-
backup->CloseHandles();
|
|
1402
|
-
info.GetReturnValue().Set(info.This());
|
|
1403
|
-
}
|
|
1404
|
-
#line 4 "./src/util/data-converter.lzz"
|
|
1405
|
-
void DataConverter::ThrowDataConversionError (sqlite3_context * invocation, bool isBigInt)
|
|
1406
|
-
#line 4 "./src/util/data-converter.lzz"
|
|
1407
|
-
{
|
|
1408
|
-
if (isBigInt) {
|
|
1409
|
-
ThrowRangeError((GetDataErrorPrefix() + " a bigint that was too big").c_str());
|
|
1410
|
-
} else {
|
|
1411
|
-
ThrowTypeError((GetDataErrorPrefix() + " an invalid value").c_str());
|
|
1412
|
-
}
|
|
1413
|
-
PropagateJSError(invocation);
|
|
1414
|
-
}
|
|
1415
|
-
#line 4 "./src/util/custom-function.lzz"
|
|
1416
|
-
CustomFunction::CustomFunction (v8::Isolate * isolate, Database * db, char const * name, v8::Local <v8::Function> fn, bool safe_ints)
|
|
1417
|
-
#line 10 "./src/util/custom-function.lzz"
|
|
1418
|
-
: name (name), db (db), isolate (isolate), fn (isolate, fn), safe_ints (safe_ints)
|
|
1419
|
-
#line 15 "./src/util/custom-function.lzz"
|
|
1420
|
-
{}
|
|
1421
|
-
#line 17 "./src/util/custom-function.lzz"
|
|
1422
|
-
CustomFunction::~ CustomFunction ()
|
|
1423
|
-
#line 17 "./src/util/custom-function.lzz"
|
|
1424
|
-
{}
|
|
1425
|
-
#line 19 "./src/util/custom-function.lzz"
|
|
1426
|
-
void CustomFunction::xDestroy (void * self)
|
|
1427
|
-
#line 19 "./src/util/custom-function.lzz"
|
|
1428
|
-
{
|
|
1429
|
-
delete static_cast<CustomFunction*>(self);
|
|
1430
|
-
}
|
|
1431
|
-
#line 23 "./src/util/custom-function.lzz"
|
|
1432
|
-
void CustomFunction::xFunc (sqlite3_context * invocation, int argc, sqlite3_value * * argv)
|
|
1433
|
-
#line 23 "./src/util/custom-function.lzz"
|
|
1434
|
-
{
|
|
1435
|
-
CustomFunction * self = static_cast < CustomFunction * > ( sqlite3_user_data ( invocation ) ) ; v8 :: Isolate * isolate = self -> isolate ; v8 :: HandleScope scope ( isolate ) ;
|
|
1436
|
-
|
|
1437
|
-
v8::Local<v8::Value> args_fast[4];
|
|
1438
|
-
v8::Local<v8::Value>* args = NULL;
|
|
1439
|
-
if (argc != 0) {
|
|
1440
|
-
args = argc <= 4 ? args_fast : ALLOC_ARRAY<v8::Local<v8::Value>>(argc);
|
|
1441
|
-
Data::GetArgumentsJS(isolate, args, argv, argc, self->safe_ints);
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
|
-
v8::MaybeLocal<v8::Value> maybeReturnValue = self->fn.Get(isolate)->Call( isolate -> GetCurrentContext ( ) , v8::Undefined(isolate), argc, args);
|
|
1445
|
-
if (args != args_fast) delete[] args;
|
|
1446
|
-
|
|
1447
|
-
if (maybeReturnValue.IsEmpty()) self->PropagateJSError(invocation);
|
|
1448
|
-
else Data::ResultValueFromJS(isolate, invocation, maybeReturnValue.ToLocalChecked(), self);
|
|
1449
|
-
}
|
|
1450
|
-
#line 42 "./src/util/custom-function.lzz"
|
|
1451
|
-
void CustomFunction::PropagateJSError (sqlite3_context * invocation)
|
|
1452
|
-
#line 42 "./src/util/custom-function.lzz"
|
|
1453
|
-
{
|
|
1454
|
-
assert(db->GetState()->was_js_error == false);
|
|
1455
|
-
db->GetState()->was_js_error = true;
|
|
1456
|
-
sqlite3_result_error(invocation, "", 0);
|
|
1457
|
-
}
|
|
1458
|
-
#line 48 "./src/util/custom-function.lzz"
|
|
1459
|
-
std::string CustomFunction::GetDataErrorPrefix ()
|
|
1460
|
-
#line 48 "./src/util/custom-function.lzz"
|
|
1461
|
-
{
|
|
1462
|
-
return std::string("User-defined function ") + name + "() returned";
|
|
1463
|
-
}
|
|
1464
|
-
#line 4 "./src/util/custom-aggregate.lzz"
|
|
1465
|
-
CustomAggregate::CustomAggregate (v8::Isolate * isolate, Database * db, char const * name, v8::Local <v8::Value> start, v8::Local <v8::Function> step, v8::Local <v8::Value> inverse, v8::Local <v8::Value> result, bool safe_ints)
|
|
1466
|
-
#line 13 "./src/util/custom-aggregate.lzz"
|
|
1467
|
-
: CustomFunction (isolate, db, name, step, safe_ints), invoke_result (result->IsFunction()), invoke_start (start->IsFunction()), inverse (isolate, inverse->IsFunction() ? inverse.As<v8::Function>() : v8::Local<v8::Function>()), result (isolate, result->IsFunction() ? result.As<v8::Function>() : v8::Local<v8::Function>()), start (isolate, start)
|
|
1468
|
-
#line 19 "./src/util/custom-aggregate.lzz"
|
|
1469
|
-
{}
|
|
1470
|
-
#line 21 "./src/util/custom-aggregate.lzz"
|
|
1471
|
-
void CustomAggregate::xStep (sqlite3_context * invocation, int argc, sqlite3_value * * argv)
|
|
1472
|
-
#line 21 "./src/util/custom-aggregate.lzz"
|
|
1473
|
-
{
|
|
1474
|
-
xStepBase(invocation, argc, argv, &CustomAggregate::fn);
|
|
1475
|
-
}
|
|
1476
|
-
#line 25 "./src/util/custom-aggregate.lzz"
|
|
1477
|
-
void CustomAggregate::xInverse (sqlite3_context * invocation, int argc, sqlite3_value * * argv)
|
|
1478
|
-
#line 25 "./src/util/custom-aggregate.lzz"
|
|
1479
|
-
{
|
|
1480
|
-
xStepBase(invocation, argc, argv, &CustomAggregate::inverse);
|
|
1481
|
-
}
|
|
1482
|
-
#line 29 "./src/util/custom-aggregate.lzz"
|
|
1483
|
-
void CustomAggregate::xValue (sqlite3_context * invocation)
|
|
1484
|
-
#line 29 "./src/util/custom-aggregate.lzz"
|
|
1485
|
-
{
|
|
1486
|
-
xValueBase(invocation, false);
|
|
1487
|
-
}
|
|
1488
|
-
#line 33 "./src/util/custom-aggregate.lzz"
|
|
1489
|
-
void CustomAggregate::xFinal (sqlite3_context * invocation)
|
|
1490
|
-
#line 33 "./src/util/custom-aggregate.lzz"
|
|
1491
|
-
{
|
|
1492
|
-
xValueBase(invocation, true);
|
|
1493
|
-
}
|
|
1494
|
-
#line 88 "./src/util/custom-aggregate.lzz"
|
|
1495
|
-
CustomAggregate::Accumulator * CustomAggregate::GetAccumulator (sqlite3_context * invocation)
|
|
1496
|
-
#line 88 "./src/util/custom-aggregate.lzz"
|
|
1497
|
-
{
|
|
1498
|
-
Accumulator* acc = static_cast<Accumulator*>(sqlite3_aggregate_context(invocation, sizeof(Accumulator)));
|
|
1499
|
-
if (!acc->initialized) {
|
|
1500
|
-
assert(acc->value.IsEmpty());
|
|
1501
|
-
acc->initialized = true;
|
|
1502
|
-
if (invoke_start) {
|
|
1503
|
-
v8::MaybeLocal<v8::Value> maybeSeed = start.Get(isolate).As<v8::Function>()->Call( isolate -> GetCurrentContext ( ) , v8::Undefined(isolate), 0, NULL);
|
|
1504
|
-
if (maybeSeed.IsEmpty()) PropagateJSError(invocation);
|
|
1505
|
-
else acc->value.Reset(isolate, maybeSeed.ToLocalChecked());
|
|
1506
|
-
} else {
|
|
1507
|
-
assert(!start.IsEmpty());
|
|
1508
|
-
acc->value.Reset(isolate, start);
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
return acc;
|
|
1512
|
-
}
|
|
1513
|
-
#line 105 "./src/util/custom-aggregate.lzz"
|
|
1514
|
-
void CustomAggregate::DestroyAccumulator (sqlite3_context * invocation)
|
|
1515
|
-
#line 105 "./src/util/custom-aggregate.lzz"
|
|
1516
|
-
{
|
|
1517
|
-
Accumulator* acc = static_cast<Accumulator*>(sqlite3_aggregate_context(invocation, sizeof(Accumulator)));
|
|
1518
|
-
assert(acc->initialized);
|
|
1519
|
-
acc->value.Reset();
|
|
1520
|
-
}
|
|
1521
|
-
#line 111 "./src/util/custom-aggregate.lzz"
|
|
1522
|
-
void CustomAggregate::PropagateJSError (sqlite3_context * invocation)
|
|
1523
|
-
#line 111 "./src/util/custom-aggregate.lzz"
|
|
1524
|
-
{
|
|
1525
|
-
DestroyAccumulator(invocation);
|
|
1526
|
-
CustomFunction::PropagateJSError(invocation);
|
|
1527
|
-
}
|
|
1528
|
-
#line 4 "./src/util/custom-table.lzz"
|
|
1529
|
-
CustomTable::CustomTable (v8::Isolate * isolate, Database * db, char const * name, v8::Local <v8::Function> factory)
|
|
1530
|
-
#line 9 "./src/util/custom-table.lzz"
|
|
1531
|
-
: addon (db->GetAddon()), isolate (isolate), db (db), name (name), factory (isolate, factory)
|
|
1532
|
-
#line 14 "./src/util/custom-table.lzz"
|
|
1533
|
-
{}
|
|
1534
|
-
#line 16 "./src/util/custom-table.lzz"
|
|
1535
|
-
void CustomTable::Destructor (void * self)
|
|
1536
|
-
#line 16 "./src/util/custom-table.lzz"
|
|
1537
|
-
{
|
|
1538
|
-
delete static_cast<CustomTable*>(self);
|
|
1539
|
-
}
|
|
1540
|
-
#line 20 "./src/util/custom-table.lzz"
|
|
1541
|
-
sqlite3_module CustomTable::MODULE = {
|
|
1542
|
-
0,
|
|
1543
|
-
xCreate,
|
|
1544
|
-
xConnect,
|
|
1545
|
-
xBestIndex,
|
|
1546
|
-
xDisconnect,
|
|
1547
|
-
xDisconnect,
|
|
1548
|
-
xOpen,
|
|
1549
|
-
xClose,
|
|
1550
|
-
xFilter,
|
|
1551
|
-
xNext,
|
|
1552
|
-
xEof,
|
|
1553
|
-
xColumn,
|
|
1554
|
-
xRowid,
|
|
1555
|
-
NULL,
|
|
1556
|
-
NULL,
|
|
1557
|
-
NULL,
|
|
1558
|
-
NULL,
|
|
1559
|
-
NULL,
|
|
1560
|
-
NULL,
|
|
1561
|
-
NULL,
|
|
1562
|
-
NULL,
|
|
1563
|
-
NULL,
|
|
1564
|
-
NULL,
|
|
1565
|
-
NULL
|
|
1566
|
-
};
|
|
1567
|
-
#line 47 "./src/util/custom-table.lzz"
|
|
1568
|
-
sqlite3_module CustomTable::EPONYMOUS_MODULE = {
|
|
1569
|
-
0,
|
|
1570
|
-
NULL,
|
|
1571
|
-
xConnect,
|
|
1572
|
-
xBestIndex,
|
|
1573
|
-
xDisconnect,
|
|
1574
|
-
xDisconnect,
|
|
1575
|
-
xOpen,
|
|
1576
|
-
xClose,
|
|
1577
|
-
xFilter,
|
|
1578
|
-
xNext,
|
|
1579
|
-
xEof,
|
|
1580
|
-
xColumn,
|
|
1581
|
-
xRowid,
|
|
1582
|
-
NULL,
|
|
1583
|
-
NULL,
|
|
1584
|
-
NULL,
|
|
1585
|
-
NULL,
|
|
1586
|
-
NULL,
|
|
1587
|
-
NULL,
|
|
1588
|
-
NULL,
|
|
1589
|
-
NULL,
|
|
1590
|
-
NULL,
|
|
1591
|
-
NULL,
|
|
1592
|
-
NULL
|
|
1593
|
-
};
|
|
1594
|
-
#line 78 "./src/util/custom-table.lzz"
|
|
1595
|
-
CustomTable::VTab::VTab (CustomTable * parent, v8::Local <v8::Function> generator, std::vector <std::string> parameter_names, bool safe_ints)
|
|
1596
|
-
#line 83 "./src/util/custom-table.lzz"
|
|
1597
|
-
: parent (parent), parameter_count (parameter_names.size()), safe_ints (safe_ints), generator (parent->isolate, generator), parameter_names (parameter_names)
|
|
1598
|
-
#line 88 "./src/util/custom-table.lzz"
|
|
1599
|
-
{
|
|
1600
|
-
((void)base);
|
|
1601
|
-
}
|
|
1602
|
-
#line 132 "./src/util/custom-table.lzz"
|
|
1603
|
-
CustomTable::TempDataConverter::TempDataConverter (CustomTable * parent)
|
|
1604
|
-
#line 132 "./src/util/custom-table.lzz"
|
|
1605
|
-
: parent (parent), status (SQLITE_OK)
|
|
1606
|
-
#line 134 "./src/util/custom-table.lzz"
|
|
1607
|
-
{}
|
|
1608
|
-
#line 136 "./src/util/custom-table.lzz"
|
|
1609
|
-
void CustomTable::TempDataConverter::PropagateJSError (sqlite3_context * invocation)
|
|
1610
|
-
#line 136 "./src/util/custom-table.lzz"
|
|
1611
|
-
{
|
|
1612
|
-
status = SQLITE_ERROR;
|
|
1613
|
-
parent->PropagateJSError();
|
|
1614
|
-
}
|
|
1615
|
-
#line 141 "./src/util/custom-table.lzz"
|
|
1616
|
-
std::string CustomTable::TempDataConverter::GetDataErrorPrefix ()
|
|
1617
|
-
#line 141 "./src/util/custom-table.lzz"
|
|
1618
|
-
{
|
|
1619
|
-
return std::string("Virtual table module \"") + parent->name + "\" yielded";
|
|
1620
|
-
}
|
|
1621
|
-
#line 151 "./src/util/custom-table.lzz"
|
|
1622
|
-
int CustomTable::xCreate (sqlite3 * db_handle, void * _self, int argc, char const * const * argv, sqlite3_vtab * * output, char * * errOutput)
|
|
1623
|
-
#line 151 "./src/util/custom-table.lzz"
|
|
1624
|
-
{
|
|
1625
|
-
return xConnect(db_handle, _self, argc, argv, output, errOutput);
|
|
1626
|
-
}
|
|
1627
|
-
#line 156 "./src/util/custom-table.lzz"
|
|
1628
|
-
int CustomTable::xConnect (sqlite3 * db_handle, void * _self, int argc, char const * const * argv, sqlite3_vtab * * output, char * * errOutput)
|
|
1629
|
-
#line 156 "./src/util/custom-table.lzz"
|
|
1630
|
-
{
|
|
1631
|
-
CustomTable* self = static_cast<CustomTable*>(_self);
|
|
1632
|
-
v8::Isolate* isolate = self->isolate;
|
|
1633
|
-
v8::HandleScope scope(isolate);
|
|
1634
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
1635
|
-
|
|
1636
|
-
v8::Local<v8::Value>* args = ALLOC_ARRAY<v8::Local<v8::Value>>(argc);
|
|
1637
|
-
for (int i = 0; i < argc; ++i) {
|
|
1638
|
-
args[i] = StringFromUtf8(isolate, argv[i], -1);
|
|
1639
|
-
}
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
v8::MaybeLocal<v8::Value> maybeReturnValue = self->factory.Get(isolate)->Call(ctx, v8::Undefined(isolate), argc, args);
|
|
1643
|
-
delete[] args;
|
|
1644
|
-
|
|
1645
|
-
if (maybeReturnValue.IsEmpty()) {
|
|
1646
|
-
self->PropagateJSError();
|
|
1647
|
-
return SQLITE_ERROR;
|
|
1648
|
-
}
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
v8::Local<v8::Array> returnValue = maybeReturnValue.ToLocalChecked().As<v8::Array>();
|
|
1652
|
-
v8::Local<v8::String> sqlString = returnValue->Get(ctx, 0).ToLocalChecked().As<v8::String>();
|
|
1653
|
-
v8::Local<v8::Function> generator = returnValue->Get(ctx, 1).ToLocalChecked().As<v8::Function>();
|
|
1654
|
-
v8::Local<v8::Array> parameterNames = returnValue->Get(ctx, 2).ToLocalChecked().As<v8::Array>();
|
|
1655
|
-
int safe_ints = returnValue->Get(ctx, 3).ToLocalChecked().As<v8::Int32>()->Value();
|
|
1656
|
-
bool direct_only = returnValue->Get(ctx, 4).ToLocalChecked().As<v8::Boolean>()->Value();
|
|
1657
|
-
|
|
1658
|
-
v8::String::Utf8Value sql(isolate, sqlString);
|
|
1659
|
-
safe_ints = safe_ints < 2 ? safe_ints : static_cast<int>(self->db->GetState()->safe_ints);
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
std::vector<std::string> parameter_names;
|
|
1663
|
-
for (int i = 0, len = parameterNames->Length(); i < len; ++i) {
|
|
1664
|
-
v8::Local<v8::String> parameterName = parameterNames->Get(ctx, i).ToLocalChecked().As<v8::String>();
|
|
1665
|
-
v8::String::Utf8Value parameter_name(isolate, parameterName);
|
|
1666
|
-
parameter_names.emplace_back(*parameter_name);
|
|
1667
|
-
}
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
if (sqlite3_declare_vtab(db_handle, *sql) != SQLITE_OK) {
|
|
1671
|
-
*errOutput = sqlite3_mprintf("failed to declare virtual table \"%s\"", argv[2]);
|
|
1672
|
-
return SQLITE_ERROR;
|
|
1673
|
-
}
|
|
1674
|
-
if (direct_only && sqlite3_vtab_config(db_handle, SQLITE_VTAB_DIRECTONLY) != SQLITE_OK) {
|
|
1675
|
-
*errOutput = sqlite3_mprintf("failed to configure virtual table \"%s\"", argv[2]);
|
|
1676
|
-
return SQLITE_ERROR;
|
|
1677
|
-
}
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
*output = (new VTab(self, generator, parameter_names, safe_ints))->Downcast();
|
|
1681
|
-
return SQLITE_OK;
|
|
1682
|
-
}
|
|
1683
|
-
#line 210 "./src/util/custom-table.lzz"
|
|
1684
|
-
int CustomTable::xDisconnect (sqlite3_vtab * vtab)
|
|
1685
|
-
#line 210 "./src/util/custom-table.lzz"
|
|
1686
|
-
{
|
|
1687
|
-
delete VTab::Upcast(vtab);
|
|
1688
|
-
return SQLITE_OK;
|
|
1689
|
-
}
|
|
1690
|
-
#line 215 "./src/util/custom-table.lzz"
|
|
1691
|
-
int CustomTable::xOpen (sqlite3_vtab * vtab, sqlite3_vtab_cursor * * output)
|
|
1692
|
-
#line 215 "./src/util/custom-table.lzz"
|
|
1693
|
-
{
|
|
1694
|
-
*output = (new Cursor())->Downcast();
|
|
1695
|
-
return SQLITE_OK;
|
|
1696
|
-
}
|
|
1697
|
-
#line 220 "./src/util/custom-table.lzz"
|
|
1698
|
-
int CustomTable::xClose (sqlite3_vtab_cursor * cursor)
|
|
1699
|
-
#line 220 "./src/util/custom-table.lzz"
|
|
1700
|
-
{
|
|
1701
|
-
delete Cursor::Upcast(cursor);
|
|
1702
|
-
return SQLITE_OK;
|
|
1703
|
-
}
|
|
1704
|
-
#line 228 "./src/util/custom-table.lzz"
|
|
1705
|
-
int CustomTable::xFilter (sqlite3_vtab_cursor * _cursor, int idxNum, char const * idxStr, int argc, sqlite3_value * * argv)
|
|
1706
|
-
#line 228 "./src/util/custom-table.lzz"
|
|
1707
|
-
{
|
|
1708
|
-
Cursor* cursor = Cursor::Upcast(_cursor);
|
|
1709
|
-
VTab* vtab = cursor->GetVTab();
|
|
1710
|
-
CustomTable* self = vtab->parent;
|
|
1711
|
-
Addon* addon = self->addon;
|
|
1712
|
-
v8::Isolate* isolate = self->isolate;
|
|
1713
|
-
v8::HandleScope scope(isolate);
|
|
1714
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
v8::Local<v8::Value> args_fast[4];
|
|
1719
|
-
v8::Local<v8::Value>* args = NULL;
|
|
1720
|
-
int parameter_count = vtab->parameter_count;
|
|
1721
|
-
if (parameter_count != 0) {
|
|
1722
|
-
args = parameter_count <= 4 ? args_fast : ALLOC_ARRAY<v8::Local<v8::Value>>(parameter_count);
|
|
1723
|
-
int argn = 0;
|
|
1724
|
-
bool safe_ints = vtab->safe_ints;
|
|
1725
|
-
for (int i = 0; i < parameter_count; ++i) {
|
|
1726
|
-
if (idxNum & 1 << i) {
|
|
1727
|
-
args[i] = Data::GetValueJS(isolate, argv[argn++], safe_ints);
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
if (args[i]->IsNull()) {
|
|
1731
|
-
if (args != args_fast) delete[] args;
|
|
1732
|
-
cursor->done = true;
|
|
1733
|
-
return SQLITE_OK;
|
|
1734
|
-
}
|
|
1735
|
-
} else {
|
|
1736
|
-
args[i] = v8::Undefined(isolate);
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
}
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
v8::MaybeLocal<v8::Value> maybeIterator = vtab->generator.Get(isolate)->Call(ctx, v8::Undefined(isolate), parameter_count, args);
|
|
1743
|
-
if (args != args_fast) delete[] args;
|
|
1744
|
-
|
|
1745
|
-
if (maybeIterator.IsEmpty()) {
|
|
1746
|
-
self->PropagateJSError();
|
|
1747
|
-
return SQLITE_ERROR;
|
|
1748
|
-
}
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
v8::Local<v8::Object> iterator = maybeIterator.ToLocalChecked().As<v8::Object>();
|
|
1752
|
-
v8::Local<v8::Function> next = iterator->Get(ctx, addon->cs.next.Get(isolate)).ToLocalChecked().As<v8::Function>();
|
|
1753
|
-
cursor->iterator.Reset(isolate, iterator);
|
|
1754
|
-
cursor->next.Reset(isolate, next);
|
|
1755
|
-
cursor->rowid = 0;
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
return xNext(cursor->Downcast());
|
|
1759
|
-
}
|
|
1760
|
-
#line 284 "./src/util/custom-table.lzz"
|
|
1761
|
-
int CustomTable::xNext (sqlite3_vtab_cursor * _cursor)
|
|
1762
|
-
#line 284 "./src/util/custom-table.lzz"
|
|
1763
|
-
{
|
|
1764
|
-
Cursor* cursor = Cursor::Upcast(_cursor);
|
|
1765
|
-
CustomTable* self = cursor->GetVTab()->parent;
|
|
1766
|
-
Addon* addon = self->addon;
|
|
1767
|
-
v8::Isolate* isolate = self->isolate;
|
|
1768
|
-
v8::HandleScope scope(isolate);
|
|
1769
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
1770
|
-
|
|
1771
|
-
v8::Local<v8::Object> iterator = cursor->iterator.Get(isolate);
|
|
1772
|
-
v8::Local<v8::Function> next = cursor->next.Get(isolate);
|
|
1773
|
-
|
|
1774
|
-
v8::MaybeLocal<v8::Value> maybeRecord = next->Call(ctx, iterator, 0, NULL);
|
|
1775
|
-
if (maybeRecord.IsEmpty()) {
|
|
1776
|
-
self->PropagateJSError();
|
|
1777
|
-
return SQLITE_ERROR;
|
|
1778
|
-
}
|
|
1779
|
-
|
|
1780
|
-
v8::Local<v8::Object> record = maybeRecord.ToLocalChecked().As<v8::Object>();
|
|
1781
|
-
bool done = record->Get(ctx, addon->cs.done.Get(isolate)).ToLocalChecked().As<v8::Boolean>()->Value();
|
|
1782
|
-
if (!done) {
|
|
1783
|
-
cursor->row.Reset(isolate, record->Get(ctx, addon->cs.value.Get(isolate)).ToLocalChecked().As<v8::Array>());
|
|
1784
|
-
}
|
|
1785
|
-
cursor->done = done;
|
|
1786
|
-
cursor->rowid += 1;
|
|
1787
|
-
|
|
1788
|
-
return SQLITE_OK;
|
|
1789
|
-
}
|
|
1790
|
-
#line 313 "./src/util/custom-table.lzz"
|
|
1791
|
-
int CustomTable::xEof (sqlite3_vtab_cursor * cursor)
|
|
1792
|
-
#line 313 "./src/util/custom-table.lzz"
|
|
1793
|
-
{
|
|
1794
|
-
return Cursor::Upcast(cursor)->done;
|
|
1795
|
-
}
|
|
1796
|
-
#line 318 "./src/util/custom-table.lzz"
|
|
1797
|
-
int CustomTable::xColumn (sqlite3_vtab_cursor * _cursor, sqlite3_context * invocation, int column)
|
|
1798
|
-
#line 318 "./src/util/custom-table.lzz"
|
|
1799
|
-
{
|
|
1800
|
-
Cursor* cursor = Cursor::Upcast(_cursor);
|
|
1801
|
-
CustomTable* self = cursor->GetVTab()->parent;
|
|
1802
|
-
TempDataConverter temp_data_converter(self);
|
|
1803
|
-
v8::Isolate* isolate = self->isolate;
|
|
1804
|
-
v8::HandleScope scope(isolate);
|
|
1805
|
-
|
|
1806
|
-
v8::Local<v8::Array> row = cursor->row.Get(isolate);
|
|
1807
|
-
v8::MaybeLocal<v8::Value> maybeColumnValue = row->Get( isolate -> GetCurrentContext ( ) , column);
|
|
1808
|
-
if (maybeColumnValue.IsEmpty()) {
|
|
1809
|
-
temp_data_converter.PropagateJSError(NULL);
|
|
1810
|
-
} else {
|
|
1811
|
-
Data::ResultValueFromJS(isolate, invocation, maybeColumnValue.ToLocalChecked(), &temp_data_converter);
|
|
1812
|
-
}
|
|
1813
|
-
return temp_data_converter.status;
|
|
1814
|
-
}
|
|
1815
|
-
#line 336 "./src/util/custom-table.lzz"
|
|
1816
|
-
int CustomTable::xRowid (sqlite3_vtab_cursor * cursor, sqlite_int64 * output)
|
|
1817
|
-
#line 336 "./src/util/custom-table.lzz"
|
|
1818
|
-
{
|
|
1819
|
-
*output = Cursor::Upcast(cursor)->rowid;
|
|
1820
|
-
return SQLITE_OK;
|
|
1821
|
-
}
|
|
1822
|
-
#line 343 "./src/util/custom-table.lzz"
|
|
1823
|
-
int CustomTable::xBestIndex (sqlite3_vtab * vtab, sqlite3_index_info * output)
|
|
1824
|
-
#line 343 "./src/util/custom-table.lzz"
|
|
1825
|
-
{
|
|
1826
|
-
int parameter_count = VTab::Upcast(vtab)->parameter_count;
|
|
1827
|
-
int argument_count = 0;
|
|
1828
|
-
std::vector<std::pair<int, int>> forwarded;
|
|
1829
|
-
|
|
1830
|
-
for (int i = 0, len = output->nConstraint; i < len; ++i) {
|
|
1831
|
-
auto item = output->aConstraint[i];
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
if (item.op == SQLITE_INDEX_CONSTRAINT_LIMIT || item.op == SQLITE_INDEX_CONSTRAINT_OFFSET) {
|
|
1838
|
-
continue;
|
|
1839
|
-
}
|
|
1840
|
-
|
|
1841
|
-
if (item.iColumn >= 0 && item.iColumn < parameter_count) {
|
|
1842
|
-
if (item.op != SQLITE_INDEX_CONSTRAINT_EQ) {
|
|
1843
|
-
sqlite3_free(vtab->zErrMsg);
|
|
1844
|
-
vtab->zErrMsg = sqlite3_mprintf(
|
|
1845
|
-
"virtual table parameter \"%s\" can only be constrained by the '=' operator",
|
|
1846
|
-
VTab::Upcast(vtab)->parameter_names.at(item.iColumn).c_str());
|
|
1847
|
-
return SQLITE_ERROR;
|
|
1848
|
-
}
|
|
1849
|
-
if (!item.usable) {
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
return SQLITE_CONSTRAINT;
|
|
1854
|
-
}
|
|
1855
|
-
forwarded.emplace_back(item.iColumn, i);
|
|
1856
|
-
}
|
|
1857
|
-
}
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
std::sort(forwarded.begin(), forwarded.end());
|
|
1861
|
-
for (std::pair<int, int> pair : forwarded) {
|
|
1862
|
-
int bit = 1 << pair.first;
|
|
1863
|
-
if (!(output->idxNum & bit)) {
|
|
1864
|
-
output->idxNum |= bit;
|
|
1865
|
-
output->aConstraintUsage[pair.second].argvIndex = ++argument_count;
|
|
1866
|
-
output->aConstraintUsage[pair.second].omit = 1;
|
|
1867
|
-
}
|
|
1868
|
-
}
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
output->estimatedCost = output->estimatedRows = 1000000000 / (argument_count + 1);
|
|
1873
|
-
return SQLITE_OK;
|
|
1874
|
-
}
|
|
1875
|
-
#line 394 "./src/util/custom-table.lzz"
|
|
1876
|
-
void CustomTable::PropagateJSError ()
|
|
1877
|
-
#line 394 "./src/util/custom-table.lzz"
|
|
1878
|
-
{
|
|
1879
|
-
assert(db->GetState()->was_js_error == false);
|
|
1880
|
-
db->GetState()->was_js_error = true;
|
|
1881
|
-
}
|
|
1882
|
-
#line 65 "./src/util/data.lzz"
|
|
1883
|
-
namespace Data
|
|
1884
|
-
{
|
|
1885
|
-
#line 72 "./src/util/data.lzz"
|
|
1886
|
-
v8::Local <v8::Value> GetValueJS (v8::Isolate * isolate, sqlite3_stmt * handle, int column, bool safe_ints)
|
|
1887
|
-
#line 72 "./src/util/data.lzz"
|
|
1888
|
-
{
|
|
1889
|
-
switch ( sqlite3_column_type ( handle , column ) ) { case SQLITE_INTEGER : if ( safe_ints ) { return v8 :: BigInt :: New ( isolate , sqlite3_column_int64 ( handle , column ) ) ; } case SQLITE_FLOAT : return v8 :: Number :: New ( isolate , sqlite3_column_double ( handle , column ) ) ; case SQLITE_TEXT : return StringFromUtf8 ( isolate , reinterpret_cast < const char * > ( sqlite3_column_text ( handle , column ) ) , sqlite3_column_bytes ( handle , column ) ) ; case SQLITE_BLOB : return node :: Buffer :: Copy ( isolate , static_cast < const char * > ( sqlite3_column_blob ( handle , column ) ) , sqlite3_column_bytes ( handle , column ) ) . ToLocalChecked ( ) ; default : assert ( sqlite3_column_type ( handle , column ) == SQLITE_NULL ) ; return v8 :: Null ( isolate ) ; } assert ( false ) ; ;
|
|
1890
|
-
}
|
|
1891
|
-
}
|
|
1892
|
-
#line 65 "./src/util/data.lzz"
|
|
1893
|
-
namespace Data
|
|
1894
|
-
{
|
|
1895
|
-
#line 76 "./src/util/data.lzz"
|
|
1896
|
-
v8::Local <v8::Value> GetValueJS (v8::Isolate * isolate, sqlite3_value * value, bool safe_ints)
|
|
1897
|
-
#line 76 "./src/util/data.lzz"
|
|
1898
|
-
{
|
|
1899
|
-
switch ( sqlite3_value_type ( value ) ) { case SQLITE_INTEGER : if ( safe_ints ) { return v8 :: BigInt :: New ( isolate , sqlite3_value_int64 ( value ) ) ; } case SQLITE_FLOAT : return v8 :: Number :: New ( isolate , sqlite3_value_double ( value ) ) ; case SQLITE_TEXT : return StringFromUtf8 ( isolate , reinterpret_cast < const char * > ( sqlite3_value_text ( value ) ) , sqlite3_value_bytes ( value ) ) ; case SQLITE_BLOB : return node :: Buffer :: Copy ( isolate , static_cast < const char * > ( sqlite3_value_blob ( value ) ) , sqlite3_value_bytes ( value ) ) . ToLocalChecked ( ) ; default : assert ( sqlite3_value_type ( value ) == SQLITE_NULL ) ; return v8 :: Null ( isolate ) ; } assert ( false ) ; ;
|
|
1900
|
-
}
|
|
1901
|
-
}
|
|
1902
|
-
#line 65 "./src/util/data.lzz"
|
|
1903
|
-
namespace Data
|
|
1904
|
-
{
|
|
1905
|
-
#line 80 "./src/util/data.lzz"
|
|
1906
|
-
v8::Local <v8::Value> GetFlatRowJS (v8::Isolate * isolate, v8::Local <v8::Context> ctx, sqlite3_stmt * handle, bool safe_ints)
|
|
1907
|
-
#line 80 "./src/util/data.lzz"
|
|
1908
|
-
{
|
|
1909
|
-
v8::Local<v8::Object> row = v8::Object::New(isolate);
|
|
1910
|
-
int column_count = sqlite3_column_count(handle);
|
|
1911
|
-
for (int i = 0; i < column_count; ++i) {
|
|
1912
|
-
row->Set(ctx,
|
|
1913
|
-
InternalizedFromUtf8(isolate, sqlite3_column_name(handle, i), -1),
|
|
1914
|
-
Data::GetValueJS(isolate, handle, i, safe_ints)).FromJust();
|
|
1915
|
-
}
|
|
1916
|
-
return row;
|
|
1917
|
-
}
|
|
1918
|
-
}
|
|
1919
|
-
#line 65 "./src/util/data.lzz"
|
|
1920
|
-
namespace Data
|
|
1921
|
-
{
|
|
1922
|
-
#line 91 "./src/util/data.lzz"
|
|
1923
|
-
v8::Local <v8::Value> GetExpandedRowJS (v8::Isolate * isolate, v8::Local <v8::Context> ctx, sqlite3_stmt * handle, bool safe_ints)
|
|
1924
|
-
#line 91 "./src/util/data.lzz"
|
|
1925
|
-
{
|
|
1926
|
-
v8::Local<v8::Object> row = v8::Object::New(isolate);
|
|
1927
|
-
int column_count = sqlite3_column_count(handle);
|
|
1928
|
-
for (int i = 0; i < column_count; ++i) {
|
|
1929
|
-
const char* table_raw = sqlite3_column_table_name(handle, i);
|
|
1930
|
-
v8::Local<v8::String> table = InternalizedFromUtf8(isolate, table_raw == NULL ? "$" : table_raw, -1);
|
|
1931
|
-
v8::Local<v8::String> column = InternalizedFromUtf8(isolate, sqlite3_column_name(handle, i), -1);
|
|
1932
|
-
v8::Local<v8::Value> value = Data::GetValueJS(isolate, handle, i, safe_ints);
|
|
1933
|
-
if (row->HasOwnProperty(ctx, table).FromJust()) {
|
|
1934
|
-
row->Get(ctx, table).ToLocalChecked().As<v8::Object>()->Set(ctx, column, value).FromJust();
|
|
1935
|
-
} else {
|
|
1936
|
-
v8::Local<v8::Object> nested = v8::Object::New(isolate);
|
|
1937
|
-
row->Set(ctx, table, nested).FromJust();
|
|
1938
|
-
nested->Set(ctx, column, value).FromJust();
|
|
1939
|
-
}
|
|
1940
|
-
}
|
|
1941
|
-
return row;
|
|
1942
|
-
}
|
|
1943
|
-
}
|
|
1944
|
-
#line 65 "./src/util/data.lzz"
|
|
1945
|
-
namespace Data
|
|
1946
|
-
{
|
|
1947
|
-
#line 110 "./src/util/data.lzz"
|
|
1948
|
-
v8::Local <v8::Value> GetRawRowJS (v8::Isolate * isolate, v8::Local <v8::Context> ctx, sqlite3_stmt * handle, bool safe_ints)
|
|
1949
|
-
#line 110 "./src/util/data.lzz"
|
|
1950
|
-
{
|
|
1951
|
-
v8::Local<v8::Array> row = v8::Array::New(isolate);
|
|
1952
|
-
int column_count = sqlite3_column_count(handle);
|
|
1953
|
-
for (int i = 0; i < column_count; ++i) {
|
|
1954
|
-
row->Set(ctx, i, Data::GetValueJS(isolate, handle, i, safe_ints)).FromJust();
|
|
1955
|
-
}
|
|
1956
|
-
return row;
|
|
1957
|
-
}
|
|
1958
|
-
}
|
|
1959
|
-
#line 65 "./src/util/data.lzz"
|
|
1960
|
-
namespace Data
|
|
1961
|
-
{
|
|
1962
|
-
#line 119 "./src/util/data.lzz"
|
|
1963
|
-
v8::Local <v8::Value> GetRowJS (v8::Isolate * isolate, v8::Local <v8::Context> ctx, sqlite3_stmt * handle, bool safe_ints, char mode)
|
|
1964
|
-
#line 119 "./src/util/data.lzz"
|
|
1965
|
-
{
|
|
1966
|
-
if (mode == FLAT) return GetFlatRowJS(isolate, ctx, handle, safe_ints);
|
|
1967
|
-
if (mode == PLUCK) return GetValueJS(isolate, handle, 0, safe_ints);
|
|
1968
|
-
if (mode == EXPAND) return GetExpandedRowJS(isolate, ctx, handle, safe_ints);
|
|
1969
|
-
if (mode == RAW) return GetRawRowJS(isolate, ctx, handle, safe_ints);
|
|
1970
|
-
assert(false);
|
|
1971
|
-
return v8::Local<v8::Value>();
|
|
1972
|
-
}
|
|
1973
|
-
}
|
|
1974
|
-
#line 65 "./src/util/data.lzz"
|
|
1975
|
-
namespace Data
|
|
1976
|
-
{
|
|
1977
|
-
#line 128 "./src/util/data.lzz"
|
|
1978
|
-
void GetArgumentsJS (v8::Isolate * isolate, v8::Local <v8::Value> * out, sqlite3_value * * values, int argument_count, bool safe_ints)
|
|
1979
|
-
#line 128 "./src/util/data.lzz"
|
|
1980
|
-
{
|
|
1981
|
-
assert(argument_count > 0);
|
|
1982
|
-
for (int i = 0; i < argument_count; ++i) {
|
|
1983
|
-
out[i] = Data::GetValueJS(isolate, values[i], safe_ints);
|
|
1984
|
-
}
|
|
1985
|
-
}
|
|
1986
|
-
}
|
|
1987
|
-
#line 65 "./src/util/data.lzz"
|
|
1988
|
-
namespace Data
|
|
1989
|
-
{
|
|
1990
|
-
#line 135 "./src/util/data.lzz"
|
|
1991
|
-
int BindValueFromJS (v8::Isolate * isolate, sqlite3_stmt * handle, int index, v8::Local <v8::Value> value)
|
|
1992
|
-
#line 135 "./src/util/data.lzz"
|
|
1993
|
-
{
|
|
1994
|
-
if ( value -> IsNumber ( ) ) { return sqlite3_bind_double ( handle , index , value . As < v8 :: Number > ( ) -> Value ( ) ) ; } else if ( value -> IsBigInt ( ) ) { bool lossless ; int64_t v = value . As < v8 :: BigInt > ( ) -> Int64Value ( & lossless ) ; if ( lossless ) { return sqlite3_bind_int64 ( handle , index , v ) ; } } else if ( value -> IsString ( ) ) { v8 :: String :: Utf8Value utf8 ( isolate , value . As < v8 :: String > ( ) ) ; return sqlite3_bind_text ( handle , index , * utf8 , utf8 . length ( ) , SQLITE_TRANSIENT ) ; } else if ( node :: Buffer :: HasInstance ( value ) ) { const char * data = node :: Buffer :: Data ( value ) ; return sqlite3_bind_blob ( handle , index , data ? data : "" , node :: Buffer :: Length ( value ) , SQLITE_TRANSIENT ) ; } else if ( value -> IsNull ( ) || value -> IsUndefined ( ) ) { return sqlite3_bind_null ( handle , index ) ; } ;
|
|
1995
|
-
return value->IsBigInt() ? SQLITE_TOOBIG : -1;
|
|
1996
|
-
}
|
|
1997
|
-
}
|
|
1998
|
-
#line 65 "./src/util/data.lzz"
|
|
1999
|
-
namespace Data
|
|
2000
|
-
{
|
|
2001
|
-
#line 140 "./src/util/data.lzz"
|
|
2002
|
-
void ResultValueFromJS (v8::Isolate * isolate, sqlite3_context * invocation, v8::Local <v8::Value> value, DataConverter * converter)
|
|
2003
|
-
#line 140 "./src/util/data.lzz"
|
|
2004
|
-
{
|
|
2005
|
-
if ( value -> IsNumber ( ) ) { return sqlite3_result_double ( invocation , value . As < v8 :: Number > ( ) -> Value ( ) ) ; } else if ( value -> IsBigInt ( ) ) { bool lossless ; int64_t v = value . As < v8 :: BigInt > ( ) -> Int64Value ( & lossless ) ; if ( lossless ) { return sqlite3_result_int64 ( invocation , v ) ; } } else if ( value -> IsString ( ) ) { v8 :: String :: Utf8Value utf8 ( isolate , value . As < v8 :: String > ( ) ) ; return sqlite3_result_text ( invocation , * utf8 , utf8 . length ( ) , SQLITE_TRANSIENT ) ; } else if ( node :: Buffer :: HasInstance ( value ) ) { const char * data = node :: Buffer :: Data ( value ) ; return sqlite3_result_blob ( invocation , data ? data : "" , node :: Buffer :: Length ( value ) , SQLITE_TRANSIENT ) ; } else if ( value -> IsNull ( ) || value -> IsUndefined ( ) ) { return sqlite3_result_null ( invocation ) ; } ;
|
|
2006
|
-
converter->ThrowDataConversionError(invocation, value->IsBigInt());
|
|
2007
|
-
}
|
|
2008
|
-
}
|
|
2009
|
-
#line 4 "./src/util/binder.lzz"
|
|
2010
|
-
Binder::Binder (sqlite3_stmt * _handle)
|
|
2011
|
-
#line 4 "./src/util/binder.lzz"
|
|
2012
|
-
{
|
|
2013
|
-
handle = _handle;
|
|
2014
|
-
param_count = sqlite3_bind_parameter_count(_handle);
|
|
2015
|
-
anon_index = 0;
|
|
2016
|
-
success = true;
|
|
2017
|
-
}
|
|
2018
|
-
#line 11 "./src/util/binder.lzz"
|
|
2019
|
-
bool Binder::Bind (v8::FunctionCallbackInfo <v8 :: Value> const & info, int argc, Statement * stmt)
|
|
2020
|
-
#line 11 "./src/util/binder.lzz"
|
|
2021
|
-
{
|
|
2022
|
-
assert(anon_index == 0);
|
|
2023
|
-
Result result = BindArgs(info, argc, stmt);
|
|
2024
|
-
if (success && result.count != param_count) {
|
|
2025
|
-
if (result.count < param_count) {
|
|
2026
|
-
if (!result.bound_object && stmt->GetBindMap( info . GetIsolate ( ) )->GetSize()) {
|
|
2027
|
-
Fail(ThrowTypeError, "Missing named parameters");
|
|
2028
|
-
} else {
|
|
2029
|
-
Fail(ThrowRangeError, "Too few parameter values were provided");
|
|
2030
|
-
}
|
|
2031
|
-
} else {
|
|
2032
|
-
Fail(ThrowRangeError, "Too many parameter values were provided");
|
|
2033
|
-
}
|
|
2034
|
-
}
|
|
2035
|
-
return success;
|
|
2036
|
-
}
|
|
2037
|
-
#line 55 "./src/util/binder.lzz"
|
|
2038
|
-
void Binder::Fail (void (* Throw) (char const *), char const * message)
|
|
2039
|
-
#line 55 "./src/util/binder.lzz"
|
|
2040
|
-
{
|
|
2041
|
-
assert(success == true);
|
|
2042
|
-
assert((Throw == NULL) == (message == NULL));
|
|
2043
|
-
assert(Throw == ThrowError || Throw == ThrowTypeError || Throw == ThrowRangeError || Throw == NULL);
|
|
2044
|
-
if (Throw) Throw(message);
|
|
2045
|
-
success = false;
|
|
2046
|
-
}
|
|
2047
|
-
#line 63 "./src/util/binder.lzz"
|
|
2048
|
-
int Binder::NextAnonIndex ()
|
|
2049
|
-
#line 63 "./src/util/binder.lzz"
|
|
2050
|
-
{
|
|
2051
|
-
while (sqlite3_bind_parameter_name(handle, ++anon_index) != NULL) {}
|
|
2052
|
-
return anon_index;
|
|
2053
|
-
}
|
|
2054
|
-
#line 69 "./src/util/binder.lzz"
|
|
2055
|
-
void Binder::BindValue (v8::Isolate * isolate, v8::Local <v8::Value> value, int index)
|
|
2056
|
-
#line 69 "./src/util/binder.lzz"
|
|
2057
|
-
{
|
|
2058
|
-
int status = Data::BindValueFromJS(isolate, handle, index, value);
|
|
2059
|
-
if (status != SQLITE_OK) {
|
|
2060
|
-
switch (status) {
|
|
2061
|
-
case -1:
|
|
2062
|
-
return Fail(ThrowTypeError, "SQLite3 can only bind numbers, strings, bigints, buffers, and null");
|
|
2063
|
-
case SQLITE_TOOBIG:
|
|
2064
|
-
return Fail(ThrowRangeError, "The bound string, buffer, or bigint is too big");
|
|
2065
|
-
case SQLITE_RANGE:
|
|
2066
|
-
return Fail(ThrowRangeError, "Too many parameter values were provided");
|
|
2067
|
-
case SQLITE_NOMEM:
|
|
2068
|
-
return Fail(ThrowError, "Out of memory");
|
|
2069
|
-
default:
|
|
2070
|
-
return Fail(ThrowError, "An unexpected error occured while trying to bind parameters");
|
|
2071
|
-
}
|
|
2072
|
-
assert(false);
|
|
2073
|
-
}
|
|
2074
|
-
}
|
|
2075
|
-
#line 90 "./src/util/binder.lzz"
|
|
2076
|
-
int Binder::BindArray (v8::Isolate * isolate, v8::Local <v8::Array> arr)
|
|
2077
|
-
#line 90 "./src/util/binder.lzz"
|
|
2078
|
-
{
|
|
2079
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
2080
|
-
uint32_t length = arr->Length();
|
|
2081
|
-
if (length > INT_MAX) {
|
|
2082
|
-
Fail(ThrowRangeError, "Too many parameter values were provided");
|
|
2083
|
-
return 0;
|
|
2084
|
-
}
|
|
2085
|
-
int len = static_cast<int>(length);
|
|
2086
|
-
for (int i = 0; i < len; ++i) {
|
|
2087
|
-
v8::MaybeLocal<v8::Value> maybeValue = arr->Get(ctx, i);
|
|
2088
|
-
if (maybeValue.IsEmpty()) {
|
|
2089
|
-
Fail(NULL, NULL);
|
|
2090
|
-
return i;
|
|
2091
|
-
}
|
|
2092
|
-
BindValue(isolate, maybeValue.ToLocalChecked(), NextAnonIndex());
|
|
2093
|
-
if (!success) {
|
|
2094
|
-
return i;
|
|
2095
|
-
}
|
|
2096
|
-
}
|
|
2097
|
-
return len;
|
|
2098
|
-
}
|
|
2099
|
-
#line 116 "./src/util/binder.lzz"
|
|
2100
|
-
int Binder::BindObject (v8::Isolate * isolate, v8::Local <v8::Object> obj, Statement * stmt)
|
|
2101
|
-
#line 116 "./src/util/binder.lzz"
|
|
2102
|
-
{
|
|
2103
|
-
v8 :: Local < v8 :: Context > ctx = isolate -> GetCurrentContext ( ) ;
|
|
2104
|
-
BindMap* bind_map = stmt->GetBindMap(isolate);
|
|
2105
|
-
BindMap::Pair* pairs = bind_map->GetPairs();
|
|
2106
|
-
int len = bind_map->GetSize();
|
|
2107
|
-
|
|
2108
|
-
for (int i = 0; i < len; ++i) {
|
|
2109
|
-
v8::Local<v8::String> key = pairs[i].GetName(isolate);
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
v8::Maybe<bool> has_property = obj->HasOwnProperty(ctx, key);
|
|
2113
|
-
if (has_property.IsNothing()) {
|
|
2114
|
-
Fail(NULL, NULL);
|
|
2115
|
-
return i;
|
|
2116
|
-
}
|
|
2117
|
-
if (!has_property.FromJust()) {
|
|
2118
|
-
v8::String::Utf8Value param_name(isolate, key);
|
|
2119
|
-
Fail(ThrowRangeError, (std::string("Missing named parameter \"") + *param_name + "\"").c_str());
|
|
2120
|
-
return i;
|
|
2121
|
-
}
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
v8::MaybeLocal<v8::Value> maybeValue = obj->Get(ctx, key);
|
|
2125
|
-
if (maybeValue.IsEmpty()) {
|
|
2126
|
-
Fail(NULL, NULL);
|
|
2127
|
-
return i;
|
|
2128
|
-
}
|
|
2129
|
-
|
|
2130
|
-
BindValue(isolate, maybeValue.ToLocalChecked(), pairs[i].GetIndex());
|
|
2131
|
-
if (!success) {
|
|
2132
|
-
return i;
|
|
2133
|
-
}
|
|
2134
|
-
}
|
|
2135
|
-
|
|
2136
|
-
return len;
|
|
2137
|
-
}
|
|
2138
|
-
#line 160 "./src/util/binder.lzz"
|
|
2139
|
-
Binder::Result Binder::BindArgs (v8::FunctionCallbackInfo <v8 :: Value> const & info, int argc, Statement * stmt)
|
|
2140
|
-
#line 160 "./src/util/binder.lzz"
|
|
2141
|
-
{
|
|
2142
|
-
v8 :: Isolate * isolate = info . GetIsolate ( ) ;
|
|
2143
|
-
int count = 0;
|
|
2144
|
-
bool bound_object = false;
|
|
2145
|
-
|
|
2146
|
-
for (int i = 0; i < argc; ++i) {
|
|
2147
|
-
v8::Local<v8::Value> arg = info[i];
|
|
2148
|
-
|
|
2149
|
-
if (arg->IsArray()) {
|
|
2150
|
-
count += BindArray(isolate, arg.As<v8::Array>());
|
|
2151
|
-
if (!success) break;
|
|
2152
|
-
continue;
|
|
2153
|
-
}
|
|
2154
|
-
|
|
2155
|
-
if (arg->IsObject() && !node::Buffer::HasInstance(arg)) {
|
|
2156
|
-
v8::Local<v8::Object> obj = arg.As<v8::Object>();
|
|
2157
|
-
if (IsPlainObject(isolate, obj)) {
|
|
2158
|
-
if (bound_object) {
|
|
2159
|
-
Fail(ThrowTypeError, "You cannot specify named parameters in two different objects");
|
|
2160
|
-
break;
|
|
2161
|
-
}
|
|
2162
|
-
bound_object = true;
|
|
2163
|
-
|
|
2164
|
-
count += BindObject(isolate, obj, stmt);
|
|
2165
|
-
if (!success) break;
|
|
2166
|
-
continue;
|
|
2167
|
-
} else if (stmt->GetBindMap(isolate)->GetSize()) {
|
|
2168
|
-
Fail(ThrowTypeError, "Named parameters can only be passed within plain objects");
|
|
2169
|
-
break;
|
|
2170
|
-
}
|
|
2171
|
-
}
|
|
2172
|
-
|
|
2173
|
-
BindValue(isolate, arg, NextAnonIndex());
|
|
2174
|
-
if (!success) break;
|
|
2175
|
-
count += 1;
|
|
2176
|
-
}
|
|
2177
|
-
|
|
2178
|
-
return { count, bound_object };
|
|
2179
|
-
}
|
|
2180
|
-
#line 35 "./src/better_sqlite3.lzz"
|
|
2181
|
-
void Addon::JS_setErrorConstructor (v8::FunctionCallbackInfo <v8 :: Value> const & info)
|
|
2182
|
-
#line 35 "./src/better_sqlite3.lzz"
|
|
2183
|
-
{
|
|
2184
|
-
if ( info . Length ( ) <= ( 0 ) || ! info [ 0 ] -> IsFunction ( ) ) return ThrowTypeError ( "Expected " "first" " argument to be " "a function" ) ; v8 :: Local < v8 :: Function > SqliteError = ( info [ 0 ] . As < v8 :: Function > ( ) ) ;
|
|
2185
|
-
static_cast < Addon * > ( info . Data ( ) . As < v8 :: External > ( ) -> Value ( ) ) ->SqliteError.Reset( info . GetIsolate ( ) , SqliteError);
|
|
2186
|
-
}
|
|
2187
|
-
#line 40 "./src/better_sqlite3.lzz"
|
|
2188
|
-
void Addon::Cleanup (void * ptr)
|
|
2189
|
-
#line 40 "./src/better_sqlite3.lzz"
|
|
2190
|
-
{
|
|
2191
|
-
Addon* addon = static_cast<Addon*>(ptr);
|
|
2192
|
-
for (Database* db : addon->dbs) db->CloseHandles();
|
|
2193
|
-
addon->dbs.clear();
|
|
2194
|
-
delete addon;
|
|
2195
|
-
}
|
|
2196
|
-
#line 47 "./src/better_sqlite3.lzz"
|
|
2197
|
-
Addon::Addon (v8::Isolate * isolate)
|
|
2198
|
-
#line 47 "./src/better_sqlite3.lzz"
|
|
2199
|
-
: privileged_info (NULL), next_id (0), cs (isolate)
|
|
2200
|
-
#line 50 "./src/better_sqlite3.lzz"
|
|
2201
|
-
{}
|
|
2202
|
-
#undef LZZ_INLINE
|