summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Vincent Rischmann2020-12-31 23:42:44 +0100
committerGravatar GitHub2020-12-31 23:42:44 +0100
commit71e1eb2a645fb33e6558193ef3f8f8b244a54fb3 (patch)
tree5e0b6477d55e5d44f28c7f116b7ae8f31fe06fc4
parentMerge pull request #9 from vrischmann/split-alloc (diff)
parentfix error checks based on the sqlite version (diff)
downloadzig-sqlite-71e1eb2a645fb33e6558193ef3f8f8b244a54fb3.tar.gz
zig-sqlite-71e1eb2a645fb33e6558193ef3f8f8b244a54fb3.tar.xz
zig-sqlite-71e1eb2a645fb33e6558193ef3f8f8b244a54fb3.zip
Merge pull request #11 from vrischmann/map-errors
Map errors
-rw-r--r--error.zig268
-rw-r--r--sqlite.zig19
2 files changed, 277 insertions, 10 deletions
diff --git a/error.zig b/error.zig
new file mode 100644
index 0000000..eb2f00c
--- /dev/null
+++ b/error.zig
@@ -0,0 +1,268 @@
1const std = @import("std");
2
3const c = @cImport({
4 @cInclude("sqlite3.h");
5});
6
7pub const SQLiteExtendedIOError = error{
8 SQLiteIOErrRead,
9 SQLiteIOErrShortRead,
10 SQLiteIOErrWrite,
11 SQLiteIOErrFsync,
12 SQLiteIOErrDirFsync,
13 SQLiteIOErrTruncate,
14 SQLiteIOErrFstat,
15 SQLiteIOErrUnlock,
16 SQLiteIOErrRDLock,
17 SQLiteIOErrDelete,
18 SQLiteIOErrBlocked,
19 SQLiteIOErrNoMem,
20 SQLiteIOErrAccess,
21 SQLiteIOErrCheckReservedLock,
22 SQLiteIOErrLock,
23 SQLiteIOErrClose,
24 SQLiteIOErrDirClose,
25 SQLiteIOErrSHMOpen,
26 SQLiteIOErrSHMSize,
27 SQLiteIOErrSHMLock,
28 SQLiteIOErrSHMMap,
29 SQLiteIOErrSeek,
30 SQLiteIOErrDeleteNoEnt,
31 SQLiteIOErrMmap,
32 SQLiteIOErrGetTempPath,
33 SQLiteIOErrConvPath,
34 SQLiteIOErrVnode,
35 SQLiteIOErrAuth,
36 SQLiteIOErrBeginAtomic,
37 SQLiteIOErrCommitAtomic,
38 SQLiteIOErrRollbackAtomic,
39 SQLiteIOErrData,
40 SQLiteIOErrCorruptFS,
41};
42
43pub const SQLiteExtendedCantOpenError = error{
44 SQLiteCantOpenNoTempDir,
45 SQLiteCantOpenIsDir,
46 SQLiteCantOpenFullPath,
47 SQLiteCantOpenConvPath,
48 SQLiteCantOpenDirtyWAL,
49 SQLiteCantOpenSymlink,
50};
51
52pub const SQLiteExtendedReadOnlyError = error{
53 SQLiteReadOnlyRecovery,
54 SQLiteReadOnlyCantLock,
55 SQLiteReadOnlyRollback,
56 SQLiteReadOnlyDBMoved,
57 SQLiteReadOnlyCantInit,
58 SQLiteReadOnlyDirectory,
59};
60
61pub const SQLiteExtendedConstraintError = error{
62 SQLiteConstraintCheck,
63 SQLiteConstraintCommitHook,
64 SQLiteConstraintForeignKey,
65 SQLiteConstraintFunction,
66 SQLiteConstraintNotNull,
67 SQLiteConstraintPrimaryKey,
68 SQLiteConstraintTrigger,
69 SQLiteConstraintUnique,
70 SQLiteConstraintVTab,
71 SQLiteConstraintRowID,
72 SQLiteConstraintPinned,
73};
74
75pub const SQLiteExtendedError = error{
76 SQLiteErrorMissingCollSeq,
77 SQLiteErrorRetry,
78 SQLiteErrorSnapshot,
79
80 SQLiteLockedSharedCache,
81 SQLiteLockedVTab,
82
83 SQLiteBusyRecovery,
84 SQLiteBusySnapshot,
85 SQLiteBusyTimeout,
86
87 SQLiteCorruptVTab,
88 SQLiteCorruptSequence,
89 SQLiteCorruptIndex,
90
91 SQLiteAbortRollback,
92};
93
94pub const SQLiteError = error{
95 SQLiteError,
96 SQLiteInternal,
97 SQLitePerm,
98 SQLiteAbort,
99 SQLiteBusy,
100 SQLiteLocked,
101 SQLiteNoMem,
102 SQLiteReadOnly,
103 SQLiteInterrupt,
104 SQLiteIOErr,
105 SQLiteCorrupt,
106 SQLiteNotFound,
107 SQLiteFull,
108 SQLiteCantOpen,
109 SQLiteProtocol,
110 SQLiteEmpty,
111 SQLiteSchema,
112 SQLiteTooBig,
113 SQLiteConstraint,
114 SQLiteMismatch,
115 SQLiteMisuse,
116 SQLiteNoLFS,
117 SQLiteAuth,
118 SQLiteRange,
119 SQLiteNotADatabase,
120 SQLiteNotice,
121 SQLiteWarning,
122};
123
124pub const Error = SQLiteError ||
125 SQLiteExtendedError ||
126 SQLiteExtendedIOError ||
127 SQLiteExtendedCantOpenError ||
128 SQLiteExtendedReadOnlyError ||
129 SQLiteExtendedConstraintError;
130
131pub fn errorFromResultCode(code: c_int) Error {
132 // TODO(vincent): can we do something with comptime here ?
133 // The version number is always static and defined by sqlite.
134
135 // These errors are only available since 3.25.0.
136 if (c.SQLITE_VERSION_NUMBER >= 3025000) {
137 switch (code) {
138 c.SQLITE_ERROR_SNAPSHOT => return error.SQLiteErrorSnapshot,
139 c.SQLITE_LOCKED_VTAB => return error.SQLiteLockedVTab,
140 c.SQLITE_CANTOPEN_DIRTYWAL => return error.SQLiteCantOpenDirtyWAL,
141 c.SQLITE_CORRUPT_SEQUENCE => return error.SQLiteCorruptSequence,
142 else => {},
143 }
144 }
145 // These errors are only available since 3.31.0.
146 if (c.SQLITE_VERSION_NUMBER >= 3031000) {
147 switch (code) {
148 c.SQLITE_CANTOPEN_SYMLINK => return error.SQLiteCantOpenSymlink,
149 c.SQLITE_CONSTRAINT_PINNED => return error.SQLiteConstraintPinned,
150 else => {},
151 }
152 }
153 // These errors are only available since 3.32.0.
154 if (c.SQLITE_VERSION_NUMBER >= 3032000) {
155 switch (code) {
156 c.SQLITE_IOERR_DATA => return error.SQLiteIOErrData, // See https://sqlite.org/cksumvfs.html
157 c.SQLITE_BUSY_TIMEOUT => return error.SQLiteBusyTimeout,
158 c.SQLITE_CORRUPT_INDEX => return error.SQLiteCorruptIndex,
159 else => {},
160 }
161 }
162 // These errors are only available since 3.34.0.
163 if (c.SQLITE_VERSION_NUMBER >= 3034000) {
164 switch (code) {
165 c.SQLITE_IOERR_CORRUPTFS => return error.SQLiteIOErrCorruptFS,
166 else => {},
167 }
168 }
169
170 return switch (code) {
171 c.SQLITE_ERROR => error.SQLiteError,
172 c.SQLITE_INTERNAL => error.SQLiteInternal,
173 c.SQLITE_PERM => error.SQLitePerm,
174 c.SQLITE_ABORT => error.SQLiteAbort,
175 c.SQLITE_BUSY => error.SQLiteBusy,
176 c.SQLITE_LOCKED => error.SQLiteLocked,
177 c.SQLITE_NOMEM => error.SQLiteNoMem,
178 c.SQLITE_READONLY => error.SQLiteReadOnly,
179 c.SQLITE_INTERRUPT => error.SQLiteInterrupt,
180 c.SQLITE_IOERR => error.SQLiteIOErr,
181 c.SQLITE_CORRUPT => error.SQLiteCorrupt,
182 c.SQLITE_NOTFOUND => error.SQLiteNotFound,
183 c.SQLITE_FULL => error.SQLiteFull,
184 c.SQLITE_CANTOPEN => error.SQLiteCantOpen,
185 c.SQLITE_PROTOCOL => error.SQLiteProtocol,
186 c.SQLITE_EMPTY => error.SQLiteEmpty,
187 c.SQLITE_SCHEMA => error.SQLiteSchema,
188 c.SQLITE_TOOBIG => error.SQLiteTooBig,
189 c.SQLITE_CONSTRAINT => error.SQLiteConstraint,
190 c.SQLITE_MISMATCH => error.SQLiteMismatch,
191 c.SQLITE_MISUSE => error.SQLiteMisuse,
192 c.SQLITE_NOLFS => error.SQLiteNoLFS,
193 c.SQLITE_AUTH => error.SQLiteAuth,
194 c.SQLITE_RANGE => error.SQLiteRange,
195 c.SQLITE_NOTADB => error.SQLiteNotADatabase,
196 c.SQLITE_NOTICE => error.SQLiteNotice,
197 c.SQLITE_WARNING => error.SQLiteWarning,
198
199 c.SQLITE_ERROR_MISSING_COLLSEQ => error.SQLiteErrorMissingCollSeq,
200 c.SQLITE_ERROR_RETRY => error.SQLiteErrorRetry,
201
202 c.SQLITE_IOERR_READ => error.SQLiteIOErrRead,
203 c.SQLITE_IOERR_SHORT_READ => error.SQLiteIOErrShortRead,
204 c.SQLITE_IOERR_WRITE => error.SQLiteIOErrWrite,
205 c.SQLITE_IOERR_FSYNC => error.SQLiteIOErrFsync,
206 c.SQLITE_IOERR_DIR_FSYNC => error.SQLiteIOErrDirFsync,
207 c.SQLITE_IOERR_TRUNCATE => error.SQLiteIOErrTruncate,
208 c.SQLITE_IOERR_FSTAT => error.SQLiteIOErrFstat,
209 c.SQLITE_IOERR_UNLOCK => error.SQLiteIOErrUnlock,
210 c.SQLITE_IOERR_RDLOCK => error.SQLiteIOErrRDLock,
211 c.SQLITE_IOERR_DELETE => error.SQLiteIOErrDelete,
212 c.SQLITE_IOERR_BLOCKED => error.SQLiteIOErrBlocked,
213 c.SQLITE_IOERR_NOMEM => error.SQLiteIOErrNoMem,
214 c.SQLITE_IOERR_ACCESS => error.SQLiteIOErrAccess,
215 c.SQLITE_IOERR_CHECKRESERVEDLOCK => error.SQLiteIOErrCheckReservedLock,
216 c.SQLITE_IOERR_LOCK => error.SQLiteIOErrLock,
217 c.SQLITE_IOERR_CLOSE => error.SQLiteIOErrClose,
218 c.SQLITE_IOERR_DIR_CLOSE => error.SQLiteIOErrDirClose,
219 c.SQLITE_IOERR_SHMOPEN => error.SQLiteIOErrSHMOpen,
220 c.SQLITE_IOERR_SHMSIZE => error.SQLiteIOErrSHMSize,
221 c.SQLITE_IOERR_SHMLOCK => error.SQLiteIOErrSHMLock,
222 c.SQLITE_IOERR_SHMMAP => error.SQLiteIOErrSHMMap,
223 c.SQLITE_IOERR_SEEK => error.SQLiteIOErrSeek,
224 c.SQLITE_IOERR_DELETE_NOENT => error.SQLiteIOErrDeleteNoEnt,
225 c.SQLITE_IOERR_MMAP => error.SQLiteIOErrMmap,
226 c.SQLITE_IOERR_GETTEMPPATH => error.SQLiteIOErrGetTempPath,
227 c.SQLITE_IOERR_CONVPATH => error.SQLiteIOErrConvPath,
228 c.SQLITE_IOERR_VNODE => error.SQLiteIOErrVnode,
229 c.SQLITE_IOERR_AUTH => error.SQLiteIOErrAuth,
230 c.SQLITE_IOERR_BEGIN_ATOMIC => error.SQLiteIOErrBeginAtomic,
231 c.SQLITE_IOERR_COMMIT_ATOMIC => error.SQLiteIOErrCommitAtomic,
232 c.SQLITE_IOERR_ROLLBACK_ATOMIC => error.SQLiteIOErrRollbackAtomic,
233
234 c.SQLITE_LOCKED_SHAREDCACHE => error.SQLiteLockedSharedCache,
235
236 c.SQLITE_BUSY_RECOVERY => error.SQLiteBusyRecovery,
237 c.SQLITE_BUSY_SNAPSHOT => error.SQLiteBusySnapshot,
238
239 c.SQLITE_CANTOPEN_NOTEMPDIR => error.SQLiteCantOpenNoTempDir,
240 c.SQLITE_CANTOPEN_ISDIR => error.SQLiteCantOpenIsDir,
241 c.SQLITE_CANTOPEN_FULLPATH => error.SQLiteCantOpenFullPath,
242 c.SQLITE_CANTOPEN_CONVPATH => error.SQLiteCantOpenConvPath,
243
244 c.SQLITE_CORRUPT_VTAB => error.SQLiteCorruptVTab,
245
246 c.SQLITE_READONLY_RECOVERY => error.SQLiteReadOnlyRecovery,
247 c.SQLITE_READONLY_CANTLOCK => error.SQLiteReadOnlyCantLock,
248 c.SQLITE_READONLY_ROLLBACK => error.SQLiteReadOnlyRollback,
249 c.SQLITE_READONLY_DBMOVED => error.SQLiteReadOnlyDBMoved,
250 c.SQLITE_READONLY_CANTINIT => error.SQLiteReadOnlyCantInit,
251 c.SQLITE_READONLY_DIRECTORY => error.SQLiteReadOnlyDirectory,
252
253 c.SQLITE_ABORT_ROLLBACK => error.SQLiteAbortRollback,
254
255 c.SQLITE_CONSTRAINT_CHECK => error.SQLiteConstraintCheck,
256 c.SQLITE_CONSTRAINT_COMMITHOOK => error.SQLiteConstraintCommitHook,
257 c.SQLITE_CONSTRAINT_FOREIGNKEY => error.SQLiteConstraintForeignKey,
258 c.SQLITE_CONSTRAINT_FUNCTION => error.SQLiteConstraintFunction,
259 c.SQLITE_CONSTRAINT_NOTNULL => error.SQLiteConstraintNotNull,
260 c.SQLITE_CONSTRAINT_PRIMARYKEY => error.SQLiteConstraintPrimaryKey,
261 c.SQLITE_CONSTRAINT_TRIGGER => error.SQLiteConstraintTrigger,
262 c.SQLITE_CONSTRAINT_UNIQUE => error.SQLiteConstraintUnique,
263 c.SQLITE_CONSTRAINT_VTAB => error.SQLiteConstraintVTab,
264 c.SQLITE_CONSTRAINT_ROWID => error.SQLiteConstraintRowID,
265
266 else => std.debug.panic("invalid result code {}", .{code}),
267 };
268}
diff --git a/sqlite.zig b/sqlite.zig
index 6abedc4..ec46ed9 100644
--- a/sqlite.zig
+++ b/sqlite.zig
@@ -9,6 +9,7 @@ const c = @cImport({
9}); 9});
10 10
11usingnamespace @import("query.zig"); 11usingnamespace @import("query.zig");
12usingnamespace @import("error.zig");
12 13
13const logger = std.log.scoped(.sqlite); 14const logger = std.log.scoped(.sqlite);
14 15
@@ -42,8 +43,6 @@ pub const InitOptions = struct {
42 threading_mode: ThreadingMode = .Serialized, 43 threading_mode: ThreadingMode = .Serialized,
43}; 44};
44 45
45pub const Error = error{};
46
47/// DetailedError contains a SQLite error code and error message. 46/// DetailedError contains a SQLite error code and error message.
48pub const DetailedError = struct { 47pub const DetailedError = struct {
49 code: usize, 48 code: usize,
@@ -128,7 +127,7 @@ pub const Db = struct {
128 var db: ?*c.sqlite3 = undefined; 127 var db: ?*c.sqlite3 = undefined;
129 const result = c.sqlite3_open_v2(path, &db, flags, null); 128 const result = c.sqlite3_open_v2(path, &db, flags, null);
130 if (result != c.SQLITE_OK or db == null) { 129 if (result != c.SQLITE_OK or db == null) {
131 return error.CannotOpenDatabase; 130 return errorFromResultCode(result);
132 } 131 }
133 132
134 self.db = db.?; 133 self.db = db.?;
@@ -141,7 +140,7 @@ pub const Db = struct {
141 var db: ?*c.sqlite3 = undefined; 140 var db: ?*c.sqlite3 = undefined;
142 const result = c.sqlite3_open_v2(":memory:", &db, flags, null); 141 const result = c.sqlite3_open_v2(":memory:", &db, flags, null);
143 if (result != c.SQLITE_OK or db == null) { 142 if (result != c.SQLITE_OK or db == null) {
144 return error.CannotOpenDatabase; 143 return errorFromResultCode(result);
145 } 144 }
146 145
147 self.db = db.?; 146 self.db = db.?;
@@ -292,7 +291,7 @@ pub fn Iterator(comptime Type: type) type {
292 return null; 291 return null;
293 } 292 }
294 if (result != c.SQLITE_ROW) { 293 if (result != c.SQLITE_ROW) {
295 return error.SQLiteStepError; 294 return errorFromResultCode(result);
296 } 295 }
297 296
298 const columns = c.sqlite3_column_count(self.stmt); 297 const columns = c.sqlite3_column_count(self.stmt);
@@ -332,7 +331,7 @@ pub fn Iterator(comptime Type: type) type {
332 return null; 331 return null;
333 } 332 }
334 if (result != c.SQLITE_ROW) { 333 if (result != c.SQLITE_ROW) {
335 return error.SQLiteStepError; 334 return errorFromResultCode(result);
336 } 335 }
337 336
338 const columns = c.sqlite3_column_count(self.stmt); 337 const columns = c.sqlite3_column_count(self.stmt);
@@ -649,7 +648,7 @@ pub fn Statement(comptime opts: StatementOptions, comptime query: ParsedQuery) t
649 null, 648 null,
650 ); 649 );
651 if (result != c.SQLITE_OK) { 650 if (result != c.SQLITE_OK) {
652 return error.CannotPrepareStatement; 651 return errorFromResultCode(result);
653 } 652 }
654 break :blk tmp.?; 653 break :blk tmp.?;
655 }; 654 };
@@ -754,7 +753,7 @@ pub fn Statement(comptime opts: StatementOptions, comptime query: ParsedQuery) t
754 const result = c.sqlite3_step(self.stmt); 753 const result = c.sqlite3_step(self.stmt);
755 switch (result) { 754 switch (result) {
756 c.SQLITE_DONE => {}, 755 c.SQLITE_DONE => {},
757 c.SQLITE_BUSY => return error.SQLiteBusy, 756 c.SQLITE_BUSY => return errorFromResultCode(result),
758 else => std.debug.panic("invalid result {}", .{result}), 757 else => std.debug.panic("invalid result {}", .{result}),
759 } 758 }
760 } 759 }
@@ -1403,7 +1402,7 @@ test "sqlite: failing open" {
1403 .open_flags = .{}, 1402 .open_flags = .{},
1404 .mode = .{ .File = "/tmp/not_existing.db" }, 1403 .mode = .{ .File = "/tmp/not_existing.db" },
1405 }); 1404 });
1406 testing.expectError(error.CannotOpenDatabase, res); 1405 testing.expectError(error.SQLiteCantOpen, res);
1407} 1406}
1408 1407
1409test "sqlite: failing prepare statement" { 1408test "sqlite: failing prepare statement" {
@@ -1411,7 +1410,7 @@ test "sqlite: failing prepare statement" {
1411 try db.init(initOptions()); 1410 try db.init(initOptions());
1412 1411
1413 const result = db.prepare("SELECT id FROM foobar"); 1412 const result = db.prepare("SELECT id FROM foobar");
1414 testing.expectError(error.CannotPrepareStatement, result); 1413 testing.expectError(error.SQLiteError, result);
1415 1414
1416 const detailed_err = db.getDetailedError(); 1415 const detailed_err = db.getDetailedError();
1417 testing.expectEqual(@as(usize, 1), detailed_err.code); 1416 testing.expectEqual(@as(usize, 1), detailed_err.code);