iterate_purse_not_closed_inconsistencies.c (5723B)
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 #include "taler/taler_pq_lib.h" 17 #include "pg_helper.h" 18 #include "auditor-database/iterate_purse_not_closed_inconsistencies.h" 19 20 21 /** 22 * Hard upper bound on the number of records returned by a single 23 * call, regardless of the limit requested by the client. 24 */ 25 #define MAX_RECORDS 50000 26 27 28 /** 29 * Closure for #purse_not_closed_inconsistencies_cb(). 30 */ 31 struct PurseNotClosedInconsistenciesContext 32 { 33 34 /** 35 * Function to call for each purse not closed_inconsistencies. 36 */ 37 TALER_AUDITORDB_PurseNotClosedInconsistenciesCallback cb; 38 39 /** 40 * Closure for @e cb 41 */ 42 void *cb_cls; 43 44 /** 45 * Plugin context. 46 */ 47 struct TALER_AUDITORDB_PostgresContext *pg; 48 49 /** 50 * Query status to return. 51 */ 52 enum GNUNET_DB_QueryStatus qs; 53 }; 54 55 56 /** 57 * Helper function for #TALER_AUDITORDB_iterate_purse_not_closed_inconsistencies(). 58 * To be called with the results of a SELECT statement 59 * that has returned @a num_results results. 60 * 61 * @param cls closure of type `struct PurseNotClosedInconsistencies *` 62 * @param result the postgres result 63 * @param num_results the number of results in @a result 64 */ 65 static void 66 purse_not_closed_inconsistencies_cb (void *cls, 67 PGresult *result, 68 unsigned int num_results) 69 { 70 struct PurseNotClosedInconsistenciesContext *dcc = cls; 71 struct TALER_AUDITORDB_PostgresContext *pg = dcc->pg; 72 73 for (unsigned int i = 0; i < num_results; i++) 74 { 75 struct TALER_AUDITORDB_PurseNotClosedInconsistencies dc; 76 struct GNUNET_PQ_ResultSpec rs[] = { 77 GNUNET_PQ_result_spec_uint64 ("row_id", 78 &dc.row_id), 79 GNUNET_PQ_result_spec_auto_from_type ("purse_pub", 80 &dc.purse_pub), 81 TALER_PQ_RESULT_SPEC_AMOUNT ("amount", 82 &dc.amount), 83 GNUNET_PQ_result_spec_absolute_time ("expiration_date", 84 &dc.expiration_date), 85 GNUNET_PQ_result_spec_bool ("suppressed", 86 &dc.suppressed), 87 GNUNET_PQ_result_spec_end 88 }; 89 enum GNUNET_GenericReturnValue rval; 90 91 if (GNUNET_OK != 92 GNUNET_PQ_extract_result (result, 93 rs, 94 i)) 95 { 96 GNUNET_break (0); 97 dcc->qs = GNUNET_DB_STATUS_HARD_ERROR; 98 return; 99 } 100 dcc->qs = i + 1; 101 rval = dcc->cb (dcc->cb_cls, 102 &dc); 103 GNUNET_PQ_cleanup_result (rs); 104 if (GNUNET_OK != rval) 105 break; 106 } 107 } 108 109 110 enum GNUNET_DB_QueryStatus 111 TALER_AUDITORDB_iterate_purse_not_closed_inconsistencies (struct 112 TALER_AUDITORDB_PostgresContext 113 *pg, 114 int64_t limit, 115 uint64_t offset, 116 bool return_suppressed 117 , 118 TALER_AUDITORDB_PurseNotClosedInconsistenciesCallback 119 cb, 120 void *cb_cls) 121 { 122 uint64_t plimit = GNUNET_MIN ((uint64_t) MAX_RECORDS, 123 TALER_AUDITORDB_abs_limit (limit)); 124 struct GNUNET_PQ_QueryParam params[] = { 125 GNUNET_PQ_query_param_uint64 (&offset), 126 GNUNET_PQ_query_param_bool (return_suppressed), 127 GNUNET_PQ_query_param_uint64 (&plimit), 128 GNUNET_PQ_query_param_end 129 }; 130 struct PurseNotClosedInconsistenciesContext dcc = { 131 .cb = cb, 132 .cb_cls = cb_cls, 133 .pg = pg 134 }; 135 enum GNUNET_DB_QueryStatus qs; 136 137 PREPARE (pg, 138 "iterate_purse_not_closed_inconsistencies_desc", 139 "SELECT" 140 " row_id" 141 ",purse_pub" 142 ",amount" 143 ",expiration_date" 144 ",suppressed" 145 " FROM auditor_purse_not_closed_inconsistencies" 146 " WHERE (row_id < $1)" 147 " AND ($2 OR NOT suppressed)" 148 " ORDER BY row_id DESC" 149 " LIMIT $3" 150 ); 151 PREPARE (pg, 152 "iterate_purse_not_closed_inconsistencies_asc", 153 "SELECT" 154 " row_id" 155 ",purse_pub" 156 ",amount" 157 ",expiration_date" 158 ",suppressed" 159 " FROM auditor_purse_not_closed_inconsistencies" 160 " WHERE (row_id > $1)" 161 " AND ($2 OR NOT suppressed)" 162 " ORDER BY row_id ASC" 163 " LIMIT $3" 164 ); 165 qs = GNUNET_PQ_eval_prepared_multi_select ( 166 pg->conn, 167 (limit > 0) 168 ? "iterate_purse_not_closed_inconsistencies_asc" 169 : "iterate_purse_not_closed_inconsistencies_desc", 170 params, 171 &purse_not_closed_inconsistencies_cb, 172 &dcc); 173 if (qs > 0) 174 return dcc.qs; 175 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs); 176 return qs; 177 }