exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit 263340e88275f201025052c99a00b9ba99fe951d
parent 4d185c7ff1225756fbc5e82a8cbdc97e83614999
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sat,  8 Aug 2026 21:27:25 +0200

use upsert instead of insert+update

Diffstat:
Msrc/auditor/taler-helper-auditor-aggregation.c | 31-------------------------------
Msrc/auditor/taler-helper-auditor-aml.c | 14--------------
Msrc/auditor/taler-helper-auditor-coins.c | 46----------------------------------------------
Msrc/auditor/taler-helper-auditor-deposits.c | 48+++++++++++++-----------------------------------
Msrc/auditor/taler-helper-auditor-purses.c | 110++++++++++++++++++++++++++-----------------------------------------------------
Msrc/auditor/taler-helper-auditor-reserves.c | 42------------------------------------------
Msrc/auditor/taler-helper-auditor-transfer.c | 20--------------------
Msrc/auditor/taler-helper-auditor-wire-credit.c | 25-------------------------
Msrc/auditor/taler-helper-auditor-wire-debit.c | 29-----------------------------
Msrc/auditordb/insert_auditor_progress.c | 25++++++++++++++++++-------
Msrc/auditordb/insert_balance.c | 15+++++++++++++--
Msrc/auditordb/meson.build | 25+++++++++++++++++++++++--
Msrc/auditordb/test_auditordb_checkpoints.c | 44++++++++++++++++++++++++--------------------
Asrc/auditordb/test_auditordb_regression.c | 267+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/auditordb/update_auditor_progress.c | 95-------------------------------------------------------------------------------
Dsrc/auditordb/update_balance.c | 95-------------------------------------------------------------------------------
Msrc/include/auditor-database/insert_auditor_progress.h | 8++++++--
Msrc/include/auditor-database/insert_balance.h | 8++++++--
Dsrc/include/auditor-database/update_auditor_progress.h | 44--------------------------------------------
Dsrc/include/auditor-database/update_balance.h | 46----------------------------------------------
20 files changed, 406 insertions(+), 631 deletions(-)

