31 #include <glib/gi18n.h>
34 #include "qofquery-p.h"
35 #include "qofquerycore-p.h"
40 #include "engine-helpers.h"
53 #include "splint-defs.h"
56 #define SIMPLE_QUERY_COMPILATION 1
57 #define LOAD_TRANSACTIONS_AS_NEEDED 0
61 #define TRANSACTION_TABLE "transactions"
62 #define TX_TABLE_VERSION 3
63 #define SPLIT_TABLE "splits"
64 #define SPLIT_TABLE_VERSION 4
74 #define TX_MAX_NUM_LEN 2048
75 #define TX_MAX_DESCRIPTION_LEN 2048
81 {
"currency_guid", CT_COMMODITYREF, 0,
COL_NNUL,
"currency" },
82 {
"num", CT_STRING, TX_MAX_NUM_LEN,
COL_NNUL,
"num" },
83 {
"post_date", CT_TIMESPEC, 0, 0,
"post-date" },
84 {
"enter_date", CT_TIMESPEC, 0, 0,
"enter-date" },
85 {
"description", CT_STRING, TX_MAX_DESCRIPTION_LEN, 0,
"description" },
90 static gpointer get_split_reconcile_state( gpointer pObject );
91 static void set_split_reconcile_state( gpointer pObject, gpointer pValue );
92 static void set_split_lot( gpointer pObject, gpointer pLot );
94 #define SPLIT_MAX_MEMO_LEN 2048
95 #define SPLIT_MAX_ACTION_LEN 2048
101 {
"tx_guid", CT_TXREF, 0,
COL_NNUL,
"transaction" },
102 {
"account_guid", CT_ACCOUNTREF, 0,
COL_NNUL,
"account" },
103 {
"memo", CT_STRING, SPLIT_MAX_MEMO_LEN,
COL_NNUL,
"memo" },
104 {
"action", CT_STRING, SPLIT_MAX_ACTION_LEN,
COL_NNUL,
"action" },
106 "reconcile_state", CT_STRING, 1,
COL_NNUL, NULL, NULL,
107 (
QofAccessFunc)get_split_reconcile_state, set_split_reconcile_state
109 {
"reconcile_date", CT_TIMESPEC, 0, 0,
"reconcile-date" },
110 {
"value", CT_NUMERIC, 0,
COL_NNUL,
"value" },
111 {
"quantity", CT_NUMERIC, 0,
COL_NNUL,
"amount" },
113 "lot_guid", CT_LOTREF, 0, 0, NULL, NULL,
123 {
"post_date", CT_TIMESPEC, 0, 0,
"post-date" },
131 {
"account_guid", CT_ACCOUNTREF, 0,
COL_NNUL,
"account" },
139 {
"tx_guid", CT_GUID, 0, 0,
"guid" },
147 get_split_reconcile_state( gpointer pObject )
151 g_return_val_if_fail( pObject != NULL, NULL );
152 g_return_val_if_fail( GNC_IS_SPLIT(pObject), NULL );
160 set_split_reconcile_state( gpointer pObject, gpointer pValue )
162 const gchar* s = (
const gchar*)pValue;
164 g_return_if_fail( pObject != NULL );
165 g_return_if_fail( GNC_IS_SPLIT(pObject) );
166 g_return_if_fail( pValue != NULL );
172 set_split_lot( gpointer pObject, gpointer pLot )
177 g_return_if_fail( pObject != NULL );
178 g_return_if_fail( GNC_IS_SPLIT(pObject) );
180 if ( pLot == NULL )
return;
182 g_return_if_fail( GNC_IS_LOT(pLot) );
184 split = GNC_SPLIT(pObject);
194 Split* pSplit = NULL;
195 gboolean bad_guid = FALSE;
197 g_return_val_if_fail( be != NULL, NULL );
198 g_return_val_if_fail( row != NULL, NULL );
201 if ( guid == NULL )
return NULL;
204 PWARN(
"Bad GUID, creating new");
214 if ( pSplit == NULL )
230 PERR(
"A malformed split with id %s was found in the dataset.", guidstr);
243 g_return_if_fail( be != NULL );
245 if ( list == NULL )
return;
248 g_string_append_printf( sql,
"SELECT * FROM %s WHERE %s IN (", SPLIT_TABLE, tx_guid_col_table[0].col_name );
250 (void)g_string_append( sql,
")" );
254 if ( result != NULL )
256 GList* split_list = NULL;
259 row = gnc_sql_result_get_first_row( result );
260 while ( row != NULL )
263 s = load_single_split( be, row );
266 split_list = g_list_prepend( split_list, s );
268 row = gnc_sql_result_get_next_row( result );
271 if ( split_list != NULL )
274 g_list_free( split_list );
277 gnc_sql_result_dispose( result );
279 (void)g_string_free( sql, TRUE );
289 g_return_val_if_fail( be != NULL, NULL );
290 g_return_val_if_fail( row != NULL, NULL );
293 if ( guid == NULL )
return NULL;
311 PERR(
"A malformed transaction with id %s was found in the dataset.", guidstr);
348 g_return_if_fail( be != NULL );
349 g_return_if_fail( stmt != NULL );
352 if ( result != NULL )
354 GList* tx_list = NULL;
358 #if LOAD_TRANSACTIONS_AS_NEEDED
359 GSList* bal_list = NULL;
361 Account* root = gnc_book_get_root_account( be->
book );
369 save_account_balances,
374 row = gnc_sql_result_get_first_row( result );
375 while ( row != NULL )
377 tx = load_single_tx( be, row );
380 tx_list = g_list_prepend( tx_list, tx );
382 row = gnc_sql_result_get_next_row( result );
384 gnc_sql_result_dispose( result );
387 if ( tx_list != NULL )
390 load_splits_for_tx_list( be, tx_list );
394 for ( node = tx_list; node != NULL; node = node->next )
399 g_list_free( tx_list );
401 #if LOAD_TRANSACTIONS_AS_NEEDED
406 for ( nextbal = bal_list; nextbal != NULL; nextbal = nextbal->next )
414 g_object_get( balns->acc,
415 "end-balance", &pnew_end_bal,
416 "end-cleared-balance", &pnew_end_c_bal,
417 "end-reconciled-balance", &pnew_end_r_bal,
420 qof_instance_increase_editlevel (balns-acc);
427 g_object_set( balns->acc,
"start-balance", &balns->start_bal, NULL );
428 qof_instance_decrease_editlevel (balns-acc);
434 balns->start_cleared_bal =
gnc_numeric_add( balns->start_cleared_bal, adj,
436 g_object_set( balns->acc,
"start-cleared-balance", &balns->start_cleared_bal, NULL );
438 if ( !
gnc_numeric_eq( *pnew_end_r_bal, balns->end_reconciled_bal ) )
442 balns->start_reconciled_bal =
gnc_numeric_add( balns->start_reconciled_bal, adj,
444 g_object_set( balns->acc,
"start-reconciled-balance", &balns->start_reconciled_bal, NULL );
446 qof_instance_decrease_editlevel (balns-acc);
448 g_free( pnew_end_bal );
449 g_free( pnew_end_c_bal );
450 g_free( pnew_end_r_bal );
453 if ( bal_list != NULL )
455 g_slist_free( bal_list );
476 g_return_if_fail( be != NULL );
485 PERR(
"Unable to create index\n" );
488 else if ( version < TX_TABLE_VERSION )
496 PINFO(
"Transactions table upgraded from version %d to version %d\n", version, TX_TABLE_VERSION);
506 PERR(
"Unable to create index\n" );
508 ok =
gnc_sql_create_index( be,
"splits_account_guid_index", SPLIT_TABLE, account_guid_col_table );
511 PERR(
"Unable to create index\n" );
514 else if ( version < SPLIT_TABLE_VERSION )
524 PERR(
"Unable to create index\n" );
526 ok =
gnc_sql_create_index( be,
"splits_account_guid_index", SPLIT_TABLE, account_guid_col_table );
529 PERR(
"Unable to create index\n" );
532 PINFO(
"Splits table upgraded from version %d to version %d\n", version, SPLIT_TABLE_VERSION);
543 delete_split_slots_cb( gpointer data, gpointer user_data )
546 Split* pSplit = GNC_SPLIT(data);
548 g_return_if_fail( data != NULL );
549 g_return_if_fail( GNC_IS_SPLIT(data) );
550 g_return_if_fail( user_data != NULL );
552 if ( split_info->is_ok )
571 g_return_val_if_fail( be != NULL, FALSE );
572 g_return_val_if_fail( pTx != NULL, FALSE );
575 SPLIT_TABLE, pTx, tx_guid_col_table ) )
580 split_info.is_ok = TRUE;
584 return split_info.is_ok;
602 g_return_val_if_fail( inst != NULL, FALSE );
603 g_return_val_if_fail( be != NULL, FALSE );
605 is_infant = qof_instance_get_infant( inst );
622 qof_instance_set_guid (inst, guid);
626 inst, split_col_table );
633 qof_instance_get_slots( inst ) );
640 save_split_cb( gpointer data, gpointer user_data )
643 Split* pSplit = GNC_SPLIT(data);
645 g_return_if_fail( data != NULL );
646 g_return_if_fail( GNC_IS_SPLIT(data) );
647 g_return_if_fail( user_data != NULL );
649 if ( split_info->is_ok )
651 split_info->is_ok = commit_split( split_info->be, QOF_INSTANCE(pSplit) );
660 g_return_val_if_fail( be != NULL, FALSE );
661 g_return_val_if_fail( tx_guid != NULL, FALSE );
662 g_return_val_if_fail( pSplitList != NULL, FALSE );
665 split_info.guid = tx_guid;
666 split_info.is_ok = TRUE;
667 g_list_foreach( pSplitList, save_split_cb, &split_info );
669 return split_info.is_ok;
679 gboolean is_ok = TRUE;
682 g_return_val_if_fail( be != NULL, FALSE );
683 g_return_val_if_fail( pTx != NULL, FALSE );
685 inst = QOF_INSTANCE(pTx);
686 is_infant = qof_instance_get_infant( inst );
700 if ( op != OP_DB_DELETE )
704 is_ok = gnc_sql_save_commodity( be, commodity );
707 err =
"Commodity save failed: Probably an invalid or missing currency";
717 err =
"Transaction header save failed. Check trace log for SQL errors";
730 err =
"Slots save failed. Check trace log for SQL errors";
732 if ( is_ok && do_save_splits )
737 err =
"Split save failed. Check trace log for SQL errors";
746 err =
"Slots delete failed. Check trace log for SQL errors";
750 is_ok = delete_splits( be, pTx );
753 err =
"Split delete failed. Check trace log for SQL errors";
760 G_GNUC_UNUSED gchar *message1 =
"Transaction %s dated %s in account %s not saved due to %s.%s";
761 G_GNUC_UNUSED gchar *message2 =
"\nDatabase may be corrupted, check your data carefully.";
773 PERR(
"Transaction %s dated %s in account %s not saved due to %s.\n",
785 g_return_val_if_fail( be != NULL, FALSE );
786 g_return_val_if_fail( inst != NULL, FALSE );
787 g_return_val_if_fail( GNC_IS_TRANS(inst), FALSE );
789 return save_transaction( be, GNC_TRANS(inst), TRUE );
795 g_return_val_if_fail( be != NULL, FALSE );
796 g_return_val_if_fail( inst != NULL, FALSE );
797 g_return_val_if_fail( GNC_IS_TRANS(inst), FALSE );
799 return save_transaction( be, GNC_TRANS(inst), FALSE );
816 g_return_if_fail( be != NULL );
817 g_return_if_fail( account != NULL );
821 query_sql = g_strdup_printf(
822 "SELECT DISTINCT t.* FROM %s AS t, %s AS s WHERE s.tx_guid=t.guid AND s.account_guid ='%s'",
823 TRANSACTION_TABLE, SPLIT_TABLE, guid_buf );
828 query_transactions( be, stmt );
829 gnc_sql_statement_dispose( stmt );
844 g_return_if_fail( be != NULL );
846 query_sql = g_strdup_printf(
"SELECT * FROM %s", TRANSACTION_TABLE );
851 query_transactions( be, stmt );
852 gnc_sql_statement_dispose( stmt );
857 convert_query_comparison_to_sql(
QofQueryPredData* pPredData, gboolean isInverted, GString* sql )
859 if ( pPredData->how == QOF_COMPARE_LT
860 || ( isInverted && pPredData->how == QOF_COMPARE_GTE ) )
862 g_string_append( sql,
"<" );
864 else if ( pPredData->how == QOF_COMPARE_LTE
865 || ( isInverted && pPredData->how == QOF_COMPARE_GT ) )
867 g_string_append( sql,
"<=" );
869 else if ( pPredData->how == QOF_COMPARE_EQUAL
870 || ( isInverted && pPredData->how == QOF_COMPARE_NEQ ) )
872 g_string_append( sql,
"=" );
874 else if ( pPredData->how == QOF_COMPARE_GT
875 || ( isInverted && pPredData->how == QOF_COMPARE_LTE ) )
877 g_string_append( sql,
">" );
879 else if ( pPredData->how == QOF_COMPARE_GTE
880 || ( isInverted && pPredData->how == QOF_COMPARE_LT ) )
882 g_string_append( sql,
">=" );
884 else if ( pPredData->how == QOF_COMPARE_NEQ
885 || ( isInverted && pPredData->how == QOF_COMPARE_EQUAL ) )
887 g_string_append( sql,
"~=" );
891 PERR(
"Unknown comparison type\n" );
892 g_string_append( sql,
"??" );
897 convert_query_term_to_sql(
const GncSqlBackend* be,
const gchar* fieldName, QofQueryTerm* pTerm, GString* sql )
902 g_return_if_fail( pTerm != NULL );
903 g_return_if_fail( sql != NULL );
905 pPredData = qof_query_term_get_pred_data( pTerm );
906 isInverted = qof_query_term_is_inverted( pTerm );
908 if ( g_strcmp0( pPredData->type_name, QOF_TYPE_GUID ) == 0 )
913 g_string_append( sql,
"(" );
914 g_string_append( sql, fieldName );
916 switch ( guid_data->options )
919 if ( isInverted ) g_string_append( sql,
" NOT IN (" );
920 else g_string_append( sql,
" IN (" );
923 case QOF_GUID_MATCH_NONE:
924 if ( isInverted ) g_string_append( sql,
" IN (" );
925 else g_string_append( sql,
" NOT IN (" );
929 PERR(
"Unexpected GncGUID match type: %d\n", guid_data->options );
932 for ( guid_entry = guid_data->guids; guid_entry != NULL; guid_entry = guid_entry->next )
936 if ( guid_entry != guid_data->guids ) g_string_append( sql,
"," );
938 g_string_append_printf( sql,
"'%s'", guid_buf );
940 g_string_append( sql,
"))" );
943 else if ( g_strcmp0( pPredData->type_name, QOF_TYPE_CHAR ) == 0 )
950 g_string_append( sql,
"NOT(" );
952 if ( char_data->options == QOF_CHAR_MATCH_NONE )
954 g_string_append( sql,
"NOT " );
956 g_string_append( sql,
"(" );
957 for ( i = 0; char_data->char_list[i] !=
'\0'; i++ )
961 g_string_append( sql,
" OR " );
963 g_string_append( sql, fieldName );
964 g_string_append( sql,
" = '" );
965 g_string_append_c( sql, char_data->char_list[i] );
966 g_string_append( sql,
"'" );
968 g_string_append( sql,
") " );
971 g_string_append( sql,
") " );
975 else if ( g_strcmp0( pPredData->type_name, QOF_TYPE_STRING ) == 0 )
982 g_string_append( sql,
"NOT(" );
984 if ( pPredData->how == QOF_COMPARE_NEQ )
986 g_string_append( sql,
"NOT(" );
988 g_string_append( sql, fieldName );
989 if ( string_data->is_regex || string_data->options == QOF_STRING_MATCH_CASEINSENSITIVE )
991 PWARN(
"String is_regex || option = QOF_STRING_MATCH_INSENSITIVE\n" );
995 g_string_append( sql,
" =" );
1000 g_string_append( sql,
"'" );
1001 g_string_append( sql, sqlEscapeString( escape, string_data->matchstring ) );
1002 g_string_append( sql,
"'" );
1003 if ( pPredData->how == QOF_COMPARE_NEQ )
1005 g_string_append( sql,
")" );
1009 g_string_append( sql,
")" );
1011 sqlEscape_destroy( escape );
1016 g_string_append( sql,
"(" );
1017 g_string_append( sql, fieldName );
1018 convert_query_comparison_to_sql( pPredData, isInverted, sql );
1020 if ( strcmp( pPredData->type_name, QOF_TYPE_NUMERIC ) == 0 )
1025 g_string_append_printf( sql,
"%f", d );
1028 else if ( g_strcmp0( pPredData->type_name, QOF_TYPE_DATE ) == 0 )
1034 g_string_append_printf( sql,
"'%s'", datebuf );
1037 else if ( strcmp( pPredData->type_name, QOF_TYPE_INT32 ) == 0 )
1041 g_string_append_printf( sql,
"%d", pData->val );
1044 else if ( strcmp( pPredData->type_name, QOF_TYPE_INT64 ) == 0 )
1048 g_string_append_printf( sql,
"%" G_GINT64_FORMAT, pData->val );
1051 else if ( strcmp( pPredData->type_name, QOF_TYPE_DOUBLE ) == 0 )
1055 g_string_append_printf( sql,
"%f", pData->val );
1058 else if ( strcmp( pPredData->type_name, QOF_TYPE_BOOLEAN ) == 0 )
1062 g_string_append_printf( sql,
"%d", pData->val );
1067 PERR(
"Unknown query predicate type: %s\n", pPredData->type_name );
1070 g_string_append( sql,
")" );
1077 gboolean has_been_run;
1080 #define TX_GUID_CHECK 0
1082 G_GNUC_UNUSED
static gpointer
1088 g_return_val_if_fail( be != NULL, NULL );
1089 g_return_val_if_fail( query != NULL, NULL );
1092 g_assert( query_info != NULL );
1093 query_info->has_been_run = FALSE;
1097 GList* orterms = qof_query_get_terms( query );
1099 GString* sql = g_string_new(
"" );
1100 gboolean need_OR = FALSE;
1102 for ( orTerm = orterms; orTerm != NULL; orTerm = orTerm->next )
1104 GList* andterms = (GList*)orTerm->data;
1106 gboolean need_AND = FALSE;
1108 gboolean has_tx_guid_check = FALSE;
1112 g_string_append( sql,
" OR " );
1114 g_string_append( sql,
"(" );
1115 for ( andTerm = andterms; andTerm != NULL; andTerm = andTerm->next )
1119 gboolean unknownPath = FALSE;
1121 term = (QofQueryTerm*)andTerm->data;
1122 paramPath = qof_query_term_get_param_path( term );
1126 #if SIMPLE_QUERY_COMPILATION
1127 if ( strcmp( paramPath->data, SPLIT_ACCOUNT ) != 0
1128 || strcmp( paramPath->next->data, QOF_PARAM_GUID ) != 0 )
continue;
1131 if ( need_AND ) g_string_append( sql,
" AND " );
1133 if ( strcmp( paramPath->data, SPLIT_ACCOUNT ) == 0
1134 && strcmp( paramPath->next->data, QOF_PARAM_GUID ) == 0 )
1136 convert_query_term_to_sql( be,
"s.account_guid", term, sql );
1137 #if SIMPLE_QUERY_COMPILATION
1138 goto done_compiling_query;
1142 else if ( strcmp( paramPath->data, SPLIT_RECONCILE ) == 0 )
1144 convert_query_term_to_sql( be,
"s.reconcile_state", term, sql );
1147 else if ( strcmp( paramPath->data, SPLIT_TRANS ) == 0 )
1150 if ( !has_tx_guid_check )
1152 g_string_append( sql,
"(splits.tx_guid = transactions.guid) AND " );
1153 has_tx_guid_check = TRUE;
1156 if ( strcmp( paramPath->next->data, TRANS_DATE_POSTED ) == 0 )
1158 convert_query_term_to_sql( be,
"t.post_date", term, sql );
1160 else if ( strcmp( paramPath->next->data, TRANS_DESCRIPTION ) == 0 )
1162 convert_query_term_to_sql( be,
"t.description", term, sql );
1170 else if ( strcmp( paramPath->data, SPLIT_VALUE ) == 0 )
1172 convert_query_term_to_sql( be,
"s.value_num/s.value_denom", term, sql );
1182 GString* name = g_string_new( (gchar*)paramPath->data );
1183 while ( paramPath->next != NULL )
1185 g_string_append( name,
"." );
1186 g_string_append( name, paramPath->next->data );
1187 paramPath = paramPath->next;
1189 PERR(
"Unknown SPLIT query field: %s\n", name->str );
1190 g_string_free( name, TRUE );
1197 if ( sql->str[sql->len-1] ==
'(' )
1199 g_string_truncate( sql, sql->len - 1 );
1204 g_string_append( sql,
")" );
1209 #if SIMPLE_QUERY_COMPILATION
1210 done_compiling_query:
1212 if ( sql->len != 0 )
1214 #if SIMPLE_QUERY_COMPILATION
1215 g_string_append( sql,
")" );
1217 query_sql = g_strdup_printf(
1218 "SELECT DISTINCT t.* FROM %s AS t, %s AS s WHERE s.tx_guid=t.guid AND %s",
1219 TRANSACTION_TABLE, SPLIT_TABLE, sql->str );
1223 query_sql = g_strdup_printf(
"SELECT * FROM %s", TRANSACTION_TABLE );
1227 g_string_free( sql, TRUE );
1228 g_free( query_sql );
1233 query_sql = g_strdup_printf(
"SELECT * FROM %s", TRANSACTION_TABLE );
1235 g_free( query_sql );
1241 G_GNUC_UNUSED
static void
1246 g_return_if_fail( be != NULL );
1247 g_return_if_fail( pQuery != NULL );
1249 if ( !query_info->has_been_run )
1251 query_transactions( be, query_info->stmt );
1252 query_info->has_been_run = TRUE;
1253 gnc_sql_statement_dispose( query_info->stmt );
1254 query_info->stmt = NULL;
1258 G_GNUC_UNUSED
static void
1261 g_return_if_fail( be != NULL );
1262 g_return_if_fail( pQuery != NULL );
1273 char reconcile_state;
1278 set_acct_bal_account_from_guid( gpointer pObject, gpointer pValue )
1283 g_return_if_fail( pObject != NULL );
1284 g_return_if_fail( pValue != NULL );
1290 set_acct_bal_reconcile_state( gpointer pObject, gpointer pValue )
1293 const gchar* s = (
const gchar*)pValue;
1295 g_return_if_fail( pObject != NULL );
1296 g_return_if_fail( pValue != NULL );
1298 bal->reconcile_state = s[0];
1302 set_acct_bal_balance( gpointer pObject,
gnc_numeric value )
1306 g_return_if_fail( pObject != NULL );
1308 bal->balance = value;
1314 {
"account_guid", CT_GUID, 0, 0, NULL, NULL, NULL, (
QofSetterFunc)set_acct_bal_account_from_guid },
1315 {
"reconcile_state", CT_STRING, 1, 0, NULL, NULL, NULL, (
QofSetterFunc)set_acct_bal_reconcile_state },
1316 {
"quantity", CT_NUMERIC, 0, 0, NULL, NULL, NULL, (
QofSetterFunc)set_acct_bal_balance },
1326 g_return_val_if_fail( be != NULL, NULL );
1327 g_return_val_if_fail( row != NULL, NULL );
1330 g_assert( bal != NULL );
1341 #if LOAD_TRANSACTIONS_AS_NEEDED
1345 GSList* bal_slist = NULL;
1347 g_return_val_if_fail( be != NULL, NULL );
1349 buf = g_strdup_printf(
"SELECT account_guid, reconcile_state, sum(quantity_num) as quantity_num, quantity_denom FROM %s GROUP BY account_guid, reconcile_state, quantity_denom ORDER BY account_guid, reconcile_state",
1352 g_assert( stmt != NULL );
1355 gnc_sql_statement_dispose( stmt );
1356 if ( result != NULL )
1361 row = gnc_sql_result_get_first_row( result );
1362 while ( row != NULL )
1367 single_bal = load_single_acct_balances( be, row );
1368 if ( single_bal != NULL )
1370 if ( bal != NULL && bal->acct != single_bal->acct )
1372 bal->cleared_balance =
gnc_numeric_add( bal->cleared_balance, bal->reconciled_balance,
1376 bal_slist = g_slist_append( bal_slist, bal );
1382 g_assert( bal != NULL );
1384 bal->acct = single_bal->acct;
1385 bal->balance = gnc_numeric_zero();
1386 bal->cleared_balance = gnc_numeric_zero();
1387 bal->reconciled_balance = gnc_numeric_zero();
1389 if ( single_bal->reconcile_state ==
'n' )
1394 else if ( single_bal->reconcile_state ==
'c' )
1396 bal->cleared_balance =
gnc_numeric_add( bal->cleared_balance, single_bal->balance,
1399 else if ( single_bal->reconcile_state ==
'y' )
1401 bal->reconciled_balance =
gnc_numeric_add( bal->reconciled_balance, single_bal->balance,
1404 g_free( single_bal );
1406 row = gnc_sql_result_get_next_row( result );
1412 bal->cleared_balance =
gnc_numeric_add( bal->cleared_balance, bal->reconciled_balance,
1416 bal_slist = g_slist_append( bal_slist, bal );
1418 gnc_sql_result_dispose( result );
1436 const gchar* guid_str;
1438 g_return_if_fail( be != NULL );
1439 g_return_if_fail( row != NULL );
1440 g_return_if_fail( pObject != NULL );
1441 g_return_if_fail( table_row != NULL );
1443 val = gnc_sql_row_get_value_at_col_name( row, table_row->
col_name );
1444 g_assert( val != NULL );
1445 guid_str = g_value_get_string(val);
1446 if ( guid_str != NULL )
1457 buf = g_strdup_printf(
"SELECT * FROM %s WHERE guid='%s'",
1458 TRANSACTION_TABLE, guid_str );
1469 qof_instance_increase_editlevel (pObject);
1471 qof_instance_decrease_editlevel (pObject);
1475 g_return_if_fail( setter != NULL );
1476 (*setter)( pObject, (
const gpointer)tx );
1490 gnc_sql_init_transaction_handler(
void )
1494 GNC_SQL_BACKEND_VERSION,
1497 #if LOAD_TRANSACTIONS_AS_NEEDED
1502 create_transaction_tables,
1510 GNC_SQL_BACKEND_VERSION,
1515 #if LOAD_TRANSACTIONS_AS_NEEDED
1516 compile_split_query,
gboolean qof_object_register_backend(QofIdTypeConst type_name, const char *backend_name, gpointer be_data)
Transaction * xaccMallocTransaction(QofBook *book)
void qof_backend_set_error(QofBackend *be, QofBackendError err)
const GncGUID * qof_instance_get_guid(gconstpointer)
Split * xaccTransGetSplit(const Transaction *trans, int i)
gint gnc_sql_get_table_version(const GncSqlBackend *be, const gchar *table_name)
time64 xaccTransGetDate(const Transaction *trans)
#define qof_instance_is_dirty
void gnc_account_foreach_descendant(const Account *acc, AccountCb thunk, gpointer user_data)
void gnc_sql_upgrade_table(GncSqlBackend *be, const gchar *table_name, const GncSqlColumnTableEntry *col_table)
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
#define PINFO(format, args...)
load and save data to SQL
void gnc_sql_add_colname_to_list(const GncSqlColumnTableEntry *table_row, GList **pList)
load and save accounts data to SQL
GncGUID guid_new_return(void)
gboolean qof_instance_get_destroying(gconstpointer ptr)
gboolean string_to_guid(const gchar *string, GncGUID *guid)
char xaccSplitGetReconcile(const Split *split)
gboolean gnc_sql_create_table(GncSqlBackend *be, const gchar *table_name, gint table_version, const GncSqlColumnTableEntry *col_table)
void gnc_lot_add_split(GNCLot *lot, Split *split)
load and save data to SQL
void gnc_sql_register_col_type_handler(const gchar *colType, const GncSqlColumnTypeHandler *handler)
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
void xaccSplitSetReconcile(Split *split, char recn)
void gnc_sql_add_objectref_guid_col_info_to_list(const GncSqlBackend *be, const GncSqlColumnTableEntry *table_row, GList **pList)
gchar * guid_to_string_buff(const GncGUID *guid, gchar *buff)
gpointer(* QofAccessFunc)(gpointer object, const QofParam *param)
gboolean gnc_sql_save_transaction(GncSqlBackend *be, QofInstance *inst)
#define PERR(format, args...)
struct _QofQuery QofQuery
gboolean gnc_sql_create_index(const GncSqlBackend *be, const gchar *index_name, const gchar *table_name, const GncSqlColumnTableEntry *col_table)
#define PWARN(format, args...)
const GncGUID * gnc_sql_load_guid(const GncSqlBackend *be, GncSqlRow *row)
Transaction * xaccTransLookup(const GncGUID *guid, QofBook *book)
char * qof_print_date(time64 secs)
gdouble gnc_numeric_to_double(gnc_numeric n)
Split * xaccSplitLookup(const GncGUID *guid, QofBook *book)
Account handling public routines.
guint gnc_sql_append_guid_list_to_sql(GString *sql, GList *list, guint maxCount)
gboolean gnc_sql_set_table_version(GncSqlBackend *be, const gchar *table_name, gint version)
gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2)
void gnc_sql_add_gvalue_objectref_guid_to_slist(const GncSqlBackend *be, QofIdTypeConst obj_name, const gpointer pObject, const GncSqlColumnTableEntry *table_row, GSList **pList)
#define GUID_ENCODING_LENGTH
void gnc_sql_slots_load_for_list(GncSqlBackend *be, GList *list)
void xaccAccountRecomputeBalance(Account *acc)
load and save data to SQL
void gnc_sql_transaction_load_tx_for_account(GncSqlBackend *be, Account *account)
const char * xaccTransGetDescription(const Transaction *trans)
GSList * gnc_sql_get_account_balances_slist(GncSqlBackend *be)
void xaccTransCommitEdit(Transaction *trans)
void xaccTransBeginEdit(Transaction *trans)
GncSqlResult * gnc_sql_execute_select_statement(GncSqlBackend *be, GncSqlStatement *stmt)
gboolean gnc_numeric_eq(gnc_numeric a, gnc_numeric b)
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)
const gchar * gobj_param_name
Split * xaccMallocSplit(QofBook *book)
void gnc_sql_transaction_load_all_tx(GncSqlBackend *be)
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
gboolean gnc_sql_slots_delete(GncSqlBackend *be, const GncGUID *guid)
void qof_event_suspend(void)
Suspend all engine events.
void xaccAccountBeginEdit(Account *acc)
Account * xaccSplitGetAccount(const Split *s)
const GncGUID * guid_null(void)
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
void qof_event_resume(void)
void(* QofSetterFunc)(gpointer, gpointer)
int qof_query_has_terms(QofQuery *q)
gboolean gnc_sql_do_db_operation(GncSqlBackend *be, E_DB_OPERATION op, const gchar *table_name, QofIdTypeConst obj_name, gpointer pObject, const GncSqlColumnTableEntry *table)
GncSqlStatement * gnc_sql_create_statement_from_sql(GncSqlBackend *be, const gchar *sql)
const char * xaccAccountGetName(const Account *acc)
API for Transactions and Splits (journal entries)
void xaccAccountCommitEdit(Account *acc)
SplitList * xaccTransGetSplitList(const Transaction *trans)
Commodity handling public routines.
gboolean gnc_sql_slots_save(GncSqlBackend *be, const GncGUID *guid, gboolean is_infant, KvpFrame *pFrame)
GncSqlResult * gnc_sql_execute_select_sql(GncSqlBackend *be, const gchar *sql)
GNCLot * xaccSplitGetLot(const Split *split)
const gchar * QofLogModule
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
gchar * gnc_sql_convert_timespec_to_string(const GncSqlBackend *be, Timespec ts)