28 #include <glib/gstdio.h> 37 #define _(String) dgettext (GETTEXT_PACKAGE, String) 38 #define ACCESS_METHOD "sqlite" 46 #define PRIORITY_HIGH 9 48 #define PRIORITY_STANDARD 5 50 #define PRIORITY_LOW 0 55 #define QSQL_KVP_TABLE "sqlite_kvp" 57 #define END_DB_VERSION " dbversion int );" 60 static gboolean loading = FALSE;
76 const gchar *fullpath;
80 GHashTable *kvp_table;
86 QofErrorId err_delete, err_insert, err_update, err_create;
98 QSQLiteBackend *qsql_be;
130 cm_i64 = strtoll (content, &tail, 0);
133 return kvp_value_new_gint64 (cm_i64);
140 cm_double = strtod (content, &tail);
142 return kvp_value_new_double (cm_double);
148 return kvp_value_new_numeric (cm_numeric);
153 return kvp_value_new_string (content);
158 cm_guid = g_new0 (
GUID, 1);
160 return kvp_value_new_guid (cm_guid);
173 retval = kvp_value_new_time (qt);
179 PERR (
" failed to parse date");
194 static G_GNUC_UNUSED
void 197 QSQLiteBackend *qsql_be;
198 struct QsqlBuilder *qb;
202 qb = (
struct QsqlBuilder *) builder;
203 qsql_be = qb->qsql_be;
204 g_return_if_fail (key && val && qsql_be);
205 n = kvp_value_get_type (val);
220 g_strdup_printf (
" kvp key=%s val=%s type=%s", key,
223 DEBUG (
" %s", qb->sql_str);
224 qb->has_slots = TRUE;
235 PERR (
" unsupported value = %d", kvp_value_get_type (val));
239 LEAVE (
" %s", qb->sql_str);
248 gpointer handler_data, gpointer event_data)
251 QSQLiteBackend *qsql_be;
252 gchar *gstr, *sql_str;
254 qsql_be = (QSQLiteBackend *) handler_data;
267 ENTER (
" %s do_free=%d", ent->e_type,
272 DEBUG (
" sql_str=%s", sql_str);
273 if (sqlite_exec (qsql_be->sqliteh, sql_str,
274 NULL, qsql_be, &qsql_be->err) != SQLITE_OK)
276 qof_error_set_be (be, qsql_be->err_delete);
277 qsql_be->error = TRUE;
278 LEAVE (
" error on delete:%s", qsql_be->err);
281 LEAVE (
" %d", event_type);
282 qsql_be->error = FALSE;
294 gpointer handler_data, gpointer event_data)
297 struct QsqlBuilder qb;
298 QSQLiteBackend *qsql_be;
302 qsql_be = (QSQLiteBackend *) handler_data;
314 ENTER (
" insert:%s", ent->e_type);
318 DEBUG (
" guid=%s", gstr);
322 DEBUG (
" sql_str=%s", qb.sql_str);
323 if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
324 NULL, &qb, &qsql_be->err) != SQLITE_OK)
326 qof_error_set_be (be, qsql_be->err_insert);
327 qsql_be->error = TRUE;
328 PERR (
" error on create_event:%s", qsql_be->err);
333 qsql_be->error = FALSE;
345 if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
346 NULL, &qb, &qsql_be->err) != SQLITE_OK)
348 qof_error_set_be (be, qsql_be->err_insert);
349 qsql_be->error = TRUE;
350 PERR (
" error on KVP create_event:%s", qsql_be->err);
355 qsql_be->error = FALSE;
375 struct QsqlBuilder qb;
376 QSQLiteBackend *qsql_be;
378 qsql_be = (QSQLiteBackend *) be;
379 qb.qsql_be = qsql_be;
386 if (!inst->
param->param_setfcn)
389 inst->
param->param_name);
393 LEAVE (
" null string");
396 DEBUG (
" sql_str=%s", qb.sql_str);
397 if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
398 NULL, &qb, &qsql_be->err) != SQLITE_OK)
400 qof_error_set_be (be, qsql_be->err_update);
401 qsql_be->error = TRUE;
402 PERR (
" error on modify:%s", qsql_be->err);
408 qsql_be->error = FALSE;
418 gchar ** columnNames)
420 QSQLiteBackend *qsql_be;
421 struct QsqlBuilder *qb;
428 qb = (
struct QsqlBuilder *) builder;
429 qsql_be = qb->qsql_be;
433 for (i = 0; i < col_num; i++)
441 if (0 ==
safe_strcmp (columnNames[i], QOF_TYPE_GUID))
447 DEBUG (
" set guid failed:%s", strings[i]);
460 update_dirty (gpointer value, gpointer builder)
464 struct QsqlBuilder *qb;
465 QSQLiteBackend *qsql_be;
469 qb = (
struct QsqlBuilder *) builder;
470 qsql_be = qb->qsql_be;
483 LEAVE (
" null string");
486 DEBUG (
" update=%s", qb->sql_str);
487 if (sqlite_exec (qsql_be->sqliteh, qb->sql_str,
488 NULL, qb, &qsql_be->err) != SQLITE_OK)
490 qof_error_set_be (be, qsql_be->err_update);
491 qsql_be->error = TRUE;
492 PERR (
" error on update_dirty:%s", qsql_be->err);
497 qsql_be->error = FALSE;
506 create_dirty_list (gpointer builder, gint col_num, gchar ** strings,
507 gchar ** columnNames)
509 struct QsqlBuilder *qb;
512 gchar * G_GNUC_UNUSED value, *columnName, * G_GNUC_UNUSED tmp;
515 qb = (
struct QsqlBuilder *) builder;
521 columnName = columnNames[col_num];
522 tmp = strings[col_num];
528 qb->dirty_list = g_list_prepend (qb->dirty_list, qb->ent);
529 DEBUG (
" dirty_list=%d", g_list_length (qb->dirty_list));
534 mark_entity (gpointer builder, gint col_num, gchar ** strings,
535 gchar ** columnNames)
537 struct QsqlBuilder *qb;
539 qb = (
struct QsqlBuilder *) builder;
548 QSQLiteBackend *qsql_be;
549 struct QsqlBuilder qb;
552 qsql_be = (QSQLiteBackend *) be;
559 qb.has_slots = FALSE;
560 ENTER (
" %s", ent->e_type);
564 g_strdup_printf (
"SELECT * FROM %s where guid = \"%s\";",
566 PINFO (
" check exists: %s", qb.sql_str);
568 qb.dirty_list = NULL;
570 if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
571 mark_entity, &qb, &qsql_be->err) != SQLITE_OK)
573 qof_error_set_be (be, qsql_be->err_update);
574 qsql_be->error = TRUE;
575 PERR (
" error on select :%s", qsql_be->err);
581 DEBUG (
" sql_str= %s", qb.sql_str);
582 if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
583 NULL, qsql_be, &qsql_be->err) != SQLITE_OK)
585 qof_error_set_be (be, qsql_be->err_insert);
586 qsql_be->error = TRUE;
587 PERR (
" error creating new entity:%s", qsql_be->err);
597 check_state (
QofEntity * ent, gpointer builder)
600 QSQLiteBackend *qsql_be;
601 struct QsqlBuilder *qb;
605 qb = (
struct QsqlBuilder *) builder;
606 qsql_be = qb->qsql_be;
615 g_strdup_printf (
"SELECT * FROM %s where guid = \"%s\";",
618 qb->dirty_list = NULL;
622 qb->qsql_be = qsql_be;
627 if (sqlite_exec (qsql_be->sqliteh, qb->sql_str,
628 create_dirty_list, qb, &qsql_be->err) != SQLITE_OK)
630 qof_error_set_be (be, qsql_be->err_update);
631 qsql_be->error = TRUE;
632 PERR (
" error on check_state:%s", qsql_be->err);
638 DEBUG (
" sql_str= %s", qb->sql_str);
639 if (sqlite_exec (qsql_be->sqliteh, qb->sql_str,
640 NULL, qb, &qsql_be->err) != SQLITE_OK)
642 qof_error_set_be (be, qsql_be->err_insert);
643 qsql_be->error = TRUE;
644 PERR (
" error on check_state create_new:%s", qsql_be->err);
646 g_free (qb->sql_str);
649 g_list_foreach (qb->dirty_list, update_dirty, &qb);
650 g_free (qb->sql_str);
664 gchar ** columnNames)
666 QSQLiteBackend *qsql_be;
667 struct QsqlBuilder *qb;
675 qb = (
struct QsqlBuilder *) builder;
677 qsql_be = qb->qsql_be;
678 g_return_val_if_fail ((col_num < 4),
QSQL_ERROR);
679 g_return_val_if_fail (strings[2],
QSQL_ERROR);
687 PERR (
" invalid type returned from kvp table");
694 PERR (
" invalid KvpValue for type: %d", type);
700 g_hash_table_insert (qsql_be->kvp_table, strings[1], frame);
702 g_hash_table_insert (qsql_be->kvp_id, strings[0], strings[1]);
704 max = strtol (strings[0], &tail, 0);
707 qsql_be->index = (max > qsql_be->index) ? max : qsql_be->index;
716 struct QsqlBuilder qb;
720 g_return_if_fail (qsql_be);
728 if (sq_code == SQLITE_ERROR)
732 g_strdup_printf (
"CREATE TABLE %s (%s, %s, %s, %s, %s, %s",
734 "guid char(32)",
"path mediumtext",
"type mediumtext",
735 "value text", END_DB_VERSION);
736 PINFO (
" creating kvp table. sql=%s", qb.sql_str);
737 if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
740 qsql_be->error = TRUE;
741 PERR (
" unable to create kvp table:%s", qsql_be->err);
744 else if (sq_code != SQLITE_OK)
746 qof_error_set_be (be, qsql_be->err_create);
747 qsql_be->error = TRUE;
748 PERR (
" error on KVP select:%s:%s:%d", qb.sql_str, qsql_be->err, sq_code);
757 struct QsqlBuilder qb;
758 QSQLiteBackend *qsql_be;
761 qsql_be = (QSQLiteBackend *) data;
763 qb.qsql_be = qsql_be;
764 qb.e_type = obj->e_type;
765 ENTER (
" obj_type=%s", qb.e_type);
766 switch (qsql_be->stm_type)
779 if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
780 NULL, NULL, &qsql_be->err) != SQLITE_OK)
782 qof_error_set_be (be, qsql_be->err_create);
783 qsql_be->error = TRUE;
784 PERR (
" error on SQL_CREATE:%s", qsql_be->err);
792 g_strdup_printf (
"SELECT * FROM %s;", obj->e_type);
793 PINFO (
" sql=%s", qb.sql_str);
794 if (sqlite_exec (qsql_be->sqliteh, qb.sql_str,
797 qsql_be->error = TRUE;
798 PERR (
" error on SQL_LOAD:%s", qsql_be->err);
818 QSQLiteBackend *qsql_be;
819 struct QsqlBuilder G_GNUC_UNUSED qb;
821 g_return_if_fail (be || session);
823 qsql_be = (QSQLiteBackend *) be;
825 qb.qsql_be = qsql_be;
826 qsql_be->book = qof_session_get_book (session);
827 DEBUG (
" create_file %s", qsql_be->fullpath);
828 f = fopen (qsql_be->fullpath,
"a+");
834 (_(
"Unable to open the output file '%s' - do you have " 835 "permission to create this file?"), TRUE));
836 qsql_be->error = TRUE;
837 LEAVE (
" unable to create new file '%s'", qsql_be->fullpath);
841 sqlite_open (qsql_be->fullpath, 0644, &qsql_be->err);
842 if (!qsql_be->sqliteh)
844 qof_error_set_be (be, qsql_be->err_create);
845 qsql_be->error = TRUE;
846 LEAVE (
" unable to open sqlite:%s", qsql_be->err);
856 QSQLiteBackend *qsql_be;
858 g_return_if_fail (be || session);
860 qsql_be = (QSQLiteBackend *) be;
862 sqlite_open (qsql_be->fullpath, 0666, &qsql_be->err);
863 if (!qsql_be->sqliteh)
866 (_(
"Unable to open the sqlite database '%s'."), TRUE));
867 qsql_be->error = TRUE;
868 PERR (
" %s", qsql_be->err);
870 LEAVE (
" %s", qsql_be->fullpath);
875 const gchar * book_path, gboolean ignore_lock,
876 gboolean create_if_nonexistent)
878 QSQLiteBackend *qsql_be;
880 struct stat statinfo;
881 gint G_GNUC_UNUSED stat_val;
883 g_return_if_fail (be);
884 ENTER (
" book_path=%s", book_path);
885 qsql_be = (QSQLiteBackend *) be;
887 if (book_path == NULL)
890 (_(
"Please provide a filename for sqlite."), FALSE));
891 qsql_be->error = TRUE;
896 pp = g_strsplit (book_path,
":", 2);
899 qsql_be->fullpath = g_strdup (pp[1]);
903 qsql_be->fullpath = g_strdup (book_path);
904 be->
fullpath = g_strdup (qsql_be->fullpath);
905 PINFO (
" final path = %s", qsql_be->fullpath);
906 stat_val = g_stat (qsql_be->fullpath, &statinfo);
907 if (!S_ISREG (statinfo.st_mode) || statinfo.st_size == 0)
908 qsql_backend_createdb (be, session);
910 qsql_backend_opendb (be, session);
913 LEAVE (
" open failed");
916 qsql_be->create_handler =
918 qsql_be->delete_handler =
920 LEAVE (
" db=%s", qsql_be->fullpath);
926 QSQLiteBackend *qsql_be;
928 g_return_if_fail (be);
931 qsql_be = (QSQLiteBackend *) be;
933 qsql_be->book = book;
944 QSQLiteBackend *qsql_be;
946 g_return_if_fail (be);
947 qsql_be = (QSQLiteBackend *) be;
949 qsql_be->book = book;
955 qsql_determine_file_type (
const gchar * path)
965 QSQLiteBackend *qsql_be;
967 g_return_if_fail (be);
968 qsql_be = (QSQLiteBackend *) be;
969 if (qsql_be->sqliteh)
970 sqlite_close (qsql_be->sqliteh);
976 QSQLiteBackend *qsql_be;
978 g_return_if_fail (be);
979 qsql_be = (QSQLiteBackend *) be;
980 g_hash_table_destroy (qsql_be->kvp_table);
981 g_hash_table_destroy (qsql_be->kvp_id);
1014 QSQLiteBackend *qsql_be;
1018 qsql_be = g_new0 (QSQLiteBackend, 1);
1020 qof_backend_init (be);
1021 qsql_be->kvp_table = g_hash_table_new (g_str_hash, g_str_equal);
1022 qsql_be->kvp_id = g_hash_table_new (g_str_hash, g_str_equal);
1025 qsql_be->err_delete =
1027 qsql_be->err_create =
1029 qsql_be->err_insert =
1031 qsql_be->err_update =
1033 be->session_begin = qsqlite_session_begin;
1035 be->session_end = qsqlite_session_end;
1036 be->destroy_backend = qsqlite_destroy_backend;
1037 be->load = qsqlite_db_load;
1041 be->begin = qsql_create;
1043 be->commit = qsql_modify;
1044 be->rollback = NULL;
1046 be->compile_query = NULL;
1048 be->free_query = NULL;
1049 be->run_query = NULL;
1052 be->events_pending = NULL;
1053 be->process_events = NULL;
1055 be->sync = qsqlite_write_db;
1056 be->load_config = NULL;
1057 be->get_config = NULL;
1068 bindtextdomain (PACKAGE, LOCALE_DIR);
Private KVP utilities for backends etc.
void qof_sqlite_provider_init(void)
Initialises the SQLite backend.
#define QOF_DATE_FORMAT_UTC
QOF UTC format, xsd:date compatible. QOF_UTC_DATE_FORMAT "%Y-%m-%dT%H:%M:%SZ".
QofErrorId qof_error_register(const gchar *err_message, gboolean use_file)
Generate and register a new error.
gboolean(* save_may_clobber_data)(QofBackend *)
#define PERR(format, args...)
gpointer qof_object_new_instance(QofIdTypeConst type_name, QofBook *book)
#define PINFO(format, args...)
static KvpValue * string_to_kvp_value(const gchar *content, KvpValueType type)
gboolean qof_class_is_registered(QofIdTypeConst obj_name)
void qof_date_free(QofDate *date)
void qof_backend_register_provider(QofBackendProvider *)
#define QOF_OBJECT_VERSION
gchar * qof_sql_entity_insert(QofEntity *ent)
Build a SQL 'INSERT' statement for this entity.
static gint build_kvp_table(gpointer builder, gint col_num, gchar **strings, gchar **columnNames)
chekc kvp data once per record
QofIdTypeConst kvp_value_type_to_qof_id(KvpValueType n)
Convert a KvpValueType to a QofIdType.
KvpValueType
possible types in the union KvpValue
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofEntityForeachCB cb, gpointer user_data)
#define QOF_EVENT_DESTROY
gboolean string_to_guid(const gchar *string, GUID *guid)
static void qsql_class_foreach(QofObject *obj, gpointer data)
gboolean partial_book_supported
Partial QofBook handler.
gint32 QofErrorId
The ID of this error.
gchar * qof_sql_object_create_table(QofObject *obj)
Build a SQL 'CREATE' statement for this object.
struct _KvpFrame KvpFrame
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...
KvpValue * kvp_value_new_boolean(gboolean value)
QofErrorId qof_error_check_be(QofBackend *be)
Check for errors.
gint qof_util_bool_to_int(const gchar *val)
#define LEAVE(format, args...)
#define GUID_ENCODING_LENGTH
static void qsql_load_kvp(QSQLiteBackend *qsql_be)
QofTime * qof_date_to_qtime(const QofDate *qd)
Full range replacement for struct tm.
KvpFrame * kvp_frame_set_value(KvpFrame *frame, const gchar *key_path, const KvpValue *value)
Copy the KvpValue into the frame.
128bit denominator/numerator maths.
gchar * qof_sql_entity_update(QofEntity *ent)
Build a SQL 'UPDATE' statement for the current entity parameter.
const QofParam * qof_class_get_parameter(QofIdTypeConst obj_name, const gchar *parameter)
gint qof_event_register_handler(QofEventHandler handler, gpointer user_data)
Register a handler for events.
const GUID * qof_instance_get_guid(QofInstance *inst)
QofDate * qof_date_parse(const gchar *str, QofDateFormat df)
Convert a timestamp to a QofTime.
struct _KvpValue KvpValue
static void create_event(QofEntity *ent, QofEventId event_type, gpointer handler_data, gpointer event_data)
KvpFrame * qof_instance_get_slots(QofInstance *inst)
void qof_error_set(QofSession *session, QofErrorId error)
Add an error to the stack for this session.
gboolean qof_numeric_from_string(const gchar *str, QofNumeric *n)
gboolean qof_book_not_saved(QofBook *book)
KvpValueType qof_id_to_kvp_value_type(QofIdTypeConst type_string)
Convert a QofIdType to a KvpValueType.
static gint record_foreach(gpointer builder, gint col_num, gchar **strings, gchar **columnNames)
void qof_time_free(QofTime *qt)
Free a QofTime when no longer required.
void(* provider_free)(QofBackendProvider *)
#define DEBUG(format, args...)
QofBackend *(* backend_new)(void)
gchar * qof_util_param_to_string(QofEntity *ent, const QofParam *param)
Converts a parameter to a string for storage or display.
void qof_event_unregister_handler(gint handler_id)
Unregister an event handler.
gchar * guid_to_string_buff(const GUID *guid, gchar *buff)
gchar * kvp_value_to_bare_string(const KvpValue *val)
General purpose function to convert any KvpValue to a string.
gboolean qof_util_param_set_string(QofEntity *ent, const QofParam *param, const gchar *value_string)
Set a parameter from a value string.
Private QOF SQL generation routines.
const gchar * access_method
void kvp_frame_for_each_slot(KvpFrame *f, KvpValueForeachCB proc, gpointer data)
gboolean(* check_data_type)(const gchar *)
Distinguish two providers with same access method.
void qof_sql_entity_set_kvp_tablename(const gchar *name)
Set a default KVP table name for each backend.
struct QofTime64 QofTime
Use a 64-bit signed int QofTime.
void qof_event_suspend(void)
Suspend all engine events.
const GUID * qof_entity_get_guid(QofEntity *ent)
void qof_event_resume(void)
Public interface of qof-backend-sqlite.
static G_GNUC_UNUSED void kvpvalue_to_sql(const gchar *key, KvpValue *val, gpointer builder)
void qof_entity_set_guid(QofEntity *ent, const GUID *guid)
static QofBackend * qsql_backend_new(void)
Starts the backend and creates the context.
KvpFrame * kvp_frame_new(void)
gint safe_strcmp(const gchar *da, const gchar *db)
KvpFrame * kvp_value_get_frame(const KvpValue *value)
const gchar * provider_name
const gchar * qof_error_get_message_be(QofBackend *be)
Pop the most recent error and get the message.
#define ENTER(format, args...)
gchar * qof_sql_entity_delete(QofEntity *ent)
Build a SQL 'DELETE' statement for this entity.
void qof_object_foreach_type(QofForeachTypeCB cb, gpointer user_data)
const gchar * QofLogModule
64bit time/date handling.