QOF  0.7.5
qof-sqlite.c File Reference

Public interface of qof-backend-sqlite. More...

#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <glib/gstdio.h>
#include <sqlite.h>
#include <glib.h>
#include <libintl.h>
#include "qof.h"

Go to the source code of this file.

Macros

#define _(String)   dgettext (GETTEXT_PACKAGE, String)
 
#define ACCESS_METHOD   "sqlite"
 
#define PRIORITY_HIGH   9
 
#define PRIORITY_STANDARD   5
 
#define PRIORITY_LOW   0
 
#define QSQL_ERROR   -1
 
#define QSQL_KVP_TABLE   "sqlite_kvp"
 
#define END_DB_VERSION   " dbversion int );"
 

Enumerations

enum  QsqlStatementType {
  SQL_NONE = 0, SQL_CREATE, SQL_LOAD, SQL_WRITE,
  SQL_INSERT, SQL_DELETE, SQL_UPDATE
}
 

Functions

static gchar * add_to_sql (gchar *sql_str, const gchar *add)
 
static QofIdTypeConst kvp_value_to_qof_type_helper (KvpValueType n)
 Map a KvpValue to a QofIdType. More...
 
static KvpValueType sql_to_kvp_helper (const gchar *type_string)
 
KvpValuestring_to_kvp_value (const gchar *content, KvpValueType type)
 Convert a string value into KvpValue. More...
 
static void kvpvalue_to_sql (const gchar *key, KvpValue *val, gpointer builder)
 
static gchar * string_param_to_sql (QofParam *param)
 
static void create_param_list (QofParam *param, gpointer builder)
 list just the parameter names More...
 
static void create_each_param (QofParam *param, gpointer builder)
 
static void delete_event (QofEntity *ent, QofEventId event_type, gpointer handler_data, gpointer event_data)
 use the new-style event handlers for insert and update insert runs after QOF_EVENT_CREATE delete runs before QOF_EVENT_DESTROY More...
 
static void create_event (QofEntity *ent, QofEventId event_type, gpointer handler_data, gpointer event_data)
 
static void qsql_modify (QofBackend *be, QofInstance *inst)
 
static gint record_foreach (gpointer builder, gint col_num, gchar **strings, gchar **columnNames)
 
static void string_param_foreach (QofParam *param, gpointer builder)
 
static void update_param_foreach (QofParam *param, gpointer builder)
 
static void update_dirty (gpointer value, gpointer builder)
 
static gint create_dirty_list (gpointer builder, gint col_num, gchar **strings, gchar **columnNames)
 
static gint mark_entity (gpointer builder, gint col_num, gchar **strings, gchar **columnNames)
 
static void qsql_create (QofBackend *be, QofInstance *inst)
 
static void check_state (QofEntity *ent, gpointer builder)
 
static gint build_kvp_table (gpointer builder, gint col_num, gchar **strings, gchar **columnNames)
 chekc kvp data once per record More...
 
static void qsql_load_kvp (QSQLiteBackend *qsql_be)
 
static void qsql_class_foreach (QofObject *obj, gpointer data)
 
static void qsql_backend_createdb (QofBackend *be, QofSession *session)
 
static void qsql_backend_opendb (QofBackend *be, QofSession *session)
 
static void qsqlite_session_begin (QofBackend *be, QofSession *session, const gchar *book_path, gboolean ignore_lock, gboolean create_if_nonexistent)
 
static void qsqlite_db_load (QofBackend *be, QofBook *book)
 
static void qsqlite_write_db (QofBackend *be, QofBook *book)
 
static gboolean qsql_determine_file_type (const gchar *path)
 
static void qsqlite_session_end (QofBackend *be)
 
static void qsqlite_destroy_backend (QofBackend *be)
 
static void qsql_provider_free (QofBackendProvider *prov)
 
static QofBackendqsql_backend_new (void)
 Starts the backend and creates the context. More...
 
void qof_sqlite_provider_init (void)
 Initialises the SQLite backend. More...
 

Variables

static QofLogModule log_module = QOF_MOD_SQLITE
 
