|
GnuCash 2.4.99
|
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 ===================== */
1.7.4