gpe-expenses 0.1.7

qof-main.c

Go to the documentation of this file.
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 ======================*/