static gboolean loading = FALSE
 

Detailed Description

Public interface of qof-backend-sqlite.

Author
Copyright 2006-2007 Neil Williams linux.nosp@m.@cod.nosp@m.ehelp.nosp@m..co..nosp@m.uk

Definition in file qof-sqlite.c.

Macro Definition Documentation

#define PRIORITY_HIGH   9

Indicates an item with high priority.

Definition at line 43 of file qof-sqlite.c.

#define PRIORITY_LOW   0

Indicates a low priority item.

Definition at line 47 of file qof-sqlite.c.

#define PRIORITY_STANDARD   5

Indicates an item with default priority.

Definition at line 45 of file qof-sqlite.c.

#define QSQL_ERROR   -1

Indicate an error to sqlite

Definition at line 49 of file qof-sqlite.c.

#define QSQL_KVP_TABLE   "sqlite_kvp"

One KVP table per file for all instances.

Definition at line 51 of file qof-sqlite.c.

Enumeration Type Documentation

Enumerator
SQL_NONE 

no operation defined. init value.

SQL_CREATE 

Create a new database

SQL_LOAD 

Load all data from existing database.

SQL_WRITE 

Write / sync all data to the database.

SQL_INSERT 

Run a single INSERT statement.

SQL_DELETE 

Run a single DELETE statement.

SQL_UPDATE 

Run a single UPDATE statement.

Definition at line 58 of file qof-sqlite.c.