diff --git a/src/auditor/taler-helper-auditor-aggregation.c b/src/auditor/taler-helper-auditor-aggregation.c @@ -42,8 +42,6 @@ struct AggregationContext; #include "auditor-database/insert_fee_time_inconsistency.h" #include "auditor-database/insert_row_inconsistency.h" #include "auditor-database/insert_wire_out_inconsistency.h" -#include "auditor-database/update_auditor_progress.h" -#include "auditor-database/update_balance.h" #include "exchange-database/get_coin_transactions.h" #include "exchange-database/get_known_coin.h" #include "exchange-database/get_wire_fee.h" @@ -1502,24 +1500,6 @@ analyze_aggregations (void *cls) GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); return qs; } - qs = TALER_AUDITORDB_update_balance ( - TALER_ARL_adb, - TALER_ARL_SET_AB (aggregation_total_wire_fee_revenue), - TALER_ARL_SET_AB (aggregation_total_arithmetic_delta_plus), - TALER_ARL_SET_AB (aggregation_total_arithmetic_delta_minus), - TALER_ARL_SET_AB (aggregation_total_bad_sig_loss), - TALER_ARL_SET_AB (aggregation_total_wire_out_delta_plus), - TALER_ARL_SET_AB (aggregation_total_wire_out_delta_minus), - TALER_ARL_SET_AB (aggregation_total_coin_delta_plus), - TALER_ARL_SET_AB (aggregation_total_coin_delta_minus), - NULL); - if (0 > qs) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Failed to update auditor DB, not recording progress\n"); - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - return qs; - } qs = TALER_AUDITORDB_insert_auditor_progress ( TALER_ARL_adb, @@ -1532,17 +1512,6 @@ analyze_aggregations (void *cls) GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); return qs; } - qs = TALER_AUDITORDB_update_auditor_progress ( - TALER_ARL_adb, - TALER_ARL_SET_PP (aggregation_last_wire_out_serial_id), - NULL); - if (0 > qs) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Failed to update auditor DB, not recording progress\n"); - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - return qs; - } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Concluded aggregation audit step at %llu\n", (unsigned long long) TALER_ARL_USE_PP ( diff --git a/src/auditor/taler-helper-auditor-aml.c b/src/auditor/taler-helper-auditor-aml.c @@ -75,7 +75,6 @@ #include "auditor-database/insert_auditor_progress.h" #include "auditor-database/insert_row_inconsistency.h" #include "auditor-database/iterate_aml_staff.h" -#include "auditor-database/update_auditor_progress.h" #include "exchange-database/iterate_aml_history_above_serial_id.h" #include "exchange-database/iterate_aml_staff_above_serial_id.h" #include "exchange-database/iterate_legitimization_outcomes_above_serial_id.h" @@ -858,19 +857,6 @@ analyze_aml (void *cls) GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); return qs; } - qs = TALER_AUDITORDB_update_auditor_progress ( - TALER_ARL_adb, - TALER_ARL_SET_PP (aml_history_serial_id), - TALER_ARL_SET_PP (aml_staff_uuid), - TALER_ARL_SET_PP (legitimization_outcome_serial_id), - NULL); - if (0 > qs) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Failed to update auditor DB, not recording progress\n"); - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - return qs; - } return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; } diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c @@ -38,8 +38,6 @@ #include "auditor-database/insert_emergency_by_count.h" #include "auditor-database/insert_historic_denom_revenue.h" #include "auditor-database/insert_row_inconsistency.h" -#include "auditor-database/update_auditor_progress.h" -#include "auditor-database/update_balance.h" #include "auditor-database/update_denomination_balance.h" #include "exchange-database/get_count_known_coins.h" #include "exchange-database/get_coin_transactions.h" @@ -2890,31 +2888,6 @@ analyze_coins (void *cls) goto cleanup; } - qs = TALER_AUDITORDB_update_balance ( - TALER_ARL_adb, - TALER_ARL_SET_AB (coin_balance_risk), - TALER_ARL_SET_AB (total_escrowed), - TALER_ARL_SET_AB (coin_irregular_loss), - TALER_ARL_SET_AB (coin_melt_fee_revenue), - TALER_ARL_SET_AB (coin_deposit_fee_revenue), - TALER_ARL_SET_AB (coin_deposit_fee_loss), - TALER_ARL_SET_AB (coin_refund_fee_revenue), - TALER_ARL_SET_AB (total_recoup_loss), - TALER_ARL_SET_AB (coins_total_arithmetic_delta_plus), - TALER_ARL_SET_AB (coins_total_arithmetic_delta_minus), - TALER_ARL_SET_AB (coins_reported_emergency_risk_by_count), - TALER_ARL_SET_AB (coins_reported_emergency_risk_by_amount), - TALER_ARL_SET_AB (coins_emergencies_loss), - TALER_ARL_SET_AB (coins_emergencies_loss_by_count), - NULL); - if (0 > qs) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Failed to update auditor DB, not recording progress\n"); - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - goto cleanup; - } - qs = TALER_AUDITORDB_insert_auditor_progress ( TALER_ARL_adb, TALER_ARL_SET_PP (coins_withdraw_serial_id), @@ -2934,25 +2907,6 @@ analyze_coins (void *cls) goto cleanup; } - qs = TALER_AUDITORDB_update_auditor_progress ( - TALER_ARL_adb, - TALER_ARL_SET_PP (coins_withdraw_serial_id), - TALER_ARL_SET_PP (coins_deposit_serial_id), - TALER_ARL_SET_PP (coins_melt_serial_id), - TALER_ARL_SET_PP (coins_refund_serial_id), - TALER_ARL_SET_PP (coins_recoup_serial_id), - TALER_ARL_SET_PP (coins_recoup_refresh_serial_id), - TALER_ARL_SET_PP (coins_purse_deposits_serial_id), - TALER_ARL_SET_PP (coins_purse_refunds_serial_id), - NULL); - if (0 > qs) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Failed to update auditor DB, not recording progress\n"); - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - goto cleanup; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Concluded coin audit step at %llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu\n", (unsigned long long) TALER_ARL_USE_PP (coins_withdraw_serial_id), diff --git a/src/auditor/taler-helper-auditor-deposits.c b/src/auditor/taler-helper-auditor-deposits.c @@ -38,8 +38,6 @@ #include "auditor-database/iterate_deposit_confirmations.h" #include "auditor-database/insert_auditor_progress.h" #include "auditor-database/insert_balance.h" -#include "auditor-database/update_auditor_progress.h" -#include "auditor-database/update_balance.h" #include "exchange-database/get_exists_deposit.h" /* @@ -286,19 +284,11 @@ analyze_deposit_confirmations (void *cls) return qs; } had_pp = (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs); - if (had_pp) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Resuming deposit confirmation audit at %llu\n", - (unsigned long long) TALER_ARL_USE_PP ( - deposit_confirmation_serial_id)); - pp = TALER_ARL_USE_PP (deposit_confirmation_serial_id); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, - "First analysis using deposit auditor, starting audit from scratch\n"); - } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Resuming deposit confirmation audit at %llu\n", + (unsigned long long) TALER_ARL_USE_PP ( + deposit_confirmation_serial_id)); + pp = TALER_ARL_USE_PP (deposit_confirmation_serial_id); qs = TALER_AUDITORDB_get_balance ( TALER_ARL_adb, TALER_ARL_GET_AB (total_missed_deposit_confirmations), @@ -331,16 +321,10 @@ analyze_deposit_confirmations (void *cls) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Analyzed %d deposit confirmations\n", (int) qs); - if (had_pp) - qs = TALER_AUDITORDB_update_auditor_progress ( - TALER_ARL_adb, - TALER_ARL_SET_PP (deposit_confirmation_serial_id), - NULL); - else - qs = TALER_AUDITORDB_insert_auditor_progress ( - TALER_ARL_adb, - TALER_ARL_SET_PP (deposit_confirmation_serial_id), - NULL); + qs = TALER_AUDITORDB_insert_auditor_progress ( + TALER_ARL_adb, + TALER_ARL_SET_PP (deposit_confirmation_serial_id), + NULL); if (0 > qs) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -371,16 +355,10 @@ analyze_deposit_confirmations (void *cls) "Re-analyzed %d deposit confirmations\n", (int) qs); } - if (had_bal) - qs = TALER_AUDITORDB_update_balance ( - TALER_ARL_adb, - TALER_ARL_SET_AB (total_missed_deposit_confirmations), - NULL); - else - qs = TALER_AUDITORDB_insert_balance ( - TALER_ARL_adb, - TALER_ARL_SET_AB (total_missed_deposit_confirmations), - NULL); + qs = TALER_AUDITORDB_insert_balance ( + TALER_ARL_adb, + TALER_ARL_SET_AB (total_missed_deposit_confirmations), + NULL); if (0 > qs) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, diff --git a/src/auditor/taler-helper-auditor-purses.c b/src/auditor/taler-helper-auditor-purses.c @@ -41,8 +41,6 @@ struct PurseContext; #define TALER_AUDITORDB_EXPIRED_PURSE_RESULT_CLOSURE struct PurseContext #include "auditor-database/iterate_purse_expired.h" -#include "auditor-database/update_auditor_progress.h" -#include "auditor-database/update_balance.h" #include "auditor-database/update_purse_info.h" #include "exchange-database/get_global_fee.h" struct PurseContext; @@ -1389,8 +1387,6 @@ analyze_purses (void *cls) { struct PurseContext pc; enum GNUNET_DB_QueryStatus qs; - bool had_pp; - bool had_bal; (void) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -1410,31 +1406,22 @@ analyze_purses (void *cls) GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); return qs; } - had_pp = (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs); - if (had_pp) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Resuming purse audit at %llu/%llu/%llu/%llu/%llu/%llu/%llu\n", - (unsigned long long) TALER_ARL_USE_PP ( - purse_open_counter), - (unsigned long long) TALER_ARL_USE_PP ( - purse_request_serial_id), - (unsigned long long) TALER_ARL_USE_PP ( - purse_decision_serial_id), - (unsigned long long) TALER_ARL_USE_PP ( - purse_deletion_serial_id), - (unsigned long long) TALER_ARL_USE_PP ( - purse_merges_serial_id), - (unsigned long long) TALER_ARL_USE_PP ( - purse_deposits_serial_id), - (unsigned long long) TALER_ARL_USE_PP ( - purse_account_merge_serial_id)); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, - "First analysis using this auditor, starting audit from scratch\n"); - } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Resuming purse audit at %llu/%llu/%llu/%llu/%llu/%llu/%llu\n", + (unsigned long long) TALER_ARL_USE_PP ( + purse_open_counter), + (unsigned long long) TALER_ARL_USE_PP ( + purse_request_serial_id), + (unsigned long long) TALER_ARL_USE_PP ( + purse_decision_serial_id), + (unsigned long long) TALER_ARL_USE_PP ( + purse_deletion_serial_id), + (unsigned long long) TALER_ARL_USE_PP ( + purse_merges_serial_id), + (unsigned long long) TALER_ARL_USE_PP ( + purse_deposits_serial_id), + (unsigned long long) TALER_ARL_USE_PP ( + purse_account_merge_serial_id)); pc.qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; qs = TALER_AUDITORDB_get_balance ( TALER_ARL_adb, @@ -1451,7 +1438,6 @@ analyze_purses (void *cls) GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); return qs; } - had_bal = (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs); pc.purses = GNUNET_CONTAINER_multihashmap_create (512, GNUNET_NO); @@ -1580,28 +1566,16 @@ analyze_purses (void *cls) GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == pc.qs); return pc.qs; } - if (had_bal) - qs = TALER_AUDITORDB_update_balance ( - TALER_ARL_adb, - TALER_ARL_SET_AB (purse_global_balance), - TALER_ARL_SET_AB (purse_total_balance_insufficient_loss), - TALER_ARL_SET_AB (purse_total_delayed_decisions), - TALER_ARL_SET_AB (purse_total_balance_purse_not_closed), - TALER_ARL_SET_AB (purse_total_arithmetic_delta_plus), - TALER_ARL_SET_AB (purse_total_arithmetic_delta_minus), - TALER_ARL_SET_AB (purse_total_bad_sig_loss), - NULL); - else - qs = TALER_AUDITORDB_insert_balance ( - TALER_ARL_adb, - TALER_ARL_SET_AB (purse_global_balance), - TALER_ARL_SET_AB (purse_total_balance_insufficient_loss), - TALER_ARL_SET_AB (purse_total_delayed_decisions), - TALER_ARL_SET_AB (purse_total_balance_purse_not_closed), - TALER_ARL_SET_AB (purse_total_arithmetic_delta_plus), - TALER_ARL_SET_AB (purse_total_arithmetic_delta_minus), - TALER_ARL_SET_AB (purse_total_bad_sig_loss), - NULL); + qs = TALER_AUDITORDB_insert_balance ( + TALER_ARL_adb, + TALER_ARL_SET_AB (purse_global_balance), + TALER_ARL_SET_AB (purse_total_balance_insufficient_loss), + TALER_ARL_SET_AB (purse_total_delayed_decisions), + TALER_ARL_SET_AB (purse_total_balance_purse_not_closed), + TALER_ARL_SET_AB (purse_total_arithmetic_delta_plus), + TALER_ARL_SET_AB (purse_total_arithmetic_delta_minus), + TALER_ARL_SET_AB (purse_total_bad_sig_loss), + NULL); if (0 > qs) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -1609,28 +1583,16 @@ analyze_purses (void *cls) GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); return qs; } - if (had_pp) - qs = TALER_AUDITORDB_update_auditor_progress ( - TALER_ARL_adb, - TALER_ARL_SET_PP (purse_account_merge_serial_id), - TALER_ARL_SET_PP (purse_decision_serial_id), - TALER_ARL_SET_PP (purse_deletion_serial_id), - TALER_ARL_SET_PP (purse_deposits_serial_id), - TALER_ARL_SET_PP (purse_merges_serial_id), - TALER_ARL_SET_PP (purse_request_serial_id), - TALER_ARL_SET_PP (purse_open_counter), - NULL); - else - qs = TALER_AUDITORDB_insert_auditor_progress ( - TALER_ARL_adb, - TALER_ARL_SET_PP (purse_account_merge_serial_id), - TALER_ARL_SET_PP (purse_decision_serial_id), - TALER_ARL_SET_PP (purse_deletion_serial_id), - TALER_ARL_SET_PP (purse_deposits_serial_id), - TALER_ARL_SET_PP (purse_merges_serial_id), - TALER_ARL_SET_PP (purse_request_serial_id), - TALER_ARL_SET_PP (purse_open_counter), - NULL); + qs = TALER_AUDITORDB_insert_auditor_progress ( + TALER_ARL_adb, + TALER_ARL_SET_PP (purse_account_merge_serial_id), + TALER_ARL_SET_PP (purse_decision_serial_id), + TALER_ARL_SET_PP (purse_deletion_serial_id), + TALER_ARL_SET_PP (purse_deposits_serial_id), + TALER_ARL_SET_PP (purse_merges_serial_id), + TALER_ARL_SET_PP (purse_request_serial_id), + TALER_ARL_SET_PP (purse_open_counter), + NULL); if (0 > qs) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, diff --git a/src/auditor/taler-helper-auditor-reserves.c b/src/auditor/taler-helper-auditor-reserves.c @@ -47,8 +47,6 @@ struct ReserveContext; #include "auditor-database/insert_reserve_info.h" #include "auditor-database/insert_reserve_not_closed_inconsistency.h" #include "auditor-database/insert_row_inconsistency.h" -#include "auditor-database/update_auditor_progress.h" -#include "auditor-database/update_balance.h" #include "auditor-database/update_reserve_info.h" #include "exchange-database/get_denomination_revocation.h" #include "exchange-database/get_wire_fee.h" @@ -2018,28 +2016,6 @@ analyze_reserves (void *cls) goto cleanup; } - qs = TALER_AUDITORDB_update_balance ( - TALER_ARL_adb, - TALER_ARL_SET_AB (reserves_reserve_total_balance), - TALER_ARL_SET_AB (reserves_reserve_loss), - TALER_ARL_SET_AB (reserves_withdraw_fee_revenue), - TALER_ARL_SET_AB (reserves_close_fee_revenue), - TALER_ARL_SET_AB (reserves_purse_fee_revenue), - TALER_ARL_SET_AB (reserves_open_fee_revenue), - TALER_ARL_SET_AB (reserves_history_fee_revenue), - TALER_ARL_SET_AB (reserves_total_bad_sig_loss), - TALER_ARL_SET_AB (total_balance_reserve_not_closed), - TALER_ARL_SET_AB (reserves_total_arithmetic_delta_plus), - TALER_ARL_SET_AB (reserves_total_arithmetic_delta_minus), - TALER_ARL_SET_AB (total_balance_summary_delta_plus), - TALER_ARL_SET_AB (total_balance_summary_delta_minus), - NULL); - if (0 > qs) - { - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - goto cleanup; - } - qs = TALER_AUDITORDB_insert_auditor_progress ( TALER_ARL_adb, TALER_ARL_SET_PP (reserves_reserve_in_serial_id), @@ -2058,24 +2034,6 @@ analyze_reserves (void *cls) GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); goto cleanup; } - qs = TALER_AUDITORDB_update_auditor_progress ( - TALER_ARL_adb, - TALER_ARL_SET_PP (reserves_reserve_in_serial_id), - TALER_ARL_SET_PP (reserves_withdraw_serial_id), - TALER_ARL_SET_PP (reserves_reserve_recoup_serial_id), - TALER_ARL_SET_PP (reserves_reserve_open_serial_id), - TALER_ARL_SET_PP (reserves_reserve_close_serial_id), - TALER_ARL_SET_PP (reserves_purse_decisions_serial_id), - TALER_ARL_SET_PP (reserves_account_merges_serial_id), - TALER_ARL_SET_PP (reserves_history_requests_serial_id), - NULL); - if (0 > qs) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Failed to update auditor DB, not recording progress\n"); - GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); - goto cleanup; - } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Concluded reserve audit step at %llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu\n", diff --git a/src/auditor/taler-helper-auditor-transfer.c b/src/auditor/taler-helper-auditor-transfer.c @@ -61,8 +61,6 @@ #include "auditor-database/preflight.h" #include "auditor-database/start.h" #include "auditor-database/update_aml_hold.h" -#include "auditor-database/update_auditor_progress.h" -#include "auditor-database/update_balance.h" #include "exchange-database/get_aggregation_deferral_by_wtid.h" #include "exchange-database/get_aggregation_transient_by_wtid.h" #include "exchange-database/get_open_legitimization_measure.h" @@ -1086,14 +1084,6 @@ begin_transaction (void) if (0 > qs) goto handle_db_error; - qs = TALER_AUDITORDB_update_auditor_progress ( - TALER_ARL_adb, - TALER_ARL_SET_PP (wire_batch_deposit_id), - TALER_ARL_SET_PP (wire_aggregation_id), - TALER_ARL_SET_PP (wire_hold_aggregation_id), - NULL); - if (0 > qs) - goto handle_db_error; qs = TALER_AUDITORDB_insert_auditor_progress ( TALER_ARL_adb, TALER_ARL_SET_PP (wire_batch_deposit_id), @@ -1102,16 +1092,6 @@ begin_transaction (void) NULL); if (0 > qs) goto handle_db_error; - qs = TALER_AUDITORDB_update_balance ( - TALER_ARL_adb, - TALER_ARL_SET_AB (total_amount_lag), - TALER_ARL_SET_AB (total_early_aggregation), - TALER_ARL_SET_AB (total_aml_hold), - TALER_ARL_SET_AB (total_small_aggregate), - TALER_ARL_SET_AB (total_transfer_lag), - NULL); - if (0 > qs) - goto handle_db_error; qs = TALER_AUDITORDB_insert_balance ( TALER_ARL_adb, TALER_ARL_SET_AB (total_amount_lag), diff --git a/src/auditor/taler-helper-auditor-wire-credit.c b/src/auditor/taler-helper-auditor-wire-credit.c @@ -49,8 +49,6 @@ #include "auditor-database/preflight.h" #include "auditor-database/get_reserve_in_inconsistency.h" #include "auditor-database/start.h" -#include "auditor-database/update_auditor_progress.h" -#include "auditor-database/update_balance.h" #include "exchange-database/preflight.h" #include "exchange-database/rollback.h" #include \ @@ -515,18 +513,6 @@ commit (enum GNUNET_DB_QueryStatus qs) TALER_EXCHANGEDB_rollback (TALER_ARL_edb); if (qs < 0) goto handle_db_error; - qs = TALER_AUDITORDB_update_balance ( - TALER_ARL_adb, - TALER_ARL_SET_AB (total_wire_in), - TALER_ARL_SET_AB (total_kycauth_in), - TALER_ARL_SET_AB (total_kycauth_revenue), - TALER_ARL_SET_AB (total_wire_credit_fees), - TALER_ARL_SET_AB (total_bad_amount_in_plus), - TALER_ARL_SET_AB (total_bad_amount_in_minus), - TALER_ARL_SET_AB (total_misattribution_in), - NULL); - if (0 > qs) - goto handle_db_error; qs = TALER_AUDITORDB_insert_balance ( TALER_ARL_adb, TALER_ARL_SET_AB (total_wire_in), @@ -543,17 +529,6 @@ commit (enum GNUNET_DB_QueryStatus qs) NULL != wa; wa = wa->next) { - qs = TALER_AUDITORDB_update_auditor_progress ( - TALER_ARL_adb, - wa->label_reserve_in_serial_id, - wa->last_reserve_in_serial_id, - wa->label_kycauth_in_serial_id, - wa->last_kycauth_in_serial_id, - wa->label_wire_off_in, - wa->wire_off_in, - NULL); - if (0 > qs) - goto handle_db_error; qs = TALER_AUDITORDB_insert_auditor_progress ( TALER_ARL_adb, wa->label_reserve_in_serial_id, diff --git a/src/auditor/taler-helper-auditor-wire-debit.c b/src/auditor/taler-helper-auditor-wire-debit.c @@ -58,8 +58,6 @@ struct WireAccount; #include "auditor-database/insert_wire_out_inconsistency.h" #include "auditor-database/preflight.h" #include "auditor-database/start.h" -#include "auditor-database/update_auditor_progress.h" -#include "auditor-database/update_balance.h" #include "exchange-database/get_profit_drain.h" #include "exchange-database/preflight.h" #include "exchange-database/rollback.h" @@ -551,18 +549,6 @@ commit (enum GNUNET_DB_QueryStatus qs) "Transaction logic ended with status %d\n", qs); TALER_EXCHANGEDB_rollback (TALER_ARL_edb); - qs = TALER_AUDITORDB_update_balance ( - TALER_ARL_adb, - TALER_ARL_SET_AB (total_drained), - TALER_ARL_SET_AB (total_wire_out), - TALER_ARL_SET_AB (total_bad_amount_out_plus), - TALER_ARL_SET_AB (total_bad_amount_out_minus), - TALER_ARL_SET_AB (total_closure_amount_lag), - TALER_ARL_SET_AB (wire_debit_duplicate_transfer_subject_total), - TALER_ARL_SET_AB (total_wire_out), - NULL); - if (0 > qs) - goto handle_db_error; qs = TALER_AUDITORDB_insert_balance ( TALER_ARL_adb, TALER_ARL_SET_AB (total_drained), @@ -584,15 +570,6 @@ commit (enum GNUNET_DB_QueryStatus qs) wa->ai->section_name, (unsigned long long) wa->last_wire_out_serial_id, (unsigned long long) wa->wire_off_out); - qs = TALER_AUDITORDB_update_auditor_progress ( - TALER_ARL_adb, - wa->label_wire_out_serial_id, - wa->last_wire_out_serial_id, - wa->label_wire_off_out, - wa->wire_off_out, - NULL); - if (0 > qs) - goto handle_db_error; qs = TALER_AUDITORDB_insert_auditor_progress ( TALER_ARL_adb, wa->label_wire_out_serial_id, @@ -608,12 +585,6 @@ commit (enum GNUNET_DB_QueryStatus qs) (unsigned long long) wa->last_wire_out_serial_id, wa->ai->section_name); } - qs = TALER_AUDITORDB_update_auditor_progress ( - TALER_ARL_adb, - TALER_ARL_SET_PP (wire_reserve_close_id), - NULL); - if (0 > qs) - goto handle_db_error; qs = TALER_AUDITORDB_insert_auditor_progress ( TALER_ARL_adb, TALER_ARL_SET_PP (wire_reserve_close_id), diff --git a/src/auditordb/insert_auditor_progress.c b/src/auditordb/insert_auditor_progress.c @@ -24,11 +24,11 @@ enum GNUNET_DB_QueryStatus -TALER_AUDITORDB_insert_auditor_progress (struct - TALER_AUDITORDB_PostgresContext *pg, - const char *progress_key, - uint64_t progress_offset, - ...) +TALER_AUDITORDB_insert_auditor_progress ( + struct TALER_AUDITORDB_PostgresContext *pg, + const char *progress_key, + uint64_t progress_offset, + ...) { unsigned int cnt = 1; va_list ap; @@ -75,15 +75,26 @@ TALER_AUDITORDB_insert_auditor_progress (struct const char *)); va_end (ap); + /* Note: this is an upsert, not a plain INSERT: the auditor helpers + cannot tell from the query status of + #TALER_AUDITORDB_get_auditor_progress() whether a progress row + already exists (auditor_do_get_auditor_progress() returns one + row per key, present or not), so this function stores the + offset regardless of whether the row already exists. + DISTINCT ON is required because a caller may pass the same key + twice; ON CONFLICT DO UPDATE cannot touch a row twice in one + statement. */ PREPARE (pg, "insert_auditor_progress", "INSERT INTO auditor_progress " "(progress_key" ",progress_offset" - ") SELECT *" + ") SELECT DISTINCT ON (key) key,off" " FROM UNNEST (CAST($1 AS TEXT[])," " CAST($2 AS INT8[]))" - " ON CONFLICT DO NOTHING;"); + " AS t(key,off)" + " ON CONFLICT (progress_key) DO UPDATE" + " SET progress_offset=excluded.progress_offset;"); qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, "insert_auditor_progress", params); diff --git a/src/auditordb/insert_balance.c b/src/auditordb/insert_balance.c @@ -74,16 +74,27 @@ TALER_AUDITORDB_insert_balance (struct TALER_AUDITORDB_PostgresContext *pg, const char *)); va_end (ap); + /* Note: this is an upsert, not a plain INSERT: the auditor helpers + cannot tell from the query status of + #TALER_AUDITORDB_get_balance() whether a balance row already + exists (auditor_do_get_balance() returns one row per key, + present or not), so this function must store the given value + regardless of whether the row already exists. + DISTINCT ON is required because a caller may pass the same key + twice; ON CONFLICT DO UPDATE cannot touch a row twice in one + statement. */ PREPARE (pg, "insert_balance", "INSERT INTO auditor_balances " "(balance_key" ",balance_value.val" ",balance_value.frac" - ") SELECT *" + ") SELECT DISTINCT ON (key) key,val,frac" " FROM UNNEST (CAST($1 AS TEXT[])," " CAST($2 AS taler_amount[]))" - " ON CONFLICT DO NOTHING;"); + " AS t(key,val,frac)" + " ON CONFLICT (balance_key) DO UPDATE" + " SET balance_value=excluded.balance_value;"); qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, "insert_balance", params); diff --git a/src/auditordb/meson.build b/src/auditordb/meson.build @@ -180,9 +180,7 @@ libtalerauditordb = library( 'iterate_purse_expired.c', 'get_reserve_in_inconsistency.c', 'start.c', - 'update_auditor_progress.c', 'update_aml_hold.c', - 'update_balance.c', 'update_denomination_balance.c', 'update_to_suppressed.c', 'update_purse_info.c', @@ -258,6 +256,29 @@ test( is_parallel: false, ) +test_auditordb_regression = executable( + 'test_auditordb_regression', + ['test_auditordb_regression.c'], + install_rpath: rpath_option, + dependencies: [ + libtalerutil_dep, + libtalerpq_dep, + gnunetpq_dep, + gnunetutil_dep, + libtalerauditordb_dep, + pq_dep, + ], + include_directories: [incdir, configuration_inc], + install: false, +) +test( + 'test_auditordb_regression', + test_auditordb_regression, + workdir: meson.current_build_dir(), + suite: ['auditordb'], + is_parallel: false, +) + configure_file( input: 'test-auditor-db-postgres.conf', output: 'test-auditor-db-postgres.conf', diff --git a/src/auditordb/test_auditordb_checkpoints.c b/src/auditordb/test_auditordb_checkpoints.c @@ -29,8 +29,6 @@ #include "auditor-database/insert_balance.h" #include "auditor-database/preflight.h" #include "auditor-database/start.h" -#include "auditor-database/update_auditor_progress.h" -#include "auditor-database/update_balance.h" /** @@ -141,9 +139,10 @@ run (void *cls) 69, NULL) ); - /* Test re-inserting the same value; should yield no results */ + /* Test re-inserting the same value; insert is an upsert, so this + still touches the row */ GNUNET_assert ( - GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == TALER_AUDITORDB_insert_auditor_progress (pg, "Test", 69, @@ -151,7 +150,7 @@ run (void *cls) ); /* Test inserting multiple values, with one already existing */ GNUNET_assert ( - 2 == TALER_AUDITORDB_insert_auditor_progress (pg, + 3 == TALER_AUDITORDB_insert_auditor_progress (pg, "Test", 69, "Test2", @@ -160,9 +159,10 @@ run (void *cls) 245, NULL) ); - /* Test re-re-inserting the same key with a different value; should also yield no results */ + /* Test re-re-inserting the same key with a different value; the + upsert must store the new value */ GNUNET_assert ( - GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == TALER_AUDITORDB_insert_auditor_progress (pg, "Test", 42, @@ -171,15 +171,16 @@ run (void *cls) /* Test updating the same key (again) with a different value; should yield a result */ GNUNET_assert ( GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == - TALER_AUDITORDB_update_auditor_progress (pg, + TALER_AUDITORDB_insert_auditor_progress (pg, "Test", 42, NULL) ); - /* Test updating a key that doesn't exist; should yield 0 */ + /* Test updating a key that does not exist yet; update is an upsert, + so the row must be created */ GNUNET_assert ( - GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == - TALER_AUDITORDB_update_auditor_progress (pg, + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == + TALER_AUDITORDB_insert_auditor_progress (pg, "NonexistentTest", 1, NULL) @@ -261,9 +262,10 @@ run (void *cls) &a1, NULL) ); - /* Test re-inserting the same value; should yield no results */ + /* Test re-inserting the same value; insert is an upsert, so this + still touches the row */ GNUNET_assert ( - GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == TALER_AUDITORDB_insert_balance (pg, "Test", &a1, @@ -271,7 +273,7 @@ run (void *cls) ); /* Test inserting multiple values, with one already existing */ GNUNET_assert ( - 2 == TALER_AUDITORDB_insert_balance (pg, + 3 == TALER_AUDITORDB_insert_balance (pg, "Test", &a1, "Test2", @@ -280,9 +282,10 @@ run (void *cls) &a3, NULL) ); - /* Test re-re-inserting the same key with a different value; should also yield no results */ + /* Test re-re-inserting the same key with a different value; the + upsert must store the new value */ GNUNET_assert ( - GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == TALER_AUDITORDB_insert_balance (pg, "Test", &a2, @@ -291,15 +294,16 @@ run (void *cls) /* Test updating the same key (again) with a different value; should yield a result */ GNUNET_assert ( GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == - TALER_AUDITORDB_update_balance (pg, + TALER_AUDITORDB_insert_balance (pg, "Test", &a2, NULL) ); - /* Test updating a key that doesn't exist; should yield 0 */ + /* Test updating a key that does not exist yet; update is an upsert, + so the row must be created */ GNUNET_assert ( - GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == - TALER_AUDITORDB_update_balance (pg, + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == + TALER_AUDITORDB_insert_balance (pg, "NonexistentTest", &a2, NULL) diff --git a/src/auditordb/test_auditordb_regression.c b/src/auditordb/test_auditordb_regression.c @@ -0,0 +1,267 @@ +/* + This file is part of TALER + Copyright (C) 2026 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file auditordb/test_auditordb_regression.c + * @brief regression tests for individual auditor DB operations + * @author Christian Grothoff + * + * Each test function in this file pins down the behaviour of one + * auditor DB operation that was found to be wrong. Keep them small + * and independent: the file is meant to grow one function per fixed + * defect. + */ +#include <gnunet/gnunet_db_lib.h> +#include "auditordb_lib.h" +#include "auditor-database/create_tables.h" +#include "auditor-database/drop_tables.h" +#include "auditor-database/get_auditor_progress.h" +#include "auditor-database/get_balance.h" +#include "auditor-database/insert_auditor_progress.h" +#include "auditor-database/insert_balance.h" +#include "auditor-database/preflight.h" +#include "auditor-database/start.h" + +/** + * Currency we use, must match CURRENCY in "test-auditor-db-postgres.conf". + */ +#define CURRENCY "EUR" + +/** + * Complain and fail the test if @a cond is true. + */ +#define FAILIF(cond) \ + do { \ + if (! (cond)) break; \ + GNUNET_break (0); \ + return GNUNET_SYSERR; \ + } while (0) + + +/** + * Global result from the testcase. + */ +static int result = -1; + +/** + * Database connection under test. + */ +static struct TALER_AUDITORDB_PostgresContext *pg; + + +/** + * Parse @a str into @a amount, asserting success. + * + * @param str amount to parse, without currency + * @param[out] amount where to write the result + */ +static void +amount (const char *str, + struct TALER_Amount *amount) +{ + char buf[128]; + + GNUNET_snprintf (buf, + sizeof (buf), + "%s:%s", + CURRENCY, + str); + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount (buf, + amount)); +} + + +/** + * A-1: neither TALER_AUDITORDB_get_balance() nor + * TALER_AUDITORDB_get_auditor_progress() can report "key not on file" + * (auditor_do_get_balance() emits one row per key either way), so an + * auditor helper cannot know whether to insert or to update. Both + * operations must therefore store the value they are given no matter + * which one the caller picks. + * + * @return #GNUNET_OK on success + */ +static enum GNUNET_GenericReturnValue +test_checkpoint_upsert (void) +{ + struct TALER_Amount one; + struct TALER_Amount two; + struct TALER_Amount got; + uint64_t off; + + amount ("1", + &one); + amount ("2", + &two); + + /* insert_balance() on a key that does not exist yet must create it. */ + FAILIF (0 > + TALER_AUDITORDB_insert_balance (pg, + "a1-update-only", + &one, + NULL)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + TALER_AUDITORDB_get_balance (pg, + "a1-update-only", + &got, + NULL)); + FAILIF (0 != + TALER_amount_cmp (&got, + &one)); + + /* insert_balance() on a key that already exists must overwrite it. */ + FAILIF (0 > + TALER_AUDITORDB_insert_balance (pg, + "a1-insert-twice", + &one, + NULL)); + FAILIF (0 > + TALER_AUDITORDB_insert_balance (pg, + "a1-insert-twice", + &two, + NULL)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + TALER_AUDITORDB_get_balance (pg, + "a1-insert-twice", + &got, + NULL)); + FAILIF (0 != + TALER_amount_cmp (&got, + &two)); + + /* Same two properties for the progress points. */ + FAILIF (0 > + TALER_AUDITORDB_insert_auditor_progress (pg, + "a1-update-only", + 42, + NULL)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + TALER_AUDITORDB_get_auditor_progress (pg, + "a1-update-only", + &off, + NULL)); + FAILIF (42 != off); + + FAILIF (0 > + TALER_AUDITORDB_insert_auditor_progress (pg, + "a1-insert-twice", + 42, + NULL)); + FAILIF (0 > + TALER_AUDITORDB_insert_auditor_progress (pg, + "a1-insert-twice", + 43, + NULL)); + FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != + TALER_AUDITORDB_get_auditor_progress (pg, + "a1-insert-twice", + &off, + NULL)); + FAILIF (43 != off); + return GNUNET_OK; +} + + +/** + * Main function that will be run by the scheduler. + * + * @param cls closure with the configuration + */ +static void +run (void *cls) +{ + struct GNUNET_CONFIGURATION_Handle *cfg = cls; + + if (NULL == + (pg = TALER_AUDITORDB_connect (cfg))) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to connect to database\n"); + result = 77; + return; + } + GNUNET_assert (GNUNET_OK == + TALER_AUDITORDB_preflight (pg)); + (void) TALER_AUDITORDB_drop_tables (pg, + GNUNET_YES); + if (GNUNET_OK != + TALER_AUDITORDB_create_tables (pg, + false, + 0)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to 'create_tables'\n"); + result = 77; + goto unload; + } + if (GNUNET_SYSERR == + TALER_AUDITORDB_preflight (pg)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed preflight check\n"); + result = 77; + goto drop; + } + if (GNUNET_OK != + TALER_AUDITORDB_start (pg, + "test-auditordb-regression")) + { + GNUNET_break (0); + goto drop; + } + if (GNUNET_OK != + test_checkpoint_upsert ()) + goto rollback; + result = 0; + GNUNET_break (0 <= + TALER_AUDITORDB_commit (pg)); + goto drop; +rollback: + TALER_AUDITORDB_rollback (pg); +drop: + GNUNET_break (GNUNET_OK == + TALER_AUDITORDB_drop_tables (pg, + GNUNET_YES)); +unload: + TALER_AUDITORDB_disconnect (pg); + pg = NULL; +} + + +int +main (int argc, + char *const argv[]) +{ + struct GNUNET_CONFIGURATION_Handle *cfg; + + (void) argc; + result = -1; + GNUNET_log_setup (argv[0], + "WARNING", + NULL); + cfg = GNUNET_CONFIGURATION_create (TALER_AUDITOR_project_data ()); + if (GNUNET_OK != + GNUNET_CONFIGURATION_parse (cfg, + "test-auditor-db-postgres.conf")) + { + GNUNET_break (0); + return 2; + } + GNUNET_SCHEDULER_run (&run, + cfg); + GNUNET_CONFIGURATION_destroy (cfg); + return result; +} diff --git a/src/auditordb/update_auditor_progress.c b/src/auditordb/update_auditor_progress.c @@ -1,95 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file update_auditor_progress.c - * @brief Low-level (statement-level) Postgres database access for the exchange - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "auditor-database/update_auditor_progress.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_AUDITORDB_update_auditor_progress (struct - TALER_AUDITORDB_PostgresContext *pg, - const char *progress_key, - uint64_t progress_offset, - ...) -{ - unsigned int cnt = 1; - va_list ap; - - va_start (ap, - progress_offset); - while (NULL != va_arg (ap, - const char *)) - { - cnt++; - (void) va_arg (ap, - uint64_t); - } - va_end (ap); - { - const char *keys[cnt]; - uint64_t offsets[cnt]; - unsigned int off = 1; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_array_ptrs_string (cnt, - keys, - pg->conn), - GNUNET_PQ_query_param_array_uint64 (cnt, - offsets, - pg->conn), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - keys[0] = progress_key; - offsets[0] = progress_offset; - - va_start (ap, - progress_offset); - while (off < cnt) - { - keys[off] = va_arg (ap, - const char *); - offsets[off] = va_arg (ap, - uint64_t); - off++; - } - GNUNET_assert (NULL == va_arg (ap, - const char *)); - va_end (ap); - - PREPARE (pg, - "update_auditor_progress", - "UPDATE auditor_progress" - " SET progress_offset=data.off" - " FROM (" - " SELECT *" - " FROM UNNEST (CAST($1 AS TEXT[])," - " CAST($2 AS INT8[]))" - " AS t(key,off)" - " ) AS data" - " WHERE auditor_progress.progress_key=data.key;"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_auditor_progress", - params); - GNUNET_PQ_cleanup_query_params_closures (params); - return qs; - } -} diff --git a/src/auditordb/update_balance.c b/src/auditordb/update_balance.c @@ -1,95 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/auditordb/update_balance.c - * @brief Implementation of the update_balance function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "auditor-database/update_balance.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_AUDITORDB_update_balance (struct TALER_AUDITORDB_PostgresContext *pg, - const char *balance_key, - const struct TALER_Amount *balance_amount, - ...) -{ - unsigned int cnt = 1; - va_list ap; - - va_start (ap, - balance_amount); - while (NULL != va_arg (ap, - const char *)) - { - cnt++; - (void) va_arg (ap, - const struct TALER_Amount *); - } - va_end (ap); - { - const char *keys[cnt]; - struct TALER_Amount amounts[cnt]; - unsigned int off = 1; - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_array_ptrs_string (cnt, - keys, - pg->conn), - TALER_PQ_query_param_array_amount (cnt, - amounts, - pg->conn), - GNUNET_PQ_query_param_end - }; - enum GNUNET_DB_QueryStatus qs; - - keys[0] = balance_key; - amounts[0] = *balance_amount; - - va_start (ap, - balance_amount); - while (off < cnt) - { - keys[off] = va_arg (ap, - const char *); - amounts[off] = *va_arg (ap, - const struct TALER_Amount *); - off++; - } - GNUNET_assert (NULL == va_arg (ap, - const char *)); - va_end (ap); - - PREPARE (pg, - "update_balance", - "UPDATE auditor_balances" - " SET balance_value.val=data.val" - " ,balance_value.frac=data.frac" - " FROM (" - " SELECT *" - " FROM UNNEST (CAST($1 AS TEXT[])," - " CAST($2 AS taler_amount[]))" - " AS t(key,val,frac)" - " ) AS data" - " WHERE auditor_balances.balance_key=data.key;"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_balance", - params); - GNUNET_PQ_cleanup_query_params_closures (params); - return qs; - } -} diff --git a/src/include/auditor-database/insert_auditor_progress.h b/src/include/auditor-database/insert_auditor_progress.h @@ -25,8 +25,12 @@ /** - * Insert information about the auditor's progress with an exchange's - * data. + * Store information about the auditor's progress with an exchange's + * data. If a record for @a progress_key already exists, it is + * overwritten (this is an upsert): callers cannot tell from + * #TALER_AUDITORDB_get_auditor_progress() whether a progress point is + * already on file, so insert and update must behave identically. + * Passing the same key twice is allowed; the first value given wins. * * @param pg the database context * @param progress_key name of the progress indicator diff --git a/src/include/auditor-database/insert_balance.h b/src/include/auditor-database/insert_balance.h @@ -26,8 +26,12 @@ #include "auditordb_lib.h" /** - * Insert information about a balance tracked by the auditor. There must not be an - * existing record. + * Store information about a balance tracked by the auditor. If a + * record for @a balance_key already exists, it is overwritten (this is + * an upsert): callers cannot tell from + * #TALER_AUDITORDB_get_balance() whether a balance is already on file, + * so insert and update must behave identically. Passing the same key + * twice is allowed; the first value given wins. * * @param pg the database context * @param balance_key key of the balance to store diff --git a/src/include/auditor-database/update_auditor_progress.h b/src/include/auditor-database/update_auditor_progress.h @@ -1,44 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file update_auditor_progress.h - * @brief implementation of the update_auditor_progress function - * @author Christian Grothoff - */ -#ifndef AUDITOR_DATABASE_UPDATE_AUDITOR_PROGRESS_H -#define AUDITOR_DATABASE_UPDATE_AUDITOR_PROGRESS_H - -#include "auditordb_lib.h" - - -/** - * Update information about the progress of the auditor. There - * must be an existing record for the exchange. - * - * @param pg the database context - * @param progress_key name of the progress indicator - * @param progress_offset offset until which we have made progress - * @param ... NULL terminated list of additional key-value pairs to update - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -TALER_AUDITORDB_update_auditor_progress (struct - TALER_AUDITORDB_PostgresContext *pg, - const char *progress_key, - uint64_t progress_offset, - ...); - -#endif diff --git a/src/include/auditor-database/update_balance.h b/src/include/auditor-database/update_balance.h @@ -1,46 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2024 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/auditor-database/update_balance.h - * @brief implementation of the update_balance function for Postgres - * @author Christian Grothoff - */ -#ifndef AUDITOR_DATABASE_UPDATE_BALANCE_H -#define AUDITOR_DATABASE_UPDATE_BALANCE_H - -#include "taler/taler_util.h" -#include "taler/taler_json_lib.h" -#include "auditordb_lib.h" - - -/** - * Insert information about a balance tracked by the auditor. Destructively updates an - * existing record, which must already exist. - * - * @param pg the database context - * @param balance_key key of the balance to store - * @param balance_amount value to store - * @param ... NULL terminated list of additional key-value pairs to update - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -TALER_AUDITORDB_update_balance (struct TALER_AUDITORDB_PostgresContext *pg, - const char *balance_key, - const struct TALER_Amount *balance_amount, - ...); - - -#endif