Mercurial > sci
comparison db.c @ 3:215c0c3b3609
misc: use JSON everywhere (scictl/sciwebd)
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 14 Jun 2021 22:08:24 +0200 |
parents | 5fa3d2f479b2 |
children | 9c4fea43803c |
comparison
equal
deleted
inserted
replaced
2:5fa3d2f479b2 | 3:215c0c3b3609 |
---|---|
1 #include <sys/queue.h> | |
1 #include <assert.h> | 2 #include <assert.h> |
2 #include <stdlib.h> | 3 #include <stdlib.h> |
3 #include <string.h> | 4 #include <string.h> |
4 | 5 |
5 #include <sqlite3.h> | 6 #include <sqlite3.h> |
6 | 7 |
7 #include "db.h" | 8 #include "db.h" |
8 #include "job.h" | |
9 #include "log.h" | 9 #include "log.h" |
10 #include "project.h" | 10 #include "types.h" |
11 #include "worker.h" | 11 #include "util.h" |
12 | 12 |
13 #include "sql/init.h" | 13 #include "sql/init.h" |
14 #include "sql/job-queue.h" | 14 #include "sql/job-add.h" |
15 #include "sql/job-result-todo.h" | 15 #include "sql/job-todo.h" |
16 #include "sql/job-save.h" | 16 #include "sql/jobresult-add.h" |
17 #include "sql/project-insert.h" | 17 #include "sql/project-add.h" |
18 #include "sql/project-get.h" | |
19 #include "sql/project-find.h" | 18 #include "sql/project-find.h" |
20 #include "sql/worker-get.h" | 19 #include "sql/project-find-id.h" |
20 #include "sql/project-list.h" | |
21 #include "sql/worker-add.h" | |
21 #include "sql/worker-find.h" | 22 #include "sql/worker-find.h" |
22 #include "sql/worker-insert.h" | 23 #include "sql/worker-find-id.h" |
24 #include "sql/worker-list.h" | |
23 | 25 |
24 #define CHAR(v) (const char *)(v) | 26 #define CHAR(v) (const char *)(v) |
25 | 27 |
26 static sqlite3 *db; | 28 static sqlite3 *db; |
27 | 29 |
30 struct str { | |
31 char *str; | |
32 SLIST_ENTRY(str) link; | |
33 }; | |
34 | |
35 SLIST_HEAD(strlist, str); | |
36 | |
37 static struct strlist * | |
38 strlist_new(void) | |
39 { | |
40 struct strlist *l; | |
41 | |
42 l = util_calloc(1, sizeof (*l)); | |
43 SLIST_INIT(l); | |
44 | |
45 return l; | |
46 } | |
47 | |
48 static const char * | |
49 strlist_add(struct strlist *l, const char *text) | |
50 { | |
51 struct str *s; | |
52 | |
53 s = util_calloc(1, sizeof (*s)); | |
54 s->str = util_strdup(text); | |
55 | |
56 SLIST_INSERT_HEAD(l, s, link); | |
57 | |
58 return s->str; | |
59 } | |
60 | |
61 static void | |
62 strlist_free(struct strlist *l) | |
63 { | |
64 struct str *s, *tmp; | |
65 | |
66 SLIST_FOREACH_SAFE(s, l, link, tmp) { | |
67 free(s->str); | |
68 free(s); | |
69 } | |
70 | |
71 SLIST_INIT(l); | |
72 } | |
73 | |
28 static inline void | 74 static inline void |
29 convert_project(struct project *project, sqlite3_stmt *stmt) | 75 convert_project(struct db_ctx *ctx, struct project *project, sqlite3_stmt *stmt) |
30 { | 76 { |
31 project->id = sqlite3_column_int64(stmt, 0); | 77 project->id = sqlite3_column_int(stmt, 0); |
32 strlcpy(project->name, CHAR(sqlite3_column_text(stmt, 1)), sizeof (project->name)); | 78 project->name = strlist_add(ctx->handle, CHAR(sqlite3_column_text(stmt, 1))); |
33 strlcpy(project->desc, CHAR(sqlite3_column_text(stmt, 2)), sizeof (project->desc)); | 79 project->desc = strlist_add(ctx->handle, CHAR(sqlite3_column_text(stmt, 2))); |
34 strlcpy(project->url, CHAR(sqlite3_column_text(stmt, 3)), sizeof (project->url)); | 80 project->url = strlist_add(ctx->handle, CHAR(sqlite3_column_text(stmt, 3))); |
35 strlcpy(project->script, CHAR(sqlite3_column_text(stmt, 4)), sizeof (project->script)); | 81 project->script = strlist_add(ctx->handle, CHAR(sqlite3_column_text(stmt, 4))); |
82 } | |
83 | |
84 static int | |
85 insert(const char *sql, const char *fmt, ...) | |
86 { | |
87 assert(sql); | |
88 assert(fmt); | |
89 | |
90 sqlite3_stmt *stmt = NULL; | |
91 va_list ap; | |
92 | |
93 if (sqlite3_prepare(db, sql, -1, &stmt, NULL) != SQLITE_OK) | |
94 return log_warn("db: %s", sqlite3_errmsg(db)), -1; | |
95 | |
96 va_start(ap, fmt); | |
97 | |
98 for (int index = 1; *fmt; ++fmt) { | |
99 switch (*fmt) { | |
100 case 'i': | |
101 sqlite3_bind_int(stmt, index++, va_arg(ap, int)); | |
102 break; | |
103 case 's': | |
104 sqlite3_bind_text(stmt, index++, va_arg(ap, const char *), -1, SQLITE_STATIC); | |
105 break; | |
106 default: | |
107 break; | |
108 } | |
109 } | |
110 | |
111 va_end(ap); | |
112 | |
113 if (sqlite3_step(stmt) != SQLITE_DONE) { | |
114 log_warn("db: %s", sqlite3_errmsg(db)); | |
115 sqlite3_finalize(stmt); | |
116 return -1; | |
117 } | |
118 | |
119 return sqlite3_last_insert_rowid(db); | |
36 } | 120 } |
37 | 121 |
38 int | 122 int |
39 db_open(const char *path) | 123 db_open(const char *path) |
40 { | 124 { |
62 assert(pj); | 146 assert(pj); |
63 | 147 |
64 sqlite3_stmt *stmt = NULL; | 148 sqlite3_stmt *stmt = NULL; |
65 int ret = -1; | 149 int ret = -1; |
66 | 150 |
67 if (sqlite3_prepare(db, CHAR(sql_project_insert), -1, &stmt, NULL) != SQLITE_OK) | 151 if (sqlite3_prepare(db, CHAR(sql_project_add), -1, &stmt, NULL) != SQLITE_OK) |
68 goto sqlite3_err; | 152 goto sqlite3_err; |
69 | 153 |
70 sqlite3_bind_text(stmt, 1, pj->name, -1, SQLITE_STATIC); | 154 sqlite3_bind_text(stmt, 1, pj->name, -1, SQLITE_STATIC); |
71 sqlite3_bind_text(stmt, 2, pj->desc, -1, SQLITE_STATIC); | 155 sqlite3_bind_text(stmt, 2, pj->desc, -1, SQLITE_STATIC); |
72 sqlite3_bind_text(stmt, 3, pj->url, -1, SQLITE_STATIC); | 156 sqlite3_bind_text(stmt, 3, pj->url, -1, SQLITE_STATIC); |
84 | 168 |
85 return ret; | 169 return ret; |
86 } | 170 } |
87 | 171 |
88 ssize_t | 172 ssize_t |
89 db_project_get(struct project *projects, size_t projectsz) | 173 db_project_list(struct db_ctx *ctx, struct project *projects, size_t projectsz) |
90 { | 174 { |
91 assert(projects); | 175 assert(projects); |
92 | 176 |
93 sqlite3_stmt *stmt = NULL; | 177 sqlite3_stmt *stmt = NULL; |
94 struct project *p = projects; | 178 struct project *p = projects; |
95 ssize_t ret = 0; | 179 ssize_t ret = 0; |
96 | 180 |
97 if (sqlite3_prepare(db, CHAR(sql_project_get), -1, &stmt, NULL) != SQLITE_OK) { | 181 if (sqlite3_prepare(db, CHAR(sql_project_list), -1, &stmt, NULL) != SQLITE_OK) { |
98 log_warn("db: %s", sqlite3_errmsg(db)); | 182 log_warn("db: %s", sqlite3_errmsg(db)); |
99 return -1; | 183 return -1; |
100 } | 184 } |
101 | 185 |
102 sqlite3_bind_int64(stmt, 1, projectsz); | 186 sqlite3_bind_int(stmt, 1, projectsz); |
187 ctx->handle = strlist_new(); | |
103 | 188 |
104 for (; sqlite3_step(stmt) == SQLITE_ROW && (size_t)ret < projectsz; ++ret, ++p) | 189 for (; sqlite3_step(stmt) == SQLITE_ROW && (size_t)ret < projectsz; ++ret, ++p) |
105 convert_project(p, stmt); | 190 convert_project(ctx, p, stmt); |
106 | 191 |
107 if (stmt) | 192 if (stmt) |
108 sqlite3_finalize(stmt); | 193 sqlite3_finalize(stmt); |
109 | 194 |
110 return ret; | 195 return ret; |
111 } | 196 } |
112 | 197 |
113 int | 198 int |
114 db_project_find(struct project *project) | 199 db_project_find(struct db_ctx *ctx, struct project *project) |
115 { | 200 { |
201 assert(ctx); | |
116 assert(project); | 202 assert(project); |
117 | 203 |
118 sqlite3_stmt *stmt = NULL; | 204 sqlite3_stmt *stmt = NULL; |
119 int ret = -1; | 205 int ret = -1; |
120 | 206 |
207 ctx->handle = NULL; | |
208 | |
121 if (sqlite3_prepare(db, CHAR(sql_project_find), -1, &stmt, NULL) != SQLITE_OK) | 209 if (sqlite3_prepare(db, CHAR(sql_project_find), -1, &stmt, NULL) != SQLITE_OK) |
122 goto sqlite3_err; | 210 goto sqlite3_err; |
123 | 211 |
124 sqlite3_bind_text(stmt, 1, project->name, -1, SQLITE_STATIC); | 212 sqlite3_bind_text(stmt, 1, project->name, -1, SQLITE_STATIC); |
125 | 213 |
126 if (sqlite3_step(stmt) != SQLITE_ROW) | 214 if (sqlite3_step(stmt) != SQLITE_ROW) |
127 goto sqlite3_err; | 215 goto sqlite3_err; |
128 | 216 |
129 ret = 0; | 217 ret = 0; |
130 convert_project(project, stmt); | 218 ctx->handle = strlist_new(); |
131 | 219 convert_project(ctx, project, stmt); |
132 sqlite3_err: | 220 |
133 if (ret < 0) | 221 sqlite3_err: |
134 log_warn("db: %s", sqlite3_errmsg(db)); | 222 if (ret < 0) { |
223 if (ctx->handle) | |
224 db_ctx_finish(ctx); | |
225 | |
226 log_warn("db: %s", sqlite3_errmsg(db)); | |
227 } | |
228 if (stmt) | |
229 sqlite3_finalize(stmt); | |
230 | |
231 return ret; | |
232 } | |
233 | |
234 int | |
235 db_project_find_id(struct db_ctx *ctx, struct project *project) | |
236 { | |
237 assert(ctx); | |
238 assert(project); | |
239 | |
240 sqlite3_stmt *stmt = NULL; | |
241 int ret = -1; | |
242 | |
243 ctx->handle = NULL; | |
244 | |
245 if (sqlite3_prepare(db, CHAR(sql_project_find_id), -1, &stmt, NULL) != SQLITE_OK) | |
246 goto sqlite3_err; | |
247 | |
248 sqlite3_bind_int(stmt, 1, project->id); | |
249 | |
250 if (sqlite3_step(stmt) != SQLITE_ROW) | |
251 goto sqlite3_err; | |
252 | |
253 ret = 0; | |
254 ctx->handle = strlist_new(); | |
255 convert_project(ctx, project, stmt); | |
256 | |
257 sqlite3_err: | |
258 if (ret < 0) { | |
259 if (ctx->handle) | |
260 db_ctx_finish(ctx); | |
261 | |
262 log_warn("db: %s", sqlite3_errmsg(db)); | |
263 } | |
135 if (stmt) | 264 if (stmt) |
136 sqlite3_finalize(stmt); | 265 sqlite3_finalize(stmt); |
137 | 266 |
138 return ret; | 267 return ret; |
139 } | 268 } |
144 assert(wk); | 273 assert(wk); |
145 | 274 |
146 sqlite3_stmt *stmt = NULL; | 275 sqlite3_stmt *stmt = NULL; |
147 int ret = -1; | 276 int ret = -1; |
148 | 277 |
149 if (sqlite3_prepare(db, CHAR(sql_worker_insert), -1, &stmt, NULL) != SQLITE_OK) | 278 if (sqlite3_prepare(db, CHAR(sql_worker_add), -1, &stmt, NULL) != SQLITE_OK) |
150 goto sqlite3_err; | 279 goto sqlite3_err; |
151 | 280 |
152 sqlite3_bind_text(stmt, 1, wk->name, -1, SQLITE_STATIC); | 281 sqlite3_bind_text(stmt, 1, wk->name, -1, SQLITE_STATIC); |
153 sqlite3_bind_text(stmt, 2, wk->desc, -1, SQLITE_STATIC); | 282 sqlite3_bind_text(stmt, 2, wk->desc, -1, SQLITE_STATIC); |
154 | 283 |
164 | 293 |
165 return ret; | 294 return ret; |
166 } | 295 } |
167 | 296 |
168 ssize_t | 297 ssize_t |
169 db_worker_get(struct worker *wk, size_t wksz) | 298 db_worker_list(struct db_ctx *ctx, struct worker *wk, size_t wksz) |
170 { | 299 { |
300 assert(ctx); | |
171 assert(wk); | 301 assert(wk); |
172 | 302 |
173 sqlite3_stmt *stmt = NULL; | 303 sqlite3_stmt *stmt = NULL; |
174 struct worker *w = wk; | 304 struct worker *w = wk; |
175 ssize_t ret = -1; | 305 ssize_t ret = -1; |
176 | 306 |
177 if (sqlite3_prepare(db, CHAR(sql_worker_get), -1, &stmt, NULL) != SQLITE_OK) | 307 ctx->handle = NULL; |
178 goto sqlite3_err; | 308 |
179 | 309 if (sqlite3_prepare(db, CHAR(sql_worker_list), -1, &stmt, NULL) != SQLITE_OK) |
180 sqlite3_bind_int64(stmt, 1, wksz); | 310 goto sqlite3_err; |
311 | |
312 sqlite3_bind_int(stmt, 1, wksz); | |
313 ctx->handle = strlist_new(); | |
181 | 314 |
182 for (ret = 0; sqlite3_step(stmt) == SQLITE_ROW && (size_t)ret < wksz; ++ret, ++w) { | 315 for (ret = 0; sqlite3_step(stmt) == SQLITE_ROW && (size_t)ret < wksz; ++ret, ++w) { |
183 w->id = sqlite3_column_int64(stmt, 0); | 316 w->id = sqlite3_column_int(stmt, 0); |
184 strlcpy(w->name, CHAR(sqlite3_column_text(stmt, 1)), sizeof (w->name)); | 317 w->name = strlist_add(ctx->handle, CHAR(sqlite3_column_text(stmt, 1))); |
185 strlcpy(w->desc, CHAR(sqlite3_column_text(stmt, 2)), sizeof (w->desc)); | 318 w->desc = strlist_add(ctx->handle, CHAR(sqlite3_column_text(stmt, 2))); |
186 } | 319 } |
187 | 320 |
188 sqlite3_err: | 321 sqlite3_err: |
189 if (ret < 0) | 322 if (ret < 0) { |
190 log_warn("db: %s", sqlite3_errmsg(db)); | 323 if (ctx->handle) |
191 if (stmt) | 324 db_ctx_finish(ctx); |
192 sqlite3_finalize(stmt); | 325 |
193 | 326 log_warn("db: %s", sqlite3_errmsg(db)); |
194 return ret; | 327 } |
195 } | 328 if (stmt) |
196 | 329 sqlite3_finalize(stmt); |
197 int | 330 |
198 db_worker_find(struct worker *w) | 331 return ret; |
199 { | 332 } |
333 | |
334 int | |
335 db_worker_find(struct db_ctx *ctx, struct worker *w) | |
336 { | |
337 assert(ctx); | |
200 assert(w); | 338 assert(w); |
201 | 339 |
202 sqlite3_stmt *stmt = NULL; | 340 sqlite3_stmt *stmt = NULL; |
203 int ret = -1; | 341 int ret = -1; |
204 | 342 |
343 ctx->handle = NULL; | |
344 | |
205 if (sqlite3_prepare(db, CHAR(sql_worker_find), -1, &stmt, NULL) != SQLITE_OK) | 345 if (sqlite3_prepare(db, CHAR(sql_worker_find), -1, &stmt, NULL) != SQLITE_OK) |
206 goto sqlite3_err; | 346 goto sqlite3_err; |
207 | 347 |
208 sqlite3_bind_text(stmt, 1, w->name, -1, SQLITE_STATIC); | 348 sqlite3_bind_text(stmt, 1, w->name, -1, SQLITE_STATIC); |
209 | 349 |
210 if (sqlite3_step(stmt) != SQLITE_ROW) | 350 if (sqlite3_step(stmt) != SQLITE_ROW) |
211 goto sqlite3_err; | 351 goto sqlite3_err; |
212 | 352 |
213 ret = 0; | 353 ret = 0; |
214 w->id = sqlite3_column_int64(stmt, 0); | 354 ctx->handle = strlist_new(); |
215 strlcpy(w->name, CHAR(sqlite3_column_text(stmt, 1)), sizeof (w->name)); | 355 w->id = sqlite3_column_int(stmt, 0); |
216 strlcpy(w->desc, CHAR(sqlite3_column_text(stmt, 2)), sizeof (w->desc)); | 356 w->name = strlist_add(ctx->handle, CHAR(sqlite3_column_text(stmt, 1))); |
217 | 357 w->desc = strlist_add(ctx->handle, CHAR(sqlite3_column_text(stmt, 2))); |
218 sqlite3_err: | 358 |
219 if (ret < 0) | 359 sqlite3_err: |
220 log_warn("db: %s", sqlite3_errmsg(db)); | 360 if (ret < 0) { |
221 if (stmt) | 361 if (ctx->handle) |
222 sqlite3_finalize(stmt); | 362 db_ctx_finish(ctx); |
223 | 363 |
224 return ret; | 364 log_warn("db: %s", sqlite3_errmsg(db)); |
225 } | 365 } |
226 | 366 if (stmt) |
227 int | 367 sqlite3_finalize(stmt); |
228 db_job_queue(struct job *job) | 368 |
369 return ret; | |
370 } | |
371 | |
372 int | |
373 db_worker_find_id(struct db_ctx *ctx, struct worker *w) | |
374 { | |
375 assert(ctx); | |
376 assert(w); | |
377 | |
378 sqlite3_stmt *stmt = NULL; | |
379 int ret = -1; | |
380 | |
381 ctx->handle = NULL; | |
382 | |
383 if (sqlite3_prepare(db, CHAR(sql_worker_find_id), -1, &stmt, NULL) != SQLITE_OK) | |
384 goto sqlite3_err; | |
385 | |
386 sqlite3_bind_int(stmt, 1, w->id); | |
387 | |
388 if (sqlite3_step(stmt) != SQLITE_ROW) | |
389 goto sqlite3_err; | |
390 | |
391 ret = 0; | |
392 ctx->handle = strlist_new(); | |
393 w->id = sqlite3_column_int(stmt, 0); | |
394 w->name = strlist_add(ctx->handle, CHAR(sqlite3_column_text(stmt, 1))); | |
395 w->desc = strlist_add(ctx->handle, CHAR(sqlite3_column_text(stmt, 2))); | |
396 | |
397 sqlite3_err: | |
398 if (ret < 0) { | |
399 if (ctx->handle) | |
400 db_ctx_finish(ctx); | |
401 | |
402 log_warn("db: %s", sqlite3_errmsg(db)); | |
403 } | |
404 if (stmt) | |
405 sqlite3_finalize(stmt); | |
406 | |
407 return ret; | |
408 } | |
409 | |
410 int | |
411 db_job_add(struct job *job) | |
229 { | 412 { |
230 assert(job); | 413 assert(job); |
231 | 414 |
232 sqlite3_stmt *stmt = NULL; | 415 job->id = insert(CHAR(sql_job_add), "si", job->tag, job->project_id); |
233 int ret = -1; | 416 |
234 | 417 return job->id < 0 ? -1 : 0; |
235 if (sqlite3_prepare(db, CHAR(sql_job_queue), -1, &stmt, NULL) != SQLITE_OK) | |
236 goto sqlite3_err; | |
237 | |
238 sqlite3_bind_text(stmt, 1, job->tag, -1, SQLITE_STATIC); | |
239 sqlite3_bind_int64(stmt, 2, job->project.id); | |
240 | |
241 if (sqlite3_step(stmt) != SQLITE_DONE) | |
242 goto sqlite3_err; | |
243 | |
244 job->id = sqlite3_last_insert_rowid(db); | |
245 ret = 0; | |
246 | |
247 sqlite3_err: | |
248 if (ret < 0) | |
249 log_warn("db: %s", sqlite3_errmsg(db)); | |
250 if (stmt) | |
251 sqlite3_finalize(stmt); | |
252 | |
253 return ret; | |
254 } | 418 } |
255 | 419 |
256 ssize_t | 420 ssize_t |
257 db_job_result_todo(struct job_result *re, size_t resz, int64_t worker_id) | 421 db_job_todo(struct db_ctx *ctx, struct job *jobs, size_t jobsz, int worker_id) |
258 { | 422 { |
259 assert(re); | 423 assert(ctx); |
424 assert(jobs); | |
260 | 425 |
261 sqlite3_stmt *stmt = NULL; | 426 sqlite3_stmt *stmt = NULL; |
262 ssize_t ret = 0; | 427 ssize_t ret = 0; |
263 | 428 |
264 if (sqlite3_prepare(db, CHAR(sql_job_result_todo), -1, &stmt, NULL) != SQLITE_OK) { | 429 if (sqlite3_prepare(db, CHAR(sql_job_todo), -1, &stmt, NULL) != SQLITE_OK) { |
265 log_warn("db: %s", sqlite3_errmsg(db)); | 430 log_warn("db: %s", sqlite3_errmsg(db)); |
266 return -1; | 431 return -1; |
267 } | 432 } |
268 | 433 |
269 sqlite3_bind_int64(stmt, 1, worker_id); | 434 sqlite3_bind_int(stmt, 1, worker_id); |
270 sqlite3_bind_int64(stmt, 2, resz); | 435 sqlite3_bind_int(stmt, 2, jobsz); |
271 | 436 ctx->handle = strlist_new(); |
272 while (sqlite3_step(stmt) == SQLITE_ROW && (size_t)ret++ < resz) { | 437 |
273 memset(re, 0, sizeof (*re)); | 438 while (sqlite3_step(stmt) == SQLITE_ROW && (size_t)ret++ < jobsz) { |
274 re->job.id = sqlite3_column_int64(stmt, 0); | 439 jobs->id = sqlite3_column_int(stmt, 0); |
275 strlcpy(re->job.tag, CHAR(sqlite3_column_text(stmt, 1)), | 440 jobs->tag = strlist_add(ctx->handle, CHAR(sqlite3_column_text(stmt, 1))); |
276 sizeof (re->job.tag)); | 441 jobs++->project_id = sqlite3_column_int(stmt, 2); |
277 strlcpy(re->job.project.name, CHAR(sqlite3_column_text(stmt, 2)), | |
278 sizeof (re->job.project.name)); | |
279 | |
280 ++re; | |
281 }; | 442 }; |
282 | 443 |
283 if (stmt) | 444 sqlite3_finalize(stmt); |
284 sqlite3_finalize(stmt); | 445 |
285 | 446 return ret; |
286 return ret; | 447 } |
287 } | 448 |
288 | 449 int |
289 int | 450 db_jobresult_add(struct jobresult *r) |
290 db_job_save(struct job_result *r) | |
291 { | 451 { |
292 assert(r); | 452 assert(r); |
293 | 453 |
294 sqlite3_stmt *stmt = NULL; | 454 r->id = insert(CHAR(sql_jobresult_add), "iiis", r->job_id, |
295 int ret = -1; | 455 r->worker_id, r->exitcode, r->log); |
296 | 456 |
297 if (sqlite3_prepare(db, CHAR(sql_job_save), -1, &stmt, NULL) != SQLITE_OK) | 457 return r->id < 0 ? -1 : 0; |
298 goto sqlite3_err; | |
299 | |
300 sqlite3_bind_int64(stmt, 1, r->job.id); | |
301 sqlite3_bind_int64(stmt, 2, r->worker.id); | |
302 sqlite3_bind_int(stmt, 3, r->status); | |
303 sqlite3_bind_int(stmt, 4, r->retcode); | |
304 sqlite3_bind_text(stmt, 5, r->console, -1, SQLITE_STATIC); | |
305 | |
306 if (sqlite3_step(stmt) != SQLITE_DONE) | |
307 goto sqlite3_err; | |
308 | |
309 ret = 0; | |
310 r->id = sqlite3_last_insert_rowid(db); | |
311 | |
312 sqlite3_err: | |
313 if (ret < 0) | |
314 log_warn("db: %s", sqlite3_errmsg(db)); | |
315 if (stmt) | |
316 sqlite3_finalize(stmt); | |
317 | |
318 return ret; | |
319 } | 458 } |
320 | 459 |
321 void | 460 void |
322 db_finish(void) | 461 db_finish(void) |
323 { | 462 { |
324 if (db) { | 463 if (db) { |
325 sqlite3_close(db); | 464 sqlite3_close(db); |
326 db = NULL; | 465 db = NULL; |
327 } | 466 } |
328 } | 467 } |
468 | |
469 void | |
470 db_ctx_finish(struct db_ctx *ctx) | |
471 { | |
472 if (ctx->handle) { | |
473 strlist_free(ctx->handle); | |
474 ctx->handle = NULL; | |
475 } | |
476 } |