gpe-expenses  0.1.9
qof-main.c
Go to the documentation of this file.
1 /***************************************************************************
2  * qof-main.c
3  *
4  * This is an auto-generated file. Patches are available from
5  * http://qof-gen.sourceforge.net/
6  *
7  * Thu Jan 13 10:55:44 2005
8  * Copyright 2005-2009 Neil Williams
9  * linux@codehelp.co.uk
10  ****************************************************************************/
11 /*
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25  */
26 
38 #define _GNU_SOURCE
39 #include "config.h"
40 #include <glib.h>
41 #include <glib/gi18n.h>
42 #include <glib/gprintf.h>
43 #include <qof.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <regex.h>
47 #include <time.h>
48 #include "qof-main.h"
49 
50 #define MAX_LINE 79
51 
52 /* the debugging module for this file. */
53 static QofLogModule log_module = QOF_MAIN_CLI;
54 
55 void
56 qof_main_wrap_line (FILE * fp, gint indent,
57  const gchar * template, ...)
58 {
59  gint line_length, msg_length;
60  va_list wraps;
61  gchar *message;
62 
63  line_length = MAX_LINE;
64  /* note the modulus. Don't use CLAMP here */
65  /* indent != line_length or particularly close to it. */
66  indent = indent >= line_length ? indent % line_length : indent;
67  indent = indent < 0 ? 0 : indent;
68  message = NULL;
69  g_return_if_fail (template);
70  va_start (wraps, template);
71  message = g_strdup_vprintf (template, wraps);
72  va_end (wraps);
73  g_return_if_fail (message);
74  msg_length = strlen (message);
75  while (msg_length > line_length)
76  {
77  gchar *chunk;
78  gchar format[16];
79 
80  chunk = message + line_length - 1;
81  while (chunk > message && !g_ascii_isspace (*chunk))
82  chunk--;
83  if (chunk == message)
84  break; /* give up */
85  while (chunk > (message + 1) && g_ascii_isspace (*chunk))
86  chunk--;
87  chunk++;
88  g_sprintf (format, "%%.%ds\n%%%ds", (gint) (chunk - message),
89  indent);
90  g_fprintf (fp, format, message, "");
91  message = chunk;
92  while (g_ascii_isspace (*message) && *message)
93  message++;
94  msg_length = strlen (message);
95  if (line_length == MAX_LINE)
96  line_length -= indent;
97  }
98  if (msg_length)
99  g_fprintf (fp, "%s\n", message);
100 }
101 
102 static void
103 qof_main_run_sql (QofMainContext * context)
104 {
105  QofSqlQuery *q;
106  QofBook *book;
107  gchar *sql;
108 
109  ENTER (" ");
110  q = qof_sql_query_new ();
111  sql = g_strdup (context->sql_str);
112  book = qof_session_get_book (context->input_session);
113  qof_sql_query_set_book (q, book);
114  qof_sql_query_run (q, sql);
115  context->query = qof_sql_query_get_query (q);
116  LEAVE (" ");
117 }
118 
119 static void
120 qof_main_run_query (QofMainContext * context)
121 {
122  QofBook *book;
123  GList *results;
124 
125  ENTER (" ");
126  results = NULL;
127  book = qof_session_get_book (context->input_session);
128  qof_query_set_book (context->query, book);
129  results = qof_query_run (context->query);
130  if (results != NULL)
131  qof_entity_copy_list (context->export_session, results);
132  LEAVE (" ");
133 }
134 
135 void
137 {
138  g_free (context->filename);
139  g_free (context->write_file);
140  g_free (context->sql_file);
141  g_free (context->database);
142  g_free (context->category);
143 }
144 
145 static void
146 find_param_cb (QofParam * param, gpointer user_data)
147 {
148  gchar * tmp;
149  QofMainContext *context;
150  QofQueryPredData *time_pred_data;
151 
152  context = (QofMainContext *) user_data;
153  if ((param->param_getfcn == NULL) ||
154  (param->param_setfcn == NULL))
155  return;
156  if (0 == safe_strcmp (context->param_type, param->param_type))
157  {
158  time_pred_data = qof_query_time_predicate (QOF_COMPARE_GTE,
159  QOF_DATE_MATCH_NORMAL, context->min_qt);
160  tmp = g_strdup (param->param_name);
161  qof_query_add_term (context->query,
162  qof_query_build_param_list (tmp, NULL), time_pred_data, QOF_QUERY_AND);
163  time_pred_data = qof_query_time_predicate (QOF_COMPARE_LTE,
164  QOF_DATE_MATCH_NORMAL, context->max_qt);
165  qof_query_add_term (context->query,
166  qof_query_build_param_list (tmp, NULL), time_pred_data, QOF_QUERY_AND);
167  qof_main_run_query (context);
168  qof_query_purge_terms (context->query,
169  qof_query_build_param_list (tmp, QOF_ID_BOOK, QOF_TYPE_GUID, NULL));
170  PINFO (" param_name=%s added", tmp);
171  }
172  LEAVE (" ");
173 }
174 
175 /* takes one database name and runs -c and -t queries against it. */
176 static void
177 build_database_list (QofIdTypeConst obj_type, QofMainContext * context)
178 {
179  if (!obj_type || !context)
180  return;
181  if (!qof_class_is_registered (obj_type))
182  return;
183  ENTER (" object_type=%s", obj_type);
184  context->query = qof_query_create_for (obj_type);
185  if (context->category != NULL)
186  {
187  QofQueryPredData *category_pred;
188 
189  category_pred =
190  qof_query_string_predicate (QOF_COMPARE_EQUAL,
191  context->category, QOF_STRING_MATCH_CASEINSENSITIVE,
192  FALSE);
193  qof_query_add_term (context->query,
194  qof_query_build_param_list (CATEGORY_NAME, NULL),
195  category_pred, QOF_QUERY_AND);
196  }
197  if (context->min_qt)
198  {
199  PINFO (" Preparing a time based queryset.");
200  context->param_type = QOF_TYPE_TIME;
201  qof_class_param_foreach (obj_type, find_param_cb, context);
202  }
203  else
204  {
205  qof_main_run_query (context);
206  if (context->query)
207  qof_query_clear (context->query);
208  }
209  LEAVE (" ");
210 }
211 
212 static void
213 select_cb (QofObject * obj, gpointer data)
214 {
215  QofMainContext *context;
216 
217  context = (QofMainContext *) data;
218  g_return_if_fail (context);
219  if (0 != safe_strcmp (context->exclude, obj->e_type))
220  build_database_list (obj->e_type, context);
221 }
222 
223 void
225 {
226  gboolean all;
227 
228  ENTER (" ");
229  all = TRUE;
230  context->query = qof_query_create ();
231  while (context->sql_list)
232  {
233  PINFO ("running sql_list");
234  context->sql_str = g_strdup (context->sql_list->data);
235  qof_main_run_sql (context);
236  qof_main_run_query (context);
237  if (context->query)
238  qof_query_clear (context->query);
239  g_free (context->sql_str);
240  context->sql_str = NULL;
241  all = FALSE;
242  context->sql_list = g_list_next (context->sql_list);
243  }
244  if (0 < g_list_length (context->sql_list))
245  {
246  context->sql_str = NULL;
247  g_list_free (context->sql_list);
248  all = FALSE;
249  }
250  if (context->sql_str != NULL)
251  {
252  PINFO ("running sql_str");
253  qof_main_run_sql (context);
254  qof_main_run_query (context);
255  if (context->query)
256  qof_query_clear (context->query);
257  all = FALSE;
258  }
259  if ((context->exclude != NULL)
260  && (qof_class_is_registered (context->exclude)))
261  {
262  qof_object_foreach_type (select_cb, context);
263  all = FALSE;
264  }
265  if ((context->database != NULL)
266  && (qof_class_is_registered (context->database)))
267  {
268  build_database_list (context->database, context);
269  all = FALSE;
270  }
271  if (all == TRUE)
272  qof_object_foreach_type (select_cb, context);
273  LEAVE (" ");
274 }
275 
276 static void
277 option_cb (QofBackendOption * option, gpointer data)
278 {
279  QofMainContext *context;
280 
281  context = (QofMainContext *) data;
282  g_return_if_fail (context);
283 /* Normally, I'd use GPOINTER_TO_INT but internally,
284 the QofBackendOption uses gint64 which gets mangled by
285 the 32-bit macro. */
286  ENTER (" compression=%" G_GINT64_FORMAT " encoding=%s",
287  context->gz_level, context->encoding);
288  if (0 == safe_strcmp (QSF_COMPRESS, option->option_name))
289  option->value = (gpointer) & context->gz_level;
290  if (0 == safe_strcmp (QSF_ENCODING, option->option_name))
291  option->value = (gpointer) g_strdup(context->encoding);
292  if (0 == safe_strcmp (QSF_DATE_CONVERT, option->option_name))
293  option->value = (gpointer) & context->convert;
294  LEAVE (" ");
295 }
296 
297 void
298 qof_mod_compression (gint64 gz_level, QofMainContext * context)
299 {
300  KvpFrame *be_config;
301  QofBook *book;
302  QofBackend *be;
303 
304  ENTER (" compression=%" G_GINT64_FORMAT, gz_level);
305  if ((gz_level > 0) && (gz_level <= 9))
306  {
307  book = qof_session_get_book (context->export_session);
308  be = qof_book_get_backend (book);
309  be_config = qof_backend_get_config (be);
310  context->gz_level = gz_level;
311  qof_backend_option_foreach (be_config, option_cb, context);
312  qof_backend_load_config (be, be_config);
313  }
314  LEAVE (" ");
315 }
316 
317 void
318 qof_mod_encoding (const gchar * encoding, QofMainContext * context)
319 {
320  KvpFrame *be_config;
321  QofBook *book;
322  QofBackend *be;
323 
324  ENTER (" encode to %s", encoding);
325  book = qof_session_get_book (context->export_session);
326  be = qof_book_get_backend (book);
327  be_config = qof_backend_get_config (be);
328  context->encoding = encoding;
329  qof_backend_option_foreach (be_config, option_cb, context);
330  qof_backend_load_config (be, be_config);
331  LEAVE (" ");
332 }
333 
334 void
335 qof_mod_convert_deprecated (gint64 convert, QofMainContext * context)
336 {
337  KvpFrame *be_config;
338  QofBook *book;
339  QofBackend *be;
340  gboolean set;
341 
342  set = (convert == 0) ? FALSE : TRUE;
343  ENTER (" convert deprecated date values? %i No if 0.", set);
344  book = qof_session_get_book (context->export_session);
345  be = qof_book_get_backend (book);
346  be_config = qof_backend_get_config (be);
347  context->convert = convert;
348  qof_backend_option_foreach (be_config, option_cb, context);
349  qof_backend_load_config (be, be_config);
350  LEAVE (" ");
351 }
352 
353 void
355 {
356  QofSession *input_session, *export_session;
357 
358  ENTER (" ");
359  input_session = context->input_session;
360  if (0 == safe_strcmp (context->exclude, context->database)
361  && (context->exclude != NULL))
362  {
364  /* Translators: This line is wrapped by the program -
365  please make sure you do NOT add line endings here. */
366  _("%s: Error: Cannot exclude database \"%s\" with option -e "
367  "because option -d is set to include the database: \"%s\". "
368  "Use the \'-l\' command to see the full list of supported "
369  "databases.\n"), PACKAGE, context->exclude,
370  context->database);
371  qof_session_end (input_session);
372  LEAVE (" conflicting options");
373  return;
374  }
375  qof_session_begin (input_session, context->filename, TRUE, FALSE);
376  qof_main_show_error (input_session);
377  if (0 != safe_strcmp (QOF_STDOUT, context->filename))
378  qof_session_load (input_session, NULL);
379  qof_main_show_error (input_session);
380  export_session = qof_session_new ();
381  context->export_session = export_session;
382  if (context->write_file)
383  {
384  qof_session_begin (export_session, context->write_file, TRUE,
385  TRUE);
386  qof_mod_compression (context->gz_level, context);
387  }
388  else
389  qof_session_begin (export_session, QOF_STDOUT, TRUE, FALSE);
390  qof_main_show_error (export_session);
391  /* ensure encoding value is set in the new export_session */
392  qof_mod_encoding (context->encoding, context);
393  qof_main_moderate_query (context);
394  qof_session_save (export_session, NULL);
395  qof_main_show_error (export_session);
396  qof_main_show_error (input_session);
397  qof_session_end (input_session);
398  qof_session_end (export_session);
399  LEAVE (" ");
400 }
401 
402 static void
403 qof_main_list (QofObject * obj, gpointer G_GNUC_UNUSED data)
404 {
405  fprintf (stdout, "%-20s%-20s\n", obj->e_type, obj->type_label);
406 }
407 
408 void
409 qof_main_select (QofMainContext * context)
410 {
411  g_return_if_fail (context);
412  qof_object_foreach_type (select_cb, context);
413 }
414 
415 void
417 {
418  qof_main_wrap_line (stdout, 0,
419  /* Translators: This line is wrapped by the program -
420  please make sure you do NOT add line endings here. */
421  _("\n%s: You can use the supported database names with '%s -d' "
422  "and in SQL queries (as the table name) with '%s -s|f'. "
423  "Descriptions are shown only for readability.\n"),
424  PACKAGE, PACKAGE, PACKAGE);
425  fprintf (stdout, "%-20s%-20s\n", _("Name"), _("Description"));
426  qof_object_foreach_type (qof_main_list, NULL);
427  qof_main_wrap_line (stdout, 0,
428  /* Translators: This line is wrapped by the program -
429  please make sure you do NOT add line endings here. */
430  _("\nUse '%s -d <database> --explain' to see the list of fields "
431  "within any supported database."), PACKAGE);
432  fprintf (stdout, _("\nThank you for using %s\n\n"), PACKAGE);
433 }
434 
435 static void
436 explain_cb (QofParam * param, gpointer G_GNUC_UNUSED user_data)
437 {
438  if (param->param_getfcn && param->param_setfcn)
439  fprintf (stdout, _("Type: %s\tName: %s\n"),
440  param->param_type, param->param_name);
441 }
442 
443 void
445 {
446  if (context->error)
447  return;
448  fprintf (stdout, _("\nParameters of the %s database:\n\n"),
449  context->database);
450  qof_class_param_foreach (context->database, explain_cb, NULL);
451  fprintf (stdout, _("\nThank you for using %s\n\n"), PACKAGE);
452 }
453 
454 void
455 qof_mod_category (const gchar * category, QofMainContext * data)
456 {
457  data->category = g_strdup (category);
458 }
459 
460 glong
462 {
463  glong local_offset;
464  struct tm local;
465  time_t now;
466 
467  local_offset = 0; /* UTC */
468  now = time (NULL);
469  local = *localtime_r (&now, &local);
470  local_offset -= local.tm_gmtoff;
471  return local_offset;
472 }
473 
474 void
475 qof_mod_database (const gchar * database, QofMainContext * data)
476 {
477  if (qof_class_is_registered (database))
478  data->database = g_strdup (database);
479 }
480 
481 void
482 qof_mod_time (const gchar * date_time, QofMainContext * data)
483 {
484  QofDate *qd;
485  gint adding_days;
486  gchar *info;
487 
488  /* incoming date is assumed to be localtime */
489  ENTER (" date_time=%s", date_time);
490  g_return_if_fail (date_time);
491  qd = qof_date_parse (date_time, QOF_DATE_FORMAT_ISO);
492  if (!qd)
493  qd = qof_date_parse (date_time, QOF_DATE_FORMAT_UTC);
494  info = qof_date_print (qd, QOF_DATE_FORMAT_ISO8601);
495  PINFO (" parsed start_time=%s", info);
496  g_free (info);
497  /* set first second of day, UTC */
498  qof_date_set_day_start (qd);
499  data->min_qt = qof_date_to_qtime (qd);
500  /* adjust for incoming localtime */
501  qof_time_add_secs (data->min_qt,
503  /* year specified but no month or day, select the entire year */
504  if (strlen (date_time) == 4)
505  {
506  PINFO (" match entire year %s", date_time);
507  /* go to end of this year, not first day of next. */
508  adding_days = qof_date_isleap(qd->qd_year) ? 365 : 364;
509  qof_date_adddays (qd, adding_days);
510  }
511  /* month specified, but no day, select entire month */
512  if (strlen (date_time) == 7)
513  {
514  PINFO (" match entire month %s", date_time);
515  adding_days = qof_date_get_mday (qd->qd_mon, qd->qd_year);
516  qof_date_adddays (qd, adding_days - 1);
517  }
518  /* set last second of day */
519  qof_date_set_day_end (qd);
520  data->max_qt = qof_date_to_qtime (qd);
521  /* adjust for incoming localtime */
522  qof_time_add_secs (data->max_qt,
524  LEAVE (" ");
525 }
526 
527 void
528 qof_mod_exclude (const gchar * exclude, QofMainContext * data)
529 {
530  if (qof_class_is_registered (exclude))
531  data->exclude = g_strdup (exclude);
532 }
533 
534 void
535 qof_mod_sql (const gchar * sql_query, QofMainContext * data)
536 {
537  data->sql_str = g_strdup (sql_query);
538 }
539 
540 void
541 qof_mod_sql_file (const gchar * sql_file, QofMainContext * data)
542 {
543  FILE *filehandle;
544 #ifndef HAVE_GETLINE
545  gchar lineptr[1024];
546 #else
547  gchar *lineptr;
548 #endif
549  gchar *buf;
550  size_t n;
551  regex_t *r;
552  gint reg_exp_check;
553  const gchar *fmt;
554  static gchar *pattern = QOF_SQL_SUPPORTED;
555 
556  ENTER (" ");
557  data->sql_file = g_strdup (sql_file);
558  n = 0;
559  data->sql_list = NULL;
560  filehandle = fopen (sql_file, "r");
561  if (!filehandle)
562  {
563  fmt = _("%s: There was an error reading the file '%s'.\n");
564  qof_main_wrap_line (stderr, ERR_INDENT, fmt, PACKAGE, sql_file);
565  return;
566  }
567  r = g_new (regex_t, 1);
568 #ifndef HAVE_GETLINE
569  while (NULL != (fgets (lineptr, sizeof (lineptr), filehandle)))
570 #else
571  lineptr = NULL;
572  while (0 < getline (&lineptr, &n, filehandle))
573 #endif
574  {
575  reg_exp_check =
576  regcomp (r, pattern, REG_ICASE | REG_NOSUB | REG_EXTENDED);
577  g_return_if_fail (reg_exp_check == 0);
578  if (0 != regexec (r, lineptr, 0, NULL, 0))
579  continue;
580  buf = g_strdup (g_strchomp (lineptr));
581  data->sql_list = g_list_prepend (data->sql_list, buf);
582  }
583  regfree (r);
584  g_free (r);
585  fclose (filehandle);
586  LEAVE (" sql_list=%d", g_list_length (data->sql_list));
587 }
588 
589 void
590 qof_mod_write (const gchar * write_file, QofMainContext * data)
591 {
592  data->write_file = g_strdup (write_file);
593 }
594 
595 void
596 qof_main_show_error (QofSession * session)
597 {
598  const gchar *fmt;
599 
600  if (qof_error_check (session))
601  {
602  fmt = "%s: %s\n";
603  qof_main_wrap_line (stderr, ERR_INDENT, fmt, PACKAGE,
604  qof_error_get_message (session));
605  }
606 }
607 
610 /*==================== END OF FILE ======================*/