/* ================================================================= */ static gboolean save_employee (GncSqlBackend* be, QofInstance* inst) { GncEmployee* emp; const GncGUID* guid; E_DB_OPERATION op; gboolean is_infant; gboolean is_ok = TRUE; g_return_val_if_fail (inst != NULL, FALSE); g_return_val_if_fail (GNC_IS_EMPLOYEE (inst), FALSE); g_return_val_if_fail (be != NULL, FALSE); emp = GNC_EMPLOYEE (inst); is_infant = qof_instance_get_infant (inst); if (qof_instance_get_destroying (inst)) { op = OP_DB_DELETE; } else if (be->is_pristine_db || is_infant) { op = OP_DB_INSERT; } else { op = OP_DB_UPDATE; } if (op != OP_DB_DELETE) { // Ensure the commodity is in the db is_ok = gnc_sql_save_commodity (be, gncEmployeeGetCurrency (emp)); } if (is_ok) { is_ok = gnc_sql_do_db_operation (be, op, TABLE_NAME, GNC_ID_EMPLOYEE, emp, col_table); } if (is_ok) { // Now, commit or delete any slots guid = qof_instance_get_guid (inst); if (!qof_instance_get_destroying (inst)) { is_ok = gnc_sql_slots_save (be, guid, is_infant, inst); } else { is_ok = gnc_sql_slots_delete (be, guid); } } return is_ok; }
/* ================================================================= */ bool GncSqlInvoiceBackend::commit (GncSqlBackend* be, QofInstance* inst) { const GncGUID* guid; GncInvoice* invoice; E_DB_OPERATION op; gboolean is_infant; gboolean is_ok = TRUE; g_return_val_if_fail (inst != NULL, FALSE); g_return_val_if_fail (GNC_IS_INVOICE (inst), FALSE); g_return_val_if_fail (be != NULL, FALSE); invoice = GNC_INVOICE (inst); is_infant = qof_instance_get_infant (inst); if (qof_instance_get_destroying (inst)) { op = OP_DB_DELETE; } else if (be->pristine() || is_infant) { op = OP_DB_INSERT; } else { op = OP_DB_UPDATE; } if (op != OP_DB_DELETE) { // Ensure the commodity is in the db is_ok = gnc_sql_save_commodity (be, gncInvoiceGetCurrency (invoice)); } if (is_ok) { is_ok = gnc_sql_do_db_operation (be, op, TABLE_NAME, GNC_ID_INVOICE, inst, col_table); } if (is_ok) { // Now, commit or delete any slots guid = qof_instance_get_guid (inst); if (!qof_instance_get_destroying (inst)) { is_ok = gnc_sql_slots_save (be, guid, is_infant, inst); } else { is_ok = gnc_sql_slots_delete (be, guid); } } return is_ok; }
static gboolean save_taxtable( GncSqlBackend* be, QofInstance* inst ) { GncTaxTable* tt; const GncGUID* guid; gint op; gboolean is_infant; gboolean is_ok; g_return_val_if_fail( inst != NULL, FALSE ); g_return_val_if_fail( GNC_IS_TAXTABLE(inst), FALSE ); g_return_val_if_fail( be != NULL, FALSE ); tt = GNC_TAXTABLE(inst); is_infant = qof_instance_get_infant( inst ); if ( qof_instance_get_destroying( inst ) ) { op = OP_DB_DELETE; } else if ( be->is_pristine_db || is_infant ) { op = OP_DB_INSERT; } else { op = OP_DB_UPDATE; } is_ok = gnc_sql_do_db_operation( be, op, TT_TABLE_NAME, GNC_ID_TAXTABLE, tt, tt_col_table ); if ( is_ok ) { // Now, commit or delete any slots and tax table entries guid = qof_instance_get_guid( inst ); if ( !qof_instance_get_destroying(inst) ) { is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) ); if ( is_ok ) { is_ok = save_tt_entries( be, guid, gncTaxTableGetEntries( tt ) ); } } else { is_ok = gnc_sql_slots_delete( be, guid ); if ( is_ok ) { is_ok = delete_all_tt_entries( be, guid ); } } } return is_ok; }
/* ================================================================= */ static gboolean delete_all_tt_entries( GncSqlBackend* be, const GncGUID* guid ) { guid_info_t guid_info; g_return_val_if_fail( be != NULL, FALSE ); g_return_val_if_fail( guid != NULL, FALSE ); guid_info.be = be; guid_info.guid = guid; return gnc_sql_do_db_operation( be, OP_DB_DELETE, TTENTRIES_TABLE_NAME, TTENTRIES_TABLE_NAME, &guid_info, guid_col_table ); }
gboolean gnc_sql_recurrence_delete( GncSqlBackend* be, const GncGUID* guid ) { recurrence_info_t recurrence_info; g_return_val_if_fail( be != NULL, FALSE ); g_return_val_if_fail( guid != NULL, FALSE ); recurrence_info.be = be; recurrence_info.guid = guid; return gnc_sql_do_db_operation( be, OP_DB_DELETE, TABLE_NAME, TABLE_NAME, &recurrence_info, guid_col_table ); }
gboolean gnc_sql_slots_delete( GncSqlBackend* be, const GncGUID* guid ) { gchar* buf; GncSqlResult* result; gchar guid_buf[GUID_ENCODING_LENGTH + 1]; GncSqlStatement* stmt; slot_info_t slot_info = { NULL, NULL, TRUE, NULL, 0, NULL, FRAME, NULL, g_string_new('\0') }; g_return_val_if_fail( be != NULL, FALSE ); g_return_val_if_fail( guid != NULL, FALSE ); (void)guid_to_string_buff( guid, guid_buf ); buf = g_strdup_printf( "SELECT * FROM %s WHERE obj_guid='%s' and slot_type in ('%d', '%d') and not guid_val is null", TABLE_NAME, guid_buf, KVP_TYPE_FRAME, KVP_TYPE_GLIST ); stmt = gnc_sql_create_statement_from_sql( be, buf ); g_free( buf ); if ( stmt != NULL ) { result = gnc_sql_execute_select_statement( be, stmt ); gnc_sql_statement_dispose( stmt ); if ( result != NULL ) { GncSqlRow* row = gnc_sql_result_get_first_row( result ); while ( row != NULL ) { GncSqlColumnTableEntry table_row = col_table[guid_val_col]; GncGUID child_guid; const GValue* val = gnc_sql_row_get_value_at_col_name( row, table_row.col_name); if ( val == NULL ) continue; (void)string_to_guid( g_value_get_string( val ), &child_guid ); gnc_sql_slots_delete( be, &child_guid ); row = gnc_sql_result_get_next_row( result ); } gnc_sql_result_dispose( result ); } } slot_info.be = be; slot_info.guid = guid; slot_info.is_ok = TRUE; slot_info.is_ok = gnc_sql_do_db_operation( be, OP_DB_DELETE, TABLE_NAME, TABLE_NAME, &slot_info, obj_guid_col_table ); return slot_info.is_ok; }
gboolean gnc_sql_recurrence_save( GncSqlBackend* be, const GncGUID* guid, const Recurrence* r ) { recurrence_info_t recurrence_info; g_return_val_if_fail( be != NULL, FALSE ); g_return_val_if_fail( guid != NULL, FALSE ); g_return_val_if_fail( r != NULL, FALSE ); (void)gnc_sql_recurrence_delete( be, guid ); recurrence_info.be = be; recurrence_info.guid = guid; recurrence_info.pRecurrence = (Recurrence*)r; return gnc_sql_do_db_operation( be, OP_DB_INSERT, TABLE_NAME, TABLE_NAME, &recurrence_info, col_table ); }
/** * Commits a split to the database * * @param be SQL backend * @param inst Split * @return TRUE if successful, FALSE if error */ static gboolean commit_split( GncSqlBackend* be, QofInstance* inst ) { gint op; gboolean is_infant; gboolean is_ok; GncGUID *guid = (GncGUID*)qof_instance_get_guid(inst); g_return_val_if_fail( inst != NULL, FALSE ); g_return_val_if_fail( be != NULL, FALSE ); is_infant = qof_instance_get_infant( inst ); if ( qof_instance_get_destroying( inst ) ) { op = OP_DB_DELETE; } else if ( be->is_pristine_db || is_infant ) { op = OP_DB_INSERT; } else { op = OP_DB_UPDATE; } if (guid_equal (guid, guid_null ())) { *guid = guid_new_return (); qof_instance_set_guid (inst, guid); } is_ok = gnc_sql_do_db_operation( be, op, SPLIT_TABLE, GNC_ID_SPLIT, inst, split_col_table ); if ( is_ok && !qof_instance_get_destroying (inst)) { is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) ); } return is_ok; }
/** * Deletes all of the splits for a transaction * * @param be SQL backend * @param pTx Transaction * @return TRUE if successful, FALSE if unsuccessful */ static gboolean delete_splits( GncSqlBackend* be, Transaction* pTx ) { split_info_t split_info; g_return_val_if_fail( be != NULL, FALSE ); g_return_val_if_fail( pTx != NULL, FALSE ); if ( !gnc_sql_do_db_operation( be, OP_DB_DELETE, SPLIT_TABLE, SPLIT_TABLE, pTx, tx_guid_col_table ) ) { return FALSE; } split_info.be = be; split_info.is_ok = TRUE; g_list_foreach( xaccTransGetSplitList( pTx ), delete_split_slots_cb, &split_info ); return split_info.is_ok; }
void gnc_sql_recurrence_save_list( GncSqlBackend* be, const GncGUID* guid, GList* schedule ) { recurrence_info_t recurrence_info; GList* l; g_return_if_fail( be != NULL ); g_return_if_fail( guid != NULL ); (void)gnc_sql_recurrence_delete( be, guid ); recurrence_info.be = be; recurrence_info.guid = guid; for ( l = schedule; l != NULL; l = g_list_next( l ) ) { recurrence_info.pRecurrence = (Recurrence*)l->data; (void)gnc_sql_do_db_operation( be, OP_DB_INSERT, TABLE_NAME, TABLE_NAME, &recurrence_info, col_table ); } }
static gboolean save_price (GncSqlBackend* be, QofInstance* inst) { GNCPrice* pPrice = GNC_PRICE (inst); E_DB_OPERATION op; gboolean is_infant; gboolean is_ok = TRUE; g_return_val_if_fail (be != NULL, FALSE); g_return_val_if_fail (inst != NULL, FALSE); g_return_val_if_fail (GNC_IS_PRICE (inst), FALSE); is_infant = qof_instance_get_infant (inst); if (qof_instance_get_destroying (inst)) { op = OP_DB_DELETE; } else if (be->is_pristine_db || is_infant) { op = OP_DB_INSERT; } else { op = OP_DB_UPDATE; } if (op != OP_DB_DELETE) { /* Ensure commodity and currency are in the db */ (void)gnc_sql_save_commodity (be, gnc_price_get_commodity (pPrice)); is_ok = gnc_sql_save_commodity (be, gnc_price_get_currency (pPrice)); } if (is_ok) { is_ok = gnc_sql_do_db_operation (be, op, TABLE_NAME, GNC_ID_PRICE, pPrice, col_table); } return is_ok; }
/* ================================================================= */ static gboolean do_commit_commodity( GncSqlBackend* be, QofInstance* inst, gboolean force_insert ) { const GncGUID* guid; gboolean is_infant; gint op; gboolean is_ok; is_infant = qof_instance_get_infant( inst ); if ( qof_instance_get_destroying( inst ) ) { op = OP_DB_DELETE; } else if ( be->is_pristine_db || is_infant || force_insert ) { op = OP_DB_INSERT; } else { op = OP_DB_UPDATE; } is_ok = gnc_sql_do_db_operation( be, op, COMMODITIES_TABLE, GNC_ID_COMMODITY, inst, col_table ); if ( is_ok ) { // Now, commit any slots guid = qof_instance_get_guid( inst ); if ( !qof_instance_get_destroying(inst) ) { is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) ); } else { is_ok = gnc_sql_slots_delete( be, guid ); } } return is_ok; }
static gboolean save_tt_entries( GncSqlBackend* be, const GncGUID* guid, GList* entries ) { GList* entry; gboolean is_ok; g_return_val_if_fail( be != NULL, FALSE ); g_return_val_if_fail( guid != NULL, FALSE ); /* First, delete the old entries for this object */ is_ok = delete_all_tt_entries( be, guid ); for ( entry = entries; entry != NULL && is_ok; entry = entry->next ) { GncTaxTableEntry* e = (GncTaxTableEntry*)entry->data; is_ok = gnc_sql_do_db_operation( be, OP_DB_INSERT, TTENTRIES_TABLE_NAME, GNC_ID_TAXTABLE, e, ttentries_col_table ); } return is_ok; }
static gboolean save_transaction( GncSqlBackend* be, Transaction* pTx, gboolean do_save_splits ) { const GncGUID* guid; gint op; gboolean is_infant; QofInstance* inst; gboolean is_ok = TRUE; gchar* err = NULL; g_return_val_if_fail( be != NULL, FALSE ); g_return_val_if_fail( pTx != NULL, FALSE ); inst = QOF_INSTANCE(pTx); is_infant = qof_instance_get_infant( inst ); if ( qof_instance_get_destroying( inst ) ) { op = OP_DB_DELETE; } else if ( be->is_pristine_db || is_infant ) { op = OP_DB_INSERT; } else { op = OP_DB_UPDATE; } if ( op != OP_DB_DELETE ) { gnc_commodity *commodity = xaccTransGetCurrency( pTx ); // Ensure the commodity is in the db is_ok = gnc_sql_save_commodity( be, commodity ); if ( ! is_ok ) { err = "Commodity save failed: Probably an invalid or missing currency"; qof_backend_set_error( &be->be, ERR_BACKEND_DATA_CORRUPT); } } if ( is_ok ) { is_ok = gnc_sql_do_db_operation( be, op, TRANSACTION_TABLE, GNC_ID_TRANS, pTx, tx_col_table ); if ( ! is_ok ) { err = "Transaction header save failed. Check trace log for SQL errors"; } } if ( is_ok ) { // Commit slots and splits guid = qof_instance_get_guid( inst ); if ( !qof_instance_get_destroying(inst) ) { is_ok = gnc_sql_slots_save( be, guid, is_infant, qof_instance_get_slots( inst ) ); if ( ! is_ok ) { err = "Slots save failed. Check trace log for SQL errors"; } if ( is_ok && do_save_splits ) { is_ok = save_splits( be, guid, xaccTransGetSplitList( pTx ) ); if ( ! is_ok ) { err = "Split save failed. Check trace log for SQL errors"; } } } else { is_ok = gnc_sql_slots_delete( be, guid ); if ( ! is_ok ) { err = "Slots delete failed. Check trace log for SQL errors"; } if ( is_ok ) { is_ok = delete_splits( be, pTx ); if ( ! is_ok ) { err = "Split delete failed. Check trace log for SQL errors"; } } } } if (! is_ok ) { G_GNUC_UNUSED gchar *message1 = "Transaction %s dated %s in account %s not saved due to %s.%s"; G_GNUC_UNUSED gchar *message2 = "\nDatabase may be corrupted, check your data carefully."; Split* split = xaccTransGetSplit( pTx, 0); Account *acc = xaccSplitGetAccount( split ); /* FIXME: This needs to be implemented qof_error_format_secondary_text( GTK_MESSAGE_DIALOG( msg ), message1, xaccTransGetDescription( pTx ), qof_print_date( xaccTransGetDate( pTx ) ), xaccAccountGetName( acc ), err, message2 ); */ PERR( "Transaction %s dated %s in account %s not saved due to %s.\n", xaccTransGetDescription( pTx ), qof_print_date( xaccTransGetDate( pTx ) ), xaccAccountGetName( acc ), err ); } return is_ok; }
static void save_slot( const gchar* key, KvpValue* value, gpointer data ) { slot_info_t* pSlot_info = (slot_info_t*)data; gsize curlen; g_return_if_fail( key != NULL ); g_return_if_fail( value != NULL ); g_return_if_fail( data != NULL ); // Ignore if we've already run into a failure if ( !pSlot_info->is_ok ) { return; } curlen = pSlot_info->path->len; pSlot_info->pKvpValue = value; if ( curlen != 0 ) { (void)g_string_append( pSlot_info->path, "/" ); } (void)g_string_append( pSlot_info->path, key ); pSlot_info->value_type = kvp_value_get_type( value ); switch ( pSlot_info->value_type ) { case KVP_TYPE_FRAME: { KvpFrame* pKvpFrame = kvp_value_get_frame( value ); GncGUID guid = guid_new_return(); slot_info_t *pNewInfo = slot_info_copy( pSlot_info, &guid ); KvpValue *oldValue = pSlot_info->pKvpValue; pSlot_info->pKvpValue = kvp_value_new_guid( &guid ); pSlot_info->is_ok = gnc_sql_do_db_operation( pSlot_info->be, OP_DB_INSERT, TABLE_NAME, TABLE_NAME, pSlot_info, col_table ); g_return_if_fail( pSlot_info->is_ok ); kvp_frame_for_each_slot( pKvpFrame, save_slot, pNewInfo ); kvp_value_delete( pSlot_info->pKvpValue ); pSlot_info->pKvpValue = oldValue; g_string_free( pNewInfo->path, TRUE ); g_slice_free( slot_info_t, pNewInfo ); } break; case KVP_TYPE_GLIST: { GList *cursor; GncGUID guid = guid_new_return(); slot_info_t *pNewInfo = slot_info_copy( pSlot_info, &guid ); KvpValue *oldValue = pSlot_info->pKvpValue; pSlot_info->pKvpValue = kvp_value_new_guid( &guid ); pSlot_info->is_ok = gnc_sql_do_db_operation( pSlot_info->be, OP_DB_INSERT, TABLE_NAME, TABLE_NAME, pSlot_info, col_table ); g_return_if_fail( pSlot_info->is_ok ); for (cursor = kvp_value_get_glist(value); cursor; cursor = cursor->next) { kvp_value *val = (kvp_value*)cursor->data; save_slot("", val, pNewInfo); } kvp_value_delete( pSlot_info->pKvpValue ); pSlot_info->pKvpValue = oldValue; g_string_free( pNewInfo->path, TRUE ); g_slice_free( slot_info_t, pNewInfo ); } break; default: { pSlot_info->is_ok = gnc_sql_do_db_operation( pSlot_info->be, OP_DB_INSERT, TABLE_NAME, TABLE_NAME, pSlot_info, col_table ); } break; } (void)g_string_truncate( pSlot_info->path, curlen ); }
/* ================================================================= */ gboolean gnc_sql_save_account (GncSqlBackend* be, QofInstance* inst) { Account* pAcc = GNC_ACCOUNT (inst); const GncGUID* guid; gboolean is_infant; gboolean is_ok = FALSE; gnc_commodity* commodity; E_DB_OPERATION op; g_return_val_if_fail (be != NULL, FALSE); g_return_val_if_fail (inst != NULL, FALSE); g_return_val_if_fail (GNC_IS_ACCOUNT (inst), FALSE); ENTER ("inst=%p", inst); is_infant = qof_instance_get_infant (inst); // If there is no commodity yet, this might be because a new account name // has been entered directly into the register and an account window will // be opened. The account info is not complete yet, but the name has been // set, triggering this commit commodity = xaccAccountGetCommodity (pAcc); is_ok = TRUE; if (qof_instance_get_destroying (inst)) { op = OP_DB_DELETE; } else if (be->is_pristine_db || is_infant) { op = OP_DB_INSERT; } else { op = OP_DB_UPDATE; } // If not deleting the account, ensure the commodity is in the db if (op != OP_DB_DELETE && commodity != NULL) { is_ok = gnc_sql_save_commodity (be, commodity); } if (is_ok) { is_ok = gnc_sql_do_db_operation (be, op, TABLE_NAME, GNC_ID_ACCOUNT, pAcc, col_table); } if (is_ok) { // Now, commit or delete any slots guid = qof_instance_get_guid (inst); if (!qof_instance_get_destroying (inst)) { is_ok = gnc_sql_slots_save (be, guid, is_infant, inst); } else { is_ok = gnc_sql_slots_delete (be, guid); } } LEAVE ("is_ok=%d", is_ok); return is_ok; }
static void save_slot( const gchar* key, KvpValue* value, gpointer data ) { slot_info_t* pSlot_info = (slot_info_t*)data; gsize curlen; g_return_if_fail( key != NULL ); g_return_if_fail( value != NULL ); g_return_if_fail( data != NULL ); // Ignore if we've already run into a failure if ( !pSlot_info->is_ok ) { return; } curlen = pSlot_info->path->len; pSlot_info->pKvpValue = value; if ( curlen != 0 ) { (void)g_string_append( pSlot_info->path, "/" ); } (void)g_string_append( pSlot_info->path, key ); pSlot_info->value_type = value->get_type(); switch ( pSlot_info->value_type ) { case KvpValue::Type::FRAME: { auto pKvpFrame = value->get<KvpFrame*>(); auto guid = guid_new(); slot_info_t *pNewInfo = slot_info_copy( pSlot_info, guid ); KvpValue *oldValue = pSlot_info->pKvpValue; pSlot_info->pKvpValue = new KvpValue{guid}; pSlot_info->is_ok = gnc_sql_do_db_operation( pSlot_info->be, OP_DB_INSERT, TABLE_NAME, TABLE_NAME, pSlot_info, col_table ); g_return_if_fail( pSlot_info->is_ok ); pKvpFrame->for_each_slot(save_slot, pNewInfo); delete pSlot_info->pKvpValue; pSlot_info->pKvpValue = oldValue; g_string_free( pNewInfo->path, TRUE ); g_slice_free( slot_info_t, pNewInfo ); } break; case KvpValue::Type::GLIST: { GncGUID guid = guid_new_return(); slot_info_t *pNewInfo = slot_info_copy( pSlot_info, &guid ); KvpValue *oldValue = pSlot_info->pKvpValue; pSlot_info->pKvpValue = new KvpValue{&guid}; pSlot_info->is_ok = gnc_sql_do_db_operation( pSlot_info->be, OP_DB_INSERT, TABLE_NAME, TABLE_NAME, pSlot_info, col_table ); g_return_if_fail( pSlot_info->is_ok ); for (auto cursor = value->get<GList*>(); cursor; cursor = cursor->next) { auto val = static_cast<KvpValue*>(cursor->data); save_slot("", val, pNewInfo); } delete pSlot_info->pKvpValue; pSlot_info->pKvpValue = oldValue; g_string_free( pNewInfo->path, TRUE ); g_slice_free( slot_info_t, pNewInfo ); } break; default: { pSlot_info->is_ok = gnc_sql_do_db_operation( pSlot_info->be, OP_DB_INSERT, TABLE_NAME, TABLE_NAME, pSlot_info, col_table ); } break; } (void)g_string_truncate( pSlot_info->path, curlen ); }