insert_balance.c (3684B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file insert_balance.c 18 * @brief Implementation of the insert_balance function 19 * @author Christian Grothoff 20 */ 21 #include "taler/taler_pq_lib.h" 22 #include "auditor-database/insert_balance.h" 23 #include "pg_helper.h" 24 25 26 enum GNUNET_DB_QueryStatus 27 TALER_AUDITORDB_insert_balance (struct TALER_AUDITORDB_PostgresContext *pg, 28 const char *balance_key, 29 const struct TALER_Amount *balance_value, 30 ...) 31 { 32 unsigned int cnt = 1; 33 va_list ap; 34 35 va_start (ap, 36 balance_value); 37 while (NULL != va_arg (ap, 38 const char *)) 39 { 40 cnt++; 41 (void) va_arg (ap, 42 const struct TALER_Amount *); 43 } 44 va_end (ap); 45 { 46 const char *keys[cnt]; 47 struct TALER_Amount amounts[cnt]; 48 unsigned int off = 1; 49 struct GNUNET_PQ_QueryParam params[] = { 50 GNUNET_PQ_query_param_array_ptrs_string (cnt, 51 keys, 52 pg->conn), 53 TALER_PQ_query_param_array_amount (cnt, 54 amounts, 55 pg->conn), 56 GNUNET_PQ_query_param_end 57 }; 58 enum GNUNET_DB_QueryStatus qs; 59 60 keys[0] = balance_key; 61 amounts[0] = *balance_value; 62 63 va_start (ap, 64 balance_value); 65 while (off < cnt) 66 { 67 keys[off] = va_arg (ap, 68 const char *); 69 amounts[off] = *va_arg (ap, 70 const struct TALER_Amount *); 71 off++; 72 } 73 GNUNET_assert (NULL == va_arg (ap, 74 const char *)); 75 va_end (ap); 76 77 /* Note: this is an upsert, not a plain INSERT: the auditor helpers 78 cannot tell from the query status of 79 #TALER_AUDITORDB_get_balance() whether a balance row already 80 exists (auditor_do_get_balance() returns one row per key, 81 present or not), so this function must store the given value 82 regardless of whether the row already exists. 83 DISTINCT ON is required because a caller may pass the same key 84 twice; ON CONFLICT DO UPDATE cannot touch a row twice in one 85 statement. */ 86 PREPARE (pg, 87 "insert_balance", 88 "INSERT INTO auditor_balances " 89 "(balance_key" 90 ",balance_value.val" 91 ",balance_value.frac" 92 ") SELECT DISTINCT ON (key) key,val,frac" 93 " FROM UNNEST (CAST($1 AS TEXT[])," 94 " CAST($2 AS taler_amount[]))" 95 " AS t(key,val,frac)" 96 " ON CONFLICT (balance_key) DO UPDATE" 97 " SET balance_value=excluded.balance_value;"); 98 qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, 99 "insert_balance", 100 params); 101 GNUNET_PQ_cleanup_query_params_closures (params); 102 return qs; 103 } 104 }