pg_select_purse_deposits_above_serial_id.c (6677B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2022 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 pg_select_purse_deposits_above_serial_id.c 18 * @brief Implementation of the select_purse_deposits_above_serial_id function for Postgres 19 * @author Christian Grothoff 20 */ 21 #include "taler/taler_pq_lib.h" 22 #include "taler/exchange-database/select_purse_deposits_above_serial_id.h" 23 #include "helper.h" 24 25 /** 26 * Closure for #purse_deposit_serial_helper_cb(). 27 */ 28 struct PurseDepositSerialContext 29 { 30 31 /** 32 * Callback to call. 33 */ 34 TALER_EXCHANGEDB_PurseDepositCallback cb; 35 36 /** 37 * Closure for @e cb. 38 */ 39 void *cb_cls; 40 41 /** 42 * Plugin context. 43 */ 44 struct TALER_EXCHANGEDB_PostgresContext *pg; 45 46 /** 47 * Status code, set to #GNUNET_SYSERR on hard errors. 48 */ 49 enum GNUNET_GenericReturnValue status; 50 }; 51 52 53 /** 54 * Helper function to be called with the results of a SELECT statement 55 * that has returned @a num_results results. 56 * 57 * @param cls closure of type `struct DepositSerialContext` 58 * @param result the postgres result 59 * @param num_results the number of results in @a result 60 */ 61 static void 62 purse_deposit_serial_helper_cb (void *cls, 63 PGresult *result, 64 unsigned int num_results) 65 { 66 struct PurseDepositSerialContext *dsc = cls; 67 struct TALER_EXCHANGEDB_PostgresContext *pg = dsc->pg; 68 69 for (unsigned int i = 0; i<num_results; i++) 70 { 71 struct TALER_EXCHANGEDB_PurseDeposit deposit = { 72 .exchange_base_url = NULL 73 }; 74 struct TALER_DenominationPublicKey denom_pub; 75 uint64_t rowid; 76 uint32_t flags32; 77 struct TALER_ReservePublicKeyP reserve_pub; 78 bool not_merged = false; 79 struct TALER_Amount purse_balance; 80 struct TALER_Amount purse_total; 81 struct GNUNET_PQ_ResultSpec rs[] = { 82 TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee", 83 &deposit.amount), 84 TALER_PQ_RESULT_SPEC_AMOUNT ("balance", 85 &purse_balance), 86 TALER_PQ_RESULT_SPEC_AMOUNT ("total", 87 &purse_total), 88 TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit", 89 &deposit.deposit_fee), 90 GNUNET_PQ_result_spec_allow_null ( 91 GNUNET_PQ_result_spec_string ("partner_base_url", 92 &deposit.exchange_base_url), 93 NULL), 94 GNUNET_PQ_result_spec_allow_null ( 95 GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", 96 &reserve_pub), 97 ¬_merged), 98 TALER_PQ_result_spec_denom_pub ("denom_pub", 99 &denom_pub), 100 GNUNET_PQ_result_spec_auto_from_type ("purse_pub", 101 &deposit.purse_pub), 102 GNUNET_PQ_result_spec_auto_from_type ("coin_sig", 103 &deposit.coin_sig), 104 GNUNET_PQ_result_spec_uint32 ("flags", 105 &flags32), 106 GNUNET_PQ_result_spec_auto_from_type ("coin_pub", 107 &deposit.coin_pub), 108 GNUNET_PQ_result_spec_allow_null ( 109 GNUNET_PQ_result_spec_auto_from_type ("age_commitment_hash", 110 &deposit.h_age_commitment), 111 &deposit.no_age_commitment), 112 GNUNET_PQ_result_spec_uint64 ("purse_deposit_serial_id", 113 &rowid), 114 GNUNET_PQ_result_spec_end 115 }; 116 enum GNUNET_GenericReturnValue ret; 117 118 memset (&deposit, 119 0, 120 sizeof (deposit)); 121 if (GNUNET_OK != 122 GNUNET_PQ_extract_result (result, 123 rs, 124 i)) 125 { 126 GNUNET_break (0); 127 dsc->status = GNUNET_SYSERR; 128 return; 129 } 130 ret = dsc->cb (dsc->cb_cls, 131 rowid, 132 &deposit, 133 not_merged ? NULL : &reserve_pub, 134 (enum TALER_WalletAccountMergeFlags) flags32, 135 &purse_balance, 136 &purse_total, 137 &denom_pub); 138 GNUNET_PQ_cleanup_result (rs); 139 if (GNUNET_OK != ret) 140 break; 141 } 142 } 143 144 145 enum GNUNET_DB_QueryStatus 146 TALER_TALER_EXCHANGEDB_select_purse_deposits_above_serial_id ( 147 struct TALER_EXCHANGEDB_PostgresContext *pg, 148 uint64_t serial_id, 149 TALER_EXCHANGEDB_PurseDepositCallback cb, 150 void *cb_cls) 151 { 152 struct GNUNET_PQ_QueryParam params[] = { 153 GNUNET_PQ_query_param_uint64 (&serial_id), 154 GNUNET_PQ_query_param_end 155 }; 156 struct PurseDepositSerialContext dsc = { 157 .cb = cb, 158 .cb_cls = cb_cls, 159 .pg = pg, 160 .status = GNUNET_OK 161 }; 162 enum GNUNET_DB_QueryStatus qs; 163 164 PREPARE (pg, 165 "audit_get_purse_deposits_incr", 166 "SELECT" 167 " pd.amount_with_fee" 168 ",pr.amount_with_fee AS total" 169 ",pr.balance" 170 ",pr.flags" 171 ",pd.purse_pub" 172 ",pd.coin_sig" 173 ",partner_base_url" 174 ",denom.denom_pub" 175 ",denom.fee_deposit" 176 ",pm.reserve_pub" 177 ",kc.coin_pub" 178 ",kc.age_commitment_hash" 179 ",pd.purse_deposit_serial_id" 180 " FROM purse_deposits pd" 181 " LEFT JOIN partners USING (partner_serial_id)" 182 " LEFT JOIN purse_merges pm USING (purse_pub)" 183 " JOIN purse_requests pr USING (purse_pub)" 184 " JOIN known_coins kc USING (coin_pub)" 185 " JOIN denominations denom USING (denominations_serial)" 186 " WHERE (" 187 " (purse_deposit_serial_id>=$1)" 188 " )" 189 " ORDER BY purse_deposit_serial_id ASC;"); 190 qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, 191 "audit_get_purse_deposits_incr", 192 params, 193 &purse_deposit_serial_helper_cb, 194 &dsc); 195 if (GNUNET_OK != dsc.status) 196 return GNUNET_DB_STATUS_HARD_ERROR; 197 return qs; 198 }