59 {
61  SQL_NONE = 0,
63  SQL_CREATE,
65  SQL_LOAD,
67  SQL_WRITE,
69  SQL_INSERT,
71  SQL_DELETE,

Function Documentation

static gint build_kvp_table ( gpointer  builder,
gint  col_num,
gchar **  strings,
gchar **  columnNames 
)
static

chekc kvp data once per record

creates a new KvpFrame as data for a GHashTable with the guid as key

Todo:
improve error checking support in case the SQLite data is tweaked manually.

Definition at line 1076 of file qof-sqlite.c.

1078 {
1079  QSQLiteBackend *qsql_be;
1080  struct QsqlBuilder *qb;
1081  KvpFrame *frame;
1082  KvpValueType type;
1083  KvpValue *value;
1084  glong max;
1085  gchar *tail;
1086 
1087  g_return_val_if_fail (builder, QSQL_ERROR);
1088  qb = (struct QsqlBuilder *) builder;
1089  max = 0;
1090  qsql_be = qb->qsql_be;
1091  g_return_val_if_fail ((col_num < 4), QSQL_ERROR);
1092  g_return_val_if_fail (strings[2], QSQL_ERROR);
1093  frame = kvp_frame_new ();
1094  /* columnNames = fields strings = values
1095  [0]=kvp_id, [1]=guid, [2]=path, [3]=type, [4]=value
1096  get type from type_string */
1097  type = sql_to_kvp_helper (strings[3]);
1098  if (type == 0)
1099  {
1100  PERR (" invalid type returned from kvp table");
1101  return QSQL_ERROR;
1102  }
1103  /* use the type to make a KvpValue from value */
1104  value = string_to_kvp_value (strings[4], type);
1105  if (!value)
1106  {
1107  PERR (" invalid KvpValue for type: %d", type);
1108  return QSQL_ERROR;
1109  }
1110  /* add the KvpValue to the frame at path */
1111  kvp_frame_set_value (frame, strings[2], value);
1112  /* index the frame under the entity GUID */
1113  g_hash_table_insert (qsql_be->kvp_table, strings[1], frame);
1114  /* index the guid under the kvp_id */
1115  g_hash_table_insert (qsql_be->kvp_id, strings[0], strings[1]);
1116  errno = 0;
1117  max = strtol (strings[0], &tail, 0);
1118  if (errno == 0)
1119  {
1120  qsql_be->index = (max > qsql_be->index) ? max : qsql_be->index;
1121  }
1122  return SQLITE_OK;
1123 }
static void create_each_param ( QofParam param,
gpointer  builder 
)
static

create the sql for each parameter

Bug:
will need to use QofEntityReference here if partial books are actually to be supported.

Definition at line 447 of file qof-sqlite.c.

448 {
449  gchar *value;
450  struct QsqlBuilder *qb;
451  qb = (struct QsqlBuilder *) builder;
452  GList *references;
453 
454  /* avoid creating database fields for calculated values */
455  if (!param->param_setfcn)
456  return;
457  /* avoid setting KVP even if a param_setfcn has been set
458  because a QofSetterFunc for KVP is quite pointless. */
459  if (0 == safe_strcmp (param->param_type, QOF_TYPE_KVP))
460  return;
461  references = qof_class_get_referenceList (qb->ent->e_type);
462  if (g_list_find (references, param))
463  {
466  QofEntity *e;
467  e = param->param_getfcn (qb->ent, param);
468  value = g_strnfill (GUID_ENCODING_LENGTH + 1, ' ');
470  PINFO (" ref=%p GUID=%s", e, value);
471  }
472  else
473  value = qof_util_param_to_string (qb->ent, param);
474  if (value)
475  g_strescape (value, NULL);
476  if (!value)
477  value = g_strdup ("");
478  if (!g_str_has_suffix (qb->sql_str, "("))
479  {
480  gchar *val;
481  val = g_strconcat (", \"", value, "\"", NULL);
482  qb->sql_str = add_to_sql (qb->sql_str, val);
483  g_free (val);
484  }
485  else
486  {
487  gchar *val;
488  val = g_strconcat ("\"", value, "\"", NULL);
489  qb->sql_str = add_to_sql (qb->sql_str, val);
490  g_free (val);
491  }
492 }
static void create_event ( QofEntity ent,
QofEventId  event_type,
gpointer  handler_data,
gpointer  event_data 
)
static

receives QSQLiteBackend, passes on QsqlBuilder

Definition at line 548 of file qof-sqlite.c.

550 {
551  QofBackend *be;
552  struct QsqlBuilder qb;
553  QSQLiteBackend *qsql_be;
554  gchar *gstr;
555  KvpFrame *slots;
556 
557  qsql_be = (QSQLiteBackend *) handler_data;
558  be = (QofBackend *) qsql_be;
559  if (!ent)
560  return;
561  if (0 == safe_strcmp (ent->e_type, QOF_ID_BOOK))
562  return;
563  if (!qof_class_is_registered (ent->e_type))
564  return;
565  switch (event_type)
566  {
567  case QOF_EVENT_CREATE:
568  {
569  gchar *tmp;
570  ENTER (" create:%s", ent->e_type);
571  gstr = g_strnfill (GUID_ENCODING_LENGTH + 1, ' ');
573  ent), gstr);
574  DEBUG (" guid=%s", gstr);
575  qb.ent = ent;
576  qb.sql_str =
577  g_strdup_printf ("INSERT into %s (guid ", ent->e_type);
578  qof_class_param_foreach (ent->e_type, create_param_list, &qb);
579  tmp = g_strconcat (") VALUES (\"", gstr, "\" ", NULL);
580  qb.sql_str = add_to_sql (qb.sql_str, tmp);
581  g_free (tmp);
582  qof_class_param_foreach (ent->e_type, create_each_param, &qb);
583  qb.sql_str = add_to_sql (qb.sql_str, ");");
584  DEBUG (" sql_str=%s", qb.sql_str);
585  if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
586  NULL, &qb, &qsql_be->err) != SQLITE_OK)
587  {
588  qof_error_set_be (be, qsql_be->err_insert);
589  qsql_be->error = TRUE;
590  PERR (" error on create_event:%s", qsql_be->err);
591  }
592  else
593  {
594  ((QofInstance *) ent)->dirty = FALSE;
595  qsql_be->error = FALSE;
596  g_free (qb.sql_str);
597  g_free (gstr);
598  LEAVE (" ");
599  break;
600  }
601  /* insert sqlite_kvp data */
602  slots = qof_instance_get_slots ((QofInstance *) ent);
603  if (slots)
604  {
605  /* id, guid, path, type, value */
606  qb.sql_str = g_strconcat ("INSERT into ", QSQL_KVP_TABLE,
607  " (kvp_id \"", gstr, "\", ", NULL);
609  qb.sql_str = add_to_sql (qb.sql_str, END_DB_VERSION);
610  if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
611  NULL, &qb, &qsql_be->err) != SQLITE_OK)
612  {
613  qof_error_set_be (be, qsql_be->err_insert);
614  qsql_be->error = TRUE;
615  PERR (" error on KVP create_event:%s", qsql_be->err);
616  }
617  else
618  {
619  ((QofInstance *) ent)->dirty = FALSE;
620  qsql_be->error = FALSE;
621  g_free (qb.sql_str);
622  g_free (gstr);
623  LEAVE (" ");
624  break;
625  }
626  }
627  g_free (qb.sql_str);
628  g_free (gstr);
629  LEAVE (" ");
630  break;
631  }
632  default:
633  break;
634  }
635 }
static void create_param_list ( QofParam param,
gpointer  builder 
)
static

