From 0b3c459482f3670b235cc92ce94b7a02e337e968 Mon Sep 17 00:00:00 2001 From: sergiotarxz Date: Sat, 27 Nov 2021 23:43:39 +0100 Subject: [PATCH] Adding initial database support. --- include/openmg/database.h | 23 +++++ include/openmg/database/migrations.h | 10 ++ include/openmg/database/statement.h | 15 +++ meson.build | 8 +- src/database/.statement.c.swp | Bin 0 -> 20480 bytes src/database/statement.c | 142 +++++++++++++++++++++++++++ 6 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 include/openmg/database.h create mode 100644 include/openmg/database/migrations.h create mode 100644 include/openmg/database/statement.h create mode 100644 src/database/.statement.c.swp create mode 100644 src/database/statement.c 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 0000000000000000000000000000000000000000..c82ae39ff615b305097487ff46487be3a74aa350 GIT binary patch literal 20480 zcmeI4TWB0r7{`y+da3n-g6M;Kj952ulT<6Bt*LI3ZCp)ulu3V!eXmlZc{dMMM;<{?Bb@HknP677WT+_+^-x zGw1T1?|kR-eWbK}ZDx#K+IJDb?_@&uzr532)W3}Uu#OPVa;tWOy_o%1G3%x`dlLTk zPLW}M-E^v^Ync_x?f2Yrf5r68lIdCfo^SeA-E#cC@*J|$NwfsC1m-1y6Ud5-E?mw& zIk)Q^dg>_?^ZHsR))LSX&=SxR&=SxR&=SxR&=SxR_-{+VZ!RKtp$SLIX7tGG5!0?m z$@`MLc29f1NZzY_+-dLSt-fdpXbETuXbETuXbETuXbETuXbETuXbETuXbCKU1k4H{ zJC+b~-SH?K{(rUq|NbOG_JI$90Tmp^&-z+6$FL)U|4K{-oFu-YGKkE4;umP*{B)A7$0scTc z-U1sz0jvgRf?tm#;?}48&ts*SP#wvOTaJ35b`N_2&@Oo!S6?- zp5RSzA83IJI2|koe=jEF0QeK^2d{(2!FDhOmVxhapz=1@2{wT;xB#3Ee!^kOhhQhz z0XBeZz)J8V4p_bbpMa0RKJYHs0g9j>ECoxzao~VD$cfV}7H?sf>E?!AA!Hk&_<5UZ zwr{O4rfkQo*|%FX;aRn*-qoI8_q$i|BvqqavrN}$ly0`lK20o>Ng7)m%k7ql#;U_I zs-vKSI%p5eiVo1R5o0)2Obw_5Je)zs#HB?B55rl*o729hzJXB~T zCkpP7AJDBNrXiv^tV!%wLb%B-qWa-g4xwR-anN8#A6yI^>xNrN&Y8BiW(fe zDQ$xzNyAYT87POV&CvpFbb{%WVP`}S$P$IVg%)I%A{SiUXrMK->f7OJ8n<2Z(loBj zF{WMWD;s&CgynpI$;R}&WCvrFRR%kgE{MTWmGhGL&fwiytEnM@B0}L9UxS7)v8p=Ht1;|Dlw4dlo{pK3!*;QBT{$+r)6fd`MH(6=nEsHD zo5K(RA51f3pq3tl6)bKoP*nyF(s@-cQ2cvt9FoMp zt!ZHuPA#WZht3gfFVbr=*)%t77!HBP2DMDa8;2y!C^v>;XV8r{idIb5@VYNs7i295 zgLtfVD6rZHW*2i1mK02iZVOu`Bc@8M;^*202yf&Kd~!1n*xGVY2RP7cBuT0WAS70WAS70WAS70WAS7 z0WAS70WAS7fd!VpwhjkswqwIT8+X{ikNemG9ozqJhmZJt_?FrJza*RT7xw=Lz|Y`0 z;DJ8y9sKyugGn$5dcjigHGKEaf+DyQB*F1uAAI)Dflc5lum+^TW#B0A9sKtDz^lLq zmw}VO=kVL_0*`?zD1ssI8~pZPgRj7s;0v%9JOb_lCBXdqi^2Qw-#-rS2IF85FrWT! z@Zs+PFMzv&2L?b7I0Nj45C1jr3U~>;2p$C+z#4EK_ya!tJ>WI)6u1N21ae>ujDjn{ ziC_K zaNtKh4$M!$A0vdpwVkT+#Pc(Ab*#_)*;IUd&Hyc3I|^r$k-LT}pEL9Miq`{y-@jx# z6~nh~#mHs{?n#P!>((Td?#kW^lPaTPK9wzG5L+SrS2IsBamE|1b8vLe;}ZCBK9B9d z_wmUhb?InjSOtAm$?`_imA-A(#{XsHiE{g(bHs75axb?Wc(f5O!+T2g3GMd)F-a+dPC;Dnk@6e8>35PUqB$rjUjS<#WTJT8H! zM}}bM0EI;*`SC#{?4-Zll_(!+YAotaNyf z4)0muKsaR%b$Ac|uUCOna<0*2I=lyArw0%3Ve`TvN5#w<=EHKH9_quNu}SSPVqKWK zdq${B5FJWb5$boy4LewDh$=vb`|y86CjxY3kegWNw8sp!g8MF +#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) { +}