]> git.ipfire.org Git - pakfire.git/blob - src/libpakfire/db.c
packager: Package scriptlets
[pakfire.git] / src / libpakfire / db.c
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 <linux/limits.h>
23 #include <stdlib.h>
24 #include <time.h>
25
26 #include <sqlite3.h>
27
28 #include <pakfire/archive.h>
29 #include <pakfire/db.h>
30 #include <pakfire/file.h>
31 #include <pakfire/logging.h>
32 #include <pakfire/package.h>
33 #include <pakfire/pakfire.h>
34 #include <pakfire/private.h>
35 #include <pakfire/repo.h>
36 #include <pakfire/types.h>
37 #include <pakfire/util.h>
38
39 #define DATABASE_PATH PAKFIRE_PRIVATE_DIR "/packages.db"
40
41 #define CURRENT_SCHEMA 8
42 #define SCHEMA_MIN_SUP 7
43
44 struct pakfire_db {
45 Pakfire pakfire;
46 int nrefs;
47
48 char path[PATH_MAX];
49 int mode;
50
51 sqlite3* handle;
52 int schema;
53 };
54
55 static void logging_callback(void* data, int r, const char* msg) {
56 Pakfire pakfire = (Pakfire)data;
57
58 ERROR(pakfire, "Database Error: %s: %s\n",
59 sqlite3_errstr(r), msg);
60 }
61
62 static int pakfire_db_execute(struct pakfire_db* db, const char* stmt) {
63 int r;
64
65 DEBUG(db->pakfire, "Executing database query: %s\n", stmt);
66
67 do {
68 r = sqlite3_exec(db->handle, stmt, NULL, NULL, NULL);
69 } while (r == SQLITE_BUSY);
70
71 // Log any errors
72 if (r) {
73 ERROR(db->pakfire, "Database query failed: %s\n", sqlite3_errmsg(db->handle));
74 }
75
76 return r;
77 }
78
79 static int pakfire_db_begin_transaction(struct pakfire_db* db) {
80 return pakfire_db_execute(db, "BEGIN TRANSACTION");
81 }
82
83 static int pakfire_db_commit(struct pakfire_db* db) {
84 return pakfire_db_execute(db, "COMMIT");
85 }
86
87 static int pakfire_db_rollback(struct pakfire_db* db) {
88 return pakfire_db_execute(db, "ROLLBACK");
89 }
90
91 /*
92 This function performs any fast optimization and tries to truncate the WAL log file
93 to keep the database as compact as possible on disk.
94 */
95 static void pakfire_db_optimize(struct pakfire_db* db) {
96 pakfire_db_execute(db, "PRAGMA optimize");
97 pakfire_db_execute(db, "PRAGMA wal_checkpoint = TRUNCATE");
98 }
99
100 static void pakfire_db_free(struct pakfire_db* db) {
101 if (db->handle) {
102 // Optimize the database before it is being closed
103 pakfire_db_optimize(db);
104
105 // Close database handle
106 int r = sqlite3_close(db->handle);
107 if (r != SQLITE_OK) {
108 ERROR(db->pakfire, "Could not close database handle: %s\n",
109 sqlite3_errmsg(db->handle));
110 }
111 }
112
113 pakfire_unref(db->pakfire);
114
115 free(db);
116 }
117
118 static sqlite3_value* pakfire_db_get(struct pakfire_db* db, const char* key) {
119 sqlite3_stmt* stmt = NULL;
120 sqlite3_value* val = NULL;
121 int r;
122
123 const char* sql = "SELECT val FROM settings WHERE key = ?";
124
125 // Prepare the statement
126 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
127 if (r != SQLITE_OK) {
128 //ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
129 // sql, sqlite3_errmsg(db->handle));
130 return NULL;
131 }
132
133 // Bind key
134 r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
135 if (r != SQLITE_OK) {
136 ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
137 goto ERROR;
138 }
139
140 // Execute the statement
141 do {
142 r = sqlite3_step(stmt);
143 } while (r == SQLITE_BUSY);
144
145 // We should have read a row
146 if (r != SQLITE_ROW)
147 goto ERROR;
148
149 // Read value
150 val = sqlite3_column_value(stmt, 0);
151 if (!val) {
152 ERROR(db->pakfire, "Could not read value\n");
153 goto ERROR;
154 }
155
156 // Copy value onto the heap
157 val = sqlite3_value_dup(val);
158
159 ERROR:
160 if (stmt)
161 sqlite3_finalize(stmt);
162
163 return val;
164 }
165
166 static int pakfire_db_set_int(struct pakfire_db* db, const char* key, int val) {
167 sqlite3_stmt* stmt = NULL;
168 int r;
169
170 const char* sql = "INSERT INTO settings(key, val) VALUES(?, ?) \
171 ON CONFLICT (key) DO UPDATE SET val = excluded.val";
172
173 // Prepare statement
174 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
175 if (r != SQLITE_OK) {
176 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
177 sql, sqlite3_errmsg(db->handle));
178 return 1;
179 }
180
181 // Bind key
182 r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
183 if (r != SQLITE_OK) {
184 ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
185 goto ERROR;
186 }
187
188 // Bind val
189 r = sqlite3_bind_int64(stmt, 2, val);
190 if (r != SQLITE_OK) {
191 ERROR(db->pakfire, "Could not bind val: %s\n", sqlite3_errmsg(db->handle));
192 goto ERROR;
193 }
194
195 // Execute the statement
196 do {
197 r = sqlite3_step(stmt);
198 } while (r == SQLITE_BUSY);
199
200 // Set return code
201 r = (r == SQLITE_OK);
202
203 ERROR:
204 if (stmt)
205 sqlite3_finalize(stmt);
206
207 return r;
208 }
209
210 static int pakfire_db_get_schema(struct pakfire_db* db) {
211 sqlite3_value* value = pakfire_db_get(db, "schema");
212 if (!value)
213 return -1;
214
215 int schema = sqlite3_value_int64(value);
216 sqlite3_value_free(value);
217
218 DEBUG(db->pakfire, "Database has schema version %d\n", schema);
219
220 return schema;
221 }
222
223 static int pakfire_db_create_schema(struct pakfire_db* db) {
224 int r;
225
226 // Create settings table
227 r = pakfire_db_execute(db, "CREATE TABLE IF NOT EXISTS settings(key TEXT, val TEXT)");
228 if (r)
229 return 1;
230
231 // settings: Add a unique index on key
232 r = pakfire_db_execute(db, "CREATE UNIQUE INDEX IF NOT EXISTS settings_key ON settings(key)");
233 if (r)
234 return 1;
235
236 // Create packages table
237 r = pakfire_db_execute(db,
238 "CREATE TABLE IF NOT EXISTS packages("
239 "id INTEGER PRIMARY KEY, "
240 "name TEXT, "
241 "evr TEXT, "
242 "arch TEXT, "
243 "groups TEXT, "
244 "filename TEXT, "
245 "size INTEGER, "
246 "inst_size INTEGER, "
247 "hash1 TEXT, "
248 "license TEXT, "
249 "summary TEXT, "
250 "description TEXT, "
251 "uuid TEXT, "
252 "vendor TEXT, "
253 "build_host 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
267 // packages: Create unique index over UUID
268 r = pakfire_db_execute(db, "CREATE UNIQUE INDEX IF NOT EXISTS packages_uuid ON packages(uuid)");
269 if (r)
270 return 1;
271
272 // Create dependencies table
273 r = pakfire_db_execute(db,
274 "CREATE TABLE IF NOT EXISTS dependencies("
275 "pkg INTEGER, "
276 "type TEXT, "
277 "dependency TEXT, "
278 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
279 ")");
280 if (r)
281 return r;
282
283 // dependencies: Add index over packages
284 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS dependencies_pkg_index ON dependencies(pkg)");
285 if (r)
286 return r;
287
288 // Create files table
289 r = pakfire_db_execute(db,
290 "CREATE TABLE IF NOT EXISTS files("
291 "id INTEGER PRIMARY KEY, "
292 "path TEXT, "
293 "pkg INTEGER, "
294 "size INTEGER, "
295 "type INTEGER, "
296 "config INTEGER, "
297 "datafile INTEGER, "
298 "mode INTEGER, "
299 "user TEXT, "
300 "'group' TEXT, "
301 "hash1 TEXT, "
302 "ctime INTEGER, "
303 "mtime INTEGER, "
304 "capabilities TEXT, "
305 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
306 ")");
307 if (r)
308 return 1;
309
310 // files: Add index over packages
311 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS files_pkg_index ON files(pkg)");
312 if (r)
313 return 1;
314
315 // Create scriptlets table
316 r = pakfire_db_execute(db,
317 "CREATE TABLE IF NOT EXISTS scriptlets("
318 "id INTEGER PRIMARY KEY, "
319 "pkg INTEGER, "
320 "type TEXT, "
321 "scriptlet TEXT, "
322 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
323 ")");
324 if (r)
325 return 1;
326
327 // scriptlets: Add index over packages
328 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS scriptlets_pkg_index ON scriptlets(pkg)");
329 if (r)
330 return 1;
331
332 return 0;
333 }
334
335 static int pakfire_db_migrate_to_schema_8(struct pakfire_db* db) {
336 // packages: Drop build_id column
337
338 // Add foreign keys
339 // TODO sqlite doesn't support adding foreign keys to existing tables and so we would
340 // need to recreate the whole table and rename it afterwards. Annoying.
341
342 return 0;
343 }
344
345 static int pakfire_db_migrate_schema(struct pakfire_db* db) {
346 int r;
347
348 while (db->schema < CURRENT_SCHEMA) {
349 // Begin a new transaction
350 r = pakfire_db_begin_transaction(db);
351 if (r)
352 goto ROLLBACK;
353
354 switch (db->schema) {
355 // No schema exists
356 case -1:
357 r = pakfire_db_create_schema(db);
358 if (r)
359 goto ROLLBACK;
360
361 db->schema = CURRENT_SCHEMA;
362 break;
363
364 case 7:
365 r = pakfire_db_migrate_to_schema_8(db);
366 if (r)
367 goto ROLLBACK;
368
369 db->schema++;
370 break;
371
372 default:
373 ERROR(db->pakfire, "Cannot migrate database from schema %d\n", db->schema);
374 goto ROLLBACK;
375 }
376
377 // Update the schema version
378 r = pakfire_db_set_int(db, "schema", CURRENT_SCHEMA);
379 if (r)
380 goto ROLLBACK;
381
382 // All done, commit!
383 r = pakfire_db_commit(db);
384 if (r)
385 goto ROLLBACK;
386 }
387
388 return 0;
389
390 ROLLBACK:
391 pakfire_db_rollback(db);
392
393 return 1;
394 }
395
396 static int pakfire_db_setup(struct pakfire_db* db) {
397 int r;
398
399 // Setup logging
400 sqlite3_config(SQLITE_CONFIG_LOG, logging_callback, db->pakfire);
401
402 // Enable foreign keys
403 pakfire_db_execute(db, "PRAGMA foreign_keys = ON");
404
405 // Make LIKE case-sensitive
406 pakfire_db_execute(db, "PRAGMA case_sensitive_like = ON");
407
408 // Fetch the current schema
409 db->schema = pakfire_db_get_schema(db);
410
411 // Check if the schema is recent enough
412 if (db->schema > 0 && db->schema < SCHEMA_MIN_SUP) {
413 ERROR(db->pakfire, "Database schema %d is not supported by this version of Pakfire\n",
414 db->schema);
415 return 1;
416 }
417
418 // Done when not in read-write mode
419 if (db->mode != PAKFIRE_DB_READWRITE)
420 return 0;
421
422 // Disable secure delete
423 pakfire_db_execute(db, "PRAGMA secure_delete = OFF");
424
425 // Set database journal to WAL
426 r = pakfire_db_execute(db, "PRAGMA journal_mode = WAL");
427 if (r != SQLITE_OK) {
428 ERROR(db->pakfire, "Could not set journal mode to WAL: %s\n",
429 sqlite3_errmsg(db->handle));
430 return 1;
431 }
432
433 // Disable autocheckpoint
434 r = sqlite3_wal_autocheckpoint(db->handle, 0);
435 if (r != SQLITE_OK) {
436 ERROR(db->pakfire, "Could not disable autocheckpoint: %s\n",
437 sqlite3_errmsg(db->handle));
438 return 1;
439 }
440
441 // Create or migrate schema
442 r = pakfire_db_migrate_schema(db);
443 if (r)
444 return r;
445
446 return 0;
447 }
448
449 PAKFIRE_EXPORT int pakfire_db_open(struct pakfire_db** db, Pakfire pakfire, int flags) {
450 int r = 1;
451
452 struct pakfire_db* o = calloc(1, sizeof(*o));
453 if (!o)
454 return -ENOMEM;
455
456 o->pakfire = pakfire_ref(pakfire);
457 o->nrefs = 1;
458
459 int sqlite3_flags = 0;
460
461 // Store mode & forward it to sqlite3
462 if (flags & PAKFIRE_DB_READWRITE) {
463 o->mode = PAKFIRE_DB_READWRITE;
464 sqlite3_flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
465 } else {
466 o->mode = PAKFIRE_DB_READONLY;
467 sqlite3_flags |= SQLITE_OPEN_READONLY;
468 }
469
470 // Make the filename
471 r = pakfire_make_path(o->pakfire, o->path, DATABASE_PATH);
472 if (r < 0)
473 goto END;
474
475 // Try to open the sqlite3 database file
476 r = sqlite3_open_v2(o->path, &o->handle, sqlite3_flags, NULL);
477 if (r != SQLITE_OK) {
478 ERROR(pakfire, "Could not open database %s: %s\n",
479 o->path, sqlite3_errmsg(o->handle));
480
481 r = 1;
482 goto END;
483 }
484
485 // Setup the database
486 r = pakfire_db_setup(o);
487 if (r)
488 goto END;
489
490 *db = o;
491 r = 0;
492
493 END:
494 if (r)
495 pakfire_db_free(o);
496
497 return r;
498 }
499
500 PAKFIRE_EXPORT struct pakfire_db* pakfire_db_ref(struct pakfire_db* db) {
501 db->nrefs++;
502
503 return db;
504 }
505
506 PAKFIRE_EXPORT struct pakfire_db* pakfire_db_unref(struct pakfire_db* db) {
507 if (--db->nrefs > 0)
508 return db;
509
510 pakfire_db_free(db);
511
512 return NULL;
513 }
514
515 static unsigned long pakfire_db_integrity_check(struct pakfire_db* db) {
516 sqlite3_stmt* stmt = NULL;
517 int r;
518
519 r = sqlite3_prepare_v2(db->handle, "PRAGMA integrity_check", -1, &stmt, NULL);
520 if (r) {
521 ERROR(db->pakfire, "Could not prepare integrity check: %s\n",
522 sqlite3_errmsg(db->handle));
523 return 1;
524 }
525
526 // Count any errors
527 unsigned long errors = 0;
528
529 while (1) {
530 do {
531 r = sqlite3_step(stmt);
532 } while (r == SQLITE_BUSY);
533
534 if (r == SQLITE_ROW) {
535 const char* error = (const char*)sqlite3_column_text(stmt, 0);
536
537 // If the message is "ok", the database has passed the check
538 if (strcmp(error, "ok") == 0)
539 continue;
540
541 // Increment error counter
542 errors++;
543
544 // Log the message
545 ERROR(db->pakfire, "%s\n", error);
546
547 // Break on anything else
548 } else
549 break;
550 }
551
552 sqlite3_finalize(stmt);
553
554 if (errors)
555 ERROR(db->pakfire, "Database integrity check failed\n");
556 else
557 INFO(db->pakfire, "Database integrity check passed\n");
558
559 return errors;
560 }
561
562 static unsigned long pakfire_db_foreign_key_check(struct pakfire_db* db) {
563 sqlite3_stmt* stmt = NULL;
564 int r;
565
566 r = sqlite3_prepare_v2(db->handle, "PRAGMA foreign_key_check", -1, &stmt, NULL);
567 if (r) {
568 ERROR(db->pakfire, "Could not prepare foreign key check: %s\n",
569 sqlite3_errmsg(db->handle));
570 return 1;
571 }
572
573 // Count any errors
574 unsigned long errors = 0;
575
576 while (1) {
577 do {
578 r = sqlite3_step(stmt);
579 } while (r == SQLITE_BUSY);
580
581 if (r == SQLITE_ROW) {
582 const unsigned char* table = sqlite3_column_text(stmt, 0);
583 unsigned long rowid = sqlite3_column_int64(stmt, 1);
584 const unsigned char* foreign_table = sqlite3_column_text(stmt, 2);
585 unsigned long foreign_rowid = sqlite3_column_int64(stmt, 3);
586
587 // Increment error counter
588 errors++;
589
590 // Log the message
591 ERROR(db->pakfire, "Foreign key violation found in %s, row %lu: "
592 "%lu does not exist in table %s\n", table, rowid, foreign_rowid, foreign_table);
593
594 // Break on anything else
595 } else
596 break;
597 }
598
599 sqlite3_finalize(stmt);
600
601 if (errors)
602 ERROR(db->pakfire, "Foreign key check failed\n");
603 else
604 INFO(db->pakfire, "Foreign key check passed\n");
605
606 return errors;
607 }
608
609 /*
610 This function performs an integrity check of the database
611 */
612 PAKFIRE_EXPORT int pakfire_db_check(struct pakfire_db* db) {
613 int r;
614
615 // Perform integrity check
616 r = pakfire_db_integrity_check(db);
617 if (r)
618 return 1;
619
620 // Perform foreign key check
621 r = pakfire_db_foreign_key_check(db);
622 if (r)
623 return 1;
624
625 return 0;
626 }
627
628 // Returns the number of packages installed
629 PAKFIRE_EXPORT ssize_t pakfire_db_packages(struct pakfire_db* db) {
630 sqlite3_stmt* stmt = NULL;
631 ssize_t packages = -1;
632
633 int r = sqlite3_prepare_v2(db->handle, "SELECT COUNT(*) FROM packages", -1, &stmt, NULL);
634 if (r) {
635 ERROR(db->pakfire, "Could not prepare SQL statement: %s\n",
636 sqlite3_errmsg(db->handle));
637 return -1;
638 }
639
640 // Execute query
641 do {
642 r = sqlite3_step(stmt);
643 } while (r == SQLITE_BUSY);
644
645 if (r == SQLITE_ROW) {
646 packages = sqlite3_column_int64(stmt, 0);
647 }
648
649 sqlite3_finalize(stmt);
650
651 return packages;
652 }
653
654 static int pakfire_db_add_dependencies(struct pakfire_db* db, unsigned long id, PakfirePackage pkg) {
655 sqlite3_stmt* stmt = NULL;
656 int r = 1;
657
658 const char* sql = "INSERT INTO dependencies(pkg, type, dependency) VALUES(?, ?, ?)";
659
660 // Prepare the statement
661 r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL);
662 if (r) {
663 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
664 sql, sqlite3_errmsg(db->handle));
665 goto END;
666 }
667
668 const struct __relation {
669 const char* type;
670 char** (*func)(PakfirePackage);
671 } relations[] = {
672 { "provides", pakfire_package_get_provides },
673 { "prerequires", pakfire_package_get_prerequires },
674 { "requires", pakfire_package_get_requires },
675 { "conflicts", pakfire_package_get_conflicts },
676 { "obsoletes", pakfire_package_get_obsoletes },
677 { "recommends", pakfire_package_get_recommends },
678 { "suggests", pakfire_package_get_suggests },
679 { "supplements", pakfire_package_get_supplements },
680 { "enhances", pakfire_package_get_enhances },
681 { NULL, NULL },
682 };
683
684 for (const struct __relation* relation = relations; relation->type; relation++) {
685 char** list = relation->func(pkg);
686 if (!list)
687 continue;
688
689 for (char** dep = list; *dep; dep++) {
690 // Bind package ID
691 r = sqlite3_bind_int64(stmt, 1, id);
692 if (r) {
693 ERROR(db->pakfire, "Could not bind id: %s\n",
694 sqlite3_errmsg(db->handle));
695 goto END;
696 }
697
698 // Bind type
699 r = sqlite3_bind_text(stmt, 2, relation->type, -1, NULL);
700 if (r) {
701 ERROR(db->pakfire, "Could not bind type: %s\n",
702 sqlite3_errmsg(db->handle));
703 goto END;
704 }
705
706 // Bind dependency
707 r = sqlite3_bind_text(stmt, 3, *dep, -1, NULL);
708 if (r) {
709 ERROR(db->pakfire, "Could not bind dependency: %s\n",
710 sqlite3_errmsg(db->handle));
711 goto END;
712 }
713
714 // Execute query
715 do {
716 r = sqlite3_step(stmt);
717 } while (r == SQLITE_BUSY);
718
719 free(*dep);
720
721 // Reset bound values
722 sqlite3_reset(stmt);
723 }
724
725 free(list);
726 }
727
728 // All okay
729 r = 0;
730
731 END:
732 if (stmt)
733 sqlite3_finalize(stmt);
734
735 return r;
736 }
737
738 static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, PakfireArchive archive) {
739 sqlite3_stmt* stmt = NULL;
740 int r = 1;
741
742 // Get the filelist from the archive
743 PakfireFilelist filelist = pakfire_archive_get_filelist(archive);
744 if (!filelist) {
745 ERROR(db->pakfire, "Could not fetch filelist from archive\n");
746 return 1;
747 }
748
749 // Nothing to do if the list is empty
750 if (pakfire_filelist_is_empty(filelist)) {
751 r = 0;
752 goto END;
753 }
754
755 const char* sql = "INSERT INTO files(pkg, path, size, type, config, datafile, mode, "
756 "user, 'group', hash1, ctime, mtime, capabilities) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
757
758 // Prepare the statement
759 r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL);
760 if (r) {
761 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
762 sql, sqlite3_errmsg(db->handle));
763 goto END;
764 }
765
766 for (unsigned int i = 0; i < pakfire_filelist_size(filelist); i++) {
767 PakfireFile file = pakfire_filelist_get(filelist, i);
768
769 // Bind package ID
770 r = sqlite3_bind_int64(stmt, 1, id);
771 if (r) {
772 ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
773 pakfire_file_unref(file);
774 goto END;
775 }
776
777 // Bind name
778 const char* path = pakfire_file_get_path(file);
779
780 r = sqlite3_bind_text(stmt, 2, path, -1, NULL);
781 if (r) {
782 ERROR(db->pakfire, "Could not bind path: %s\n", sqlite3_errmsg(db->handle));
783 pakfire_file_unref(file);
784 goto END;
785 }
786
787 // Bind size
788 size_t size = pakfire_file_get_size(file);
789
790 r = sqlite3_bind_int64(stmt, 3, size);
791 if (r) {
792 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
793 pakfire_file_unref(file);
794 goto END;
795 }
796
797 // Bind type - XXX this is char which isn't very helpful
798 //char type = pakfire_file_get_type(file);
799
800 r = sqlite3_bind_null(stmt, 4);
801 if (r) {
802 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
803 pakfire_file_unref(file);
804 goto END;
805 }
806
807 // Bind config - XXX TODO
808 r = sqlite3_bind_null(stmt, 5);
809 if (r) {
810 ERROR(db->pakfire, "Could not bind config: %s\n", sqlite3_errmsg(db->handle));
811 pakfire_file_unref(file);
812 goto END;
813 }
814
815 // Bind datafile - XXX TODO
816 r = sqlite3_bind_null(stmt, 6);
817 if (r) {
818 ERROR(db->pakfire, "Could not bind datafile: %s\n", sqlite3_errmsg(db->handle));
819 pakfire_file_unref(file);
820 goto END;
821 }
822
823 // Bind mode
824 mode_t mode = pakfire_file_get_mode(file);
825
826 r = sqlite3_bind_int64(stmt, 7, mode);
827 if (r) {
828 ERROR(db->pakfire, "Could not bind mode: %s\n", sqlite3_errmsg(db->handle));
829 pakfire_file_unref(file);
830 goto END;
831 }
832
833 // Bind user
834 const char* user = pakfire_file_get_user(file);
835
836 r = sqlite3_bind_text(stmt, 8, user, -1, NULL);
837 if (r) {
838 ERROR(db->pakfire, "Could not bind user: %s\n", sqlite3_errmsg(db->handle));
839 pakfire_file_unref(file);
840 goto END;
841 }
842
843 // Bind group
844 const char* group = pakfire_file_get_group(file);
845
846 r = sqlite3_bind_text(stmt, 9, group, -1, NULL);
847 if (r) {
848 ERROR(db->pakfire, "Could not bind group: %s\n", sqlite3_errmsg(db->handle));
849 pakfire_file_unref(file);
850 goto END;
851 }
852
853 // Bind hash1
854 const char* chksum = pakfire_file_get_chksum(file);
855
856 r = sqlite3_bind_text(stmt, 10, chksum, -1, NULL);
857 if (r) {
858 ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle));
859 pakfire_file_unref(file);
860 goto END;
861 }
862
863 // Bind ctime
864 time_t ctime = pakfire_file_get_ctime(file);
865
866 r = sqlite3_bind_int64(stmt, 11, ctime);
867 if (r) {
868 ERROR(db->pakfire, "Could not bind ctime: %s\n", sqlite3_errmsg(db->handle));
869 pakfire_file_unref(file);
870 goto END;
871 }
872
873 // Bind mtime
874 time_t mtime = pakfire_file_get_mtime(file);
875
876 r = sqlite3_bind_int64(stmt, 12, mtime);
877 if (r) {
878 ERROR(db->pakfire, "Could not bind mtime: %s\n", sqlite3_errmsg(db->handle));
879 pakfire_file_unref(file);
880 goto END;
881 }
882
883 // Bind capabilities - XXX TODO
884 r = sqlite3_bind_null(stmt, 13);
885 if (r) {
886 ERROR(db->pakfire, "Could not bind capabilities: %s\n", sqlite3_errmsg(db->handle));
887 pakfire_file_unref(file);
888 goto END;
889 }
890
891 // Execute query
892 do {
893 r = sqlite3_step(stmt);
894 } while (r == SQLITE_BUSY);
895
896 // Move on to next file
897 pakfire_file_unref(file);
898
899 // Check for errors
900 if (r != SQLITE_DONE) {
901 ERROR(db->pakfire, "Could not add file to database: %s\n",
902 sqlite3_errmsg(db->handle));
903 goto END;
904 }
905
906 // Reset bound values
907 sqlite3_reset(stmt);
908 }
909
910 // All okay
911 r = 0;
912
913 END:
914 if (stmt)
915 sqlite3_finalize(stmt);
916
917 pakfire_filelist_unref(filelist);
918
919 return r;
920 }
921
922 static int pakfire_db_add_scriptlets(struct pakfire_db* db, unsigned long id, PakfireArchive archive) {
923 sqlite3_stmt* stmt = NULL;
924 size_t size;
925 int r = 1;
926
927 const char* sql = "INSERT INTO scriptlets(pkg, type, scriptlet) VALUES(?, ?, ?)";
928
929 // Prepare the statement
930 r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL);
931 if (r) {
932 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
933 sql, sqlite3_errmsg(db->handle));
934 goto END;
935 }
936
937 for (const char** type = pakfire_scriptlet_types; *type; type++) {
938 // Fetch the scriptlet
939 struct pakfire_scriptlet* scriptlet = pakfire_archive_get_scriptlet(archive, *type);
940 if (!scriptlet)
941 continue;
942
943 // Bind package ID
944 r = sqlite3_bind_int64(stmt, 1, id);
945 if (r) {
946 ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
947 pakfire_scriptlet_unref(scriptlet);
948 goto END;
949 }
950
951 // Bind handle
952 r = sqlite3_bind_text(stmt, 2, *type, -1, NULL);
953 if (r) {
954 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
955 pakfire_scriptlet_unref(scriptlet);
956 goto END;
957 }
958
959 const char* data = pakfire_scriptlet_get_data(scriptlet, &size);
960
961 // Bind scriptlet
962 r = sqlite3_bind_text(stmt, 3, data, size, NULL);
963 if (r) {
964 ERROR(db->pakfire, "Could not bind scriptlet: %s\n", sqlite3_errmsg(db->handle));
965 pakfire_scriptlet_unref(scriptlet);
966 goto END;
967 }
968
969 // Execute query
970 do {
971 r = sqlite3_step(stmt);
972 } while (r == SQLITE_BUSY);
973
974 // Check for errors
975 if (r != SQLITE_DONE) {
976 ERROR(db->pakfire, "Could not add scriptlet to database: %s\n",
977 sqlite3_errmsg(db->handle));
978 pakfire_scriptlet_unref(scriptlet);
979 goto END;
980 }
981
982 pakfire_scriptlet_unref(scriptlet);
983
984 // Reset bound values
985 sqlite3_reset(stmt);
986 }
987
988 // All okay
989 r = 0;
990
991 END:
992 if (stmt)
993 sqlite3_finalize(stmt);
994
995 return r;
996 }
997
998 PAKFIRE_EXPORT int pakfire_db_add_package(struct pakfire_db* db,
999 PakfirePackage pkg, PakfireArchive archive) {
1000 sqlite3_stmt* stmt = NULL;
1001 int r;
1002
1003 // Begin a new transaction
1004 r = pakfire_db_begin_transaction(db);
1005 if (r)
1006 goto ROLLBACK;
1007
1008 const char* sql = "INSERT INTO packages(name, evr, arch, groups, filename, size, "
1009 "inst_size, hash1, license, summary, description, uuid, vendor, build_host, "
1010 "build_time, installed, repository, reason) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, "
1011 "?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)";
1012
1013 // Prepare the statement
1014 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1015 if (r != SQLITE_OK) {
1016 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
1017 sql, sqlite3_errmsg(db->handle));
1018 goto ROLLBACK;
1019 }
1020
1021 // Bind name
1022 const char* name = pakfire_package_get_name(pkg);
1023
1024 r = sqlite3_bind_text(stmt, 1, name, -1, NULL);
1025 if (r) {
1026 ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
1027 goto ROLLBACK;
1028 }
1029
1030 // Bind evr
1031 const char* evr = pakfire_package_get_evr(pkg);
1032
1033 r = sqlite3_bind_text(stmt, 2, evr, -1, NULL);
1034 if (r) {
1035 ERROR(db->pakfire, "Could not bind evr: %s\n", sqlite3_errmsg(db->handle));
1036 goto ROLLBACK;
1037 }
1038
1039 // Bind arch
1040 const char* arch = pakfire_package_get_arch(pkg);
1041
1042 r = sqlite3_bind_text(stmt, 3, arch, -1, NULL);
1043 if (r) {
1044 ERROR(db->pakfire, "Could not bind arch: %s\n", sqlite3_errmsg(db->handle));
1045 goto ROLLBACK;
1046 }
1047
1048 // Bind groups
1049 char* groups = pakfire_package_get_groups(pkg);
1050 if (groups) {
1051 r = sqlite3_bind_text(stmt, 4, groups, -1, NULL);
1052 if (r) {
1053 ERROR(db->pakfire, "Could not bind groups: %s\n", sqlite3_errmsg(db->handle));
1054 free(groups);
1055 goto ROLLBACK;
1056 }
1057
1058 free(groups);
1059
1060 // No groups
1061 } else {
1062 r = sqlite3_bind_null(stmt, 4);
1063 if (r)
1064 goto ROLLBACK;
1065 }
1066
1067 // Bind filename
1068 const char* filename = pakfire_package_get_filename(pkg);
1069
1070 r = sqlite3_bind_text(stmt, 5, filename, -1, NULL);
1071 if (r) {
1072 ERROR(db->pakfire, "Could not bind filename: %s\n", sqlite3_errmsg(db->handle));
1073 goto ROLLBACK;
1074 }
1075
1076 // Bind size
1077 unsigned long long size = pakfire_package_get_downloadsize(pkg);
1078
1079 r = sqlite3_bind_int64(stmt, 6, size);
1080 if (r) {
1081 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
1082 goto ROLLBACK;
1083 }
1084
1085 // Bind installed size
1086 unsigned long long inst_size = pakfire_package_get_installsize(pkg);
1087
1088 r = sqlite3_bind_int64(stmt, 7, inst_size);
1089 if (r) {
1090 ERROR(db->pakfire, "Could not bind inst_size: %s\n", sqlite3_errmsg(db->handle));
1091 goto ROLLBACK;
1092 }
1093
1094 // Bind hash1
1095 const char* hash1 = pakfire_package_get_checksum(pkg);
1096
1097 r = sqlite3_bind_text(stmt, 8, hash1, -1, NULL);
1098 if (r) {
1099 ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle));
1100 goto ROLLBACK;
1101 }
1102
1103 // Bind license
1104 const char* license = pakfire_package_get_license(pkg);
1105
1106 r = sqlite3_bind_text(stmt, 9, license, -1, NULL);
1107 if (r) {
1108 ERROR(db->pakfire, "Could not bind license: %s\n", sqlite3_errmsg(db->handle));
1109 goto ROLLBACK;
1110 }
1111
1112 // Bind summary
1113 const char* summary = pakfire_package_get_summary(pkg);
1114
1115 r = sqlite3_bind_text(stmt, 10, summary, -1, NULL);
1116 if (r) {
1117 ERROR(db->pakfire, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle));
1118 goto ROLLBACK;
1119 }
1120
1121 // Bind description
1122 const char* description = pakfire_package_get_description(pkg);
1123
1124 r = sqlite3_bind_text(stmt, 11, description, -1, NULL);
1125 if (r) {
1126 ERROR(db->pakfire, "Could not bind description: %s\n", sqlite3_errmsg(db->handle));
1127 goto ROLLBACK;
1128 }
1129
1130 // Bind uuid
1131 const char* uuid = pakfire_package_get_uuid(pkg);
1132
1133 r = sqlite3_bind_text(stmt, 12, uuid, -1, NULL);
1134 if (r) {
1135 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
1136 goto ROLLBACK;
1137 }
1138
1139 // Bind vendor
1140 const char* vendor = pakfire_package_get_vendor(pkg);
1141
1142 r = sqlite3_bind_text(stmt, 13, vendor, -1, NULL);
1143 if (r) {
1144 ERROR(db->pakfire, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle));
1145 goto ROLLBACK;
1146 }
1147
1148 // Bind build_host
1149 const char* build_host = pakfire_package_get_build_host(pkg);
1150
1151 r = sqlite3_bind_text(stmt, 14, build_host, -1, NULL);
1152 if (r) {
1153 ERROR(db->pakfire, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle));
1154 goto ROLLBACK;
1155 }
1156
1157 // Bind build_time
1158 time_t build_time = pakfire_package_get_build_time(pkg);
1159
1160 r = sqlite3_bind_int64(stmt, 15, build_time);
1161 if (r) {
1162 ERROR(db->pakfire, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle));
1163 goto ROLLBACK;
1164 }
1165
1166 // Bind repository name
1167 PakfireRepo repo = pakfire_package_get_repo(pkg);
1168 if (repo) {
1169 const char* repo_name = pakfire_repo_get_name(repo);
1170 pakfire_repo_unref(repo);
1171
1172 r = sqlite3_bind_text(stmt, 16, repo_name, -1, NULL);
1173 if (r)
1174 goto ROLLBACK;
1175
1176 // No repository?
1177 } else {
1178 r = sqlite3_bind_null(stmt, 16);
1179 if (r)
1180 goto ROLLBACK;
1181 }
1182
1183 // XXX TODO Bind reason
1184 r = sqlite3_bind_null(stmt, 17);
1185 if (r)
1186 goto ROLLBACK;
1187
1188 // Run query
1189 do {
1190 r = sqlite3_step(stmt);
1191 } while (r == SQLITE_BUSY);
1192
1193 if (r != SQLITE_DONE) {
1194 ERROR(db->pakfire, "Could not add package to database: %s\n",
1195 sqlite3_errmsg(db->handle));
1196 goto ROLLBACK;
1197 }
1198
1199 // Save package ID
1200 unsigned long packages_id = sqlite3_last_insert_rowid(db->handle);
1201
1202 // This is done
1203 r = sqlite3_finalize(stmt);
1204 if (r == SQLITE_OK)
1205 stmt = NULL;
1206
1207 // Add dependencies
1208 r = pakfire_db_add_dependencies(db, packages_id, pkg);
1209 if (r)
1210 goto ROLLBACK;
1211
1212 // Add files
1213 r = pakfire_db_add_files(db, packages_id, archive);
1214 if (r)
1215 goto ROLLBACK;
1216
1217 // Add scriptlets
1218 r = pakfire_db_add_scriptlets(db, packages_id, archive);
1219 if (r)
1220 goto ROLLBACK;
1221
1222 // All done, commit!
1223 r = pakfire_db_commit(db);
1224 if (r)
1225 goto ROLLBACK;
1226
1227 return 0;
1228
1229 ROLLBACK:
1230 if (stmt)
1231 sqlite3_finalize(stmt);
1232
1233 pakfire_db_rollback(db);
1234
1235 return 1;
1236 }
1237
1238 PAKFIRE_EXPORT int pakfire_db_remove_package(struct pakfire_db* db, PakfirePackage pkg) {
1239 sqlite3_stmt* stmt = NULL;
1240 int r = 1;
1241
1242 // Fetch the package's UUID
1243 const char* uuid = pakfire_package_get_uuid(pkg);
1244 if (!uuid) {
1245 ERROR(db->pakfire, "Package has no UUID\n");
1246 goto ERROR;
1247 }
1248
1249 r = sqlite3_prepare_v2(db->handle,
1250 "DELETE FROM packages WHERE uuid = ?", -1, &stmt, NULL);
1251 if (r) {
1252 ERROR(db->pakfire, "Could not prepare SQL statement: %s\n",
1253 sqlite3_errmsg(db->handle));
1254 goto ERROR;
1255 }
1256
1257 // Bind UUID
1258 r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
1259 if (r) {
1260 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
1261 return 1;
1262 }
1263
1264 // Execute query
1265 do {
1266 r = sqlite3_step(stmt);
1267 } while (r == SQLITE_BUSY);
1268
1269 // Check if we have been successful
1270 if (r != SQLITE_DONE) {
1271 ERROR(db->pakfire, "Could not delete package %s\n", uuid);
1272 r = 1;
1273 goto ERROR;
1274 }
1275
1276 r = 0;
1277
1278 ERROR:
1279 if (stmt)
1280 sqlite3_finalize(stmt);
1281
1282 return r;
1283 }
1284
1285 struct pakfire_scriptlet* pakfire_db_get_scriptlet(struct pakfire_db* db,
1286 PakfirePackage pkg, const char* type) {
1287 struct pakfire_scriptlet* scriptlet = NULL;
1288 sqlite3_stmt* stmt = NULL;
1289 int r = 1;
1290
1291 // Fetch the package's UUID
1292 const char* uuid = pakfire_package_get_uuid(pkg);
1293 if (!uuid) {
1294 ERROR(db->pakfire, "Package has no UUID\n");
1295 goto ERROR;
1296 }
1297
1298 const char* sql = "SELECT scriptlet.scriptlet FROM packages \
1299 JOIN scriptlets ON packages.id = scriptlets.pkg \
1300 WHERE packages.uuid = ? AND scriptlets.type = ?";
1301
1302 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1303 if (r) {
1304 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
1305 sql, sqlite3_errmsg(db->handle));
1306 goto ERROR;
1307 }
1308
1309 // Bind UUID
1310 r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
1311 if (r) {
1312 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
1313 goto ERROR;
1314 }
1315
1316 r = sqlite3_bind_text(stmt, 2, type, -1, NULL);
1317 if (r) {
1318 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
1319 goto ERROR;
1320 }
1321
1322 DEBUG(db->pakfire, "Searching for scriptlet for package %s of type %s\n", uuid, type);
1323
1324 // Execute query
1325 do {
1326 r = sqlite3_step(stmt);
1327 } while (r == SQLITE_BUSY);
1328
1329 // We have some payload
1330 if (r == SQLITE_ROW) {
1331 const void* data = sqlite3_column_blob(stmt, 1);
1332 ssize_t size = sqlite3_column_bytes(stmt, 1);
1333
1334 // Create a scriptlet object
1335 r = pakfire_scriptlet_create(&scriptlet, db->pakfire, type, data, size);
1336 if (r)
1337 goto ERROR;
1338 }
1339
1340 ERROR:
1341 if (stmt)
1342 sqlite3_finalize(stmt);
1343
1344 return scriptlet;
1345 }
1346
1347 static int pakfire_db_load_package(struct pakfire_db* db, PakfireRepo repo, sqlite3_stmt* stmt) {
1348 PakfirePackage pkg = NULL;
1349 int r = 1;
1350
1351 // Name
1352 const char* name = (const char*)sqlite3_column_text(stmt, 0);
1353 if (!name) {
1354 ERROR(db->pakfire, "Could not read name: %s\n", sqlite3_errmsg(db->handle));
1355 goto ERROR;
1356 }
1357
1358 // EVR
1359 const char* evr = (const char*)sqlite3_column_text(stmt, 1);
1360 if (!evr) {
1361 ERROR(db->pakfire, "Could not read evr: %s\n", sqlite3_errmsg(db->handle));
1362 goto ERROR;
1363 }
1364
1365 // Arch
1366 const char* arch = (const char*)sqlite3_column_text(stmt, 2);
1367 if (!arch) {
1368 ERROR(db->pakfire, "Could not read arch: %s\n", sqlite3_errmsg(db->handle));
1369 goto ERROR;
1370 }
1371
1372 // Create package
1373 pkg = pakfire_package_create(db->pakfire, repo, name, evr, arch);
1374 if (!pkg) {
1375 ERROR(db->pakfire, "Could not create package\n");
1376 goto ERROR;
1377 }
1378
1379 // Groups
1380 const char* groups = (const char*)sqlite3_column_text(stmt, 3);
1381 if (groups) {
1382 pakfire_package_set_groups(pkg, groups);
1383 }
1384
1385 // Filename
1386 const char* filename = (const char*)sqlite3_column_text(stmt, 4);
1387 if (filename) {
1388 pakfire_package_set_filename(pkg, filename);
1389 }
1390
1391 // Size
1392 size_t size = sqlite3_column_int64(stmt, 5);
1393 if (size) {
1394 pakfire_package_set_downloadsize(pkg, size);
1395 }
1396
1397 // Installed size
1398 size = sqlite3_column_int64(stmt, 6);
1399 if (size) {
1400 pakfire_package_set_installsize(pkg, size);
1401 }
1402
1403 // Hash 1
1404 const char* hash1 = (const char*)sqlite3_column_text(stmt, 7);
1405 if (hash1) {
1406 pakfire_package_set_checksum(pkg, hash1);
1407 }
1408
1409 // License
1410 const char* license = (const char*)sqlite3_column_text(stmt, 8);
1411 if (license) {
1412 pakfire_package_set_license(pkg, license);
1413 }
1414
1415 // Summary
1416 const char* summary = (const char*)sqlite3_column_text(stmt, 9);
1417 if (summary) {
1418 pakfire_package_set_summary(pkg, summary);
1419 }
1420
1421 // Description
1422 const char* description = (const char*)sqlite3_column_text(stmt, 10);
1423 if (description) {
1424 pakfire_package_set_description(pkg, description);
1425 }
1426
1427 // UUID
1428 const char* uuid = (const char*)sqlite3_column_text(stmt, 11);
1429 if (uuid) {
1430 pakfire_package_set_uuid(pkg, uuid);
1431 }
1432
1433 // Vendor
1434 const char* vendor = (const char*)sqlite3_column_text(stmt, 12);
1435 if (vendor) {
1436 pakfire_package_set_vendor(pkg, vendor);
1437 }
1438
1439 // Build Host
1440 const char* build_host = (const char*)sqlite3_column_text(stmt, 13);
1441 if (build_host) {
1442 pakfire_package_set_build_host(pkg, build_host);
1443 }
1444
1445 // Build Time
1446 time_t build_time = sqlite3_column_int64(stmt, 14);
1447 if (build_time) {
1448 pakfire_package_set_build_time(pkg, build_time);
1449 }
1450
1451 // Install Time
1452 time_t install_time = sqlite3_column_int64(stmt, 15);
1453 if (install_time) {
1454 pakfire_package_set_install_time(pkg, install_time);
1455 }
1456
1457 // Files
1458 const char* files = (const char*)sqlite3_column_text(stmt, 16);
1459 if (files) {
1460 r = pakfire_package_set_filelist_from_string(pkg, files);
1461 if (r)
1462 goto ERROR;
1463 }
1464
1465 // Dependencies
1466
1467 const struct dependency {
1468 unsigned int field;
1469 void (*func)(PakfirePackage pkg, const char* dep);
1470 } dependencies[] = {
1471 { 17, pakfire_package_add_provides },
1472 { 18, pakfire_package_add_prerequires },
1473 { 10, pakfire_package_add_requires },
1474 { 20, pakfire_package_add_conflicts },
1475 { 21, pakfire_package_add_obsoletes },
1476 { 22, pakfire_package_add_recommends },
1477 { 23, pakfire_package_add_suggests },
1478 { 24, pakfire_package_add_supplements },
1479 { 25, pakfire_package_add_enhances },
1480 { 0, NULL },
1481 };
1482
1483 for (const struct dependency* deps = dependencies; deps->field; deps++) {
1484 const char* relations = (const char*)sqlite3_column_text(stmt, deps->field);
1485 if (relations) {
1486 pakfire_parse_deps(db->pakfire, pkg, deps->func, relations);
1487 }
1488 }
1489
1490 // Success
1491 r = 0;
1492
1493 ERROR:
1494 if (pkg)
1495 pakfire_package_unref(pkg);
1496
1497 return r;
1498 }
1499
1500 int pakfire_db_load(struct pakfire_db* db, PakfireRepo repo) {
1501 sqlite3_stmt* stmt = NULL;
1502 int r = 1;
1503
1504 DEBUG(db->pakfire, "Loading package database...\n");
1505
1506 // Drop contents of the repository
1507 pakfire_repo_clear(repo);
1508
1509 // Save starting time
1510 clock_t t_start = clock();
1511 clock_t t_end;
1512
1513 const char* sql =
1514 "SELECT "
1515 "name, evr, arch, groups, filename, size, inst_size, hash1, license, summary, "
1516 "description, uuid, vendor, build_host, build_time, "
1517 "strftime('%s', installed) AS installed, "
1518 "("
1519 "SELECT group_concat(path, '\n') FROM files WHERE files.pkg = packages.id"
1520 ") AS files, "
1521 "("
1522 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1523 "WHERE d.pkg = packages.id AND d.type = 'provides'"
1524 ") AS provides, "
1525 "("
1526 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1527 "WHERE d.pkg = packages.id AND d.type = 'prerequires'"
1528 ") AS prerequires, "
1529 "("
1530 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1531 "WHERE d.pkg = packages.id AND d.type = 'requires'"
1532 ") AS requires, "
1533 "("
1534 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1535 "WHERE d.pkg = packages.id AND d.type = 'conflicts'"
1536 ") AS conflicts, "
1537 "("
1538 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1539 "WHERE d.pkg = packages.id AND d.type = 'obsoletes'"
1540 ") AS obsoletes, "
1541 "("
1542 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1543 "WHERE d.pkg = packages.id AND d.type = 'recommends'"
1544 ") AS recommends, "
1545 "("
1546 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1547 "WHERE d.pkg = packages.id AND d.type = 'suggests'"
1548 ") AS suggests, "
1549 "("
1550 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1551 "WHERE d.pkg = packages.id AND d.type = 'supplements'"
1552 ") AS supplements, "
1553 "("
1554 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1555 "WHERE d.pkg = packages.id AND d.type = 'enhances'"
1556 ") AS enhances "
1557 "FROM "
1558 "packages"
1559 ";";
1560
1561 // Prepare the statement
1562 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1563 if (r) {
1564 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
1565 sql, sqlite3_errmsg(db->handle));
1566 goto ERROR;
1567 }
1568
1569 for (;;) {
1570 // Execute query
1571 r = sqlite3_step(stmt);
1572
1573 switch (r) {
1574 // Retry if the database was busy
1575 case SQLITE_BUSY:
1576 continue;
1577
1578 // Read a row
1579 case SQLITE_ROW:
1580 r = pakfire_db_load_package(db, repo, stmt);
1581 if (r)
1582 goto ERROR;
1583 break;
1584
1585 // All rows have been processed
1586 case SQLITE_DONE:
1587 goto END;
1588
1589 // Go to error in any other cases
1590 default:
1591 goto ERROR;
1592 }
1593 }
1594
1595 END:
1596 // Save time when we finished
1597 t_end = clock();
1598
1599 DEBUG(db->pakfire, "Loading package database completed in %.4fms\n",
1600 (double)(t_end - t_start) * 1000 / CLOCKS_PER_SEC);
1601
1602 // Internalize repository
1603 pakfire_repo_internalize(repo);
1604
1605 // All done
1606 r = 0;
1607
1608 ERROR:
1609 if (r) {
1610 ERROR(db->pakfire, "Failed reading package database: %d\n", r);
1611 pakfire_repo_clear(repo);
1612 }
1613
1614 if (stmt)
1615 sqlite3_finalize(stmt);
1616
1617 return r;
1618 }