GCC Code Coverage Report


Directory: src/
File: src/sqlite.c
Date: 2024-04-25 03:45:42
Exec Total Coverage
Lines: 101 162 62.3%
Branches: 21 95 22.1%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2022 Egor Tensin <egor@tensin.name>
3 * This file is part of the "cimple" project.
4 * For details, see https://github.com/egor-tensin/cimple.
5 * Distributed under the MIT License.
6 */
7
8 #include "sqlite.h"
9 #include "compiler.h"
10 #include "log.h"
11
12 #include <sqlite3.h>
13
14 #include <stddef.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 #define sqlite_errno(var, fn) \
20 do { \
21 log_err("%s: %s\n", fn, sqlite3_errstr(var)); \
22 var = -var; \
23 } while (0)
24
25 #define sqlite_errno_if(expr, fn) \
26 do { \
27 int CONCAT(ret, __LINE__) = expr; \
28 if (CONCAT(ret, __LINE__)) \
29 sqlite_errno(CONCAT(ret, __LINE__), fn); \
30 } while (0)
31
32 29 int sqlite_init(void)
33 {
34 29 int ret = 0;
35
36 29 ret = sqlite3_initialize();
37
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret) {
38 sqlite_errno(ret, "sqlite3_initialize");
39 return ret;
40 }
41
42 29 return ret;
43 }
44
45 29 void sqlite_destroy(void)
46 {
47
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
29 sqlite_errno_if(sqlite3_shutdown(), "sqlite3_shutdown");
48 29 }
49
50 29 static int sqlite_open(const char *path, sqlite3 **db, int flags)
51 {
52 29 int ret = 0;
53
54 29 ret = sqlite3_open_v2(path, db, flags, NULL);
55
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret) {
56 sqlite_errno(ret, "sqlite3_open_v2");
57 return ret;
58 }
59
60 29 return ret;
61 }
62
63 29 int sqlite_open_rw(const char *path, sqlite3 **db)
64 {
65 static const int flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
66 29 return sqlite_open(path, db, flags);
67 }
68
69 int sqlite_open_ro(const char *path, sqlite3 **db)
70 {
71 static const int flags = SQLITE_OPEN_READONLY;
72 return sqlite_open(path, db, flags);
73 }
74
75 29 void sqlite_close(sqlite3 *db)
76 {
77
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
29 sqlite_errno_if(sqlite3_close(db), "sqlite3_close");
78 29 }
79
80 58 int sqlite_exec(sqlite3 *db, const char *stmt, sqlite3_callback callback, void *arg)
81 {
82 58 int ret = 0;
83
84 58 ret = sqlite3_exec(db, stmt, callback, arg, NULL);
85
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if (ret) {
86 sqlite_errno(ret, "sqlite3_exec");
87 return ret;
88 }
89
90 58 return ret;
91 }
92
93 int sqlite_exec_log_result(UNUSED void *arg, int numof_columns, char **values, char **column_names)
94 {
95 log("Row:\n");
96 for (int i = 0; i < numof_columns; ++i) {
97 log("\t%s: %s\n", column_names[i], values[i]);
98 }
99 return 0;
100 }
101
102 203 int sqlite_prepare(sqlite3 *db, const char *stmt, sqlite3_stmt **result)
103 {
104 203 int ret = 0;
105
106 203 ret = sqlite3_prepare_v2(db, stmt, -1, result, NULL);
107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
203 if (ret) {
108 sqlite_errno(ret, "sqlite3_prepare_v2");
109 return ret;
110 }
111
112 203 return ret;
113 }
114
115 36775 void sqlite_reset(sqlite3_stmt *stmt)
116 {
117
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 36775 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
36775 sqlite_errno_if(sqlite3_reset(stmt), "sqlite3_reset");
118
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 36775 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
36775 sqlite_errno_if(sqlite3_clear_bindings(stmt), "sqlite3_clear_bindings");
119 36775 }
120
121 203 void sqlite_finalize(sqlite3_stmt *stmt)
122 {
123
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 203 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
203 sqlite_errno_if(sqlite3_finalize(stmt), "sqlite3_finalize");
124 203 }
125
126 45984 int sqlite_step(sqlite3_stmt *stmt)
127 {
128 45984 int ret = 0;
129
130 45984 ret = sqlite3_step(stmt);
131
132
2/3
✓ Branch 0 taken 27569 times.
✓ Branch 1 taken 18415 times.
✗ Branch 2 not taken.
45984 switch (ret) {
133 27569 case SQLITE_ROW:
134 27569 return 1;
135 18415 case SQLITE_DONE:
136 18415 return 0;
137
138 default:
139 sqlite_errno(ret, "sqlite3_step");
140 return ret;
141 }
142 }
143
144 45929 int sqlite_column_int(sqlite3_stmt *stmt, int index)
145 {
146 45929 return sqlite3_column_int(stmt, index);
147 }
148
149 18360 int sqlite_column_text(sqlite3_stmt *stmt, int index, char **_result)
150 {
151 18360 int ret = 0;
152
153 18360 const unsigned char *value = sqlite3_column_text(stmt, index);
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18360 times.
18360 if (!value) {
155 ret = sqlite3_errcode(sqlite3_db_handle(stmt));
156 if (ret) {
157 sqlite_errno(ret, "sqlite3_column_text");
158 return ret;
159 }
160
161 *_result = NULL;
162 return 0;
163 }
164
165 18360 ret = sqlite3_column_bytes(stmt, index);
166 18360 size_t nb = (size_t)ret;
167
168 18360 char *result = calloc(nb + 1, 1);
169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18360 times.
18360 if (!result) {
170 log_errno("calloc");
171 return -1;
172 }
173 18360 memcpy(result, value, nb);
174
175 18360 *_result = result;
176 18360 return 0;
177 }
178
179 int sqlite_column_blob(sqlite3_stmt *stmt, int index, unsigned char **_result)
180 {
181 int ret = 0;
182
183 const unsigned char *value = sqlite3_column_blob(stmt, index);
184 if (!value) {
185 ret = sqlite3_errcode(sqlite3_db_handle(stmt));
186 if (ret) {
187 sqlite_errno(ret, "sqlite3_column_text");
188 return ret;
189 }
190
191 *_result = NULL;
192 return 0;
193 }
194
195 ret = sqlite3_column_bytes(stmt, index);
196 size_t nb = (size_t)ret;
197
198 unsigned char *result = malloc(nb);
199 if (!result) {
200 log_errno("malloc");
201 return -1;
202 }
203 memcpy(result, value, nb);
204
205 *_result = result;
206 return 0;
207 }
208
209 45929 int sqlite_bind_int(sqlite3_stmt *stmt, int index, int value)
210 {
211 45929 int ret = 0;
212
213 45929 ret = sqlite3_bind_int(stmt, index, value);
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45929 times.
45929 if (ret) {
215 sqlite_errno(ret, "sqlite3_bind_int");
216 return ret;
217 }
218
219 45929 return ret;
220 }
221
222 27540 int sqlite_bind_text(sqlite3_stmt *stmt, int index, const char *value)
223 {
224 27540 int ret = 0;
225
226 27540 ret = sqlite3_bind_text(stmt, index, value, -1, SQLITE_STATIC);
227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27540 times.
27540 if (ret) {
228 sqlite_errno(ret, "sqlite3_bind_text");
229 return ret;
230 }
231
232 27540 return ret;
233 }
234
235 9180 int sqlite_bind_blob(sqlite3_stmt *stmt, int index, unsigned char *value, size_t nb)
236 {
237 9180 int ret = 0;
238
239 9180 ret = sqlite3_bind_blob64(stmt, index, value, nb, SQLITE_STATIC);
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret) {
241 sqlite_errno(ret, "sqlite3_bind_blob64");
242 return ret;
243 }
244
245 9180 return ret;
246 }
247
248 29 int sqlite_exec_as_transaction(sqlite3 *db, const char *stmt)
249 {
250 static const char *const fmt = "BEGIN; %s COMMIT;";
251 29 int ret = 0;
252
253 29 ret = snprintf(NULL, 0, fmt, stmt);
254 29 size_t nb = (size_t)ret + 1;
255 29 ret = 0;
256
257 29 char *full_stmt = malloc(nb);
258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!full_stmt) {
259 log_errno("malloc");
260 return -1;
261 }
262 29 snprintf(full_stmt, nb, fmt, stmt);
263
264 29 ret = sqlite_exec(db, stmt, NULL, NULL);
265 29 goto free;
266
267 29 free:
268 29 free(full_stmt);
269
270 29 return ret;
271 }
272
273 29 int sqlite_get_user_version(sqlite3 *db, unsigned int *output)
274 {
275 static const char *const sql = "PRAGMA user_version;";
276
277 29 sqlite3_stmt *stmt = NULL;
278 29 int result = -1, ret = 0;
279
280 29 ret = sqlite_prepare(db, sql, &stmt);
281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
282 return ret;
283 29 ret = sqlite_step(stmt);
284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
285 goto finalize;
286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!ret) {
287 ret = -1;
288 log_err("Failed to read database version\n");
289 goto finalize;
290 }
291
292 29 result = sqlite_column_int(stmt, 0);
293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (result < 0) {
294 log_err("Invalid database version: %d\n", result);
295 ret = -1;
296 goto finalize;
297 }
298 29 *output = (unsigned int)result;
299
300 29 goto finalize;
301
302 29 finalize:
303 29 sqlite_finalize(stmt);
304
305 29 return ret;
306 }
307
308 29 int sqlite_set_foreign_keys(sqlite3 *db)
309 {
310 static const char *const sql = "PRAGMA foreign_keys = ON;";
311 29 return sqlite_exec(db, sql, NULL, NULL);
312 }
313