]>
Commit | Line | Data |
---|---|---|
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 | ||
33d55ab4 | 26 | #include <pakfire/db.h> |
33d55ab4 | 27 | #include <pakfire/logging.h> |
e49b93d1 | 28 | #include <pakfire/package.h> |
18bf891d MT |
29 | #include <pakfire/pakfire.h> |
30 | #include <pakfire/private.h> | |
e49b93d1 | 31 | #include <pakfire/repo.h> |
33d55ab4 MT |
32 | #include <pakfire/types.h> |
33 | #include <pakfire/util.h> | |
34 | ||
0cb487ff MT |
35 | #define DATABASE_PATH PAKFIRE_PRIVATE_DIR "/packages.db" |
36 | ||
c745fb2d MT |
37 | #define CURRENT_SCHEMA 7 |
38 | #define SCHEMA_MIN_SUP 7 | |
39 | ||
33d55ab4 MT |
40 | struct pakfire_db { |
41 | Pakfire pakfire; | |
42 | int nrefs; | |
77a4b3a3 MT |
43 | |
44 | int mode; | |
26affd69 MT |
45 | |
46 | sqlite3* handle; | |
c745fb2d | 47 | int schema; |
33d55ab4 MT |
48 | }; |
49 | ||
9c5938ea MT |
50 | static void logging_callback(void* data, int r, const char* msg) { |
51 | Pakfire pakfire = (Pakfire)data; | |
52 | ||
53 | ERROR(pakfire, "Database Error: %s: %s\n", | |
54 | sqlite3_errstr(r), msg); | |
55 | } | |
56 | ||
0076c50d MT |
57 | static int pakfire_db_execute(struct pakfire_db* db, const char* stmt) { |
58 | int r; | |
c745fb2d MT |
59 | |
60 | DEBUG(db->pakfire, "Executing database query: %s\n", stmt); | |
0076c50d MT |
61 | |
62 | do { | |
c745fb2d | 63 | r = sqlite3_exec(db->handle, stmt, NULL, NULL, NULL); |
0076c50d MT |
64 | } while (r == SQLITE_BUSY); |
65 | ||
c745fb2d MT |
66 | // Log any errors |
67 | if (r) { | |
68 | ERROR(db->pakfire, "Database query failed: %s\n", sqlite3_errmsg(db->handle)); | |
69 | } | |
70 | ||
25753290 MT |
71 | return r; |
72 | } | |
73 | ||
c745fb2d MT |
74 | static int pakfire_db_begin_transaction(struct pakfire_db* db) { |
75 | return pakfire_db_execute(db, "BEGIN TRANSACTION"); | |
76 | } | |
77 | ||
78 | static int pakfire_db_commit(struct pakfire_db* db) { | |
79 | return pakfire_db_execute(db, "COMMIT"); | |
80 | } | |
81 | ||
82 | static int pakfire_db_rollback(struct pakfire_db* db) { | |
83 | return pakfire_db_execute(db, "ROLLBACK"); | |
84 | } | |
85 | ||
25753290 MT |
86 | /* |
87 | This function performs any fast optimization and tries to truncate the WAL log file | |
88 | to keep the database as compact as possible on disk. | |
89 | */ | |
90 | static void pakfire_db_optimize(struct pakfire_db* db) { | |
91 | pakfire_db_execute(db, "PRAGMA optmize"); | |
92 | pakfire_db_execute(db, "PRAGMA wal_checkpoint = TRUNCATE"); | |
0076c50d MT |
93 | } |
94 | ||
26affd69 MT |
95 | static void pakfire_db_free(struct pakfire_db* db) { |
96 | DEBUG(db->pakfire, "Releasing database at %p\n", db); | |
97 | ||
26affd69 | 98 | if (db->handle) { |
25753290 MT |
99 | // Optimize the database before it is being closed |
100 | pakfire_db_optimize(db); | |
101 | ||
102 | // Close database handle | |
26affd69 MT |
103 | int r = sqlite3_close(db->handle); |
104 | if (r != SQLITE_OK) { | |
105 | ERROR(db->pakfire, "Could not close database handle: %s\n", | |
106 | sqlite3_errmsg(db->handle)); | |
107 | } | |
108 | } | |
109 | ||
110 | pakfire_unref(db->pakfire); | |
111 | ||
112 | pakfire_free(db); | |
113 | } | |
114 | ||
c745fb2d MT |
115 | static sqlite3_value* pakfire_db_get(struct pakfire_db* db, const char* key) { |
116 | sqlite3_stmt* stmt = NULL; | |
117 | sqlite3_value* val = NULL; | |
118 | int r; | |
119 | ||
120 | const char* sql = "SELECT val FROM settings WHERE key = ?"; | |
121 | ||
122 | // Prepare the statement | |
123 | r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL); | |
124 | if (r != SQLITE_OK) { | |
125 | //ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n", | |
126 | // sql, sqlite3_errmsg(db->handle)); | |
127 | return NULL; | |
128 | } | |
129 | ||
130 | // Bind key | |
131 | r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL); | |
132 | if (r != SQLITE_OK) { | |
133 | ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle)); | |
134 | goto ERROR; | |
135 | } | |
136 | ||
137 | // Execute the statement | |
138 | do { | |
139 | r = sqlite3_step(stmt); | |
140 | } while (r == SQLITE_BUSY); | |
141 | ||
142 | // Read value | |
143 | val = sqlite3_column_value(stmt, 1); | |
144 | if (!val) { | |
145 | ERROR(db->pakfire, "Could not read value\n"); | |
146 | goto ERROR; | |
147 | } | |
148 | ||
149 | // Copy value onto the heap | |
150 | val = sqlite3_value_dup(val); | |
151 | ||
152 | ERROR: | |
153 | if (stmt) | |
154 | sqlite3_finalize(stmt); | |
155 | ||
156 | return val; | |
157 | } | |
158 | ||
159 | static int pakfire_db_set_int(struct pakfire_db* db, const char* key, int val) { | |
160 | sqlite3_stmt* stmt = NULL; | |
161 | int r; | |
162 | ||
163 | const char* sql = "INSERT INTO settings(key, val) VALUES(?, ?) \ | |
164 | ON CONFLICT (key) DO UPDATE SET val = excluded.val"; | |
165 | ||
166 | // Prepare statement | |
167 | r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL); | |
168 | if (r != SQLITE_OK) { | |
169 | ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n", | |
170 | sql, sqlite3_errmsg(db->handle)); | |
171 | return 1; | |
172 | } | |
173 | ||
174 | // Bind key | |
175 | r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL); | |
176 | if (r != SQLITE_OK) { | |
177 | ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle)); | |
178 | goto ERROR; | |
179 | } | |
180 | ||
181 | // Bind val | |
182 | r = sqlite3_bind_int64(stmt, 2, val); | |
183 | if (r != SQLITE_OK) { | |
184 | ERROR(db->pakfire, "Could not bind val: %s\n", sqlite3_errmsg(db->handle)); | |
185 | goto ERROR; | |
186 | } | |
187 | ||
188 | // Execute the statement | |
189 | do { | |
190 | r = sqlite3_step(stmt); | |
191 | } while (r == SQLITE_BUSY); | |
192 | ||
193 | // Set return code | |
194 | r = (r == SQLITE_OK); | |
195 | ||
196 | ERROR: | |
197 | if (stmt) | |
198 | sqlite3_finalize(stmt); | |
199 | ||
200 | return r; | |
201 | } | |
202 | ||
203 | static int pakfire_db_get_schema(struct pakfire_db* db) { | |
204 | sqlite3_value* value = pakfire_db_get(db, "schema"); | |
205 | if (!value) | |
206 | return 0; | |
207 | ||
208 | int schema = sqlite3_value_int64(value); | |
209 | sqlite3_value_free(value); | |
210 | ||
211 | DEBUG(db->pakfire, "Database has schema version %d\n", schema); | |
212 | ||
213 | return schema; | |
214 | } | |
215 | ||
216 | static int pakfire_db_create_schema(struct pakfire_db* db) { | |
217 | int r; | |
218 | ||
219 | // Create settings table | |
220 | r = pakfire_db_execute(db, "CREATE TABLE IF NOT EXISTS settings(key TEXT, val TEXT)"); | |
221 | if (r) | |
222 | return 1; | |
223 | ||
224 | // settings: Add a unique index on key | |
225 | r = pakfire_db_execute(db, "CREATE UNIQUE INDEX IF NOT EXISTS settings_key ON settings(key)"); | |
226 | if (r) | |
227 | return 1; | |
228 | ||
704b3993 MT |
229 | // Create packages table |
230 | r = pakfire_db_execute(db, | |
231 | "CREATE TABLE IF NOT EXISTS packages(" | |
232 | "id INTEGER PRIMARY KEY, " | |
233 | "name TEXT, " | |
234 | "epoch INTEGER, " | |
235 | "version TEXT, " | |
236 | "release TEXT, " | |
237 | "arch TEXT, " | |
238 | "groups TEXT, " | |
239 | "filename TEXT, " | |
240 | "size INTEGER, " | |
241 | "inst_size INTEGER, " | |
242 | "hash1 TEXT, " | |
243 | "license TEXT, " | |
244 | "summary TEXT, " | |
245 | "description TEXT, " | |
246 | "uuid TEXT, " | |
247 | "vendor TEXT, " | |
248 | "build_id TEXT, " | |
249 | "build_host TEXT, " | |
250 | "build_date TEXT, " | |
251 | "build_time INTEGER, " | |
252 | "installed INTEGER, " | |
253 | "reason TEXT, " | |
254 | "repository TEXT" | |
255 | ")"); | |
256 | if (r) | |
257 | return 1; | |
258 | ||
259 | // packages: Create index to find package by name | |
260 | r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS packages_name ON packages(name)"); | |
261 | if (r) | |
262 | return 1; | |
263 | ||
2359ca14 MT |
264 | // Create dependencies table |
265 | r = pakfire_db_execute(db, | |
266 | "CREATE TABLE IF NOT EXISTS dependencies(" | |
267 | "pkg INTEGER, " | |
268 | "type TEXT, " | |
46257c5f MT |
269 | "dependency TEXT, " |
270 | "FOREIGN KEY (pkg) REFERENCES packages(id)" | |
2359ca14 MT |
271 | ")"); |
272 | if (r) | |
273 | return r; | |
274 | ||
275 | // dependencies: Add index over packages | |
276 | r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS dependencies_pkg_index ON dependencies(pkg)"); | |
277 | if (r) | |
278 | return r; | |
279 | ||
68036506 MT |
280 | // Create files table |
281 | r = pakfire_db_execute(db, | |
282 | "CREATE TABLE IF NOT EXISTS files(" | |
283 | "id INTEGER PRIMARY KEY, " | |
284 | "name TEXT, " | |
285 | "pkg INTEGER, " | |
286 | "size INTEGER, " | |
287 | "type INTEGER, " | |
288 | "config INTEGER, " | |
289 | "datafile INTEGER, " | |
290 | "mode INTEGER, " | |
291 | "user TEXT, " | |
292 | "'group' TEXT, " | |
293 | "hash1 TEXT, " | |
294 | "mtime INTEGER, " | |
46257c5f MT |
295 | "capabilities TEXT, " |
296 | "FOREIGN KEY (pkg) REFERENCES packages(id)" | |
68036506 MT |
297 | ")"); |
298 | if (r) | |
299 | return 1; | |
300 | ||
301 | // files: Add index over packages | |
302 | r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS files_pkg_index ON files(pkg)"); | |
303 | if (r) | |
304 | return 1; | |
305 | ||
d83414aa MT |
306 | // Create scriptlets table |
307 | r = pakfire_db_execute(db, | |
308 | "CREATE TABLE IF NOT EXISTS scriptlets(" | |
309 | "id INTEGER PRIMARY KEY, " | |
310 | "pkg INTEGER, " | |
311 | "action TEXT, " | |
46257c5f MT |
312 | "scriptlet TEXT, " |
313 | "FOREIGN KEY (pkg) REFERENCES packages(id)" | |
d83414aa MT |
314 | ")"); |
315 | if (r) | |
316 | return 1; | |
317 | ||
318 | // scriptlets: Add index over packages | |
319 | r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS scriptlets_pkg_index ON scriptlets(pkg)"); | |
320 | if (r) | |
321 | return 1; | |
322 | ||
c745fb2d MT |
323 | return 0; |
324 | } | |
325 | ||
46257c5f MT |
326 | static int pakfire_db_migrate_to_schema_8(struct pakfire_db* db) { |
327 | // Add foreign keys | |
328 | // TODO sqlite doesn't support adding foreign keys to existing tables and so we would | |
329 | // need to recreate the whole table and rename it afterwards. Annoying. | |
330 | ||
331 | return 0; | |
332 | } | |
333 | ||
c745fb2d MT |
334 | static int pakfire_db_migrate_schema(struct pakfire_db* db) { |
335 | int r; | |
336 | ||
337 | while (db->schema < CURRENT_SCHEMA) { | |
338 | // Begin a new transaction | |
339 | r = pakfire_db_begin_transaction(db); | |
340 | if (r) | |
341 | goto ROLLBACK; | |
342 | ||
343 | switch (db->schema) { | |
344 | // No schema exists | |
345 | case 0: | |
346 | r = pakfire_db_create_schema(db); | |
347 | if (r) | |
348 | goto ROLLBACK; | |
349 | ||
350 | db->schema = CURRENT_SCHEMA; | |
351 | break; | |
352 | ||
46257c5f MT |
353 | case 7: |
354 | r = pakfire_db_migrate_to_schema_8(db); | |
355 | if (r) | |
356 | goto ROLLBACK; | |
357 | ||
358 | db->schema++; | |
359 | break; | |
360 | ||
c745fb2d MT |
361 | default: |
362 | ERROR(db->pakfire, "Cannot migrate database from schema %d\n", db->schema); | |
363 | goto ROLLBACK; | |
364 | } | |
365 | ||
366 | // Update the schema version | |
367 | r = pakfire_db_set_int(db, "schema", CURRENT_SCHEMA); | |
368 | if (r) | |
369 | goto ROLLBACK; | |
370 | ||
371 | // All done, commit! | |
372 | r = pakfire_db_commit(db); | |
373 | if (r) | |
374 | goto ROLLBACK; | |
375 | } | |
376 | ||
377 | return 0; | |
378 | ||
379 | ROLLBACK: | |
380 | pakfire_db_rollback(db); | |
381 | ||
382 | return 1; | |
383 | } | |
384 | ||
9c5938ea | 385 | static int pakfire_db_setup(struct pakfire_db* db) { |
25753290 MT |
386 | int r; |
387 | ||
9c5938ea MT |
388 | // Setup logging |
389 | sqlite3_config(SQLITE_CONFIG_LOG, logging_callback, db->pakfire); | |
390 | ||
46257c5f MT |
391 | // Enable foreign keys |
392 | pakfire_db_execute(db, "PRAGMA foreign_keys = ON"); | |
393 | ||
0076c50d MT |
394 | // Make LIKE case-sensitive |
395 | pakfire_db_execute(db, "PRAGMA case_sensitive_like = ON"); | |
396 | ||
c745fb2d MT |
397 | // Fetch the current schema |
398 | db->schema = pakfire_db_get_schema(db); | |
399 | ||
400 | // Check if the schema is recent enough | |
401 | if (db->schema > 0 && db->schema < SCHEMA_MIN_SUP) { | |
402 | ERROR(db->pakfire, "Database schema %d is not supported by this version of Pakfire\n", | |
403 | db->schema); | |
404 | return 1; | |
405 | } | |
406 | ||
9c5938ea MT |
407 | // Done when not in read-write mode |
408 | if (db->mode != PAKFIRE_DB_READWRITE) | |
409 | return 0; | |
410 | ||
0076c50d MT |
411 | // Disable secure delete |
412 | pakfire_db_execute(db, "PRAGMA secure_delete = OFF"); | |
413 | ||
25753290 MT |
414 | // Set database journal to WAL |
415 | r = pakfire_db_execute(db, "PRAGMA journal_mode = WAL"); | |
416 | if (r != SQLITE_OK) { | |
417 | ERROR(db->pakfire, "Could not set journal mode to WAL: %s\n", | |
418 | sqlite3_errmsg(db->handle)); | |
419 | return 1; | |
420 | } | |
421 | ||
422 | // Disable autocheckpoint | |
423 | r = sqlite3_wal_autocheckpoint(db->handle, 0); | |
424 | if (r != SQLITE_OK) { | |
425 | ERROR(db->pakfire, "Could not disable autocheckpoint: %s\n", | |
426 | sqlite3_errmsg(db->handle)); | |
427 | return 1; | |
428 | } | |
429 | ||
c745fb2d MT |
430 | // Create or migrate schema |
431 | r = pakfire_db_migrate_schema(db); | |
432 | if (r) | |
433 | return r; | |
9c5938ea MT |
434 | |
435 | return 0; | |
436 | } | |
437 | ||
77a4b3a3 | 438 | PAKFIRE_EXPORT int pakfire_db_open(struct pakfire_db** db, Pakfire pakfire, int flags) { |
26affd69 MT |
439 | int r = 1; |
440 | ||
33d55ab4 MT |
441 | struct pakfire_db* o = pakfire_calloc(1, sizeof(*o)); |
442 | if (!o) | |
443 | return -ENOMEM; | |
444 | ||
445 | DEBUG(pakfire, "Allocated database at %p\n", o); | |
446 | ||
447 | o->pakfire = pakfire_ref(pakfire); | |
448 | o->nrefs = 1; | |
449 | ||
26affd69 MT |
450 | int sqlite3_flags = 0; |
451 | ||
452 | // Store mode & forward it to sqlite3 | |
453 | if (flags & PAKFIRE_DB_READWRITE) { | |
77a4b3a3 | 454 | o->mode = PAKFIRE_DB_READWRITE; |
26affd69 MT |
455 | sqlite3_flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; |
456 | } else { | |
77a4b3a3 | 457 | o->mode = PAKFIRE_DB_READONLY; |
26affd69 MT |
458 | sqlite3_flags |= SQLITE_OPEN_READONLY; |
459 | } | |
460 | ||
461 | // Make the filename | |
462 | char* path = pakfire_make_path(o->pakfire, DATABASE_PATH); | |
463 | if (!path) | |
464 | goto END; | |
465 | ||
466 | // Try to open the sqlite3 database file | |
467 | r = sqlite3_open_v2(path, &o->handle, sqlite3_flags, NULL); | |
468 | if (r != SQLITE_OK) { | |
469 | ERROR(pakfire, "Could not open database %s: %s\n", | |
470 | path, sqlite3_errmsg(o->handle)); | |
471 | ||
472 | r = 1; | |
473 | goto END; | |
474 | } | |
77a4b3a3 | 475 | |
9c5938ea MT |
476 | // Setup the database |
477 | r = pakfire_db_setup(o); | |
478 | if (r) | |
479 | goto END; | |
480 | ||
33d55ab4 | 481 | *db = o; |
26affd69 MT |
482 | r = 0; |
483 | ||
484 | END: | |
485 | if (r) | |
486 | pakfire_db_free(o); | |
33d55ab4 | 487 | |
26affd69 MT |
488 | if (path) |
489 | free(path); | |
490 | ||
491 | return r; | |
33d55ab4 MT |
492 | } |
493 | ||
18bf891d | 494 | PAKFIRE_EXPORT struct pakfire_db* pakfire_db_ref(struct pakfire_db* db) { |
33d55ab4 MT |
495 | db->nrefs++; |
496 | ||
497 | return db; | |
498 | } | |
499 | ||
18bf891d | 500 | PAKFIRE_EXPORT struct pakfire_db* pakfire_db_unref(struct pakfire_db* db) { |
33d55ab4 MT |
501 | if (--db->nrefs > 0) |
502 | return db; | |
503 | ||
504 | pakfire_db_free(db); | |
505 | ||
506 | return NULL; | |
507 | } | |
eafbe2ce | 508 | |
18bf891d | 509 | PAKFIRE_EXPORT int pakfire_db_add_package(struct pakfire_db* db, PakfirePackage pkg) { |
e49b93d1 MT |
510 | sqlite3_stmt* stmt = NULL; |
511 | int r; | |
512 | ||
513 | // Begin a new transaction | |
514 | r = pakfire_db_begin_transaction(db); | |
515 | if (r) | |
516 | goto ROLLBACK; | |
517 | ||
518 | const char* sql = "INSERT INTO packages(name, epoch, version, release, arch, groups, " | |
519 | "filename, size, inst_size, hash1, license, summary, description, uuid, vendor, " | |
520 | "build_id, build_host, build_time, installed, repository, reason) VALUES(?, ?, " | |
521 | "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)"; | |
522 | ||
523 | // Prepare the statement | |
524 | r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL); | |
525 | if (r != SQLITE_OK) { | |
526 | ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n", | |
527 | sql, sqlite3_errmsg(db->handle)); | |
528 | goto ROLLBACK; | |
529 | } | |
530 | ||
531 | // Bind name | |
532 | const char* name = pakfire_package_get_name(pkg); | |
533 | ||
534 | r = sqlite3_bind_text(stmt, 1, name, -1, NULL); | |
535 | if (r) { | |
536 | ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle)); | |
537 | goto ROLLBACK; | |
538 | } | |
539 | ||
540 | // Bind epoch | |
541 | unsigned long epoch = pakfire_package_get_epoch(pkg); | |
542 | ||
543 | r = sqlite3_bind_int64(stmt, 2, epoch); | |
544 | if (r) { | |
545 | ERROR(db->pakfire, "Could not bind epoch: %s\n", sqlite3_errmsg(db->handle)); | |
546 | goto ROLLBACK; | |
547 | } | |
548 | ||
549 | // Bind version | |
550 | const char* version = pakfire_package_get_version(pkg); | |
551 | ||
552 | r = sqlite3_bind_text(stmt, 3, version, -1, NULL); | |
553 | if (r) { | |
554 | ERROR(db->pakfire, "Could not bind version: %s\n", sqlite3_errmsg(db->handle)); | |
555 | goto ROLLBACK; | |
556 | } | |
557 | ||
558 | // Bind release | |
559 | const char* release = pakfire_package_get_release(pkg); | |
560 | ||
561 | r = sqlite3_bind_text(stmt, 4, release, -1, NULL); | |
562 | if (r) { | |
563 | ERROR(db->pakfire, "Could not bind release: %s\n", sqlite3_errmsg(db->handle)); | |
564 | goto ROLLBACK; | |
565 | } | |
566 | ||
567 | // Bind arch | |
568 | const char* arch = pakfire_package_get_arch(pkg); | |
569 | ||
570 | r = sqlite3_bind_text(stmt, 5, arch, -1, NULL); | |
571 | if (r) { | |
572 | ERROR(db->pakfire, "Could not bind arch: %s\n", sqlite3_errmsg(db->handle)); | |
573 | goto ROLLBACK; | |
574 | } | |
575 | ||
576 | // Bind groups | |
577 | const char* groups = pakfire_package_get_groups(pkg); | |
578 | ||
579 | r = sqlite3_bind_text(stmt, 6, groups, -1, NULL); | |
580 | if (r) { | |
581 | ERROR(db->pakfire, "Could not bind groups: %s\n", sqlite3_errmsg(db->handle)); | |
582 | goto ROLLBACK; | |
583 | } | |
584 | ||
585 | // Bind filename | |
586 | const char* filename = pakfire_package_get_filename(pkg); | |
587 | ||
588 | r = sqlite3_bind_text(stmt, 7, filename, -1, NULL); | |
589 | if (r) { | |
590 | ERROR(db->pakfire, "Could not bind filename: %s\n", sqlite3_errmsg(db->handle)); | |
591 | goto ROLLBACK; | |
592 | } | |
593 | ||
594 | // Bind size | |
595 | unsigned long long size = pakfire_package_get_downloadsize(pkg); | |
596 | ||
597 | r = sqlite3_bind_int64(stmt, 8, size); | |
598 | if (r) { | |
599 | ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle)); | |
600 | goto ROLLBACK; | |
601 | } | |
602 | ||
603 | // Bind installed size | |
604 | unsigned long long inst_size = pakfire_package_get_installsize(pkg); | |
605 | ||
606 | r = sqlite3_bind_int64(stmt, 9, inst_size); | |
607 | if (r) { | |
608 | ERROR(db->pakfire, "Could not bind inst_size: %s\n", sqlite3_errmsg(db->handle)); | |
609 | goto ROLLBACK; | |
610 | } | |
611 | ||
612 | // Bind hash1 | |
613 | const char* hash1 = pakfire_package_get_checksum(pkg); | |
614 | ||
615 | r = sqlite3_bind_text(stmt, 10, hash1, -1, NULL); | |
616 | if (r) { | |
617 | ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle)); | |
618 | goto ROLLBACK; | |
619 | } | |
620 | ||
621 | // Bind license | |
622 | const char* license = pakfire_package_get_license(pkg); | |
623 | ||
624 | r = sqlite3_bind_text(stmt, 11, license, -1, NULL); | |
625 | if (r) { | |
626 | ERROR(db->pakfire, "Could not bind license: %s\n", sqlite3_errmsg(db->handle)); | |
627 | goto ROLLBACK; | |
628 | } | |
629 | ||
630 | // Bind summary | |
631 | const char* summary = pakfire_package_get_summary(pkg); | |
632 | ||
633 | r = sqlite3_bind_text(stmt, 12, summary, -1, NULL); | |
634 | if (r) { | |
635 | ERROR(db->pakfire, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle)); | |
636 | goto ROLLBACK; | |
637 | } | |
638 | ||
639 | // Bind description | |
640 | const char* description = pakfire_package_get_description(pkg); | |
641 | ||
642 | r = sqlite3_bind_text(stmt, 13, description, -1, NULL); | |
643 | if (r) { | |
644 | ERROR(db->pakfire, "Could not bind description: %s\n", sqlite3_errmsg(db->handle)); | |
645 | goto ROLLBACK; | |
646 | } | |
647 | ||
648 | // Bind uuid | |
649 | const char* uuid = pakfire_package_get_uuid(pkg); | |
650 | ||
651 | r = sqlite3_bind_text(stmt, 14, uuid, -1, NULL); | |
652 | if (r) { | |
653 | ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle)); | |
654 | goto ROLLBACK; | |
655 | } | |
656 | ||
657 | // Bind vendor | |
658 | const char* vendor = pakfire_package_get_vendor(pkg); | |
659 | ||
660 | r = sqlite3_bind_text(stmt, 14, vendor, -1, NULL); | |
661 | if (r) { | |
662 | ERROR(db->pakfire, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle)); | |
663 | goto ROLLBACK; | |
664 | } | |
665 | ||
666 | // Bind build_id | |
667 | #if 0 | |
668 | const char* build_id = pakfire_package_get_buildid(pkg); | |
669 | #else | |
670 | const char* build_id = NULL; // To be done | |
671 | #endif | |
672 | ||
673 | r = sqlite3_bind_text(stmt, 15, build_id, -1, NULL); | |
674 | if (r) { | |
675 | ERROR(db->pakfire, "Could not bind build_id: %s\n", sqlite3_errmsg(db->handle)); | |
676 | goto ROLLBACK; | |
677 | } | |
678 | ||
679 | // Bind build_host | |
680 | const char* buildhost = pakfire_package_get_buildhost(pkg); | |
681 | ||
682 | r = sqlite3_bind_text(stmt, 16, buildhost, -1, NULL); | |
683 | if (r) { | |
684 | ERROR(db->pakfire, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle)); | |
685 | goto ROLLBACK; | |
686 | } | |
687 | ||
688 | // Bind build_time | |
689 | unsigned long long build_time = pakfire_package_get_buildtime(pkg); | |
690 | ||
691 | r = sqlite3_bind_int64(stmt, 17, build_time); | |
692 | if (r) { | |
693 | ERROR(db->pakfire, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle)); | |
694 | goto ROLLBACK; | |
695 | } | |
696 | ||
697 | // Bind repository name | |
698 | PakfireRepo repo = pakfire_package_get_repo(pkg); | |
699 | if (repo) { | |
700 | const char* repo_name = pakfire_repo_get_name(repo); | |
701 | pakfire_repo_unref(repo); | |
702 | ||
703 | r = sqlite3_bind_text(stmt, 18, repo_name, -1, NULL); | |
704 | if (r) | |
705 | goto ROLLBACK; | |
706 | ||
707 | // No repository? | |
708 | } else { | |
709 | r = sqlite3_bind_null(stmt, 18); | |
710 | if (r) | |
711 | goto ROLLBACK; | |
712 | } | |
713 | ||
714 | // XXX TODO Bind reason | |
715 | r = sqlite3_bind_null(stmt, 19); | |
716 | if (r) | |
717 | goto ROLLBACK; | |
718 | ||
719 | // Run query | |
720 | do { | |
721 | r = sqlite3_step(stmt); | |
722 | } while (r == SQLITE_BUSY); | |
723 | ||
724 | if (r != SQLITE_DONE) { | |
725 | ERROR(db->pakfire, "Could not add package to database: %s\n", | |
726 | sqlite3_errmsg(db->handle)); | |
727 | goto ROLLBACK; | |
728 | } | |
729 | ||
730 | // This is done | |
731 | sqlite3_finalize(stmt); | |
732 | ||
733 | // All done, commit! | |
734 | r = pakfire_db_commit(db); | |
735 | if (r) | |
736 | goto ROLLBACK; | |
737 | ||
738 | return 0; | |
739 | ||
740 | ROLLBACK: | |
741 | sqlite3_finalize(stmt); | |
742 | ||
743 | pakfire_db_rollback(db); | |
744 | ||
745 | return 1; | |
eafbe2ce MT |
746 | } |
747 | ||
18bf891d | 748 | PAKFIRE_EXPORT int pakfire_db_remove_package(struct pakfire_db* db, PakfirePackage pkg) { |
eafbe2ce MT |
749 | return 0; // TODO |
750 | } |