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