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