UNPKG

5.15 kBtext/x-cView Raw
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
15using namespace Napi;
16
17namespace node_sqlite3 {
18
19class Database;
20
21
22class Database : public Napi::ObjectWrap<Database> {
23public:
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
135protected:
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
169protected:
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