list just the parameter names

Note
Must match the number and order of the list of parameter values from create_each_param

Definition at line 419 of file qof-sqlite.c.

420 {
421  struct QsqlBuilder *qb;
422  qb = (struct QsqlBuilder *) builder;
423 
424  /* avoid creating database fields for calculated values */
425  if (!param->param_setfcn)
426  return;
427  /* avoid setting KVP even if a param_setfcn has been set
428  because a QofSetterFunc for KVP is quite pointless. */
429  if (0 == safe_strcmp (param->param_type, QOF_TYPE_KVP))
430  {
431  PINFO (" kvp support tag");
432  return;
433  }
434  if (!g_str_has_suffix (qb->sql_str, "("))
435  {
436  gchar *add;
437  add = g_strconcat (", ", param->param_name, NULL);
438  qb->sql_str = add_to_sql (qb->sql_str, add);
439  g_free (add);
440  }
441  else
442  qb->sql_str = add_to_sql (qb->sql_str, param->param_name);
443 }
static void delete_event ( QofEntity ent,
QofEventId  event_type,
gpointer  handler_data,
gpointer  event_data 
)
static

use the new-style event handlers for insert and update insert runs after QOF_EVENT_CREATE delete runs before QOF_EVENT_DESTROY

Todo:
delete records from QSQL_KVP_TABLE with this GUID

Definition at line 499 of file qof-sqlite.c.

501 {
502  QofBackend *be;
503  QSQLiteBackend *qsql_be;
504  gchar *gstr, *sql_str;
505 
506  qsql_be = (QSQLiteBackend *) handler_data;
507  be = (QofBackend *) qsql_be;
508  if (!ent)
509  return;
510  if (0 == safe_strcmp (ent->e_type, QOF_ID_BOOK))
511  return;
512  /* do not try to delete if only a QofObject has been loaded. */
513  if (!qof_class_is_registered (ent->e_type))
514  return;
515  switch (event_type)
516  {
517  case QOF_EVENT_DESTROY:
518  {
519  ENTER (" %s do_free=%d", ent->e_type,
520  ((QofInstance *) ent)->do_free);
521  gstr = g_strnfill (GUID_ENCODING_LENGTH + 1, ' ');
523  sql_str = g_strconcat ("DELETE from ", ent->e_type, " WHERE ",
524  QOF_TYPE_GUID, "='", gstr, "';", NULL);
525  DEBUG (" sql_str=%s", sql_str);
526  if (sqlite_exec (qsql_be->sqliteh, sql_str,
527  NULL, qsql_be, &qsql_be->err) != SQLITE_OK)
528  {
529  qof_error_set_be (be, qsql_be->err_delete);
530  qsql_be->error = TRUE;
531  LEAVE (" error on delete:%s", qsql_be->err);
532  break;
533  }
535  /* SELECT kvp_id from QSQL_KVP_TABLE where guid = gstr */
536  LEAVE (" %d", event_type);
537  qsql_be->error = FALSE;
538  g_free (gstr);
539  break;
540  }
541  default:
542  break;
543  }
544 }
static QofIdTypeConst kvp_value_to_qof_type_helper ( KvpValueType  n)
static

