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