/* This file is part of TALER Copyright (C) 2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. TALER is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, see */ /** * @file backenddb/pg_lookup_reward_details.c * @brief Implementation of the lookup_reward_details function for Postgres * @author Iván Ávalos */ #include "platform.h" #include #include #include #include "pg_lookup_reward_details.h" #include "pg_helper.h" /** * Closure for #lookup_pickup_details_cb(). */ struct LookupRewardDetailsContext { /** * Length of the @e sigs array */ unsigned int *pickups_length; /** * Where to store the signatures. */ struct TALER_MERCHANTDB_PickupDetails **pickups; /** * Database handle. */ struct PostgresClosure *pg; /** * Transaction status. */ enum GNUNET_DB_QueryStatus qs; }; /** * Function to be called with the results of a SELECT statement * that has returned @a num_results results about pickups. * * @param[in,out] cls of type `struct LookupRewardDetailsContext *` * @param result the postgres result * @param num_results the number of results in @a result */ static void lookup_pickup_details_cb (void *cls, PGresult *result, unsigned int num_results) { struct LookupRewardDetailsContext *ltdc = cls; *ltdc->pickups_length = num_results; *ltdc->pickups = GNUNET_new_array (num_results, struct TALER_MERCHANTDB_PickupDetails); for (unsigned int i = 0; i < num_results; i++) { struct TALER_MERCHANTDB_PickupDetails *pd = &((*ltdc->pickups)[i]); uint64_t num_planchets = 0; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_auto_from_type ("pickup_id", &pd->pickup_id), TALER_PQ_result_spec_amount_with_currency ("amount", &pd->requested_amount), GNUNET_PQ_result_spec_uint64 ("num_planchets", &num_planchets), GNUNET_PQ_result_spec_end }; if (GNUNET_OK != GNUNET_PQ_extract_result (result, rs, i)) { GNUNET_break (0); ltdc->qs = GNUNET_DB_STATUS_HARD_ERROR; GNUNET_array_grow (*ltdc->pickups, *ltdc->pickups_length, 0); return; } pd->num_planchets = num_planchets; } } enum GNUNET_DB_QueryStatus TMH_PG_lookup_reward_details (void *cls, const char *instance_id, const struct TALER_RewardIdentifierP *reward_id, bool fpu, struct TALER_Amount *total_authorized, struct TALER_Amount *total_picked_up, char **justification, struct GNUNET_TIME_Timestamp *expiration, struct TALER_ReservePublicKeyP *reserve_pub, unsigned int *pickups_length, struct TALER_MERCHANTDB_PickupDetails **pickups) { struct PostgresClosure *pg = cls; uint64_t reward_serial; enum GNUNET_DB_QueryStatus qs; { struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_string (instance_id), GNUNET_PQ_query_param_auto_from_type (reward_id), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_uint64 ("reward_serial", &reward_serial), TALER_PQ_result_spec_amount_with_currency ("amount", total_authorized), TALER_PQ_result_spec_amount_with_currency ("picked_up", total_picked_up), GNUNET_PQ_result_spec_string ("justification", justification), GNUNET_PQ_result_spec_timestamp ("expiration", expiration), GNUNET_PQ_result_spec_auto_from_type ("reserve_pub", reserve_pub), GNUNET_PQ_result_spec_end }; check_connection (pg); PREPARE (pg, "lookup_reward_details", "SELECT" " reward_serial" ",amount" ",picked_up" ",justification" ",merchant_rewards.expiration" ",reserve_pub" " FROM merchant_rewards" " JOIN merchant_reward_reserves USING (reserve_serial)" " WHERE reward_id = $2" " AND merchant_serial =" " (SELECT merchant_serial" " FROM merchant_instances" " WHERE merchant_id=$1)"); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "lookup_reward_details", params, rs); if (qs <= 0) return qs; if (! fpu) { *pickups_length = 0; *pickups = NULL; return qs; } } { struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&reward_serial), GNUNET_PQ_query_param_end }; struct LookupRewardDetailsContext ltdc = { .pickups_length = pickups_length, .pickups = pickups, .pg = pg, .qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT }; PREPARE (pg, "lookup_pickup_details", "SELECT" " pickup_id" ",amount" ",COUNT(blind_sig) AS num_planchets" " FROM merchant_reward_pickups" " JOIN merchant_reward_pickup_signatures USING (pickup_serial)" " WHERE reward_serial = $1" " GROUP BY pickup_serial"); qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn, "lookup_pickup_details", params, &lookup_pickup_details_cb, <dc); if (qs < 0) return qs; return ltdc.qs; } }