Line data Source code
1 : /* 2 : This file is part of TALER 3 : Copyright (C) 2025 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 backenddb/pg_lookup_statistics_counter_by_interval.c 18 : * @brief Implementation of the lookup_statistics_counter_by_interval function for Postgres 19 : * @author Martin Schanzenbach 20 : */ 21 : #include "platform.h" 22 : #include <taler/taler_error_codes.h> 23 : #include <taler/taler_dbevents.h> 24 : #include <taler/taler_pq_lib.h> 25 : #include "pg_lookup_statistics_counter_by_interval.h" 26 : #include "pg_helper.h" 27 : #include "taler_merchantdb_plugin.h" 28 : 29 : 30 : /** 31 : * Context used for TMH_PG_lookup_statistics_counter(). 32 : */ 33 : struct LookupCounterStatisticsContext 34 : { 35 : /** 36 : * Function to call with the results. 37 : */ 38 : TALER_MERCHANTDB_CounterByIntervalStatisticsCallback cb; 39 : 40 : /** 41 : * Closure for @a cb. 42 : */ 43 : void *cb_cls; 44 : 45 : /** 46 : * Did database result extraction fail? 47 : */ 48 : bool extract_failed; 49 : }; 50 : 51 : 52 : /** 53 : * Function to be called with the results of a SELECT statement 54 : * that has returned @a num_results results about token families. 55 : * 56 : * @param[in,out] cls of type `struct LookupTokenFamiliesContext *` 57 : * @param result the postgres result 58 : * @param num_results the number of results in @a result 59 : */ 60 : static void 61 4 : lookup_statistics_counter_by_interval_cb (void *cls, 62 : PGresult *result, 63 : unsigned int num_results) 64 : { 65 4 : struct LookupCounterStatisticsContext *tflc = cls; 66 : 67 4 : for (unsigned int i = 0; i < num_results; i++) 68 : { 69 : char *description; 70 : uint64_t cumulative_number; 71 : uint64_t interval_start_epoch; 72 0 : struct GNUNET_PQ_ResultSpec rs[] = { 73 0 : GNUNET_PQ_result_spec_string ("description", 74 : &description), 75 0 : GNUNET_PQ_result_spec_uint64 ("start_time", 76 : &interval_start_epoch), 77 0 : GNUNET_PQ_result_spec_uint64 ("cumulative_number", 78 : &cumulative_number), 79 : GNUNET_PQ_result_spec_end 80 : }; 81 : struct GNUNET_TIME_Timestamp interval_start; 82 : 83 0 : if (GNUNET_OK != 84 0 : GNUNET_PQ_extract_result (result, 85 : rs, 86 : i)) 87 : { 88 0 : GNUNET_break (0); 89 0 : tflc->extract_failed = true; 90 0 : return; 91 : } 92 : 93 0 : interval_start = GNUNET_TIME_timestamp_from_s (interval_start_epoch); 94 0 : tflc->cb (tflc->cb_cls, 95 : description, 96 : interval_start, 97 : cumulative_number); 98 0 : GNUNET_PQ_cleanup_result (rs); 99 : } 100 : } 101 : 102 : 103 : enum GNUNET_DB_QueryStatus 104 4 : TMH_PG_lookup_statistics_counter_by_interval ( 105 : void *cls, 106 : const char *instance_id, 107 : const char *slug, 108 : TALER_MERCHANTDB_CounterByIntervalStatisticsCallback cb, 109 : void *cb_cls) 110 : { 111 4 : struct PostgresClosure *pg = cls; 112 4 : struct LookupCounterStatisticsContext context = { 113 : .cb = cb, 114 : .cb_cls = cb_cls, 115 : /* Can be overwritten by the lookup_token_families_cb */ 116 : .extract_failed = false, 117 : }; 118 4 : struct GNUNET_PQ_QueryParam params[] = { 119 4 : GNUNET_PQ_query_param_string (instance_id), 120 4 : GNUNET_PQ_query_param_string (slug), 121 : GNUNET_PQ_query_param_end 122 : }; 123 : enum GNUNET_DB_QueryStatus qs; 124 : 125 4 : check_connection (pg); 126 4 : PREPARE (pg, 127 : "lookup_statistics_counter_by_interval", 128 : "SELECT *" 129 : " FROM merchant_statistic_interval_number_get($1,$2)" 130 : " JOIN merchant_statistic_bucket_meta" 131 : " ON slug=$2"); 132 4 : qs = GNUNET_PQ_eval_prepared_multi_select ( 133 : pg->conn, 134 : "lookup_statistics_counter_by_interval", 135 : params, 136 : &lookup_statistics_counter_by_interval_cb, 137 : &context); 138 : /* If there was an error inside the cb, return a hard error. */ 139 4 : if (context.extract_failed) 140 : { 141 0 : GNUNET_break (0); 142 0 : return GNUNET_DB_STATUS_HARD_ERROR; 143 : } 144 4 : return qs; 145 : }