41 #include "splint-defs.h"
46 #define TABLE_NAME "slots"
47 #define TABLE_VERSION 3
73 static gpointer get_obj_guid( gpointer pObject );
74 static void set_obj_guid(
void );
75 static gpointer get_path( gpointer pObject );
76 static void set_path( gpointer pObject, gpointer pValue );
78 static void set_slot_type( gpointer pObject, gpointer pValue );
79 static gint64 get_int64_val( gpointer pObject );
80 static void set_int64_val( gpointer pObject, gint64 pValue );
81 static gpointer get_string_val( gpointer pObject );
82 static void set_string_val( gpointer pObject, gpointer pValue );
83 static gpointer get_double_val( gpointer pObject );
84 static void set_double_val( gpointer pObject, gpointer pValue );
85 static Timespec get_timespec_val( gpointer pObject );
86 static void set_timespec_val( gpointer pObject,
Timespec ts );
87 static gpointer get_guid_val( gpointer pObject );
88 static void set_guid_val( gpointer pObject, gpointer pValue );
89 static gnc_numeric get_numeric_val( gpointer pObject );
90 static void set_numeric_val( gpointer pObject,
gnc_numeric value );
91 static GDate* get_gdate_val( gpointer pObject );
92 static void set_gdate_val( gpointer pObject, GDate* value );
96 #define SLOT_MAX_PATHNAME_LEN 4096
97 #define SLOT_MAX_STRINGVAL_LEN 4096
119 "obj_guid", CT_GUID, 0,
COL_NNUL, NULL, NULL,
123 "name", CT_STRING, SLOT_MAX_PATHNAME_LEN,
COL_NNUL, NULL, NULL,
127 "slot_type", CT_INT, 0,
COL_NNUL, NULL, NULL,
131 "int64_val", CT_INT64, 0, 0, NULL, NULL,
135 "string_val", CT_STRING, SLOT_MAX_PATHNAME_LEN, 0, NULL, NULL,
139 "double_val", CT_DOUBLE, 0, 0, NULL, NULL,
143 "timespec_val", CT_TIMESPEC, 0, 0, NULL, NULL,
147 "guid_val", CT_GUID, 0, 0, NULL, NULL,
151 "numeric_val", CT_NUMERIC, 0, 0, NULL, NULL,
155 "gdate_val", CT_GDATE, 0, 0, NULL, NULL,
167 {
"obj_guid", CT_GUID, 0, 0, NULL, NULL, (
QofAccessFunc)get_obj_guid, _retrieve_guid_ },
175 {
"gdate_val", CT_GDATE, 0, 0, },
183 get_key_from_path( GString *path )
185 gchar *str = NULL, *key = NULL, *ret = NULL;
187 g_return_val_if_fail( path != NULL, strdup(
"") );
189 if ( path->str == NULL )
return strdup(
"");
190 str = g_strdup( path->str );
191 key = strrchr( str,
'/');
194 if ( key == NULL )
return str;
195 while ( str + strlen(str) - key == 1 )
198 key = strrchr( str,
'/' );
200 if ( key == NULL )
return str;
202 while ( *key ==
'/') ++key;
210 get_path_from_path( GString *path )
212 gchar *str = NULL, *key = NULL;
214 g_return_val_if_fail( path != NULL, NULL );
216 if ( path->str == NULL )
return NULL;
217 str = g_strdup( path->str );
218 key = strrchr( str,
'/');
226 while ( str + strlen(str) - key == 1 )
229 key = strrchr( str,
'/' );
245 g_return_if_fail( pInfo != NULL );
246 g_return_if_fail( pValue != NULL );
248 switch ( pInfo->context)
252 gchar *key = get_key_from_path( pInfo->path );
259 pInfo->pList = g_list_append(pInfo->pList, pValue);
265 gchar *key = get_key_from_path( pInfo->path );
266 gchar *path = get_path_from_path( pInfo->path );
270 frame = kvp_frame_get_frame_slash( frame, path );
281 get_obj_guid( gpointer pObject )
285 g_return_val_if_fail( pObject != NULL, NULL );
287 return (gpointer)pInfo->guid;
297 get_path( gpointer pObject )
301 g_return_val_if_fail( pObject != NULL, NULL );
303 return (gpointer)pInfo->path->str;
307 set_path( gpointer pObject, gpointer pValue )
311 g_return_if_fail( pObject != NULL );
312 g_return_if_fail( pValue != NULL );
314 if ( pInfo->path != NULL )
316 (void)g_string_free( pInfo->path, TRUE );
318 pInfo->path = g_string_new( (gchar*)pValue );
322 get_slot_type( gpointer pObject )
326 g_return_val_if_fail( pObject != NULL, 0 );
329 return pInfo->value_type;
333 set_slot_type( gpointer pObject, gpointer pValue )
337 g_return_if_fail( pObject != NULL );
338 g_return_if_fail( pValue != NULL );
344 get_int64_val( gpointer pObject )
348 g_return_val_if_fail( pObject != NULL, 0 );
361 set_int64_val( gpointer pObject, gint64 value )
366 g_return_if_fail( pObject != NULL );
369 pValue = kvp_value_new_gint64( value );
370 set_slot_from_value( pInfo, pValue );
374 get_string_val( gpointer pObject )
378 g_return_val_if_fail( pObject != NULL, NULL );
391 set_string_val( gpointer pObject, gpointer pValue )
396 g_return_if_fail( pObject != NULL );
399 value = kvp_value_new_string( (gchar*)pValue );
400 set_slot_from_value( pInfo, value );
404 get_double_val( gpointer pObject )
409 g_return_val_if_fail( pObject != NULL, NULL );
413 d_val = kvp_value_get_double( pInfo->pKvpValue );
414 return (gpointer)&d_val;
423 set_double_val( gpointer pObject, gpointer pValue )
428 g_return_if_fail( pObject != NULL );
431 value = kvp_value_new_double( *((
double*)pValue) );
432 set_slot_from_value( pInfo, value );
436 get_timespec_val( gpointer pObject )
443 return kvp_value_get_timespec( pInfo->pKvpValue );
447 set_timespec_val( gpointer pObject,
Timespec ts )
452 g_return_if_fail( pObject != NULL );
455 value = kvp_value_new_timespec( ts );
456 set_slot_from_value( pInfo, value );
460 get_guid_val( gpointer pObject )
464 g_return_val_if_fail( pObject != NULL, NULL );
466 if ( kvp_value_get_type( pInfo->pKvpValue ) ==
KVP_TYPE_GUID )
477 set_guid_val( gpointer pObject, gpointer pValue )
481 g_return_if_fail( pObject != NULL );
482 if ( pValue == NULL )
return;
484 switch ( pInfo->value_type)
489 set_slot_from_value( pInfo, value );
496 gchar *key = get_key_from_path( pInfo->path );
498 newInfo->context = LIST;
500 slots_load_info( newInfo );
503 g_string_free( newInfo->path, TRUE );
512 newInfo->pKvpFrame = newFrame;
514 switch ( pInfo->context )
519 gchar *key = get_key_from_path( pInfo->path );
520 newInfo->path = g_string_assign( newInfo->path, key );
521 pInfo->pList = g_list_append( pInfo->pList, value );
528 gchar *key = get_key_from_path( pInfo->path );
529 kvp_frame_set_frame_nc( pInfo->pKvpFrame, key, newFrame );
535 newInfo->context = FRAME;
536 slots_load_info ( newInfo );
537 g_string_free( newInfo->path, TRUE );
547 get_numeric_val( gpointer pObject )
551 g_return_val_if_fail( pObject != NULL, gnc_numeric_zero() );
555 return kvp_value_get_numeric( pInfo->pKvpValue );
559 return gnc_numeric_zero();
564 set_numeric_val( gpointer pObject,
gnc_numeric value )
569 g_return_if_fail( pObject != NULL );
572 pValue = kvp_value_new_numeric( value );
573 set_slot_from_value( pInfo, pValue );
577 get_gdate_val( gpointer pObject )
582 g_return_val_if_fail( pObject != NULL, NULL );
596 set_gdate_val( gpointer pObject, GDate* value )
601 g_return_if_fail( pObject != NULL );
604 pValue = kvp_value_new_gdate( *value );
605 set_slot_from_value( pInfo, pValue );
612 g_return_val_if_fail( pInfo != NULL, NULL );
615 newSlot->be = pInfo->be;
616 newSlot->guid = guid == NULL ? pInfo->guid : guid;
617 newSlot->is_ok = pInfo->is_ok;
618 newSlot->pKvpFrame = pInfo->pKvpFrame;
619 newSlot->value_type = pInfo->value_type;
620 newSlot->pList = pInfo->pList;
621 newSlot->context = pInfo->context;
622 newSlot->pKvpValue = pInfo->pKvpValue;
623 newSlot->path = g_string_new(pInfo->path->str);
628 save_slot(
const gchar* key,
KvpValue* value, gpointer data )
633 g_return_if_fail( key != NULL );
634 g_return_if_fail( value != NULL );
635 g_return_if_fail( data != NULL );
638 if ( !pSlot_info->is_ok )
643 curlen = pSlot_info->path->len;
644 pSlot_info->pKvpValue = value;
647 (void)g_string_append( pSlot_info->path,
"/" );
649 (void)g_string_append( pSlot_info->path, key );
650 pSlot_info->value_type = kvp_value_get_type( value );
652 switch ( pSlot_info->value_type )
658 slot_info_t *pNewInfo = slot_info_copy( pSlot_info, &guid );
659 KvpValue *oldValue = pSlot_info->pKvpValue;
660 pSlot_info->pKvpValue = kvp_value_new_guid( &guid );
662 OP_DB_INSERT, TABLE_NAME,
663 TABLE_NAME, pSlot_info,
665 g_return_if_fail( pSlot_info->is_ok );
668 pSlot_info->pKvpValue = oldValue;
669 g_string_free( pNewInfo->path, TRUE );
677 slot_info_t *pNewInfo = slot_info_copy( pSlot_info, &guid );
678 KvpValue *oldValue = pSlot_info->pKvpValue;
679 pSlot_info->pKvpValue = kvp_value_new_guid( &guid );
681 OP_DB_INSERT, TABLE_NAME,
682 TABLE_NAME, pSlot_info,
684 g_return_if_fail( pSlot_info->is_ok );
688 save_slot(
"", val, pNewInfo);
691 pSlot_info->pKvpValue = oldValue;
692 g_string_free( pNewInfo->path, TRUE );
699 OP_DB_INSERT, TABLE_NAME,
700 TABLE_NAME, pSlot_info,
706 (void)g_string_truncate( pSlot_info->path, curlen );
712 slot_info_t slot_info = { NULL, NULL, TRUE, NULL, 0, NULL, FRAME, NULL, g_string_new(NULL) };
714 g_return_val_if_fail( be != NULL, FALSE );
715 g_return_val_if_fail( guid != NULL, FALSE );
716 g_return_val_if_fail( pFrame != NULL, FALSE );
725 slot_info.guid = guid;
727 (void)g_string_free( slot_info.path, TRUE );
729 return slot_info.is_ok;
739 slot_info_t slot_info = { NULL, NULL, TRUE, NULL, 0, NULL, FRAME, NULL, g_string_new(NULL) };
741 g_return_val_if_fail( be != NULL, FALSE );
742 g_return_val_if_fail( guid != NULL, FALSE );
746 buf = g_strdup_printf(
"SELECT * FROM %s WHERE obj_guid='%s' and slot_type in ('%d', '%d') and not guid_val is null",
753 gnc_sql_statement_dispose( stmt );
754 if ( result != NULL )
756 GncSqlRow* row = gnc_sql_result_get_first_row( result );
758 while ( row != NULL )
763 gnc_sql_row_get_value_at_col_name( row, table_row.
col_name);
769 row = gnc_sql_result_get_next_row( result );
771 gnc_sql_result_dispose( result );
776 slot_info.guid = guid;
777 slot_info.is_ok = TRUE;
779 TABLE_NAME, &slot_info, obj_guid_col_table );
781 return slot_info.is_ok;
789 g_return_if_fail( pInfo != NULL );
790 g_return_if_fail( pInfo->be != NULL );
791 g_return_if_fail( row != NULL );
792 g_return_if_fail( pInfo->pKvpFrame != NULL );
794 slot_info = slot_info_copy( pInfo, NULL );
795 g_string_free( slot_info->path, TRUE );
796 slot_info->path = NULL;
800 if ( slot_info->path != NULL )
802 (void)g_string_free( slot_info->path, TRUE );
804 if ( slot_info->pList != pInfo->pList )
806 if (pInfo->pList != NULL)
808 PWARN(
"Load slot returned a different list than the original");
812 pInfo->pList = slot_info->pList;
821 slot_info_t info = { NULL, NULL, TRUE, NULL, 0, NULL, FRAME, NULL, g_string_new(NULL) };
822 g_return_if_fail( be != NULL );
823 g_return_if_fail( inst != NULL );
827 info.pKvpFrame = qof_instance_get_slots( inst );
830 slots_load_info( &info );
841 g_return_if_fail( pInfo != NULL );
842 g_return_if_fail( pInfo->be != NULL );
843 g_return_if_fail( pInfo->guid != NULL );
844 g_return_if_fail( pInfo->pKvpFrame != NULL );
848 buf = g_strdup_printf(
"SELECT * FROM %s WHERE obj_guid='%s'",
849 TABLE_NAME, guid_buf );
855 gnc_sql_statement_dispose( stmt );
856 if ( result != NULL )
858 GncSqlRow* row = gnc_sql_result_get_first_row( result );
860 while ( row != NULL )
862 load_slot( pInfo, row );
863 row = gnc_sql_result_get_next_row( result );
865 gnc_sql_result_dispose( result );
875 g_return_val_if_fail( be != NULL, NULL );
876 g_return_val_if_fail( row != NULL, NULL );
886 slot_info_t slot_info = { NULL, NULL, TRUE, NULL, 0, NULL, FRAME, NULL, NULL };
890 g_return_if_fail( be != NULL );
891 g_return_if_fail( row != NULL );
892 g_return_if_fail( coll != NULL );
894 guid = load_obj_guid( be, row );
895 g_assert( guid != NULL );
899 slot_info.pKvpFrame = qof_instance_get_slots( inst );
900 slot_info.context = NONE;
904 if ( slot_info.path != NULL )
906 (void)g_string_free( slot_info.path, TRUE );
917 gboolean single_item;
919 g_return_if_fail( be != NULL );
922 if ( list == NULL )
return;
928 g_string_append_printf( sql,
"SELECT * FROM %s WHERE %s ", TABLE_NAME, obj_guid_col_table[0].col_name );
929 if ( g_list_length( list ) != 1 )
931 (void)g_string_append( sql,
"IN (" );
936 (void)g_string_append( sql,
"= " );
942 (void)g_string_append( sql,
")" );
949 PERR(
"stmt == NULL, SQL = '%s'\n", sql->str );
950 (void)g_string_free( sql, TRUE );
953 (void)g_string_free( sql, TRUE );
955 gnc_sql_statement_dispose( stmt );
956 if ( result != NULL )
958 GncSqlRow* row = gnc_sql_result_get_first_row( result );
960 while ( row != NULL )
962 load_slot_for_list_item( be, row, coll );
963 row = gnc_sql_result_get_next_row( result );
965 gnc_sql_result_dispose( result );
972 slot_info_t slot_info = { NULL, NULL, TRUE, NULL, 0, NULL, FRAME, NULL, NULL };
976 g_return_if_fail( be != NULL );
977 g_return_if_fail( row != NULL );
978 g_return_if_fail( lookup_fn != NULL );
980 guid = load_obj_guid( be, row );
981 g_return_if_fail( guid != NULL );
982 inst = lookup_fn( guid, be->
book );
983 g_return_if_fail( inst != NULL );
986 slot_info.pKvpFrame = qof_instance_get_slots( inst );
987 slot_info.path = NULL;
991 if ( slot_info.path != NULL )
993 (void)g_string_free( slot_info.path, TRUE );
1007 BookLookupFn lookup_fn )
1013 g_return_if_fail( be != NULL );
1016 if ( subquery == NULL )
return;
1018 sql = g_strdup_printf(
"SELECT * FROM %s WHERE %s IN (%s)",
1019 TABLE_NAME, obj_guid_col_table[0].col_name,
1026 PERR(
"stmt == NULL, SQL = '%s'\n", sql );
1032 gnc_sql_statement_dispose( stmt );
1033 if ( result != NULL )
1035 GncSqlRow* row = gnc_sql_result_get_first_row( result );
1037 while ( row != NULL )
1039 load_slot_for_book_object( be, row, lookup_fn );
1040 row = gnc_sql_result_get_next_row( result );
1042 gnc_sql_result_dispose( result );
1053 g_return_if_fail( be != NULL );
1063 PERR(
"Unable to create index\n" );
1066 else if ( version < TABLE_VERSION )
1078 PERR(
"Unable to create index\n" );
1081 else if ( version == 2 )
1086 PERR(
"Unable to add gdate column\n" );
1090 PINFO(
"Slots table upgraded from version %d to version %d\n", version, TABLE_VERSION);
1096 gnc_sql_init_slots_handler(
void )
1100 GNC_SQL_BACKEND_VERSION,
1104 create_slots_tables,
gboolean qof_object_register_backend(QofIdTypeConst type_name, const char *backend_name, gpointer be_data)
const GncGUID * qof_instance_get_guid(gconstpointer)
gint gnc_sql_get_table_version(const GncSqlBackend *be, const gchar *table_name)
void gnc_sql_upgrade_table(GncSqlBackend *be, const gchar *table_name, const GncSqlColumnTableEntry *col_table)
QofInstance * qof_collection_lookup_entity(const QofCollection *, const GncGUID *)
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
#define PINFO(format, args...)
load and save accounts data to SQL
KvpValueType
possible types in the union KvpValue
GncGUID guid_new_return(void)
gboolean string_to_guid(const gchar *string, GncGUID *guid)
gboolean gnc_sql_create_table(GncSqlBackend *be, const gchar *table_name, gint table_version, const GncSqlColumnTableEntry *col_table)
load and save data to SQL
Use a 64-bit unsigned int timespec.
gboolean gnc_sql_add_columns_to_table(GncSqlBackend *be, const gchar *table_name, const GncSqlColumnTableEntry *new_col_table)
QofCollection * qof_instance_get_collection(gconstpointer inst)
gchar * guid_to_string_buff(const GncGUID *guid, gchar *buff)
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
Timespec gnc_dmy2timespec(gint day, gint month, gint year)
#define PERR(format, args...)
KvpValue * kvp_value_new_frame_nc(KvpFrame *value)
gint64 kvp_value_get_gint64(const KvpValue *value)
gboolean gnc_sql_create_index(const GncSqlBackend *be, const gchar *index_name, const gchar *table_name, const GncSqlColumnTableEntry *col_table)
#define PWARN(format, args...)
void gnc_sql_slots_load_for_sql_subquery(GncSqlBackend *be, const gchar *subquery, BookLookupFn lookup_fn)
guint gnc_sql_append_guid_list_to_sql(GString *sql, GList *list, guint maxCount)
char * kvp_value_get_string(const KvpValue *value)
gboolean gnc_sql_set_table_version(GncSqlBackend *be, const gchar *table_name, gint version)
#define GUID_ENCODING_LENGTH
void gnc_sql_slots_load_for_list(GncSqlBackend *be, GList *list)
void kvp_frame_set_slot_nc(KvpFrame *frame, const gchar *key, KvpValue *value)
GList * kvp_value_get_glist(const KvpValue *value)
void gnc_sql_slots_load(GncSqlBackend *be, QofInstance *inst)
GncGUID * kvp_value_get_guid(const KvpValue *value)
GncSqlResult * gnc_sql_execute_select_statement(GncSqlBackend *be, GncSqlStatement *stmt)
KvpFrame * kvp_frame_set_value_nc(KvpFrame *frame, const gchar *path, KvpValue *value)
All type declarations for the whole Gnucash engine.
void gnc_sql_load_object(const GncSqlBackend *be, GncSqlRow *row, QofIdTypeConst obj_name, gpointer pObject, const GncSqlColumnTableEntry *table)
void kvp_frame_for_each_slot(KvpFrame *f, void(*proc)(const gchar *key, KvpValue *value, gpointer data), gpointer data)
gboolean gnc_sql_slots_delete(GncSqlBackend *be, const GncGUID *guid)
KvpValue * kvp_value_new_glist_nc(GList *lst)
struct KvpFrameImpl KvpFrame
GDate kvp_value_get_gdate(const KvpValue *value)
void(* QofSetterFunc)(gpointer, gpointer)
gboolean gnc_sql_do_db_operation(GncSqlBackend *be, E_DB_OPERATION op, const gchar *table_name, QofIdTypeConst obj_name, gpointer pObject, const GncSqlColumnTableEntry *table)
KvpFrame * kvp_frame_new(void)
KvpFrame * kvp_value_get_frame(const KvpValue *value)
GncSqlStatement * gnc_sql_create_statement_from_sql(GncSqlBackend *be, const gchar *sql)
void kvp_value_delete(KvpValue *value)
struct KvpValueImpl KvpValue
gboolean gnc_sql_slots_save(GncSqlBackend *be, const GncGUID *guid, gboolean is_infant, KvpFrame *pFrame)
const gchar * QofLogModule