qof-sqlite.c File Reference


Detailed Description

Public interface of qof-backend-sqlite.

Author:
Copyright 2006-2007 Neil Williams <linux@codehelp.co.uk>

Definition in file qof-sqlite.c.

#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.

Defines

#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.
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.
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
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
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
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.
void qof_sqlite_provider_init (void)
 Initialises the SQLite backend.

Variables

static QofLogModule log_module = QOF_MOD_SQLITE
static gboolean loading = FALSE


Define 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

enum QsqlStatementType

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.

00059 {
00061     SQL_NONE = 0,
00063     SQL_CREATE,
00065     SQL_LOAD,
00067     SQL_WRITE,
00069     SQL_INSERT,
00071     SQL_DELETE,
00073     SQL_UPDATE
00074 } QsqlStatementType;


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 1075 of file qof-sqlite.c.

01078 {
01079     QSQLiteBackend *qsql_be;
01080     struct QsqlBuilder *qb;
01081     KvpFrame *frame;
01082     KvpValueType type;
01083     KvpValue *value;
01084     glong max;
01085     gchar *tail;
01086 
01087     g_return_val_if_fail (builder, QSQL_ERROR);
01088     qb = (struct QsqlBuilder *) builder;
01089     max = 0;
01090     qsql_be = qb->qsql_be;
01091     g_return_val_if_fail ((col_num < 4), QSQL_ERROR);
01092     g_return_val_if_fail (strings[2], QSQL_ERROR);
01093     frame = kvp_frame_new ();
01094     /* columnNames = fields strings = values
01095        [0]=kvp_id, [1]=guid, [2]=path, [3]=type, [4]=value
01096        get type from type_string */
01097     type = sql_to_kvp_helper (strings[3]);
01098     if (type == 0)
01099     {
01100         PERR (" invalid type returned from kvp table");
01101         return QSQL_ERROR;
01102     }
01103     /* use the type to make a KvpValue from value */
01104     value = string_to_kvp_value (strings[4], type);
01105     if (!value)
01106     {
01107         PERR (" invalid KvpValue for type: %d", type);
01108         return QSQL_ERROR;
01109     }
01110     /* add the KvpValue to the frame at path */
01111     kvp_frame_set_value (frame, strings[2], value);
01112     /* index the frame under the entity GUID */
01113     g_hash_table_insert (qsql_be->kvp_table, strings[1], frame);
01114     /* index the guid under the kvp_id */
01115     g_hash_table_insert (qsql_be->kvp_id, strings[0], strings[1]);
01116     errno = 0;
01117     max = strtol (strings[0], &tail, 0);
01118     if (errno == 0)
01119     {
01120         qsql_be->index = (max > qsql_be->index) ? max : qsql_be->index;
01121     }
01122     return SQLITE_OK;

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 446 of file qof-sqlite.c.

00448 {
00449     gchar *value;
00450     struct QsqlBuilder *qb;
00451     qb = (struct QsqlBuilder *) builder;
00452     GList *references;
00453 
00454     /* avoid creating database fields for calculated values */
00455     if (!param->param_setfcn)
00456         return;
00457     /* avoid setting KVP even if a param_setfcn has been set
00458        because a QofSetterFunc for KVP is quite pointless. */
00459     if (0 == safe_strcmp (param->param_type, QOF_TYPE_KVP))
00460         return;
00461     references = qof_class_get_referenceList (qb->ent->e_type);
00462     if (g_list_find (references, param))
00463     {
00466         QofEntity *e;
00467         e = param->param_getfcn (qb->ent, param);
00468         value = g_strnfill (GUID_ENCODING_LENGTH + 1, ' ');
00469         guid_to_string_buff (qof_entity_get_guid (e), value);
00470         PINFO (" ref=%p GUID=%s", e, value);
00471     }
00472     else
00473         value = qof_util_param_to_string (qb->ent, param);
00474     if (value)
00475         g_strescape (value, NULL);
00476     if (!value)
00477         value = g_strdup ("");
00478     if (!g_str_has_suffix (qb->sql_str, "("))
00479     {
00480         gchar *val;
00481         val = g_strconcat (", \"", value, "\"", NULL);
00482         qb->sql_str = add_to_sql (qb->sql_str, val);
00483         g_free (val);
00484     }
00485     else
00486     {
00487         gchar *val;
00488         val = g_strconcat ("\"", value, "\"", NULL);
00489         qb->sql_str = add_to_sql (qb->sql_str, val);
00490         g_free (val);
00491     }

static void create_event ( QofEntity ent,
QofEventId  event_type,
gpointer  handler_data,
gpointer  event_data 
) [static]

receives QSQLiteBackend, passes on QsqlBuilder

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

00550 {
00551     QofBackend *be;
00552     struct QsqlBuilder qb;
00553     QSQLiteBackend *qsql_be;
00554     gchar *gstr;
00555     KvpFrame *slots;
00556 
00557     qsql_be = (QSQLiteBackend *) handler_data;
00558     be = (QofBackend *) qsql_be;
00559     if (!ent)
00560         return;
00561     if (0 == safe_strcmp (ent->e_type, QOF_ID_BOOK))
00562         return;
00563     if (!qof_class_is_registered (ent->e_type))
00564         return;
00565     switch (event_type)
00566     {
00567     case QOF_EVENT_CREATE:
00568         {
00569             gchar *tmp;
00570             ENTER (" create:%s", ent->e_type);
00571             gstr = g_strnfill (GUID_ENCODING_LENGTH + 1, ' ');
00572             guid_to_string_buff (qof_instance_get_guid ((QofInstance *)
00573                     ent), gstr);
00574             DEBUG (" guid=%s", gstr);
00575             qb.ent = ent;
00576             qb.sql_str =
00577                 g_strdup_printf ("INSERT into %s (guid ", ent->e_type);
00578             qof_class_param_foreach (ent->e_type, create_param_list, &qb);
00579             tmp = g_strconcat (") VALUES (\"", gstr, "\" ", NULL);
00580             qb.sql_str = add_to_sql (qb.sql_str, tmp);
00581             g_free (tmp);
00582             qof_class_param_foreach (ent->e_type, create_each_param, &qb);
00583             qb.sql_str = add_to_sql (qb.sql_str, ");");
00584             DEBUG (" sql_str=%s", qb.sql_str);
00585             if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
00586                     NULL, &qb, &qsql_be->err) != SQLITE_OK)
00587             {
00588                 qof_error_set_be (be, qsql_be->err_insert);
00589                 qsql_be->error = TRUE;
00590                 PERR (" error on create_event:%s", qsql_be->err);
00591             }
00592             else
00593             {
00594                 ((QofInstance *) ent)->dirty = FALSE;
00595                 qsql_be->error = FALSE;
00596                 g_free (qb.sql_str);
00597                 g_free (gstr);
00598                 LEAVE (" ");
00599                 break;
00600             }
00601             /* insert sqlite_kvp data */
00602             slots = qof_instance_get_slots ((QofInstance *) ent);
00603             if (slots)
00604             {
00605                 /* id, guid, path, type, value */
00606                 qb.sql_str = g_strconcat ("INSERT into ", QSQL_KVP_TABLE,
00607                     "  (kvp_id \"", gstr, "\", ", NULL);
00608                 kvp_frame_for_each_slot (slots, kvpvalue_to_sql, &qb);
00609                 qb.sql_str = add_to_sql (qb.sql_str, END_DB_VERSION);
00610                 if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
00611                         NULL, &qb, &qsql_be->err) != SQLITE_OK)
00612                 {
00613                     qof_error_set_be (be, qsql_be->err_insert);
00614                     qsql_be->error = TRUE;
00615                     PERR (" error on KVP create_event:%s", qsql_be->err);
00616                 }
00617                 else
00618                 {
00619                     ((QofInstance *) ent)->dirty = FALSE;
00620                     qsql_be->error = FALSE;
00621                     g_free (qb.sql_str);
00622                     g_free (gstr);
00623                     LEAVE (" ");
00624                     break;
00625                 }
00626             }
00627             g_free (qb.sql_str);
00628             g_free (gstr);
00629             LEAVE (" ");
00630             break;
00631         }
00632     default:
00633         break;
00634     }

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 418 of file qof-sqlite.c.

