exchange

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

insert_balance.c (3684B)


      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 insert_balance.c
     18  * @brief Implementation of the insert_balance function
     19  * @author Christian Grothoff
     20  */
     21 #include "taler/taler_pq_lib.h"
     22 #include "auditor-database/insert_balance.h"
     23 #include "pg_helper.h"
     24 
     25 
     26 enum GNUNET_DB_QueryStatus
     27 TALER_AUDITORDB_insert_balance (struct TALER_AUDITORDB_PostgresContext *pg,
     28                                 const char *balance_key,
     29                                 const struct TALER_Amount *balance_value,
     30                                 ...)
     31 {
     32   unsigned int cnt = 1;
     33   va_list ap;
     34 
     35   va_start (ap,
     36             balance_value);
     37   while (NULL != va_arg (ap,
     38                          const char *))
     39   {
     40     cnt++;
     41     (void) va_arg (ap,
     42                    const struct TALER_Amount *);
     43   }
     44   va_end (ap);
     45   {
     46     const char *keys[cnt];
     47     struct TALER_Amount amounts[cnt];
     48     unsigned int off = 1;
     49     struct GNUNET_PQ_QueryParam params[] = {
     50       GNUNET_PQ_query_param_array_ptrs_string (cnt,
     51                                                keys,
     52                                                pg->conn),
     53       TALER_PQ_query_param_array_amount (cnt,
     54                                          amounts,
     55                                          pg->conn),
     56       GNUNET_PQ_query_param_end
     57     };
     58     enum GNUNET_DB_QueryStatus qs;
     59 
     60     keys[0] = balance_key;
     61     amounts[0] = *balance_value;
     62 
     63     va_start (ap,
     64               balance_value);
     65     while (off < cnt)
     66     {
     67       keys[off] = va_arg (ap,
     68                           const char *);
     69       amounts[off] = *va_arg (ap,
     70                               const struct TALER_Amount *);
     71       off++;
     72     }
     73     GNUNET_assert (NULL == va_arg (ap,
     74                                    const char *));
     75     va_end (ap);
     76 
     77     /* Note: this is an upsert, not a plain INSERT: the auditor helpers
     78        cannot tell from the query status of
     79        #TALER_AUDITORDB_get_balance() whether a balance row already
     80        exists (auditor_do_get_balance() returns one row per key,
     81        present or not), so this function must store the given value
     82        regardless of whether the row already exists.
     83        DISTINCT ON is required because a caller may pass the same key
     84        twice; ON CONFLICT DO UPDATE cannot touch a row twice in one
     85        statement. */
     86     PREPARE (pg,
     87              "insert_balance",
     88              "INSERT INTO auditor_balances "
     89              "(balance_key"
     90              ",balance_value.val"
     91              ",balance_value.frac"
     92              ") SELECT DISTINCT ON (key) key,val,frac"
     93              " FROM UNNEST (CAST($1 AS TEXT[]),"
     94              "              CAST($2 AS taler_amount[]))"
     95              "   AS t(key,val,frac)"
     96              " ON CONFLICT (balance_key) DO UPDATE"
     97              "   SET balance_value=excluded.balance_value;");
     98     qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
     99                                              "insert_balance",
    100                                              params);
    101     GNUNET_PQ_cleanup_query_params_closures (params);
    102     return qs;
    103   }
    104 }