]> git.ipfire.org Git - pakfire.git/commitdiff
db: Check if schema exists before reading settings
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 5 Sep 2023 15:52:23 +0000 (15:52 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 5 Sep 2023 15:57:25 +0000 (15:57 +0000)
Earlier versions of SQLite did not seem to complain, but newer versions
log an error when we are trying to access the settings table when it
does not exist, yet.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/db.c

index 6e9fb572768b5d66770f86be3b07b9a86d68dca9..97c9da440fbb49747589cac6e393ddd9db564056 100644 (file)
@@ -64,11 +64,65 @@ static void logging_callback(void* data, int r, const char* msg) {
                sqlite3_errstr(r), msg);
 }
 
+static int pakfire_db_check_table(struct pakfire_db* db, const char* table) {
+       sqlite3_stmt* stmt = NULL;
+       int r;
+
+       const char* sql = "SELECT * FROM sqlite_master WHERE type = ? AND name = ?";
+
+       // Prepare the statement
+       r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
+       if (r != SQLITE_OK) {
+               ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
+                       sql, sqlite3_errmsg(db->handle));
+               goto ERROR;
+       }
+
+       // Bind type
+       r = sqlite3_bind_text(stmt, 1, "table", -1, NULL);
+       if (r != SQLITE_OK) {
+               ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
+               goto ERROR;
+       }
+
+       // Bind name
+       r = sqlite3_bind_text(stmt, 2, table, -1, NULL);
+       if (r != SQLITE_OK) {
+               ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
+               goto ERROR;
+       }
+
+       // Execute the statement
+       do {
+               r = sqlite3_step(stmt);
+       } while (r == SQLITE_BUSY);
+
+       // We should have read a row
+       if (r != SQLITE_ROW)
+               goto ERROR;
+
+       // If we get here, the table exists.
+       r = 0;
+
+ERROR:
+       if (stmt)
+               sqlite3_finalize(stmt);
+
+       return r;
+}
+
 static sqlite3_value* pakfire_db_get(struct pakfire_db* db, const char* key) {
        sqlite3_stmt* stmt = NULL;
        sqlite3_value* val = NULL;
        int r;
 
+       // If the schema has not been initialized, yet, check if the settings table exist, at all
+       if (!db->schema) {
+               r = pakfire_db_check_table(db, "settings");
+               if (r)
+                       return NULL;
+       }
+
        const char* sql = "SELECT val FROM settings WHERE key = ?";
 
        // Prepare the statement
@@ -325,9 +379,10 @@ static void pakfire_db_free(struct pakfire_db* db) {
 }
 
 static int pakfire_db_get_schema(struct pakfire_db* db) {
+       // Fetch the schema version
        sqlite3_value* value = pakfire_db_get(db, "schema");
        if (!value)
-               return -1;
+               return 0;
 
        int schema = sqlite3_value_int64(value);
        sqlite3_value_free(value);
@@ -494,7 +549,7 @@ static int pakfire_db_migrate_schema(struct pakfire_db* db) {
 
                switch (db->schema) {
                        // No schema exists
-                       case -1:
+                       case 0:
                                r = pakfire_db_create_schema(db);
                                if (r)
                                        goto ROLLBACK;
@@ -576,7 +631,7 @@ static int pakfire_db_setup(struct pakfire_db* db) {
        db->schema = pakfire_db_get_schema(db);
 
        // Check if the schema is recent enough
-       if (db->schema > 0 && db->schema < SCHEMA_MIN_SUP) {
+       if (db->schema && db->schema < SCHEMA_MIN_SUP) {
                ERROR(db->pakfire, "Database schema %d is not supported by this version of Pakfire\n",
                        db->schema);
                return 1;