pi-para 0.7.8 → 0.7.10
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/CHANGELOG.md +10 -0
- package/node_modules/better-sqlite3/LICENSE +21 -0
- package/node_modules/better-sqlite3/README.md +99 -0
- package/node_modules/better-sqlite3/binding.gyp +60 -0
- package/node_modules/better-sqlite3/deps/common.gypi +68 -0
- package/node_modules/better-sqlite3/deps/copy.js +31 -0
- package/node_modules/better-sqlite3/deps/defines.gypi +42 -0
- package/node_modules/better-sqlite3/deps/download.sh +123 -0
- package/node_modules/better-sqlite3/deps/patches/1208.patch +15 -0
- package/node_modules/better-sqlite3/deps/sqlite3/sqlite3.c +269668 -0
- package/node_modules/better-sqlite3/deps/sqlite3/sqlite3.h +14349 -0
- package/node_modules/better-sqlite3/deps/sqlite3/sqlite3ext.h +739 -0
- package/node_modules/better-sqlite3/deps/sqlite3.gyp +80 -0
- package/node_modules/better-sqlite3/deps/test_extension.c +21 -0
- package/node_modules/better-sqlite3/lib/binding.js +62 -0
- package/node_modules/better-sqlite3/lib/darwin-arm64.js +3 -0
- package/node_modules/better-sqlite3/lib/darwin-x64.js +3 -0
- package/node_modules/better-sqlite3/lib/database.js +109 -0
- package/node_modules/better-sqlite3/lib/index.js +3 -0
- package/node_modules/better-sqlite3/lib/linux-arm64.js +3 -0
- package/node_modules/better-sqlite3/lib/linux-x64.js +3 -0
- package/node_modules/better-sqlite3/lib/linuxmusl-arm64.js +4 -0
- package/node_modules/better-sqlite3/lib/linuxmusl-x64.js +4 -0
- package/node_modules/better-sqlite3/lib/methods/aggregate.js +43 -0
- package/node_modules/better-sqlite3/lib/methods/backup.js +67 -0
- package/node_modules/better-sqlite3/lib/methods/explain.js +9 -0
- package/node_modules/better-sqlite3/lib/methods/function.js +31 -0
- package/node_modules/better-sqlite3/lib/methods/inspect.js +7 -0
- package/node_modules/better-sqlite3/lib/methods/pragma.js +12 -0
- package/node_modules/better-sqlite3/lib/methods/serialize.js +16 -0
- package/node_modules/better-sqlite3/lib/methods/table.js +195 -0
- package/node_modules/better-sqlite3/lib/methods/transaction.js +78 -0
- package/node_modules/better-sqlite3/lib/methods/wrappers.js +54 -0
- package/node_modules/better-sqlite3/lib/sqlite-error.js +25 -0
- package/node_modules/better-sqlite3/lib/util.js +12 -0
- package/node_modules/better-sqlite3/lib/win32-arm64.js +3 -0
- package/node_modules/better-sqlite3/lib/win32-x64.js +3 -0
- package/node_modules/better-sqlite3/package.json +67 -0
- package/node_modules/better-sqlite3/prebuilds/darwin-arm64.node +0 -0
- package/node_modules/better-sqlite3/prebuilds/darwin-x64.node +0 -0
- package/node_modules/better-sqlite3/prebuilds/linux-arm64.node +0 -0
- package/node_modules/better-sqlite3/prebuilds/linux-x64.node +0 -0
- package/node_modules/better-sqlite3/prebuilds/linuxmusl-arm64.node +0 -0
- package/node_modules/better-sqlite3/prebuilds/linuxmusl-x64.node +0 -0
- package/node_modules/better-sqlite3/prebuilds/win32-arm64.node +0 -0
- package/node_modules/better-sqlite3/prebuilds/win32-x64.node +0 -0
- package/node_modules/better-sqlite3/src/addon.cpp +59 -0
- package/node_modules/better-sqlite3/src/better_sqlite3.cpp +73 -0
- package/node_modules/better-sqlite3/src/objects/backup.cpp +121 -0
- package/node_modules/better-sqlite3/src/objects/backup.hpp +32 -0
- package/node_modules/better-sqlite3/src/objects/database.cpp +432 -0
- package/node_modules/better-sqlite3/src/objects/database.hpp +100 -0
- package/node_modules/better-sqlite3/src/objects/statement-iterator.cpp +119 -0
- package/node_modules/better-sqlite3/src/objects/statement-iterator.hpp +71 -0
- package/node_modules/better-sqlite3/src/objects/statement.cpp +380 -0
- package/node_modules/better-sqlite3/src/objects/statement.hpp +65 -0
- package/node_modules/better-sqlite3/src/util/bind-map.cpp +73 -0
- package/node_modules/better-sqlite3/src/util/binder.cpp +210 -0
- package/node_modules/better-sqlite3/src/util/constants.cpp +172 -0
- package/node_modules/better-sqlite3/src/util/custom-aggregate.cpp +121 -0
- package/node_modules/better-sqlite3/src/util/custom-function.cpp +59 -0
- package/node_modules/better-sqlite3/src/util/custom-table.cpp +406 -0
- package/node_modules/better-sqlite3/src/util/data-converter.cpp +17 -0
- package/node_modules/better-sqlite3/src/util/data.cpp +134 -0
- package/node_modules/better-sqlite3/src/util/helpers.cpp +190 -0
- package/node_modules/better-sqlite3/src/util/macros.cpp +74 -0
- package/node_modules/better-sqlite3/src/util/query-macros.cpp +71 -0
- package/node_modules/better-sqlite3/src/util/row-builder.cpp +53 -0
- package/node_modules/better-sqlite3/src/util/row-builder.hpp +22 -0
- package/node_modules/node-addon-api/LICENSE.md +9 -0
- package/node_modules/node-addon-api/README.md +95 -0
- package/node_modules/node-addon-api/common.gypi +21 -0
- package/node_modules/node-addon-api/except.gypi +25 -0
- package/node_modules/node-addon-api/index.js +14 -0
- package/node_modules/node-addon-api/napi-inl.deprecated.h +186 -0
- package/node_modules/node-addon-api/napi-inl.h +7165 -0
- package/node_modules/node-addon-api/napi.h +3364 -0
- package/node_modules/node-addon-api/node_addon_api.gyp +42 -0
- package/node_modules/node-addon-api/node_api.gyp +9 -0
- package/node_modules/node-addon-api/noexcept.gypi +26 -0
- package/node_modules/node-addon-api/nothing.c +0 -0
- package/node_modules/node-addon-api/package-support.json +21 -0
- package/node_modules/node-addon-api/package.json +480 -0
- package/node_modules/node-addon-api/tools/README.md +73 -0
- package/node_modules/node-addon-api/tools/check-napi.js +99 -0
- package/node_modules/node-addon-api/tools/clang-format.js +71 -0
- package/node_modules/node-addon-api/tools/conversion.js +301 -0
- package/package.json +5 -2
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
class Binder {
|
|
2
|
+
public:
|
|
3
|
+
|
|
4
|
+
explicit Binder(sqlite3_stmt* _handle) {
|
|
5
|
+
handle = _handle;
|
|
6
|
+
param_count = sqlite3_bind_parameter_count(_handle);
|
|
7
|
+
anon_index = 0;
|
|
8
|
+
success = true;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
bool Bind(NODE_ARGUMENTS info, int argc, Statement* stmt) {
|
|
12
|
+
assert(anon_index == 0);
|
|
13
|
+
Napi::Env env = info.Env();
|
|
14
|
+
Result result = BindArgs(info, argc, stmt);
|
|
15
|
+
if (success && result.count != param_count) {
|
|
16
|
+
if (result.count < param_count) {
|
|
17
|
+
if (!result.bound_object && stmt->GetBindMap(env).GetSize()) {
|
|
18
|
+
Fail(ThrowTypeError, env, "Missing named parameters");
|
|
19
|
+
} else {
|
|
20
|
+
Fail(ThrowRangeError, env, "Too few parameter values were provided");
|
|
21
|
+
}
|
|
22
|
+
} else {
|
|
23
|
+
Fail(ThrowRangeError, env, "Too many parameter values were provided");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return success;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private:
|
|
30
|
+
|
|
31
|
+
struct Result {
|
|
32
|
+
int count;
|
|
33
|
+
bool bound_object;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
static Napi::Value GetPrototype(Napi::Env env, Napi::Object obj) {
|
|
37
|
+
napi_value proto;
|
|
38
|
+
// This can fail (e.g., a Proxy whose getPrototypeOf trap throws), in
|
|
39
|
+
// which case an empty value is returned and an exception is pending.
|
|
40
|
+
if (napi_get_prototype(env, obj, &proto) != napi_ok) return Napi::Value();
|
|
41
|
+
return Napi::Value(env, proto);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// An object is "plain" if its prototype is null or a top-level prototype
|
|
45
|
+
// (i.e., some realm's Object.prototype). Rather than comparing against the
|
|
46
|
+
// current realm's Object.prototype -- which would reject plain objects from
|
|
47
|
+
// other contexts, such as the "vm" module -- we walk to the top of the
|
|
48
|
+
// prototype chain. A plain object's chain is exactly "obj -> proto -> null",
|
|
49
|
+
// so its immediate prototype must itself have a null prototype. This mirrors
|
|
50
|
+
// the cross-realm heuristic used by lodash's isPlainObject.
|
|
51
|
+
static bool IsPlainObject(Napi::Env env, Napi::Object obj) {
|
|
52
|
+
Napi::Value proto = GetPrototype(env, obj);
|
|
53
|
+
if (proto.IsEmpty()) return false;
|
|
54
|
+
if (proto.IsNull()) return true;
|
|
55
|
+
Napi::Value grandproto = GetPrototype(env, proto.As<Napi::Object>());
|
|
56
|
+
if (grandproto.IsEmpty()) return false;
|
|
57
|
+
return grandproto.IsNull();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
void Fail(Napi::Value (*Throw)(Napi::Env, const char*), Napi::Env env, const char* message) {
|
|
61
|
+
assert(success == true);
|
|
62
|
+
assert((Throw == NULL) == (message == NULL));
|
|
63
|
+
assert(Throw == ThrowError || Throw == ThrowTypeError || Throw == ThrowRangeError || Throw == NULL);
|
|
64
|
+
if (Throw) Throw(env, message);
|
|
65
|
+
success = false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
int NextAnonIndex() {
|
|
69
|
+
while (sqlite3_bind_parameter_name(handle, ++anon_index) != NULL) {}
|
|
70
|
+
return anon_index;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Binds the value at the given index or throws an appropriate error.
|
|
74
|
+
void BindValue(Napi::Env env, Napi::Value value, int index) {
|
|
75
|
+
int status = Data::BindValueFromJS(env, handle, index, value);
|
|
76
|
+
if (status != SQLITE_OK) {
|
|
77
|
+
switch (status) {
|
|
78
|
+
case -1:
|
|
79
|
+
return Fail(ThrowTypeError, env, "SQLite3 can only bind numbers, strings, bigints, buffers, and null");
|
|
80
|
+
case SQLITE_TOOBIG:
|
|
81
|
+
return Fail(ThrowRangeError, env, "The bound string, buffer, or bigint is too big");
|
|
82
|
+
case SQLITE_RANGE:
|
|
83
|
+
return Fail(ThrowRangeError, env, "Too many parameter values were provided");
|
|
84
|
+
case SQLITE_NOMEM:
|
|
85
|
+
return Fail(ThrowError, env, "Out of memory");
|
|
86
|
+
default:
|
|
87
|
+
return Fail(ThrowError, env, "An unexpected error occured while trying to bind parameters");
|
|
88
|
+
}
|
|
89
|
+
assert(false);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Binds each value in the array or throws an appropriate error.
|
|
94
|
+
// The number of successfully bound parameters is returned.
|
|
95
|
+
int BindArray(Napi::Env env, Napi::Array arr) {
|
|
96
|
+
uint32_t length = arr.Length();
|
|
97
|
+
if (length > INT_MAX) {
|
|
98
|
+
Fail(ThrowRangeError, env, "Too many parameter values were provided");
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
int len = static_cast<int>(length);
|
|
102
|
+
for (int i = 0; i < len; ++i) {
|
|
103
|
+
Napi::Value value = SafeGetElement(env, arr, static_cast<uint32_t>(i));
|
|
104
|
+
if (value.IsEmpty()) {
|
|
105
|
+
Fail(NULL, env, NULL);
|
|
106
|
+
return i;
|
|
107
|
+
}
|
|
108
|
+
BindValue(env, value, NextAnonIndex());
|
|
109
|
+
if (!success) {
|
|
110
|
+
return i;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return len;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Binds all named parameters using the values found in the given object.
|
|
117
|
+
// The number of successfully bound parameters is returned.
|
|
118
|
+
// If a named parameter is missing from the object, an error is thrown.
|
|
119
|
+
// This should only be invoked once per instance.
|
|
120
|
+
int BindObject(Napi::Env env, Napi::Object obj, Statement* stmt) {
|
|
121
|
+
BindMap& bind_map = stmt->GetBindMap(env);
|
|
122
|
+
BindMap::Pair* pairs = bind_map.GetPairs();
|
|
123
|
+
int len = bind_map.GetSize();
|
|
124
|
+
|
|
125
|
+
for (int i = 0; i < len; ++i) {
|
|
126
|
+
Napi::String key = pairs[i].GetName(env);
|
|
127
|
+
|
|
128
|
+
// Check if the named parameter was provided.
|
|
129
|
+
bool has_property;
|
|
130
|
+
if (!SafeHasOwnProperty(env, obj, key, &has_property)) {
|
|
131
|
+
Fail(NULL, env, NULL);
|
|
132
|
+
return i;
|
|
133
|
+
}
|
|
134
|
+
if (!has_property) {
|
|
135
|
+
std::string param_name = key.Utf8Value();
|
|
136
|
+
Fail(ThrowRangeError, env, (std::string("Missing named parameter \"") + param_name + "\"").c_str());
|
|
137
|
+
return i;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Get the current property value.
|
|
141
|
+
Napi::Value value = SafeGet(env, obj, key);
|
|
142
|
+
if (value.IsEmpty()) {
|
|
143
|
+
Fail(NULL, env, NULL);
|
|
144
|
+
return i;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
BindValue(env, value, pairs[i].GetIndex());
|
|
148
|
+
if (!success) {
|
|
149
|
+
return i;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return len;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Binds all parameters using the values found in the arguments object.
|
|
157
|
+
// Anonymous parameter values can be directly in the arguments object or in an Array.
|
|
158
|
+
// Named parameter values can be provided in a plain Object argument.
|
|
159
|
+
// Only one plain Object argument may be provided.
|
|
160
|
+
// If an error occurs, an appropriate error is thrown.
|
|
161
|
+
// The return value is a struct indicating how many parameters were successfully bound
|
|
162
|
+
// and whether or not it tried to bind an object.
|
|
163
|
+
Result BindArgs(NODE_ARGUMENTS info, int argc, Statement* stmt) {
|
|
164
|
+
Napi::Env env = info.Env();
|
|
165
|
+
int count = 0;
|
|
166
|
+
bool bound_object = false;
|
|
167
|
+
|
|
168
|
+
for (int i = 0; i < argc; ++i) {
|
|
169
|
+
Napi::Value arg = info[i];
|
|
170
|
+
|
|
171
|
+
if (arg.IsArray()) {
|
|
172
|
+
count += BindArray(env, arg.As<Napi::Array>());
|
|
173
|
+
if (!success) break;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (arg.IsObject() && !arg.IsBuffer()) {
|
|
178
|
+
Napi::Object obj = arg.As<Napi::Object>();
|
|
179
|
+
if (IsPlainObject(env, obj)) {
|
|
180
|
+
if (bound_object) {
|
|
181
|
+
Fail(ThrowTypeError, env, "You cannot specify named parameters in two different objects");
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
bound_object = true;
|
|
185
|
+
|
|
186
|
+
count += BindObject(env, obj, stmt);
|
|
187
|
+
if (!success) break;
|
|
188
|
+
continue;
|
|
189
|
+
} else if (env.IsExceptionPending()) {
|
|
190
|
+
Fail(NULL, env, NULL);
|
|
191
|
+
break;
|
|
192
|
+
} else if (stmt->GetBindMap(env).GetSize()) {
|
|
193
|
+
Fail(ThrowTypeError, env, "Named parameters can only be passed within plain objects");
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
BindValue(env, arg, NextAnonIndex());
|
|
199
|
+
if (!success) break;
|
|
200
|
+
count += 1;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return { count, bound_object };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
sqlite3_stmt* handle;
|
|
207
|
+
int param_count;
|
|
208
|
+
int anon_index; // This value should only be used by NextAnonIndex()
|
|
209
|
+
bool success; // This value should only be set by Fail()
|
|
210
|
+
};
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// Caches JavaScript strings that are used frequently as property keys or
|
|
2
|
+
// error codes. Persistent references to strings require Node-API version 10.
|
|
3
|
+
class CS {
|
|
4
|
+
public:
|
|
5
|
+
|
|
6
|
+
Napi::String Code(Napi::Env env, int code) {
|
|
7
|
+
auto element = codes.find(code);
|
|
8
|
+
if (element != codes.end()) return element->second.Value();
|
|
9
|
+
return StringFromUtf8(env, (std::string("UNKNOWN_SQLITE_ERROR_") + std::to_string(code)).c_str(), -1);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
explicit CS(Napi::Env env) {
|
|
13
|
+
SetString(env, database, "database");
|
|
14
|
+
SetString(env, reader, "reader");
|
|
15
|
+
SetString(env, source, "source");
|
|
16
|
+
SetString(env, memory, "memory");
|
|
17
|
+
SetString(env, readonly, "readonly");
|
|
18
|
+
SetString(env, name, "name");
|
|
19
|
+
SetString(env, next, "next");
|
|
20
|
+
SetString(env, length, "length");
|
|
21
|
+
SetString(env, done, "done");
|
|
22
|
+
SetString(env, value, "value");
|
|
23
|
+
SetString(env, changes, "changes");
|
|
24
|
+
SetString(env, lastInsertRowid, "lastInsertRowid");
|
|
25
|
+
SetString(env, statement, "statement");
|
|
26
|
+
SetString(env, column, "column");
|
|
27
|
+
SetString(env, table, "table");
|
|
28
|
+
SetString(env, type, "type");
|
|
29
|
+
SetString(env, totalPages, "totalPages");
|
|
30
|
+
SetString(env, remainingPages, "remainingPages");
|
|
31
|
+
|
|
32
|
+
SetCode(env, SQLITE_OK, "SQLITE_OK");
|
|
33
|
+
SetCode(env, SQLITE_ERROR, "SQLITE_ERROR");
|
|
34
|
+
SetCode(env, SQLITE_INTERNAL, "SQLITE_INTERNAL");
|
|
35
|
+
SetCode(env, SQLITE_PERM, "SQLITE_PERM");
|
|
36
|
+
SetCode(env, SQLITE_ABORT, "SQLITE_ABORT");
|
|
37
|
+
SetCode(env, SQLITE_BUSY, "SQLITE_BUSY");
|
|
38
|
+
SetCode(env, SQLITE_LOCKED, "SQLITE_LOCKED");
|
|
39
|
+
SetCode(env, SQLITE_NOMEM, "SQLITE_NOMEM");
|
|
40
|
+
SetCode(env, SQLITE_READONLY, "SQLITE_READONLY");
|
|
41
|
+
SetCode(env, SQLITE_INTERRUPT, "SQLITE_INTERRUPT");
|
|
42
|
+
SetCode(env, SQLITE_IOERR, "SQLITE_IOERR");
|
|
43
|
+
SetCode(env, SQLITE_CORRUPT, "SQLITE_CORRUPT");
|
|
44
|
+
SetCode(env, SQLITE_NOTFOUND, "SQLITE_NOTFOUND");
|
|
45
|
+
SetCode(env, SQLITE_FULL, "SQLITE_FULL");
|
|
46
|
+
SetCode(env, SQLITE_CANTOPEN, "SQLITE_CANTOPEN");
|
|
47
|
+
SetCode(env, SQLITE_PROTOCOL, "SQLITE_PROTOCOL");
|
|
48
|
+
SetCode(env, SQLITE_EMPTY, "SQLITE_EMPTY");
|
|
49
|
+
SetCode(env, SQLITE_SCHEMA, "SQLITE_SCHEMA");
|
|
50
|
+
SetCode(env, SQLITE_TOOBIG, "SQLITE_TOOBIG");
|
|
51
|
+
SetCode(env, SQLITE_CONSTRAINT, "SQLITE_CONSTRAINT");
|
|
52
|
+
SetCode(env, SQLITE_MISMATCH, "SQLITE_MISMATCH");
|
|
53
|
+
SetCode(env, SQLITE_MISUSE, "SQLITE_MISUSE");
|
|
54
|
+
SetCode(env, SQLITE_NOLFS, "SQLITE_NOLFS");
|
|
55
|
+
SetCode(env, SQLITE_AUTH, "SQLITE_AUTH");
|
|
56
|
+
SetCode(env, SQLITE_FORMAT, "SQLITE_FORMAT");
|
|
57
|
+
SetCode(env, SQLITE_RANGE, "SQLITE_RANGE");
|
|
58
|
+
SetCode(env, SQLITE_NOTADB, "SQLITE_NOTADB");
|
|
59
|
+
SetCode(env, SQLITE_NOTICE, "SQLITE_NOTICE");
|
|
60
|
+
SetCode(env, SQLITE_WARNING, "SQLITE_WARNING");
|
|
61
|
+
SetCode(env, SQLITE_ROW, "SQLITE_ROW");
|
|
62
|
+
SetCode(env, SQLITE_DONE, "SQLITE_DONE");
|
|
63
|
+
|
|
64
|
+
SetCode(env, SQLITE_ERROR_MISSING_COLLSEQ, "SQLITE_ERROR_MISSING_COLLSEQ");
|
|
65
|
+
SetCode(env, SQLITE_ERROR_RETRY, "SQLITE_ERROR_RETRY");
|
|
66
|
+
SetCode(env, SQLITE_ERROR_SNAPSHOT, "SQLITE_ERROR_SNAPSHOT");
|
|
67
|
+
SetCode(env, SQLITE_IOERR_READ, "SQLITE_IOERR_READ");
|
|
68
|
+
SetCode(env, SQLITE_IOERR_SHORT_READ, "SQLITE_IOERR_SHORT_READ");
|
|
69
|
+
SetCode(env, SQLITE_IOERR_WRITE, "SQLITE_IOERR_WRITE");
|
|
70
|
+
SetCode(env, SQLITE_IOERR_FSYNC, "SQLITE_IOERR_FSYNC");
|
|
71
|
+
SetCode(env, SQLITE_IOERR_DIR_FSYNC, "SQLITE_IOERR_DIR_FSYNC");
|
|
72
|
+
SetCode(env, SQLITE_IOERR_TRUNCATE, "SQLITE_IOERR_TRUNCATE");
|
|
73
|
+
SetCode(env, SQLITE_IOERR_FSTAT, "SQLITE_IOERR_FSTAT");
|
|
74
|
+
SetCode(env, SQLITE_IOERR_UNLOCK, "SQLITE_IOERR_UNLOCK");
|
|
75
|
+
SetCode(env, SQLITE_IOERR_RDLOCK, "SQLITE_IOERR_RDLOCK");
|
|
76
|
+
SetCode(env, SQLITE_IOERR_DELETE, "SQLITE_IOERR_DELETE");
|
|
77
|
+
SetCode(env, SQLITE_IOERR_BLOCKED, "SQLITE_IOERR_BLOCKED");
|
|
78
|
+
SetCode(env, SQLITE_IOERR_NOMEM, "SQLITE_IOERR_NOMEM");
|
|
79
|
+
SetCode(env, SQLITE_IOERR_ACCESS, "SQLITE_IOERR_ACCESS");
|
|
80
|
+
SetCode(env, SQLITE_IOERR_CHECKRESERVEDLOCK, "SQLITE_IOERR_CHECKRESERVEDLOCK");
|
|
81
|
+
SetCode(env, SQLITE_IOERR_LOCK, "SQLITE_IOERR_LOCK");
|
|
82
|
+
SetCode(env, SQLITE_IOERR_CLOSE, "SQLITE_IOERR_CLOSE");
|
|
83
|
+
SetCode(env, SQLITE_IOERR_DIR_CLOSE, "SQLITE_IOERR_DIR_CLOSE");
|
|
84
|
+
SetCode(env, SQLITE_IOERR_SHMOPEN, "SQLITE_IOERR_SHMOPEN");
|
|
85
|
+
SetCode(env, SQLITE_IOERR_SHMSIZE, "SQLITE_IOERR_SHMSIZE");
|
|
86
|
+
SetCode(env, SQLITE_IOERR_SHMLOCK, "SQLITE_IOERR_SHMLOCK");
|
|
87
|
+
SetCode(env, SQLITE_IOERR_SHMMAP, "SQLITE_IOERR_SHMMAP");
|
|
88
|
+
SetCode(env, SQLITE_IOERR_SEEK, "SQLITE_IOERR_SEEK");
|
|
89
|
+
SetCode(env, SQLITE_IOERR_DELETE_NOENT, "SQLITE_IOERR_DELETE_NOENT");
|
|
90
|
+
SetCode(env, SQLITE_IOERR_MMAP, "SQLITE_IOERR_MMAP");
|
|
91
|
+
SetCode(env, SQLITE_IOERR_GETTEMPPATH, "SQLITE_IOERR_GETTEMPPATH");
|
|
92
|
+
SetCode(env, SQLITE_IOERR_CONVPATH, "SQLITE_IOERR_CONVPATH");
|
|
93
|
+
SetCode(env, SQLITE_IOERR_VNODE, "SQLITE_IOERR_VNODE");
|
|
94
|
+
SetCode(env, SQLITE_IOERR_AUTH, "SQLITE_IOERR_AUTH");
|
|
95
|
+
SetCode(env, SQLITE_IOERR_BEGIN_ATOMIC, "SQLITE_IOERR_BEGIN_ATOMIC");
|
|
96
|
+
SetCode(env, SQLITE_IOERR_COMMIT_ATOMIC, "SQLITE_IOERR_COMMIT_ATOMIC");
|
|
97
|
+
SetCode(env, SQLITE_IOERR_ROLLBACK_ATOMIC, "SQLITE_IOERR_ROLLBACK_ATOMIC");
|
|
98
|
+
SetCode(env, SQLITE_IOERR_DATA, "SQLITE_IOERR_DATA");
|
|
99
|
+
SetCode(env, SQLITE_IOERR_CORRUPTFS, "SQLITE_IOERR_CORRUPTFS");
|
|
100
|
+
SetCode(env, SQLITE_IOERR_IN_PAGE, "SQLITE_IOERR_IN_PAGE");
|
|
101
|
+
SetCode(env, SQLITE_LOCKED_SHAREDCACHE, "SQLITE_LOCKED_SHAREDCACHE");
|
|
102
|
+
SetCode(env, SQLITE_LOCKED_VTAB, "SQLITE_LOCKED_VTAB");
|
|
103
|
+
SetCode(env, SQLITE_BUSY_RECOVERY, "SQLITE_BUSY_RECOVERY");
|
|
104
|
+
SetCode(env, SQLITE_BUSY_SNAPSHOT, "SQLITE_BUSY_SNAPSHOT");
|
|
105
|
+
SetCode(env, SQLITE_CANTOPEN_NOTEMPDIR, "SQLITE_CANTOPEN_NOTEMPDIR");
|
|
106
|
+
SetCode(env, SQLITE_CANTOPEN_ISDIR, "SQLITE_CANTOPEN_ISDIR");
|
|
107
|
+
SetCode(env, SQLITE_CANTOPEN_FULLPATH, "SQLITE_CANTOPEN_FULLPATH");
|
|
108
|
+
SetCode(env, SQLITE_CANTOPEN_CONVPATH, "SQLITE_CANTOPEN_CONVPATH");
|
|
109
|
+
SetCode(env, SQLITE_CANTOPEN_DIRTYWAL, "SQLITE_CANTOPEN_DIRTYWAL");
|
|
110
|
+
SetCode(env, SQLITE_CANTOPEN_SYMLINK, "SQLITE_CANTOPEN_SYMLINK");
|
|
111
|
+
SetCode(env, SQLITE_CORRUPT_VTAB, "SQLITE_CORRUPT_VTAB");
|
|
112
|
+
SetCode(env, SQLITE_CORRUPT_SEQUENCE, "SQLITE_CORRUPT_SEQUENCE");
|
|
113
|
+
SetCode(env, SQLITE_CORRUPT_INDEX, "SQLITE_CORRUPT_INDEX");
|
|
114
|
+
SetCode(env, SQLITE_READONLY_RECOVERY, "SQLITE_READONLY_RECOVERY");
|
|
115
|
+
SetCode(env, SQLITE_READONLY_CANTLOCK, "SQLITE_READONLY_CANTLOCK");
|
|
116
|
+
SetCode(env, SQLITE_READONLY_ROLLBACK, "SQLITE_READONLY_ROLLBACK");
|
|
117
|
+
SetCode(env, SQLITE_READONLY_DBMOVED, "SQLITE_READONLY_DBMOVED");
|
|
118
|
+
SetCode(env, SQLITE_READONLY_CANTINIT, "SQLITE_READONLY_CANTINIT");
|
|
119
|
+
SetCode(env, SQLITE_READONLY_DIRECTORY, "SQLITE_READONLY_DIRECTORY");
|
|
120
|
+
SetCode(env, SQLITE_ABORT_ROLLBACK, "SQLITE_ABORT_ROLLBACK");
|
|
121
|
+
SetCode(env, SQLITE_CONSTRAINT_CHECK, "SQLITE_CONSTRAINT_CHECK");
|
|
122
|
+
SetCode(env, SQLITE_CONSTRAINT_COMMITHOOK, "SQLITE_CONSTRAINT_COMMITHOOK");
|
|
123
|
+
SetCode(env, SQLITE_CONSTRAINT_FOREIGNKEY, "SQLITE_CONSTRAINT_FOREIGNKEY");
|
|
124
|
+
SetCode(env, SQLITE_CONSTRAINT_FUNCTION, "SQLITE_CONSTRAINT_FUNCTION");
|
|
125
|
+
SetCode(env, SQLITE_CONSTRAINT_NOTNULL, "SQLITE_CONSTRAINT_NOTNULL");
|
|
126
|
+
SetCode(env, SQLITE_CONSTRAINT_PRIMARYKEY, "SQLITE_CONSTRAINT_PRIMARYKEY");
|
|
127
|
+
SetCode(env, SQLITE_CONSTRAINT_TRIGGER, "SQLITE_CONSTRAINT_TRIGGER");
|
|
128
|
+
SetCode(env, SQLITE_CONSTRAINT_UNIQUE, "SQLITE_CONSTRAINT_UNIQUE");
|
|
129
|
+
SetCode(env, SQLITE_CONSTRAINT_VTAB, "SQLITE_CONSTRAINT_VTAB");
|
|
130
|
+
SetCode(env, SQLITE_CONSTRAINT_ROWID, "SQLITE_CONSTRAINT_ROWID");
|
|
131
|
+
SetCode(env, SQLITE_CONSTRAINT_PINNED, "SQLITE_CONSTRAINT_PINNED");
|
|
132
|
+
SetCode(env, SQLITE_CONSTRAINT_DATATYPE, "SQLITE_CONSTRAINT_DATATYPE");
|
|
133
|
+
SetCode(env, SQLITE_NOTICE_RECOVER_WAL, "SQLITE_NOTICE_RECOVER_WAL");
|
|
134
|
+
SetCode(env, SQLITE_NOTICE_RECOVER_ROLLBACK, "SQLITE_NOTICE_RECOVER_ROLLBACK");
|
|
135
|
+
SetCode(env, SQLITE_NOTICE_RBU, "SQLITE_NOTICE_RBU");
|
|
136
|
+
SetCode(env, SQLITE_WARNING_AUTOINDEX, "SQLITE_WARNING_AUTOINDEX");
|
|
137
|
+
SetCode(env, SQLITE_AUTH_USER, "SQLITE_AUTH_USER");
|
|
138
|
+
SetCode(env, SQLITE_OK_LOAD_PERMANENTLY, "SQLITE_OK_LOAD_PERMANENTLY");
|
|
139
|
+
SetCode(env, SQLITE_OK_SYMLINK, "SQLITE_OK_SYMLINK");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
Napi::Reference<Napi::String> database;
|
|
143
|
+
Napi::Reference<Napi::String> reader;
|
|
144
|
+
Napi::Reference<Napi::String> source;
|
|
145
|
+
Napi::Reference<Napi::String> memory;
|
|
146
|
+
Napi::Reference<Napi::String> readonly;
|
|
147
|
+
Napi::Reference<Napi::String> name;
|
|
148
|
+
Napi::Reference<Napi::String> next;
|
|
149
|
+
Napi::Reference<Napi::String> length;
|
|
150
|
+
Napi::Reference<Napi::String> done;
|
|
151
|
+
Napi::Reference<Napi::String> value;
|
|
152
|
+
Napi::Reference<Napi::String> changes;
|
|
153
|
+
Napi::Reference<Napi::String> lastInsertRowid;
|
|
154
|
+
Napi::Reference<Napi::String> statement;
|
|
155
|
+
Napi::Reference<Napi::String> column;
|
|
156
|
+
Napi::Reference<Napi::String> table;
|
|
157
|
+
Napi::Reference<Napi::String> type;
|
|
158
|
+
Napi::Reference<Napi::String> totalPages;
|
|
159
|
+
Napi::Reference<Napi::String> remainingPages;
|
|
160
|
+
|
|
161
|
+
private:
|
|
162
|
+
|
|
163
|
+
static void SetString(Napi::Env env, Napi::Reference<Napi::String>& constant, const char* str) {
|
|
164
|
+
constant = Napi::Persistent(InternalizedFromLatin1(env, str));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
void SetCode(Napi::Env env, int code, const char* str) {
|
|
168
|
+
codes.emplace(code, Napi::Persistent(InternalizedFromLatin1(env, str)));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
std::unordered_map<int, Napi::Reference<Napi::String>> codes;
|
|
172
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
class CustomAggregate : public CustomFunction {
|
|
2
|
+
public:
|
|
3
|
+
|
|
4
|
+
explicit CustomAggregate(
|
|
5
|
+
Napi::Env env,
|
|
6
|
+
Database* db,
|
|
7
|
+
const char* name,
|
|
8
|
+
Napi::Value start,
|
|
9
|
+
Napi::Function step,
|
|
10
|
+
Napi::Value inverse,
|
|
11
|
+
Napi::Value result,
|
|
12
|
+
bool safe_ints
|
|
13
|
+
) :
|
|
14
|
+
CustomFunction(env, db, name, step, safe_ints),
|
|
15
|
+
invoke_result(result.IsFunction()),
|
|
16
|
+
invoke_start(start.IsFunction()),
|
|
17
|
+
inverse(inverse.IsFunction() ? Napi::Persistent(inverse.As<Napi::Function>()) : Napi::FunctionReference()),
|
|
18
|
+
result(result.IsFunction() ? Napi::Persistent(result.As<Napi::Function>()) : Napi::FunctionReference()),
|
|
19
|
+
start(Napi::Persistent(start)) {}
|
|
20
|
+
|
|
21
|
+
static void xStep(sqlite3_context* invocation, int argc, sqlite3_value** argv) {
|
|
22
|
+
xStepBase(invocation, argc, argv, &CustomAggregate::fn);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static void xInverse(sqlite3_context* invocation, int argc, sqlite3_value** argv) {
|
|
26
|
+
xStepBase(invocation, argc, argv, &CustomAggregate::inverse);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static void xValue(sqlite3_context* invocation) {
|
|
30
|
+
xValueBase(invocation, false);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static void xFinal(sqlite3_context* invocation) {
|
|
34
|
+
xValueBase(invocation, true);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private:
|
|
38
|
+
|
|
39
|
+
static inline void xStepBase(sqlite3_context* invocation, int argc, sqlite3_value** argv, const Napi::FunctionReference CustomAggregate::*ptrtm) {
|
|
40
|
+
AGGREGATE_START();
|
|
41
|
+
|
|
42
|
+
napi_value args_fast[5];
|
|
43
|
+
napi_value* args = argc <= 4 ? args_fast : ALLOC_ARRAY<napi_value>(argc + 1);
|
|
44
|
+
args[0] = acc->value.Value();
|
|
45
|
+
if (argc != 0) Data::GetArgumentsJS(env, args + 1, argv, argc, self->safe_ints);
|
|
46
|
+
|
|
47
|
+
Napi::Value returnValue = SafeCall(env, (self->*ptrtm).Value(), env.Undefined(), argc + 1, args);
|
|
48
|
+
if (args != args_fast) delete[] args;
|
|
49
|
+
|
|
50
|
+
if (env.IsExceptionPending()) {
|
|
51
|
+
self->PropagateJSError(invocation);
|
|
52
|
+
} else {
|
|
53
|
+
if (!returnValue.IsUndefined()) acc->value.Reset(returnValue, 1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static inline void xValueBase(sqlite3_context* invocation, bool is_final) {
|
|
58
|
+
AGGREGATE_START();
|
|
59
|
+
|
|
60
|
+
if (!is_final) {
|
|
61
|
+
acc->is_window = true;
|
|
62
|
+
} else if (acc->is_window) {
|
|
63
|
+
DestroyAccumulator(invocation);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Napi::Value result = acc->value.Value();
|
|
68
|
+
if (self->invoke_result) {
|
|
69
|
+
napi_value arg = result;
|
|
70
|
+
Napi::Value maybeResult = SafeCall(env, self->result.Value(), env.Undefined(), 1, &arg);
|
|
71
|
+
if (env.IsExceptionPending()) {
|
|
72
|
+
self->PropagateJSError(invocation);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
result = maybeResult;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
Data::ResultValueFromJS(env, invocation, result, self);
|
|
79
|
+
if (is_final) DestroyAccumulator(invocation);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
struct Accumulator { public:
|
|
83
|
+
Napi::Reference<Napi::Value> value;
|
|
84
|
+
bool initialized;
|
|
85
|
+
bool is_window;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
Accumulator* GetAccumulator(sqlite3_context* invocation) {
|
|
89
|
+
Accumulator* acc = static_cast<Accumulator*>(sqlite3_aggregate_context(invocation, sizeof(Accumulator)));
|
|
90
|
+
if (!acc->initialized) {
|
|
91
|
+
assert(acc->value.IsEmpty());
|
|
92
|
+
acc->initialized = true;
|
|
93
|
+
if (invoke_start) {
|
|
94
|
+
Napi::Value maybeSeed = SafeCall(env, start.Value().As<Napi::Function>(), env.Undefined(), 0, NULL);
|
|
95
|
+
if (env.IsExceptionPending()) PropagateJSError(invocation);
|
|
96
|
+
else acc->value.Reset(maybeSeed, 1);
|
|
97
|
+
} else {
|
|
98
|
+
assert(!start.IsEmpty());
|
|
99
|
+
acc->value.Reset(start.Value(), 1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return acc;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static void DestroyAccumulator(sqlite3_context* invocation) {
|
|
106
|
+
Accumulator* acc = static_cast<Accumulator*>(sqlite3_aggregate_context(invocation, sizeof(Accumulator)));
|
|
107
|
+
assert(acc->initialized);
|
|
108
|
+
acc->value.Reset();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
void PropagateJSError(sqlite3_context* invocation) {
|
|
112
|
+
DestroyAccumulator(invocation);
|
|
113
|
+
CustomFunction::PropagateJSError(invocation);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const bool invoke_result;
|
|
117
|
+
const bool invoke_start;
|
|
118
|
+
const Napi::FunctionReference inverse;
|
|
119
|
+
const Napi::FunctionReference result;
|
|
120
|
+
const Napi::Reference<Napi::Value> start;
|
|
121
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
class CustomFunction : protected DataConverter {
|
|
2
|
+
public:
|
|
3
|
+
|
|
4
|
+
explicit CustomFunction(
|
|
5
|
+
Napi::Env env,
|
|
6
|
+
Database* db,
|
|
7
|
+
const char* name,
|
|
8
|
+
Napi::Function fn,
|
|
9
|
+
bool safe_ints
|
|
10
|
+
) :
|
|
11
|
+
name(name),
|
|
12
|
+
db(db),
|
|
13
|
+
env(env),
|
|
14
|
+
fn(Napi::Persistent(fn)),
|
|
15
|
+
safe_ints(safe_ints) {}
|
|
16
|
+
|
|
17
|
+
virtual ~CustomFunction() {}
|
|
18
|
+
|
|
19
|
+
static void xDestroy(void* self) {
|
|
20
|
+
delete static_cast<CustomFunction*>(self);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static void xFunc(sqlite3_context* invocation, int argc, sqlite3_value** argv) {
|
|
24
|
+
FUNCTION_START();
|
|
25
|
+
|
|
26
|
+
napi_value args_fast[4];
|
|
27
|
+
napi_value* args = NULL;
|
|
28
|
+
if (argc != 0) {
|
|
29
|
+
args = argc <= 4 ? args_fast : ALLOC_ARRAY<napi_value>(argc);
|
|
30
|
+
Data::GetArgumentsJS(env, args, argv, argc, self->safe_ints);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Napi::Value returnValue = SafeCall(env, self->fn.Value(), env.Undefined(), argc, args);
|
|
34
|
+
if (args != args_fast) delete[] args;
|
|
35
|
+
|
|
36
|
+
if (env.IsExceptionPending()) self->PropagateJSError(invocation);
|
|
37
|
+
else Data::ResultValueFromJS(env, invocation, returnValue, self);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
protected:
|
|
41
|
+
|
|
42
|
+
void PropagateJSError(sqlite3_context* invocation) {
|
|
43
|
+
assert(db->GetState()->was_js_error == false);
|
|
44
|
+
db->GetState()->was_js_error = true;
|
|
45
|
+
sqlite3_result_error(invocation, "", 0);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
std::string GetDataErrorPrefix() {
|
|
49
|
+
return std::string("User-defined function ") + name + "() returned";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private:
|
|
53
|
+
const std::string name;
|
|
54
|
+
Database* const db;
|
|
55
|
+
protected:
|
|
56
|
+
const Napi::Env env;
|
|
57
|
+
const Napi::FunctionReference fn;
|
|
58
|
+
const bool safe_ints;
|
|
59
|
+
};
|