exchange

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

pg_helper.h (5052B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 2022 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 pg_helper.h
     18  * @brief shared internal definitions for postgres DB plugin
     19  * @author Christian Grothoff
     20  */
     21 #ifndef PG_HELPER_H
     22 #define PG_HELPER_H
     23 
     24 
     25 #include "auditordb_lib.h"
     26 
     27 /**
     28  * Postgres database connection handle.
     29  */
     30 struct TALER_AUDITORDB_PostgresContext
     31 {
     32 
     33   /**
     34    * Postgres connection handle.
     35    */
     36   struct GNUNET_PQ_Context *conn;
     37 
     38   /**
     39    * Name of the ongoing transaction, used to debug cases where
     40    * a transaction is not properly terminated via COMMIT or
     41    * ROLLBACK.
     42    */
     43   const char *transaction_name;
     44 
     45   /**
     46    * Our configuration.
     47    */
     48   const struct GNUNET_CONFIGURATION_Handle *cfg;
     49   /**
     50    * How often have we connected to the DB so far?
     51    */
     52   unsigned long long prep_gen;
     53 
     54   /**
     55    * Which currency should we assume all amounts to be in?
     56    */
     57   char *currency;
     58 };
     59 
     60 
     61 // FIXME: comment
     62 const char *
     63 TALER_AUDITORDB_get_deletable_suppressable_table_name (
     64   enum TALER_AUDITORDB_DeletableSuppressableTables table);
     65 
     66 
     67 /**
     68  * Convert the signed @a limit of a monitoring listing into the row
     69  * limit to pass to SQL.  The sign selects the iteration direction and
     70  * the magnitude the number of rows, but computing `-limit` directly is
     71  * undefined behaviour for `INT64_MIN`, and the resulting value would
     72  * reach Postgres as `LIMIT -9223372036854775808`, which errors out.
     73  * `INT64_MIN` is therefore saturated to `INT64_MAX`.
     74  *
     75  * @param limit signed limit as given by the caller
     76  * @return absolute value of @a limit, without signed overflow
     77  */
     78 static inline uint64_t
     79 TALER_AUDITORDB_abs_limit (int64_t limit)
     80 {
     81   /* Postgres binds INT8 as a *signed* 64-bit integer, so a magnitude
     82      above INT64_MAX would reach LIMIT as a negative number. */
     83   if (INT64_MIN == limit)
     84     return (uint64_t) INT64_MAX;
     85   if (limit < 0)
     86     return (uint64_t) -limit;
     87   return (uint64_t) limit;
     88 }
     89 
     90 
     91 /**
     92  * Prepares SQL statement @a sql under @a name for
     93  * connection @a pg once.
     94  * Returns with #GNUNET_DB_STATUS_HARD_ERROR on failure.
     95  *
     96  * @param pg a `struct PostgresClosure`
     97  * @param name name to prepare the statement under
     98  * @param sql actual SQL text
     99  */
    100 #define PREPARE(pg,name,sql)                            \
    101         do {                                            \
    102           static struct {                               \
    103             unsigned long long cnt;                     \
    104             struct TALER_AUDITORDB_PostgresContext *pg;       \
    105           } preps_[2]; /* 2 ctrs for taler-auditor-sync*/ \
    106           unsigned int off_ = 0;                        \
    107                                                         \
    108           while ( (NULL != preps_[off_].pg) &&          \
    109                   (pg != preps_[off_].pg) &&            \
    110                   (off_ < sizeof(preps_) / sizeof(*preps_)) ) \
    111           off_++;                                       \
    112           GNUNET_assert (off_ <                         \
    113                          sizeof(preps_) / sizeof(*preps_)); \
    114           if (preps_[off_].cnt < pg->prep_gen)          \
    115           {                                             \
    116             struct GNUNET_PQ_PreparedStatement ps[] = { \
    117               GNUNET_PQ_make_prepare (name, sql),       \
    118               GNUNET_PQ_PREPARED_STATEMENT_END          \
    119             };                                          \
    120                                                         \
    121             if (GNUNET_OK !=                            \
    122                 GNUNET_PQ_prepare_statements (pg->conn, \
    123                                               ps))      \
    124             {                                           \
    125               GNUNET_break (0);                         \
    126               return GNUNET_DB_STATUS_HARD_ERROR;       \
    127             }                                           \
    128             preps_[off_].pg = pg;                       \
    129             preps_[off_].cnt = pg->prep_gen;            \
    130           }                                             \
    131         } while (0)
    132 
    133 
    134 /**
    135  * Wrapper macro to add the currency from the plugin's state
    136  * when fetching amounts from the database.
    137  *
    138  * @param field name of the database field to fetch amount from
    139  * @param[out] amountp pointer to amount to set
    140  */
    141 #define TALER_PQ_RESULT_SPEC_AMOUNT(field,   \
    142                                     amountp) \
    143         TALER_PQ_result_spec_amount (        \
    144           field,pg->currency,amountp)
    145 
    146 
    147 #endif