|
gpe-expenses 0.1.7
|
00001 /*************************************************************************** 00002 * qof-main.c 00003 * 00004 * This is an auto-generated file. Patches are available from 00005 * http://qof-gen.sourceforge.net/ 00006 * 00007 * Thu Jan 13 10:55:44 2005 00008 * Copyright 2005-2009 Neil Williams 00009 * linux@codehelp.co.uk 00010 ****************************************************************************/ 00011 /* 00012 * This program is free software; you can redistribute it and/or modify 00013 * it under the terms of the GNU General Public License as published by 00014 * the Free Software Foundation; either version 2 of the License, or 00015 * (at your option) any later version. 00016 * 00017 * This program is distributed in the hope that it will be useful, 00018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 * GNU General Public License for more details. 00021 * 00022 * You should have received a copy of the GNU General Public License 00023 * along with this program; if not, write to the Free Software 00024 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00025 */ 00026 00038 #define _GNU_SOURCE 00039 #include "config.h" 00040 #include <glib.h> 00041 #include <glib/gi18n.h> 00042 #include <glib/gprintf.h> 00043 #include <qof.h> 00044 #include <stdlib.h> 00045 #include <stdio.h> 00046 #include <regex.h> 00047 #include <time.h> 00048 #include "qof-main.h" 00049 00050 #define MAX_LINE 79 00051 00052 /* the debugging module for this file. */ 00053 static QofLogModule log_module = QOF_MAIN_CLI; 00054 00055 void 00056 qof_main_wrap_line (FILE * fp, gint indent, 00057 const gchar * template, ...) 00058 { 00059 gint line_length, msg_length; 00060 va_list wraps; 00061 gchar *message; 00062 00063 line_length = MAX_LINE; 00064 /* note the modulus. Don't use CLAMP here */ 00065 /* indent != line_length or particularly close to it. */ 00066 indent = indent >= line_length ? indent % line_length : indent; 00067 indent = indent < 0 ? 0 : indent; 00068 message = NULL; 00069 g_return_if_fail (template); 00070 va_start (wraps, template); 00071 message = g_strdup_vprintf (template, wraps); 00072 va_end (wraps); 00073 g_return_if_fail (message); 00074 msg_length = strlen (message); 00075 while (msg_length > line_length) 00076 { 00077 gchar *chunk; 00078 gchar format[16]; 00079 00080 chunk = message + line_length - 1; 00081 while (chunk > message && !g_ascii_isspace (*chunk)) 00082 chunk--; 00083 if (chunk == message) 00084 break; /* give up */ 00085 while (chunk > (message + 1) && g_ascii_isspace (*chunk)) 00086 chunk--; 00087 chunk++; 00088 g_sprintf (format, "%%.%ds\n%%%ds", (gint) (chunk - message), 00089 indent); 00090 g_fprintf (fp, format, message, ""); 00091 message = chunk; 00092 while (g_ascii_isspace (*message) && *message) 00093 message++; 00094 msg_length = strlen (message); 00095 if (line_length == MAX_LINE) 00096 line_length -= indent; 00097 } 00098 if (msg_length) 00099 g_fprintf (fp, "%s\n", message); 00100 } 00101 00102 static void 00103 qof_main_run_sql (QofMainContext * context) 00104 { 00105 QofSqlQuery *q; 00106 QofBook *book; 00107 gchar *sql; 00108 00109 ENTER (" "); 00110 q = qof_sql_query_new (); 00111 sql = g_strdup (context->sql_str); 00112 book = qof_session_get_book (context->input_session); 00113 qof_sql_query_set_book (q, book); 00114 qof_sql_query_run (q, sql); 00115 context->query = qof_sql_query_get_query (q); 00116 LEAVE (" "); 00117 } 00118 00119 static void 00120 qof_main_run_query (QofMainContext * context) 00121 { 00122 QofBook *book; 00123 GList *results; 00124 00125 ENTER (" "); 00126 results = NULL; 00127 book = qof_session_get_book (context->input_session); 00128 qof_query_set_book (context->query, book); 00129 results = qof_query_run (context->query); 00130 if (results != NULL) 00131 qof_entity_copy_list (context->export_session, results); 00132 LEAVE (" "); 00133 } 00134 00135 void 00136 qof_main_free (QofMainContext * context) 00137 { 00138 g_free (context->filename); 00139 g_free (context->write_file); 00140 g_free (context->sql_file); 00141 g_free (context->database); 00142 g_free (context->category); 00143 } 00144 00145 static void 00146 find_param_cb (QofParam * param, gpointer user_data) 00147 { 00148 gchar * tmp; 00149 QofMainContext *context; 00150 QofQueryPredData *time_pred_data; 00151 00152 context = (QofMainContext *) user_data; 00153 if ((param->param_getfcn == NULL) || 00154 (param->param_setfcn == NULL)) 00155 return; 00156 if (0 == safe_strcmp (context->param_type, param->param_type)) 00157 { 00158 time_pred_data = qof_query_time_predicate (QOF_COMPARE_GTE, 00159 QOF_DATE_MATCH_NORMAL, context->min_qt); 00160 tmp = g_strdup (param->param_name); 00161 qof_query_add_term (context->query, 00162 qof_query_build_param_list (tmp, NULL), time_pred_data, QOF_QUERY_AND); 00163 time_pred_data = qof_query_time_predicate (QOF_COMPARE_LTE, 00164 QOF_DATE_MATCH_NORMAL, context->max_qt); 00165 qof_query_add_term (context->query, 00166 qof_query_build_param_list (tmp, NULL), time_pred_data, QOF_QUERY_AND); 00167 qof_main_run_query (context); 00168 qof_query_purge_terms (context->query, 00169 qof_query_build_param_list (tmp, QOF_ID_BOOK, QOF_TYPE_GUID, NULL)); 00170 PINFO (" param_name=%s added", tmp); 00171 } 00172 LEAVE (" "); 00173 } 00174 00175 /* takes one database name and runs -c and -t queries against it. */ 00176 static void 00177 build_database_list (QofIdTypeConst obj_type, QofMainContext * context) 00178 { 00179 if (!obj_type || !context) 00180 return; 00181 if (!qof_class_is_registered (obj_type)) 00182 return; 00183 ENTER (" object_type=%s", obj_type); 00184 context->query = qof_query_create_for (obj_type); 00185 if (context->category != NULL) 00186 { 00187 QofQueryPredData *category_pred; 00188 00189 category_pred = 00190 qof_query_string_predicate (QOF_COMPARE_EQUAL, 00191 context->category, QOF_STRING_MATCH_CASEINSENSITIVE, 00192 FALSE); 00193 qof_query_add_term (context->query, 00194 qof_query_build_param_list (CATEGORY_NAME, NULL), 00195 category_pred, QOF_QUERY_AND); 00196 } 00197 if (context->min_qt) 00198 { 00199 PINFO (" Preparing a time based queryset."); 00200 context->param_type = QOF_TYPE_TIME; 00201 qof_class_param_foreach (obj_type, find_param_cb, context); 00202 } 00203 else 00204 { 00205 qof_main_run_query (context); 00206 if (context->query) 00207 qof_query_clear (context->query); 00208 } 00209 LEAVE (" "); 00210 } 00211 00212 static void 00213 select_cb (QofObject * obj, gpointer data) 00214 { 00215 QofMainContext *context; 00216 00217 context = (QofMainContext *) data; 00218 g_return_if_fail (context); 00219 if (0 != safe_strcmp (context->exclude, obj->e_type)) 00220 build_database_list (obj->e_type, context); 00221 } 00222 00223 void 00224 qof_main_moderate_query (QofMainContext * context) 00225 { 00226 GSList *date_param_list, *category_param_list; 00227 gboolean all; 00228 00229 ENTER (" "); 00230 all = TRUE; 00231 context->query = qof_query_create (); 00232 date_param_list = NULL; 00233 category_param_list = NULL; 00234 while (context->sql_list) 00235 { 00236 PINFO ("running sql_list"); 00237 context->sql_str = g_strdup (context->sql_list->data); 00238 qof_main_run_sql (context); 00239 qof_main_run_query (context); 00240 if (context->query) 00241 qof_query_clear (context->query); 00242 g_free (context->sql_str); 00243 context->sql_str = NULL; 00244 all = FALSE; 00245 context->sql_list = g_list_next (context->sql_list); 00246 } 00247 if (0 < g_list_length (context->sql_list)) 00248 { 00249 context->sql_str = NULL; 00250 g_list_free (context->sql_list); 00251 all = FALSE; 00252 } 00253 if (context->sql_str != NULL) 00254 { 00255 PINFO ("running sql_str"); 00256 qof_main_run_sql (context); 00257 qof_main_run_query (context); 00258 if (context->query) 00259 qof_query_clear (context->query); 00260 all = FALSE; 00261 } 00262 if ((context->exclude != NULL) 00263 && (qof_class_is_registered (context->exclude))) 00264 { 00265 qof_object_foreach_type (select_cb, context); 00266 all = FALSE; 00267 } 00268 if ((context->database != NULL) 00269 && (qof_class_is_registered (context->database))) 00270 { 00271 build_database_list (context->database, context); 00272 all = FALSE; 00273 } 00274 if (all == TRUE) 00275 qof_object_foreach_type (select_cb, context); 00276 LEAVE (" "); 00277 } 00278 00279 static void 00280 option_cb (QofBackendOption * option, gpointer data) 00281 { 00282 QofMainContext *context; 00283 00284 context = (QofMainContext *) data; 00285 g_return_if_fail (context); 00286 /* Normally, I'd use GPOINTER_TO_INT but internally, 00287 the QofBackendOption uses gint64 which gets mangled by 00288 the 32-bit macro. */ 00289 ENTER (" compression=%" G_GINT64_FORMAT " encoding=%s", 00290 context->gz_level, context->encoding); 00291 if (0 == safe_strcmp (QSF_COMPRESS, option->option_name)) 00292 option->value = (gpointer) & context->gz_level; 00293 if (0 == safe_strcmp (QSF_ENCODING, option->option_name)) 00294 option->value = (gpointer) g_strdup(context->encoding); 00295 if (0 == safe_strcmp (QSF_DATE_CONVERT, option->option_name)) 00296 option->value = (gpointer) & context->convert; 00297 LEAVE (" "); 00298 } 00299 00300 void 00301 qof_mod_compression (gint64 gz_level, QofMainContext * context) 00302 { 00303 KvpFrame *be_config; 00304 QofBook *book; 00305 QofBackend *be; 00306 00307 ENTER (" compression=%" G_GINT64_FORMAT, gz_level); 00308 if ((gz_level > 0) && (gz_level <= 9)) 00309 { 00310 book = qof_session_get_book (context->export_session); 00311 be = qof_book_get_backend (book); 00312 be_config = qof_backend_get_config (be); 00313 context->gz_level = gz_level; 00314 qof_backend_option_foreach (be_config, option_cb, context); 00315 qof_backend_load_config (be, be_config); 00316 } 00317 LEAVE (" "); 00318 } 00319 00320 void 00321 qof_mod_encoding (const gchar * encoding, QofMainContext * context) 00322 { 00323 KvpFrame *be_config; 00324 QofBook *book; 00325 QofBackend *be; 00326 00327 ENTER (" encode to %s", encoding); 00328 book = qof_session_get_book (context->export_session); 00329 be = qof_book_get_backend (book); 00330 be_config = qof_backend_get_config (be); 00331 context->encoding = encoding; 00332 qof_backend_option_foreach (be_config, option_cb, context); 00333 qof_backend_load_config (be, be_config); 00334 LEAVE (" "); 00335 } 00336 00337 void 00338 qof_mod_convert_deprecated (gint64 convert, QofMainContext * context) 00339 { 00340 KvpFrame *be_config; 00341 QofBook *book; 00342 QofBackend *be; 00343 gboolean set; 00344 00345 set = (convert == 0) ? FALSE : TRUE; 00346 ENTER (" convert deprecated date values? %i No if 0.", set); 00347 book = qof_session_get_book (context->export_session); 00348 be = qof_book_get_backend (book); 00349 be_config = qof_backend_get_config (be); 00350 context->convert = convert; 00351 qof_backend_option_foreach (be_config, option_cb, context); 00352 qof_backend_load_config (be, be_config); 00353 LEAVE (" "); 00354 } 00355 00356 void 00357 qof_cmd_xmlfile (QofMainContext * context) 00358 { 00359 QofSession *input_session, *export_session; 00360 00361 ENTER (" "); 00362 input_session = context->input_session; 00363 if (0 == safe_strcmp (context->exclude, context->database) 00364 && (context->exclude != NULL)) 00365 { 00366 qof_main_wrap_line (stderr, ERR_INDENT, 00367 /* Translators: This line is wrapped by the program - 00368 please make sure you do NOT add line endings here. */ 00369 _("%s: Error: Cannot exclude database \"%s\" with option -e " 00370 "because option -d is set to include the database: \"%s\". " 00371 "Use the \'-l\' command to see the full list of supported " 00372 "databases.\n"), PACKAGE, context->exclude, 00373 context->database); 00374 qof_session_end (input_session); 00375 LEAVE (" conflicting options"); 00376 return; 00377 } 00378 qof_session_begin (input_session, context->filename, TRUE, FALSE); 00379 qof_main_show_error (input_session); 00380 if (0 != safe_strcmp (QOF_STDOUT, context->filename)) 00381 qof_session_load (input_session, NULL); 00382 qof_main_show_error (input_session); 00383 export_session = qof_session_new (); 00384 context->export_session = export_session; 00385 if (context->write_file) 00386 { 00387 qof_session_begin (export_session, context->write_file, TRUE, 00388 TRUE); 00389 qof_mod_compression (context->gz_level, context); 00390 } 00391 else 00392 qof_session_begin (export_session, QOF_STDOUT, TRUE, FALSE); 00393 qof_main_show_error (export_session); 00394 /* ensure encoding value is set in the new export_session */ 00395 qof_mod_encoding (context->encoding, context); 00396 qof_main_moderate_query (context); 00397 qof_session_save (export_session, NULL); 00398 qof_main_show_error (export_session); 00399 qof_main_show_error (input_session); 00400 qof_session_end (input_session); 00401 qof_session_end (export_session); 00402 LEAVE (" "); 00403 } 00404 00405 static void 00406 qof_main_list (QofObject * obj, gpointer G_GNUC_UNUSED data) 00407 { 00408 fprintf (stdout, "%-20s%-20s\n", obj->e_type, obj->type_label); 00409 } 00410 00411 void 00412 qof_main_select (QofMainContext * context) 00413 { 00414 g_return_if_fail (context); 00415 qof_object_foreach_type (select_cb, context); 00416 } 00417 00418 void 00419 qof_cmd_list (void) 00420 { 00421 qof_main_wrap_line (stdout, 0, 00422 /* Translators: This line is wrapped by the program - 00423 please make sure you do NOT add line endings here. */ 00424 _("\n%s: You can use the supported database names with '%s -d' " 00425 "and in SQL queries (as the table name) with '%s -s|f'. " 00426 "Descriptions are shown only for readability.\n"), 00427 PACKAGE, PACKAGE, PACKAGE); 00428 fprintf (stdout, "%-20s%-20s\n", _("Name"), _("Description")); 00429 qof_object_foreach_type (qof_main_list, NULL); 00430 qof_main_wrap_line (stdout, 0, 00431 /* Translators: This line is wrapped by the program - 00432 please make sure you do NOT add line endings here. */ 00433 _("\nUse '%s -d <database> --explain' to see the list of fields " 00434 "within any supported database."), PACKAGE); 00435 fprintf (stdout, _("\nThank you for using %s\n\n"), PACKAGE); 00436 } 00437 00438 static void 00439 explain_cb (QofParam * param, gpointer G_GNUC_UNUSED user_data) 00440 { 00441 if (param->param_getfcn && param->param_setfcn) 00442 fprintf (stdout, _("Type: %s\tName: %s\n"), 00443 param->param_type, param->param_name); 00444 } 00445 00446 void 00447 qof_cmd_explain (QofMainContext * context) 00448 { 00449 if (context->error) 00450 return; 00451 fprintf (stdout, _("\nParameters of the %s database:\n\n"), 00452 context->database); 00453 qof_class_param_foreach (context->database, explain_cb, NULL); 00454 fprintf (stdout, _("\nThank you for using %s\n\n"), PACKAGE); 00455 } 00456 00457 void 00458 qof_mod_category (const gchar * category, QofMainContext * data) 00459 { 00460 data->category = g_strdup (category); 00461 } 00462 00463 glong 00464 qof_mod_get_local_offset (void) 00465 { 00466 glong local_offset; 00467 struct tm local; 00468 time_t now; 00469 00470 local_offset = 0; /* UTC */ 00471 now = time (NULL); 00472 local = *localtime_r (&now, &local); 00473 local_offset -= local.tm_gmtoff; 00474 return local_offset; 00475 } 00476 00477 void 00478 qof_mod_database (const gchar * database, QofMainContext * data) 00479 { 00480 if (qof_class_is_registered (database)) 00481 data->database = g_strdup (database); 00482 } 00483 00484 void 00485 qof_mod_time (const gchar * date_time, QofMainContext * data) 00486 { 00487 QofDate *qd; 00488 gboolean all_year, all_month; 00489 gint adding_days; 00490 gchar *info; 00491 00492 /* incoming date is assumed to be localtime */ 00493 ENTER (" date_time=%s", date_time); 00494 all_month = all_year = FALSE; 00495 g_return_if_fail (date_time); 00496 qd = qof_date_parse (date_time, QOF_DATE_FORMAT_ISO); 00497 if (!qd) 00498 qd = qof_date_parse (date_time, QOF_DATE_FORMAT_UTC); 00499 info = qof_date_print (qd, QOF_DATE_FORMAT_ISO8601); 00500 PINFO (" parsed start_time=%s", info); 00501 g_free (info); 00502 /* set first second of day, UTC */ 00503 qof_date_set_day_start (qd); 00504 data->min_qt = qof_date_to_qtime (qd); 00505 /* adjust for incoming localtime */ 00506 qof_time_add_secs (data->min_qt, 00507 qof_mod_get_local_offset()); 00508 /* year specified but no month or day, select the entire year */ 00509 if (strlen (date_time) == 4) 00510 { 00511 PINFO (" match entire year %s", date_time); 00512 /* go to end of this year, not first day of next. */ 00513 adding_days = qof_date_isleap(qd->qd_year) ? 365 : 364; 00514 qof_date_adddays (qd, adding_days); 00515 } 00516 /* month specified, but no day, select entire month */ 00517 if (strlen (date_time) == 7) 00518 { 00519 PINFO (" match entire month %s", date_time); 00520 adding_days = qof_date_get_mday (qd->qd_mon, qd->qd_year); 00521 qof_date_adddays (qd, adding_days - 1); 00522 } 00523 /* set last second of day */ 00524 qof_date_set_day_end (qd); 00525 data->max_qt = qof_date_to_qtime (qd); 00526 /* adjust for incoming localtime */ 00527 qof_time_add_secs (data->max_qt, 00528 qof_mod_get_local_offset()); 00529 LEAVE (" "); 00530 } 00531 00532 void 00533 qof_mod_exclude (const gchar * exclude, QofMainContext * data) 00534 { 00535 if (qof_class_is_registered (exclude)) 00536 data->exclude = g_strdup (exclude); 00537 } 00538 00539 void 00540 qof_mod_sql (const gchar * sql_query, QofMainContext * data) 00541 { 00542 data->sql_str = g_strdup (sql_query); 00543 } 00544 00545 void 00546 qof_mod_sql_file (const gchar * sql_file, QofMainContext * data) 00547 { 00548 FILE *filehandle; 00549 #ifndef HAVE_GETLINE 00550 gchar lineptr[1024]; 00551 #else 00552 gchar *lineptr; 00553 #endif 00554 gchar *buf; 00555 size_t n; 00556 QofQuery *q; 00557 regex_t *r; 00558 gint reg_exp_check; 00559 const gchar *fmt; 00560 static gchar *pattern = QOF_SQL_SUPPORTED; 00561 00562 ENTER (" "); 00563 data->sql_file = g_strdup (sql_file); 00564 n = 0; 00565 q = NULL; 00566 data->sql_list = NULL; 00567 filehandle = fopen (sql_file, "r"); 00568 if (!filehandle) 00569 { 00570 fmt = _("%s: There was an error reading the file '%s'.\n"); 00571 qof_main_wrap_line (stderr, ERR_INDENT, fmt, PACKAGE, sql_file); 00572 return; 00573 } 00574 r = g_new (regex_t, 1); 00575 #ifndef HAVE_GETLINE 00576 while (NULL != (fgets (lineptr, sizeof (lineptr), filehandle))) 00577 #else 00578 lineptr = NULL; 00579 while (0 < getline (&lineptr, &n, filehandle)) 00580 #endif 00581 { 00582 reg_exp_check = 00583 regcomp (r, pattern, REG_ICASE | REG_NOSUB | REG_EXTENDED); 00584 g_return_if_fail (reg_exp_check == 0); 00585 if (0 != regexec (r, lineptr, 0, NULL, 0)) 00586 continue; 00587 buf = g_strdup (g_strchomp (lineptr)); 00588 data->sql_list = g_list_prepend (data->sql_list, buf); 00589 } 00590 regfree (r); 00591 g_free (r); 00592 fclose (filehandle); 00593 LEAVE (" sql_list=%d", g_list_length (data->sql_list)); 00594 } 00595 00596 void 00597 qof_mod_write (const gchar * write_file, QofMainContext * data) 00598 { 00599 data->write_file = g_strdup (write_file); 00600 } 00601 00602 void 00603 qof_main_show_error (QofSession * session) 00604 { 00605 const gchar *fmt; 00606 00607 if (qof_error_check (session)) 00608 { 00609 fmt = "%s: %s\n"; 00610 qof_main_wrap_line (stderr, ERR_INDENT, fmt, PACKAGE, 00611 qof_error_get_message (session)); 00612 } 00613 } 00614 00617 /*==================== END OF FILE ======================*/
1.7.3