insert_receipts_submitted.c (4863B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2023 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 src/donaudb/insert_receipts_submitted.c 18 * @brief Implementation of the insert_receipts_submitted function for Postgres 19 * @author Johannes Casaburi 20 */ 21 #include <donau_config.h> 22 #include <taler/taler_error_codes.h> 23 #include <taler/taler_dbevents.h> 24 #include <taler/taler_pq_lib.h> 25 #include "insert_receipts_submitted.h" 26 #include "helper.h" 27 #include "donau_service.h" 28 #include "donau_pq_lib.h" 29 30 31 enum GNUNET_DB_QueryStatus 32 DONAUDB_insert_receipts_submitted ( 33 struct DONAUDB_PostgresContext *ctx, 34 struct DONAU_HashDonorTaxId *h_donor_tax_id, 35 size_t num_dr, 36 const struct DONAU_DonationReceipt donation_receipts[static num_dr], 37 uint64_t donation_year, 38 size_t *conflict_index, 39 size_t *unknown_du_index) 40 { 41 struct GNUNET_HashCode h_donation_unit_pubs[GNUNET_NZL (num_dr)]; 42 struct DONAU_UniqueDonorIdentifierNonce nonces[GNUNET_NZL (num_dr)]; 43 struct DONAU_DonationUnitSignature donation_unit_sigs[GNUNET_NZL (num_dr)]; 44 struct GNUNET_PQ_QueryParam params[] = { 45 GNUNET_PQ_query_param_auto_from_type (h_donor_tax_id), 46 GNUNET_PQ_query_param_array_auto_from_type (num_dr, 47 h_donation_unit_pubs, 48 ctx->conn), 49 GNUNET_PQ_query_param_array_auto_from_type (num_dr, 50 nonces, 51 ctx->conn), 52 DONAU_PQ_query_param_array_donation_unit_sig (num_dr, 53 donation_unit_sigs, 54 ctx->conn), 55 GNUNET_PQ_query_param_uint64 (&donation_year), 56 GNUNET_PQ_query_param_end 57 }; 58 bool *conflicted = NULL; 59 size_t num_conflicted = num_dr; 60 uint32_t unknown_du; 61 struct GNUNET_PQ_ResultSpec rs[] = { 62 GNUNET_PQ_result_spec_array_bool (ctx->conn, 63 "conflicted", 64 &num_conflicted, 65 &conflicted), 66 GNUNET_PQ_result_spec_uint32 ("unknown_du", 67 &unknown_du), 68 GNUNET_PQ_result_spec_end 69 }; 70 enum GNUNET_DB_QueryStatus qs; 71 72 *conflict_index = num_dr; 73 *unknown_du_index = num_dr; 74 for (unsigned int i = 0; i < num_dr; i++) 75 { 76 const struct DONAU_DonationReceipt *dr = &donation_receipts[i]; 77 78 h_donation_unit_pubs[i] = dr->h_donation_unit_pub.hash; 79 nonces[i] = dr->nonce; 80 donation_unit_sigs[i] = dr->donation_unit_sig; 81 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 82 "Do insert submitted receipt\n"); 83 } 84 85 PREPARE (ctx, 86 "insert_receipts_submitted", 87 "SELECT " 88 " out_conflict AS conflicted" 89 ",out_unknown_du AS unknown_du" 90 " FROM do_insert_submitted_receipts" 91 "($1,$2,$3,$4,$5);"); 92 qs = GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, 93 "insert_receipts_submitted", 94 params, 95 rs); 96 GNUNET_PQ_cleanup_query_params_closures (params); 97 if (qs > 0) 98 { 99 if (0 != unknown_du) 100 { 101 /* Nothing was written; the batch names a donation unit we do not 102 know. Report it instead of letting the foreign key violation 103 escape as a hard error. */ 104 *unknown_du_index = (size_t) (unknown_du - 1); 105 GNUNET_free (conflicted); 106 GNUNET_PQ_cleanup_result (rs); 107 return qs; 108 } 109 for (size_t i = 0; i < num_conflicted; i++) 110 { 111 /* NOTE: `conflicted[i]' is TRUE only for the *non*-idempotent case, 112 i.e. the row was not inserted AND the stored row is not this 113 donor's. That receipt was dropped and the caller must be told. */ 114 if (conflicted[i]) 115 { 116 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 117 "Submitted donation receipt at index %llu conflicts with an existing entry!\n", 118 (unsigned long long) i); 119 if (num_dr == *conflict_index) 120 *conflict_index = i; 121 } 122 } 123 } 124 GNUNET_free (conflicted); 125 GNUNET_PQ_cleanup_result (rs); 126 return qs; 127 }