| ... | @@ -257,21 +257,34 @@ pub const s = struct { | ... | @@ -257,21 +257,34 @@ pub const s = struct { |
| 257 | if (code == c.SQLITE_OK) return; | 257 | if (code == c.SQLITE_OK) return; |
| 258 | return rc2p(code); | 258 | return rc2p(code); |
| 259 | } | 259 | } |
| | 260 | pub fn rc2p_d(db: *c.sqlite3, code: c_int) Error { |
| | 261 | if (builtin.mode == .Debug) @panic(std.mem.sliceTo(c.sqlite3_errmsg(db), 0)); |
| | 262 | return rc2e(code); |
| | 263 | } |
| | 264 | pub fn assert_d(db: *c.sqlite3, code: c_int) void { |
| | 265 | if (code == c.SQLITE_OK) return; |
| | 266 | @panic(std.mem.sliceTo(c.sqlite3_errmsg(db), 0)); |
| | 267 | } |
| | 268 | pub fn please_d(db: *c.sqlite3, code: c_int) !void { |
| | 269 | if (code == c.SQLITE_OK) return; |
| | 270 | return rc2p_d(db, code); |
| | 271 | } |
| 260 | }; | 272 | }; |
| 261 | | 273 | |
| 262 | pub const Statement = struct { | 274 | pub const Statement = struct { |
| | 275 | db: *c.sqlite3, |
| 263 | stmt: *c.sqlite3_stmt, | 276 | stmt: *c.sqlite3_stmt, |
| 264 | | 277 | |
| 265 | pub fn prepare(driver: *Self, query: []const u8) !Statement { | 278 | pub fn prepare(driver: *Self, query: []const u8) !Statement { |
| 266 | var stmt: ?*c.sqlite3_stmt = null; | 279 | var stmt: ?*c.sqlite3_stmt = null; |
| 267 | var flags: c_uint = 0; | 280 | var flags: c_uint = 0; |
| 268 | _ = &flags; | 281 | _ = &flags; |
| 269 | try s.please(c.sqlite3_prepare_v3(driver.db, query.ptr, @intCast(query.len), flags, &stmt, null)); | 282 | try s.please_d(driver.db, c.sqlite3_prepare_v3(driver.db, query.ptr, @intCast(query.len), flags, &stmt, null)); |
| 270 | return .{ .stmt = stmt.? }; | 283 | return .{ .db = driver.db, .stmt = stmt.? }; |
| 271 | } | 284 | } |
| 272 | | 285 | |
| 273 | pub fn finalize(stmt: Statement) void { | 286 | pub fn finalize(stmt: Statement) void { |
| 274 | s.assert(c.sqlite3_finalize(stmt.stmt)); | 287 | s.assert_d(stmt.db, c.sqlite3_finalize(stmt.stmt)); |
| 275 | } | 288 | } |
| 276 | | 289 | |
| 277 | pub fn bindArgs(stmt: Statement, allocator: std.mem.Allocator, args: anytype) !void { | 290 | pub fn bindArgs(stmt: Statement, allocator: std.mem.Allocator, args: anytype) !void { |
| ... | @@ -289,10 +302,10 @@ pub const Statement = struct { | ... | @@ -289,10 +302,10 @@ pub const Statement = struct { |
| 289 | | 302 | |
| 290 | fn bindType(stmt: Statement, allocator: std.mem.Allocator, idx: usize, T: type, value: T) !void { | 303 | fn bindType(stmt: Statement, allocator: std.mem.Allocator, idx: usize, T: type, value: T) !void { |
| 291 | if (comptime extras.isZigString(T)) { | 304 | if (comptime extras.isZigString(T)) { |
| 292 | return s.please(c.sqlite3_bind_text64(stmt.stmt, @intCast(idx), value.ptr, value.len, c.SQLITE_STATIC, c.SQLITE_UTF8)); | 305 | return s.please_d(stmt.db, c.sqlite3_bind_text64(stmt.stmt, @intCast(idx), value.ptr, value.len, c.SQLITE_STATIC, c.SQLITE_UTF8)); |
| 293 | } | 306 | } |
| 294 | if (comptime extras.isArrayOf(u8)(T)) { | 307 | if (comptime extras.isArrayOf(u8)(T)) { |
| 295 | return s.please(c.sqlite3_bind_blob64(stmt.stmt, @intCast(idx), &value, value.len, c.SQLITE_TRANSIENT)); | 308 | return s.please_d(stmt.db, c.sqlite3_bind_blob64(stmt.stmt, @intCast(idx), &value, value.len, c.SQLITE_TRANSIENT)); |
| 296 | } | 309 | } |
| 297 | switch (@typeInfo(T)) { | 310 | switch (@typeInfo(T)) { |
| 298 | .@"struct" => |info| { | 311 | .@"struct" => |info| { |
| ... | @@ -304,7 +317,7 @@ pub const Statement = struct { | ... | @@ -304,7 +317,7 @@ pub const Statement = struct { |
| 304 | comptime std.debug.assert(info.bits <= 64); | 317 | comptime std.debug.assert(info.bits <= 64); |
| 305 | if (value > std.math.maxInt(c.sqlite_int64)) return error.Overflow; | 318 | if (value > std.math.maxInt(c.sqlite_int64)) return error.Overflow; |
| 306 | if (value < std.math.minInt(c.sqlite_int64)) return error.Overflow; | 319 | if (value < std.math.minInt(c.sqlite_int64)) return error.Overflow; |
| 307 | return s.please(c.sqlite3_bind_int64(stmt.stmt, @intCast(idx), @intCast(value))); | 320 | return s.please_d(stmt.db, c.sqlite3_bind_int64(stmt.stmt, @intCast(idx), @intCast(value))); |
| 308 | }, | 321 | }, |
| 309 | .optional => |info| { | 322 | .optional => |info| { |
| 310 | if (value == null) return s.please(c.sqlite3_bind_null(stmt.stmt, @intCast(idx))); | 323 | if (value == null) return s.please(c.sqlite3_bind_null(stmt.stmt, @intCast(idx))); |
| ... | @@ -352,20 +365,21 @@ pub const Statement = struct { | ... | @@ -352,20 +365,21 @@ pub const Statement = struct { |
| 352 | } | 365 | } |
| 353 | | 366 | |
| 354 | pub fn iterate(stmt: Statement) Iterator { | 367 | pub fn iterate(stmt: Statement) Iterator { |
| 355 | return .{ .stmt = stmt.stmt }; | 368 | return .{ .db = stmt.db, .stmt = stmt.stmt }; |
| 356 | } | 369 | } |
| 357 | | 370 | |
| 358 | pub const Iterator = struct { | 371 | pub const Iterator = struct { |
| | 372 | db: *c.sqlite3, |
| 359 | stmt: *c.sqlite3_stmt, | 373 | stmt: *c.sqlite3_stmt, |
| 360 | | 374 | |
| 361 | pub fn reset(iter: Iterator) void { | 375 | pub fn reset(iter: Iterator) void { |
| 362 | return s.please(c.sqlite3_reset(iter.stmt)) catch {}; | 376 | return s.please_d(iter.db, c.sqlite3_reset(iter.stmt)) catch {}; |
| 363 | } | 377 | } |
| 364 | | 378 | |
| 365 | pub fn step(iter: Iterator, allocator: std.mem.Allocator, T: type) !?T { | 379 | pub fn step(iter: Iterator, allocator: std.mem.Allocator, T: type) !?T { |
| 366 | const code = c.sqlite3_step(iter.stmt); | 380 | const code = c.sqlite3_step(iter.stmt); |
| 367 | if (code == c.SQLITE_DONE) return null; | 381 | if (code == c.SQLITE_DONE) return null; |
| 368 | if (code != c.SQLITE_ROW) return s.rc2p(code); | 382 | if (code != c.SQLITE_ROW) return s.rc2p_d(iter.db, code); |
| 369 | if (T == void) return; | 383 | if (T == void) return; |
| 370 | if (T == string) return try readType(iter, allocator, 0, string); | 384 | if (T == string) return try readType(iter, allocator, 0, string); |
| 371 | if (@typeInfo(T) == .int) return try readType(iter, allocator, 0, T); | 385 | if (@typeInfo(T) == .int) return try readType(iter, allocator, 0, T); |