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