diff --git a/include/openmg/database.h b/include/openmg/database.h new file mode 100644 index 0000000..cbd2fca --- /dev/null +++ b/include/openmg/database.h @@ -0,0 +1,23 @@ +#pragma once +#include + +#include + +G_BEGIN_DECLS; + +#define MG_TYPE_DATABASE mg_database_get_type() +G_DECLARE_FINAL_TYPE (MgDatabase, mg_database, MG, DATABASE, GObject) + +MgDatabase *mg_database_new (); + +MgDatabaseStatement * +mg_database_prepare (MgDatabase *self, char *z_sql, const char **pz_tail); + +int +mg_database_get_affected_rows (MgDatabase *self); + +char * +mg_database_get_error_string (MgDatabase *self); + +G_END_DECLS + diff --git a/include/openmg/database/migrations.h b/include/openmg/database/migrations.h new file mode 100644 index 0000000..f74f496 --- /dev/null +++ b/include/openmg/database/migrations.h @@ -0,0 +1,10 @@ +const char *const MIGRATIONS[] = { + ("CREATE TABLE options (\n" + "key TEXT PRIMARY KEY,\n" + "value TEXT\n" + ");\n"), + ("CREATE TABLE image (\n" + "url TEXT PRIMARY KEY,\n" + "file TEXT\n" + ");\n"), +}; diff --git a/include/openmg/database/statement.h b/include/openmg/database/statement.h new file mode 100644 index 0000000..ce5f9a6 --- /dev/null +++ b/include/openmg/database/statement.h @@ -0,0 +1,15 @@ +#pragma once +#include + +G_BEGIN_DECLS; + +#define MG_TYPE_DATABASE_STATEMENT mg_database_statement_get_type() +G_DECLARE_FINAL_TYPE (MgDatabaseStatement, mg_database_statement, MG, DATABASE_STATEMENT, GObject) + +MgDatabaseStatement *mg_database_statement_new (); + +void +mg_database_statement_bind_text (MgDatabaseStatement *self, int index, char *value); + +G_END_DECLS + diff --git a/meson.build b/meson.build index c624b87..852e4f5 100644 --- a/meson.build +++ b/meson.build @@ -8,7 +8,8 @@ openmgdeps = [ dependency('libsoup-2.4'), dependency('libxml-2.0'), dependency('libpcre2-8'), - dependency('gio-2.0') + dependency('gio-2.0'), + dependency('sqlite3') ] sources = [ @@ -26,11 +27,14 @@ sources = [ 'src/manga.c', 'src/chapter.c', 'src/backend/readmng.c', + 'src/database.c', + 'src/database/statement.c', 'src/main.c', ] link_arguments = [ - '-ldl' + '-ldl', + '-lm' ] executable('openmg', diff --git a/src/database/.statement.c.swp b/src/database/.statement.c.swp new file mode 100644 index 0000000..c82ae39 Binary files /dev/null and b/src/database/.statement.c.swp differ diff --git a/src/database/statement.c b/src/database/statement.c new file mode 100644 index 0000000..ab98fa7 --- /dev/null +++ b/src/database/statement.c @@ -0,0 +1,142 @@ +#include +#include + +#include +#include + +struct _MgDatabaseStatement { + GObject parent_instance; + MgDatabase *owner; + sqlite3_stmt *stmt; +}; + +G_DEFINE_TYPE (MgDatabaseStatement, mg_database_statement, G_TYPE_OBJECT) + +typedef enum { + MG_DATABASE_STATEMENT_OWNER, + MG_DATABASE_STATEMENT_STMT, + MG_DATABASE_STATEMENT_N_PROPERTIES +} MgDatabaseStatementProperties; + +static GParamSpec +*database_statement_properties[MG_DATABASE_STATEMENT_N_PROPERTIES] = { NULL, }; + +static void +mg_database_statement_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void +mg_database_statement_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void +mg_database_statement_dispose (GObject *object); + +MgDatabaseStatement * +mg_database_statement_new (MgDatabase *owner, sqlite3_stmt *statement) { + MgDatabaseStatement *self = NULL; + self = MG_DATABASE_STATEMENT ((g_object_new (MG_TYPE_DATABASE_STATEMENT, + "owner", owner, "stmt", statement))); + return self; +} + +static void +mg_database_statement_class_init (MgDatabaseStatementClass *class) { + GObjectClass *object_class = G_OBJECT_CLASS (class); + object_class->set_property = mg_database_statement_set_property; + object_class->get_property = mg_database_statement_get_property; + object_class->dispose = mg_database_statement_dispose; + database_statement_properties[MG_DATABASE_STATEMENT_OWNER] = g_param_spec_object ( + "owner", + "Owner", + "Owner MgDatabase.", + MG_TYPE_DATABASE_STATEMENT, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + database_statement_properties[MG_DATABASE_STATEMENT_STMT] = g_param_spec_pointer ( + "stmt", + "STMT", + "Statement pointer", + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_properties + (object_class, MG_DATABASE_STATEMENT_N_PROPERTIES, + database_statement_properties); +} + +static void +mg_database_statement_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { + MgDatabaseStatement *self = MG_DATABASE_STATEMENT (object); + switch ((MgDatabaseStatementProperties) property_id) { + case MG_DATABASE_STATEMENT_OWNER: + g_value_set_instance (value, self->owner); + break; + case MG_DATABASE_STATEMENT_STMT: + g_value_set_pointer (value, self->stmt); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +mg_database_statement_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { + MgDatabaseStatement *self = MG_DATABASE_STATEMENT (object); + switch ((MgDatabaseStatementProperties) property_id) { + case MG_DATABASE_STATEMENT_OWNER: + if (self->owner) { + g_clear_object (&(self->owner)); + } + self->owner = g_value_peek_pointer (value); + break; + case MG_DATABASE_STATEMENT_STMT: + if (self->stmt) { + sqlite3_finalize (self->stmt); + } + self->stmt = g_value_get_pointer (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static sqlite3_stmt * +mg_database_statement_get_stmt (MgDatabaseStatement *self) { + sqlite3_stmt *stmt; + GValue value = G_VALUE_INIT; + g_value_init (&value, G_TYPE_POINTER); + g_object_get_property (G_OBJECT (self), + "stmt", + &value); + stmt = g_value_get_pointer (&value); + g_value_unset (&value); + return stmt; +} + +static void +mg_database_statement_dispose (GObject *object) { + MgDatabaseStatement *self = MG_DATABASE_STATEMENT (object); + g_clear_object (&(self->owner)); + sqlite3_finalize (self->stmt); +} + +void +mg_database_statement_bind_text (MgDatabaseStatement *self, int index, char *value) { + sqlite3_stmt *stmt = mg_database_statement_get_stmt (self); + int error = sqlite3_bind_text (stmt, index, value, -1, SQLITE_TRANSIENT); + if ( error != SQLITE_OK ) { + g_error (mg_database_get_error_string (self->owner)); + } +} + +static void +mg_database_statement_init (MgDatabaseStatement *self) { +}