sqlite: Changed module interface - New interface is simpler.
authorTomas Mlcoch <tmlcoch@redhat.com>
Thu, 16 May 2013 10:07:22 +0000 (12:07 +0200)
committerTomas Mlcoch <tmlcoch@redhat.com>
Thu, 16 May 2013 10:08:41 +0000 (12:08 +0200)
src/createrepo_c.c
src/mergerepo_c.c
src/python/sqlite-py.c
src/sqlite.c
src/sqlite.h
tests/test_sqlite.c

index 0b3a728..d79e7bb 100644 (file)
@@ -51,9 +51,9 @@ struct UserData {
     cr_XmlFile *pri_f;              // Opened compressed primary.xml.*
     cr_XmlFile *fil_f;              // Opened compressed filelists.xml.*
     cr_XmlFile *oth_f;              // Opened compressed other.xml.*
-    cr_DbPrimaryStatements pri_statements;  // Opened connection to primary.sqlite
-    cr_DbFilelistsStatements fil_statements;// Opened connection to filelists.sqlite
-    cr_DbOtherStatements oth_statements;    // Opened connection to other.sqlite
+    cr_SqliteDb *pri_db;            // Primary db
+    cr_SqliteDb *fil_db;            // Filelists db
+    cr_SqliteDb *oth_db;            // Other db
     int changelog_limit;            // Max number of changelogs for a package
     const char *location_base;      // Base location url
     int repodir_name_len;           // Len of path to repo /foo/bar/repodata
@@ -169,8 +169,8 @@ write_pkg(long id,
         g_cond_wait (udata->cond_pri, udata->mutex_pri);
     udata->id_pri++;
     cr_xmlfile_add_chunk(udata->pri_f, (const char *) res.primary, NULL);
-    if (udata->pri_statements)
-        cr_db_add_primary_pkg(udata->pri_statements, pkg, NULL);
+    if (udata->pri_db)
+        cr_db_add_pkg(udata->pri_db, pkg, NULL);
     g_mutex_unlock(udata->mutex_pri);
     g_cond_broadcast(udata->cond_pri);
 
@@ -180,8 +180,8 @@ write_pkg(long id,
         g_cond_wait (udata->cond_fil, udata->mutex_fil);
     udata->id_fil++;
     cr_xmlfile_add_chunk(udata->fil_f, (const char *) res.filelists, NULL);
-    if (udata->fil_statements)
-        cr_db_add_filelists_pkg(udata->fil_statements, pkg, NULL);
+    if (udata->fil_db)
+        cr_db_add_pkg(udata->fil_db, pkg, NULL);
     g_mutex_unlock(udata->mutex_fil);
     g_cond_broadcast(udata->cond_fil);
 
@@ -191,8 +191,8 @@ write_pkg(long id,
         g_cond_wait (udata->cond_oth, udata->mutex_oth);
     udata->id_oth++;
     cr_xmlfile_add_chunk(udata->oth_f, (const char *) res.other, NULL);
-    if (udata->oth_statements)
-        cr_db_add_other_pkg(udata->oth_statements, pkg, NULL);
+    if (udata->oth_db)
+        cr_db_add_pkg(udata->oth_db, pkg, NULL);
     g_mutex_unlock(udata->mutex_oth);
     g_cond_broadcast(udata->cond_oth);
 }
@@ -906,12 +906,9 @@ main(int argc, char **argv)
     gchar *pri_db_filename = NULL;
     gchar *fil_db_filename = NULL;
     gchar *oth_db_filename = NULL;
-    sqlite3 *pri_db = NULL;
-    sqlite3 *fil_db = NULL;
-    sqlite3 *oth_db = NULL;
-    cr_DbPrimaryStatements pri_statements   = NULL;
-    cr_DbFilelistsStatements fil_statements = NULL;
-    cr_DbOtherStatements oth_statements     = NULL;
+    cr_SqliteDb *pri_db = NULL;
+    cr_SqliteDb *fil_db = NULL;
+    cr_SqliteDb *oth_db = NULL;
 
     if (!cmd_options->no_database) {
         g_message("Preparing sqlite DBs");
@@ -922,9 +919,6 @@ main(int argc, char **argv)
         pri_db = cr_db_open_primary(pri_db_filename, NULL);
         fil_db = cr_db_open_filelists(fil_db_filename, NULL);
         oth_db = cr_db_open_other(oth_db_filename, NULL);
-        pri_statements = cr_db_prepare_primary_statements(pri_db, NULL);
-        fil_statements = cr_db_prepare_filelists_statements(fil_db, NULL);
-        oth_statements = cr_db_prepare_other_statements(oth_db, NULL);
     }
 
 
@@ -939,9 +933,9 @@ main(int argc, char **argv)
     user_data.pri_f             = pri_cr_file;
     user_data.fil_f             = fil_cr_file;
     user_data.oth_f             = oth_cr_file;
-    user_data.pri_statements    = pri_statements;
-    user_data.fil_statements    = fil_statements;
-    user_data.oth_statements    = oth_statements;
+    user_data.pri_db            = pri_db;
+    user_data.fil_db            = fil_db;
+    user_data.oth_db            = oth_db;
     user_data.changelog_limit   = cmd_options->changelog_limit;
     user_data.location_base     = cmd_options->location_base;
     user_data.checksum_type_str = cr_checksum_name_str(cmd_options->checksum_type);
@@ -1053,13 +1047,9 @@ main(int argc, char **argv)
         cr_db_dbinfo_update(fil_db, fil_xml_rec->checksum, NULL);
         cr_db_dbinfo_update(oth_db, oth_xml_rec->checksum, NULL);
 
-        cr_db_destroy_primary_statements(pri_statements);
-        cr_db_destroy_filelists_statements(fil_statements);
-        cr_db_destroy_other_statements(oth_statements);
-
-        cr_db_close_primary(pri_db, NULL);
-        cr_db_close_filelists(fil_db, NULL);
-        cr_db_close_other(oth_db, NULL);
+        cr_db_close(pri_db, NULL);
+        cr_db_close(fil_db, NULL);
+        cr_db_close(oth_db, NULL);
 
 
         // Compress dbs
index 26dbf2f..2de12c3 100644 (file)
@@ -1061,12 +1061,9 @@ dump_merged_metadata(GHashTable *merged_hashtable,
 
     // Prepare sqlite if needed
 
-    sqlite3 *pri_db = NULL;
-    sqlite3 *fil_db = NULL;
-    sqlite3 *oth_db = NULL;
-    cr_DbPrimaryStatements pri_statements = NULL;
-    cr_DbFilelistsStatements fil_statements = NULL;
-    cr_DbOtherStatements oth_statements = NULL;
+    cr_SqliteDb *pri_db = NULL;
+    cr_SqliteDb *fil_db = NULL;
+    cr_SqliteDb *oth_db = NULL;
 
     if (!cmd_options->no_database) {
         gchar *pri_db_filename = NULL;
@@ -1084,10 +1081,6 @@ dump_merged_metadata(GHashTable *merged_hashtable,
         g_free(pri_db_filename);
         g_free(fil_db_filename);
         g_free(oth_db_filename);
-
-        pri_statements = cr_db_prepare_primary_statements(pri_db, NULL);
-        fil_statements = cr_db_prepare_filelists_statements(fil_db, NULL);
-        oth_statements = cr_db_prepare_other_statements(oth_db, NULL);
     }
 
 
@@ -1113,9 +1106,9 @@ dump_merged_metadata(GHashTable *merged_hashtable,
             cr_puts(oth_f, (const char *) res.other);
 
             if (!cmd_options->no_database) {
-                cr_db_add_primary_pkg(pri_statements, pkg, NULL);
-                cr_db_add_filelists_pkg(fil_statements, pkg, NULL);
-                cr_db_add_other_pkg(oth_statements, pkg, NULL);
+                cr_db_add_pkg(pri_db, pkg, NULL);
+                cr_db_add_pkg(fil_db, pkg, NULL);
+                cr_db_add_pkg(oth_db, pkg, NULL);
             }
 
             free(res.primary);
@@ -1218,14 +1211,9 @@ dump_merged_metadata(GHashTable *merged_hashtable,
         cr_db_dbinfo_update(fil_db, fil_xml_rec->checksum, NULL);
         cr_db_dbinfo_update(oth_db, oth_xml_rec->checksum, NULL);
 
-        // Close dbs
-        cr_db_destroy_primary_statements(pri_statements);
-        cr_db_destroy_filelists_statements(fil_statements);
-        cr_db_destroy_other_statements(oth_statements);
-
-        cr_db_close_primary(pri_db, NULL);
-        cr_db_close_filelists(fil_db, NULL);
-        cr_db_close_other(oth_db, NULL);
+        cr_db_close(pri_db, NULL);
+        cr_db_close(fil_db, NULL);
+        cr_db_close(oth_db, NULL);
 
         // Compress dbs
         gchar *pri_db_filename = g_strconcat(cmd_options->tmp_out_repo, "/primary.sqlite", NULL);
index 6a4e46e..449d1f8 100644 (file)
@@ -28,9 +28,7 @@
 
 typedef struct {
     PyObject_HEAD
-    int type;           // cr_DatabaseType value or -1
-    void *statements;
-    sqlite3 *db;
+    cr_SqliteDb *db;
 } _SqliteObject;
 
 // Forward declaration
@@ -58,11 +56,8 @@ sqlite_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     CR_UNUSED(args);
     CR_UNUSED(kwds);
     _SqliteObject *self = (_SqliteObject *)type->tp_alloc(type, 0);
-    if (self) {
-        self->type = -1;
-        self->statements = NULL;
+    if (self)
         self->db = NULL;
-    }
     return (PyObject *)self;
 }
 
@@ -93,54 +88,22 @@ sqlite_init(_SqliteObject *self, PyObject *args, PyObject *kwds)
         return -1;
     }
 
-    if (self->statements) {
-        if (self->type == CR_DB_PRIMARY)
-            cr_db_destroy_primary_statements(self->statements);
-        else if (self->type == CR_DB_FILELISTS)
-            cr_db_destroy_filelists_statements(self->statements);
-        else if (self->type == CR_DB_OTHER)
-            cr_db_destroy_other_statements(self->statements);
-        self->statements = NULL;
-    }
-
     /* Init */
-    self->type = db_type;
-    if (self->type == CR_DB_PRIMARY)
-        self->db = cr_db_open_primary(path, &err);
-    else if (self->type == CR_DB_FILELISTS)
-        self->db = cr_db_open_filelists(path, &err);
-    else if (self->type == CR_DB_OTHER)
-        self->db = cr_db_open_other(path, &err);
-
+    self->db = cr_db_open(path, db_type, &err);
     if (err) {
         PyErr_Format(CrErr_Exception, "Sqlite initialization failed: %s", err->message);
         g_clear_error(&err);
         return -1;
     }
 
-    if (self->db == NULL) {
-        PyErr_SetString(CrErr_Exception, "Sqlite initialization failed");
-        return -1;
-    }
-
     return 0;
 }
 
 static void
 sqlite_dealloc(_SqliteObject *self)
 {
-    if (self->statements) {
-        if (self->type == CR_DB_PRIMARY)
-            cr_db_destroy_primary_statements(self->statements);
-        else if (self->type == CR_DB_FILELISTS)
-            cr_db_destroy_filelists_statements(self->statements);
-        else if (self->type == CR_DB_OTHER)
-            cr_db_destroy_other_statements(self->statements);
-        self->statements = NULL;
-    }
-
     if (self->db)
-        cr_db_close(self->db, self->type, NULL);
+        cr_db_close(self->db, NULL);
 
     Py_TYPE(self)->tp_free(self);
 }
@@ -149,10 +112,10 @@ static PyObject *
 sqlite_repr(_SqliteObject *self)
 {
     char *type;
-    if (self->type == CR_DB_PRIMARY)        type = "PrimaryDb";
-    else if (self->type == CR_DB_FILELISTS) type = "FilelistsDb";
-    else if (self->type == CR_DB_OTHER)     type = "OtherDb";
-    else                                    type = "UnknownDb";
+    if (self->db->type == CR_DB_PRIMARY)        type = "PrimaryDb";
+    else if (self->db->type == CR_DB_FILELISTS) type = "FilelistsDb";
+    else if (self->db->type == CR_DB_OTHER)     type = "OtherDb";
+    else                                        type = "UnknownDb";
     return PyString_FromFormat("<createrepo_c.Sqlite %s object>", type);
 }
 
@@ -165,34 +128,6 @@ sqlite_repr(_SqliteObject *self)
 /* Sqlite methods */
 
 static PyObject *
-prepare_statements(_SqliteObject *self, void *nothing)
-{
-    CR_UNUSED(nothing);
-    GError *err = NULL;
-
-    if (self->statements)
-        Py_RETURN_NONE;
-
-    if (check_SqliteStatus(self))
-        return NULL;
-
-    if (self->type == CR_DB_PRIMARY)
-        self->statements = cr_db_prepare_primary_statements(self->db, &err);
-    else if (self->type == CR_DB_FILELISTS)
-        self->statements = cr_db_prepare_filelists_statements(self->db, &err);
-    else if (self->type == CR_DB_OTHER)
-        self->statements = cr_db_prepare_other_statements(self->db, &err);
-
-    if (err) {
-        PyErr_Format(CrErr_Exception, "Sqlite statement error: %s", err->message);
-        g_clear_error(&err);
-        return NULL;
-    }
-
-    Py_RETURN_NONE;
-}
-
-static PyObject *
 add_pkg(_SqliteObject *self, PyObject *args)
 {
     PyObject *py_pkg;
@@ -200,17 +135,11 @@ add_pkg(_SqliteObject *self, PyObject *args)
 
     if (!PyArg_ParseTuple(args, "O!:add_pkg", &Package_Type, &py_pkg))
         return NULL;
+
     if (check_SqliteStatus(self))
         return NULL;
-    if (!self->statements)
-        Py_XDECREF(prepare_statements(self, NULL));
-    if (self->type == CR_DB_PRIMARY)
-        cr_db_add_primary_pkg(self->statements, Package_FromPyObject(py_pkg), &err);
-    else if (self->type == CR_DB_FILELISTS)
-        cr_db_add_filelists_pkg(self->statements, Package_FromPyObject(py_pkg), &err);
-    else if (self->type == CR_DB_OTHER)
-        cr_db_add_other_pkg(self->statements, Package_FromPyObject(py_pkg), &err);
 
+    cr_db_add_pkg(self->db, Package_FromPyObject(py_pkg), &err);
     if (err) {
         PyErr_Format(CrErr_Exception, "Cannot add package: %s", err->message);
         g_clear_error(&err);
@@ -228,10 +157,11 @@ dbinfo_update(_SqliteObject *self, PyObject *args)
 
     if (!PyArg_ParseTuple(args, "s:dbinfo_update", &checksum))
         return NULL;
+
     if (check_SqliteStatus(self))
         return NULL;
-    cr_db_dbinfo_update(self->db, checksum, &err);
 
+    cr_db_dbinfo_update(self->db, checksum, &err);
     if (err) {
         PyErr_Format(CrErr_Exception, "Sqlite dbinfo_update error: %s", err->message);
         g_clear_error(&err);
@@ -249,7 +179,7 @@ close_db(_SqliteObject *self, void *nothing)
     CR_UNUSED(nothing);
 
     if (self->db) {
-        cr_db_close(self->db, self->type, &err);
+        cr_db_close(self->db, &err);
         self->db = NULL;
         if (err) {
             PyErr_Format(CrErr_Exception, "Sqlite close error: %s", err->message);
@@ -262,7 +192,6 @@ close_db(_SqliteObject *self, void *nothing)
 }
 
 static struct PyMethodDef sqlite_methods[] = {
-    {"_prepare_statements", (PyCFunction)prepare_statements, METH_NOARGS, NULL},
     {"add_pkg", (PyCFunction)add_pkg, METH_VARARGS, NULL},
     {"dbinfo_update", (PyCFunction)dbinfo_update, METH_VARARGS, NULL},
     {"close", (PyCFunction)close_db, METH_NOARGS, NULL},
index 87c623f..f04f548 100644 (file)
@@ -464,119 +464,35 @@ db_index_other_tables (sqlite3 *db, GError **err)
 }
 
 
-sqlite3 *
-cr_db_open(const char *path, cr_DatabaseType db_type, GError **err)
-{
-    int exists;
-    GError *tmp_err = NULL;
-    sqlite3 *db = NULL;
-
-    assert(db_type < CR_DB_SENTINEL);
-
-    if (!path || path[0] == '\0')
-        return db;
-
-    exists = g_file_test(path, G_FILE_TEST_IS_REGULAR);
-
-    sqlite3_enable_shared_cache(1);
-
-    db = open_sqlite_db(path, &tmp_err);
-    if (tmp_err) {
-        g_propagate_error(err, tmp_err);
-        return db;
-    }
-
-    sqlite3_exec(db, "BEGIN", NULL, NULL, NULL);
-
-    db_tweak(db, &tmp_err);
-    if (tmp_err) {
-        g_propagate_error(err, tmp_err);
-        return db;
-    }
-
-    db_create_dbinfo_table(db, &tmp_err);
-    if (tmp_err) {
-        g_propagate_error(err, tmp_err);
-        return db;
-    }
-
-    if (!exists) {
-        // Do not recreate tables, indexes and triggers if db has existed.
-        switch (db_type) {
-            case CR_DB_PRIMARY:
-                db_create_primary_tables(db, &tmp_err); break;
-            case CR_DB_FILELISTS:
-                db_create_filelists_tables(db, &tmp_err); break;
-            case CR_DB_OTHER:
-                db_create_other_tables(db, &tmp_err); break;
-            default:
-                assert(0);
-        }
-
-        if (tmp_err)
-            g_propagate_error(err, tmp_err);
-    }
-
-    return db;
-}
-
-
-void
-cr_db_close(sqlite3 *db, cr_DatabaseType db_type, GError **err)
-{
-    GError *tmp_err = NULL;
-
-    assert(db_type < CR_DB_SENTINEL);
-
-    if (!db)
-        return;
-
-    switch (db_type) {
-        case CR_DB_PRIMARY:
-            db_index_primary_tables(db, &tmp_err); break;
-        case CR_DB_FILELISTS:
-            db_index_filelists_tables(db, &tmp_err); break;
-        case CR_DB_OTHER:
-            db_index_other_tables(db, &tmp_err); break;
-        default:
-            assert(0);
-    }
-
-    if (tmp_err)
-        g_propagate_error(err, tmp_err);
-
-    sqlite3_exec (db, "COMMIT", NULL, NULL, NULL);
-
-    sqlite3_close(db);
-}
-
-
 /*
  * Package insertion stuff
  */
 
 
-void
-cr_db_dbinfo_update(sqlite3 *db, const char *checksum, GError **err)
+int
+cr_db_dbinfo_update(cr_SqliteDb *sqlitedb, const char *checksum, GError **err)
 {
     int rc;
     sqlite3_stmt *handle;
     const char *query = "INSERT INTO db_info (dbversion, checksum) VALUES (?, ?)";
 
+    assert(sqlitedb);
+    assert(!err || *err == NULL);
+
     /* Prepare insert statement */
-    rc = sqlite3_prepare_v2(db, query, -1, &handle, NULL);
+    rc = sqlite3_prepare_v2(sqlitedb->db, query, -1, &handle, NULL);
     if (rc != SQLITE_OK) {
         g_set_error(err, CR_DB_ERROR, CRE_DB,
                     "Cannot prepare db_info update: %s",
-                    sqlite3_errmsg(db));
+                    sqlite3_errmsg(sqlitedb->db));
         g_critical("%s: Cannot prepare db_info update statement: %s",
-                   __func__, sqlite3_errmsg(db));
+                   __func__, sqlite3_errmsg(sqlitedb->db));
         sqlite3_finalize(handle);
-        return;
+        return CRE_DB;
     }
 
     /* Delete all previous content of db_info */
-    sqlite3_exec(db, "DELETE FROM db_info", NULL, NULL, NULL);
+    sqlite3_exec(sqlitedb->db, "DELETE FROM db_info", NULL, NULL, NULL);
 
     /* Perform insert */
     sqlite3_bind_int(handle, 1, CR_DB_CACHE_DBVERSION);
@@ -587,11 +503,13 @@ cr_db_dbinfo_update(sqlite3 *db, const char *checksum, GError **err)
     if (rc != SQLITE_OK) {
         g_set_error(err, CR_DB_ERROR, CRE_DB,
                       "Cannot update dbinfo table: %s",
-                       sqlite3_errmsg (db));
+                       sqlite3_errmsg (sqlitedb->db));
         g_critical("%s: Cannot update dbinfo table: %s",
-                    __func__, sqlite3_errmsg(db));
+                    __func__, sqlite3_errmsg(sqlitedb->db));
+        return CRE_DB;
     }
 
+    return CRE_OK;
 }
 
 
@@ -1378,3 +1296,194 @@ cr_db_add_other_pkg(cr_DbOtherStatements stmts, cr_Package *pkg, GError **err)
         }
     }
 }
+
+
+// Function from header file (Public interface of the module)
+
+
+cr_SqliteDb *
+cr_db_open(const char *path, cr_DatabaseType db_type, GError **err)
+{
+    cr_SqliteDb *sqlitedb = NULL;
+    int exists;
+    sqlite3 *db = NULL;
+    GError *tmp_err = NULL;
+    void *statements;
+
+    assert(path);
+    assert(db_type < CR_DB_SENTINEL);
+    assert(!err || *err == NULL);
+
+    if (path[0] == '\0') {
+        g_set_error(err, CR_DB_ERROR, CRE_BADARG, "Bad path: \"%s\"", path);
+        return NULL;
+    }
+
+    exists = g_file_test(path, G_FILE_TEST_IS_REGULAR);
+
+    sqlite3_enable_shared_cache(1);
+
+    db = open_sqlite_db(path, &tmp_err);
+    if (tmp_err) {
+        g_propagate_error(err, tmp_err);
+        return NULL;
+    }
+
+    sqlite3_exec(db, "BEGIN", NULL, NULL, NULL);
+
+    db_tweak(db, &tmp_err);
+    if (tmp_err) {
+        g_propagate_error(err, tmp_err);
+        sqlite3_close(db);
+        return NULL;
+    }
+
+    db_create_dbinfo_table(db, &tmp_err);
+    if (tmp_err) {
+        g_propagate_error(err, tmp_err);
+        sqlite3_close(db);
+        return NULL;
+    }
+
+    if (!exists) {
+        // Do not recreate tables, indexes and triggers if db has existed.
+        switch (db_type) {
+            case CR_DB_PRIMARY:
+                db_create_primary_tables(db, &tmp_err);
+                break;
+            case CR_DB_FILELISTS:
+                db_create_filelists_tables(db, &tmp_err);
+                break;
+            case CR_DB_OTHER:
+                db_create_other_tables(db, &tmp_err);
+                break;
+            default:
+                assert(0);
+        }
+
+        if (tmp_err) {
+            g_propagate_error(err, tmp_err);
+            sqlite3_close(db);
+            return NULL;
+        }
+    }
+
+    // Compile SQL statements
+    switch (db_type) {
+        case CR_DB_PRIMARY:
+            statements = cr_db_prepare_primary_statements(db, &tmp_err);
+            break;
+        case CR_DB_FILELISTS:
+            statements = cr_db_prepare_filelists_statements(db, &tmp_err);
+            break;
+        case CR_DB_OTHER:
+            statements = cr_db_prepare_other_statements(db, &tmp_err);
+            break;
+        default:
+            assert(0);
+    }
+
+    if (tmp_err) {
+            g_propagate_error(err, tmp_err);
+            sqlite3_close(db);
+            return NULL;
+    }
+
+    sqlitedb = g_new0(cr_SqliteDb, 1);
+    sqlitedb->db         = db;
+    sqlitedb->type       = db_type;
+
+    switch (db_type) {
+        case CR_DB_PRIMARY:
+            sqlitedb->statements.pri = statements;
+            break;
+        case CR_DB_FILELISTS:
+            sqlitedb->statements.fil = statements;
+            break;
+        case CR_DB_OTHER:
+            sqlitedb->statements.oth = statements;
+            break;
+        default:
+            assert(0);
+    }
+
+    return sqlitedb;
+}
+
+
+int
+cr_db_close(cr_SqliteDb *sqlitedb, GError **err)
+{
+    GError *tmp_err = NULL;
+
+    assert(!err || *err == NULL);
+
+    if (!sqlitedb)
+        return CRE_OK;
+
+    switch (sqlitedb->type) {
+        case CR_DB_PRIMARY:
+            db_index_primary_tables(sqlitedb->db, &tmp_err);
+            cr_db_destroy_primary_statements(sqlitedb->statements.pri);
+            break;
+        case CR_DB_FILELISTS:
+            db_index_filelists_tables(sqlitedb->db, &tmp_err);
+            cr_db_destroy_filelists_statements(sqlitedb->statements.fil);
+            break;
+        case CR_DB_OTHER:
+            db_index_other_tables(sqlitedb->db, &tmp_err);
+            cr_db_destroy_other_statements(sqlitedb->statements.oth);
+            break;
+        default:
+            assert(0);
+    }
+
+    if (tmp_err) {
+        int code = tmp_err->code;
+        g_propagate_error(err, tmp_err);
+        return code;
+    }
+
+    sqlite3_exec (sqlitedb->db, "COMMIT", NULL, NULL, NULL);
+    sqlite3_close(sqlitedb->db);
+
+    g_free(sqlitedb);
+
+    return CRE_OK;
+}
+
+
+int
+cr_db_add_pkg(cr_SqliteDb *sqlitedb, cr_Package *pkg, GError **err)
+{
+    GError *tmp_err = NULL;
+
+    assert(sqlitedb);
+    assert(sqlitedb->type < CR_DB_SENTINEL);
+    assert(!err || *err == NULL);
+
+    if (!pkg)
+        return CRE_OK;
+
+    switch (sqlitedb->type) {
+    case CR_DB_PRIMARY:
+        cr_db_add_primary_pkg(sqlitedb->statements.pri, pkg, &tmp_err);
+        break;
+    case CR_DB_FILELISTS:
+        cr_db_add_filelists_pkg(sqlitedb->statements.fil, pkg, &tmp_err);
+        break;
+    case CR_DB_OTHER:
+        cr_db_add_other_pkg(sqlitedb->statements.oth, pkg, &tmp_err);
+        break;
+    default:
+        assert(0);
+    }
+
+    if (tmp_err) {
+        int code = tmp_err->code;
+        g_propagate_error(err, tmp_err);
+        return code;
+    }
+
+    return CRE_OK;
+}
index ff08949..d61d919 100644 (file)
@@ -36,24 +36,20 @@ extern "C" {
  * \code
  * cr_Package *pkg;
  * sqlite3 *primary_db;
- * cr_DbPrimary_Statements primary_statements;
  *
  * // Load pkg (See parsepkg or parsehdr module)
  *
  * // Create primary sqlite database
- * primary_db = cr_db_open_primary("/foo/bar/repodata/primary.sqlite");
- * // Compile statements (to avoid SQL parsing overhead)
- * primary_statements = cr_db_prepare_primary_statements(primary_db, NULL);
+ * primary_db = cr_db_open_primary("/foo/bar/repodata/primary.sqlite", NULL);
  *
  * // Add all packages here
- * cr_db_add_primary_pkg(primary_statements, pkg, NULL);
+ * cr_db_add_pkg(primary_db, pkg, NULL);
  *
  * // Add checksum of XML version of file (primary in this case)
  * cr_db_dbinfo_update(primary_db, "foochecksum", NULL);
  *
  * // Cleanup
- * cr_db_destroy_primary_statements(primary_db);
- * cr_db_close_primary(primary_db, NULL);
+ * cr_db_close(primary_db, NULL);
  * \endcode
  *
  *  \addtogroup sqlite
@@ -62,10 +58,6 @@ extern "C" {
 
 #define CR_DB_CACHE_DBVERSION       10      /*!< Version of DB api */
 
-typedef struct _DbPrimaryStatements   * cr_DbPrimaryStatements;
-typedef struct _DbFilelistsStatements * cr_DbFilelistsStatements;
-typedef struct _DbOtherStatements     * cr_DbOtherStatements;
-
 /** Database type.
  */
 typedef enum {
@@ -75,6 +67,27 @@ typedef enum {
     CR_DB_SENTINEL,     /*!< sentinel of the list */
 } cr_DatabaseType;
 
+typedef struct _DbPrimaryStatements   * cr_DbPrimaryStatements;
+typedef struct _DbFilelistsStatements * cr_DbFilelistsStatements;
+typedef struct _DbOtherStatements     * cr_DbOtherStatements;
+
+typedef union {
+    cr_DbPrimaryStatements pri;
+    cr_DbFilelistsStatements fil;
+    cr_DbOtherStatements oth;
+} cr_Statements;
+
+/** cr_SqliteDb structure.
+ */
+typedef struct {
+    sqlite3 *db; /*!<
+        Sqlite database */
+    cr_DatabaseType type; /*!<
+        Type of Sqlite database. */
+    cr_Statements statements; /*!<
+        Compiled SQL statements */
+} cr_SqliteDb;
+
 /** Macro over cr_db_open function. Open (create new) primary sqlite sqlite db.
  *  - creates db file
  *  - creates primary tables
@@ -82,7 +95,7 @@ typedef enum {
  *  - tweak some db params
  * @param PATH                  Path to the db file.
  * @param ERR                   **GError
- * @return                      open db pointer
+ * @return                      Opened db or NULL on error
  */
 #define cr_db_open_primary(PATH, ERR)    cr_db_open(PATH, CR_DB_PRIMARY, ERR)
 
@@ -93,7 +106,7 @@ typedef enum {
  *  - tweak some db params
  * @param PATH                  Path to the db file.
  * @param ERR                   **GError
- * @return                      open db pointer
+ * @return                      Opened db or NULL on error
  */
 #define cr_db_open_filelists(PATH, ERR)  cr_db_open(PATH, CR_DB_FILELISTS, ERR)
 
@@ -105,37 +118,10 @@ typedef enum {
  *  - tweak some db params
  * @param PATH                  Path to the db file.
  * @param ERR                   **GError
- * @return                      open db connection
+ * @return                      Opened db or NULL on error
  */
 #define cr_db_open_other(PATH, ERR)      cr_db_open(PATH, CR_DB_OTHER, ERR)
 
-/** Macro over cr_db_close function. Close db.
- *  - creates indexes on tables
- *  - commits transaction
- *  - closes db
- * @param DB                    open db connection
- * @param ERR                   **GError
- */
-#define cr_db_close_primary(DB, ERR)     cr_db_close(DB, CR_DB_PRIMARY, ERR)
-
-/** Macro over cr_db_close function. Close db.
- *  - creates indexes on tables
- *  - commits transaction
- *  - closes db
- * @param DB                    open db connection
- * @param ERR                   **GError
- */
-#define cr_db_close_filelists(DB, ERR)   cr_db_close(DB, CR_DB_FILELISTS, ERR)
-
-/** Macro over cr_db_close function. Close db.
- *  - creates indexes on tables
- *  - commits transaction
- *  - closes db
- * @param DB                    open db connection
- * @param ERR                   **GError
- */
-#define cr_db_close_other(DB, ERR)       cr_db_close(DB, CR_DB_OTHER, ERR)
-
 /** Open (create new) other sqlite sqlite db.
  *  - creates db file
  *  - opens transaction
@@ -145,91 +131,41 @@ typedef enum {
  * @param path                  Path to the db file.
  * @param db_type               Type of database (primary, filelists, other)
  * @param err                   **GError
- * @return                      open db connection
- */
-sqlite3 *cr_db_open(const char *path, cr_DatabaseType db_type, GError **err);
-
-/** Prepare compiled statements for use in the cr_db_add_primary_pkg function.
- * @param db                    Open db connection
- * @param err                   **GError
- * @return                      cr_DbPrimaryStatements object
- */
-cr_DbPrimaryStatements cr_db_prepare_primary_statements(sqlite3 *db,
-                                                        GError **err);
-
-/** Prepare compiled statements for use in the cr_db_add_filelists_pkg function.
- * @param db                    Open db connection
- * @param err                   **GError
- * @return                      cr_DbFilelistsStatements object
- */
-cr_DbFilelistsStatements cr_db_prepare_filelists_statements(sqlite3 *db,
-                                                            GError **err);
-
-/** Prepare compiled statements for use in the cr_db_add_other_pkg function.
- * @param db                    Open db connection
- * @param err                   **GError
- * @return                      cr_DbOtherStatements object
- */
-cr_DbOtherStatements cr_db_prepare_other_statements(sqlite3 *db, GError **err);
-
-/** Frees cr_DbPrimaryStatements object.
- * @param stmts                 statements object
- */
-void cr_db_destroy_primary_statements(cr_DbPrimaryStatements stmts);
-
-/** Frees cr_DbFilelistsStatements object.
- * @param stmts                 statements object
+ * @return                      Opened db or NULL on error
  */
-void cr_db_destroy_filelists_statements(cr_DbFilelistsStatements stmts);
-
-/** Frees cr_DbOtherStatements object.
- * @param stmts                 statements object
- */
-void cr_db_destroy_other_statements(cr_DbOtherStatements stmts);
-
-/** Add package into the database.
- * @param stmts                 object with compiled statements
- * @param pkg                   package object
- * @param err                   **GError
- */
-void cr_db_add_primary_pkg(cr_DbPrimaryStatements stmts,
-                           cr_Package *pkg,
-                           GError **err);
+cr_SqliteDb *cr_db_open(const char *path,
+                        cr_DatabaseType db_type,
+                        GError **err);
 
 /** Add package into the database.
- * @param stmts                 object with compiled statements
+ * @param sqlitedb              open db connection
  * @param pkg                   package object
  * @param err                   **GError
+ * @return                      cr_Error code
  */
-void cr_db_add_filelists_pkg(cr_DbFilelistsStatements stmts,
-                             cr_Package *pkg,
-                             GError **err);
-
-/** Add package into the database.
- * @param stmts                 object with compiled statements
- * @param pkg                   package object
- * @param err                   **GError
- */
-void cr_db_add_other_pkg(cr_DbOtherStatements stmts,
-                         cr_Package *pkg,
-                         GError **err);
+int cr_db_add_pkg(cr_SqliteDb *sqlitedb,
+                  cr_Package *pkg,
+                  GError **err);
 
 /** Insert record into the updateinfo table
- * @param db                    open db connection
+ * @param sqlitedb              open db connection
  * @param checksum              compressed xml file checksum
  * @param err                   **GError
+ * @return                      cr_Error code
  */
-void cr_db_dbinfo_update(sqlite3 *db, const char *checksum, GError **err);
+int cr_db_dbinfo_update(cr_SqliteDb *sqlitedb,
+                        const char *checksum,
+                        GError **err);
 
 /** Close db.
  *  - creates indexes on tables
  *  - commits transaction
  *  - closes db
- * @param db                    open db connection
- * @param db_type               Type of database (primary, filelists, other)
+ * @param sqlitedb              open db connection
  * @param err                   **GError
+ * @return                      cr_Error code
  */
-void cr_db_close(sqlite3 *db, cr_DatabaseType db_type, GError **err);
+int cr_db_close(cr_SqliteDb *sqlitedb, GError **err);
 
 /** @} */
 
index bfef7f9..1e9f8ed 100644 (file)
@@ -164,7 +164,7 @@ test_cr_open_db(TestData *testdata, gconstpointer test_data)
 
     GError *err = NULL;
     gchar *path = NULL;
-    sqlite3 *db;
+    cr_SqliteDb *db;
 
     // Create new db
 
@@ -174,7 +174,7 @@ test_cr_open_db(TestData *testdata, gconstpointer test_data)
     g_assert(!err);
     g_assert(g_file_test(path, G_FILE_TEST_EXISTS));
     g_free(path);
-    cr_db_close_primary(db, &err);
+    cr_db_close(db, &err);
     g_assert(!err);
 
     path = g_strconcat(testdata->tmp_dir, "/", TMP_FILELISTS_NAME, NULL);
@@ -183,7 +183,7 @@ test_cr_open_db(TestData *testdata, gconstpointer test_data)
     g_assert(!err);
     g_assert(g_file_test(path, G_FILE_TEST_EXISTS));
     g_free(path);
-    cr_db_close_filelists(db, &err);
+    cr_db_close(db, &err);
     g_assert(!err);
 
     path = g_strconcat(testdata->tmp_dir, "/", TMP_OTHER_NAME, NULL);
@@ -192,7 +192,7 @@ test_cr_open_db(TestData *testdata, gconstpointer test_data)
     g_assert(!err);
     g_assert(g_file_test(path, G_FILE_TEST_EXISTS));
     g_free(path);
-    cr_db_close_other(db, &err);
+    cr_db_close(db, &err);
     g_assert(!err);
 }
 
@@ -204,15 +204,16 @@ test_cr_db_add_primary_pkg(TestData *testdata, gconstpointer test_data)
 
     GError *err = NULL;
     gchar *path;
-    sqlite3 *db;
+    cr_SqliteDb *db;
     cr_Package *pkg;
 
     GTimer *timer = g_timer_new();
-    gdouble topen, tprepare, tadd, tclean, tmp;
+    gdouble topen, tadd, tclean, tmp;
 
     // Create new db
 
     path = g_strconcat(testdata->tmp_dir, "/", TMP_PRIMARY_NAME, NULL);
+
     g_timer_start(timer);
     db = cr_db_open_primary(path, &err);
     topen = g_timer_elapsed(timer, NULL);
@@ -226,25 +227,17 @@ test_cr_db_add_primary_pkg(TestData *testdata, gconstpointer test_data)
 
     // Add package
 
-    cr_DbPrimaryStatements pri_stmts;
-
     tmp = g_timer_elapsed(timer, NULL);
-    pri_stmts = cr_db_prepare_primary_statements(db, &err);
-    tprepare = g_timer_elapsed(timer, NULL) - tmp;
-    g_assert(!err);
-
-    tmp = g_timer_elapsed(timer, NULL);
-    cr_db_add_primary_pkg(pri_stmts, pkg, &err);
+    cr_db_add_pkg(db, pkg, &err);
     tadd = g_timer_elapsed(timer, NULL) - tmp;
     g_assert(!err);
 
     tmp = g_timer_elapsed(timer, NULL);
-    cr_db_destroy_primary_statements(pri_stmts);
-    cr_db_close_primary(db, &err);
+    cr_db_close(db, &err);
     tclean = g_timer_elapsed(timer, NULL) - tmp;
 
-    printf("Stats:\nOpen:    %f\nPrepare: %f\nAdd:     %f\nCleanup: %f\nSum:     %f\n",
-            topen, tprepare, tadd, tclean, (topen + tprepare + tadd + tclean));
+    printf("Stats:\nOpen:    %f\nAdd:     %f\nCleanup: %f\nSum:     %f\n",
+           topen, tadd, tclean, (tadd + tclean));
 
     // Cleanup
 
@@ -262,7 +255,7 @@ test_cr_db_dbinfo_update(TestData *testdata, gconstpointer test_data)
 
     GError *err = NULL;
     gchar *path;
-    sqlite3 *db;
+    cr_SqliteDb *db;
     cr_Package *pkg;
 
     // Create new db
@@ -284,16 +277,9 @@ test_cr_db_dbinfo_update(TestData *testdata, gconstpointer test_data)
 
     // Add package
 
-    cr_DbPrimaryStatements pri_stmts;
-
-    pri_stmts = cr_db_prepare_primary_statements(db, &err);
+    cr_db_add_pkg(db, pkg, &err);
     g_assert(!err);
 
-    cr_db_add_primary_pkg(pri_stmts, pkg, &err);
-    g_assert(!err);
-
-    cr_db_destroy_primary_statements(pri_stmts);
-
     // Try cr_db_dbinfo_update again
 
     cr_db_dbinfo_update(db, "foochecksum", &err);
@@ -303,7 +289,7 @@ test_cr_db_dbinfo_update(TestData *testdata, gconstpointer test_data)
 
     cr_package_free(pkg);
     g_free(path);
-    cr_db_close_primary(db, &err);
+    cr_db_close(db, &err);
     g_assert(!err);
 }
 
@@ -316,7 +302,7 @@ test_all(TestData *testdata, gconstpointer test_data)
 
     GError *err = NULL;
     gchar *path;
-    sqlite3 *db = NULL;
+    cr_SqliteDb *db = NULL;
     cr_Package *pkg, *pkg2 = NULL;
 
     // Create new db
@@ -343,18 +329,11 @@ test_all(TestData *testdata, gconstpointer test_data)
 
     // Add package
 
-    cr_DbPrimaryStatements pri_stmts;
-
-    pri_stmts = cr_db_prepare_primary_statements(db, &err);
+    cr_db_add_pkg(db, pkg, &err);
     g_assert(!err);
-
-    cr_db_add_primary_pkg(pri_stmts, pkg, &err);
-    g_assert(!err);
-    cr_db_add_primary_pkg(pri_stmts, pkg2, &err);
+    cr_db_add_pkg(db, pkg2, &err);
     g_assert(!err);
 
-    cr_db_destroy_primary_statements(pri_stmts);
-
     // Try cr_db_dbinfo_update again
 
     cr_db_dbinfo_update(db, "foochecksum", &err);
@@ -365,7 +344,7 @@ test_all(TestData *testdata, gconstpointer test_data)
 
     cr_package_free(pkg);
     cr_package_free(pkg2);
-    cr_db_close_primary(db, &err);
+    cr_db_close(db, &err);
     g_assert(!err);
     g_free(path);
 }