GnuCash 2.4.99
gnc-recurrence-sql.c
Go to the documentation of this file.
00001 /********************************************************************
00002  * gnc-recurrence-sql.c: load and save data to SQL                  *
00003  *                                                                  *
00004  * This program is free software; you can redistribute it and/or    *
00005  * modify it under the terms of the GNU General Public License as   *
00006  * published by the Free Software Foundation; either version 2 of   *
00007  * the License, or (at your option) any later version.              *
00008  *                                                                  *
00009  * This program is distributed in the hope that it will be useful,  *
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00012  * GNU General Public License for more details.                     *
00013  *                                                                  *
00014  * You should have received a copy of the GNU General Public License*
00015  * along with this program; if not, contact:                        *
00016  *                                                                  *
00017  * Free Software Foundation           Voice:  +1-617-542-5942       *
00018  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00019  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00020 \********************************************************************/
00029 #include "config.h"
00030 
00031 #include <glib.h>
00032 
00033 #include "qof.h"
00034 #include "gnc-engine.h"
00035 #include "Recurrence.h"
00036 
00037 #include "gnc-backend-sql.h"
00038 
00039 #include "gnc-recurrence-sql.h"
00040 
00041 #if defined( S_SPLINT_S )
00042 #include "splint-defs.h"
00043 #endif
00044 
00045 /*@ unused @*/ static QofLogModule log_module = G_LOG_DOMAIN;
00046 
00047 #define TABLE_NAME "recurrences"
00048 #define TABLE_VERSION 1
00049 
00050 #define BUDGET_MAX_RECURRENCE_PERIOD_TYPE_LEN 2048
00051 
00052 typedef struct
00053 {
00054     /*@ dependent @*/ GncSqlBackend* be;
00055     /*@ dependent @*/
00056     const GncGUID* guid;
00057     /*@ dependent @*/
00058     Recurrence* pRecurrence;
00059 } recurrence_info_t;
00060 
00061 static /*@ null @*/ gpointer get_obj_guid( gpointer pObject );
00062 static void set_obj_guid( void );
00063 static gint get_recurrence_mult( gpointer pObject );
00064 static void set_recurrence_mult( gpointer pObject, gint value );
00065 static /*@ null @*/ gpointer get_recurrence_period_type( gpointer pObject );
00066 static void set_recurrence_period_type( gpointer pObject, /*@ null @*/ gpointer pValue );
00067 static /*@ dependent @*//*@ null @*/ gpointer get_recurrence_period_start( gpointer pObject );
00068 static void set_recurrence_period_start( gpointer pObject, /*@ null @*/ gpointer pValue );
00069 
00070 static const GncSqlColumnTableEntry col_table[] =
00071 {
00072     /*@ -full_init_block @*/
00073     { "id",                      CT_INT,    0,                                     COL_PKEY | COL_NNUL | COL_AUTOINC },
00074     {
00075         "obj_guid",                CT_GUID,   0,                                     COL_NNUL, NULL, NULL,
00076         (QofAccessFunc)get_obj_guid, (QofSetterFunc)set_obj_guid
00077     },
00078     {
00079         "recurrence_mult",         CT_INT,    0,                                     COL_NNUL, NULL, NULL,
00080         (QofAccessFunc)get_recurrence_mult, (QofSetterFunc)set_recurrence_mult
00081     },
00082     {
00083         "recurrence_period_type",  CT_STRING, BUDGET_MAX_RECURRENCE_PERIOD_TYPE_LEN, COL_NNUL, NULL, NULL,
00084         (QofAccessFunc)get_recurrence_period_type, set_recurrence_period_type
00085     },
00086     {
00087         "recurrence_period_start", CT_GDATE,  0,                                     COL_NNUL, NULL, NULL,
00088         (QofAccessFunc)get_recurrence_period_start, set_recurrence_period_start
00089     },
00090     { NULL }
00091     /*@ +full_init_block @*/
00092 };
00093 
00094 /* Special column table because we need to be able to access the table by
00095 a column other than the primary key */
00096 static const GncSqlColumnTableEntry guid_col_table[] =
00097 {
00098     /*@ -full_init_block @*/
00099     {
00100         "obj_guid", CT_GUID, 0, 0, NULL, NULL,
00101         (QofAccessFunc)get_obj_guid, (QofSetterFunc)set_obj_guid
00102     },
00103     { NULL }
00104     /*@ +full_init_block @*/
00105 };
00106 
00107 /* ================================================================= */
00108 
00109 static /*@ null @*/ gpointer
00110 get_obj_guid( gpointer pObject )
00111 {
00112     recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
00113 
00114     g_return_val_if_fail( pObject != NULL, NULL );
00115 
00116     return (gpointer)pInfo->guid;
00117 }
00118 
00119 static void
00120 set_obj_guid( void )
00121 {
00122     // Nowhere to put the GncGUID
00123 }
00124 
00125 static gint
00126 get_recurrence_mult( gpointer pObject )
00127 {
00128     recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
00129 
00130     g_return_val_if_fail( pObject != NULL, 0 );
00131     g_return_val_if_fail( pInfo->pRecurrence != NULL, 0 );
00132 
00133     return (gint)pInfo->pRecurrence->mult;
00134 }
00135 
00136 static void
00137 set_recurrence_mult( gpointer pObject, gint value )
00138 {
00139     recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
00140 
00141     g_return_if_fail( pObject != NULL );
00142     g_return_if_fail( pInfo->pRecurrence != NULL );
00143 
00144     pInfo->pRecurrence->mult = (guint16)value;
00145 }
00146 
00147 static /*@ null @*/ gpointer
00148 get_recurrence_period_type( gpointer pObject )
00149 {
00150     recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
00151 
00152     g_return_val_if_fail( pObject != NULL, NULL );
00153     g_return_val_if_fail( pInfo->pRecurrence != NULL, NULL );
00154 
00155     return (gpointer)recurrencePeriodTypeToString(
00156                recurrenceGetPeriodType( pInfo->pRecurrence ) );
00157 }
00158 
00159 static void
00160 set_recurrence_period_type( gpointer pObject, gpointer pValue )
00161 {
00162     recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
00163 
00164     g_return_if_fail( pObject != NULL );
00165     g_return_if_fail( pInfo->pRecurrence != NULL );
00166     g_return_if_fail( pValue != NULL );
00167 
00168     pInfo->pRecurrence->ptype = recurrencePeriodTypeFromString( (gchar*)pValue );
00169 }
00170 
00171 static /*@ dependent @*//*@ null @*/ gpointer
00172 get_recurrence_period_start( gpointer pObject )
00173 {
00174     recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
00175     static GDate date;
00176 
00177     g_return_val_if_fail( pObject != NULL, NULL );
00178     g_return_val_if_fail( pInfo->pRecurrence != NULL, NULL );
00179 
00180     date = recurrenceGetDate( pInfo->pRecurrence );
00181     return (gpointer)&date;
00182 }
00183 
00184 static void
00185 set_recurrence_period_start( gpointer pObject, gpointer pValue )
00186 {
00187     recurrence_info_t* pInfo = (recurrence_info_t*)pObject;
00188     GDate* date = (GDate*)pValue;
00189 
00190     g_return_if_fail( pObject != NULL );
00191     g_return_if_fail( pInfo->pRecurrence != NULL );
00192     g_return_if_fail( pValue != NULL );
00193 
00194     pInfo->pRecurrence->start = *date;
00195 }
00196 
00197 /* ================================================================= */
00198 
00199 gboolean
00200 gnc_sql_recurrence_save( GncSqlBackend* be, const GncGUID* guid, const Recurrence* r )
00201 {
00202     recurrence_info_t recurrence_info;
00203 
00204     g_return_val_if_fail( be != NULL, FALSE );
00205     g_return_val_if_fail( guid != NULL, FALSE );
00206     g_return_val_if_fail( r != NULL, FALSE );
00207 
00208     (void)gnc_sql_recurrence_delete( be, guid );
00209 
00210     recurrence_info.be = be;
00211     recurrence_info.guid = guid;
00212     recurrence_info.pRecurrence = (Recurrence*)r;
00213     return gnc_sql_do_db_operation( be, OP_DB_INSERT, TABLE_NAME,
00214                                     TABLE_NAME, &recurrence_info, col_table );
00215 }
00216 
00217 void
00218 gnc_sql_recurrence_save_list( GncSqlBackend* be, const GncGUID* guid, GList* schedule )
00219 {
00220     recurrence_info_t recurrence_info;
00221     GList* l;
00222 
00223     g_return_if_fail( be != NULL );
00224     g_return_if_fail( guid != NULL );
00225 
00226     (void)gnc_sql_recurrence_delete( be, guid );
00227 
00228     recurrence_info.be = be;
00229     recurrence_info.guid = guid;
00230     for ( l = schedule; l != NULL; l = g_list_next( l ) )
00231     {
00232         recurrence_info.pRecurrence = (Recurrence*)l->data;
00233         (void)gnc_sql_do_db_operation( be, OP_DB_INSERT, TABLE_NAME,
00234                                        TABLE_NAME, &recurrence_info, col_table );
00235     }
00236 }
00237 
00238 gboolean
00239 gnc_sql_recurrence_delete( GncSqlBackend* be, const GncGUID* guid )
00240 {
00241     recurrence_info_t recurrence_info;
00242 
00243     g_return_val_if_fail( be != NULL, FALSE );
00244     g_return_val_if_fail( guid != NULL, FALSE );
00245 
00246     recurrence_info.be = be;
00247     recurrence_info.guid = guid;
00248     return gnc_sql_do_db_operation( be, OP_DB_DELETE, TABLE_NAME,
00249                                     TABLE_NAME, &recurrence_info, guid_col_table );
00250 }
00251 
00252 static void
00253 load_recurrence( GncSqlBackend* be, GncSqlRow* row, /*@ out @*/ Recurrence* r )
00254 {
00255     recurrence_info_t recurrence_info;
00256 
00257     g_return_if_fail( be != NULL );
00258     g_return_if_fail( row != NULL );
00259     g_return_if_fail( r != NULL );
00260 
00261     recurrence_info.be = be;
00262     recurrence_info.pRecurrence = r;
00263 
00264     gnc_sql_load_object( be, row, TABLE_NAME, &recurrence_info, col_table );
00265 }
00266 
00267 static /*@ null @*/ GncSqlResult*
00268 gnc_sql_set_recurrences_from_db( GncSqlBackend* be, const GncGUID* guid )
00269 {
00270     gchar* buf;
00271     gchar guid_buf[GUID_ENCODING_LENGTH+1];
00272     GncSqlStatement* stmt;
00273     GncSqlResult* result;
00274 
00275     g_return_val_if_fail( be != NULL, NULL );
00276     g_return_val_if_fail( guid != NULL, NULL );
00277 
00278     (void)guid_to_string_buff( guid, guid_buf );
00279     buf = g_strdup_printf( "SELECT * FROM %s WHERE obj_guid='%s'", TABLE_NAME, guid_buf );
00280     stmt = gnc_sql_connection_create_statement_from_sql( be->conn, buf );
00281     g_free( buf );
00282     result = gnc_sql_execute_select_statement( be, stmt );
00283     gnc_sql_statement_dispose( stmt );
00284     return result;
00285 }
00286 
00287 /*@ null @*/ Recurrence*
00288 gnc_sql_recurrence_load( GncSqlBackend* be, const GncGUID* guid )
00289 {
00290     GncSqlResult* result;
00291     Recurrence* r = NULL;
00292 
00293     g_return_val_if_fail( be != NULL, NULL );
00294     g_return_val_if_fail( guid != NULL, NULL );
00295 
00296     result = gnc_sql_set_recurrences_from_db( be, guid );
00297     if ( result != NULL )
00298     {
00299         guint numRows = gnc_sql_result_get_num_rows( result );
00300 
00301         if ( numRows > 0 )
00302         {
00303             if ( numRows > 1 )
00304             {
00305                 g_warning( "More than 1 recurrence found: first one used" );
00306             }
00307             r = g_new0( Recurrence, 1 );
00308             g_assert( r != NULL );
00309             load_recurrence( be, gnc_sql_result_get_first_row( result ), r );
00310         }
00311         else
00312         {
00313             g_warning( "No recurrences found" );
00314         }
00315         gnc_sql_result_dispose( result );
00316     }
00317 
00318     return r;
00319 }
00320 
00321 /*@ null @*/ GList*
00322 gnc_sql_recurrence_load_list( GncSqlBackend* be, const GncGUID* guid )
00323 {
00324     GncSqlResult* result;
00325     GList* list = NULL;
00326 
00327     g_return_val_if_fail( be != NULL, NULL );
00328     g_return_val_if_fail( guid != NULL, NULL );
00329 
00330     result = gnc_sql_set_recurrences_from_db( be, guid );
00331     if ( result != NULL )
00332     {
00333         GncSqlRow* row = gnc_sql_result_get_first_row( result );
00334 
00335         while ( row != NULL )
00336         {
00337             Recurrence* pRecurrence = g_new0( Recurrence, 1 );
00338             g_assert( pRecurrence != NULL );
00339             load_recurrence( be, row, pRecurrence );
00340             list = g_list_append( list, pRecurrence );
00341             row = gnc_sql_result_get_next_row( result );
00342         }
00343         gnc_sql_result_dispose( result );
00344     }
00345 
00346     return list;
00347 }
00348 
00349 /* ================================================================= */
00350 static void
00351 create_recurrence_tables( GncSqlBackend* be )
00352 {
00353     gint version;
00354 
00355     g_return_if_fail( be != NULL );
00356 
00357     version = gnc_sql_get_table_version( be, TABLE_NAME );
00358     if ( version == 0 )
00359     {
00360         (void)gnc_sql_create_table( be, TABLE_NAME, TABLE_VERSION, col_table );
00361     }
00362 }
00363 
00364 /* ================================================================= */
00365 void
00366 gnc_sql_init_recurrence_handler( void )
00367 {
00368     static GncSqlObjectBackend be_data =
00369     {
00370         GNC_SQL_BACKEND_VERSION,
00371         GNC_ID_ACCOUNT,
00372         NULL,                           /* commit - cannot occur */
00373         NULL,                           /* initial_load - cannot occur */
00374         create_recurrence_tables,       /* create_tables */
00375         NULL,                           /* compile_query */
00376         NULL,                           /* run_query */
00377         NULL,                           /* free_query */
00378         NULL                            /* write */
00379     };
00380 
00381     (void)qof_object_register_backend( TABLE_NAME, GNC_SQL_BACKEND, &be_data );
00382 }
00383 /* ========================== END OF FILE ===================== */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines