Commit de38e53b authored by Adrien Plazas's avatar Adrien Plazas
Browse files

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
parent 002cab84
......@@ -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 \
......
// This file is part of GNOME Games. License: GPL-3.0+.
private errordomain Games.DatabaseError {
COULDNT_OPEN,
EXECUTION_FAILED,
PREPARATION_FAILED,
BINDING_FAILED,
}
// 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;
}
}
// 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);
}
}
// 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);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment