diff options
| author | 2022-08-04 09:45:32 +0200 | |
|---|---|---|
| committer | 2022-08-04 12:46:16 +0200 | |
| commit | 00ac50a1b79ea5cec2e8ed2fc344bc2f546c171f (patch) | |
| tree | 73d71ceafd82380cb04197e4699b1617892cc071 | |
| parent | use a single cImport (diff) | |
| download | zig-sqlite-00ac50a1b79ea5cec2e8ed2fc344bc2f546c171f.tar.gz zig-sqlite-00ac50a1b79ea5cec2e8ed2fc344bc2f546c171f.tar.xz zig-sqlite-00ac50a1b79ea5cec2e8ed2fc344bc2f546c171f.zip | |
move DetailedError, do some cleanup
DetailedError uses getLastErrorOffset, which must check the SQLite
version with versionGreaterThanOrEqualTo.
Instead of publicly exposing versionGreaterThanOrEqualTo in sqlite.zig
move DetailedError in errors.zig
Diffstat (limited to '')
| -rw-r--r-- | errors.zig | 56 | ||||
| -rw-r--r-- | sqlite.zig | 46 |
2 files changed, 53 insertions, 49 deletions
| @@ -1,4 +1,5 @@ | |||
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const mem = std.mem; | ||
| 2 | 3 | ||
| 3 | const c = @import("c.zig").c; | 4 | const c = @import("c.zig").c; |
| 4 | 5 | ||
| @@ -126,13 +127,13 @@ pub const Error = SQLiteError || | |||
| 126 | SQLiteExtendedReadOnlyError || | 127 | SQLiteExtendedReadOnlyError || |
| 127 | SQLiteExtendedConstraintError; | 128 | SQLiteExtendedConstraintError; |
| 128 | 129 | ||
| 129 | fn greaterThanOrEqualsTo(major: u8, minor: u8, patch: u8) bool { | 130 | fn versionGreaterThanOrEqualTo(major: u8, minor: u8, patch: u8) bool { |
| 130 | return c.SQLITE_VERSION_NUMBER >= @as(u32, major) * 1000000 + @as(u32, minor) * 1000 + @as(u32, patch); | 131 | return c.SQLITE_VERSION_NUMBER >= @as(u32, major) * 1000000 + @as(u32, minor) * 1000 + @as(u32, patch); |
| 131 | } | 132 | } |
| 132 | 133 | ||
| 133 | pub fn errorFromResultCode(code: c_int) Error { | 134 | pub fn errorFromResultCode(code: c_int) Error { |
| 134 | // These errors are only available since 3.22.0. | 135 | // These errors are only available since 3.22.0. |
| 135 | if (comptime greaterThanOrEqualsTo(3, 22, 0)) { | 136 | if (comptime versionGreaterThanOrEqualTo(3, 22, 0)) { |
| 136 | switch (code) { | 137 | switch (code) { |
| 137 | c.SQLITE_ERROR_MISSING_COLLSEQ => return error.SQLiteErrorMissingCollSeq, | 138 | c.SQLITE_ERROR_MISSING_COLLSEQ => return error.SQLiteErrorMissingCollSeq, |
| 138 | c.SQLITE_ERROR_RETRY => return error.SQLiteErrorRetry, | 139 | c.SQLITE_ERROR_RETRY => return error.SQLiteErrorRetry, |
| @@ -143,7 +144,7 @@ pub fn errorFromResultCode(code: c_int) Error { | |||
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | // These errors are only available since 3.25.0. | 146 | // These errors are only available since 3.25.0. |
| 146 | if (comptime greaterThanOrEqualsTo(3, 25, 0)) { | 147 | if (comptime versionGreaterThanOrEqualTo(3, 25, 0)) { |
| 147 | switch (code) { | 148 | switch (code) { |
| 148 | c.SQLITE_ERROR_SNAPSHOT => return error.SQLiteErrorSnapshot, | 149 | c.SQLITE_ERROR_SNAPSHOT => return error.SQLiteErrorSnapshot, |
| 149 | c.SQLITE_LOCKED_VTAB => return error.SQLiteLockedVTab, | 150 | c.SQLITE_LOCKED_VTAB => return error.SQLiteLockedVTab, |
| @@ -153,7 +154,7 @@ pub fn errorFromResultCode(code: c_int) Error { | |||
| 153 | } | 154 | } |
| 154 | } | 155 | } |
| 155 | // These errors are only available since 3.31.0. | 156 | // These errors are only available since 3.31.0. |
| 156 | if (comptime greaterThanOrEqualsTo(3, 31, 0)) { | 157 | if (comptime versionGreaterThanOrEqualTo(3, 31, 0)) { |
| 157 | switch (code) { | 158 | switch (code) { |
| 158 | c.SQLITE_CANTOPEN_SYMLINK => return error.SQLiteCantOpenSymlink, | 159 | c.SQLITE_CANTOPEN_SYMLINK => return error.SQLiteCantOpenSymlink, |
| 159 | c.SQLITE_CONSTRAINT_PINNED => return error.SQLiteConstraintPinned, | 160 | c.SQLITE_CONSTRAINT_PINNED => return error.SQLiteConstraintPinned, |
| @@ -161,7 +162,7 @@ pub fn errorFromResultCode(code: c_int) Error { | |||
| 161 | } | 162 | } |
| 162 | } | 163 | } |
| 163 | // These errors are only available since 3.32.0. | 164 | // These errors are only available since 3.32.0. |
| 164 | if (comptime greaterThanOrEqualsTo(3, 32, 0)) { | 165 | if (comptime versionGreaterThanOrEqualTo(3, 32, 0)) { |
| 165 | switch (code) { | 166 | switch (code) { |
| 166 | c.SQLITE_IOERR_DATA => return error.SQLiteIOErrData, // See https://sqlite.org/cksumvfs.html | 167 | c.SQLITE_IOERR_DATA => return error.SQLiteIOErrData, // See https://sqlite.org/cksumvfs.html |
| 167 | c.SQLITE_BUSY_TIMEOUT => return error.SQLiteBusyTimeout, | 168 | c.SQLITE_BUSY_TIMEOUT => return error.SQLiteBusyTimeout, |
| @@ -170,7 +171,7 @@ pub fn errorFromResultCode(code: c_int) Error { | |||
| 170 | } | 171 | } |
| 171 | } | 172 | } |
| 172 | // These errors are only available since 3.34.0. | 173 | // These errors are only available since 3.34.0. |
| 173 | if (comptime greaterThanOrEqualsTo(3, 34, 0)) { | 174 | if (comptime versionGreaterThanOrEqualTo(3, 34, 0)) { |
| 174 | switch (code) { | 175 | switch (code) { |
| 175 | c.SQLITE_IOERR_CORRUPTFS => return error.SQLiteIOErrCorruptFS, | 176 | c.SQLITE_IOERR_CORRUPTFS => return error.SQLiteIOErrCorruptFS, |
| 176 | else => {}, | 177 | else => {}, |
| @@ -271,3 +272,46 @@ pub fn errorFromResultCode(code: c_int) Error { | |||
| 271 | else => std.debug.panic("invalid result code {}", .{code}), | 272 | else => std.debug.panic("invalid result code {}", .{code}), |
| 272 | } | 273 | } |
| 273 | } | 274 | } |
| 275 | |||
| 276 | /// DetailedError contains a SQLite error code and error message. | ||
| 277 | pub const DetailedError = struct { | ||
| 278 | code: usize, | ||
| 279 | near: i32, | ||
| 280 | message: []const u8, | ||
| 281 | |||
| 282 | pub fn format(self: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | ||
| 283 | _ = fmt; | ||
| 284 | _ = options; | ||
| 285 | |||
| 286 | _ = try writer.print("{{code: {}, near: {d}, message: {s}}}", .{ self.code, self.near, self.message }); | ||
| 287 | } | ||
| 288 | }; | ||
| 289 | |||
| 290 | pub fn getDetailedErrorFromResultCode(code: c_int) DetailedError { | ||
| 291 | return .{ | ||
| 292 | .code = @intCast(usize, code), | ||
| 293 | .near = -1, | ||
| 294 | .message = blk: { | ||
| 295 | const msg = c.sqlite3_errstr(code); | ||
| 296 | break :blk mem.sliceTo(msg, 0); | ||
| 297 | }, | ||
| 298 | }; | ||
| 299 | } | ||
| 300 | |||
| 301 | pub fn getErrorOffset(db: *c.sqlite3) i32 { | ||
| 302 | if (comptime versionGreaterThanOrEqualTo(3, 38, 0)) { | ||
| 303 | return c.sqlite3_error_offset(db); | ||
| 304 | } | ||
| 305 | return -1; | ||
| 306 | } | ||
| 307 | |||
| 308 | pub fn getLastDetailedErrorFromDb(db: *c.sqlite3) DetailedError { | ||
| 309 | return .{ | ||
| 310 | .code = @intCast(usize, c.sqlite3_extended_errcode(db)), | ||
| 311 | .near = getErrorOffset(db), | ||
| 312 | .message = blk: { | ||
| 313 | const msg = c.sqlite3_errmsg(db); | ||
| 314 | break :blk mem.sliceTo(msg, 0); | ||
| 315 | }, | ||
| 316 | }; | ||
| 317 | } | ||
| @@ -15,6 +15,9 @@ pub const ParsedQuery = @import("query.zig").ParsedQuery; | |||
| 15 | const errors = @import("errors.zig"); | 15 | const errors = @import("errors.zig"); |
| 16 | pub const errorFromResultCode = errors.errorFromResultCode; | 16 | pub const errorFromResultCode = errors.errorFromResultCode; |
| 17 | pub const Error = errors.Error; | 17 | pub const Error = errors.Error; |
| 18 | pub const DetailedError = errors.DetailedError; | ||
| 19 | const getLastDetailedErrorFromDb = errors.getLastDetailedErrorFromDb; | ||
| 20 | const getDetailedErrorFromResultCode = errors.getDetailedErrorFromResultCode; | ||
| 18 | 21 | ||
| 19 | const logger = std.log.scoped(.sqlite); | 22 | const logger = std.log.scoped(.sqlite); |
| 20 | 23 | ||
| @@ -255,53 +258,10 @@ pub const InitOptions = struct { | |||
| 255 | diags: ?*Diagnostics = null, | 258 | diags: ?*Diagnostics = null, |
| 256 | }; | 259 | }; |
| 257 | 260 | ||
| 258 | /// DetailedError contains a SQLite error code and error message. | ||
| 259 | pub const DetailedError = struct { | ||
| 260 | code: usize, | ||
| 261 | near: i32, | ||
| 262 | message: []const u8, | ||
| 263 | |||
| 264 | pub fn format(self: @This(), comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { | ||
| 265 | _ = fmt; | ||
| 266 | _ = options; | ||
| 267 | |||
| 268 | _ = try writer.print("{{code: {}, near: {d}, message: {s}}}", .{ self.code, self.near, self.message }); | ||
| 269 | } | ||
| 270 | }; | ||
| 271 | |||
| 272 | fn isThreadSafe() bool { | 261 | fn isThreadSafe() bool { |
| 273 | return c.sqlite3_threadsafe() > 0; | 262 | return c.sqlite3_threadsafe() > 0; |
| 274 | } | 263 | } |
| 275 | 264 | ||
| 276 | fn getDetailedErrorFromResultCode(code: c_int) DetailedError { | ||
| 277 | return .{ | ||
| 278 | .code = @intCast(usize, code), | ||
| 279 | .near = -1, | ||
| 280 | .message = blk: { | ||
| 281 | const msg = c.sqlite3_errstr(code); | ||
| 282 | break :blk mem.sliceTo(msg, 0); | ||
| 283 | }, | ||
| 284 | }; | ||
| 285 | } | ||
| 286 | |||
| 287 | fn getErrorOffset(db: *c.sqlite3) i32 { | ||
| 288 | if (c.SQLITE_VERSION_NUMBER >= 3038000) { | ||
| 289 | return c.sqlite3_error_offset(db); | ||
| 290 | } | ||
| 291 | return -1; | ||
| 292 | } | ||
| 293 | |||
| 294 | fn getLastDetailedErrorFromDb(db: *c.sqlite3) DetailedError { | ||
| 295 | return .{ | ||
| 296 | .code = @intCast(usize, c.sqlite3_extended_errcode(db)), | ||
| 297 | .near = getErrorOffset(db), | ||
| 298 | .message = blk: { | ||
| 299 | const msg = c.sqlite3_errmsg(db); | ||
| 300 | break :blk mem.sliceTo(msg, 0); | ||
| 301 | }, | ||
| 302 | }; | ||
| 303 | } | ||
| 304 | |||
| 305 | /// Db is a wrapper around a SQLite database, providing high-level functions for executing queries. | 265 | /// Db is a wrapper around a SQLite database, providing high-level functions for executing queries. |
| 306 | /// A Db can be opened with a file database or a in-memory database: | 266 | /// A Db can be opened with a file database or a in-memory database: |
| 307 | /// | 267 | /// |