]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/db.c
libpakfire: steps: Make them independent from libsolv
[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
5ba550fe 37#define CURRENT_SCHEMA 8
c745fb2d
MT
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) {
44d392ef 91 pakfire_db_execute(db, "PRAGMA optimize");
25753290 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
f168dd0c
MT
142 // We should have read a row
143 if (r != SQLITE_ROW)
144 goto ERROR;
145
c745fb2d 146 // Read value
f168dd0c 147 val = sqlite3_column_value(stmt, 0);
c745fb2d
MT
148 if (!val) {
149 ERROR(db->pakfire, "Could not read value\n");
150 goto ERROR;
151 }
152
153 // Copy value onto the heap
154 val = sqlite3_value_dup(val);
155
156ERROR:
157 if (stmt)
158 sqlite3_finalize(stmt);
159
160 return val;
161}
162
163static int pakfire_db_set_int(struct pakfire_db* db, const char* key, int val) {
164 sqlite3_stmt* stmt = NULL;
165 int r;
166
167 const char* sql = "INSERT INTO settings(key, val) VALUES(?, ?) \
168 ON CONFLICT (key) DO UPDATE SET val = excluded.val";
169
170 // Prepare statement
171 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
172 if (r != SQLITE_OK) {
173 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
174 sql, sqlite3_errmsg(db->handle));
175 return 1;
176 }
177
178 // Bind key
179 r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
180 if (r != SQLITE_OK) {
181 ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
182 goto ERROR;
183 }
184
185 // Bind val
186 r = sqlite3_bind_int64(stmt, 2, val);
187 if (r != SQLITE_OK) {
188 ERROR(db->pakfire, "Could not bind val: %s\n", sqlite3_errmsg(db->handle));
189 goto ERROR;
190 }
191
192 // Execute the statement
193 do {
194 r = sqlite3_step(stmt);
195 } while (r == SQLITE_BUSY);
196
197 // Set return code
198 r = (r == SQLITE_OK);
199
200ERROR:
201 if (stmt)
202 sqlite3_finalize(stmt);
203
204 return r;
205}
206
207static int pakfire_db_get_schema(struct pakfire_db* db) {
208 sqlite3_value* value = pakfire_db_get(db, "schema");
209 if (!value)
f168dd0c 210 return -1;
c745fb2d
MT
211
212 int schema = sqlite3_value_int64(value);
213 sqlite3_value_free(value);
214
215 DEBUG(db->pakfire, "Database has schema version %d\n", schema);
216
217 return schema;
218}
219
220static int pakfire_db_create_schema(struct pakfire_db* db) {
221 int r;
222
223 // Create settings table
224 r = pakfire_db_execute(db, "CREATE TABLE IF NOT EXISTS settings(key TEXT, val TEXT)");
225 if (r)
226 return 1;
227
228 // settings: Add a unique index on key
229 r = pakfire_db_execute(db, "CREATE UNIQUE INDEX IF NOT EXISTS settings_key ON settings(key)");
230 if (r)
231 return 1;
232
704b3993
MT
233 // Create packages table
234 r = pakfire_db_execute(db,
235 "CREATE TABLE IF NOT EXISTS packages("
236 "id INTEGER PRIMARY KEY, "
237 "name TEXT, "
238 "epoch INTEGER, "
239 "version TEXT, "
240 "release TEXT, "
241 "arch TEXT, "
242 "groups TEXT, "
243 "filename TEXT, "
244 "size INTEGER, "
245 "inst_size INTEGER, "
246 "hash1 TEXT, "
247 "license TEXT, "
248 "summary TEXT, "
249 "description TEXT, "
250 "uuid TEXT, "
251 "vendor TEXT, "
704b3993
MT
252 "build_host TEXT, "
253 "build_date TEXT, "
254 "build_time INTEGER, "
255 "installed INTEGER, "
256 "reason TEXT, "
257 "repository TEXT"
258 ")");
259 if (r)
260 return 1;
261
262 // packages: Create index to find package by name
263 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS packages_name ON packages(name)");
264 if (r)
265 return 1;
266
2359ca14
MT
267 // Create dependencies table
268 r = pakfire_db_execute(db,
269 "CREATE TABLE IF NOT EXISTS dependencies("
270 "pkg INTEGER, "
271 "type TEXT, "
46257c5f
MT
272 "dependency TEXT, "
273 "FOREIGN KEY (pkg) REFERENCES packages(id)"
2359ca14
MT
274 ")");
275 if (r)
276 return r;
277
278 // dependencies: Add index over packages
279 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS dependencies_pkg_index ON dependencies(pkg)");
280 if (r)
281 return r;
282
68036506
MT
283 // Create files table
284 r = pakfire_db_execute(db,
285 "CREATE TABLE IF NOT EXISTS files("
286 "id INTEGER PRIMARY KEY, "
287 "name TEXT, "
288 "pkg INTEGER, "
289 "size INTEGER, "
290 "type INTEGER, "
291 "config INTEGER, "
292 "datafile INTEGER, "
293 "mode INTEGER, "
294 "user TEXT, "
295 "'group' TEXT, "
296 "hash1 TEXT, "
297 "mtime INTEGER, "
46257c5f
MT
298 "capabilities TEXT, "
299 "FOREIGN KEY (pkg) REFERENCES packages(id)"
68036506
MT
300 ")");
301 if (r)
302 return 1;
303
304 // files: Add index over packages
305 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS files_pkg_index ON files(pkg)");
306 if (r)
307 return 1;
308
d83414aa
MT
309 // Create scriptlets table
310 r = pakfire_db_execute(db,
311 "CREATE TABLE IF NOT EXISTS scriptlets("
312 "id INTEGER PRIMARY KEY, "
313 "pkg INTEGER, "
314 "action TEXT, "
46257c5f
MT
315 "scriptlet TEXT, "
316 "FOREIGN KEY (pkg) REFERENCES packages(id)"
d83414aa
MT
317 ")");
318 if (r)
319 return 1;
320
321 // scriptlets: Add index over packages
322 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS scriptlets_pkg_index ON scriptlets(pkg)");
323 if (r)
324 return 1;
325
c745fb2d
MT
326 return 0;
327}
328
46257c5f 329static int pakfire_db_migrate_to_schema_8(struct pakfire_db* db) {
5ba550fe
MT
330 // packages: Drop build_id column
331
46257c5f
MT
332 // Add foreign keys
333 // TODO sqlite doesn't support adding foreign keys to existing tables and so we would
334 // need to recreate the whole table and rename it afterwards. Annoying.
335
336 return 0;
337}
338
c745fb2d
MT
339static int pakfire_db_migrate_schema(struct pakfire_db* db) {
340 int r;
341
342 while (db->schema < CURRENT_SCHEMA) {
343 // Begin a new transaction
344 r = pakfire_db_begin_transaction(db);
345 if (r)
346 goto ROLLBACK;
347
348 switch (db->schema) {
349 // No schema exists
f168dd0c 350 case -1:
c745fb2d
MT
351 r = pakfire_db_create_schema(db);
352 if (r)
353 goto ROLLBACK;
354
355 db->schema = CURRENT_SCHEMA;
356 break;
357
46257c5f
MT
358 case 7:
359 r = pakfire_db_migrate_to_schema_8(db);
360 if (r)
361 goto ROLLBACK;
362
363 db->schema++;
364 break;
365
c745fb2d
MT
366 default:
367 ERROR(db->pakfire, "Cannot migrate database from schema %d\n", db->schema);
368 goto ROLLBACK;
369 }
370
371 // Update the schema version
372 r = pakfire_db_set_int(db, "schema", CURRENT_SCHEMA);
373 if (r)
374 goto ROLLBACK;
375
376 // All done, commit!
377 r = pakfire_db_commit(db);
378 if (r)
379 goto ROLLBACK;
380 }
381
382 return 0;
383
384ROLLBACK:
385 pakfire_db_rollback(db);
386
387 return 1;
388}
389
9c5938ea 390static int pakfire_db_setup(struct pakfire_db* db) {
25753290
MT
391 int r;
392
9c5938ea
MT
393 // Setup logging
394 sqlite3_config(SQLITE_CONFIG_LOG, logging_callback, db->pakfire);
395
46257c5f
MT
396 // Enable foreign keys
397 pakfire_db_execute(db, "PRAGMA foreign_keys = ON");
398
0076c50d
MT
399 // Make LIKE case-sensitive
400 pakfire_db_execute(db, "PRAGMA case_sensitive_like = ON");
401
c745fb2d
MT
402 // Fetch the current schema
403 db->schema = pakfire_db_get_schema(db);
404
405 // Check if the schema is recent enough
406 if (db->schema > 0 && db->schema < SCHEMA_MIN_SUP) {
407 ERROR(db->pakfire, "Database schema %d is not supported by this version of Pakfire\n",
408 db->schema);
409 return 1;
410 }
411
9c5938ea
MT
412 // Done when not in read-write mode
413 if (db->mode != PAKFIRE_DB_READWRITE)
414 return 0;
415
0076c50d
MT
416 // Disable secure delete
417 pakfire_db_execute(db, "PRAGMA secure_delete = OFF");
418
25753290
MT
419 // Set database journal to WAL
420 r = pakfire_db_execute(db, "PRAGMA journal_mode = WAL");
421 if (r != SQLITE_OK) {
422 ERROR(db->pakfire, "Could not set journal mode to WAL: %s\n",
423 sqlite3_errmsg(db->handle));
424 return 1;
425 }
426
427 // Disable autocheckpoint
428 r = sqlite3_wal_autocheckpoint(db->handle, 0);
429 if (r != SQLITE_OK) {
430 ERROR(db->pakfire, "Could not disable autocheckpoint: %s\n",
431 sqlite3_errmsg(db->handle));
432 return 1;
433 }
434
c745fb2d
MT
435 // Create or migrate schema
436 r = pakfire_db_migrate_schema(db);
437 if (r)
438 return r;
9c5938ea
MT
439
440 return 0;
441}
442
77a4b3a3 443PAKFIRE_EXPORT int pakfire_db_open(struct pakfire_db** db, Pakfire pakfire, int flags) {
26affd69
MT
444 int r = 1;
445
33d55ab4
MT
446 struct pakfire_db* o = pakfire_calloc(1, sizeof(*o));
447 if (!o)
448 return -ENOMEM;
449
450 DEBUG(pakfire, "Allocated database at %p\n", o);
451
452 o->pakfire = pakfire_ref(pakfire);
453 o->nrefs = 1;
454
26affd69
MT
455 int sqlite3_flags = 0;
456
457 // Store mode & forward it to sqlite3
458 if (flags & PAKFIRE_DB_READWRITE) {
77a4b3a3 459 o->mode = PAKFIRE_DB_READWRITE;
26affd69
MT
460 sqlite3_flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
461 } else {
77a4b3a3 462 o->mode = PAKFIRE_DB_READONLY;
26affd69
MT
463 sqlite3_flags |= SQLITE_OPEN_READONLY;
464 }
465
466 // Make the filename
467 char* path = pakfire_make_path(o->pakfire, DATABASE_PATH);
468 if (!path)
469 goto END;
470
471 // Try to open the sqlite3 database file
472 r = sqlite3_open_v2(path, &o->handle, sqlite3_flags, NULL);
473 if (r != SQLITE_OK) {
474 ERROR(pakfire, "Could not open database %s: %s\n",
475 path, sqlite3_errmsg(o->handle));
476
477 r = 1;
478 goto END;
479 }
77a4b3a3 480
9c5938ea
MT
481 // Setup the database
482 r = pakfire_db_setup(o);
483 if (r)
484 goto END;
485
33d55ab4 486 *db = o;
26affd69
MT
487 r = 0;
488
489END:
490 if (r)
491 pakfire_db_free(o);
33d55ab4 492
26affd69
MT
493 if (path)
494 free(path);
495
496 return r;
33d55ab4
MT
497}
498
18bf891d 499PAKFIRE_EXPORT struct pakfire_db* pakfire_db_ref(struct pakfire_db* db) {
33d55ab4
MT
500 db->nrefs++;
501
502 return db;
503}
504
18bf891d 505PAKFIRE_EXPORT struct pakfire_db* pakfire_db_unref(struct pakfire_db* db) {
33d55ab4
MT
506 if (--db->nrefs > 0)
507 return db;
508
509 pakfire_db_free(db);
510
511 return NULL;
512}
eafbe2ce 513
a1571786
MT
514static unsigned long pakfire_db_integrity_check(struct pakfire_db* db) {
515 sqlite3_stmt* stmt = NULL;
516 int r;
517
518 r = sqlite3_prepare_v2(db->handle, "PRAGMA integrity_check", -1, &stmt, NULL);
519 if (r) {
520 ERROR(db->pakfire, "Could not prepare integrity check: %s\n",
521 sqlite3_errmsg(db->handle));
522 return 1;
523 }
524
525 // Count any errors
526 unsigned long errors = 0;
527
528 while (1) {
529 do {
530 r = sqlite3_step(stmt);
531 } while (r == SQLITE_BUSY);
532
533 if (r == SQLITE_ROW) {
534 const char* error = (const char*)sqlite3_column_text(stmt, 0);
535
536 // If the message is "ok", the database has passed the check
537 if (strcmp(error, "ok") == 0)
538 continue;
539
540 // Increment error counter
541 errors++;
542
543 // Log the message
544 ERROR(db->pakfire, "%s\n", error);
545
546 // Break on anything else
547 } else
548 break;
549 }
550
551 sqlite3_finalize(stmt);
552
553 if (errors)
554 ERROR(db->pakfire, "Database integrity check failed\n");
555 else
556 INFO(db->pakfire, "Database integrity check passed\n");
557
558 return errors;
559}
560
561static unsigned long pakfire_db_foreign_key_check(struct pakfire_db* db) {
562 sqlite3_stmt* stmt = NULL;
563 int r;
564
565 r = sqlite3_prepare_v2(db->handle, "PRAGMA foreign_key_check", -1, &stmt, NULL);
566 if (r) {
567 ERROR(db->pakfire, "Could not prepare foreign key check: %s\n",
568 sqlite3_errmsg(db->handle));
569 return 1;
570 }
571
572 // Count any errors
573 unsigned long errors = 0;
574
575 while (1) {
576 do {
577 r = sqlite3_step(stmt);
578 } while (r == SQLITE_BUSY);
579
580 if (r == SQLITE_ROW) {
581 const unsigned char* table = sqlite3_column_text(stmt, 0);
582 unsigned long rowid = sqlite3_column_int64(stmt, 1);
583 const unsigned char* foreign_table = sqlite3_column_text(stmt, 2);
584 unsigned long foreign_rowid = sqlite3_column_int64(stmt, 3);
585
586 // Increment error counter
587 errors++;
588
589 // Log the message
590 ERROR(db->pakfire, "Foreign key violation found in %s, row %lu: "
591 "%lu does not exist in table %s\n", table, rowid, foreign_rowid, foreign_table);
592
593 // Break on anything else
594 } else
595 break;
596 }
597
598 sqlite3_finalize(stmt);
599
600 if (errors)
601 ERROR(db->pakfire, "Foreign key check failed\n");
602 else
603 INFO(db->pakfire, "Foreign key check passed\n");
604
605 return errors;
606}
607
608/*
609 This function performs an integrity check of the database
610*/
611PAKFIRE_EXPORT int pakfire_db_check(struct pakfire_db* db) {
612 int r;
613
614 // Perform integrity check
615 r = pakfire_db_integrity_check(db);
616 if (r)
617 return 1;
618
619 // Perform foreign key check
620 r = pakfire_db_foreign_key_check(db);
621 if (r)
622 return 1;
623
624 return 0;
625}
626
18bf891d 627PAKFIRE_EXPORT int pakfire_db_add_package(struct pakfire_db* db, PakfirePackage pkg) {
e49b93d1
MT
628 sqlite3_stmt* stmt = NULL;
629 int r;
630
631 // Begin a new transaction
632 r = pakfire_db_begin_transaction(db);
633 if (r)
634 goto ROLLBACK;
635
636 const char* sql = "INSERT INTO packages(name, epoch, version, release, arch, groups, "
637 "filename, size, inst_size, hash1, license, summary, description, uuid, vendor, "
1ca6a13d
MT
638 "build_host, build_time, installed, repository, reason) VALUES(?, ?, "
639 "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)";
e49b93d1
MT
640
641 // Prepare the statement
642 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
643 if (r != SQLITE_OK) {
644 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
645 sql, sqlite3_errmsg(db->handle));
646 goto ROLLBACK;
647 }
648
649 // Bind name
650 const char* name = pakfire_package_get_name(pkg);
651
652 r = sqlite3_bind_text(stmt, 1, name, -1, NULL);
653 if (r) {
654 ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
655 goto ROLLBACK;
656 }
657
658 // Bind epoch
659 unsigned long epoch = pakfire_package_get_epoch(pkg);
660
661 r = sqlite3_bind_int64(stmt, 2, epoch);
662 if (r) {
663 ERROR(db->pakfire, "Could not bind epoch: %s\n", sqlite3_errmsg(db->handle));
664 goto ROLLBACK;
665 }
666
667 // Bind version
668 const char* version = pakfire_package_get_version(pkg);
669
670 r = sqlite3_bind_text(stmt, 3, version, -1, NULL);
671 if (r) {
672 ERROR(db->pakfire, "Could not bind version: %s\n", sqlite3_errmsg(db->handle));
673 goto ROLLBACK;
674 }
675
676 // Bind release
677 const char* release = pakfire_package_get_release(pkg);
678
679 r = sqlite3_bind_text(stmt, 4, release, -1, NULL);
680 if (r) {
681 ERROR(db->pakfire, "Could not bind release: %s\n", sqlite3_errmsg(db->handle));
682 goto ROLLBACK;
683 }
684
685 // Bind arch
686 const char* arch = pakfire_package_get_arch(pkg);
687
688 r = sqlite3_bind_text(stmt, 5, arch, -1, NULL);
689 if (r) {
690 ERROR(db->pakfire, "Could not bind arch: %s\n", sqlite3_errmsg(db->handle));
691 goto ROLLBACK;
692 }
693
694 // Bind groups
695 const char* groups = pakfire_package_get_groups(pkg);
696
697 r = sqlite3_bind_text(stmt, 6, groups, -1, NULL);
698 if (r) {
699 ERROR(db->pakfire, "Could not bind groups: %s\n", sqlite3_errmsg(db->handle));
700 goto ROLLBACK;
701 }
702
703 // Bind filename
704 const char* filename = pakfire_package_get_filename(pkg);
705
706 r = sqlite3_bind_text(stmt, 7, filename, -1, NULL);
707 if (r) {
708 ERROR(db->pakfire, "Could not bind filename: %s\n", sqlite3_errmsg(db->handle));
709 goto ROLLBACK;
710 }
711
712 // Bind size
713 unsigned long long size = pakfire_package_get_downloadsize(pkg);
714
715 r = sqlite3_bind_int64(stmt, 8, size);
716 if (r) {
717 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
718 goto ROLLBACK;
719 }
720
721 // Bind installed size
722 unsigned long long inst_size = pakfire_package_get_installsize(pkg);
723
724 r = sqlite3_bind_int64(stmt, 9, inst_size);
725 if (r) {
726 ERROR(db->pakfire, "Could not bind inst_size: %s\n", sqlite3_errmsg(db->handle));
727 goto ROLLBACK;
728 }
729
730 // Bind hash1
731 const char* hash1 = pakfire_package_get_checksum(pkg);
732
733 r = sqlite3_bind_text(stmt, 10, hash1, -1, NULL);
734 if (r) {
735 ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle));
736 goto ROLLBACK;
737 }
738
739 // Bind license
740 const char* license = pakfire_package_get_license(pkg);
741
742 r = sqlite3_bind_text(stmt, 11, license, -1, NULL);
743 if (r) {
744 ERROR(db->pakfire, "Could not bind license: %s\n", sqlite3_errmsg(db->handle));
745 goto ROLLBACK;
746 }
747
748 // Bind summary
749 const char* summary = pakfire_package_get_summary(pkg);
750
751 r = sqlite3_bind_text(stmt, 12, summary, -1, NULL);
752 if (r) {
753 ERROR(db->pakfire, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle));
754 goto ROLLBACK;
755 }
756
757 // Bind description
758 const char* description = pakfire_package_get_description(pkg);
759
760 r = sqlite3_bind_text(stmt, 13, description, -1, NULL);
761 if (r) {
762 ERROR(db->pakfire, "Could not bind description: %s\n", sqlite3_errmsg(db->handle));
763 goto ROLLBACK;
764 }
765
766 // Bind uuid
767 const char* uuid = pakfire_package_get_uuid(pkg);
768
769 r = sqlite3_bind_text(stmt, 14, uuid, -1, NULL);
770 if (r) {
771 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
772 goto ROLLBACK;
773 }
774
775 // Bind vendor
776 const char* vendor = pakfire_package_get_vendor(pkg);
777
778 r = sqlite3_bind_text(stmt, 14, vendor, -1, NULL);
779 if (r) {
780 ERROR(db->pakfire, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle));
781 goto ROLLBACK;
782 }
783
e49b93d1
MT
784 // Bind build_host
785 const char* buildhost = pakfire_package_get_buildhost(pkg);
786
787 r = sqlite3_bind_text(stmt, 16, buildhost, -1, NULL);
788 if (r) {
789 ERROR(db->pakfire, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle));
790 goto ROLLBACK;
791 }
792
793 // Bind build_time
794 unsigned long long build_time = pakfire_package_get_buildtime(pkg);
795
796 r = sqlite3_bind_int64(stmt, 17, build_time);
797 if (r) {
798 ERROR(db->pakfire, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle));
799 goto ROLLBACK;
800 }
801
802 // Bind repository name
803 PakfireRepo repo = pakfire_package_get_repo(pkg);
804 if (repo) {
805 const char* repo_name = pakfire_repo_get_name(repo);
806 pakfire_repo_unref(repo);
807
808 r = sqlite3_bind_text(stmt, 18, repo_name, -1, NULL);
809 if (r)
810 goto ROLLBACK;
811
812 // No repository?
813 } else {
814 r = sqlite3_bind_null(stmt, 18);
815 if (r)
816 goto ROLLBACK;
817 }
818
819 // XXX TODO Bind reason
820 r = sqlite3_bind_null(stmt, 19);
821 if (r)
822 goto ROLLBACK;
823
824 // Run query
825 do {
826 r = sqlite3_step(stmt);
827 } while (r == SQLITE_BUSY);
828
829 if (r != SQLITE_DONE) {
830 ERROR(db->pakfire, "Could not add package to database: %s\n",
831 sqlite3_errmsg(db->handle));
832 goto ROLLBACK;
833 }
834
835 // This is done
836 sqlite3_finalize(stmt);
837
838 // All done, commit!
839 r = pakfire_db_commit(db);
840 if (r)
841 goto ROLLBACK;
842
843 return 0;
844
845ROLLBACK:
846 sqlite3_finalize(stmt);
847
848 pakfire_db_rollback(db);
849
850 return 1;
eafbe2ce
MT
851}
852
18bf891d 853PAKFIRE_EXPORT int pakfire_db_remove_package(struct pakfire_db* db, PakfirePackage pkg) {
eafbe2ce
MT
854 return 0; // TODO
855}