Map a KvpValue to a QofIdType.

Todo:
reconcile the duplication with the QSF version

Definition at line 145 of file qof-sqlite.c.

146 {
147  switch (n)
148  {
149  case KVP_TYPE_GINT64:
150  {
151  return QOF_TYPE_INT64;
152  break;
153  }
154  case KVP_TYPE_DOUBLE:
155  {
156  return QOF_TYPE_DOUBLE;
157  break;
158  }
159  case KVP_TYPE_NUMERIC:
160  {
161  return QOF_TYPE_NUMERIC;
162  break;
163  }
164  case KVP_TYPE_STRING:
165  {
166  return QOF_TYPE_STRING;
167  break;
168  }
169  case KVP_TYPE_GUID:
170  {
171  return QOF_TYPE_GUID;
172  break;
173  }
174 #ifndef QOF_DISABLE_DEPRECATED
175  case KVP_TYPE_TIMESPEC:
176  {
177  return QOF_TYPE_DATE;
178  break;
179  }
180 #endif
181  case KVP_TYPE_BOOLEAN:
182  {
183  return QOF_TYPE_BOOLEAN;
184  break;
185  }
186  case KVP_TYPE_TIME:
187  {
188  return QOF_TYPE_TIME;
189  break;
190  }
191  default:
192  {
193  return NULL;
194  }
195  }
196 }
static void kvpvalue_to_sql ( const gchar *  key,
KvpValue val,
gpointer  builder 
)
static

returns the VALUES for INSERT in pre-defined order

Definition at line 316 of file qof-sqlite.c.

317 {
318  QSQLiteBackend *qsql_be;
319  struct QsqlBuilder *qb;
320  KvpValueType n;
321  gchar *full_path;
322 
323  full_path = NULL;
324  ENTER (" ");
325  qb = (struct QsqlBuilder *) builder;
326  qsql_be = qb->qsql_be;
327  g_return_if_fail (key && val && qsql_be);
328  n = kvp_value_get_type (val);
329  switch (n)
330  {
331  case KVP_TYPE_GINT64:
332  case KVP_TYPE_DOUBLE:
333  case KVP_TYPE_NUMERIC:
334  case KVP_TYPE_STRING:
335  case KVP_TYPE_GUID:
336  case KVP_TYPE_TIME:
337  case KVP_TYPE_BOOLEAN:
338 #ifndef QOF_DISABLE_DEPRECATED
339  case KVP_TYPE_TIMESPEC:
340 #endif
341  {
342  /* ("kvp_id int primary key not null", "guid char(32)", "path mediumtext",
343  "type mediumtext", "value text", */
344 
345  qb->sql_str =
346  g_strdup_printf (" kvp key=%s val=%s type=%s", key,
349  DEBUG (" %s", qb->sql_str);
350  qb->has_slots = TRUE;
351  break;
352  }
353  case KVP_TYPE_FRAME:
354  {
356  kvpvalue_to_sql, qb);
357  break;
358  }
359  default:
360  {
361  PERR (" unsupported value = %d", kvp_value_get_type (val));
362  break;
363  }
364  }
365  LEAVE (" %s", qb->sql_str);
366 }
static QofBackend* qsql_backend_new ( void  )
static

Starts the backend and creates the context.

Note
Take care when handling the main QSQLiteBackend context and the QsqlBuilder context. QSQLiteBackend contains the long-term data, QsqlBuilder the transient. Only QSQLiteBackend is guaranteed to exist at any one time. All functions need to be able to locate the QSQLiteBackend. Functions started from the QofBackend routines or from the event handlers will be passed the QofBackend which can be cast to QSQLiteBackend. Internal functions create a local QsqlBuilder struct and set the QSQLiteBackend pointer before passing a pointer to the QsqlBuilder. Use the qsql_ prefix only for functions that are started from QofBackend and the _event suffix for QofEvent.

