[rygel] db: Make Database more generic



commit 6ffa6bd40a61ebb6e1d096fae4b391c1885da0fc
Author: Jens Georg <mail jensge org>
Date:   Mon Apr 20 09:13:03 2015 +0200

    db: Make Database more generic
    
    - Introduce the two flavors CACHE and CONFIG; one is placed in XDG_USER_CACHE,
      the other in XDG_USER_CONFIG.
    - If the name of the database is an absolute path use it as is.
    - Remove SqliteWrapper class
    
    Signed-off-by: Jens Georg <mail jensge org>

 src/librygel-db/database-cursor.vala |   34 +++++++++++--
 src/librygel-db/database.vala        |   89 +++++++++++++++++++++++-----------
 src/librygel-db/filelist.am          |    1 -
 src/librygel-db/sqlite-wrapper.vala  |   80 ------------------------------
 4 files changed, 91 insertions(+), 113 deletions(-)
---
diff --git a/src/librygel-db/database-cursor.vala b/src/librygel-db/database-cursor.vala
index 763f1d8..e5a18c3 100644
--- a/src/librygel-db/database-cursor.vala
+++ b/src/librygel-db/database-cursor.vala
@@ -22,10 +22,11 @@
 
 using Sqlite;
 
-public class Rygel.Database.Cursor : SqliteWrapper {
+public class Rygel.Database.Cursor : Object {
     private Statement statement;
     private int current_state = -1;
     private bool dirty = true;
+    private unowned Sqlite.Database db;
 
     /**
      * Prepare a SQLite statement from a SQL string
@@ -43,9 +44,9 @@ public class Rygel.Database.Cursor : SqliteWrapper {
      * none
      */
     public Cursor (Sqlite.Database   db,
-                           string            sql,
-                           GLib.Value[]?     arguments) throws DatabaseError {
-        base.wrap (db);
+                   string            sql,
+                   GLib.Value[]?     arguments) throws DatabaseError {
+        this.db = db;
 
         this.throw_if_code_is_error (db.prepare_v2 (sql,
                                                     -1,
@@ -144,4 +145,29 @@ public class Rygel.Database.Cursor : SqliteWrapper {
             return this.cursor.next ();
         }
     }
+
+    /**
+     * Convert a SQLite return code to a DatabaseError
+     */
+    protected void throw_if_code_is_error (int sqlite_error)
+                                           throws DatabaseError {
+        switch (sqlite_error) {
+            case Sqlite.OK:
+            case Sqlite.DONE:
+            case Sqlite.ROW:
+                return;
+            default:
+                throw new DatabaseError.SQLITE_ERROR
+                                        ("SQLite error %d: %s",
+                                         sqlite_error,
+                                         this.db.errmsg ());
+        }
+    }
+
+    /**
+     * Check if the last operation on the database was an error
+     */
+    protected void throw_if_db_has_error () throws DatabaseError {
+        this.throw_if_code_is_error (this.db.errcode ());
+    }
 }
diff --git a/src/librygel-db/database.vala b/src/librygel-db/database.vala
index 15d0fd1..e931c55 100644
--- a/src/librygel-db/database.vala
+++ b/src/librygel-db/database.vala
@@ -22,12 +22,29 @@
 
 using Sqlite;
 
-public errordomain Rygel.Database.DatabaseError {
-    IO_ERROR,
-    SQLITE_ERROR
-}
-
 namespace Rygel.Database {
+
+    public errordomain DatabaseError {
+        SQLITE_ERROR, /// Error code translated from SQLite
+        OPEN          /// Error while opening database file
+    }
+
+    public enum Flavor {
+        CACHE, /// Database is a cache (will be placed in XDG_USER_CACHE
+        CONFIG /// Database is configuration (will be placed in XDG_USER_CONFIG)
+    }
+
+    public enum Flags {
+        READ_ONLY = 1, /// Database is read-only
+        WRITE_ONLY = 1 << 1, /// Database is write-only
+        /// Database can be read and updated
+        READ_WRITE = READ_ONLY | WRITE_ONLY,
+
+        /// Database is shared between several processes
+        SHARED = 1 << 2;
+    }
+
+    /// Prototype for UTF-8 collation function
     extern static int utf8_collate_str (uint8[] a, uint8[] b);
 
     /**
@@ -48,7 +65,7 @@ namespace Rygel.Database {
  * It adds statement preparation based on GValue and a cancellable exec
  * function.
  */
-public class Rygel.Database.Database : SqliteWrapper {
+public class Rygel.Database.Database : Object {
 
     /**
      * Function to implement the custom SQL function 'contains'
@@ -89,33 +106,55 @@ public class Rygel.Database.Database : SqliteWrapper {
         return utf8_collate_str (_a, _b);
     }
 
-    /**
-     * Open a database in the user's cache directory as defined by XDG
-     *
-     * @param name of the database, used to build full path
-     * (<cache-dir>/rygel/<name>.db)
-     */
-    public Database (string name) throws DatabaseError {
-        string db_file;
-
-        if (name != ":memory:") {
+    private static string build_path (string name, Flavor flavor) {
+        if (name != ":memory:" && !Path.is_absolute (name)) {
             var dirname = Path.build_filename (
-                                        Environment.get_user_cache_dir (),
+                                        flavor == Flavor.CACHE
+                                            ? Environment.get_user_cache_dir ()
+                                            : Environment.get_user_config_dir (),
                                         "rygel");
             DirUtils.create_with_parents (dirname, 0750);
-            db_file = Path.build_filename (dirname, "%s.db".printf (name));
+
+            return Path.build_filename (dirname, "%s.db".printf (name));
         } else {
-            db_file = name;
+            return name;
         }
+    }
+
+    private Sqlite.Database db;
 
-        base (db_file);
+    /**
+     * Connect to a SQLite database file
+     *
+     * @param name: Name of the database which is used to create the file-name
+     * @param flavor: Specifies the flavor of the database
+     * @param flags: How to open the database
+     */
+    public Database (string name,
+                     Flavor flavor = Flavor.CACHE,
+                     Flags  flags = Flags.READ_WRITE) throws DatabaseError {
+        var path = Database.build_path (name, flavor);
+        if (flags == Flags.READ_ONLY) {
+            Sqlite.Database.open_v2 (path, out this.db, Sqlite.OPEN_READONLY);
+        } else {
+            Sqlite.Database.open (path, out this.db);
+        }
+        if (this.db.errcode () != Sqlite.OK) {
+            var msg = _("Error while opening SQLite database %s: %s");
+            throw new DatabaseError.OPEN (msg, path, this.db.errmsg ());
+        }
 
-        debug ("Using database file %s", db_file);
+        debug ("Using database file %s", path);
 
         this.exec ("PRAGMA synchronous = OFF");
-        this.exec ("PRAGMA temp_store = MEMORY");
         this.exec ("PRAGMA count_changes = OFF");
 
+        if (Flags.SHARED in flags) {
+            this.exec ("PRAGMA journal_mode = WAL");
+        } else {
+            this.exec ("PRAGMA temp_store = MEMORY");
+        }
+
         this.db.create_function ("contains",
                                  2,
                                  Sqlite.UTF8,
@@ -156,12 +195,6 @@ public class Rygel.Database.Database : SqliteWrapper {
     public void exec (string        sql,
                       GLib.Value[]? arguments = null)
                       throws DatabaseError {
-        if (arguments == null) {
-            this.throw_if_code_is_error (this.db.exec (sql));
-
-            return;
-        }
-
         var cursor = this.exec_cursor (sql, arguments);
         while (cursor.has_next ()) {
             cursor.next ();
diff --git a/src/librygel-db/filelist.am b/src/librygel-db/filelist.am
index b0dd254..9abd7c6 100644
--- a/src/librygel-db/filelist.am
+++ b/src/librygel-db/filelist.am
@@ -3,7 +3,6 @@ LIBRYGEL_DB_VAPI_SOURCE_FILES = \
        database-cursor.vala \
        database.vala \
        sql-function.vala \
-       sqlite-wrapper.vala \
        sql-operator.vala
 
 LIBRYGEL_DB_NONVAPI_SOURCE_FILES = \


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]