00420 {
00421     struct QsqlBuilder *qb;
00422     qb = (struct QsqlBuilder *) builder;
00423 
00424     /* avoid creating database fields for calculated values */
00425     if (!param->param_setfcn)
00426         return;
00427     /* avoid setting KVP even if a param_setfcn has been set
00428        because a QofSetterFunc for KVP is quite pointless. */
00429     if (0 == safe_strcmp (param->param_type, QOF_TYPE_KVP))
00430     {
00431         PINFO (" kvp support tag");
00432         return;
00433     }
00434     if (!g_str_has_suffix (qb->sql_str, "("))
00435     {
00436         gchar *add;
00437         add = g_strconcat (", ", param->param_name, NULL);
00438         qb->sql_str = add_to_sql (qb->sql_str, add);
00439         g_free (add);
00440     }
00441     else
00442         qb->sql_str = add_to_sql (qb->sql_str, param->param_name);

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 498 of file qof-sqlite.c.

00501 {
00502     QofBackend *be;
00503     QSQLiteBackend *qsql_be;
00504     gchar *gstr, *sql_str;
00505 
00506     qsql_be = (QSQLiteBackend *) handler_data;
00507     be = (QofBackend *) qsql_be;
00508     if (!ent)
00509         return;
00510     if (0 == safe_strcmp (ent->e_type, QOF_ID_BOOK))
00511         return;
00512     /* do not try to delete if only a QofObject has been loaded. */
00513     if (!qof_class_is_registered (ent->e_type))
00514         return;
00515     switch (event_type)
00516     {
00517     case QOF_EVENT_DESTROY:
00518         {
00519             ENTER (" %s do_free=%d", ent->e_type,
00520                 ((QofInstance *) ent)->do_free);
00521             gstr = g_strnfill (GUID_ENCODING_LENGTH + 1, ' ');
00522             guid_to_string_buff (qof_entity_get_guid (ent), gstr);
00523             sql_str = g_strconcat ("DELETE from ", ent->e_type, " WHERE ",
00524                 QOF_TYPE_GUID, "='", gstr, "';", NULL);
00525             DEBUG (" sql_str=%s", sql_str);
00526             if (sqlite_exec (qsql_be->sqliteh, sql_str,
00527                     NULL, qsql_be, &qsql_be->err) != SQLITE_OK)
00528             {
00529                 qof_error_set_be (be, qsql_be->err_delete);
00530                 qsql_be->error = TRUE;
00531                 LEAVE (" error on delete:%s", qsql_be->err);
00532                 break;
00533             }
00535             /* SELECT kvp_id from QSQL_KVP_TABLE where guid = gstr */
00536             LEAVE (" %d", event_type);
00537             qsql_be->error = FALSE;
00538             g_free (gstr);
00539             break;
00540         }
00541     default:
00542         break;
00543     }

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.

00146 {
00147     switch (n)
00148     {
00149     case KVP_TYPE_GINT64:
00150         {
00151             return QOF_TYPE_INT64;
00152             break;
00153         }
00154     case KVP_TYPE_DOUBLE:
00155         {
00156             return QOF_TYPE_DOUBLE;
00157             break;
00158         }
00159     case KVP_TYPE_NUMERIC:
00160         {
00161             return QOF_TYPE_NUMERIC;
00162             break;
00163         }
00164     case KVP_TYPE_STRING:
00165         {
00166             return QOF_TYPE_STRING;
00167             break;
00168         }
00169     case KVP_TYPE_GUID:
00170         {
00171             return QOF_TYPE_GUID;
00172             break;
00173         }
00174 #ifndef QOF_DISABLE_DEPRECATED
00175     case KVP_TYPE_TIMESPEC:
00176         {
00177             return QOF_TYPE_DATE;
00178             break;
00179         }
00180 #endif
00181     case KVP_TYPE_BOOLEAN:
00182         {
00183             return QOF_TYPE_BOOLEAN;
00184             break;
00185         }
00186     case KVP_TYPE_TIME:
00187         {
00188             return QOF_TYPE_TIME;
00189             break;
00190         }
00191     default:
00192         {
00193             return NULL;
00194         }
00195     }
00196 }

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.

00317 {
00318     QSQLiteBackend *qsql_be;
00319     struct QsqlBuilder *qb;
00320     KvpValueType n;
00321     gchar *full_path;
00322 
00323     full_path = NULL;
00324     ENTER (" ");
00325     qb = (struct QsqlBuilder *) builder;
00326     qsql_be = qb->qsql_be;
00327     g_return_if_fail (key && val && qsql_be);
00328     n = kvp_value_get_type (val);
00329     switch (n)
00330     {
00331     case KVP_TYPE_GINT64:
00332     case KVP_TYPE_DOUBLE:
00333     case KVP_TYPE_NUMERIC:
00334     case KVP_TYPE_STRING:
00335     case KVP_TYPE_GUID:
00336     case KVP_TYPE_TIME:
00337     case KVP_TYPE_BOOLEAN:
00338 #ifndef QOF_DISABLE_DEPRECATED
00339     case KVP_TYPE_TIMESPEC:
00340 #endif
00341         {
00342             /* ("kvp_id int primary key not null", "guid char(32)", "path mediumtext",
00343                "type mediumtext", "value text", */
00344 
00345             qb->sql_str =
00346                 g_strdup_printf (" kvp key=%s val=%s type=%s", key,
00347                 kvp_value_to_bare_string (val),
00348                 kvp_value_to_qof_type_helper (n));
00349             DEBUG (" %s", qb->sql_str);
00350             qb->has_slots = TRUE;
00351             break;
00352         }
00353     case KVP_TYPE_FRAME:
00354         {
00355             kvp_frame_for_each_slot (kvp_value_get_frame (val),
00356                 kvpvalue_to_sql, qb);
00357             break;
00358         }
00359     default:
00360         {
00361             PERR (" unsupported value = %d", kvp_value_get_type (val));
00362             break;
00363         }
00364     }
00365     LEAVE (" %s", qb->sql_str);
00366 }

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 1445 of file qof-sqlite.c.

01447 {
01448     QSQLiteBackend *qsql_be;
01449     QofBackend *be;
01450 
01451     ENTER (" ");
01452     qsql_be = g_new0 (QSQLiteBackend, 1);
01453     be = (QofBackend *) qsql_be;
01454     qof_backend_init (be);
01455     qsql_be->kvp_table = g_hash_table_new (g_str_hash, g_str_equal);
01456     qsql_be->kvp_id = g_hash_table_new (g_str_hash, g_str_equal);
01457     qsql_be->dbversion = QOF_OBJECT_VERSION;
01458     qsql_be->stm_type = SQL_NONE;
01459     qsql_be->err_delete =
01460         qof_error_register (_("Unable to delete record."), FALSE);
01461     qsql_be->err_create =
01462         qof_error_register (_("Unable to create record."), FALSE);
01463     qsql_be->err_insert =
01464         qof_error_register (_("Unable to insert a new record."), FALSE);
01465     qsql_be->err_update =
01466         qof_error_register (_("Unable to update existing record."), FALSE);
01467     be->session_begin = qsqlite_session_begin;
01468 
01469     be->session_end = qsqlite_session_end;
01470     be->destroy_backend = qsqlite_destroy_backend;
01471     be->load = qsqlite_db_load;
01472     be->save_may_clobber_data = NULL;
01473     /* begin: create an empty entity if none exists,
01474        even if events are suspended. */
01475     be->begin = qsql_create;
01476     /* commit: write to sqlite, commit undo record. */
01477     be->commit = qsql_modify;
01478     be->rollback = NULL;
01479     /* would need a QofQuery back to QofSqlQuery conversion. */
01480     be->compile_query = NULL;
01481     /* unused */
01482     be->free_query = NULL;
01483     be->run_query = NULL;
01484     be->counter = NULL;
01485     /* The QOF SQLite backend is not multi-user - all QOF users are the same. */
01486     be->events_pending = NULL;
01487     be->process_events = NULL;
01488 
01489     be->sync = qsqlite_write_db;
01490     be->load_config = NULL;
01491     be->get_config = NULL;
01492     LEAVE (" ");
01493     return be;

static void qsql_class_foreach ( QofObject obj,
gpointer  data 
) [static]

receives QSQLiteBackend from QofBackend

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

01169 {
01170     struct QsqlBuilder qb;
01171     QSQLiteBackend *qsql_be;
01172     QofBackend *be;
01173 
01174     qsql_be = (QSQLiteBackend *) data;
01175     be = (QofBackend *) qsql_be;
01176     qb.qsql_be = qsql_be;
01177     qb.e_type = obj->e_type;
01178     ENTER (" obj_type=%s", qb.e_type);
01179     switch (qsql_be->stm_type)
01180     {
01181     case SQL_NONE:
01182     case SQL_INSERT:
01183     case SQL_DELETE:
01184     case SQL_UPDATE:
01185         {
01186             break;
01187         }
01188     case SQL_CREATE:
01189         {
01190             /* KVP is handled separately */
01191             qb.sql_str =
01192                 g_strdup_printf ("CREATE TABLE %s (", obj->e_type);
01193             qof_class_param_foreach (obj->e_type, string_param_foreach,
01194                 &qb);
01195             qb.sql_str = add_to_sql (qb.sql_str, END_DB_VERSION);
01196             if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
01197                     NULL, NULL, &qsql_be->err) != SQLITE_OK)
01198             {
01199                 qof_error_set_be (be, qsql_be->err_create);
01200                 qsql_be->error = TRUE;
01201                 PERR (" error on SQL_CREATE:%s", qsql_be->err);
01202             }
01203             g_free (qb.sql_str);
01204             break;
01205         }
01206     case SQL_LOAD:
01207         {
01208             qb.sql_str =
01209                 g_strdup_printf ("SELECT * FROM %s;", obj->e_type);
01210             PINFO (" sql=%s", qb.sql_str);
01211             if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
01212                     record_foreach, &qb, &qsql_be->err) != SQLITE_OK)
01213             {
01214                 qsql_be->error = TRUE;
01215                 PERR (" error on SQL_LOAD:%s", qsql_be->err);
01216             }
01217             break;
01218         }
01219     case SQL_WRITE:
01220         {
01221             if (!qof_book_not_saved (qsql_be->book))
01222                 break;
01223             qof_object_foreach (obj->e_type, qsql_be->book, check_state,
01224                 &qb);
01225             break;
01226         }
01227     }
01228     LEAVE (" ");