Definition at line 1446 of file qof-sqlite.c.

1447 {
1448  QSQLiteBackend *qsql_be;
1449  QofBackend *be;
1450 
1451  ENTER (" ");
1452  qsql_be = g_new0 (QSQLiteBackend, 1);
1453  be = (QofBackend *) qsql_be;
1454  qof_backend_init (be);
1455  qsql_be->kvp_table = g_hash_table_new (g_str_hash, g_str_equal);
1456  qsql_be->kvp_id = g_hash_table_new (g_str_hash, g_str_equal);
1457  qsql_be->dbversion = QOF_OBJECT_VERSION;
1458  qsql_be->stm_type = SQL_NONE;
1459  qsql_be->err_delete =
1460  qof_error_register (_("Unable to delete record."), FALSE);
1461  qsql_be->err_create =
1462  qof_error_register (_("Unable to create record."), FALSE);
1463  qsql_be->err_insert =
1464  qof_error_register (_("Unable to insert a new record."), FALSE);
1465  qsql_be->err_update =
1466  qof_error_register (_("Unable to update existing record."), FALSE);
1467  be->session_begin = qsqlite_session_begin;
1468 
1469  be->session_end = qsqlite_session_end;
1470  be->destroy_backend = qsqlite_destroy_backend;
1471  be->load = qsqlite_db_load;
1472  be->save_may_clobber_data = NULL;
1473  /* begin: create an empty entity if none exists,
1474  even if events are suspended. */
1475  be->begin = qsql_create;
1476  /* commit: write to sqlite, commit undo record. */
1477  be->commit = qsql_modify;
1478  be->rollback = NULL;
1479  /* would need a QofQuery back to QofSqlQuery conversion. */
1480  be->compile_query = NULL;
1481  /* unused */
1482  be->free_query = NULL;
1483  be->run_query = NULL;
1484  be->counter = NULL;
1485  /* The QOF SQLite backend is not multi-user - all QOF users are the same. */
1486  be->events_pending = NULL;
1487  be->process_events = NULL;
1488 
1489  be->sync = qsqlite_write_db;
1490  be->load_config = NULL;
1491  be->get_config = NULL;
1492  LEAVE (" ");
1493  return be;
1494 }
static void qsql_class_foreach ( QofObject obj,
gpointer  data 
)
static

receives QSQLiteBackend from QofBackend

Definition at line 1168 of file qof-sqlite.c.

1169 {
1170  struct QsqlBuilder qb;
1171  QSQLiteBackend *qsql_be;
1172  QofBackend *be;
1173 
1174  qsql_be = (QSQLiteBackend *) data;
1175  be = (QofBackend *) qsql_be;
1176  qb.qsql_be = qsql_be;
1177  qb.e_type = obj->e_type;
1178  ENTER (" obj_type=%s", qb.e_type);
1179  switch (qsql_be->stm_type)
1180  {
1181  case SQL_NONE:
1182  case SQL_INSERT:
1183  case SQL_DELETE:
1184  case SQL_UPDATE:
1185  {
1186  break;
1187  }
1188  case SQL_CREATE:
1189  {
1190  /* KVP is handled separately */
1191  qb.sql_str =
1192  g_strdup_printf ("CREATE TABLE %s (", obj->e_type);
1193  qof_class_param_foreach (obj->e_type, string_param_foreach,
1194  &qb);
1195  qb.sql_str = add_to_sql (qb.sql_str, END_DB_VERSION);
1196  if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
1197  NULL, NULL, &qsql_be->err) != SQLITE_OK)
1198  {
1199  qof_error_set_be (be, qsql_be->err_create);
1200  qsql_be->error = TRUE;
1201  PERR (" error on SQL_CREATE:%s", qsql_be->err);
1202  }
1203  g_free (qb.sql_str);
1204  break;
1205  }
1206  case SQL_LOAD:
1207  {
1208  qb.sql_str =
1209  g_strdup_printf ("SELECT * FROM %s;", obj->e_type);
1210  PINFO (" sql=%s", qb.sql_str);
1211  if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
1212  record_foreach, &qb, &qsql_be->err) != SQLITE_OK)
1213  {
1214  qsql_be->error = TRUE;
1215  PERR (" error on SQL_LOAD:%s", qsql_be->err);
1216  }
1217  break;
1218  }
1219  case SQL_WRITE:
1220  {
1221  if (!qof_book_not_saved (qsql_be->book))
1222  break;
1223  qof_object_foreach (obj->e_type, qsql_be->book, check_state,
1224  &qb);
1225  break;
1226  }
1227  }
1228  LEAVE (" ");
1229 }
static void qsql_load_kvp ( QSQLiteBackend *  qsql_be)
static

