GCC Code Coverage Report


Directory: src/
File: src/storage_sqlite.c
Date: 2026-10-15 10:49:27
Exec Total Coverage
Lines: 245 338 72.5%
Functions: 23 23 100.0%
Branches: 66 156 42.3%

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 "storage_sqlite.h"
9
10 #include "log.h"
11 #include "process.h"
12 #include "run_queue.h"
13 #include "sql/sqlite_sql.h"
14 #include "sqlite.h"
15 #include "storage.h"
16
17 #include <sqlite3.h>
18
19 #include <pthread.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 struct storage_sqlite_settings {
25 char* path;
26 };
27
28 29 int storage_sqlite_settings_create(struct storage_settings* settings, const char* path) {
29 29 struct storage_sqlite_settings* sqlite = malloc(sizeof(struct storage_sqlite_settings));
30
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!sqlite) {
31 ✗ log_errno("malloc");
32 ✗ return -1;
33 }
34
35 29 sqlite->path = strdup(path);
36
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!sqlite->path) {
37 ✗ log_errno("strdup");
38 ✗ goto free;
39 }
40
41 29 settings->type = STORAGE_TYPE_SQLITE;
42 29 settings->sqlite = sqlite;
43 29 return 0;
44
45 ✗ free:
46 ✗ free(sqlite);
47
48 ✗ return -1;
49 }
50
51 29 void storage_sqlite_settings_destroy(const struct storage_settings* settings) {
52 29 free(settings->sqlite->path);
53 29 free(settings->sqlite);
54 29 }
55
56 struct prepared_stmt {
57 pthread_mutex_t mtx;
58 sqlite3_stmt* impl;
59 };
60
61 174 static int prepared_stmt_init(struct prepared_stmt* stmt, sqlite3* db, const char* sql) {
62 174 int ret = 0;
63
64 174 ret = pthread_mutex_init(&stmt->mtx, NULL);
65
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
174 if (ret) {
66 ✗ pthread_errno(ret, "pthread_mutex_init");
67 ✗ return ret;
68 }
69
70 174 ret = sqlite_prepare(db, sql, &stmt->impl);
71
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
174 if (ret < 0)
72 ✗ goto destroy_mtx;
73
74 174 return ret;
75
76 ✗ destroy_mtx:
77 ✗ pthread_errno_if(pthread_mutex_destroy(&stmt->mtx), "pthread_mutex_destroy");
78
79 ✗ return ret;
80 }
81
82 174 static void prepared_stmt_destroy(struct prepared_stmt* stmt) {
83
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 174 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
174 pthread_errno_if(pthread_mutex_destroy(&stmt->mtx), "pthread_mutex_destroy");
84 174 sqlite_finalize(stmt->impl);
85 174 }
86
87 36775 static int prepared_stmt_lock(struct prepared_stmt* stmt) {
88 36775 int ret = pthread_mutex_lock(&stmt->mtx);
89
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36775 times.
36775 if (ret) {
90 ✗ pthread_errno(ret, "pthread_mutex_unlock");
91 ✗ return ret;
92 }
93 36775 return ret;
94 }
95
96 36775 static void prepared_stmt_unlock(struct prepared_stmt* stmt) {
97
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 36775 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
36775 pthread_errno_if(pthread_mutex_unlock(&stmt->mtx), "pthread_mutex_unlock");
98 36775 }
99
100 struct storage_sqlite {
101 sqlite3* db;
102
103 struct prepared_stmt stmt_repo_find;
104 struct prepared_stmt stmt_repo_insert;
105 struct prepared_stmt stmt_run_insert;
106 struct prepared_stmt stmt_run_finished;
107 struct prepared_stmt stmt_get_runs;
108 struct prepared_stmt stmt_get_run_queue;
109 };
110
111 29 static int storage_sqlite_upgrade_to(struct storage_sqlite* storage, size_t version) {
112 static const char* const fmt = "%s PRAGMA user_version = %zu;";
113
114 29 const char* script = sqlite_schemas[version];
115 29 int ret = 0;
116
117 29 ret = snprintf(NULL, 0, fmt, script, version + 1);
118 29 size_t nb = (size_t)ret + 1;
119 29 ret = 0;
120
121 29 char* full_script = malloc(nb);
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!full_script) {
123 ✗ log_errno("malloc");
124 ✗ return -1;
125 }
126 29 snprintf(full_script, nb, fmt, script, version + 1);
127
128 29 ret = sqlite_exec_as_transaction(storage->db, full_script);
129 29 goto free;
130
131 29 free:
132 29 free(full_script);
133
134 29 return ret;
135 }
136
137 29 static int storage_sqlite_upgrade_from_to(struct storage_sqlite* storage, size_t from, size_t to) {
138 29 int ret = 0;
139
140
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 29 times.
58 for (size_t i = from; i < to; ++i) {
141
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 log("Upgrading SQLite database from version %zu to version %zu\n", i, i + 1);
142 29 ret = storage_sqlite_upgrade_to(storage, i);
143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0) {
144 ✗ log_err("Failed to upgrade to version %zu\n", i + 1);
145 ✗ return ret;
146 }
147 }
148
149 29 return ret;
150 }
151
152 29 static int storage_sqlite_upgrade(struct storage_sqlite* storage) {
153 29 unsigned int current_version = 0;
154 29 int ret = 0;
155
156 29 ret = sqlite_get_user_version(storage->db, &current_version);
157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
158 ✗ return ret;
159
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 log("SQLite database version: %u\n", current_version);
160
161 29 size_t newest_version = sizeof(sqlite_schemas) / sizeof(sqlite_schemas[0]);
162
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 log("Newest database version: %zu\n", newest_version);
163
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (current_version > newest_version) {
165 ✗ log_err("Unknown database version: %u\n", current_version);
166 ✗ return -1;
167 }
168
169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (current_version == newest_version) {
170 ✗ log("SQLite database already at the newest version\n");
171 ✗ return 0;
172 }
173
174 29 return storage_sqlite_upgrade_from_to(storage, current_version, newest_version);
175 }
176
177 29 static int storage_sqlite_setup(struct storage_sqlite* storage) {
178 29 int ret = 0;
179
180 29 ret = sqlite_set_foreign_keys(storage->db);
181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
182 ✗ return ret;
183
184 29 ret = storage_sqlite_upgrade(storage);
185
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
186 ✗ return ret;
187
188 29 return ret;
189 }
190
191 29 static int storage_sqlite_prepare_statements(struct storage_sqlite* storage) {
192 static const char* const fmt_repo_find = "SELECT id FROM cimple_repos WHERE url = ?;";
193 static const char* const fmt_repo_insert =
194 "INSERT INTO cimple_repos(url) VALUES (?) ON CONFLICT(url) DO NOTHING;";
195 static const char* const fmt_run_insert =
196 "INSERT INTO cimple_runs(status, exit_code, output, repo_id, repo_rev) VALUES (?, -1, x'', ?, ?) RETURNING id;";
197 static const char* const fmt_run_finished =
198 "UPDATE cimple_runs SET status = ?, exit_code = ?, output = ? WHERE id = ?;";
199 static const char* const fmt_get_runs =
200 "SELECT id, status, exit_code, repo_url, repo_rev FROM cimple_runs_view ORDER BY id DESC";
201 static const char* const fmt_get_run_queue =
202 "SELECT id, status, exit_code, repo_url, repo_rev FROM cimple_runs_view WHERE status = ? ORDER BY id;";
203
204 29 int ret = 0;
205
206 29 ret = prepared_stmt_init(&storage->stmt_repo_find, storage->db, fmt_repo_find);
207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
208 ✗ return ret;
209 29 ret = prepared_stmt_init(&storage->stmt_repo_insert, storage->db, fmt_repo_insert);
210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
211 ✗ goto finalize_repo_find;
212 29 ret = prepared_stmt_init(&storage->stmt_run_insert, storage->db, fmt_run_insert);
213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
214 ✗ goto finalize_repo_insert;
215 29 ret = prepared_stmt_init(&storage->stmt_run_finished, storage->db, fmt_run_finished);
216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
217 ✗ goto finalize_run_insert;
218 29 ret = prepared_stmt_init(&storage->stmt_get_runs, storage->db, fmt_get_runs);
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
220 ✗ goto finalize_run_finished;
221 29 ret = prepared_stmt_init(&storage->stmt_get_run_queue, storage->db, fmt_get_run_queue);
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
223 ✗ goto finalize_get_runs;
224
225 29 return ret;
226
227 ✗ finalize_get_runs:
228 ✗ prepared_stmt_destroy(&storage->stmt_get_runs);
229 ✗ finalize_run_finished:
230 ✗ prepared_stmt_destroy(&storage->stmt_run_finished);
231 ✗ finalize_run_insert:
232 ✗ prepared_stmt_destroy(&storage->stmt_run_insert);
233 ✗ finalize_repo_insert:
234 ✗ prepared_stmt_destroy(&storage->stmt_repo_insert);
235 ✗ finalize_repo_find:
236 ✗ prepared_stmt_destroy(&storage->stmt_repo_find);
237
238 ✗ return ret;
239 }
240
241 29 static void storage_sqlite_finalize_statements(struct storage_sqlite* storage) {
242 29 prepared_stmt_destroy(&storage->stmt_get_run_queue);
243 29 prepared_stmt_destroy(&storage->stmt_get_runs);
244 29 prepared_stmt_destroy(&storage->stmt_run_finished);
245 29 prepared_stmt_destroy(&storage->stmt_run_insert);
246 29 prepared_stmt_destroy(&storage->stmt_repo_insert);
247 29 prepared_stmt_destroy(&storage->stmt_repo_find);
248 29 }
249
250 29 int storage_sqlite_create(struct storage* storage, const struct storage_settings* settings) {
251 29 int ret = 0;
252
253
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 log("Using SQLite database at %s\n", settings->sqlite->path);
254
255 29 struct storage_sqlite* sqlite = malloc(sizeof(struct storage_sqlite));
256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!sqlite) {
257 ✗ log_errno("malloc");
258 ✗ return -1;
259 }
260
261 29 ret = sqlite_init();
262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
263 ✗ goto free;
264 29 ret = sqlite_open_rw(settings->sqlite->path, &sqlite->db);
265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
266 ✗ goto destroy;
267 29 ret = storage_sqlite_setup(sqlite);
268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
269 ✗ goto close;
270 29 ret = storage_sqlite_prepare_statements(sqlite);
271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
272 ✗ goto close;
273
274 29 storage->sqlite = sqlite;
275 29 return ret;
276
277 ✗ close:
278 ✗ sqlite_close(storage->sqlite->db);
279 ✗ destroy:
280 ✗ sqlite_destroy();
281 ✗ free:
282 ✗ free(sqlite);
283
284 ✗ return ret;
285 }
286
287 29 void storage_sqlite_destroy(struct storage* storage) {
288 29 storage_sqlite_finalize_statements(storage->sqlite);
289 29 sqlite_close(storage->sqlite->db);
290 29 sqlite_destroy();
291 29 free(storage->sqlite);
292 29 }
293
294 9180 static int storage_sqlite_find_repo(struct storage_sqlite* storage, const char* url) {
295 9180 struct prepared_stmt* stmt = &storage->stmt_repo_find;
296 9180 int ret = 0;
297
298 9180 ret = prepared_stmt_lock(stmt);
299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
300 ✗ return ret;
301 9180 ret = sqlite_bind_text(stmt->impl, 1, url);
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
303 ✗ goto reset;
304 9180 ret = sqlite_step(stmt->impl);
305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
306 ✗ goto reset;
307
308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (!ret)
309 ✗ goto reset;
310
311 9180 ret = sqlite_column_int(stmt->impl, 0);
312 9180 goto reset;
313
314 9180 reset:
315 9180 sqlite_reset(stmt->impl);
316 9180 prepared_stmt_unlock(stmt);
317
318 9180 return ret;
319 }
320
321 9180 static int storage_sqlite_insert_repo(struct storage_sqlite* storage, const char* url) {
322 9180 struct prepared_stmt* stmt = &storage->stmt_repo_insert;
323 9180 int ret = 0;
324
325 9180 ret = prepared_stmt_lock(stmt);
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
327 ✗ return ret;
328 9180 ret = sqlite_bind_text(stmt->impl, 1, url);
329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
330 ✗ goto reset;
331 9180 ret = sqlite_step(stmt->impl);
332
1/2
✓ Branch 0 taken 9180 times.
✗ Branch 1 not taken.
9180 if (ret < 0)
333 ✗ goto reset;
334
335 9180 reset:
336 9180 sqlite_reset(stmt->impl);
337 9180 prepared_stmt_unlock(stmt);
338
339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
340 ✗ return ret;
341
342 9180 return storage_sqlite_find_repo(storage, url);
343 }
344
345 9180 static int storage_sqlite_insert_run(struct storage_sqlite* storage, int repo_id, const char* rev) {
346 9180 struct prepared_stmt* stmt = &storage->stmt_run_insert;
347 9180 int ret = 0;
348
349 9180 ret = prepared_stmt_lock(stmt);
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
351 ✗ return ret;
352 9180 ret = sqlite_bind_int(stmt->impl, 1, RUN_STATUS_CREATED);
353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
354 ✗ goto reset;
355 9180 ret = sqlite_bind_int(stmt->impl, 2, repo_id);
356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
357 ✗ goto reset;
358 9180 ret = sqlite_bind_text(stmt->impl, 3, rev);
359
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
360 ✗ goto reset;
361 9180 ret = sqlite_step(stmt->impl);
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
363 ✗ goto reset;
364
365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (!ret) {
366 ✗ ret = -1;
367 ✗ log_err("Failed to insert a run\n");
368 ✗ goto reset;
369 }
370
371 9180 ret = sqlite_column_int(stmt->impl, 0);
372 9180 goto reset;
373
374 9180 reset:
375 9180 sqlite_reset(stmt->impl);
376 9180 prepared_stmt_unlock(stmt);
377
378 9180 return ret;
379 }
380
381 9180 int storage_sqlite_run_create(struct storage* storage, const char* repo_url, const char* rev) {
382 9180 int ret = 0;
383
384 9180 ret = storage_sqlite_insert_repo(storage->sqlite, repo_url);
385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
386 ✗ return ret;
387
388 9180 ret = storage_sqlite_insert_run(storage->sqlite, ret, rev);
389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
390 ✗ return ret;
391
392 9180 return ret;
393 }
394
395 9180 int storage_sqlite_run_finished(
396 struct storage* storage,
397 int run_id,
398 const struct process_output* output
399 ) {
400 9180 struct prepared_stmt* stmt = &storage->sqlite->stmt_run_finished;
401 9180 int ret = 0;
402
403 9180 ret = prepared_stmt_lock(stmt);
404
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
405 ✗ return ret;
406 9180 ret = sqlite_bind_int(stmt->impl, 1, RUN_STATUS_FINISHED);
407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
408 ✗ goto reset;
409 9180 ret = sqlite_bind_int(stmt->impl, 2, output->ec);
410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
411 ✗ goto reset;
412 9180 ret = sqlite_bind_blob(stmt->impl, 3, output->data, output->data_size);
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
414 ✗ goto reset;
415 9180 ret = sqlite_bind_int(stmt->impl, 4, run_id);
416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
417 ✗ goto reset;
418 9180 ret = sqlite_step(stmt->impl);
419
1/2
✓ Branch 0 taken 9180 times.
✗ Branch 1 not taken.
9180 if (ret < 0)
420 ✗ goto reset;
421
422 9180 reset:
423 9180 sqlite_reset(stmt->impl);
424 9180 prepared_stmt_unlock(stmt);
425
426 9180 return ret;
427 }
428
429 9180 static int storage_sqlite_row_to_run(struct sqlite3_stmt* stmt, struct run** run) {
430 9180 int ret = 0;
431
432 9180 int id = sqlite_column_int(stmt, 0);
433 9180 int status = sqlite_column_int(stmt, 1);
434 9180 int exit_code = sqlite_column_int(stmt, 2);
435
436 9180 char* url = NULL;
437 9180 ret = sqlite_column_text(stmt, 3, &url);
438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
439 ✗ return ret;
440
441 9180 char* rev = NULL;
442 9180 ret = sqlite_column_text(stmt, 4, &rev);
443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
444 ✗ goto free_url;
445
446 9180 ret = run_new(run, id, url, rev, status, exit_code);
447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
448 ✗ goto free_rev;
449
450
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9180 times.
9180 log("Adding run %d for repository %s to the queue\n", id, url);
451
452 9180 free_rev:
453 9180 free(rev);
454
455 9180 free_url:
456 9180 free(url);
457
458 9180 return ret;
459 }
460
461 55 static int storage_sqlite_rows_to_runs(struct sqlite3_stmt* stmt, struct run_queue* queue) {
462 55 int ret = 0;
463
464 55 run_queue_create(queue);
465
466 9180 while (1) {
467 9235 ret = sqlite_step(stmt);
468
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 9180 times.
9235 if (!ret)
469 55 break;
470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
471 ✗ goto run_queue_destroy;
472
473 9180 struct run* run = NULL;
474
475 9180 ret = storage_sqlite_row_to_run(stmt, &run);
476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
9180 if (ret < 0)
477 ✗ goto run_queue_destroy;
478
479 9180 run_queue_add_last(queue, run);
480 }
481
482 55 return ret;
483
484 ✗ run_queue_destroy:
485 ✗ run_queue_destroy(queue);
486
487 ✗ return ret;
488 }
489
490 26 int storage_sqlite_get_runs(struct storage* storage, struct run_queue* queue) {
491 26 struct prepared_stmt* stmt = &storage->sqlite->stmt_get_runs;
492 26 int ret = 0;
493
494 26 ret = prepared_stmt_lock(stmt);
495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (ret < 0)
496 ✗ return ret;
497 26 ret = storage_sqlite_rows_to_runs(stmt->impl, queue);
498
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (ret < 0)
499 ✗ goto reset;
500
501 26 reset:
502 26 sqlite_reset(stmt->impl);
503 26 prepared_stmt_unlock(stmt);
504
505 26 return ret;
506 }
507
508 29 int storage_sqlite_get_run_queue(struct storage* storage, struct run_queue* queue) {
509 29 struct prepared_stmt* stmt = &storage->sqlite->stmt_get_run_queue;
510 29 int ret = 0;
511
512 29 ret = prepared_stmt_lock(stmt);
513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
514 ✗ return ret;
515 29 ret = sqlite_bind_int(stmt->impl, 1, RUN_STATUS_CREATED);
516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
517 ✗ goto reset;
518 29 ret = storage_sqlite_rows_to_runs(stmt->impl, queue);
519
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (ret < 0)
520 ✗ goto reset;
521
522 29 reset:
523 29 sqlite_reset(stmt->impl);
524 29 prepared_stmt_unlock(stmt);
525
526 29 return ret;
527 }
528