exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

pg_get_balance.c (5067B)


      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 /**
     17  * @file auditordb/pg_get_balance.c
     18  * @brief Implementation of the get_balance function for Postgres
     19  * @author Christian Grothoff
     20  */
     21 #include "taler/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_get_balance.h"
     26 #include "pg_helper.h"
     27 
     28 
     29 /**
     30  * Closure for #balance_cb().
     31  */
     32 struct BalanceContext
     33 {
     34 
     35   /**
     36    * Where to store results.
     37    */
     38   struct TALER_Amount **dst;
     39 
     40   /**
     41    * Offset in @e dst.
     42    */
     43   unsigned int off;
     44 
     45   /**
     46    * Length of array at @e dst.
     47    */
     48   unsigned int len;
     49 
     50   /**
     51    * Plugin context.
     52    */
     53   struct PostgresClosure *pg;
     54 
     55   /**
     56    * Set to true on failure.
     57    */
     58   bool failure;
     59 
     60 };
     61 
     62 
     63 /**
     64  * Helper function for #TAH_PG_get_balance().
     65  * To be called with the results of a SELECT statement
     66  * that has returned @a num_results results.
     67  *
     68  * @param cls closure of type `struct BalanceContext *`
     69  * @param result the postgres result
     70  * @param num_results the number of results in @a result
     71  */
     72 static void
     73 balance_cb (void *cls,
     74             PGresult *result,
     75             unsigned int num_results)
     76 {
     77   struct BalanceContext *ctx = cls;
     78   struct PostgresClosure *pg = ctx->pg;
     79 
     80   GNUNET_assert (num_results <= ctx->len);
     81   for (unsigned int i = 0; i < num_results; i++)
     82   {
     83     bool is_missing;
     84     struct GNUNET_PQ_ResultSpec rs[] = {
     85       GNUNET_PQ_result_spec_allow_null (
     86         TALER_PQ_result_spec_amount ("balance",
     87                                      pg->currency,
     88                                      ctx->dst[i]),
     89         &is_missing),
     90       GNUNET_PQ_result_spec_end
     91     };
     92 
     93     if (GNUNET_OK !=
     94         GNUNET_PQ_extract_result (result,
     95                                   rs,
     96                                   i))
     97     {
     98       GNUNET_break (0);
     99       ctx->failure = true;
    100       return;
    101     }
    102     if (is_missing)
    103     {
    104       GNUNET_assert (GNUNET_OK ==
    105                      TALER_amount_set_zero (pg->currency,
    106                                             ctx->dst[i]));
    107     }
    108     ctx->off++;
    109   }
    110 }
    111 
    112 
    113 enum GNUNET_DB_QueryStatus
    114 TAH_PG_get_balance (void *cls,
    115                     const char *balance_key,
    116                     struct TALER_Amount *balance_value,
    117                     ...)
    118 {
    119   struct PostgresClosure *pg = cls;
    120   unsigned int cnt = 1;
    121   va_list ap;
    122 
    123   GNUNET_assert (GNUNET_OK ==
    124                  TALER_amount_set_zero (pg->currency,
    125                                         balance_value));
    126   va_start (ap,
    127             balance_value);
    128   while (NULL != va_arg (ap,
    129                          const char *))
    130   {
    131     struct TALER_Amount *dst;
    132 
    133     cnt++;
    134     dst = va_arg (ap,
    135                   struct TALER_Amount *);
    136     GNUNET_assert (GNUNET_OK ==
    137                    TALER_amount_set_zero (pg->currency,
    138                                           dst));
    139   }
    140   va_end (ap);
    141   {
    142     const char *keys[cnt];
    143     struct TALER_Amount *dsts[cnt];
    144     unsigned int off = 1;
    145     struct GNUNET_PQ_QueryParam params[] = {
    146       GNUNET_PQ_query_param_array_ptrs_string (cnt,
    147                                                keys,
    148                                                pg->conn),
    149       GNUNET_PQ_query_param_end
    150     };
    151     struct BalanceContext ctx = {
    152       .dst = dsts,
    153       .len = cnt,
    154       .pg = pg
    155     };
    156     enum GNUNET_DB_QueryStatus qs;
    157 
    158     keys[0] = balance_key;
    159     dsts[0] = balance_value;
    160     va_start (ap,
    161               balance_value);
    162     while (off < cnt)
    163     {
    164       keys[off] = va_arg (ap,
    165                           const char *);
    166       dsts[off] = va_arg (ap,
    167                           struct TALER_Amount *);
    168       off++;
    169     }
    170     GNUNET_assert (NULL == va_arg (ap,
    171                                    const char *));
    172     va_end (ap);
    173 
    174     PREPARE (pg,
    175              "get_balance",
    176              "SELECT "
    177              " auditor_do_get_balance AS balance"
    178              " FROM auditor_do_get_balance "
    179              "($1);");
    180     qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
    181                                                "get_balance",
    182                                                params,
    183                                                &balance_cb,
    184                                                &ctx);
    185     GNUNET_PQ_cleanup_query_params_closures (params);
    186     if (ctx.failure)
    187       return GNUNET_DB_STATUS_HARD_ERROR;
    188     if (qs < 0)
    189       return qs;
    190     GNUNET_assert (qs == ctx.off);
    191     return qs;
    192   }
    193 }