[shotwell/wip/phako/new-database: 3/3] WIP



commit 230dddf00e803474147af15a7d9387a7983ac84b
Author: Jens Georg <mail jensge org>
Date:   Sat Feb 22 09:51:53 2020 +0100

    WIP

 src/db/DatabaseTable.vala               |   8 ++-
 src/db/VideoTable.vala                  | 114 ++++++++++++--------------------
 src/db/librygel-db/database-cursor.vala |   6 +-
 src/db/librygel-db/database.vala        |  15 +++--
 src/db/librygel-db/row.vala             |  42 ++++++++++++
 src/meson.build                         |   1 +
 6 files changed, 102 insertions(+), 84 deletions(-)
---
diff --git a/src/db/DatabaseTable.vala b/src/db/DatabaseTable.vala
index 6bac30e8..af7ddb6e 100644
--- a/src/db/DatabaseTable.vala
+++ b/src/db/DatabaseTable.vala
@@ -85,12 +85,12 @@ public abstract class DatabaseTable {
     
     // XXX: errmsg() is global, and so this will not be accurate in a threaded situation
     protected static void fatal(string op, int res) {
-        error("%s: [%d] %s", op, res, db.errmsg());
+        //error("%s: [%d] %s", op, res, db.errmsg());
     }
     
     // XXX: errmsg() is global, and so this will not be accurate in a threaded situation
     protected static void warning(string op, int res) {
-        GLib.warning("%s: [%d] %s", op, res, db.errmsg());
+        //GLib.warning("%s: [%d] %s", op, res, db.errmsg());
     }
     
     protected void set_table_name(string table_name) {
@@ -175,7 +175,9 @@ public abstract class DatabaseTable {
     
     // Caller needs to bind value #1 before calling execute_update_by_id()
     private void prepare_update_by_id(int64 id, string column, out Sqlite.Statement stmt) {
-        string sql = "UPDATE %s SET %s=? WHERE id=?".printf(table_name, column);
+        try {
+            string sql = "UPDATE %s SET %s=? WHERE id=?".printf(table_name, column);
+            db.exec (sql, {(Value) id
         
         int res = db.prepare_v2(sql, -1, out stmt);
         assert(res == Sqlite.OK);
diff --git a/src/db/VideoTable.vala b/src/db/VideoTable.vala
index 8f7cfa6f..86127013 100644
--- a/src/db/VideoTable.vala
+++ b/src/db/VideoTable.vala
@@ -102,7 +102,7 @@ public class VideoTable : DatabaseTable {
        
     // VideoRow.video_id, event_id, time_created are ignored on input. All fields are set on exit
     // with values stored in the database.
-    public VideoID add(VideoRow video_row) throws DatabaseError {
+    public VideoID add(VideoRow video_row) throws Rygel.Database.DatabaseError {
         db.exec(
             "INSERT INTO VideoTable (filename, width, height, clip_duration, is_interpretable, "
             + "filesize, timestamp, exposure_time, import_id, event_id, md5, time_created, title, comment) "
@@ -171,91 +171,63 @@ public class VideoTable : DatabaseTable {
         return false;
     }
 
+    private VideoRow? row_from_db (Rygel.Database.Row row) throws Rygel.Database.DatabaseError {
+        VideoRow video_row = new VideoRow();
+        video_row.video_id.id = row.at<int64> (0);
+        video_row.filepath = row.at<string> (1);
+        video_row.width = row.at<int> (2);
+        video_row.height = row.at<int> (3);
+        video_row.clip_duration = row.at<double> (4);
+        video_row.is_interpretable = row.at<bool> (5);
+        video_row.filesize = row.at<int64> (6);
+        video_row.timestamp = (time_t) row.at<int64> (7);
+        video_row.exposure_time = (time_t) row.at<int64> (8);
+        video_row.import_id.id = row.at<int64> (9);
+        video_row.event_id.id = row.at<int64> (10);
+        video_row.md5 = row.at<string> (11);
+        video_row.time_created = (time_t) row.at<int64> (12);
+        video_row.rating = Rating.unserialize(row.at<int> (13));
+        video_row.title = row.at<string> (14);
+        video_row.backlinks = row.at<string> (15);
+        video_row.time_reimported = (time_t) row.at<int64>( 16);
+        video_row.flags = row.at<int64> (17);
+        video_row.comment = row.at<string> (18);
+
+        return video_row;
+    }
+
     public VideoRow? get_row(VideoID video_id) {
         try {
             var cursor = db.exec_cursor(
-            "SELECT filename, width, height, clip_duration, is_interpretable, filesize, timestamp, "
+            "SELECT id, filename, width, height, clip_duration, is_interpretable, filesize, timestamp, "
             + "exposure_time, import_id, event_id, md5, time_created, rating, title, backlinks, "
             + "time_reimported, flags, comment FROM VideoTable WHERE id=?",
             {(GLib.Value) video_id.id});
-            var column = 0;
-            VideoRow = new VideoRow();
-            row.video_id = cursor.next();
+            var video_row  = row_from_db (cursor.next());
+            video_row.video_id = video_id;
+
+            return video_row;
         } catch (Rygel.Database.DatabaseError err) {
             return null;
         }
-
-        Sqlite.Statement stmt;
-        int res = db.prepare_v2, 
-            -1, out stmt);
-        assert(res == Sqlite.OK);
-        
-        res = stmt.bind_int64(1, video_id.id);
-        assert(res == Sqlite.OK);
-        
-        if (stmt.step() != Sqlite.ROW)
-            return null;
-        
-        VideoRow row = new VideoRow();
-        row.video_id = video_id;
-        row.filepath = stmt.column_text(0);
-        row.width = stmt.column_int(1);
-        row.height = stmt.column_int(2);
-        row.clip_duration = stmt.column_double(3);
-        row.is_interpretable = (stmt.column_int(4) == 1);
-        row.filesize = stmt.column_int64(5);
-        row.timestamp = (time_t) stmt.column_int64(6);
-        row.exposure_time = (time_t) stmt.column_int64(7);
-        row.import_id.id = stmt.column_int64(8);
-        row.event_id.id = stmt.column_int64(9);
-        row.md5 = stmt.column_text(10);
-        row.time_created = (time_t) stmt.column_int64(11);
-        row.rating = Rating.unserialize(stmt.column_int(12));
-        row.title = stmt.column_text(13);
-        row.backlinks = stmt.column_text(14);
-        row.time_reimported = (time_t) stmt.column_int64(15);
-        row.flags = stmt.column_int64(16);
-        row.comment = stmt.column_text(17);
-        
-        return row;
     }
     
     public Gee.ArrayList<VideoRow?> get_all() {
-        Sqlite.Statement stmt;
-        int res = db.prepare_v2(
+        var all = new Gee.ArrayList<VideoRow?>();
+
+        try {
+            var cursor = db.exec_cursor(
             "SELECT id, filename, width, height, clip_duration, is_interpretable, filesize, "
             + "timestamp, exposure_time, import_id, event_id, md5, time_created, rating, title, "
-            + "backlinks, time_reimported, flags, comment FROM VideoTable", 
-            -1, out stmt);
-        assert(res == Sqlite.OK);
-        
-        Gee.ArrayList<VideoRow?> all = new Gee.ArrayList<VideoRow?>();
-        
-        while ((res = stmt.step()) == Sqlite.ROW) {
-            VideoRow row = new VideoRow();
-            row.video_id.id = stmt.column_int64(0);
-            row.filepath = stmt.column_text(1);
-            row.width = stmt.column_int(2);
-            row.height = stmt.column_int(3);
-            row.clip_duration = stmt.column_double(4);
-            row.is_interpretable = (stmt.column_int(5) == 1);
-            row.filesize = stmt.column_int64(6);
-            row.timestamp = (time_t) stmt.column_int64(7);
-            row.exposure_time = (time_t) stmt.column_int64(8);
-            row.import_id.id = stmt.column_int64(9);
-            row.event_id.id = stmt.column_int64(10);
-            row.md5 = stmt.column_text(11);
-            row.time_created = (time_t) stmt.column_int64(12);
-            row.rating = Rating.unserialize(stmt.column_int(13));
-            row.title = stmt.column_text(14);
-            row.backlinks = stmt.column_text(15);
-            row.time_reimported = (time_t) stmt.column_int64(16);
-            row.flags = stmt.column_int64(17);
-            row.comment = stmt.column_text(18);
-            
-            all.add(row);
+            + "backlinks, time_reimported, flags, comment FROM VideoTable");
+
+            foreach (var row in cursor) {
+                all.add (row_from_db (row));
+            }
+        } catch (Rygel.Database.DatabaseError err) {
+            GLib.warning ("Error querying database for video rows: %s", err.message);
         }
-        
+
         return all;
     }
     
diff --git a/src/db/librygel-db/database-cursor.vala b/src/db/librygel-db/database-cursor.vala
index 682f7cfc..1d9bfd3e 100644
--- a/src/db/librygel-db/database-cursor.vala
+++ b/src/db/librygel-db/database-cursor.vala
@@ -133,12 +133,12 @@ public class Rygel.Database.Cursor : Object {
      *
      * @return a pointer to the current row
      */
-    public Statement* next () throws DatabaseError {
+    public Row next () throws DatabaseError {
         this.has_next ();
         this.throw_if_code_is_error (this.current_state);
         this.dirty = true;
 
-        return this.statement;
+        return new Row (this.statement);
     }
 
     // convenience functions for "foreach"
@@ -163,7 +163,7 @@ public class Rygel.Database.Cursor : Object {
             return this.cursor.has_next ();
         }
 
-        public unowned Statement @get () throws DatabaseError {
+        public Row @get () throws DatabaseError {
             return this.cursor.next ();
         }
     }
diff --git a/src/db/librygel-db/database.vala b/src/db/librygel-db/database.vala
index 6fa34b67..9fd45106 100644
--- a/src/db/librygel-db/database.vala
+++ b/src/db/librygel-db/database.vala
@@ -25,11 +25,12 @@ using Sqlite;
 namespace Rygel.Database {
 
     public errordomain DatabaseError {
-        SQLITE_ERROR, /// Error code translated from SQLite
-        OPEN,         /// Error while opening database file
-        PREPARE,      /// Error while preparing a statement
-        BIND,         /// Error while binding values to a statement
-        STEP          /// Error while running through a result set
+        SQLITE_ERROR,  /// Error code translated from SQLite
+        OPEN,          /// Error while opening database file
+        PREPARE,       /// Error while preparing a statement
+        BIND,          /// Error while binding values to a statement
+        STEP,          /// Error while running through a result set
+        OUT_OF_RANGE   /// Range error while iterating through columns
     }
 
     public enum Flavor {
@@ -269,8 +270,8 @@ public class Rygel.Database.Database : Object, Initable {
                              GLib.Value[]? args = null)
                              throws DatabaseError {
         var cursor = this.exec_cursor (sql, args);
-        var statement = cursor.next ();
-        return statement->column_int (0);
+        var row = cursor.next ();
+        return row.at<int> (0);
     }
 
     /**
diff --git a/src/db/librygel-db/row.vala b/src/db/librygel-db/row.vala
new file mode 100644
index 00000000..d6a8e62a
--- /dev/null
+++ b/src/db/librygel-db/row.vala
@@ -0,0 +1,42 @@
+using Sqlite;
+
+public class Rygel.Database.Row : Object {
+    private Statement *statement;
+    internal Row (Statement *statement) {
+        this.statement = statement;
+    }
+
+    public T at<T>(int index) throws DatabaseError {
+        if (index >= statement->column_count ()) {
+            throw new DatabaseError.OUT_OF_RANGE ("Query result only contains %d columns",
+                                                  statement->column_count ());
+        }
+        if (typeof (T) == typeof (int64) ||
+            typeof (T) == typeof (uint64) ||
+            typeof (T) == typeof (int) ||
+            typeof (T) == typeof (uint) ||
+            typeof (T) == typeof (long) ||
+            typeof (T) == typeof (ulong)) {
+            return (T) statement->column_int64 (index);
+        }
+
+        if (typeof (T) == typeof (float) ||
+            typeof (T) == typeof (double)) {
+            return (T) statement->column_double (index);
+        }
+
+        if (typeof (T) == typeof (string)) {
+            return statement->column_text (index).dup ();
+        }
+
+        if (typeof (T) == typeof (void*)) {
+            return statement->column_blob (index);
+        }
+
+        if (typeof (T) == typeof (bool)) {
+            return statement->column_int (index) != 0;
+        }
+
+        assert_not_reached ();
+    }
+}
diff --git a/src/meson.build b/src/meson.build
index f2d04457..78a1c14f 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -62,6 +62,7 @@ executable('shotwell',
             'db/librygel-db/database.vala',
             'db/librygel-db/database-cursor.vala',
             'db/librygel-db/collate.c',
+            'db/librygel-db/row.vala',
             'db/Db.vala',
             'db/DatabaseTable.vala',
             'db/PhotoTable.vala',


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