]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/db.c
libpakfire: db: Add packages to database when installed
[people/ms/pakfire.git] / src / libpakfire / db.c
CommitLineData
33d55ab4
MT
1/*#############################################################################
2# #
3# Pakfire - The IPFire package management system #
4# Copyright (C) 2021 Pakfire development team #
5# #
6# This program is free software: you can redistribute it and/or modify #
7# it under the terms of the GNU General Public License as published by #
8# the Free Software Foundation, either version 3 of the License, or #
9# (at your option) any later version. #
10# #
11# This program is distributed in the hope that it will be useful, #
12# but WITHOUT ANY WARRANTY; without even the implied warranty of #
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14# GNU General Public License for more details. #
15# #
16# You should have received a copy of the GNU General Public License #
17# along with this program. If not, see <http://www.gnu.org/licenses/>. #
18# #
19#############################################################################*/
20
21#include <errno.h>
22#include <stdlib.h>
23
26affd69
MT
24#include <sqlite3.h>
25
33d55ab4 26#include <pakfire/db.h>
33d55ab4 27#include <pakfire/logging.h>
e49b93d1 28#include <pakfire/package.h>
18bf891d
MT
29#include <pakfire/pakfire.h>
30#include <pakfire/private.h>
e49b93d1 31#include <pakfire/repo.h>
33d55ab4
MT
32#include <pakfire/types.h>
33#include <pakfire/util.h>
34
0cb487ff
MT
35#define DATABASE_PATH PAKFIRE_PRIVATE_DIR "/packages.db"
36
c745fb2d
MT
37#define CURRENT_SCHEMA 7
38#define SCHEMA_MIN_SUP 7
39
33d55ab4
MT
40struct pakfire_db {
41 Pakfire pakfire;
42 int nrefs;
77a4b3a3
MT
43
44 int mode;
26affd69
MT
45
46 sqlite3* handle;
c745fb2d 47 int schema;
33d55ab4
MT
48};
49
9c5938ea
MT
50static void logging_callback(void* data, int r, const char* msg) {
51 Pakfire pakfire = (Pakfire)data;
52
53 ERROR(pakfire, "Database Error: %s: %s\n",
54 sqlite3_errstr(r), msg);
55}
56
0076c50d
MT
57static int pakfire_db_execute(struct pakfire_db* db, const char* stmt) {
58 int r;
c745fb2d
MT
59
60 DEBUG(db->pakfire, "Executing database query: %s\n", stmt);
0076c50d
MT
61
62 do {
c745fb2d 63 r = sqlite3_exec(db->handle, stmt, NULL, NULL, NULL);
0076c50d
MT
64 } while (r == SQLITE_BUSY);
65
c745fb2d
MT
66 // Log any errors
67 if (r) {
68 ERROR(db->pakfire, "Database query failed: %s\n", sqlite3_errmsg(db->handle));
69 }
70
25753290
MT
71 return r;
72}
73
c745fb2d
MT
74static int pakfire_db_begin_transaction(struct pakfire_db* db) {
75 return pakfire_db_execute(db, "BEGIN TRANSACTION");
76}
77
78static int pakfire_db_commit(struct pakfire_db* db) {
79 return pakfire_db_execute(db, "COMMIT");
80}
81
82static int pakfire_db_rollback(struct pakfire_db* db) {
83 return pakfire_db_execute(db, "ROLLBACK");
84}
85
25753290
MT
86/*
87 This function performs any fast optimization and tries to truncate the WAL log file
88 to keep the database as compact as possible on disk.
89*/
90static void pakfire_db_optimize(struct pakfire_db* db) {
91 pakfire_db_execute(db, "PRAGMA optmize");
92 pakfire_db_execute(db, "PRAGMA wal_checkpoint = TRUNCATE");
0076c50d
MT
93}
94
26affd69
MT
95static void pakfire_db_free(struct pakfire_db* db) {
96 DEBUG(db->pakfire, "Releasing database at %p\n", db);
97
26affd69 98 if (db->handle) {
25753290
MT
99 // Optimize the database before it is being closed
100 pakfire_db_optimize(db);
101
102 // Close database handle
26affd69
MT
103 int r = sqlite3_close(db->handle);
104 if (r != SQLITE_OK) {
105 ERROR(db->pakfire, "Could not close database handle: %s\n",
106 sqlite3_errmsg(db->handle));
107 }
108 }
109
110 pakfire_unref(db->pakfire);
111
112 pakfire_free(db);
113}
114
c745fb2d
MT
115static sqlite3_value* pakfire_db_get(struct pakfire_db* db, const char* key) {
116 sqlite3_stmt* stmt = NULL;
117 sqlite3_value* val = NULL;
118 int r;
119
120 const char* sql = "SELECT val FROM settings WHERE key = ?";
121
122 // Prepare the statement
123 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
124 if (r != SQLITE_OK) {
125 //ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
126 // sql, sqlite3_errmsg(db->handle));
127 return NULL;
128 }
129
130 // Bind key
131 r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
132 if (r != SQLITE_OK) {
133 ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
134 goto ERROR;
135 }
136
137 // Execute the statement
138 do {
139 r = sqlite3_step(stmt);
140 } while (r == SQLITE_BUSY);
141
142 // Read value
143 val = sqlite3_column_value(stmt, 1);
144 if (!val) {
145 ERROR(db->pakfire, "Could not read value\n");
146 goto ERROR;
147 }
148
149 // Copy value onto the heap
150 val = sqlite3_value_dup(val);
151
152ERROR:
153 if (stmt)
154 sqlite3_finalize(stmt);
155
156 return val;
157}
158
159static int pakfire_db_set_int(struct pakfire_db* db, const char* key, int val) {
160 sqlite3_stmt* stmt = NULL;
161 int r;
162
163 const char* sql = "INSERT INTO settings(key, val) VALUES(?, ?) \
164 ON CONFLICT (key) DO UPDATE SET val = excluded.val";
165
166 // Prepare statement
167 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
168 if (r != SQLITE_OK) {
169 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
170 sql, sqlite3_errmsg(db->handle));
171 return 1;
172 }
173
174 // Bind key
175 r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
176 if (r != SQLITE_OK) {
177 ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
178 goto ERROR;
179 }
180
181 // Bind val
182 r = sqlite3_bind_int64(stmt, 2, val);
183 if (r != SQLITE_OK) {
184 ERROR(db->pakfire, "Could not bind val: %s\n", sqlite3_errmsg(db->handle));
185 goto ERROR;
186 }
187
188 // Execute the statement
189 do {
190 r = sqlite3_step(stmt);
191 } while (r == SQLITE_BUSY);
192
193 // Set return code
194 r = (r == SQLITE_OK);
195
196ERROR:
197 if (stmt)
198 sqlite3_finalize(stmt);
199
200 return r;
201}
202
203static int pakfire_db_get_schema(struct pakfire_db* db) {
204 sqlite3_value* value = pakfire_db_get(db, "schema");
205 if (!value)
206 return 0;
207
208 int schema = sqlite3_value_int64(value);
209 sqlite3_value_free(value);
210
211 DEBUG(db->pakfire, "Database has schema version %d\n", schema);
212
213 return schema;
214}
215
216static int pakfire_db_create_schema(struct pakfire_db* db) {
217 int r;
218
219 // Create settings table
220 r = pakfire_db_execute(db, "CREATE TABLE IF NOT EXISTS settings(key TEXT, val TEXT)");
221 if (r)
222 return 1;
223
224 // settings: Add a unique index on key
225 r = pakfire_db_execute(db, "CREATE UNIQUE INDEX IF NOT EXISTS settings_key ON settings(key)");
226 if (r)
227 return 1;
228
704b3993
MT
229 // Create packages table
230 r = pakfire_db_execute(db,
231 "CREATE TABLE IF NOT EXISTS packages("
232 "id INTEGER PRIMARY KEY, "
233 "name TEXT, "
234 "epoch INTEGER, "
235 "version TEXT, "
236 "release TEXT, "
237 "arch TEXT, "
238 "groups TEXT, "
239 "filename TEXT, "
240 "size INTEGER, "
241 "inst_size INTEGER, "
242 "hash1 TEXT, "
243 "license TEXT, "
244 "summary TEXT, "
245 "description TEXT, "
246 "uuid TEXT, "
247 "vendor TEXT, "
248 "build_id TEXT, "
249 "build_host TEXT, "
250 "build_date TEXT, "
251 "build_time INTEGER, "
252 "installed INTEGER, "
253 "reason TEXT, "
254 "repository TEXT"
255 ")");
256 if (r)
257 return 1;
258
259 // packages: Create index to find package by name
260 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS packages_name ON packages(name)");
261 if (r)
262 return 1;
263
2359ca14
MT
264 // Create dependencies table
265 r = pakfire_db_execute(db,
266 "CREATE TABLE IF NOT EXISTS dependencies("
267 "pkg INTEGER, "
268 "type TEXT, "
46257c5f
MT
269 "dependency TEXT, "
270 "FOREIGN KEY (pkg) REFERENCES packages(id)"
2359ca14
MT
271 ")");
272 if (r)
273 return r;
274
275 // dependencies: Add index over packages
276 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS dependencies_pkg_index ON dependencies(pkg)");
277 if (r)
278 return r;
279
68036506
MT
280 // Create files table
281 r = pakfire_db_execute(db,
282 "CREATE TABLE IF NOT EXISTS files("
283 "id INTEGER PRIMARY KEY, "
284 "name TEXT, "
285 "pkg INTEGER, "
286 "size INTEGER, "
287 "type INTEGER, "
288 "config INTEGER, "
289 "datafile INTEGER, "
290 "mode INTEGER, "
291 "user TEXT, "
292 "'group' TEXT, "
293 "hash1 TEXT, "
294 "mtime INTEGER, "
46257c5f
MT
295 "capabilities TEXT, "
296 "FOREIGN KEY (pkg) REFERENCES packages(id)"
68036506
MT
297 ")");
298 if (r)
299 return 1;
300
301 // files: Add index over packages
302 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS files_pkg_index ON files(pkg)");
303 if (r)
304 return 1;
305
d83414aa
MT
306 // Create scriptlets table
307 r = pakfire_db_execute(db,
308 "CREATE TABLE IF NOT EXISTS scriptlets("
309 "id INTEGER PRIMARY KEY, "
310 "pkg INTEGER, "
311 "action TEXT, "
46257c5f
MT
312 "scriptlet TEXT, "
313 "FOREIGN KEY (pkg) REFERENCES packages(id)"
d83414aa
MT
314 ")");
315 if (r)
316 return 1;
317
318 // scriptlets: Add index over packages
319 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS scriptlets_pkg_index ON scriptlets(pkg)");
320 if (r)
321 return 1;
322
c745fb2d
MT
323 return 0;
324}
325
46257c5f
MT
326static int pakfire_db_migrate_to_schema_8(struct pakfire_db* db) {
327 // Add foreign keys
328 // TODO sqlite doesn't support adding foreign keys to existing tables and so we would
329 // need to recreate the whole table and rename it afterwards. Annoying.
330
331 return 0;
332}
333
c745fb2d
MT
334static int pakfire_db_migrate_schema(struct pakfire_db* db) {
335 int r;
336
337 while (db->schema < CURRENT_SCHEMA) {
338 // Begin a new transaction
339 r = pakfire_db_begin_transaction(db);
340 if (r)
341 goto ROLLBACK;
342
343 switch (db->schema) {
344 // No schema exists
345 case 0:
346 r = pakfire_db_create_schema(db);
347 if (r)
348 goto ROLLBACK;
349
350 db->schema = CURRENT_SCHEMA;
351 break;
352
46257c5f
MT
353 case 7:
354 r = pakfire_db_migrate_to_schema_8(db);
355 if (r)
356 goto ROLLBACK;
357
358 db->schema++;
359 break;
360
c745fb2d
MT
361 default:
362 ERROR(db->pakfire, "Cannot migrate database from schema %d\n", db->schema);
363 goto ROLLBACK;
364 }
365
366 // Update the schema version
367 r = pakfire_db_set_int(db, "schema", CURRENT_SCHEMA);
368 if (r)
369 goto ROLLBACK;
370
371 // All done, commit!
372 r = pakfire_db_commit(db);
373 if (r)
374 goto ROLLBACK;
375 }
376
377 return 0;
378
379ROLLBACK:
380 pakfire_db_rollback(db);
381
382 return 1;
383}
384
9c5938ea 385static int pakfire_db_setup(struct pakfire_db* db) {
25753290
MT
386 int r;
387
9c5938ea
MT
388 // Setup logging
389 sqlite3_config(SQLITE_CONFIG_LOG, logging_callback, db->pakfire);
390
46257c5f
MT
391 // Enable foreign keys
392 pakfire_db_execute(db, "PRAGMA foreign_keys = ON");
393
0076c50d
MT
394 // Make LIKE case-sensitive
395 pakfire_db_execute(db, "PRAGMA case_sensitive_like = ON");
396
c745fb2d
MT
397 // Fetch the current schema
398 db->schema = pakfire_db_get_schema(db);
399
400 // Check if the schema is recent enough
401 if (db->schema > 0 && db->schema < SCHEMA_MIN_SUP) {
402 ERROR(db->pakfire, "Database schema %d is not supported by this version of Pakfire\n",
403 db->schema);
404 return 1;
405 }
406
9c5938ea
MT
407 // Done when not in read-write mode
408 if (db->mode != PAKFIRE_DB_READWRITE)
409 return 0;
410
0076c50d
MT
411 // Disable secure delete
412 pakfire_db_execute(db, "PRAGMA secure_delete = OFF");
413
25753290
MT
414 // Set database journal to WAL
415 r = pakfire_db_execute(db, "PRAGMA journal_mode = WAL");
416 if (r != SQLITE_OK) {
417 ERROR(db->pakfire, "Could not set journal mode to WAL: %s\n",
418 sqlite3_errmsg(db->handle));
419 return 1;
420 }
421
422 // Disable autocheckpoint
423 r = sqlite3_wal_autocheckpoint(db->handle, 0);
424 if (r != SQLITE_OK) {
425 ERROR(db->pakfire, "Could not disable autocheckpoint: %s\n",
426 sqlite3_errmsg(db->handle));
427 return 1;
428 }
429
c745fb2d
MT
430 // Create or migrate schema
431 r = pakfire_db_migrate_schema(db);
432 if (r)
433 return r;
9c5938ea
MT
434
435 return 0;
436}
437
77a4b3a3 438PAKFIRE_EXPORT int pakfire_db_open(struct pakfire_db** db, Pakfire pakfire, int flags) {
26affd69
MT
439 int r = 1;
440
33d55ab4
MT
441 struct pakfire_db* o = pakfire_calloc(1, sizeof(*o));
442 if (!o)
443 return -ENOMEM;
444
445 DEBUG(pakfire, "Allocated database at %p\n", o);
446
447 o->pakfire = pakfire_ref(pakfire);
448 o->nrefs = 1;
449
26affd69
MT
450 int sqlite3_flags = 0;
451
452 // Store mode & forward it to sqlite3
453 if (flags & PAKFIRE_DB_READWRITE) {
77a4b3a3 454 o->mode = PAKFIRE_DB_READWRITE;
26affd69
MT
455 sqlite3_flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
456 } else {
77a4b3a3 457 o->mode = PAKFIRE_DB_READONLY;
26affd69
MT
458 sqlite3_flags |= SQLITE_OPEN_READONLY;
459 }
460
461 // Make the filename
462 char* path = pakfire_make_path(o->pakfire, DATABASE_PATH);
463 if (!path)
464 goto END;
465
466 // Try to open the sqlite3 database file
467 r = sqlite3_open_v2(path, &o->handle, sqlite3_flags, NULL);
468 if (r != SQLITE_OK) {
469 ERROR(pakfire, "Could not open database %s: %s\n",
470 path, sqlite3_errmsg(o->handle));
471
472 r = 1;
473 goto END;
474 }
77a4b3a3 475
9c5938ea
MT
476 // Setup the database
477 r = pakfire_db_setup(o);
478 if (r)
479 goto END;
480
33d55ab4 481 *db = o;
26affd69
MT
482 r = 0;
483
484END:
485 if (r)
486 pakfire_db_free(o);
33d55ab4 487
26affd69
MT
488 if (path)
489 free(path);
490
491 return r;
33d55ab4
MT
492}
493
18bf891d 494PAKFIRE_EXPORT struct pakfire_db* pakfire_db_ref(struct pakfire_db* db) {
33d55ab4
MT
495 db->nrefs++;
496
497 return db;
498}
499
18bf891d 500PAKFIRE_EXPORT struct pakfire_db* pakfire_db_unref(struct pakfire_db* db) {
33d55ab4
MT
501 if (--db->nrefs > 0)
502 return db;
503
504 pakfire_db_free(db);
505
506 return NULL;
507}
eafbe2ce 508
18bf891d 509PAKFIRE_EXPORT int pakfire_db_add_package(struct pakfire_db* db, PakfirePackage pkg) {
e49b93d1
MT
510 sqlite3_stmt* stmt = NULL;
511 int r;
512
513 // Begin a new transaction
514 r = pakfire_db_begin_transaction(db);
515 if (r)
516 goto ROLLBACK;
517
518 const char* sql = "INSERT INTO packages(name, epoch, version, release, arch, groups, "
519 "filename, size, inst_size, hash1, license, summary, description, uuid, vendor, "
520 "build_id, build_host, build_time, installed, repository, reason) VALUES(?, ?, "
521 "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)";
522
523 // Prepare the statement
524 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
525 if (r != SQLITE_OK) {
526 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
527 sql, sqlite3_errmsg(db->handle));
528 goto ROLLBACK;
529 }
530
531 // Bind name
532 const char* name = pakfire_package_get_name(pkg);
533
534 r = sqlite3_bind_text(stmt, 1, name, -1, NULL);
535 if (r) {
536 ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
537 goto ROLLBACK;
538 }
539
540 // Bind epoch
541 unsigned long epoch = pakfire_package_get_epoch(pkg);
542
543 r = sqlite3_bind_int64(stmt, 2, epoch);
544 if (r) {
545 ERROR(db->pakfire, "Could not bind epoch: %s\n", sqlite3_errmsg(db->handle));
546 goto ROLLBACK;
547 }
548
549 // Bind version
550 const char* version = pakfire_package_get_version(pkg);
551
552 r = sqlite3_bind_text(stmt, 3, version, -1, NULL);
553 if (r) {
554 ERROR(db->pakfire, "Could not bind version: %s\n", sqlite3_errmsg(db->handle));
555 goto ROLLBACK;
556 }
557
558 // Bind release
559 const char* release = pakfire_package_get_release(pkg);
560
561 r = sqlite3_bind_text(stmt, 4, release, -1, NULL);
562 if (r) {
563 ERROR(db->pakfire, "Could not bind release: %s\n", sqlite3_errmsg(db->handle));
564 goto ROLLBACK;
565 }
566
567 // Bind arch
568 const char* arch = pakfire_package_get_arch(pkg);
569
570 r = sqlite3_bind_text(stmt, 5, arch, -1, NULL);
571 if (r) {
572 ERROR(db->pakfire, "Could not bind arch: %s\n", sqlite3_errmsg(db->handle));
573 goto ROLLBACK;
574 }
575
576 // Bind groups
577 const char* groups = pakfire_package_get_groups(pkg);
578
579 r = sqlite3_bind_text(stmt, 6, groups, -1, NULL);
580 if (r) {
581 ERROR(db->pakfire, "Could not bind groups: %s\n", sqlite3_errmsg(db->handle));
582 goto ROLLBACK;
583 }
584
585 // Bind filename
586 const char* filename = pakfire_package_get_filename(pkg);
587
588 r = sqlite3_bind_text(stmt, 7, filename, -1, NULL);
589 if (r) {
590 ERROR(db->pakfire, "Could not bind filename: %s\n", sqlite3_errmsg(db->handle));
591 goto ROLLBACK;
592 }
593
594 // Bind size
595 unsigned long long size = pakfire_package_get_downloadsize(pkg);
596
597 r = sqlite3_bind_int64(stmt, 8, size);
598 if (r) {
599 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
600 goto ROLLBACK;
601 }
602
603 // Bind installed size
604 unsigned long long inst_size = pakfire_package_get_installsize(pkg);
605
606 r = sqlite3_bind_int64(stmt, 9, inst_size);
607 if (r) {
608 ERROR(db->pakfire, "Could not bind inst_size: %s\n", sqlite3_errmsg(db->handle));
609 goto ROLLBACK;
610 }
611
612 // Bind hash1
613 const char* hash1 = pakfire_package_get_checksum(pkg);
614
615 r = sqlite3_bind_text(stmt, 10, hash1, -1, NULL);
616 if (r) {
617 ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle));
618 goto ROLLBACK;
619 }
620
621 // Bind license
622 const char* license = pakfire_package_get_license(pkg);
623
624 r = sqlite3_bind_text(stmt, 11, license, -1, NULL);
625 if (r) {
626 ERROR(db->pakfire, "Could not bind license: %s\n", sqlite3_errmsg(db->handle));
627 goto ROLLBACK;
628 }
629
630 // Bind summary
631 const char* summary = pakfire_package_get_summary(pkg);
632
633 r = sqlite3_bind_text(stmt, 12, summary, -1, NULL);
634 if (r) {
635 ERROR(db->pakfire, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle));
636 goto ROLLBACK;
637 }
638
639 // Bind description
640 const char* description = pakfire_package_get_description(pkg);
641
642 r = sqlite3_bind_text(stmt, 13, description, -1, NULL);
643 if (r) {
644 ERROR(db->pakfire, "Could not bind description: %s\n", sqlite3_errmsg(db->handle));
645 goto ROLLBACK;
646 }
647
648 // Bind uuid
649 const char* uuid = pakfire_package_get_uuid(pkg);
650
651 r = sqlite3_bind_text(stmt, 14, uuid, -1, NULL);
652 if (r) {
653 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
654 goto ROLLBACK;
655 }
656
657 // Bind vendor
658 const char* vendor = pakfire_package_get_vendor(pkg);
659
660 r = sqlite3_bind_text(stmt, 14, vendor, -1, NULL);
661 if (r) {
662 ERROR(db->pakfire, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle));
663 goto ROLLBACK;
664 }
665
666 // Bind build_id
667#if 0
668 const char* build_id = pakfire_package_get_buildid(pkg);
669#else
670 const char* build_id = NULL; // To be done
671#endif
672
673 r = sqlite3_bind_text(stmt, 15, build_id, -1, NULL);
674 if (r) {
675 ERROR(db->pakfire, "Could not bind build_id: %s\n", sqlite3_errmsg(db->handle));
676 goto ROLLBACK;
677 }
678
679 // Bind build_host
680 const char* buildhost = pakfire_package_get_buildhost(pkg);
681
682 r = sqlite3_bind_text(stmt, 16, buildhost, -1, NULL);
683 if (r) {
684 ERROR(db->pakfire, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle));
685 goto ROLLBACK;
686 }
687
688 // Bind build_time
689 unsigned long long build_time = pakfire_package_get_buildtime(pkg);
690
691 r = sqlite3_bind_int64(stmt, 17, build_time);
692 if (r) {
693 ERROR(db->pakfire, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle));
694 goto ROLLBACK;
695 }
696
697 // Bind repository name
698 PakfireRepo repo = pakfire_package_get_repo(pkg);
699 if (repo) {
700 const char* repo_name = pakfire_repo_get_name(repo);
701 pakfire_repo_unref(repo);
702
703 r = sqlite3_bind_text(stmt, 18, repo_name, -1, NULL);
704 if (r)
705 goto ROLLBACK;
706
707 // No repository?
708 } else {
709 r = sqlite3_bind_null(stmt, 18);
710 if (r)
711 goto ROLLBACK;
712 }
713
714 // XXX TODO Bind reason
715 r = sqlite3_bind_null(stmt, 19);
716 if (r)
717 goto ROLLBACK;
718
719 // Run query
720 do {
721 r = sqlite3_step(stmt);
722 } while (r == SQLITE_BUSY);
723
724 if (r != SQLITE_DONE) {
725 ERROR(db->pakfire, "Could not add package to database: %s\n",
726 sqlite3_errmsg(db->handle));
727 goto ROLLBACK;
728 }
729
730 // This is done
731 sqlite3_finalize(stmt);
732
733 // All done, commit!
734 r = pakfire_db_commit(db);
735 if (r)
736 goto ROLLBACK;
737
738 return 0;
739
740ROLLBACK:
741 sqlite3_finalize(stmt);
742
743 pakfire_db_rollback(db);
744
745 return 1;
eafbe2ce
MT
746}
747
18bf891d 748PAKFIRE_EXPORT int pakfire_db_remove_package(struct pakfire_db* db, PakfirePackage pkg) {
eafbe2ce
MT
749 return 0; // TODO
750}