static void qsql_load_kvp ( QSQLiteBackend *  qsql_be  )  [static]

only call once per book

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

01128 {
01129     struct QsqlBuilder qb;
01130     QofBackend *be;
01131     gint sq_code;
01132 
01133     g_return_if_fail (qsql_be);
01134     sq_code = SQLITE_OK;
01135     be = (QofBackend *) qsql_be;
01136     qb.sql_str =
01137         g_strdup_printf ("SELECT kvp_id from %s;", QSQL_KVP_TABLE);
01138     sq_code = sqlite_exec (qsql_be->sqliteh, qb.sql_str, build_kvp_table,
01139             &qb, &qsql_be->err);
01140     /* catch older files without a sqlite_kvp table */
01141     if (sq_code == SQLITE_ERROR)
01142     {
01143         g_free (qb.sql_str);
01144         qb.sql_str =
01145             g_strdup_printf ("CREATE TABLE %s (%s, %s, %s, %s, %s, %s",
01146             QSQL_KVP_TABLE, "kvp_id int primary key not null",
01147             "guid char(32)", "path mediumtext", "type mediumtext",
01148             "value text", END_DB_VERSION);
01149         PINFO (" creating kvp table. sql=%s", qb.sql_str);
01150         if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
01151             record_foreach, &qb, &qsql_be->err) != SQLITE_OK)
01152         {
01153             qsql_be->error = TRUE;
01154             PERR (" unable to create kvp table:%s", qsql_be->err);
01155         }
01156     }
01157     else if (sq_code != SQLITE_OK)
01158     {
01159         qof_error_set_be (be, qsql_be->err_create);
01160         qsql_be->error = TRUE;
01161         PERR (" error on KVP select:%s:%s:%d", qb.sql_str, qsql_be->err, sq_code);
01162     }
01163     g_free (qb.sql_str);

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 712 of file qof-sqlite.c.

