|
QOF
0.8.7
|
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"#include "qofsql-p.h"#include "qof-sqlite.h"#include "kvputil-p.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 );" |
Functions | |
| static KvpValue * | string_to_kvp_value (const gchar *content, KvpValueType type) |
| static G_GNUC_UNUSED void | kvpvalue_to_sql (const gchar *key, KvpValue *val, 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 | 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 QofBackend * | qsql_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 |
Public interface of qof-backend-sqlite.
Definition in file qof-sqlite.c.
| #define PRIORITY_HIGH 9 |
Indicates an item with high priority.
Definition at line 46 of file qof-sqlite.c.
| #define PRIORITY_LOW 0 |
Indicates a low priority item.
Definition at line 50 of file qof-sqlite.c.
| #define PRIORITY_STANDARD 5 |
Indicates an item with default priority.
Definition at line 48 of file qof-sqlite.c.
| #define QSQL_ERROR -1 |
Indicate an error to sqlite
Definition at line 52 of file qof-sqlite.c.
| #define QSQL_KVP_TABLE "sqlite_kvp" |
One KVP table per file for all instances.
Definition at line 55 of file qof-sqlite.c.
| 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
Definition at line 663 of file qof-sqlite.c.
{
QSQLiteBackend *qsql_be;
struct QsqlBuilder *qb;
KvpFrame *frame;
KvpValueType type;
KvpValue *value;
gulong max;
gchar *tail;
g_return_val_if_fail (builder, QSQL_ERROR);
qb = (struct QsqlBuilder *) builder;
max = 0;
qsql_be = qb->qsql_be;
g_return_val_if_fail ((col_num < 4), QSQL_ERROR);
g_return_val_if_fail (strings[2], QSQL_ERROR);
frame = kvp_frame_new ();
/* columnNames = fields strings = values
[0]=kvp_id, [1]=guid, [2]=path, [3]=type, [4]=value
get type from type_string */
type = qof_id_to_kvp_value_type (strings[3]);
if (type == 0)
{
PERR (" invalid type returned from kvp table");
return QSQL_ERROR;
}
/* use the type to make a KvpValue from value */
value = string_to_kvp_value (strings[4], type);
if (!value)
{
PERR (" invalid KvpValue for type: %d", type);
return QSQL_ERROR;
}
/* add the KvpValue to the frame at path */
kvp_frame_set_value (frame, strings[2], value);
/* index the frame under the entity GUID */
g_hash_table_insert (qsql_be->kvp_table, strings[1], frame);
/* index the guid under the kvp_id */
g_hash_table_insert (qsql_be->kvp_id, strings[0], strings[1]);
errno = 0;
max = strtol (strings[0], &tail, 0);
if (errno == 0)
{
qsql_be->index = (max > qsql_be->index) ? max : qsql_be->index;
}
return SQLITE_OK;
}
| static void create_event | ( | QofEntity * | ent, |
| QofEventId | event_type, | ||
| gpointer | handler_data, | ||
| gpointer | event_data | ||
| ) | [static] |
receives QSQLiteBackend, passes on QsqlBuilder
Definition at line 293 of file qof-sqlite.c.
{
QofBackend *be;
struct QsqlBuilder qb;
QSQLiteBackend *qsql_be;
gchar *gstr;
KvpFrame *slots;
qsql_be = (QSQLiteBackend *) handler_data;
be = (QofBackend *) qsql_be;
if (!ent)
return;
if (0 == safe_strcmp (ent->e_type, QOF_ID_BOOK))
return;
if (!qof_class_is_registered (ent->e_type))
return;
switch (event_type)
{
case QOF_EVENT_CREATE:
{
ENTER (" insert:%s", ent->e_type);
gstr = g_strnfill (GUID_ENCODING_LENGTH + 1, ' ');
guid_to_string_buff (qof_instance_get_guid ((QofInstance *)
ent), gstr);
DEBUG (" guid=%s", gstr);
qb.ent = ent;
qb.sql_str = qof_sql_entity_insert (ent);
DEBUG (" sql_str=%s", qb.sql_str);
if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
NULL, &qb, &qsql_be->err) != SQLITE_OK)
{
qof_error_set_be (be, qsql_be->err_insert);
qsql_be->error = TRUE;
PERR (" error on create_event:%s", qsql_be->err);
}
else
{
((QofInstance *) ent)->dirty = FALSE;
qsql_be->error = FALSE;
g_free (qb.sql_str);
g_free (gstr);
LEAVE (" ");
break;
}
/* insert sqlite_kvp data */
slots = qof_instance_get_slots ((QofInstance *) ent);
if (slots)
{
/* id, guid, path, type, value */
qb.sql_str = qof_sql_entity_insert (ent);
if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
NULL, &qb, &qsql_be->err) != SQLITE_OK)
{
qof_error_set_be (be, qsql_be->err_insert);
qsql_be->error = TRUE;
PERR (" error on KVP create_event:%s", qsql_be->err);
}
else
{
((QofInstance *) ent)->dirty = FALSE;
qsql_be->error = FALSE;
g_free (qb.sql_str);
g_free (gstr);
LEAVE (" ");
break;
}
}
g_free (qb.sql_str);
g_free (gstr);
LEAVE (" ");
break;
}
default:
break;
}
}
| static G_GNUC_UNUSED void kvpvalue_to_sql | ( | const gchar * | key, |
| KvpValue * | val, | ||
| gpointer | builder | ||
| ) | [static] |
returns the VALUES for INSERT in pre-defined order
Definition at line 195 of file qof-sqlite.c.
{
QSQLiteBackend *qsql_be;
struct QsqlBuilder *qb;
KvpValueType n;
ENTER (" ");
qb = (struct QsqlBuilder *) builder;
qsql_be = qb->qsql_be;
g_return_if_fail (key && val && qsql_be);
n = kvp_value_get_type (val);
switch (n)
{
case KVP_TYPE_GINT64:
case KVP_TYPE_DOUBLE:
case KVP_TYPE_NUMERIC:
case KVP_TYPE_STRING:
case KVP_TYPE_GUID:
case KVP_TYPE_TIME:
case KVP_TYPE_BOOLEAN:
{
/* ("kvp_id int primary key not null", "guid char(32)", "path mediumtext",
"type mediumtext", "value text", */
qb->sql_str =
g_strdup_printf (" kvp key=%s val=%s type=%s", key,
kvp_value_to_bare_string (val),
kvp_value_type_to_qof_id (n));
DEBUG (" %s", qb->sql_str);
qb->has_slots = TRUE;
break;
}
case KVP_TYPE_FRAME:
{
kvp_frame_for_each_slot (kvp_value_get_frame (val),
kvpvalue_to_sql, qb);
break;
}
default:
{
PERR (" unsupported value = %d", kvp_value_get_type (val));
break;
}
}
LEAVE (" %s", qb->sql_str);
}
| static QofBackend* qsql_backend_new | ( | void | ) | [static] |
Starts the backend and creates the context.
Definition at line 1012 of file qof-sqlite.c.
{
QSQLiteBackend *qsql_be;
QofBackend *be;
ENTER (" ");
qsql_be = g_new0 (QSQLiteBackend, 1);
be = (QofBackend *) qsql_be;
qof_backend_init (be);
qsql_be->kvp_table = g_hash_table_new (g_str_hash, g_str_equal);
qsql_be->kvp_id = g_hash_table_new (g_str_hash, g_str_equal);
qsql_be->dbversion = QOF_OBJECT_VERSION;
qsql_be->stm_type = SQL_NONE;
qsql_be->err_delete =
qof_error_register (_("Unable to delete record."), FALSE);
qsql_be->err_create =
qof_error_register (_("Unable to create record."), FALSE);
qsql_be->err_insert =
qof_error_register (_("Unable to insert a new record."), FALSE);
qsql_be->err_update =
qof_error_register (_("Unable to update existing record."), FALSE);
be->session_begin = qsqlite_session_begin;
be->session_end = qsqlite_session_end;
be->destroy_backend = qsqlite_destroy_backend;
be->load = qsqlite_db_load;
be->save_may_clobber_data = NULL;
/* begin: create an empty entity if none exists,
even if events are suspended. */
be->begin = qsql_create;
/* commit: write to sqlite, commit undo record. */
be->commit = qsql_modify;
be->rollback = NULL;
/* would need a QofQuery back to QofSqlQuery conversion. */
be->compile_query = NULL;
/* unused */
be->free_query = NULL;
be->run_query = NULL;
be->counter = NULL;
/* The QOF SQLite backend is not multi-user - all QOF users are the same. */
be->events_pending = NULL;
be->process_events = NULL;
be->sync = qsqlite_write_db;
be->load_config = NULL;
be->get_config = NULL;
LEAVE (" ");
return be;
}
| static void qsql_class_foreach | ( | QofObject * | obj, |
| gpointer | data | ||
| ) | [static] |
receives QSQLiteBackend from QofBackend
Definition at line 755 of file qof-sqlite.c.
{
struct QsqlBuilder qb;
QSQLiteBackend *qsql_be;
QofBackend *be;
qsql_be = (QSQLiteBackend *) data;
be = (QofBackend *) qsql_be;
qb.qsql_be = qsql_be;
qb.e_type = obj->e_type;
ENTER (" obj_type=%s", qb.e_type);
switch (qsql_be->stm_type)
{
case SQL_NONE:
case SQL_INSERT:
case SQL_DELETE:
case SQL_UPDATE:
{
break;
}
case SQL_CREATE:
{
/* KVP is handled separately */
qb.sql_str = qof_sql_object_create_table (obj);
if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
NULL, NULL, &qsql_be->err) != SQLITE_OK)
{
qof_error_set_be (be, qsql_be->err_create);
qsql_be->error = TRUE;
PERR (" error on SQL_CREATE:%s", qsql_be->err);
}
g_free (qb.sql_str);
break;
}
case SQL_LOAD:
{
qb.sql_str =
g_strdup_printf ("SELECT * FROM %s;", obj->e_type);
PINFO (" sql=%s", qb.sql_str);
if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
record_foreach, &qb, &qsql_be->err) != SQLITE_OK)
{
qsql_be->error = TRUE;
PERR (" error on SQL_LOAD:%s", qsql_be->err);
}
break;
}
case SQL_WRITE:
{
if (!qof_book_not_saved (qsql_be->book))
break;
qof_object_foreach (obj->e_type, qsql_be->book, check_state,
&qb);
break;
}
}
LEAVE (" ");
}
| static void qsql_load_kvp | ( | QSQLiteBackend * | qsql_be | ) | [static] |
only call once per book
Definition at line 714 of file qof-sqlite.c.
{
struct QsqlBuilder qb;
QofBackend *be;
gint sq_code;
g_return_if_fail (qsql_be);
sq_code = SQLITE_OK;
be = (QofBackend *) qsql_be;
qb.sql_str =
g_strdup_printf ("SELECT kvp_id from %s;", QSQL_KVP_TABLE);
sq_code = sqlite_exec (qsql_be->sqliteh, qb.sql_str, build_kvp_table,
&qb, &qsql_be->err);
/* catch older files without a sqlite_kvp table */
if (sq_code == SQLITE_ERROR)
{
g_free (qb.sql_str);
qb.sql_str =
g_strdup_printf ("CREATE TABLE %s (%s, %s, %s, %s, %s, %s",
QSQL_KVP_TABLE, "kvp_id int primary key not null",
"guid char(32)", "path mediumtext", "type mediumtext",
"value text", END_DB_VERSION);
PINFO (" creating kvp table. sql=%s", qb.sql_str);
if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
record_foreach, &qb, &qsql_be->err) != SQLITE_OK)
{
qsql_be->error = TRUE;
PERR (" unable to create kvp table:%s", qsql_be->err);
}
}
else if (sq_code != SQLITE_OK)
{
qof_error_set_be (be, qsql_be->err_create);
qsql_be->error = TRUE;
PERR (" error on KVP select:%s:%s:%d", qb.sql_str, qsql_be->err, sq_code);
}
g_free (qb.sql_str);
}
| static gint record_foreach | ( | gpointer | builder, |
| gint | col_num, | ||
| gchar ** | strings, | ||
| gchar ** | columnNames | ||
| ) | [static] |
Definition at line 417 of file qof-sqlite.c.
{
QSQLiteBackend *qsql_be;
struct QsqlBuilder *qb;
const QofParam *param;
QofInstance *inst;
QofEntity *ent;
gint i;
g_return_val_if_fail (builder, QSQL_ERROR);
qb = (struct QsqlBuilder *) builder;
qsql_be = qb->qsql_be;
qof_event_suspend ();
inst = (QofInstance *) qof_object_new_instance (qb->e_type, qsql_be->book);
ent = &inst->entity;
for (i = 0; i < col_num; i++)
{
/* get param and set as string */
param = qof_class_get_parameter (qb->e_type, columnNames[i]);
if (!param)
continue;
/* set the inst->param entry */
inst->param = param;
if (0 == safe_strcmp (columnNames[i], QOF_TYPE_GUID))
{
GUID *guid;
guid = guid_malloc ();
if (!string_to_guid (strings[i], guid))
{
DEBUG (" set guid failed:%s", strings[i]);
return QSQL_ERROR;
}
qof_entity_set_guid (ent, guid);
}
if (strings[i])
qof_util_param_set_string (ent, param, strings[i]);
}
qof_event_resume ();
return SQLITE_OK;
}
| static KvpValue* string_to_kvp_value | ( | const gchar * | content, |
| KvpValueType | type | ||
| ) | [static] |
Definition at line 117 of file qof-sqlite.c.
{
gchar *tail;
gint64 cm_i64;
gdouble cm_double;
QofNumeric cm_numeric;
GUID *cm_guid;
switch (type)
{
case KVP_TYPE_GINT64:
{
errno = 0;
cm_i64 = strtoll (content, &tail, 0);
if (errno == 0)
{
return kvp_value_new_gint64 (cm_i64);
}
break;
}
case KVP_TYPE_DOUBLE:
{
errno = 0;
cm_double = strtod (content, &tail);
if (errno == 0)
return kvp_value_new_double (cm_double);
break;
}
case KVP_TYPE_NUMERIC:
{
qof_numeric_from_string (content, &cm_numeric);
return kvp_value_new_numeric (cm_numeric);
break;
}
case KVP_TYPE_STRING:
{
return kvp_value_new_string (content);
break;
}
case KVP_TYPE_GUID:
{
cm_guid = g_new0 (GUID, 1);
if (TRUE == string_to_guid (content, cm_guid))
return kvp_value_new_guid (cm_guid);
break;
}
case KVP_TYPE_TIME:
{
QofDate *qd;
QofTime *qt;
KvpValue *retval;
qd = qof_date_parse (content, QOF_DATE_FORMAT_UTC);
if (qd)
{
qt = qof_date_to_qtime (qd);
retval = kvp_value_new_time (qt);
qof_date_free (qd);
qof_time_free (qt);
return retval;
}
else
PERR (" failed to parse date");
}
case KVP_TYPE_BOOLEAN:
{
gboolean val;
val = qof_util_bool_to_int (content);
return kvp_value_new_boolean (val);
}
default:
break;
}
return NULL;
}
1.7.6.1