[gnome-games] Add the database module



commit de38e53b284ac26b35483a605892992e2ee45d6b
Author: Adrien Plazas <kekun plazas laposte net>
Date:   Fri Jul 14 13:46:20 2017 +0200

    Add the database module
    
    This will be used in the next commit to store game URIs added by the
    user.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=782824

 src/Makefile.am                         |    5 ++
 src/database/database-error.vala        |    8 +++
 src/database/database-uri-iterator.vala |   27 ++++++++++
 src/database/database-uri-source.vala   |   13 +++++
 src/database/database.vala              |   85 +++++++++++++++++++++++++++++++
 5 files changed, 138 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index a782809..026300b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -63,6 +63,11 @@ gnome_games_SOURCES = \
        core/uri-iterator.vala \
        core/uri-source.vala \
        \
+       database/database.vala \
+       database/database-error.vala \
+       database/database-uri-iterator.vala \
+       database/database-uri-source.vala \
+       \
        dummy/dummy-cover.vala \
        dummy/dummy-game.vala \
        dummy/dummy-icon.vala \
diff --git a/src/database/database-error.vala b/src/database/database-error.vala
new file mode 100644
index 0000000..279107e
--- /dev/null
+++ b/src/database/database-error.vala
@@ -0,0 +1,8 @@
+// This file is part of GNOME Games. License: GPL-3.0+.
+
+private errordomain Games.DatabaseError {
+       COULDNT_OPEN,
+       EXECUTION_FAILED,
+       PREPARATION_FAILED,
+       BINDING_FAILED,
+}
diff --git a/src/database/database-uri-iterator.vala b/src/database/database-uri-iterator.vala
new file mode 100644
index 0000000..83928a8
--- /dev/null
+++ b/src/database/database-uri-iterator.vala
@@ -0,0 +1,27 @@
+// This file is part of GNOME Games. License: GPL-3.0+.
+
+private class Games.DatabaseUriIterator : Object, UriIterator {
+       private const string SELECT_GAME_RESOURCE_QUERY = """
+               SELECT uri FROM game_resources;
+       """;
+
+       private Sqlite.Statement statement;
+       private Uri? uri;
+
+       internal DatabaseUriIterator (Sqlite.Database database) {
+               statement = Database.prepare (database, SELECT_GAME_RESOURCE_QUERY);
+       }
+
+       public new Uri? get () {
+               return uri;
+       }
+
+       public bool next () {
+               if (statement.step () != Sqlite.ROW)
+                       return false;
+
+               uri = new Uri (statement.column_text (0));
+
+               return true;
+       }
+}
diff --git a/src/database/database-uri-source.vala b/src/database/database-uri-source.vala
new file mode 100644
index 0000000..5d56529
--- /dev/null
+++ b/src/database/database-uri-source.vala
@@ -0,0 +1,13 @@
+// This file is part of GNOME Games. License: GPL-3.0+.
+
+private class Games.DatabaseUriSource : Object, UriSource {
+       private unowned Sqlite.Database database;
+
+       public DatabaseUriSource (Sqlite.Database database) {
+               this.database = database;
+       }
+
+       public UriIterator iterator () {
+               return new DatabaseUriIterator (database);
+       }
+}
diff --git a/src/database/database.vala b/src/database/database.vala
new file mode 100644
index 0000000..1cc0d3a
--- /dev/null
+++ b/src/database/database.vala
@@ -0,0 +1,85 @@
+// This file is part of GNOME Games. License: GPL-3.0+.
+
+private class Games.Database : Object {
+       private Sqlite.Database database;
+
+       private const string CREATE_TABLE_QUERY = """
+               CREATE TABLE IF NOT EXISTS game_resources (
+                       id INTEGER PRIMARY KEY NOT NULL,
+                       uri TEXT NOT NULL
+               );
+       """;
+
+       private const string ADD_GAME_RESOURCE_QUERY = """
+               INSERT INTO game_resources (id, uri) VALUES (NULL, $URI);
+       """;
+
+       private const string HAS_URI_QUERY = """
+               SELECT EXISTS (SELECT 1 FROM game_resources WHERE uri=$URI LIMIT 1);
+       """;
+
+       public Database (string path) throws Error {
+               if (Sqlite.Database.open (path, out database) != Sqlite.OK)
+                       throw new DatabaseError.COULDNT_OPEN ("Couldn’t open the database for “%s”.", path);
+
+               create_tables ();
+       }
+
+       public void add_uri (Uri uri) throws Error {
+               if (has_uri (uri))
+                       return;
+
+               var statement = prepare (database, ADD_GAME_RESOURCE_QUERY);
+
+               bind_text (statement, "$URI", uri.to_string ());
+
+               if (statement.step () != Sqlite.DONE)
+                       throw new DatabaseError.EXECUTION_FAILED ("Execution failed.");
+       }
+
+       public bool has_uri (Uri uri) {
+               var statement = prepare (database, HAS_URI_QUERY);
+
+               bind_text (statement, "$URI", uri.to_string ());
+
+               switch (statement.step ()) {
+               case Sqlite.ROW:
+                       return statement.column_text (0) == "1";
+               default:
+                       debug ("Execution failed.");
+
+                       return false;
+               }
+       }
+
+       public DatabaseUriSource get_uri_source () {
+               return new DatabaseUriSource (database);
+       }
+
+       private void create_tables () throws Error {
+               exec (CREATE_TABLE_QUERY, null);
+       }
+
+       private void exec (string query, Sqlite.Callback? callback) throws Error {
+               string error_message;
+
+               if (database.exec (query, callback, out error_message) != Sqlite.OK)
+                       throw new DatabaseError.EXECUTION_FAILED ("Execution failed: %s", error_message);
+       }
+
+       internal static Sqlite.Statement prepare (Sqlite.Database database, string query) throws Error {
+               Sqlite.Statement statement;
+               if (database.prepare_v2 (query, query.length, out statement) != Sqlite.OK)
+                       throw new DatabaseError.PREPARATION_FAILED ("Preparation failed: %s", database.errmsg 
());
+
+               return statement;
+       }
+
+       internal static void bind_text (Sqlite.Statement statement, string parameter, string text) throws 
Error {
+               var position = statement.bind_parameter_index (parameter);
+               if (position <= 0)
+                       throw new DatabaseError.BINDING_FAILED ("Couldn't bind text to the parameter “%s”, 
unexpected position: %d.", parameter, position);
+
+               statement.bind_text (position, text);
+       }
+}


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