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