gpe-expenses
0.1.9
|
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 gboolean all; 00227 00228 ENTER (" "); 00229 all = TRUE; 00230 context->query = qof_query_create (); 00231 while (context->sql_list) 00232 { 00233 PINFO ("running sql_list"); 00234 context->sql_str = g_strdup (context->sql_list->data); 00235 qof_main_run_sql (context); 00236 qof_main_run_query (context); 00237 if (context->query) 00238 qof_query_clear (context->query); 00239 g_free (context->sql_str); 00240 context->sql_str = NULL; 00241 all = FALSE; 00242 context->sql_list = g_list_next (context->sql_list); 00243 } 00244 if (0 < g_list_length (context->sql_list)) 00245 { 00246 context->sql_str = NULL; 00247 g_list_free (context->sql_list); 00248 all = FALSE; 00249 } 00250 if (context->sql_str != NULL) 00251 { 00252 PINFO ("running sql_str"); 00253 qof_main_run_sql (context); 00254 qof_main_run_query (context); 00255 if (context->query) 00256 qof_query_clear (context->query); 00257 all = FALSE; 00258 } 00259 if ((context->exclude != NULL) 00260 && (qof_class_is_registered (context->exclude))) 00261 { 00262 qof_object_foreach_type (select_cb, context); 00263 all = FALSE; 00264 } 00265 if ((context->database != NULL) 00266 && (qof_class_is_registered (context->database))) 00267 { 00268 build_database_list (context->database, context); 00269 all = FALSE; 00270 } 00271 if (all == TRUE) 00272 qof_object_foreach_type (select_cb, context); 00273 LEAVE (" "); 00274 } 00275 00276 static void 00277 option_cb (QofBackendOption * option, gpointer data) 00278 { 00279 QofMainContext *context; 00280 00281 context = (QofMainContext *) data; 00282 g_return_if_fail (context); 00283 /* Normally, I'd use GPOINTER_TO_INT but internally, 00284 the QofBackendOption uses gint64 which gets mangled by 00285 the 32-bit macro. */ 00286 ENTER (" compression=%" G_GINT64_FORMAT " encoding=%s", 00287 context->gz_level, context->encoding); 00288 if (0 == safe_strcmp (QSF_COMPRESS, option->option_name)) 00289 option->value = (gpointer) & context->gz_level; 00290 if (0 == safe_strcmp (QSF_ENCODING, option->option_name)) 00291 option->value = (gpointer) g_strdup(context->encoding); 00292 if (0 == safe_strcmp (QSF_DATE_CONVERT, option->option_name)) 00293 option->value = (gpointer) & context->convert; 00294 LEAVE (" "); 00295 } 00296 00297 void 00298 qof_mod_compression (gint64 gz_level, QofMainContext * context) 00299 { 00300 KvpFrame *be_config; 00301 QofBook *book; 00302 QofBackend *be; 00303 00304 ENTER (" compression=%" G_GINT64_FORMAT, gz_level); 00305 if ((gz_level > 0) && (gz_level <= 9)) 00306 { 00307 book = qof_session_get_book (context->export_session); 00308 be = qof_book_get_backend (book); 00309 be_config = qof_backend_get_config (be); 00310 context->gz_level = gz_level; 00311 qof_backend_option_foreach (be_config, option_cb, context); 00312 qof_backend_load_config (be, be_config); 00313 } 00314 LEAVE (" "); 00315 } 00316 00317 void 00318 qof_mod_encoding (const gchar * encoding, QofMainContext * context) 00319 { 00320 KvpFrame *be_config; 00321 QofBook *book; 00322 QofBackend *be; 00323 00324 ENTER (" encode to %s", encoding); 00325 book = qof_session_get_book (context->export_session); 00326 be = qof_book_get_backend (book); 00327 be_config = qof_backend_get_config (be); 00328 context->encoding = encoding; 00329 qof_backend_option_foreach (be_config, option_cb, context); 00330 qof_backend_load_config (be, be_config); 00331 LEAVE (" "); 00332 } 00333 00334 void 00335 qof_mod_convert_deprecated (gint64 convert, QofMainContext * context) 00336 { 00337 KvpFrame *be_config; 00338 QofBook *book; 00339 QofBackend *be; 00340 gboolean set; 00341 00342 set = (convert == 0) ? FALSE : TRUE; 00343 ENTER (" convert deprecated date values? %i No if 0.", set); 00344 book = qof_session_get_book (context->export_session); 00345 be = qof_book_get_backend (book); 00346 be_config = qof_backend_get_config (be); 00347 context->convert = convert; 00348 qof_backend_option_foreach (be_config, option_cb, context); 00349 qof_backend_load_config (be, be_config); 00350 LEAVE (" "); 00351 } 00352 00353 void 00354 qof_cmd_xmlfile (QofMainContext * context) 00355 { 00356 QofSession *input_session, *export_session; 00357 00358 ENTER (" "); 00359 input_session = context->input_session; 00360 if (0 == safe_strcmp (context->exclude, context->database) 00361 && (context->exclude != NULL)) 00362 { 00363 qof_main_wrap_line (stderr, ERR_INDENT, 00364 /* Translators: This line is wrapped by the program - 00365 please make sure you do NOT add line endings here. */ 00366 _("%s: Error: Cannot exclude database \"%s\" with option -e " 00367 "because option -d is set to include the database: \"%s\". " 00368 "Use the \'-l\' command to see the full list of supported " 00369 "databases.\n"), PACKAGE, context->exclude, 00370 context->database); 00371 qof_session_end (input_session); 00372 LEAVE (" conflicting options"); 00373 return; 00374 } 00375 qof_session_begin (input_session, context->filename, TRUE, FALSE); 00376 qof_main_show_error (input_session); 00377 if (0 != safe_strcmp (QOF_STDOUT, context->filename)) 00378 qof_session_load (input_session, NULL); 00379 qof_main_show_error (input_session); 00380 export_session = qof_session_new (); 00381 context->export_session = export_session; 00382 if (context->write_file) 00383 { 00384 qof_session_begin (export_session, context->write_file, TRUE, 00385 TRUE); 00386 qof_mod_compression (context->gz_level, context); 00387 } 00388 else 00389 qof_session_begin (export_session, QOF_STDOUT, TRUE, FALSE); 00390 qof_main_show_error (export_session); 00391 /* ensure encoding value is set in the new export_session */ 00392 qof_mod_encoding (context->encoding, context); 00393 qof_main_moderate_query (context); 00394 qof_session_save (export_session, NULL); 00395 qof_main_show_error (export_session); 00396 qof_main_show_error (input_session); 00397 qof_session_end (input_session); 00398 qof_session_end (export_session); 00399 LEAVE (" "); 00400 } 00401 00402 static void 00403 qof_main_list (QofObject * obj, gpointer G_GNUC_UNUSED data) 00404 { 00405 fprintf (stdout, "%-20s%-20s\n", obj->e_type, obj->type_label); 00406 } 00407 00408 void 00409 qof_main_select (QofMainContext * context) 00410 { 00411 g_return_if_fail (context); 00412 qof_object_foreach_type (select_cb, context); 00413 } 00414 00415 void 00416 qof_cmd_list (void) 00417 { 00418 qof_main_wrap_line (stdout, 0, 00419 /* Translators: This line is wrapped by the program - 00420 please make sure you do NOT add line endings here. */ 00421 _("\n%s: You can use the supported database names with '%s -d' " 00422 "and in SQL queries (as the table name) with '%s -s|f'. " 00423 "Descriptions are shown only for readability.\n"), 00424 PACKAGE, PACKAGE, PACKAGE); 00425 fprintf (stdout, "%-20s%-20s\n", _("Name"), _("Description")); 00426 qof_object_foreach_type (qof_main_list, NULL); 00427 qof_main_wrap_line (stdout, 0, 00428 /* Translators: This line is wrapped by the program - 00429 please make sure you do NOT add line endings here. */ 00430 _("\nUse '%s -d <database> --explain' to see the list of fields " 00431 "within any supported database."), PACKAGE); 00432 fprintf (stdout, _("\nThank you for using %s\n\n"), PACKAGE); 00433 } 00434 00435 static void 00436 explain_cb (QofParam * param, gpointer G_GNUC_UNUSED user_data) 00437 { 00438 if (param->param_getfcn && param->param_setfcn) 00439 fprintf (stdout, _("Type: %s\tName: %s\n"), 00440 param->param_type, param->param_name); 00441 } 00442 00443 void 00444 qof_cmd_explain (QofMainContext * context) 00445 { 00446 if (context->error) 00447 return; 00448 fprintf (stdout, _("\nParameters of the %s database:\n\n"), 00449 context->database); 00450 qof_class_param_foreach (context->database, explain_cb, NULL); 00451 fprintf (stdout, _("\nThank you for using %s\n\n"), PACKAGE); 00452 } 00453 00454 void 00455 qof_mod_category (const gchar * category, QofMainContext * data) 00456 { 00457 data->category = g_strdup (category); 00458 } 00459 00460 glong 00461 qof_mod_get_local_offset (void) 00462 { 00463 glong local_offset; 00464 struct tm local; 00465 time_t now; 00466 00467 local_offset = 0; /* UTC */ 00468 now = time (NULL); 00469 local = *localtime_r (&now, &local); 00470 local_offset -= local.tm_gmtoff; 00471 return local_offset; 00472 } 00473 00474 void 00475 qof_mod_database (const gchar * database, QofMainContext * data) 00476 { 00477 if (qof_class_is_registered (database)) 00478 data->database = g_strdup (database); 00479 } 00480 00481 void 00482 qof_mod_time (const gchar * date_time, QofMainContext * data) 00483 { 00484 QofDate *qd; 00485 gint adding_days; 00486 gchar *info; 00487 00488 /* incoming date is assumed to be localtime */ 00489 ENTER (" date_time=%s", date_time); 00490 g_return_if_fail (date_time); 00491 qd = qof_date_parse (date_time, QOF_DATE_FORMAT_ISO); 00492 if (!qd) 00493 qd = qof_date_parse (date_time, QOF_DATE_FORMAT_UTC); 00494 info = qof_date_print (qd, QOF_DATE_FORMAT_ISO8601); 00495 PINFO (" parsed start_time=%s", info); 00496 g_free (info); 00497 /* set first second of day, UTC */ 00498 qof_date_set_day_start (qd); 00499 data->min_qt = qof_date_to_qtime (qd); 00500 /* adjust for incoming localtime */ 00501 qof_time_add_secs (data->min_qt, 00502 qof_mod_get_local_offset()); 00503 /* year specified but no month or day, select the entire year */ 00504 if (strlen (date_time) == 4) 00505 { 00506 PINFO (" match entire year %s", date_time); 00507 /* go to end of this year, not first day of next. */ 00508 adding_days = qof_date_isleap(qd->qd_year) ? 365 : 364; 00509 qof_date_adddays (qd, adding_days); 00510 } 00511 /* month specified, but no day, select entire month */ 00512 if (strlen (date_time) == 7) 00513 { 00514 PINFO (" match entire month %s", date_time); 00515 adding_days = qof_date_get_mday (qd->qd_mon, qd->qd_year); 00516 qof_date_adddays (qd, adding_days - 1); 00517 } 00518 /* set last second of day */ 00519 qof_date_set_day_end (qd); 00520 data->max_qt = qof_date_to_qtime (qd); 00521 /* adjust for incoming localtime */ 00522 qof_time_add_secs (data->max_qt, 00523 qof_mod_get_local_offset()); 00524 LEAVE (" "); 00525 } 00526 00527 void 00528 qof_mod_exclude (const gchar * exclude, QofMainContext * data) 00529 { 00530 if (qof_class_is_registered (exclude)) 00531 data->exclude = g_strdup (exclude); 00532 } 00533 00534 void 00535 qof_mod_sql (const gchar * sql_query, QofMainContext * data) 00536 { 00537 data->sql_str = g_strdup (sql_query); 00538 } 00539 00540 void 00541 qof_mod_sql_file (const gchar * sql_file, QofMainContext * data) 00542 { 00543 FILE *filehandle; 00544 #ifndef HAVE_GETLINE 00545 gchar lineptr[1024]; 00546 #else 00547 gchar *lineptr; 00548 #endif 00549 gchar *buf; 00550 size_t n; 00551 regex_t *r; 00552 gint reg_exp_check; 00553 const gchar *fmt; 00554 static gchar *pattern = QOF_SQL_SUPPORTED; 00555 00556 ENTER (" "); 00557 data->sql_file = g_strdup (sql_file); 00558 n = 0; 00559 data->sql_list = NULL; 00560 filehandle = fopen (sql_file, "r"); 00561 if (!filehandle) 00562 { 00563 fmt = _("%s: There was an error reading the file '%s'.\n"); 00564 qof_main_wrap_line (stderr, ERR_INDENT, fmt, PACKAGE, sql_file); 00565 return; 00566 } 00567 r = g_new (regex_t, 1); 00568 #ifndef HAVE_GETLINE 00569 while (NULL != (fgets (lineptr, sizeof (lineptr), filehandle))) 00570 #else 00571 lineptr = NULL; 00572 while (0 < getline (&lineptr, &n, filehandle)) 00573 #endif 00574 { 00575 reg_exp_check = 00576 regcomp (r, pattern, REG_ICASE | REG_NOSUB | REG_EXTENDED); 00577 g_return_if_fail (reg_exp_check == 0); 00578 if (0 != regexec (r, lineptr, 0, NULL, 0)) 00579 continue; 00580 buf = g_strdup (g_strchomp (lineptr)); 00581 data->sql_list = g_list_prepend (data->sql_list, buf); 00582 } 00583 regfree (r); 00584 g_free (r); 00585 fclose (filehandle); 00586 LEAVE (" sql_list=%d", g_list_length (data->sql_list)); 00587 } 00588 00589 void 00590 qof_mod_write (const gchar * write_file, QofMainContext * data) 00591 { 00592 data->write_file = g_strdup (write_file); 00593 } 00594 00595 void 00596 qof_main_show_error (QofSession * session) 00597 { 00598 const gchar *fmt; 00599 00600 if (qof_error_check (session)) 00601 { 00602 fmt = "%s: %s\n"; 00603 qof_main_wrap_line (stderr, ERR_INDENT, fmt, PACKAGE, 00604 qof_error_get_message (session)); 00605 } 00606 } 00607 00610 /*==================== END OF FILE ======================*/