gpe-expenses 0.1.9
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         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 ======================*/