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-2006  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 gchar *
00103 qof_main_make_utf8 (gchar * string)
00104 {
00105     gchar *value;
00106 
00107     if (!string)
00108         return NULL;
00109     if (g_utf8_validate (string, -1, NULL))
00110         return string;
00111     value = g_locale_to_utf8 (string, -1, NULL, NULL, NULL);
00112     if (!value)
00113     {
00114         PWARN (" unable to convert from locale %s", string);
00115         PINFO ("trying to convert from ISO-8859-15.");
00116         value = g_convert (string, -1, "UTF-8", "ISO-8859-15",
00117             NULL, NULL, NULL);
00118         if (!value)
00119         {
00120             PERR (" conversion failed");
00121             return string;
00122         }
00123         return value;
00124     }
00125     return value;
00126 }
00127 
00128 static void
00129 qof_main_run_sql (QofMainContext * context)
00130 {
00131     QofSqlQuery *q;
00132     QofBook *book;
00133     gchar *sql;
00134 
00135     ENTER (" ");
00136     q = qof_sql_query_new ();
00137     sql = g_strdup (context->sql_str);
00138     book = qof_session_get_book (context->input_session);
00139     qof_sql_query_set_book (q, book);
00140     qof_sql_query_run (q, sql);
00141     context->query = qof_sql_query_get_query (q);
00142     LEAVE (" ");
00143 }
00144 
00145 static void
00146 qof_main_run_query (QofMainContext * context)
00147 {
00148     QofBook *book;
00149     GList *results;
00150 
00151     ENTER (" ");
00152     results = NULL;
00153     book = qof_session_get_book (context->input_session);
00154     qof_query_set_book (context->query, book);
00155     results = qof_query_run (context->query);
00156     if (results != NULL)
00157         qof_entity_copy_list (context->export_session, results);
00158     LEAVE (" ");
00159 }
00160 
00161 void
00162 qof_main_free (QofMainContext * context)
00163 {
00164     g_free (context->filename);
00165     g_free (context->write_file);
00166     g_free (context->sql_file);
00167     g_free (context->database);
00168     g_free (context->category);
00169 }
00170 
00171 static void
00172 find_param_cb (QofParam * param, gpointer user_data)
00173 {
00174     QofMainContext *context;
00175     QofQueryPredData *time_pred_data;
00176 
00177     context = (QofMainContext *) user_data;
00178     if ((param->param_getfcn == NULL) || 
00179         (param->param_setfcn == NULL))
00180         return;
00181     if (0 == safe_strcmp (context->param_type, param->param_type))
00182     {
00183         time_pred_data = qof_query_time_predicate (QOF_COMPARE_GTE,
00184             QOF_DATE_MATCH_NORMAL, context->min_qt);
00185         qof_query_add_term (context->query, 
00186             qof_query_build_param_list ((gchar*)param->param_name, 
00187             NULL), time_pred_data, QOF_QUERY_AND);
00188         time_pred_data = qof_query_time_predicate (QOF_COMPARE_LTE,
00189             QOF_DATE_MATCH_NORMAL, context->max_qt);
00190         qof_query_add_term (context->query, 
00191             qof_query_build_param_list ((gchar*)param->param_name, 
00192             NULL), time_pred_data, QOF_QUERY_AND);
00193         qof_main_run_query (context);
00194         qof_query_purge_terms (context->query, 
00195             qof_query_build_param_list ((gchar*)param->param_name, 
00196             QOF_ID_BOOK, QOF_TYPE_GUID, NULL));
00197         PINFO (" param_name=%s added", param->param_name);
00198     }
00199     LEAVE (" ");
00200 }
00201 
00202 /* takes one database name and runs -c and -t queries against it. */
00203 static void
00204 build_database_list (QofIdTypeConst obj_type, QofMainContext * context)
00205 {
00206     if (!obj_type || !context)
00207         return;
00208     if (!qof_class_is_registered (obj_type))
00209         return;
00210     ENTER (" object_type=%s", obj_type);
00211     context->query = qof_query_create_for (obj_type);
00212     if (context->category != NULL)
00213     {
00214         QofQueryPredData *category_pred;
00215 
00216         category_pred =
00217             qof_query_string_predicate (QOF_COMPARE_EQUAL,
00218             context->category, QOF_STRING_MATCH_CASEINSENSITIVE, 
00219             FALSE);
00220         qof_query_add_term (context->query, 
00221             qof_query_build_param_list (CATEGORY_NAME, NULL),
00222             category_pred, QOF_QUERY_AND);
00223     }
00224     if (context->min_qt)
00225     {
00226         PINFO (" Preparing a time based queryset.");
00227         context->param_type = QOF_TYPE_TIME;
00228         qof_class_param_foreach (obj_type, find_param_cb, context);
00229     }
00230     else
00231     {
00232         qof_main_run_query (context);
00233         if (context->query)
00234             qof_query_clear (context->query);
00235     }
00236     LEAVE (" ");
00237 }
00238 
00239 static void
00240 select_cb (QofObject * obj, gpointer data)
00241 {
00242     QofMainContext *context;
00243 
00244     context = (QofMainContext *) data;
00245     g_return_if_fail (context);
00246     if (0 != safe_strcmp (context->exclude, obj->e_type))
00247         build_database_list (obj->e_type, context);
00248 }
00249 
00250 void
00251 qof_main_moderate_query (QofMainContext * context)
00252 {
00253     GSList *date_param_list, *category_param_list;
00254     gboolean all;
00255 
00256     ENTER (" ");
00257     all = TRUE;
00258     context->query = qof_query_create ();
00259     date_param_list = NULL;
00260     category_param_list = NULL;
00261     while (context->sql_list)
00262     {
00263         PINFO ("running sql_list");
00264         context->sql_str = g_strdup (context->sql_list->data);
00265         qof_main_run_sql (context);
00266         qof_main_run_query (context);
00267         if (context->query)
00268             qof_query_clear (context->query);
00269         g_free (context->sql_str);
00270         context->sql_str = NULL;
00271         all = FALSE;
00272         context->sql_list = g_list_next (context->sql_list);
00273     }
00274     if (0 < g_list_length (context->sql_list))
00275     {
00276         context->sql_str = NULL;
00277         g_list_free (context->sql_list);
00278         all = FALSE;
00279     }
00280     if (context->sql_str != NULL)
00281     {
00282         PINFO ("running sql_str");
00283         qof_main_run_sql (context);
00284         qof_main_run_query (context);
00285         if (context->query)
00286             qof_query_clear (context->query);
00287         all = FALSE;
00288     }
00289     if ((context->exclude != NULL)
00290         && (qof_class_is_registered (context->exclude)))
00291     {
00292         qof_object_foreach_type (select_cb, context);
00293         all = FALSE;
00294     }
00295     if ((context->database != NULL)
00296         && (qof_class_is_registered (context->database)))
00297     {
00298         build_database_list (context->database, context);
00299         all = FALSE;
00300     }
00301     if (all == TRUE)
00302         qof_object_foreach_type (select_cb, context);
00303     LEAVE (" ");
00304 }
00305 
00306 static void
00307 option_cb (QofBackendOption * option, gpointer data)
00308 {
00309     QofMainContext *context;
00310 
00311     context = (QofMainContext *) data;
00312     g_return_if_fail (context);
00313 /* Normally, I'd use GPOINTER_TO_INT but internally, 
00314 the QofBackendOption uses gint64 which gets mangled by
00315 the 32-bit macro. */
00316     ENTER (" compression=%" G_GINT64_FORMAT " encoding=%s",
00317         context->gz_level, context->encoding);
00318     if (0 == safe_strcmp (QSF_COMPRESS, option->option_name))
00319         option->value = (gpointer) & context->gz_level;
00320     if (0 == safe_strcmp (QSF_ENCODING, option->option_name))
00321         option->value = (gpointer) context->encoding;
00322     if (0 == safe_strcmp (QSF_DATE_CONVERT, option->option_name))
00323         option->value = (gpointer) & context->convert;
00324     LEAVE (" ");
00325 }
00326 
00327 void
00328 qof_mod_compression (gint64 gz_level, QofMainContext * context)
00329 {
00330     KvpFrame *be_config;
00331     QofBook *book;
00332     QofBackend *be;
00333 
00334     ENTER (" compression=%" G_GINT64_FORMAT, gz_level);
00335     if ((gz_level > 0) && (gz_level <= 9))
00336     {
00337         book = qof_session_get_book (context->export_session);
00338         be = qof_book_get_backend (book);
00339         be_config = qof_backend_get_config (be);
00340         context->gz_level = gz_level;
00341         qof_backend_option_foreach (be_config, option_cb, context);
00342         qof_backend_load_config (be, be_config);
00343     }
00344     LEAVE (" ");
00345 }
00346 
00347 void
00348 qof_mod_encoding (const gchar * encoding, QofMainContext * context)
00349 {
00350     KvpFrame *be_config;
00351     QofBook *book;
00352     QofBackend *be;
00353 
00354     ENTER (" encode to %s", encoding);
00355     book = qof_session_get_book (context->export_session);
00356     be = qof_book_get_backend (book);
00357     be_config = qof_backend_get_config (be);
00358     context->encoding = encoding;
00359     qof_backend_option_foreach (be_config, option_cb, context);
00360     qof_backend_load_config (be, be_config);
00361     LEAVE (" ");
00362 }
00363 
00364 void
00365 qof_mod_convert_deprecated (gint64 convert, QofMainContext * context)
00366 {
00367     KvpFrame *be_config;
00368     QofBook *book;
00369     QofBackend *be;
00370     gboolean set;
00371 
00372     set = (convert == 0) ? FALSE : TRUE;
00373     ENTER (" convert deprecated date values? %i No if 0.", set);
00374     book = qof_session_get_book (context->export_session);
00375     be = qof_book_get_backend (book);
00376     be_config = qof_backend_get_config (be);
00377     context->convert = convert;
00378     qof_backend_option_foreach (be_config, option_cb, context);
00379     qof_backend_load_config (be, be_config);
00380     LEAVE (" ");
00381 }
00382 
00383 void
00384 qof_cmd_xmlfile (QofMainContext * context)
00385 {
00386     QofSession *input_session, *export_session;
00387 
00388     ENTER (" ");
00389     input_session = context->input_session;
00390     if (0 == safe_strcmp (context->exclude, context->database)
00391         && (context->exclude != NULL))
00392     {
00393         qof_main_wrap_line (stderr, ERR_INDENT,
00394             _("%s: Error: Cannot exclude database \"%s\" with option -e "
00395                 "because option -d is set to include the database: \"%s\". "
00396                 "Use the \'-l\' command to see the full list of supported "
00397                 "databases.\n"), PACKAGE, context->exclude,
00398             context->database);
00399         qof_session_end (input_session);
00400         LEAVE (" conflicting options");
00401         return;
00402     }
00403     qof_session_begin (input_session, context->filename, TRUE, FALSE);
00404     if (0 != safe_strcmp (QOF_STDOUT, context->filename))
00405         qof_session_load (input_session, NULL);
00406     export_session = qof_session_new ();
00407     context->export_session = export_session;
00408     if (context->write_file)
00409     {
00410         qof_session_begin (export_session, context->write_file, TRUE,
00411             TRUE);
00412         qof_mod_compression (context->gz_level, context);
00413     }
00414     else
00415         qof_session_begin (export_session, QOF_STDOUT, TRUE, TRUE);
00416     /* ensure encoding value is set in the new export_session */
00417     qof_mod_encoding (context->encoding, context);
00418     qof_main_moderate_query (context);
00419     qof_session_save (export_session, NULL);
00420     qof_main_show_error (export_session);
00421     qof_main_show_error (input_session);
00422     qof_session_end (input_session);
00423     qof_session_end (export_session);
00424     LEAVE (" ");
00425 }
00426 
00427 static void
00428 qof_main_list (QofObject * obj, gpointer data)
00429 {
00430     fprintf (stdout, "%-20s%-20s\n", obj->e_type, obj->type_label);
00431 }
00432 
00433 void
00434 qof_main_select (QofMainContext * context)
00435 {
00436     g_return_if_fail (context);
00437     qof_object_foreach_type (select_cb, context);
00438 }
00439 
00440 void
00441 qof_cmd_list (void)
00442 {
00443     qof_main_wrap_line (stdout, 0,
00444         _("\n%s: You can use the supported database names with '%s -d' "
00445             "and in SQL queries (as the table name) with '%s -s|f'. "
00446             "Descriptions are shown only for readability.\n"),
00447         PACKAGE, PACKAGE, PACKAGE);
00448     fprintf (stdout, "%-20s%-20s\n", _("Name"), _("Description"));
00449     qof_object_foreach_type (qof_main_list, NULL);
00450     qof_main_wrap_line (stdout, 0,
00451         _("\nUse '%s -d <database> --explain' to see the list of fields "
00452             "within any supported database."), PACKAGE);
00453     fprintf (stdout, _("\nThank you for using %s\n\n"), PACKAGE);
00454 }
00455 
00456 static void
00457 explain_cb (QofParam * param, gpointer user_data)
00458 {
00459     if (param->param_getfcn && param->param_setfcn)
00460         fprintf (stdout, _("Type: %s\tName: %s\n"),
00461             param->param_type, param->param_name);
00462 }
00463 
00464 void
00465 qof_cmd_explain (QofMainContext * context)
00466 {
00467     if (context->error)
00468         return;
00469     fprintf (stdout, _("\nParameters of the %s database:\n\n"),
00470         context->database);
00471     qof_class_param_foreach (context->database, explain_cb, NULL);
00472     fprintf (stdout, _("\nThank you for using %s\n\n"), PACKAGE);
00473 }
00474 
00475 void
00476 qof_mod_category (const gchar * category, QofMainContext * data)
00477 {
00478     data->category = g_strdup (category);
00479 }
00480 
00481 glong
00482 qof_mod_get_local_offset (void)
00483 {
00484     glong local_offset;
00485     struct tm local;
00486     time_t now;
00487 
00488     local_offset = 0; /* UTC */
00489     now = time (NULL);
00490     local = *localtime_r (&now, &local);
00491     local_offset -= local.tm_gmtoff;
00492     return local_offset;
00493 }
00494 
00495 void
00496 qof_mod_database (const gchar * database, QofMainContext * data)
00497 {
00498     if (qof_class_is_registered (database))
00499         data->database = g_strdup (database);
00500 }
00501 
00502 void
00503 qof_mod_time (const gchar * date_time, QofMainContext * data)
00504 {
00505     QofDate *qd;
00506     gboolean all_year, all_month;
00507     gint adding_days;
00508     gchar *info;
00509 
00510     /* incoming date is assumed to be localtime */
00511     ENTER (" date_time=%s", date_time);
00512     all_month = all_year = FALSE;
00513     g_return_if_fail (date_time);
00514     qd = qof_date_parse (date_time, QOF_DATE_FORMAT_ISO);
00515     if (!qd)
00516         qd = qof_date_parse (date_time, QOF_DATE_FORMAT_UTC);
00517     info = qof_date_print (qd, QOF_DATE_FORMAT_ISO8601);
00518     PINFO (" parsed start_time=%s", info);
00519     g_free (info);
00520     /* set first second of day, UTC */
00521     qof_date_set_day_start (qd);
00522     data->min_qt = qof_date_to_qtime (qd);
00523     /* adjust for incoming localtime */
00524     qof_time_add_secs (data->min_qt, 
00525         qof_mod_get_local_offset());
00526     /* year specified but no month or day, select the entire year */
00527     if (strlen (date_time) == 4)
00528     {
00529         PINFO (" match entire year %s", date_time);
00530         /* go to end of this year, not first day of next. */
00531         adding_days = qof_date_isleap(qd->qd_year) ? 365 : 364;
00532         qof_date_adddays (qd, adding_days);
00533     }
00534     /* month specified, but no day, select entire month */
00535     if (strlen (date_time) == 7)
00536     {
00537         PINFO (" match entire month %s", date_time);
00538         adding_days = qof_date_get_mday (qd->qd_mon, qd->qd_year);
00539         qof_date_adddays (qd, adding_days - 1);
00540     }
00541     /* set last second of day */
00542     qof_date_set_day_end (qd);
00543     data->max_qt = qof_date_to_qtime (qd);
00544     /* adjust for incoming localtime */
00545     qof_time_add_secs (data->max_qt, 
00546         qof_mod_get_local_offset());
00547     LEAVE (" ");
00548 }
00549 
00550 void
00551 qof_mod_exclude (const gchar * exclude, QofMainContext * data)
00552 {
00553     if (qof_class_is_registered (exclude))
00554         data->exclude = g_strdup (exclude);
00555 }
00556 
00557 void
00558 qof_mod_sql (const gchar * sql_query, QofMainContext * data)
00559 {
00560     data->sql_str = g_strdup (sql_query);
00561 }
00562 
00563 void
00564 qof_mod_sql_file (const gchar * sql_file, QofMainContext * data)
00565 {
00566     FILE *filehandle;
00567 #ifndef HAVE_GETLINE
00568     gchar lineptr[1024];
00569 #else
00570     gchar *lineptr;
00571 #endif
00572     gchar *buf;
00573     size_t n;
00574     QofQuery *q;
00575     regex_t *r;
00576     gint reg_exp_check;
00577     const gchar *fmt;
00578     static gchar *pattern = QOF_SQL_SUPPORTED;
00579 
00580     ENTER (" ");
00581     data->sql_file = g_strdup (sql_file);
00582     n = 0;
00583     q = NULL;
00584     data->sql_list = NULL;
00585     filehandle = fopen (sql_file, "r");
00586     if (!filehandle)
00587     {
00588         fmt = _("%s: There was an error reading the file '%s'.\n");
00589         qof_main_wrap_line (stderr, ERR_INDENT, fmt, PACKAGE, sql_file);
00590         return;
00591     }
00592     r = g_new (regex_t, 1);
00593 #ifndef HAVE_GETLINE
00594     while (NULL != (fgets (lineptr, sizeof (lineptr), filehandle)))
00595 #else
00596     lineptr = NULL;
00597     while (0 < getline (&lineptr, &n, filehandle))
00598 #endif
00599     {
00600         reg_exp_check =
00601             regcomp (r, pattern, REG_ICASE | REG_NOSUB | REG_EXTENDED);
00602         g_return_if_fail (reg_exp_check == 0);
00603         if (0 != regexec (r, lineptr, 0, NULL, 0))
00604             continue;
00605         buf = g_strdup (g_strchomp (lineptr));
00606         data->sql_list = g_list_prepend (data->sql_list, buf);
00607     }
00608     regfree (r);
00609     g_free (r);
00610     fclose (filehandle);
00611     LEAVE (" sql_list=%d", g_list_length (data->sql_list));
00612 }
00613 
00614 void
00615 qof_mod_write (const gchar * write_file, QofMainContext * data)
00616 {
00617     data->write_file = g_strdup (write_file);
00618 }
00619 
00620 void
00621 qof_main_show_error (QofSession * session)
00622 {
00623     gchar *newfile;
00624     const gchar *fmt;
00625     QofErrorId id;
00626 
00627     newfile = g_strdup (qof_session_get_file_path (session));
00628     id = qof_error_check (session);
00629     if (id != QOF_SUCCESS)
00630     {
00633         fmt = _("%s: %d %s\n");
00634         qof_main_wrap_line (stderr, ERR_INDENT, fmt, PACKAGE,
00635             id, qof_error_get_message (session));
00636         qof_error_clear (session);
00637     }
00638     g_free (newfile);
00639 }
00640 
00643 /*==================== END OF FILE ======================*/

Generated on Tue Mar 6 00:08:09 2007 for pilot-qof by  doxygen 1.5.1