1 #include "dbd_sqlite3.h"
2
3 int dbd_sqlite3_statement_create(lua_State *L, connection_t *conn, const char *sql_query);
4
run(connection_t * conn,const char * command)5 static int run(connection_t *conn, const char *command) {
6 int res = sqlite3_exec(conn->sqlite, command, NULL, NULL, NULL);
7
8 return res != SQLITE_OK;
9 }
10
commit(connection_t * conn)11 static int commit(connection_t *conn) {
12 return run(conn, "COMMIT TRANSACTION");
13 }
14
15
begin(connection_t * conn)16 static int begin(connection_t *conn) {
17 int err = 0;
18
19 if (sqlite3_get_autocommit(conn->sqlite)) {
20 err = run(conn, "BEGIN TRANSACTION");
21 } else {
22 err = 0;
23 }
24
25 return err;
26 }
27
rollback(connection_t * conn)28 static int rollback(connection_t *conn) {
29 return run(conn, "ROLLBACK TRANSACTION");
30 }
31
try_begin_transaction(connection_t * conn)32 int try_begin_transaction(connection_t *conn) {
33 if (conn->autocommit) {
34 return 1;
35 }
36
37 return begin(conn) == 0;
38 }
39
40 /*
41 * connection,err = DBD.SQLite3.New(dbfile)
42 */
connection_new(lua_State * L)43 static int connection_new(lua_State *L) {
44 int n = lua_gettop(L);
45
46 const char *db = NULL;
47 connection_t *conn = NULL;
48
49 /* db */
50 switch(n) {
51 default:
52 /*
53 * db is the only mandatory parameter
54 */
55 db = luaL_checkstring(L, 1);
56 }
57
58 int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
59 if (n >= 2) {
60 if (!lua_isnil(L, 2))
61 flags = luaL_checkinteger(L, 2);
62 }
63
64 conn = (connection_t *)lua_newuserdata(L, sizeof(connection_t));
65
66 if (sqlite3_open_v2(db, &conn->sqlite, flags, NULL) != SQLITE_OK) {
67 lua_pushnil(L);
68 lua_pushfstring(L, DBI_ERR_CONNECTION_FAILED, sqlite3_errmsg(conn->sqlite));
69 return 2;
70 }
71
72 conn->autocommit = 0;
73
74 luaL_getmetatable(L, DBD_SQLITE_CONNECTION);
75 lua_setmetatable(L, -2);
76
77 return 1;
78 }
79
80 /*
81 * success = connection:autocommit(on)
82 */
connection_autocommit(lua_State * L)83 static int connection_autocommit(lua_State *L) {
84 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
85 int on = lua_toboolean(L, 2);
86 int err = 1;
87
88 if (conn->sqlite) {
89 if (on) {
90 err = rollback(conn);
91 }
92
93 conn->autocommit = on;
94 }
95
96 lua_pushboolean(L, !err);
97 return 1;
98 }
99
100
101 /*
102 * success = connection:close()
103 */
connection_close(lua_State * L)104 static int connection_close(lua_State *L) {
105 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
106 int disconnect = 0;
107
108 if (conn->sqlite) {
109 rollback(conn);
110 sqlite3_close(conn->sqlite);
111 disconnect = 1;
112 conn->sqlite = NULL;
113 }
114
115 lua_pushboolean(L, disconnect);
116 return 1;
117 }
118
119 /*
120 * success = connection:commit()
121 */
connection_commit(lua_State * L)122 static int connection_commit(lua_State *L) {
123 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
124 int err = 1;
125
126 if (conn->sqlite) {
127 err = commit(conn);
128 }
129
130 lua_pushboolean(L, !err);
131 return 1;
132 }
133
134 /*
135 * ok = connection:ping()
136 */
connection_ping(lua_State * L)137 static int connection_ping(lua_State *L) {
138 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
139 int ok = 0;
140
141 if (conn->sqlite) {
142 ok = 1;
143 }
144
145 lua_pushboolean(L, ok);
146 return 1;
147 }
148
149 /*
150 * statement,err = connection:prepare(sql_str)
151 */
connection_prepare(lua_State * L)152 static int connection_prepare(lua_State *L) {
153 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
154
155 if (conn->sqlite) {
156 return dbd_sqlite3_statement_create(L, conn, luaL_checkstring(L, 2));
157 }
158
159 lua_pushnil(L);
160 lua_pushstring(L, DBI_ERR_DB_UNAVAILABLE);
161 return 2;
162 }
163
164 /*
165 * quoted = connection:quote(str)
166 */
connection_quote(lua_State * L)167 static int connection_quote(lua_State *L) {
168 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
169 size_t len;
170 const char *from = luaL_checklstring(L, 2, &len);
171 char *to;
172
173 if (!conn->sqlite) {
174 luaL_error(L, DBI_ERR_DB_UNAVAILABLE);
175 }
176
177 to = sqlite3_mprintf("%q", from);
178
179 lua_pushstring(L, to);
180 sqlite3_free(to);
181
182 return 1;
183 }
184
185 /*
186 * success = connection:rollback()
187 */
connection_rollback(lua_State * L)188 static int connection_rollback(lua_State *L) {
189 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
190 int err = 1;
191
192 if (conn->sqlite) {
193 err =rollback(conn);
194 }
195
196 lua_pushboolean(L, !err);
197 return 1;
198 }
199
200 /*
201 * last_id = connection:last_id()
202 */
connection_lastid(lua_State * L)203 static int connection_lastid(lua_State *L) {
204 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
205
206 lua_pushinteger(L, sqlite3_last_insert_rowid(conn->sqlite));
207 return 1;
208 }
209
210 /*
211 * __gc
212 */
connection_gc(lua_State * L)213 static int connection_gc(lua_State *L) {
214 /* always close the connection */
215 connection_close(L);
216
217 return 0;
218 }
219
220 /*
221 * __tostring
222 */
connection_tostring(lua_State * L)223 static int connection_tostring(lua_State *L) {
224 connection_t *conn = (connection_t *)luaL_checkudata(L, 1, DBD_SQLITE_CONNECTION);
225
226 lua_pushfstring(L, "%s: %p", DBD_SQLITE_CONNECTION, conn);
227
228 return 1;
229 }
230
dbd_sqlite3_connection(lua_State * L)231 int dbd_sqlite3_connection(lua_State *L) {
232 /*
233 * instance methods
234 */
235 static const luaL_Reg connection_methods[] = {
236 {"autocommit", connection_autocommit},
237 {"close", connection_close},
238 {"commit", connection_commit},
239 {"ping", connection_ping},
240 {"prepare", connection_prepare},
241 {"quote", connection_quote},
242 {"rollback", connection_rollback},
243 {"last_id", connection_lastid},
244 {NULL, NULL}
245 };
246
247 /*
248 * class methods
249 */
250 static const luaL_Reg connection_class_methods[] = {
251 {"New", connection_new},
252 {NULL, NULL}
253 };
254
255 dbd_register(L, DBD_SQLITE_CONNECTION,
256 connection_methods, connection_class_methods,
257 connection_gc, connection_tostring);
258
259 /*
260 * Connection flag constants exported in our namespace
261 */
262 static const struct {
263 const char *name;
264 int value;
265 } sqlite3_constants[] = {
266 "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY,
267 "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE,
268 "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE,
269 "SQLITE_OPEN_URI", SQLITE_OPEN_URI,
270 "SQLITE_OPEN_MEMORY", SQLITE_OPEN_MEMORY,
271 "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX,
272 "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX,
273 "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE,
274 "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE,
275 NULL, 0
276 };
277
278 int i = 0;
279 while (sqlite3_constants[i].name) {
280 lua_pushstring(L, sqlite3_constants[i].name);
281 lua_pushinteger(L, sqlite3_constants[i].value);
282 lua_rawset(L, -3);
283 ++i;
284 }
285
286 return 1;
287 }
288