@homeofthings/sqlite3 0.0.1-alpha0 → 6.1.1

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/src/database.h ADDED
@@ -0,0 +1,188 @@
1
+
2
+ #ifndef NODE_SQLITE3_SRC_DATABASE_H
3
+ #define NODE_SQLITE3_SRC_DATABASE_H
4
+
5
+
6
+ #include <assert.h>
7
+ #include <string>
8
+ #include <queue>
9
+
10
+ #include <sqlite3.h>
11
+ #include <napi.h>
12
+
13
+ #include "async.h"
14
+
15
+ using namespace Napi;
16
+
17
+ namespace node_sqlite3 {
18
+
19
+ class Database;
20
+
21
+
22
+ class Database : public Napi::ObjectWrap<Database> {
23
+ public:
24
+ #if NAPI_VERSION < 6
25
+ static Napi::FunctionReference constructor;
26
+ #endif
27
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
28
+
29
+ static inline bool HasInstance(Napi::Value val) {
30
+ auto env = val.Env();
31
+ Napi::HandleScope scope(env);
32
+ if (!val.IsObject()) return false;
33
+ auto obj = val.As<Napi::Object>();
34
+ #if NAPI_VERSION < 6
35
+ return obj.InstanceOf(constructor.Value());
36
+ #else
37
+ auto constructor =
38
+ env.GetInstanceData<Napi::FunctionReference>();
39
+ return obj.InstanceOf(constructor->Value());
40
+ #endif
41
+ }
42
+
43
+ struct Baton {
44
+ napi_async_work request = NULL;
45
+ Database* db;
46
+ Napi::FunctionReference callback;
47
+ int status;
48
+ std::string message;
49
+
50
+ Baton(Database* db_, Napi::Function cb_) :
51
+ db(db_), status(SQLITE_OK) {
52
+ db->Ref();
53
+ if (!cb_.IsUndefined() && cb_.IsFunction()) {
54
+ callback.Reset(cb_, 1);
55
+ }
56
+ }
57
+ virtual ~Baton() {
58
+ if (request) napi_delete_async_work(db->Env(), request);
59
+ db->Unref();
60
+ callback.Reset();
61
+ }
62
+ };
63
+
64
+ struct OpenBaton : Baton {
65
+ std::string filename;
66
+ int mode;
67
+ OpenBaton(Database* db_, Napi::Function cb_, const char* filename_, int mode_) :
68
+ Baton(db_, cb_), filename(filename_), mode(mode_) {}
69
+ virtual ~OpenBaton() override = default;
70
+ };
71
+
72
+ struct ExecBaton : Baton {
73
+ std::string sql;
74
+ ExecBaton(Database* db_, Napi::Function cb_, const char* sql_) :
75
+ Baton(db_, cb_), sql(sql_) {}
76
+ virtual ~ExecBaton() override = default;
77
+ };
78
+
79
+ struct LoadExtensionBaton : Baton {
80
+ std::string filename;
81
+ LoadExtensionBaton(Database* db_, Napi::Function cb_, const char* filename_) :
82
+ Baton(db_, cb_), filename(filename_) {}
83
+ virtual ~LoadExtensionBaton() override = default;
84
+ };
85
+
86
+ struct LimitBaton : Baton {
87
+ int id;
88
+ int value;
89
+ LimitBaton(Database* db_, Napi::Function cb_, int id_, int value_) :
90
+ Baton(db_, cb_), id(id_), value(value_) {}
91
+ virtual ~LimitBaton() override = default;
92
+ };
93
+
94
+ typedef void (*Work_Callback)(Baton* baton);
95
+
96
+ struct Call {
97
+ Call(Work_Callback cb_, Baton* baton_, bool exclusive_ = false) :
98
+ callback(cb_), exclusive(exclusive_), baton(baton_) {};
99
+ Work_Callback callback;
100
+ bool exclusive;
101
+ Baton* baton;
102
+ };
103
+
104
+ struct ProfileInfo {
105
+ std::string sql;
106
+ sqlite3_int64 nsecs;
107
+ };
108
+
109
+ struct UpdateInfo {
110
+ int type;
111
+ std::string database;
112
+ std::string table;
113
+ sqlite3_int64 rowid;
114
+ };
115
+
116
+ bool IsOpen() { return open; }
117
+ bool IsLocked() { return locked; }
118
+
119
+ typedef Async<std::string, Database> AsyncTrace;
120
+ typedef Async<ProfileInfo, Database> AsyncProfile;
121
+ typedef Async<UpdateInfo, Database> AsyncUpdate;
122
+
123
+ friend class Statement;
124
+ friend class Backup;
125
+
126
+ Database(const Napi::CallbackInfo& info);
127
+
128
+ ~Database() {
129
+ RemoveCallbacks();
130
+ sqlite3_close(_handle);
131
+ _handle = NULL;
132
+ open = false;
133
+ }
134
+
135
+ protected:
136
+ WORK_DEFINITION(Open);
137
+ WORK_DEFINITION(Exec);
138
+ WORK_DEFINITION(Close);
139
+ WORK_DEFINITION(LoadExtension);
140
+
141
+ void Schedule(Work_Callback callback, Baton* baton, bool exclusive = false);
142
+ void Process();
143
+
144
+ Napi::Value Wait(const Napi::CallbackInfo& info);
145
+ static void Work_Wait(Baton* baton);
146
+
147
+ Napi::Value Serialize(const Napi::CallbackInfo& info);
148
+ Napi::Value Parallelize(const Napi::CallbackInfo& info);
149
+ Napi::Value Configure(const Napi::CallbackInfo& info);
150
+ Napi::Value Interrupt(const Napi::CallbackInfo& info);
151
+
152
+ static void SetBusyTimeout(Baton* baton);
153
+ static void SetLimit(Baton* baton);
154
+
155
+ static void RegisterTraceCallback(Baton* baton);
156
+ static void TraceCallback(void* db, const char* sql);
157
+ static void TraceCallback(Database* db, std::string* sql);
158
+
159
+ static void RegisterProfileCallback(Baton* baton);
160
+ static void ProfileCallback(void* db, const char* sql, sqlite3_uint64 nsecs);
161
+ static void ProfileCallback(Database* db, ProfileInfo* info);
162
+
163
+ static void RegisterUpdateCallback(Baton* baton);
164
+ static void UpdateCallback(void* db, int type, const char* database, const char* table, sqlite3_int64 rowid);
165
+ static void UpdateCallback(Database* db, UpdateInfo* info);
166
+
167
+ void RemoveCallbacks();
168
+
169
+ protected:
170
+ sqlite3* _handle = NULL;
171
+
172
+ bool open = false;
173
+ bool closing = false;
174
+ bool locked = false;
175
+ unsigned int pending = 0;
176
+
177
+ bool serialize = false;
178
+
179
+ std::queue<Call*> queue;
180
+
181
+ AsyncTrace* debug_trace = NULL;
182
+ AsyncProfile* debug_profile = NULL;
183
+ AsyncUpdate* update_event = NULL;
184
+ };
185
+
186
+ }
187
+
188
+ #endif
@@ -0,0 +1,31 @@
1
+ // http://web.archive.org/web/20140401031018/http://rjpower9000.wordpress.com:80/2012/04/09/fun-with-shared-libraries-version-glibc_2-14-not-found/
2
+
3
+ #if defined(__linux__)
4
+
5
+ #define _GNU_SOURCE
6
+ #include <features.h>
7
+ #include <unistd.h>
8
+ #undef _GNU_SOURCE
9
+
10
+ #if defined(__GLIBC__)
11
+
12
+ #if defined(__x86_64__)
13
+ __asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
14
+ __asm__(".symver exp,exp@GLIBC_2.2.5");
15
+ __asm__(".symver log,log@GLIBC_2.2.5");
16
+ __asm__(".symver log2,log2@GLIBC_2.2.5");
17
+ __asm__(".symver pow,pow@GLIBC_2.2.5");
18
+ __asm__(".symver fcntl64,fcntl@GLIBC_2.2.5");
19
+ #endif
20
+
21
+ #if defined(__aarch64__) || defined(_M_ARM64)
22
+ __asm__(".symver memcpy,memcpy@GLIBC_2.17");
23
+ __asm__(".symver exp,exp@GLIBC_2.17");
24
+ __asm__(".symver log,log@GLIBC_2.17");
25
+ __asm__(".symver log2,log2@GLIBC_2.17");
26
+ __asm__(".symver pow,pow@GLIBC_2.17");
27
+ __asm__(".symver fcntl64,fcntl@GLIBC_2.17");
28
+ #endif
29
+
30
+ #endif
31
+ #endif
package/src/macros.h ADDED
@@ -0,0 +1,207 @@
1
+ #ifndef NODE_SQLITE3_SRC_MACROS_H
2
+ #define NODE_SQLITE3_SRC_MACROS_H
3
+
4
+ const char* sqlite_code_string(int code);
5
+ const char* sqlite_authorizer_string(int type);
6
+ #include <vector>
7
+
8
+ // TODO: better way to work around StringConcat?
9
+ #include <napi.h>
10
+ inline Napi::String StringConcat(Napi::Value str1, Napi::Value str2) {
11
+ return Napi::String::New(str1.Env(), str1.As<Napi::String>().Utf8Value() +
12
+ str2.As<Napi::String>().Utf8Value() );
13
+ }
14
+
15
+ // A Napi substitute IsInt32()
16
+ inline bool OtherIsInt(Napi::Number source) {
17
+ double orig_val = source.DoubleValue();
18
+ double int_val = static_cast<double>(source.Int32Value());
19
+ if (orig_val == int_val) {
20
+ return true;
21
+ } else {
22
+ return false;
23
+ }
24
+ }
25
+
26
+ #define IS_FUNCTION(cb) \
27
+ !cb.IsUndefined() && cb.IsFunction()
28
+
29
+ #define REQUIRE_ARGUMENTS(n) \
30
+ if (info.Length() < (n)) { \
31
+ Napi::TypeError::New(env, "Expected " #n "arguments").ThrowAsJavaScriptException(); \
32
+ return env.Null(); \
33
+ }
34
+
35
+
36
+ #define REQUIRE_ARGUMENT_EXTERNAL(i, var) \
37
+ if (info.Length() <= (i) || !info[i].IsExternal()) { \
38
+ Napi::TypeError::New(env, "Argument " #i " invalid").ThrowAsJavaScriptException(); \
39
+ return env.Null(); \
40
+ } \
41
+ Napi::External var = info[i].As<Napi::External>();
42
+
43
+
44
+ #define REQUIRE_ARGUMENT_FUNCTION(i, var) \
45
+ if (info.Length() <= (i) || !info[i].IsFunction()) { \
46
+ Napi::TypeError::New(env, "Argument " #i " must be a function").ThrowAsJavaScriptException(); \
47
+ return env.Null(); \
48
+ } \
49
+ Napi::Function var = info[i].As<Napi::Function>();
50
+
51
+
52
+ #define REQUIRE_ARGUMENT_STRING(i, var) \
53
+ if (info.Length() <= (i) || !info[i].IsString()) { \
54
+ Napi::TypeError::New(env, "Argument " #i " must be a string").ThrowAsJavaScriptException(); \
55
+ return env.Null(); \
56
+ } \
57
+ std::string var = info[i].As<Napi::String>();
58
+
59
+ #define REQUIRE_ARGUMENT_INTEGER(i, var) \
60
+ if (info.Length() <= (i) || !info[i].IsNumber()) { \
61
+ Napi::TypeError::New(env, "Argument " #i " must be an integer").ThrowAsJavaScriptException(); \
62
+ return env.Null(); \
63
+ } \
64
+ int var(info[i].As<Napi::Number>().Int32Value());
65
+
66
+ #define OPTIONAL_ARGUMENT_FUNCTION(i, var) \
67
+ Napi::Function var; \
68
+ if (info.Length() > i && !info[i].IsUndefined()) { \
69
+ if (!info[i].IsFunction()) { \
70
+ Napi::TypeError::New(env, "Argument " #i " must be a function").ThrowAsJavaScriptException(); \
71
+ return env.Null(); \
72
+ } \
73
+ var = info[i].As<Napi::Function>(); \
74
+ }
75
+
76
+
77
+ #define OPTIONAL_ARGUMENT_INTEGER(i, var, default) \
78
+ int var; \
79
+ if (info.Length() <= (i)) { \
80
+ var = (default); \
81
+ } \
82
+ else if (info[i].IsNumber()) { \
83
+ if (OtherIsInt(info[i].As<Number>())) { \
84
+ var = info[i].As<Napi::Number>().Int32Value(); \
85
+ } \
86
+ } \
87
+ else { \
88
+ Napi::TypeError::New(env, "Argument " #i " must be an integer").ThrowAsJavaScriptException(); \
89
+ return env.Null(); \
90
+ }
91
+
92
+
93
+ #define DEFINE_CONSTANT_INTEGER(target, constant, name) \
94
+ Napi::PropertyDescriptor::Value(#name, Napi::Number::New(env, constant), \
95
+ static_cast<napi_property_attributes>(napi_enumerable | napi_configurable)),
96
+
97
+ #define DEFINE_CONSTANT_STRING(target, constant, name) \
98
+ Napi::PropertyDescriptor::Value(#name, Napi::String::New(env, constant), \
99
+ static_cast<napi_property_attributes>(napi_enumerable | napi_configurable)),
100
+
101
+ #define EXCEPTION(msg, errno, name) \
102
+ Napi::Value name = Napi::Error::New(env, \
103
+ StringConcat( \
104
+ StringConcat( \
105
+ Napi::String::New(env, sqlite_code_string(errno)), \
106
+ Napi::String::New(env, ": ") \
107
+ ), \
108
+ (msg) \
109
+ ).Utf8Value() \
110
+ ).Value(); \
111
+ Napi::Object name ##_obj = name.As<Napi::Object>(); \
112
+ (name ##_obj).Set( Napi::String::New(env, "errno"), Napi::Number::New(env, errno)); \
113
+ (name ##_obj).Set( Napi::String::New(env, "code"), \
114
+ Napi::String::New(env, sqlite_code_string(errno)));
115
+
116
+
117
+ #define EMIT_EVENT(obj, argc, argv) \
118
+ TRY_CATCH_CALL((obj), \
119
+ (obj).Get("emit").As<Napi::Function>(),\
120
+ argc, argv \
121
+ );
122
+
123
+ // The Mac OS compiler complains when argv is NULL unless we
124
+ // first assign it to a locally defined variable.
125
+ #define TRY_CATCH_CALL(context, callback, argc, argv, ...) \
126
+ Napi::Value* passed_argv = argv;\
127
+ std::vector<napi_value> args;\
128
+ if ((argc != 0) && (passed_argv != NULL)) {\
129
+ args.assign(passed_argv, passed_argv + argc);\
130
+ }\
131
+ Napi::Value res = (callback).Call(Napi::Value(context), args); \
132
+ if (res.IsEmpty()) return __VA_ARGS__;
133
+
134
+ #define WORK_DEFINITION(name) \
135
+ Napi::Value name(const Napi::CallbackInfo& info); \
136
+ static void Work_Begin##name(Baton* baton); \
137
+ static void Work_##name(napi_env env, void* data); \
138
+ static void Work_After##name(napi_env env, napi_status status, void* data);
139
+
140
+ #ifdef DEBUG
141
+ #define ASSERT_STATUS() assert(status == 0);
142
+ #else
143
+ #define ASSERT_STATUS() (void)status;
144
+ #endif
145
+
146
+ #define CREATE_WORK(name, workerFn, afterFn) \
147
+ int status = napi_create_async_work(env, NULL, Napi::String::New(env, name),\
148
+ workerFn, afterFn, baton, &baton->request); \
149
+ \
150
+ ASSERT_STATUS(); \
151
+ napi_queue_async_work(env, baton->request);
152
+
153
+ #define STATEMENT_BEGIN(type) \
154
+ assert(baton); \
155
+ assert(baton->stmt); \
156
+ assert(!baton->stmt->locked); \
157
+ assert(!baton->stmt->finalized); \
158
+ assert(baton->stmt->prepared); \
159
+ baton->stmt->locked = true; \
160
+ baton->stmt->db->pending++; \
161
+ auto env = baton->stmt->Env(); \
162
+ CREATE_WORK("sqlite3.Statement."#type, Work_##type, Work_After##type);
163
+
164
+ #define STATEMENT_INIT(type) \
165
+ type* baton = static_cast<type*>(data); \
166
+ Statement* stmt = baton->stmt;
167
+
168
+ #define STATEMENT_MUTEX(name) \
169
+ if (!stmt->db->_handle) { \
170
+ stmt->status = SQLITE_MISUSE; \
171
+ stmt->message = "Database handle is closed"; \
172
+ return; \
173
+ } \
174
+ sqlite3_mutex* name = sqlite3_db_mutex(stmt->db->_handle);
175
+
176
+ #define STATEMENT_END() \
177
+ assert(stmt->locked); \
178
+ assert(stmt->db->pending); \
179
+ stmt->locked = false; \
180
+ stmt->db->pending--; \
181
+ stmt->Process(); \
182
+ stmt->db->Process();
183
+
184
+ #define BACKUP_BEGIN(type) \
185
+ assert(baton); \
186
+ assert(baton->backup); \
187
+ assert(!baton->backup->locked); \
188
+ assert(!baton->backup->finished); \
189
+ assert(baton->backup->inited); \
190
+ baton->backup->locked = true; \
191
+ baton->backup->db->pending++; \
192
+ auto env = baton->backup->Env(); \
193
+ CREATE_WORK("sqlite3.Backup."#type, Work_##type, Work_After##type);
194
+
195
+ #define BACKUP_INIT(type) \
196
+ type* baton = static_cast<type*>(data); \
197
+ Backup* backup = baton->backup;
198
+
199
+ #define BACKUP_END() \
200
+ assert(backup->locked); \
201
+ assert(backup->db->pending); \
202
+ backup->locked = false; \
203
+ backup->db->pending--; \
204
+ backup->Process(); \
205
+ backup->db->Process();
206
+
207
+ #endif
@@ -0,0 +1,128 @@
1
+ #include <stdint.h>
2
+ #include <sstream>
3
+ #include <cstring>
4
+ #include <string>
5
+ #include <sqlite3.h>
6
+
7
+ #include "macros.h"
8
+ #include "database.h"
9
+ #include "statement.h"
10
+ #include "backup.h"
11
+
12
+ using namespace node_sqlite3;
13
+
14
+ namespace {
15
+
16
+ Napi::Object RegisterModule(Napi::Env env, Napi::Object exports) {
17
+ Napi::HandleScope scope(env);
18
+
19
+ Database::Init(env, exports);
20
+ Statement::Init(env, exports);
21
+ Backup::Init(env, exports);
22
+
23
+ exports.DefineProperties({
24
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_READONLY, OPEN_READONLY)
25
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_READWRITE, OPEN_READWRITE)
26
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_CREATE, OPEN_CREATE)
27
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_FULLMUTEX, OPEN_FULLMUTEX)
28
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_URI, OPEN_URI)
29
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_SHAREDCACHE, OPEN_SHAREDCACHE)
30
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_OPEN_PRIVATECACHE, OPEN_PRIVATECACHE)
31
+ DEFINE_CONSTANT_STRING(exports, SQLITE_VERSION, VERSION)
32
+ #ifdef SQLITE_SOURCE_ID
33
+ DEFINE_CONSTANT_STRING(exports, SQLITE_SOURCE_ID, SOURCE_ID)
34
+ #endif
35
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_VERSION_NUMBER, VERSION_NUMBER)
36
+
37
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_OK, OK)
38
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_ERROR, ERROR)
39
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_INTERNAL, INTERNAL)
40
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_PERM, PERM)
41
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_ABORT, ABORT)
42
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_BUSY, BUSY)
43
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LOCKED, LOCKED)
44
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_NOMEM, NOMEM)
45
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_READONLY, READONLY)
46
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_INTERRUPT, INTERRUPT)
47
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_IOERR, IOERR)
48
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_CORRUPT, CORRUPT)
49
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_NOTFOUND, NOTFOUND)
50
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_FULL, FULL)
51
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_CANTOPEN, CANTOPEN)
52
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_PROTOCOL, PROTOCOL)
53
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_EMPTY, EMPTY)
54
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_SCHEMA, SCHEMA)
55
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_TOOBIG, TOOBIG)
56
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_CONSTRAINT, CONSTRAINT)
57
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_MISMATCH, MISMATCH)
58
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_MISUSE, MISUSE)
59
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_NOLFS, NOLFS)
60
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_AUTH, AUTH)
61
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_FORMAT, FORMAT)
62
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_RANGE, RANGE)
63
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_NOTADB, NOTADB)
64
+
65
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_LENGTH, LIMIT_LENGTH)
66
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_SQL_LENGTH, LIMIT_SQL_LENGTH)
67
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_COLUMN, LIMIT_COLUMN)
68
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_EXPR_DEPTH, LIMIT_EXPR_DEPTH)
69
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_COMPOUND_SELECT, LIMIT_COMPOUND_SELECT)
70
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_VDBE_OP, LIMIT_VDBE_OP)
71
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_FUNCTION_ARG, LIMIT_FUNCTION_ARG)
72
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_ATTACHED, LIMIT_ATTACHED)
73
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, LIMIT_LIKE_PATTERN_LENGTH)
74
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_VARIABLE_NUMBER, LIMIT_VARIABLE_NUMBER)
75
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_TRIGGER_DEPTH, LIMIT_TRIGGER_DEPTH)
76
+ DEFINE_CONSTANT_INTEGER(exports, SQLITE_LIMIT_WORKER_THREADS, LIMIT_WORKER_THREADS)
77
+ });
78
+
79
+ return exports;
80
+ }
81
+
82
+ }
83
+
84
+ const char* sqlite_code_string(int code) {
85
+ switch (code) {
86
+ case SQLITE_OK: return "SQLITE_OK";
87
+ case SQLITE_ERROR: return "SQLITE_ERROR";
88
+ case SQLITE_INTERNAL: return "SQLITE_INTERNAL";
89
+ case SQLITE_PERM: return "SQLITE_PERM";
90
+ case SQLITE_ABORT: return "SQLITE_ABORT";
91
+ case SQLITE_BUSY: return "SQLITE_BUSY";
92
+ case SQLITE_LOCKED: return "SQLITE_LOCKED";
93
+ case SQLITE_NOMEM: return "SQLITE_NOMEM";
94
+ case SQLITE_READONLY: return "SQLITE_READONLY";
95
+ case SQLITE_INTERRUPT: return "SQLITE_INTERRUPT";
96
+ case SQLITE_IOERR: return "SQLITE_IOERR";
97
+ case SQLITE_CORRUPT: return "SQLITE_CORRUPT";
98
+ case SQLITE_NOTFOUND: return "SQLITE_NOTFOUND";
99
+ case SQLITE_FULL: return "SQLITE_FULL";
100
+ case SQLITE_CANTOPEN: return "SQLITE_CANTOPEN";
101
+ case SQLITE_PROTOCOL: return "SQLITE_PROTOCOL";
102
+ case SQLITE_EMPTY: return "SQLITE_EMPTY";
103
+ case SQLITE_SCHEMA: return "SQLITE_SCHEMA";
104
+ case SQLITE_TOOBIG: return "SQLITE_TOOBIG";
105
+ case SQLITE_CONSTRAINT: return "SQLITE_CONSTRAINT";
106
+ case SQLITE_MISMATCH: return "SQLITE_MISMATCH";
107
+ case SQLITE_MISUSE: return "SQLITE_MISUSE";
108
+ case SQLITE_NOLFS: return "SQLITE_NOLFS";
109
+ case SQLITE_AUTH: return "SQLITE_AUTH";
110
+ case SQLITE_FORMAT: return "SQLITE_FORMAT";
111
+ case SQLITE_RANGE: return "SQLITE_RANGE";
112
+ case SQLITE_NOTADB: return "SQLITE_NOTADB";
113
+ case SQLITE_ROW: return "SQLITE_ROW";
114
+ case SQLITE_DONE: return "SQLITE_DONE";
115
+ default: return "UNKNOWN";
116
+ }
117
+ }
118
+
119
+ const char* sqlite_authorizer_string(int type) {
120
+ switch (type) {
121
+ case SQLITE_INSERT: return "insert";
122
+ case SQLITE_UPDATE: return "update";
123
+ case SQLITE_DELETE: return "delete";
124
+ default: return "";
125
+ }
126
+ }
127
+
128
+ NODE_API_MODULE(node_sqlite3, RegisterModule)