only call once per book

Definition at line 1127 of file qof-sqlite.c.

1128 {
1129  struct QsqlBuilder qb;
1130  QofBackend *be;
1131  gint sq_code;
1132 
1133  g_return_if_fail (qsql_be);
1134  sq_code = SQLITE_OK;
1135  be = (QofBackend *) qsql_be;
1136  qb.sql_str =
1137  g_strdup_printf ("SELECT kvp_id from %s;", QSQL_KVP_TABLE);
1138  sq_code = sqlite_exec (qsql_be->sqliteh, qb.sql_str, build_kvp_table,
1139  &qb, &qsql_be->err);
1140  /* catch older files without a sqlite_kvp table */
1141  if (sq_code == SQLITE_ERROR)
1142  {
1143  g_free (qb.sql_str);
1144  qb.sql_str =
1145  g_strdup_printf ("CREATE TABLE %s (%s, %s, %s, %s, %s, %s",
1146  QSQL_KVP_TABLE, "kvp_id int primary key not null",
1147  "guid char(32)", "path mediumtext", "type mediumtext",
1148  "value text", END_DB_VERSION);
1149  PINFO (" creating kvp table. sql=%s", qb.sql_str);
1150  if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
1151  record_foreach, &qb, &qsql_be->err) != SQLITE_OK)
1152  {
1153  qsql_be->error = TRUE;
1154  PERR (" unable to create kvp table:%s", qsql_be->err);
1155  }
1156  }
1157  else if (sq_code != SQLITE_OK)
1158  {
1159  qof_error_set_be (be, qsql_be->err_create);
1160  qsql_be->error = TRUE;
1161  PERR (" error on KVP select:%s:%s:%d", qb.sql_str, qsql_be->err, sq_code);
1162  }
1163  g_free (qb.sql_str);
1164 }
static gint record_foreach ( gpointer  builder,
gint  col_num,
gchar **  strings,
gchar **  columnNames 
)
static
Todo:
need a KVP version to load data into the slots

Definition at line 713 of file qof-sqlite.c.

715 {
716  QSQLiteBackend *qsql_be;
717  struct QsqlBuilder *qb;
718  const QofParam *param;
719  QofInstance *inst;
720  QofEntity *ent;
721  gint i;
722 
723  g_return_val_if_fail (builder, QSQL_ERROR);
724  qb = (struct QsqlBuilder *) builder;
725  qsql_be = qb->qsql_be;
727  inst = (QofInstance *) qof_object_new_instance (qb->e_type, qsql_be->book);
728  ent = &inst->entity;
729  for (i = 0; i < col_num; i++)
730  {
731  /* get param and set as string */
732  param = qof_class_get_parameter (qb->e_type, columnNames[i]);
733  if (!param)
734  continue;
735  /* set the inst->param entry */
736  inst->param = param;
737  if (0 == safe_strcmp (columnNames[i], QOF_TYPE_GUID))
738  {
739  GUID *guid;
740  guid = guid_malloc ();
741  if (!string_to_guid (strings[i], guid))
742  {
743  DEBUG (" set guid failed:%s", strings[i]);
744  return QSQL_ERROR;
745  }
746  qof_entity_set_guid (ent, guid);
747  }
748  if (strings[i])
749  qof_util_param_set_string (ent, param, strings[i]);
750  }
751  qof_event_resume ();
752  return SQLITE_OK;
753 }
static KvpValueType sql_to_kvp_helper ( const gchar *  type_string)
static
Todo:
reconcile the duplication with the QSF version

