comparison util/sqlite3.lua @ 13968:52e214142ac2

util.sqlite3: Support immediate transactions
author Kim Alvefur <zash@zash.se>
date Mon, 19 Aug 2024 00:15:40 +0200
parents e7c52d0b0e0d
children
comparison
equal deleted inserted replaced
13967:758d5d4e83ca 13968:52e214142ac2
259 function engine:_(word) 259 function engine:_(word)
260 local ret = self.conn:exec(word); 260 local ret = self.conn:exec(word);
261 if ret ~= lsqlite3.OK then return nil, self.conn:errmsg(); end 261 if ret ~= lsqlite3.OK then return nil, self.conn:errmsg(); end
262 return true; 262 return true;
263 end 263 end
264 function engine:_transaction(func, ...) 264 function engine:_transaction(rw, func, ...)
265 if not self.conn then 265 if not self.conn then
266 local a,b = self:connect(); 266 local a,b = self:connect();
267 if not a then return a,b; end 267 if not a then return a,b; end
268 end 268 end
269 --assert(not self.__transaction, "Recursive transactions not allowed"); 269 --assert(not self.__transaction, "Recursive transactions not allowed");
270 local ok, err = self:_"BEGIN"; 270 local begin = rw and "BEGIN IMMEDIATE" or "BEGIN";
271 local ok, err = self:_(begin);
271 if not ok then return ok, err; end 272 if not ok then return ok, err; end
272 self.__transaction = true; 273 self.__transaction = true;
273 local success, a, b, c = xpcall(func, debug_traceback, ...); 274 local success, a, b, c = xpcall(func, debug_traceback, ...);
274 self.__transaction = nil; 275 self.__transaction = nil;
275 if success then 276 if success then
276 log("debug", "SQL transaction success [%s]", tostring(func)); 277 log("debug", "SQL %s transaction success [%s]", rw and "write" or "read", tostring(func));
277 local ok, err = self:_"COMMIT"; 278 local ok, err = self:_"COMMIT";
278 if not ok then return ok, err; end -- commit failed 279 if not ok then return ok, err; end -- commit failed
279 return success, a, b, c; 280 return success, a, b, c;
280 else 281 else
281 log("debug", "SQL transaction failure [%s]: %s", tostring(func), a); 282 log("debug", "SQL %s transaction failure [%s]: %s", rw and "write" or "read", tostring(func), a);
282 if self.conn then self:_"ROLLBACK"; end 283 if self.conn then self:_"ROLLBACK"; end
283 return success, a; 284 return success, a;
284 end 285 end
285 end 286 end
286 function engine:transaction(...) 287 function engine:transaction(...)
287 local ok, ret = self:_transaction(...); 288 local ok, ret = self:_transaction(nil, ...);
288 if not ok then 289 if not ok then
289 local conn = self.conn; 290 local conn = self.conn;
290 if not conn or not conn:isopen() then 291 if not conn or not conn:isopen() then
291 self.conn = nil; 292 self.conn = nil;
292 self:ondisconnect(); 293 self:ondisconnect();
293 ok, ret = self:_transaction(...); 294 ok, ret = self:_transaction(nil, ...);
294 end 295 end
295 end 296 end
296 return ok, ret; 297 return ok, ret;
297 end 298 end
298 engine.write_transaction = engine.transaction; -- TODO BEGIN IMMEDATE 299 function engine:write_transaction(...)
300 local ok, ret = self:_transaction(true, ...);
301 if not ok then
302 local conn = self.conn;
303 if not conn or not conn:isopen() then
304 self.conn = nil;
305 self:ondisconnect();
306 ok, ret = self:_transaction(true, ...);
307 end
308 end
309 return ok, ret;
310 end
299 function engine:_create_index(index) 311 function engine:_create_index(index)
300 local sql = "CREATE INDEX IF NOT EXISTS \""..index.name.."\" ON \""..index.table.."\" ("; 312 local sql = "CREATE INDEX IF NOT EXISTS \""..index.name.."\" ON \""..index.table.."\" (";
301 for i=1,#index do 313 for i=1,#index do
302 sql = sql.."\""..index[i].."\""; 314 sql = sql.."\""..index[i].."\"";
303 if i ~= #index then sql = sql..", "; end 315 if i ~= #index then sql = sql..", "; end