@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.
@@ -0,0 +1,73 @@
1
+ class BindMap {
2
+ public:
3
+
4
+ // This nested class represents a single mapping between a parameter name
5
+ // and its associated parameter index in a prepared statement.
6
+ class Pair { friend class BindMap;
7
+ public:
8
+
9
+ inline int GetIndex() {
10
+ return index;
11
+ }
12
+
13
+ inline v8::Local<v8::String> GetName(v8::Isolate* isolate) {
14
+ return name.Get(isolate);
15
+ }
16
+
17
+ private:
18
+
19
+ explicit Pair(v8::Isolate* isolate, const char* name, int index)
20
+ : name(isolate, InternalizedFromUtf8(isolate, name, -1)), index(index) {}
21
+
22
+ explicit Pair(v8::Isolate* isolate, Pair* pair)
23
+ : name(isolate, pair->name), index(pair->index) {}
24
+
25
+ const v8::Global<v8::String> name;
26
+ const int index;
27
+ };
28
+
29
+ explicit BindMap(char _) {
30
+ assert(_ == 0);
31
+ pairs = NULL;
32
+ capacity = 0;
33
+ length = 0;
34
+ }
35
+
36
+ ~BindMap() {
37
+ while (length) pairs[--length].~Pair();
38
+ FREE_ARRAY<Pair>(pairs);
39
+ }
40
+
41
+ inline Pair* GetPairs() {
42
+ return pairs;
43
+ }
44
+
45
+ inline int GetSize() {
46
+ return length;
47
+ }
48
+
49
+ // Adds a pair to the bind map, expanding the capacity if necessary.
50
+ void Add(v8::Isolate* isolate, const char* name, int index) {
51
+ assert(name != NULL);
52
+ if (capacity == length) Grow(isolate);
53
+ new (pairs + length++) Pair(isolate, name, index);
54
+ }
55
+
56
+ private:
57
+
58
+ void Grow(v8::Isolate* isolate) {
59
+ assert(capacity == length);
60
+ capacity = (capacity << 1) | 2;
61
+ Pair* new_pairs = ALLOC_ARRAY<Pair>(capacity);
62
+ for (int i = 0; i < length; ++i) {
63
+ new (new_pairs + i) Pair(isolate, pairs + i);
64
+ pairs[i].~Pair();
65
+ }
66
+ FREE_ARRAY<Pair>(pairs);
67
+ pairs = new_pairs;
68
+ }
69
+
70
+ Pair* pairs;
71
+ int capacity;
72
+ int length;
73
+ };
@@ -0,0 +1,193 @@
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
+ Result result = BindArgs(info, argc, stmt);
14
+ if (success && result.count != param_count) {
15
+ if (result.count < param_count) {
16
+ if (!result.bound_object && stmt->GetBindMap(OnlyIsolate)->GetSize()) {
17
+ Fail(ThrowTypeError, "Missing named parameters");
18
+ } else {
19
+ Fail(ThrowRangeError, "Too few parameter values were provided");
20
+ }
21
+ } else {
22
+ Fail(ThrowRangeError, "Too many parameter values were provided");
23
+ }
24
+ }
25
+ return success;
26
+ }
27
+
28
+ private:
29
+
30
+ struct Result {
31
+ int count;
32
+ bool bound_object;
33
+ };
34
+
35
+ static bool IsPlainObject(v8::Isolate* isolate, v8::Local<v8::Object> obj) {
36
+ v8::Local<v8::Value> proto = obj->GetPrototype();
37
+ v8::Local<v8::Context> ctx = obj->GetCreationContext().ToLocalChecked();
38
+ ctx->Enter();
39
+ v8::Local<v8::Value> baseProto = v8::Object::New(isolate)->GetPrototype();
40
+ ctx->Exit();
41
+ return proto->StrictEquals(baseProto) || proto->StrictEquals(v8::Null(isolate));
42
+ }
43
+
44
+ void Fail(void (*Throw)(const char* _), const char* message) {
45
+ assert(success == true);
46
+ assert((Throw == NULL) == (message == NULL));
47
+ assert(Throw == ThrowError || Throw == ThrowTypeError || Throw == ThrowRangeError || Throw == NULL);
48
+ if (Throw) Throw(message);
49
+ success = false;
50
+ }
51
+
52
+ int NextAnonIndex() {
53
+ while (sqlite3_bind_parameter_name(handle, ++anon_index) != NULL) {}
54
+ return anon_index;
55
+ }
56
+
57
+ // Binds the value at the given index or throws an appropriate error.
58
+ void BindValue(v8::Isolate* isolate, v8::Local<v8::Value> value, int index) {
59
+ int status = Data::BindValueFromJS(isolate, handle, index, value);
60
+ if (status != SQLITE_OK) {
61
+ switch (status) {
62
+ case -1:
63
+ return Fail(ThrowTypeError, "SQLite3 can only bind numbers, strings, bigints, buffers, and null");
64
+ case SQLITE_TOOBIG:
65
+ return Fail(ThrowRangeError, "The bound string, buffer, or bigint is too big");
66
+ case SQLITE_RANGE:
67
+ return Fail(ThrowRangeError, "Too many parameter values were provided");
68
+ case SQLITE_NOMEM:
69
+ return Fail(ThrowError, "Out of memory");
70
+ default:
71
+ return Fail(ThrowError, "An unexpected error occured while trying to bind parameters");
72
+ }
73
+ assert(false);
74
+ }
75
+ }
76
+
77
+ // Binds each value in the array or throws an appropriate error.
78
+ // The number of successfully bound parameters is returned.
79
+ int BindArray(v8::Isolate* isolate, v8::Local<v8::Array> arr) {
80
+ UseContext;
81
+ uint32_t length = arr->Length();
82
+ if (length > INT_MAX) {
83
+ Fail(ThrowRangeError, "Too many parameter values were provided");
84
+ return 0;
85
+ }
86
+ int len = static_cast<int>(length);
87
+ for (int i = 0; i < len; ++i) {
88
+ v8::MaybeLocal<v8::Value> maybeValue = arr->Get(ctx, i);
89
+ if (maybeValue.IsEmpty()) {
90
+ Fail(NULL, NULL);
91
+ return i;
92
+ }
93
+ BindValue(isolate, maybeValue.ToLocalChecked(), NextAnonIndex());
94
+ if (!success) {
95
+ return i;
96
+ }
97
+ }
98
+ return len;
99
+ }
100
+
101
+ // Binds all named parameters using the values found in the given object.
102
+ // The number of successfully bound parameters is returned.
103
+ // If a named parameter is missing from the object, an error is thrown.
104
+ // This should only be invoked once per instance.
105
+ int BindObject(v8::Isolate* isolate, v8::Local<v8::Object> obj, Statement* stmt) {
106
+ UseContext;
107
+ BindMap* bind_map = stmt->GetBindMap(isolate);
108
+ BindMap::Pair* pairs = bind_map->GetPairs();
109
+ int len = bind_map->GetSize();
110
+
111
+ for (int i = 0; i < len; ++i) {
112
+ v8::Local<v8::String> key = pairs[i].GetName(isolate);
113
+
114
+ // Check if the named parameter was provided.
115
+ v8::Maybe<bool> has_property = obj->HasOwnProperty(ctx, key);
116
+ if (has_property.IsNothing()) {
117
+ Fail(NULL, NULL);
118
+ return i;
119
+ }
120
+ if (!has_property.FromJust()) {
121
+ v8::String::Utf8Value param_name(isolate, key);
122
+ Fail(ThrowRangeError, (std::string("Missing named parameter \"") + *param_name + "\"").c_str());
123
+ return i;
124
+ }
125
+
126
+ // Get the current property value.
127
+ v8::MaybeLocal<v8::Value> maybeValue = obj->Get(ctx, key);
128
+ if (maybeValue.IsEmpty()) {
129
+ Fail(NULL, NULL);
130
+ return i;
131
+ }
132
+
133
+ BindValue(isolate, maybeValue.ToLocalChecked(), pairs[i].GetIndex());
134
+ if (!success) {
135
+ return i;
136
+ }
137
+ }
138
+
139
+ return len;
140
+ }
141
+
142
+ // Binds all parameters using the values found in the arguments object.
143
+ // Anonymous parameter values can be directly in the arguments object or in an Array.
144
+ // Named parameter values can be provided in a plain Object argument.
145
+ // Only one plain Object argument may be provided.
146
+ // If an error occurs, an appropriate error is thrown.
147
+ // The return value is a struct indicating how many parameters were successfully bound
148
+ // and whether or not it tried to bind an object.
149
+ Result BindArgs(NODE_ARGUMENTS info, int argc, Statement* stmt) {
150
+ UseIsolate;
151
+ int count = 0;
152
+ bool bound_object = false;
153
+
154
+ for (int i = 0; i < argc; ++i) {
155
+ v8::Local<v8::Value> arg = info[i];
156
+
157
+ if (arg->IsArray()) {
158
+ count += BindArray(isolate, arg.As<v8::Array>());
159
+ if (!success) break;
160
+ continue;
161
+ }
162
+
163
+ if (arg->IsObject() && !node::Buffer::HasInstance(arg)) {
164
+ v8::Local<v8::Object> obj = arg.As<v8::Object>();
165
+ if (IsPlainObject(isolate, obj)) {
166
+ if (bound_object) {
167
+ Fail(ThrowTypeError, "You cannot specify named parameters in two different objects");
168
+ break;
169
+ }
170
+ bound_object = true;
171
+
172
+ count += BindObject(isolate, obj, stmt);
173
+ if (!success) break;
174
+ continue;
175
+ } else if (stmt->GetBindMap(isolate)->GetSize()) {
176
+ Fail(ThrowTypeError, "Named parameters can only be passed within plain objects");
177
+ break;
178
+ }
179
+ }
180
+
181
+ BindValue(isolate, arg, NextAnonIndex());
182
+ if (!success) break;
183
+ count += 1;
184
+ }
185
+
186
+ return { count, bound_object };
187
+ }
188
+
189
+ sqlite3_stmt* handle;
190
+ int param_count;
191
+ int anon_index; // This value should only be used by NextAnonIndex()
192
+ bool success; // This value should only be set by Fail()
193
+ };
@@ -0,0 +1,172 @@
1
+ class CS {
2
+ public:
3
+
4
+ v8::Local<v8::String> Code(v8::Isolate* isolate, int code) {
5
+ auto element = codes.find(code);
6
+ if (element != codes.end()) return element->second.Get(isolate);
7
+ return StringFromUtf8(isolate, (std::string("UNKNOWN_SQLITE_ERROR_") + std::to_string(code)).c_str(), -1);
8
+ }
9
+
10
+ explicit CS(v8::Isolate* isolate) {
11
+ SetString(isolate, database, "database");
12
+ SetString(isolate, reader, "reader");
13
+ SetString(isolate, source, "source");
14
+ SetString(isolate, memory, "memory");
15
+ SetString(isolate, readonly, "readonly");
16
+ SetString(isolate, name, "name");
17
+ SetString(isolate, next, "next");
18
+ SetString(isolate, length, "length");
19
+ SetString(isolate, done, "done");
20
+ SetString(isolate, value, "value");
21
+ SetString(isolate, changes, "changes");
22
+ SetString(isolate, lastInsertRowid, "lastInsertRowid");
23
+ SetString(isolate, statement, "statement");
24
+ SetString(isolate, column, "column");
25
+ SetString(isolate, table, "table");
26
+ SetString(isolate, type, "type");
27
+ SetString(isolate, totalPages, "totalPages");
28
+ SetString(isolate, remainingPages, "remainingPages");
29
+
30
+ SetCode(isolate, SQLITE_OK, "SQLITE_OK");
31
+ SetCode(isolate, SQLITE_ERROR, "SQLITE_ERROR");
32
+ SetCode(isolate, SQLITE_INTERNAL, "SQLITE_INTERNAL");
33
+ SetCode(isolate, SQLITE_PERM, "SQLITE_PERM");
34
+ SetCode(isolate, SQLITE_ABORT, "SQLITE_ABORT");
35
+ SetCode(isolate, SQLITE_BUSY, "SQLITE_BUSY");
36
+ SetCode(isolate, SQLITE_LOCKED, "SQLITE_LOCKED");
37
+ SetCode(isolate, SQLITE_NOMEM, "SQLITE_NOMEM");
38
+ SetCode(isolate, SQLITE_READONLY, "SQLITE_READONLY");
39
+ SetCode(isolate, SQLITE_INTERRUPT, "SQLITE_INTERRUPT");
40
+ SetCode(isolate, SQLITE_IOERR, "SQLITE_IOERR");
41
+ SetCode(isolate, SQLITE_CORRUPT, "SQLITE_CORRUPT");
42
+ SetCode(isolate, SQLITE_NOTFOUND, "SQLITE_NOTFOUND");
43
+ SetCode(isolate, SQLITE_FULL, "SQLITE_FULL");
44
+ SetCode(isolate, SQLITE_CANTOPEN, "SQLITE_CANTOPEN");
45
+ SetCode(isolate, SQLITE_PROTOCOL, "SQLITE_PROTOCOL");
46
+ SetCode(isolate, SQLITE_EMPTY, "SQLITE_EMPTY");
47
+ SetCode(isolate, SQLITE_SCHEMA, "SQLITE_SCHEMA");
48
+ SetCode(isolate, SQLITE_TOOBIG, "SQLITE_TOOBIG");
49
+ SetCode(isolate, SQLITE_CONSTRAINT, "SQLITE_CONSTRAINT");
50
+ SetCode(isolate, SQLITE_MISMATCH, "SQLITE_MISMATCH");
51
+ SetCode(isolate, SQLITE_MISUSE, "SQLITE_MISUSE");
52
+ SetCode(isolate, SQLITE_NOLFS, "SQLITE_NOLFS");
53
+ SetCode(isolate, SQLITE_AUTH, "SQLITE_AUTH");
54
+ SetCode(isolate, SQLITE_FORMAT, "SQLITE_FORMAT");
55
+ SetCode(isolate, SQLITE_RANGE, "SQLITE_RANGE");
56
+ SetCode(isolate, SQLITE_NOTADB, "SQLITE_NOTADB");
57
+ SetCode(isolate, SQLITE_NOTICE, "SQLITE_NOTICE");
58
+ SetCode(isolate, SQLITE_WARNING, "SQLITE_WARNING");
59
+ SetCode(isolate, SQLITE_ROW, "SQLITE_ROW");
60
+ SetCode(isolate, SQLITE_DONE, "SQLITE_DONE");
61
+
62
+ SetCode(isolate, SQLITE_ERROR_MISSING_COLLSEQ, "SQLITE_ERROR_MISSING_COLLSEQ");
63
+ SetCode(isolate, SQLITE_ERROR_RETRY, "SQLITE_ERROR_RETRY");
64
+ SetCode(isolate, SQLITE_ERROR_SNAPSHOT, "SQLITE_ERROR_SNAPSHOT");
65
+ SetCode(isolate, SQLITE_IOERR_READ, "SQLITE_IOERR_READ");
66
+ SetCode(isolate, SQLITE_IOERR_SHORT_READ, "SQLITE_IOERR_SHORT_READ");
67
+ SetCode(isolate, SQLITE_IOERR_WRITE, "SQLITE_IOERR_WRITE");
68
+ SetCode(isolate, SQLITE_IOERR_FSYNC, "SQLITE_IOERR_FSYNC");
69
+ SetCode(isolate, SQLITE_IOERR_DIR_FSYNC, "SQLITE_IOERR_DIR_FSYNC");
70
+ SetCode(isolate, SQLITE_IOERR_TRUNCATE, "SQLITE_IOERR_TRUNCATE");
71
+ SetCode(isolate, SQLITE_IOERR_FSTAT, "SQLITE_IOERR_FSTAT");
72
+ SetCode(isolate, SQLITE_IOERR_UNLOCK, "SQLITE_IOERR_UNLOCK");
73
+ SetCode(isolate, SQLITE_IOERR_RDLOCK, "SQLITE_IOERR_RDLOCK");
74
+ SetCode(isolate, SQLITE_IOERR_DELETE, "SQLITE_IOERR_DELETE");
75
+ SetCode(isolate, SQLITE_IOERR_BLOCKED, "SQLITE_IOERR_BLOCKED");
76
+ SetCode(isolate, SQLITE_IOERR_NOMEM, "SQLITE_IOERR_NOMEM");
77
+ SetCode(isolate, SQLITE_IOERR_ACCESS, "SQLITE_IOERR_ACCESS");
78
+ SetCode(isolate, SQLITE_IOERR_CHECKRESERVEDLOCK, "SQLITE_IOERR_CHECKRESERVEDLOCK");
79
+ SetCode(isolate, SQLITE_IOERR_LOCK, "SQLITE_IOERR_LOCK");
80
+ SetCode(isolate, SQLITE_IOERR_CLOSE, "SQLITE_IOERR_CLOSE");
81
+ SetCode(isolate, SQLITE_IOERR_DIR_CLOSE, "SQLITE_IOERR_DIR_CLOSE");
82
+ SetCode(isolate, SQLITE_IOERR_SHMOPEN, "SQLITE_IOERR_SHMOPEN");
83
+ SetCode(isolate, SQLITE_IOERR_SHMSIZE, "SQLITE_IOERR_SHMSIZE");
84
+ SetCode(isolate, SQLITE_IOERR_SHMLOCK, "SQLITE_IOERR_SHMLOCK");
85
+ SetCode(isolate, SQLITE_IOERR_SHMMAP, "SQLITE_IOERR_SHMMAP");
86
+ SetCode(isolate, SQLITE_IOERR_SEEK, "SQLITE_IOERR_SEEK");
87
+ SetCode(isolate, SQLITE_IOERR_DELETE_NOENT, "SQLITE_IOERR_DELETE_NOENT");
88
+ SetCode(isolate, SQLITE_IOERR_MMAP, "SQLITE_IOERR_MMAP");
89
+ SetCode(isolate, SQLITE_IOERR_GETTEMPPATH, "SQLITE_IOERR_GETTEMPPATH");
90
+ SetCode(isolate, SQLITE_IOERR_CONVPATH, "SQLITE_IOERR_CONVPATH");
91
+ SetCode(isolate, SQLITE_IOERR_VNODE, "SQLITE_IOERR_VNODE");
92
+ SetCode(isolate, SQLITE_IOERR_AUTH, "SQLITE_IOERR_AUTH");
93
+ SetCode(isolate, SQLITE_IOERR_BEGIN_ATOMIC, "SQLITE_IOERR_BEGIN_ATOMIC");
94
+ SetCode(isolate, SQLITE_IOERR_COMMIT_ATOMIC, "SQLITE_IOERR_COMMIT_ATOMIC");
95
+ SetCode(isolate, SQLITE_IOERR_ROLLBACK_ATOMIC, "SQLITE_IOERR_ROLLBACK_ATOMIC");
96
+ SetCode(isolate, SQLITE_IOERR_DATA, "SQLITE_IOERR_DATA");
97
+ SetCode(isolate, SQLITE_IOERR_CORRUPTFS, "SQLITE_IOERR_CORRUPTFS");
98
+ SetCode(isolate, SQLITE_IOERR_IN_PAGE, "SQLITE_IOERR_IN_PAGE");
99
+ SetCode(isolate, SQLITE_LOCKED_SHAREDCACHE, "SQLITE_LOCKED_SHAREDCACHE");
100
+ SetCode(isolate, SQLITE_LOCKED_VTAB, "SQLITE_LOCKED_VTAB");
101
+ SetCode(isolate, SQLITE_BUSY_RECOVERY, "SQLITE_BUSY_RECOVERY");
102
+ SetCode(isolate, SQLITE_BUSY_SNAPSHOT, "SQLITE_BUSY_SNAPSHOT");
103
+ SetCode(isolate, SQLITE_CANTOPEN_NOTEMPDIR, "SQLITE_CANTOPEN_NOTEMPDIR");
104
+ SetCode(isolate, SQLITE_CANTOPEN_ISDIR, "SQLITE_CANTOPEN_ISDIR");
105
+ SetCode(isolate, SQLITE_CANTOPEN_FULLPATH, "SQLITE_CANTOPEN_FULLPATH");
106
+ SetCode(isolate, SQLITE_CANTOPEN_CONVPATH, "SQLITE_CANTOPEN_CONVPATH");
107
+ SetCode(isolate, SQLITE_CANTOPEN_DIRTYWAL, "SQLITE_CANTOPEN_DIRTYWAL");
108
+ SetCode(isolate, SQLITE_CANTOPEN_SYMLINK, "SQLITE_CANTOPEN_SYMLINK");
109
+ SetCode(isolate, SQLITE_CORRUPT_VTAB, "SQLITE_CORRUPT_VTAB");
110
+ SetCode(isolate, SQLITE_CORRUPT_SEQUENCE, "SQLITE_CORRUPT_SEQUENCE");
111
+ SetCode(isolate, SQLITE_CORRUPT_INDEX, "SQLITE_CORRUPT_INDEX");
112
+ SetCode(isolate, SQLITE_READONLY_RECOVERY, "SQLITE_READONLY_RECOVERY");
113
+ SetCode(isolate, SQLITE_READONLY_CANTLOCK, "SQLITE_READONLY_CANTLOCK");
114
+ SetCode(isolate, SQLITE_READONLY_ROLLBACK, "SQLITE_READONLY_ROLLBACK");
115
+ SetCode(isolate, SQLITE_READONLY_DBMOVED, "SQLITE_READONLY_DBMOVED");
116
+ SetCode(isolate, SQLITE_READONLY_CANTINIT, "SQLITE_READONLY_CANTINIT");
117
+ SetCode(isolate, SQLITE_READONLY_DIRECTORY, "SQLITE_READONLY_DIRECTORY");
118
+ SetCode(isolate, SQLITE_ABORT_ROLLBACK, "SQLITE_ABORT_ROLLBACK");
119
+ SetCode(isolate, SQLITE_CONSTRAINT_CHECK, "SQLITE_CONSTRAINT_CHECK");
120
+ SetCode(isolate, SQLITE_CONSTRAINT_COMMITHOOK, "SQLITE_CONSTRAINT_COMMITHOOK");
121
+ SetCode(isolate, SQLITE_CONSTRAINT_FOREIGNKEY, "SQLITE_CONSTRAINT_FOREIGNKEY");
122
+ SetCode(isolate, SQLITE_CONSTRAINT_FUNCTION, "SQLITE_CONSTRAINT_FUNCTION");
123
+ SetCode(isolate, SQLITE_CONSTRAINT_NOTNULL, "SQLITE_CONSTRAINT_NOTNULL");
124
+ SetCode(isolate, SQLITE_CONSTRAINT_PRIMARYKEY, "SQLITE_CONSTRAINT_PRIMARYKEY");
125
+ SetCode(isolate, SQLITE_CONSTRAINT_TRIGGER, "SQLITE_CONSTRAINT_TRIGGER");
126
+ SetCode(isolate, SQLITE_CONSTRAINT_UNIQUE, "SQLITE_CONSTRAINT_UNIQUE");
127
+ SetCode(isolate, SQLITE_CONSTRAINT_VTAB, "SQLITE_CONSTRAINT_VTAB");
128
+ SetCode(isolate, SQLITE_CONSTRAINT_ROWID, "SQLITE_CONSTRAINT_ROWID");
129
+ SetCode(isolate, SQLITE_CONSTRAINT_PINNED, "SQLITE_CONSTRAINT_PINNED");
130
+ SetCode(isolate, SQLITE_CONSTRAINT_DATATYPE, "SQLITE_CONSTRAINT_DATATYPE");
131
+ SetCode(isolate, SQLITE_NOTICE_RECOVER_WAL, "SQLITE_NOTICE_RECOVER_WAL");
132
+ SetCode(isolate, SQLITE_NOTICE_RECOVER_ROLLBACK, "SQLITE_NOTICE_RECOVER_ROLLBACK");
133
+ SetCode(isolate, SQLITE_NOTICE_RBU, "SQLITE_NOTICE_RBU");
134
+ SetCode(isolate, SQLITE_WARNING_AUTOINDEX, "SQLITE_WARNING_AUTOINDEX");
135
+ SetCode(isolate, SQLITE_AUTH_USER, "SQLITE_AUTH_USER");
136
+ SetCode(isolate, SQLITE_OK_LOAD_PERMANENTLY, "SQLITE_OK_LOAD_PERMANENTLY");
137
+ SetCode(isolate, SQLITE_OK_SYMLINK, "SQLITE_OK_SYMLINK");
138
+ }
139
+
140
+ v8::Global<v8::String> database;
141
+ v8::Global<v8::String> reader;
142
+ v8::Global<v8::String> source;
143
+ v8::Global<v8::String> memory;
144
+ v8::Global<v8::String> readonly;
145
+ v8::Global<v8::String> name;
146
+ v8::Global<v8::String> next;
147
+ v8::Global<v8::String> length;
148
+ v8::Global<v8::String> done;
149
+ v8::Global<v8::String> value;
150
+ v8::Global<v8::String> changes;
151
+ v8::Global<v8::String> lastInsertRowid;
152
+ v8::Global<v8::String> statement;
153
+ v8::Global<v8::String> column;
154
+ v8::Global<v8::String> table;
155
+ v8::Global<v8::String> type;
156
+ v8::Global<v8::String> totalPages;
157
+ v8::Global<v8::String> remainingPages;
158
+
159
+ private:
160
+
161
+ static void SetString(v8::Isolate* isolate, v8::Global<v8::String>& constant, const char* str) {
162
+ constant.Reset(isolate, InternalizedFromLatin1(isolate, str));
163
+ }
164
+
165
+ void SetCode(v8::Isolate* isolate, int code, const char* str) {
166
+ codes.emplace(std::piecewise_construct,
167
+ std::forward_as_tuple(code),
168
+ std::forward_as_tuple(isolate, InternalizedFromLatin1(isolate, str)));
169
+ }
170
+
171
+ std::unordered_map<int, v8::Global<v8::String> > codes;
172
+ };
@@ -0,0 +1,121 @@
1
+ class CustomAggregate : public CustomFunction {
2
+ public:
3
+
4
+ explicit CustomAggregate(
5
+ v8::Isolate* isolate,
6
+ Database* db,
7
+ const char* name,
8
+ v8::Local<v8::Value> start,
9
+ v8::Local<v8::Function> step,
10
+ v8::Local<v8::Value> inverse,
11
+ v8::Local<v8::Value> result,
12
+ bool safe_ints
13
+ ) :
14
+ CustomFunction(isolate, db, name, step, safe_ints),
15
+ invoke_result(result->IsFunction()),
16
+ invoke_start(start->IsFunction()),
17
+ inverse(isolate, inverse->IsFunction() ? inverse.As<v8::Function>() : v8::Local<v8::Function>()),
18
+ result(isolate, result->IsFunction() ? result.As<v8::Function>() : v8::Local<v8::Function>()),
19
+ start(isolate, 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 v8::Global<v8::Function> CustomAggregate::*ptrtm) {
40
+ AGGREGATE_START();
41
+
42
+ v8::Local<v8::Value> args_fast[5];
43
+ v8::Local<v8::Value>* args = argc <= 4 ? args_fast : ALLOC_ARRAY<v8::Local<v8::Value>>(argc + 1);
44
+ args[0] = acc->value.Get(isolate);
45
+ if (argc != 0) Data::GetArgumentsJS(isolate, args + 1, argv, argc, self->safe_ints);
46
+
47
+ v8::MaybeLocal<v8::Value> maybeReturnValue = (self->*ptrtm).Get(isolate)->Call(OnlyContext, v8::Undefined(isolate), argc + 1, args);
48
+ if (args != args_fast) delete[] args;
49
+
50
+ if (maybeReturnValue.IsEmpty()) {
51
+ self->PropagateJSError(invocation);
52
+ } else {
53
+ v8::Local<v8::Value> returnValue = maybeReturnValue.ToLocalChecked();
54
+ if (!returnValue->IsUndefined()) acc->value.Reset(isolate, returnValue);
55
+ }
56
+ }
57
+
58
+ static inline void xValueBase(sqlite3_context* invocation, bool is_final) {
59
+ AGGREGATE_START();
60
+
61
+ if (!is_final) {
62
+ acc->is_window = true;
63
+ } else if (acc->is_window) {
64
+ DestroyAccumulator(invocation);
65
+ return;
66
+ }
67
+
68
+ v8::Local<v8::Value> result = acc->value.Get(isolate);
69
+ if (self->invoke_result) {
70
+ v8::MaybeLocal<v8::Value> maybeResult = self->result.Get(isolate)->Call(OnlyContext, v8::Undefined(isolate), 1, &result);
71
+ if (maybeResult.IsEmpty()) {
72
+ self->PropagateJSError(invocation);
73
+ return;
74
+ }
75
+ result = maybeResult.ToLocalChecked();
76
+ }
77
+
78
+ Data::ResultValueFromJS(isolate, invocation, result, self);
79
+ if (is_final) DestroyAccumulator(invocation);
80
+ }
81
+
82
+ struct Accumulator { public:
83
+ v8::Global<v8::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
+ v8::MaybeLocal<v8::Value> maybeSeed = start.Get(isolate).As<v8::Function>()->Call(OnlyContext, v8::Undefined(isolate), 0, NULL);
95
+ if (maybeSeed.IsEmpty()) PropagateJSError(invocation);
96
+ else acc->value.Reset(isolate, maybeSeed.ToLocalChecked());
97
+ } else {
98
+ assert(!start.IsEmpty());
99
+ acc->value.Reset(isolate, start);
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 v8::Global<v8::Function> inverse;
119
+ const v8::Global<v8::Function> result;
120
+ const v8::Global<v8::Value> start;
121
+ };
@@ -0,0 +1,59 @@
1
+ class CustomFunction : protected DataConverter {
2
+ public:
3
+
4
+ explicit CustomFunction(
5
+ v8::Isolate* isolate,
6
+ Database* db,
7
+ const char* name,
8
+ v8::Local<v8::Function> fn,
9
+ bool safe_ints
10
+ ) :
11
+ name(name),
12
+ db(db),
13
+ isolate(isolate),
14
+ fn(isolate, 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
+ v8::Local<v8::Value> args_fast[4];
27
+ v8::Local<v8::Value>* args = NULL;
28
+ if (argc != 0) {
29
+ args = argc <= 4 ? args_fast : ALLOC_ARRAY<v8::Local<v8::Value>>(argc);
30
+ Data::GetArgumentsJS(isolate, args, argv, argc, self->safe_ints);
31
+ }
32
+
33
+ v8::MaybeLocal<v8::Value> maybeReturnValue = self->fn.Get(isolate)->Call(OnlyContext, v8::Undefined(isolate), argc, args);
34
+ if (args != args_fast) delete[] args;
35
+
36
+ if (maybeReturnValue.IsEmpty()) self->PropagateJSError(invocation);
37
+ else Data::ResultValueFromJS(isolate, invocation, maybeReturnValue.ToLocalChecked(), 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
+ v8::Isolate* const isolate;
57
+ const v8::Global<v8::Function> fn;
58
+ const bool safe_ints;
59
+ };