]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/db.c
db: Check for errors after INSERT
[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, "
295 "name TEXT, "
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, "
305 "mtime INTEGER, "
46257c5f 306 "capabilities TEXT, "
432a328a 307 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
68036506
MT
308 ")");
309 if (r)
310 return 1;
311
312 // files: Add index over packages
313 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS files_pkg_index ON files(pkg)");
314 if (r)
315 return 1;
316
d83414aa
MT
317 // Create scriptlets table
318 r = pakfire_db_execute(db,
319 "CREATE TABLE IF NOT EXISTS scriptlets("
320 "id INTEGER PRIMARY KEY, "
321 "pkg INTEGER, "
265f539a 322 "type TEXT, "
46257c5f 323 "scriptlet TEXT, "
432a328a 324 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
d83414aa
MT
325 ")");
326 if (r)
327 return 1;
328
329 // scriptlets: Add index over packages
330 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS scriptlets_pkg_index ON scriptlets(pkg)");
331 if (r)
332 return 1;
333
c745fb2d
MT
334 return 0;
335}
336
46257c5f 337static int pakfire_db_migrate_to_schema_8(struct pakfire_db* db) {
5ba550fe
MT
338 // packages: Drop build_id column
339
46257c5f
MT
340 // Add foreign keys
341 // TODO sqlite doesn't support adding foreign keys to existing tables and so we would
342 // need to recreate the whole table and rename it afterwards. Annoying.
343
344 return 0;
345}
346
c745fb2d
MT
347static int pakfire_db_migrate_schema(struct pakfire_db* db) {
348 int r;
349
350 while (db->schema < CURRENT_SCHEMA) {
351 // Begin a new transaction
352 r = pakfire_db_begin_transaction(db);
353 if (r)
354 goto ROLLBACK;
355
356 switch (db->schema) {
357 // No schema exists
f168dd0c 358 case -1:
c745fb2d
MT
359 r = pakfire_db_create_schema(db);
360 if (r)
361 goto ROLLBACK;
362
363 db->schema = CURRENT_SCHEMA;
364 break;
365
46257c5f
MT
366 case 7:
367 r = pakfire_db_migrate_to_schema_8(db);
368 if (r)
369 goto ROLLBACK;
370
371 db->schema++;
372 break;
373
c745fb2d
MT
374 default:
375 ERROR(db->pakfire, "Cannot migrate database from schema %d\n", db->schema);
376 goto ROLLBACK;
377 }
378
379 // Update the schema version
380 r = pakfire_db_set_int(db, "schema", CURRENT_SCHEMA);
381 if (r)
382 goto ROLLBACK;
383
384 // All done, commit!
385 r = pakfire_db_commit(db);
386 if (r)
387 goto ROLLBACK;
388 }
389
390 return 0;
391
392ROLLBACK:
393 pakfire_db_rollback(db);
394
395 return 1;
396}
397
9c5938ea 398static int pakfire_db_setup(struct pakfire_db* db) {
25753290
MT
399 int r;
400
9c5938ea
MT
401 // Setup logging
402 sqlite3_config(SQLITE_CONFIG_LOG, logging_callback, db->pakfire);
403
46257c5f
MT
404 // Enable foreign keys
405 pakfire_db_execute(db, "PRAGMA foreign_keys = ON");
406
0076c50d
MT
407 // Make LIKE case-sensitive
408 pakfire_db_execute(db, "PRAGMA case_sensitive_like = ON");
409
c745fb2d
MT
410 // Fetch the current schema
411 db->schema = pakfire_db_get_schema(db);
412
413 // Check if the schema is recent enough
414 if (db->schema > 0 && db->schema < SCHEMA_MIN_SUP) {
415 ERROR(db->pakfire, "Database schema %d is not supported by this version of Pakfire\n",
416 db->schema);
417 return 1;
418 }
419
9c5938ea
MT
420 // Done when not in read-write mode
421 if (db->mode != PAKFIRE_DB_READWRITE)
422 return 0;
423
0076c50d
MT
424 // Disable secure delete
425 pakfire_db_execute(db, "PRAGMA secure_delete = OFF");
426
25753290
MT
427 // Set database journal to WAL
428 r = pakfire_db_execute(db, "PRAGMA journal_mode = WAL");
429 if (r != SQLITE_OK) {
430 ERROR(db->pakfire, "Could not set journal mode to WAL: %s\n",
431 sqlite3_errmsg(db->handle));
432 return 1;
433 }
434
435 // Disable autocheckpoint
436 r = sqlite3_wal_autocheckpoint(db->handle, 0);
437 if (r != SQLITE_OK) {
438 ERROR(db->pakfire, "Could not disable autocheckpoint: %s\n",
439 sqlite3_errmsg(db->handle));
440 return 1;
441 }
442
c745fb2d
MT
443 // Create or migrate schema
444 r = pakfire_db_migrate_schema(db);
445 if (r)
446 return r;
9c5938ea
MT
447
448 return 0;
449}
450
77a4b3a3 451PAKFIRE_EXPORT int pakfire_db_open(struct pakfire_db** db, Pakfire pakfire, int flags) {
26affd69
MT
452 int r = 1;
453
90312f5c 454 struct pakfire_db* o = calloc(1, sizeof(*o));
33d55ab4
MT
455 if (!o)
456 return -ENOMEM;
457
458 DEBUG(pakfire, "Allocated database at %p\n", o);
459
460 o->pakfire = pakfire_ref(pakfire);
461 o->nrefs = 1;
462
26affd69
MT
463 int sqlite3_flags = 0;
464
465 // Store mode & forward it to sqlite3
466 if (flags & PAKFIRE_DB_READWRITE) {
77a4b3a3 467 o->mode = PAKFIRE_DB_READWRITE;
26affd69
MT
468 sqlite3_flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
469 } else {
77a4b3a3 470 o->mode = PAKFIRE_DB_READONLY;
26affd69
MT
471 sqlite3_flags |= SQLITE_OPEN_READONLY;
472 }
473
474 // Make the filename
475 char* path = pakfire_make_path(o->pakfire, DATABASE_PATH);
476 if (!path)
477 goto END;
478
479 // Try to open the sqlite3 database file
480 r = sqlite3_open_v2(path, &o->handle, sqlite3_flags, NULL);
481 if (r != SQLITE_OK) {
482 ERROR(pakfire, "Could not open database %s: %s\n",
483 path, sqlite3_errmsg(o->handle));
484
485 r = 1;
486 goto END;
487 }
77a4b3a3 488
9c5938ea
MT
489 // Setup the database
490 r = pakfire_db_setup(o);
491 if (r)
492 goto END;
493
33d55ab4 494 *db = o;
26affd69
MT
495 r = 0;
496
497END:
498 if (r)
499 pakfire_db_free(o);
33d55ab4 500
26affd69
MT
501 if (path)
502 free(path);
503
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
MT
771 // Nothing to do if the list is empty
772 if (pakfire_filelist_is_empty(filelist))
773 goto END;
774
f5c77233
MT
775 const char* sql = "INSERT INTO files(pkg, name, size, type, config, datafile, mode, "
776 "user, 'group', hash1, mtime, capabilities) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
777
778 // Prepare the statement
779 r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL);
780 if (r) {
781 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
782 sql, sqlite3_errmsg(db->handle));
783 goto END;
784 }
785
5e9463ec
MT
786 for (unsigned int i = 0; i < pakfire_filelist_size(filelist); i++) {
787 PakfireFile file = pakfire_filelist_get(filelist, i);
788
f5c77233
MT
789 // Bind package ID
790 r = sqlite3_bind_int64(stmt, 1, id);
791 if (r) {
792 ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 793 pakfire_file_unref(file);
f5c77233
MT
794 goto END;
795 }
796
797 // Bind name
798 const char* name = pakfire_file_get_name(file);
799
800 r = sqlite3_bind_text(stmt, 2, name, -1, NULL);
801 if (r) {
802 ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 803 pakfire_file_unref(file);
f5c77233
MT
804 goto END;
805 }
806
807 // Bind size
808 size_t size = pakfire_file_get_size(file);
809
810 r = sqlite3_bind_int64(stmt, 3, size);
811 if (r) {
812 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 813 pakfire_file_unref(file);
f5c77233
MT
814 goto END;
815 }
816
817 // Bind type - XXX this is char which isn't very helpful
818 //char type = pakfire_file_get_type(file);
819
820 r = sqlite3_bind_null(stmt, 4);
821 if (r) {
822 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 823 pakfire_file_unref(file);
f5c77233
MT
824 goto END;
825 }
826
827 // Bind config - XXX TODO
828 r = sqlite3_bind_null(stmt, 5);
829 if (r) {
830 ERROR(db->pakfire, "Could not bind config: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 831 pakfire_file_unref(file);
f5c77233
MT
832 goto END;
833 }
834
835 // Bind datafile - XXX TODO
836 r = sqlite3_bind_null(stmt, 6);
837 if (r) {
838 ERROR(db->pakfire, "Could not bind datafile: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 839 pakfire_file_unref(file);
f5c77233
MT
840 goto END;
841 }
842
843 // Bind mode
844 mode_t mode = pakfire_file_get_mode(file);
845
846 r = sqlite3_bind_int64(stmt, 7, mode);
847 if (r) {
848 ERROR(db->pakfire, "Could not bind mode: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 849 pakfire_file_unref(file);
f5c77233
MT
850 goto END;
851 }
852
853 // Bind user
854 const char* user = pakfire_file_get_user(file);
855
856 r = sqlite3_bind_text(stmt, 8, user, -1, NULL);
857 if (r) {
858 ERROR(db->pakfire, "Could not bind user: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 859 pakfire_file_unref(file);
f5c77233
MT
860 goto END;
861 }
862
863 // Bind group
864 const char* group = pakfire_file_get_group(file);
865
866 r = sqlite3_bind_text(stmt, 9, group, -1, NULL);
867 if (r) {
868 ERROR(db->pakfire, "Could not bind group: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 869 pakfire_file_unref(file);
f5c77233
MT
870 goto END;
871 }
872
873 // Bind hash1
874 const char* chksum = pakfire_file_get_chksum(file);
875
876 r = sqlite3_bind_text(stmt, 10, chksum, -1, NULL);
877 if (r) {
878 ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 879 pakfire_file_unref(file);
f5c77233
MT
880 goto END;
881 }
882
883 // Bind mtime
884 time_t mtime = pakfire_file_get_time(file);
885
886 r = sqlite3_bind_int64(stmt, 11, mtime);
887 if (r) {
888 ERROR(db->pakfire, "Could not bind mtime: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 889 pakfire_file_unref(file);
f5c77233
MT
890 goto END;
891 }
892
893 // Bind capabilities - XXX TODO
894 r = sqlite3_bind_null(stmt, 12);
895 if (r) {
896 ERROR(db->pakfire, "Could not bind capabilities: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 897 pakfire_file_unref(file);
f5c77233
MT
898 goto END;
899 }
900
901 // Execute query
902 do {
903 r = sqlite3_step(stmt);
904 } while (r == SQLITE_BUSY);
905
906 // Move on to next file
5e9463ec 907 pakfire_file_unref(file);
f5c77233 908
5bae3112
MT
909 // Check for errors
910 if (r != SQLITE_DONE) {
911 ERROR(db->pakfire, "Could not add file to database: %s\n",
912 sqlite3_errmsg(db->handle));
913 goto END;
914 }
915
f5c77233
MT
916 // Reset bound values
917 sqlite3_reset(stmt);
918 }
919
920 // All okay
921 r = 0;
922
923END:
924 if (stmt)
925 sqlite3_finalize(stmt);
926
5e9463ec
MT
927 pakfire_filelist_unref(filelist);
928
f5c77233
MT
929 return r;
930}
931
265f539a
MT
932static int pakfire_db_add_scriptlets(struct pakfire_db* db, unsigned long id, PakfireArchive archive) {
933 sqlite3_stmt* stmt = NULL;
934 int r = 1;
935
f6942b34 936 const struct pakfire_scriptlet_type* scriptlet_type = PAKFIRE_SCRIPTLET_TYPES;
265f539a
MT
937 struct pakfire_scriptlet* scriptlet;
938
939 const char* sql = "INSERT INTO scriptlets(pkg, type, scriptlet) VALUES(?, ?, ?)";
940
941 // Prepare the statement
942 r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL);
943 if (r) {
944 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
945 sql, sqlite3_errmsg(db->handle));
946 goto END;
947 }
948
949 while (scriptlet_type->type) {
950 // Fetch the scriptlet
951 scriptlet = pakfire_archive_get_scriptlet(archive, scriptlet_type->type);
952
953 // Go to next one if the archive does not have a scriptlet of the given type
954 if (!scriptlet) {
955 scriptlet_type++;
956 continue;
957 }
958
959 // Bind package ID
960 r = sqlite3_bind_int64(stmt, 1, id);
961 if (r) {
962 ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
963 goto END;
964 }
965
966 // Bind handle
967 r = sqlite3_bind_text(stmt, 2, scriptlet_type->handle, -1, NULL);
968 if (r) {
969 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
970 goto END;
971 }
972
973 // Bind scriptlet
974 r = sqlite3_bind_text(stmt, 3, scriptlet->data, scriptlet->size, NULL);
975 if (r) {
976 ERROR(db->pakfire, "Could not bind scriptlet: %s\n", sqlite3_errmsg(db->handle));
977 goto END;
978 }
979
980 // Execute query
981 do {
982 r = sqlite3_step(stmt);
983 } while (r == SQLITE_BUSY);
984
5bae3112
MT
985 // Check for errors
986 if (r != SQLITE_DONE) {
987 ERROR(db->pakfire, "Could not add scriptlet to database: %s\n",
988 sqlite3_errmsg(db->handle));
989 goto END;
990 }
991
265f539a
MT
992 // Reset bound values
993 sqlite3_reset(stmt);
994
995 scriptlet_type++;
996 }
997
998 // All okay
999 r = 0;
1000
1001END:
1002 if (stmt)
1003 sqlite3_finalize(stmt);
1004
1005 return r;
1006}
1007
f5c77233
MT
1008PAKFIRE_EXPORT int pakfire_db_add_package(struct pakfire_db* db,
1009 PakfirePackage pkg, PakfireArchive archive) {
e49b93d1
MT
1010 sqlite3_stmt* stmt = NULL;
1011 int r;
1012
1013 // Begin a new transaction
1014 r = pakfire_db_begin_transaction(db);
1015 if (r)
1016 goto ROLLBACK;
1017
1018 const char* sql = "INSERT INTO packages(name, epoch, version, release, arch, groups, "
1019 "filename, size, inst_size, hash1, license, summary, description, uuid, vendor, "
1ca6a13d
MT
1020 "build_host, build_time, installed, repository, reason) VALUES(?, ?, "
1021 "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)";
e49b93d1
MT
1022
1023 // Prepare the statement
1024 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1025 if (r != SQLITE_OK) {
1026 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
1027 sql, sqlite3_errmsg(db->handle));
1028 goto ROLLBACK;
1029 }
1030
1031 // Bind name
1032 const char* name = pakfire_package_get_name(pkg);
1033
1034 r = sqlite3_bind_text(stmt, 1, name, -1, NULL);
1035 if (r) {
1036 ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
1037 goto ROLLBACK;
1038 }
1039
1040 // Bind epoch
1041 unsigned long epoch = pakfire_package_get_epoch(pkg);
1042
1043 r = sqlite3_bind_int64(stmt, 2, epoch);
1044 if (r) {
1045 ERROR(db->pakfire, "Could not bind epoch: %s\n", sqlite3_errmsg(db->handle));
1046 goto ROLLBACK;
1047 }
1048
1049 // Bind version
1050 const char* version = pakfire_package_get_version(pkg);
1051
1052 r = sqlite3_bind_text(stmt, 3, version, -1, NULL);
1053 if (r) {
1054 ERROR(db->pakfire, "Could not bind version: %s\n", sqlite3_errmsg(db->handle));
1055 goto ROLLBACK;
1056 }
1057
1058 // Bind release
1059 const char* release = pakfire_package_get_release(pkg);
1060
1061 r = sqlite3_bind_text(stmt, 4, release, -1, NULL);
1062 if (r) {
1063 ERROR(db->pakfire, "Could not bind release: %s\n", sqlite3_errmsg(db->handle));
1064 goto ROLLBACK;
1065 }
1066
1067 // Bind arch
1068 const char* arch = pakfire_package_get_arch(pkg);
1069
1070 r = sqlite3_bind_text(stmt, 5, arch, -1, NULL);
1071 if (r) {
1072 ERROR(db->pakfire, "Could not bind arch: %s\n", sqlite3_errmsg(db->handle));
1073 goto ROLLBACK;
1074 }
1075
1076 // Bind groups
1077 const char* groups = pakfire_package_get_groups(pkg);
1078
1079 r = sqlite3_bind_text(stmt, 6, groups, -1, NULL);
1080 if (r) {
1081 ERROR(db->pakfire, "Could not bind groups: %s\n", sqlite3_errmsg(db->handle));
1082 goto ROLLBACK;
1083 }
1084
1085 // Bind filename
1086 const char* filename = pakfire_package_get_filename(pkg);
1087
1088 r = sqlite3_bind_text(stmt, 7, filename, -1, NULL);
1089 if (r) {
1090 ERROR(db->pakfire, "Could not bind filename: %s\n", sqlite3_errmsg(db->handle));
1091 goto ROLLBACK;
1092 }
1093
1094 // Bind size
1095 unsigned long long size = pakfire_package_get_downloadsize(pkg);
1096
1097 r = sqlite3_bind_int64(stmt, 8, size);
1098 if (r) {
1099 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
1100 goto ROLLBACK;
1101 }
1102
1103 // Bind installed size
1104 unsigned long long inst_size = pakfire_package_get_installsize(pkg);
1105
1106 r = sqlite3_bind_int64(stmt, 9, inst_size);
1107 if (r) {
1108 ERROR(db->pakfire, "Could not bind inst_size: %s\n", sqlite3_errmsg(db->handle));
1109 goto ROLLBACK;
1110 }
1111
1112 // Bind hash1
1113 const char* hash1 = pakfire_package_get_checksum(pkg);
1114
1115 r = sqlite3_bind_text(stmt, 10, hash1, -1, NULL);
1116 if (r) {
1117 ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle));
1118 goto ROLLBACK;
1119 }
1120
1121 // Bind license
1122 const char* license = pakfire_package_get_license(pkg);
1123
1124 r = sqlite3_bind_text(stmt, 11, license, -1, NULL);
1125 if (r) {
1126 ERROR(db->pakfire, "Could not bind license: %s\n", sqlite3_errmsg(db->handle));
1127 goto ROLLBACK;
1128 }
1129
1130 // Bind summary
1131 const char* summary = pakfire_package_get_summary(pkg);
1132
1133 r = sqlite3_bind_text(stmt, 12, summary, -1, NULL);
1134 if (r) {
1135 ERROR(db->pakfire, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle));
1136 goto ROLLBACK;
1137 }
1138
1139 // Bind description
1140 const char* description = pakfire_package_get_description(pkg);
1141
1142 r = sqlite3_bind_text(stmt, 13, description, -1, NULL);
1143 if (r) {
1144 ERROR(db->pakfire, "Could not bind description: %s\n", sqlite3_errmsg(db->handle));
1145 goto ROLLBACK;
1146 }
1147
1148 // Bind uuid
1149 const char* uuid = pakfire_package_get_uuid(pkg);
1150
1151 r = sqlite3_bind_text(stmt, 14, uuid, -1, NULL);
1152 if (r) {
1153 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
1154 goto ROLLBACK;
1155 }
1156
1157 // Bind vendor
1158 const char* vendor = pakfire_package_get_vendor(pkg);
1159
8f3b8280 1160 r = sqlite3_bind_text(stmt, 15, vendor, -1, NULL);
e49b93d1
MT
1161 if (r) {
1162 ERROR(db->pakfire, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle));
1163 goto ROLLBACK;
1164 }
1165
e49b93d1 1166 // Bind build_host
2ffc704d 1167 const char* build_host = pakfire_package_get_build_host(pkg);
e49b93d1 1168
2ffc704d 1169 r = sqlite3_bind_text(stmt, 16, build_host, -1, NULL);
e49b93d1
MT
1170 if (r) {
1171 ERROR(db->pakfire, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle));
1172 goto ROLLBACK;
1173 }
1174
1175 // Bind build_time
2ffc704d 1176 time_t build_time = pakfire_package_get_build_time(pkg);
e49b93d1
MT
1177
1178 r = sqlite3_bind_int64(stmt, 17, build_time);
1179 if (r) {
1180 ERROR(db->pakfire, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle));
1181 goto ROLLBACK;
1182 }
1183
1184 // Bind repository name
1185 PakfireRepo repo = pakfire_package_get_repo(pkg);
1186 if (repo) {
1187 const char* repo_name = pakfire_repo_get_name(repo);
1188 pakfire_repo_unref(repo);
1189
1190 r = sqlite3_bind_text(stmt, 18, repo_name, -1, NULL);
1191 if (r)
1192 goto ROLLBACK;
1193
1194 // No repository?
1195 } else {
1196 r = sqlite3_bind_null(stmt, 18);
1197 if (r)
1198 goto ROLLBACK;
1199 }
1200
1201 // XXX TODO Bind reason
1202 r = sqlite3_bind_null(stmt, 19);
1203 if (r)
1204 goto ROLLBACK;
1205
1206 // Run query
1207 do {
1208 r = sqlite3_step(stmt);
1209 } while (r == SQLITE_BUSY);
1210
1211 if (r != SQLITE_DONE) {
1212 ERROR(db->pakfire, "Could not add package to database: %s\n",
1213 sqlite3_errmsg(db->handle));
1214 goto ROLLBACK;
1215 }
1216
f5c77233
MT
1217 // Save package ID
1218 unsigned long packages_id = sqlite3_last_insert_rowid(db->handle);
1219
e49b93d1 1220 // This is done
f5c77233
MT
1221 r = sqlite3_finalize(stmt);
1222 if (r == SQLITE_OK)
1223 stmt = NULL;
1224
1fb2b526
MT
1225 // Add dependencies
1226 r = pakfire_db_add_dependencies(db, packages_id, pkg);
1227 if (r)
1228 goto ROLLBACK;
1229
f5c77233
MT
1230 // Add files
1231 r = pakfire_db_add_files(db, packages_id, archive);
1232 if (r)
1233 goto ROLLBACK;
e49b93d1 1234
265f539a
MT
1235 // Add scriptlets
1236 r = pakfire_db_add_scriptlets(db, packages_id, archive);
1237 if (r)
1238 goto ROLLBACK;
1239
e49b93d1
MT
1240 // All done, commit!
1241 r = pakfire_db_commit(db);
1242 if (r)
1243 goto ROLLBACK;
1244
1245 return 0;
1246
1247ROLLBACK:
f5c77233
MT
1248 if (stmt)
1249 sqlite3_finalize(stmt);
e49b93d1
MT
1250
1251 pakfire_db_rollback(db);
1252
1253 return 1;
eafbe2ce
MT
1254}
1255
18bf891d 1256PAKFIRE_EXPORT int pakfire_db_remove_package(struct pakfire_db* db, PakfirePackage pkg) {
432a328a
MT
1257 sqlite3_stmt* stmt = NULL;
1258 int r = 1;
1259
1260 // Fetch the package's UUID
1261 const char* uuid = pakfire_package_get_uuid(pkg);
1262 if (!uuid) {
1263 ERROR(db->pakfire, "Package has no UUID\n");
1264 goto ERROR;
1265 }
1266
1267 r = sqlite3_prepare_v2(db->handle,
1268 "DELETE FROM packages WHERE uuid = ?", -1, &stmt, NULL);
1269 if (r) {
1270 ERROR(db->pakfire, "Could not prepare SQL statement: %s\n",
1271 sqlite3_errmsg(db->handle));
1272 goto ERROR;
1273 }
1274
1275 // Bind UUID
1276 r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
1277 if (r) {
1278 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
1279 return 1;
1280 }
1281
1282 // Execute query
1283 do {
1284 r = sqlite3_step(stmt);
1285 } while (r == SQLITE_BUSY);
1286
1287 // Check if we have been successful
1288 if (r != SQLITE_DONE) {
1289 ERROR(db->pakfire, "Could not delete package %s\n", uuid);
1290 r = 1;
1291 goto ERROR;
1292 }
1293
1294 r = 0;
1295
1296ERROR:
1297 if (stmt)
1298 sqlite3_finalize(stmt);
1299
1300 return r;
eafbe2ce 1301}
f6942b34
MT
1302
1303struct pakfire_scriptlet* pakfire_db_get_scriptlet(struct pakfire_db* db,
1304 PakfirePackage pkg, pakfire_scriptlet_type type) {
1305 struct pakfire_scriptlet* scriptlet = NULL;
1306 sqlite3_stmt* stmt = NULL;
1307 int r = 1;
1308
1309 // Fetch the package's UUID
1310 const char* uuid = pakfire_package_get_uuid(pkg);
1311 if (!uuid) {
1312 ERROR(db->pakfire, "Package has no UUID\n");
1313 goto ERROR;
1314 }
1315
1316 const char* sql = "SELECT scriptlet.scriptlet FROM packages \
1317 JOIN scriptlets ON packages.id = scriptlets.pkg \
1318 WHERE packages.uuid = ? AND scriptlets.type = ?";
1319
1320 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1321 if (r) {
1322 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
1323 sql, sqlite3_errmsg(db->handle));
1324 goto ERROR;
1325 }
1326
1327 // Bind UUID
1328 r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
1329 if (r) {
1330 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
1331 goto ERROR;
1332 }
1333
1334 // Bind type
1335 const char* handle = pakfire_scriptlet_handle_from_type(type);
1336 if (!handle)
1337 goto ERROR;
1338
1339 r = sqlite3_bind_text(stmt, 2, handle, -1, NULL);
1340 if (r) {
1341 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
1342 goto ERROR;
1343 }
1344
1345 DEBUG(db->pakfire, "Searching for scriptlet for package %s of type %s\n", uuid, handle);
1346
1347 // Execute query
1348 do {
1349 r = sqlite3_step(stmt);
1350 } while (r == SQLITE_BUSY);
1351
1352 // We have some payload
1353 if (r == SQLITE_ROW) {
1354 const void* data = sqlite3_column_blob(stmt, 1);
1355 ssize_t size = sqlite3_column_bytes(stmt, 1);
1356
1357 // Create a scriptlet object
1358 scriptlet = pakfire_scriptlet_create(db->pakfire, data, size);
1359 if (!scriptlet)
1360 goto ERROR;
1361 }
1362
1363ERROR:
1364 if (stmt)
1365 sqlite3_finalize(stmt);
1366
1367 return scriptlet;
1368}
361ca45f
MT
1369
1370static int pakfire_db_load_package(struct pakfire_db* db, PakfireRepo repo, sqlite3_stmt* stmt) {
1371 PakfirePackage pkg = NULL;
1372 char* evr = NULL;
1373 int r = 1;
1374
1375 // Name
1376 const char* name = (const char*)sqlite3_column_text(stmt, 0);
1377 if (!name) {
1378 ERROR(db->pakfire, "Could not read name: %s\n", sqlite3_errmsg(db->handle));
1379 goto ERROR;
1380 }
1381
1382 // Epoch (INTEGER but cast as string)
1383 const char* epoch = (const char*)sqlite3_column_text(stmt, 1);
1384 if (!epoch) {
1385 ERROR(db->pakfire, "Could not read epoch: %s\n", sqlite3_errmsg(db->handle));
1386 goto ERROR;
1387 }
1388
1389 // Version
1390 const char* version = (const char*)sqlite3_column_text(stmt, 2);
1391 if (!version) {
1392 ERROR(db->pakfire, "Could not read version: %s\n", sqlite3_errmsg(db->handle));
1393 goto ERROR;
1394 }
1395
1396 // Release
1397 const char* release = (const char*)sqlite3_column_text(stmt, 3);
1398 if (!release) {
1399 ERROR(db->pakfire, "Could not read release: %s\n", sqlite3_errmsg(db->handle));
1400 goto ERROR;
1401 }
1402
1403 // Arch
1404 const char* arch = (const char*)sqlite3_column_text(stmt, 4);
1405 if (!arch) {
1406 ERROR(db->pakfire, "Could not read arch: %s\n", sqlite3_errmsg(db->handle));
1407 goto ERROR;
1408 }
1409
1410 // Join EVR together
1411 evr = pakfire_package_join_evr(epoch, version, release);
1412 if (!evr) {
1413 ERROR(db->pakfire, "Could not join evr\n");
1414 goto ERROR;
1415 }
1416
1417 // Create package
f71cc0c7 1418 pkg = pakfire_package_create(db->pakfire, repo, name, evr, arch);
361ca45f
MT
1419 if (!pkg) {
1420 ERROR(db->pakfire, "Could not create package\n");
1421 goto ERROR;
1422 }
1423
7f826034
MT
1424 // Groups
1425 const char* groups = (const char*)sqlite3_column_text(stmt, 5);
1426 if (groups) {
1427 pakfire_package_set_groups(pkg, groups);
1428 }
1429
1430 // Filename
1431 const char* filename = (const char*)sqlite3_column_text(stmt, 6);
1432 if (filename) {
1433 pakfire_package_set_filename(pkg, filename);
1434 }
1435
1436 // Size
1437 size_t size = sqlite3_column_int64(stmt, 7);
1438 if (size) {
1439 pakfire_package_set_downloadsize(pkg, size);
1440 }
1441
1442 // Installed size
1443 size = sqlite3_column_int64(stmt, 8);
1444 if (size) {
1445 pakfire_package_set_installsize(pkg, size);
1446 }
1447
1448 // Hash 1
1449 const char* hash1 = (const char*)sqlite3_column_text(stmt, 9);
1450 if (hash1) {
1451 pakfire_package_set_checksum(pkg, hash1);
1452 }
1453
1454 // License
1455 const char* license = (const char*)sqlite3_column_text(stmt, 10);
1456 if (license) {
1457 pakfire_package_set_license(pkg, license);
1458 }
1459
1460 // Summary
1461 const char* summary = (const char*)sqlite3_column_text(stmt, 11);
1462 if (summary) {
1463 pakfire_package_set_summary(pkg, summary);
1464 }
1465
1466 // Description
1467 const char* description = (const char*)sqlite3_column_text(stmt, 12);
1468 if (description) {
1469 pakfire_package_set_description(pkg, description);
1470 }
1471
1472 // UUID
1473 const char* uuid = (const char*)sqlite3_column_text(stmt, 13);
1474 if (uuid) {
1475 pakfire_package_set_uuid(pkg, uuid);
1476 }
1477
1478 // Vendor
1479 const char* vendor = (const char*)sqlite3_column_text(stmt, 14);
1480 if (vendor) {
1481 pakfire_package_set_vendor(pkg, vendor);
1482 }
1483
1484 // Build Host
1485 const char* build_host = (const char*)sqlite3_column_text(stmt, 15);
1486 if (build_host) {
2ffc704d 1487 pakfire_package_set_build_host(pkg, build_host);
7f826034
MT
1488 }
1489
1490 // Build Time
1491 time_t build_time = sqlite3_column_int64(stmt, 16);
1492 if (build_time) {
2ffc704d 1493 pakfire_package_set_build_time(pkg, build_time);
7f826034
MT
1494 }
1495
af647c55
MT
1496 // Install Time
1497 time_t install_time = sqlite3_column_int64(stmt, 17);
1498 if (install_time) {
1499 pakfire_package_set_install_time(pkg, install_time);
1500 }
1501
d995f7fc 1502 // Files
af647c55 1503 const char* files = (const char*)sqlite3_column_text(stmt, 18);
d995f7fc 1504 if (files) {
d995f7fc
MT
1505 r = pakfire_package_set_filelist_from_string(pkg, files);
1506 if (r)
1507 goto ERROR;
1508 }
1509
24be412a
MT
1510 // Dependencies
1511
1512 const struct dependency {
1513 unsigned int field;
1514 void (*func)(PakfirePackage pkg, PakfireRelationList list);
1515 } dependencies[] = {
af647c55
MT
1516 { 19, pakfire_package_set_provides },
1517 { 20, pakfire_package_set_prerequires },
1518 { 21, pakfire_package_set_requires },
1519 { 22, pakfire_package_set_conflicts },
1520 { 23, pakfire_package_set_obsoletes },
1521 { 24, pakfire_package_set_recommends },
1522 { 25, pakfire_package_set_suggests },
1523 { 26, pakfire_package_set_supplements },
1524 { 27, pakfire_package_set_enhances },
24be412a
MT
1525 { 0, NULL },
1526 };
1527
1528 for (const struct dependency* deps = dependencies; deps->field; deps++) {
1529 const char* relations = (const char*)sqlite3_column_text(stmt, deps->field);
1530 if (relations) {
1531 PakfireRelationList list;
1532
1533 r = pakfire_relationlist_create_from_string(&list, db->pakfire, relations);
1534 if (r)
1535 goto ERROR;
1536
1537 deps->func(pkg, list);
1538 pakfire_relationlist_unref(list);
1539 }
1540 }
1541
361ca45f
MT
1542 // Success
1543 r = 0;
1544
1545ERROR:
1546 if (evr)
1547 free(evr);
1548
1549 if (pkg)
1550 pakfire_package_unref(pkg);
1551
1552 return r;
1553}
1554
1555int pakfire_db_load(struct pakfire_db* db, PakfireRepo repo) {
1556 sqlite3_stmt* stmt = NULL;
1557 int r = 1;
1558
1559 DEBUG(db->pakfire, "Loading package database...\n");
1560
788221bd
MT
1561 // Save starting time
1562 clock_t t_start = clock();
1563 clock_t t_end;
1564
361ca45f
MT
1565 const char* sql =
1566 "SELECT "
7f826034 1567 "name, epoch, version, release, arch, groups, filename, size, inst_size, "
d995f7fc 1568 "hash1, license, summary, description, uuid, vendor, build_host, build_time, "
af647c55 1569 "strftime('%s', installed) AS installed, "
d995f7fc
MT
1570 "("
1571 "SELECT group_concat(name, '\n') FROM files WHERE files.pkg = packages.id"
24be412a
MT
1572 ") AS files, "
1573 "("
1574 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1575 "WHERE d.pkg = packages.id AND d.type = 'provides'"
1576 ") AS provides, "
1577 "("
1578 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1579 "WHERE d.pkg = packages.id AND d.type = 'prerequires'"
1580 ") AS prerequires, "
1581 "("
1582 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1583 "WHERE d.pkg = packages.id AND d.type = 'requires'"
1584 ") AS requires, "
1585 "("
1586 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1587 "WHERE d.pkg = packages.id AND d.type = 'conflicts'"
1588 ") AS conflicts, "
1589 "("
1590 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1591 "WHERE d.pkg = packages.id AND d.type = 'obsoletes'"
1592 ") AS obsoletes, "
1593 "("
1594 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1595 "WHERE d.pkg = packages.id AND d.type = 'recommends'"
1596 ") AS recommends, "
1597 "("
1598 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1599 "WHERE d.pkg = packages.id AND d.type = 'suggests'"
8fe2e4ba
MT
1600 ") AS suggests, "
1601 "("
1602 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1603 "WHERE d.pkg = packages.id AND d.type = 'supplements'"
1604 ") AS supplements, "
1605 "("
1606 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1607 "WHERE d.pkg = packages.id AND d.type = 'enhances'"
1608 ") AS enhances "
361ca45f
MT
1609 "FROM "
1610 "packages"
1611 ";";
1612
1613 // Prepare the statement
1614 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1615 if (r) {
1616 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
1617 sql, sqlite3_errmsg(db->handle));
1618 goto ERROR;
1619 }
1620
1621 for (;;) {
1622 // Execute query
1623 r = sqlite3_step(stmt);
1624
1625 switch (r) {
1626 // Retry if the database was busy
1627 case SQLITE_BUSY:
1628 continue;
1629
1630 // Read a row
1631 case SQLITE_ROW:
1632 r = pakfire_db_load_package(db, repo, stmt);
1633 if (r)
1634 goto ERROR;
1635 break;
1636
1637 // All rows have been processed
1638 case SQLITE_DONE:
1639 goto END;
1640
1641 // Go to error in any other cases
1642 default:
1643 goto ERROR;
1644 }
1645 }
1646
1647END:
788221bd
MT
1648 // Save time when we finished
1649 t_end = clock();
1650
1651 DEBUG(db->pakfire, "Loading package database completed in %.4fms\n",
1652 (double)(t_end - t_start) * 1000 / CLOCKS_PER_SEC);
361ca45f 1653
05336f5e
MT
1654 // Internalize repository
1655 pakfire_repo_internalize(repo);
1656
361ca45f
MT
1657 // All done
1658 r = 0;
1659
1660ERROR:
1661 if (r)
1662 ERROR(db->pakfire, "Failed reading package database: %d\n", r);
1663
1664 if (stmt)
1665 sqlite3_finalize(stmt);
1666
1667 return r;
1668}