00715 {
00716     QSQLiteBackend *qsql_be;
00717     struct QsqlBuilder *qb;
00718     const QofParam *param;
00719     QofInstance *inst;
00720     QofEntity *ent;
00721     gint i;
00722 
00723     g_return_val_if_fail (builder, QSQL_ERROR);
00724     qb = (struct QsqlBuilder *) builder;
00725     qsql_be = qb->qsql_be;
00726     qof_event_suspend ();
00727     inst = (QofInstance *) qof_object_new_instance (qb->e_type, qsql_be->book);
00728     ent = &inst->entity;
00729     for (i = 0; i < col_num; i++)
00730     {
00731         /* get param and set as string */
00732         param = qof_class_get_parameter (qb->e_type, columnNames[i]);
00733         if (!param)
00734             continue;
00735         /* set the inst->param entry */
00736         inst->param = param;
00737         if (0 == safe_strcmp (columnNames[i], QOF_TYPE_GUID))
00738         {
00739             GUID *guid;
00740             guid = guid_malloc ();
00741             if (!string_to_guid (strings[i], guid))
00742             {
00743                 DEBUG (" set guid failed:%s", strings[i]);
00744                 return QSQL_ERROR;
00745             }
00746             qof_entity_set_guid (ent, guid);
00747         }
00748         if (strings[i])
00749             qof_util_param_set_string (ent, param, strings[i]);
00750     }
00751     qof_event_resume ();
00752     return SQLITE_OK;

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.

00201 {
00202     if (0 == safe_strcmp (QOF_TYPE_INT64, type_string))
00203         return KVP_TYPE_GINT64;
00204     if (0 == safe_strcmp (QOF_TYPE_DOUBLE, type_string))
00205         return KVP_TYPE_DOUBLE;
00206     if (0 == safe_strcmp (QOF_TYPE_NUMERIC, type_string))
00207         return KVP_TYPE_NUMERIC;
00208     if (0 == safe_strcmp (QOF_TYPE_STRING, type_string))
00209         return KVP_TYPE_STRING;
00210     if (0 == safe_strcmp (QOF_TYPE_GUID, type_string))
00211         return KVP_TYPE_GUID;
00212 #ifndef QOF_DISABLE_DEPRECATED
00213     if (0 == safe_strcmp (QOF_TYPE_DATE, type_string))
00214         return KVP_TYPE_TIMESPEC;
00215 #endif
00216     if (0 == safe_strcmp (QOF_TYPE_TIME, type_string))
00217         return KVP_TYPE_TIME;
00218     return 0;
00219 }

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.

00224 {
00225     gchar *tail;
00226     gint64 cm_i64;
00227     gdouble cm_double;
00228     QofNumeric cm_numeric;
00229     GUID *cm_guid;
00230 #ifndef QOF_DISABLE_DEPRECATED
00231     struct tm kvp_time;
00232     time_t kvp_time_t;
00233     Timespec cm_date;
00234 #endif
00235 
00236     switch (type)
00237     {
00238     case KVP_TYPE_GINT64:
00239         {
00240             errno = 0;
00241             cm_i64 = strtoll (content, &tail, 0);
00242             if (errno == 0)
00243             {
00244                 return kvp_value_new_gint64 (cm_i64);
00245             }
00246             break;
00247         }
00248     case KVP_TYPE_DOUBLE:
00249         {
00250             errno = 0;
00251             cm_double = strtod (content, &tail);
00252             if (errno == 0)
00253                 return kvp_value_new_double (cm_double);
00254             break;
00255         }
00256     case KVP_TYPE_NUMERIC:
00257         {
00258             qof_numeric_from_string (content, &cm_numeric);
00259             return kvp_value_new_numeric (cm_numeric);
00260             break;
00261         }
00262     case KVP_TYPE_STRING:
00263         {
00264             return kvp_value_new_string (content);
00265             break;
00266         }
00267     case KVP_TYPE_GUID:
00268         {
00269             cm_guid = g_new0 (GUID, 1);
00270             if (TRUE == string_to_guid (content, cm_guid))
00271                 return kvp_value_new_guid (cm_guid);
00272             break;
00273         }
00274     case KVP_TYPE_TIME:
00275         {
00276             QofDate *qd;
00277             QofTime *qt;
00278             KvpValue *retval;
00279 
00280             qd = qof_date_parse (content, QOF_DATE_FORMAT_UTC);
00281             if (qd)
00282             {
00283                 qt = qof_date_to_qtime (qd);
00284                 retval = kvp_value_new_time (qt);
00285                 qof_date_free (qd);
00286                 qof_time_free (qt);
00287                 return retval;
00288             }
00289             else
00290                 PERR (" failed to parse date");
00291         }
00292 #ifndef QOF_DISABLE_DEPRECATED
00293     case KVP_TYPE_TIMESPEC:
00294         {
00295             strptime (content, QOF_UTC_DATE_FORMAT, &kvp_time);
00296             kvp_time_t = mktime (&kvp_time);
00297             timespecFromTime_t (&cm_date, kvp_time_t);
00298             return kvp_value_new_timespec (cm_date);
00299             break;
00300         }
00301 #endif
00302     case KVP_TYPE_BOOLEAN:
00303         {
00304             gboolean val;
00305             val = qof_util_bool_to_int (content);
00306             return kvp_value_new_boolean (val);
00307         }
00308     default:
00309         break;
00310     }
00311     return NULL;
00312 }


Generated on Thu Jan 31 22:50:26 2008 for QOF by  doxygen 1.5.4