Definition at line 200 of file qof-sqlite.c.

201 {
202  if (0 == safe_strcmp (QOF_TYPE_INT64, type_string))
203  return KVP_TYPE_GINT64;
204  if (0 == safe_strcmp (QOF_TYPE_DOUBLE, type_string))
205  return KVP_TYPE_DOUBLE;
206  if (0 == safe_strcmp (QOF_TYPE_NUMERIC, type_string))
207  return KVP_TYPE_NUMERIC;
208  if (0 == safe_strcmp (QOF_TYPE_STRING, type_string))
209  return KVP_TYPE_STRING;
210  if (0 == safe_strcmp (QOF_TYPE_GUID, type_string))
211  return KVP_TYPE_GUID;
212 #ifndef QOF_DISABLE_DEPRECATED
213  if (0 == safe_strcmp (QOF_TYPE_DATE, type_string))
214  return KVP_TYPE_TIMESPEC;
215 #endif
216  if (0 == safe_strcmp (QOF_TYPE_TIME, type_string))
217  return KVP_TYPE_TIME;
218  return 0;
219 }
KvpValue* string_to_kvp_value ( const gchar *  content,
KvpValueType  type 
)

Convert a string value into KvpValue.

Todo:
reconcile the duplication with the QSF version

Definition at line 223 of file qof-sqlite.c.

224 {
225  gchar *tail;
226  gint64 cm_i64;
227  gdouble cm_double;
228  QofNumeric cm_numeric;
229  GUID *cm_guid;
230 #ifndef QOF_DISABLE_DEPRECATED
231  struct tm kvp_time;
232  time_t kvp_time_t;
233  Timespec cm_date;
234 #endif
235 
236  switch (type)
237  {
238  case KVP_TYPE_GINT64:
239  {
240  errno = 0;
241  cm_i64 = strtoll (content, &tail, 0);
242  if (errno == 0)
243  {
244  return kvp_value_new_gint64 (cm_i64);
245  }
246  break;
247  }
248  case KVP_TYPE_DOUBLE:
249  {
250  errno = 0;
251  cm_double = strtod (content, &tail);
252  if (errno == 0)
253  return kvp_value_new_double (cm_double);
254  break;
255  }
256  case KVP_TYPE_NUMERIC:
257  {
258  qof_numeric_from_string (content, &cm_numeric);
259  return kvp_value_new_numeric (cm_numeric);
260  break;
261  }
262  case KVP_TYPE_STRING:
263  {
264  return kvp_value_new_string (content);
265  break;
266  }
267  case KVP_TYPE_GUID:
268  {
269  cm_guid = g_new0 (GUID, 1);
270  if (TRUE == string_to_guid (content, cm_guid))
271  return kvp_value_new_guid (cm_guid);
272  break;
273  }
274  case KVP_TYPE_TIME:
275  {
276  QofDate *qd;
277  QofTime *qt;
278  KvpValue *retval;
279 
280  qd = qof_date_parse (content, QOF_DATE_FORMAT_UTC);
281  if (qd)
282  {
283  qt = qof_date_to_qtime (qd);
284  retval = kvp_value_new_time (qt);
285  qof_date_free (qd);
286  qof_time_free (qt);
287  return retval;
288  }
289  else
290  PERR (" failed to parse date");
291  }
292 #ifndef QOF_DISABLE_DEPRECATED
293  case KVP_TYPE_TIMESPEC:
294  {
295  strptime (content, QOF_UTC_DATE_FORMAT, &kvp_time);
296  kvp_time_t = mktime (&kvp_time);
297  timespecFromTime_t (&cm_date, kvp_time_t);
298  return kvp_value_new_timespec (cm_date);
299  break;
300  }
301 #endif
302  case KVP_TYPE_BOOLEAN:
303  {
304  gboolean val;
305  val = qof_util_bool_to_int (content);
306  return kvp_value_new_boolean (val);
307  }
308  default:
309  break;
310  }
311  return NULL;
312 }