LCOV - code coverage report
Current view: top level - backenddb - helper.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 83.3 % 6 5
Test Date: 2026-09-04 23:42:01 Functions: 100.0 % 1 1

            Line data    Source code
       1              : /*
       2              :    This file is part of TALER
       3              :    Copyright (C) 2023 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 src/backenddb/helper.h
      18              :  * @brief shared internal definitions for postgres logic
      19              :  * @author Christian Grothoff
      20              :  */
      21              : #ifndef HELPER_H
      22              : #define HELPER_H
      23              : 
      24              : #include <gnunet/gnunet_util_lib.h>
      25              : #include <gnunet/gnunet_db_lib.h>
      26              : #include <gnunet/gnunet_time_lib.h>
      27              : #include <taler/taler_util.h>
      28              : 
      29              : /**
      30              :  * Type of the "cls" argument given to each of the functions in
      31              :  * our API.
      32              :  */
      33              : struct TALER_MERCHANTDB_PostgresContext
      34              : {
      35              : 
      36              :   /**
      37              :    * Postgres connection handle.
      38              :    */
      39              :   struct GNUNET_PQ_Context *conn;
      40              : 
      41              :   /**
      42              :    * Underlying configuration.
      43              :    */
      44              :   const struct GNUNET_CONFIGURATION_Handle *cfg;
      45              : 
      46              :   /**
      47              :    * Name of the currently active transaction, NULL if none is active.
      48              :    */
      49              :   const char *transaction_name;
      50              : 
      51              :   /**
      52              :    * Instance id ("merchant_id") that the search_path is currently
      53              :    * pointing at, or NULL if no per-instance schema is selected.
      54              :    * Owned by this struct; set by TALER_MERCHANTDB_set_instance().
      55              :    */
      56              :   char *current_merchant_id;
      57              : 
      58              :   /**
      59              :    * merchant_serial corresponding to @e current_merchant_id, or 0
      60              :    * if no per-instance schema is selected.  Used as the suffix in
      61              :    * per-instance prepared-statement names.
      62              :    */
      63              :   uint64_t current_merchant_serial;
      64              : 
      65              :   /**
      66              :    * Public key of the currently selected instance.  Populated by
      67              :    * TALER_MERCHANTDB_set_instance() together with @e current_merchant_id
      68              :    * and @e current_merchant_serial.  Used by call sites that emit
      69              :    * cross-process events (e.g. order-pay notifications) which carry the
      70              :    * instance public key in their payload.
      71              :    */
      72              :   struct TALER_MerchantPublicKeyP current_merchant_pub;
      73              : 
      74              : };
      75              : 
      76              : 
      77              : /**
      78              :  * How many times have we connected to the DB.
      79              :  */
      80              : extern uint64_t TMH_PG_prep_gen_;
      81              : 
      82              : 
      83              : /**
      84              :  * Convert the signed @a limit of a paginated listing into the row
      85              :  * limit to pass to SQL.  The sign selects the iteration direction and
      86              :  * the magnitude the number of rows, but computing `-limit` directly is
      87              :  * undefined behaviour for `INT64_MIN`, and the resulting value would
      88              :  * reach Postgres as `LIMIT -9223372036854775808`, which errors out.
      89              :  * `INT64_MIN` is therefore saturated to `INT64_MAX`.
      90              :  *
      91              :  * @param limit signed limit as given by the caller
      92              :  * @return absolute value of @a limit, without signed overflow
      93              :  */
      94              : static inline uint64_t
      95           60 : TALER_MERCHANTDB_abs_limit (int64_t limit)
      96              : {
      97              :   /* Postgres binds INT8 as a *signed* 64-bit integer, so a magnitude
      98              :      above INT64_MAX would reach LIMIT as a negative number. */
      99           60 :   if (INT64_MIN == limit)
     100            0 :     return (uint64_t) INT64_MAX;
     101           60 :   if (limit < 0)
     102           20 :     return (uint64_t) -limit;
     103           40 :   return (uint64_t) limit;
     104              : }
     105              : 
     106              : 
     107              : /**
     108              :  * Prepares SQL statement @a sql under @a name for
     109              :  * connection @a pg once.
     110              :  * Returns with #GNUNET_DB_STATUS_HARD_ERROR on failure.
     111              :  *
     112              :  * @param pg a `struct TALER_MERCHANTDB_PostgresContext`
     113              :  * @param name name to prepare the statement under
     114              :  * @param sql actual SQL text
     115              :  */
     116              : #define PREPARE(pg,name,sql)                      \
     117              :         do {                                            \
     118              :           static unsigned long long gen;                \
     119              :                                                         \
     120              :           if (gen < TMH_PG_prep_gen_)                   \
     121              :           {                                             \
     122              :             struct GNUNET_PQ_PreparedStatement ps[] = { \
     123              :               GNUNET_PQ_make_prepare (name, sql),       \
     124              :               GNUNET_PQ_PREPARED_STATEMENT_END          \
     125              :             };                                          \
     126              :                                                         \
     127              :             if (GNUNET_OK !=                            \
     128              :                 GNUNET_PQ_prepare_statements (pg->conn, \
     129              :                                               ps))      \
     130              :             {                                           \
     131              :               GNUNET_break (0);                         \
     132              :               return GNUNET_DB_STATUS_HARD_ERROR;       \
     133              :             }                                           \
     134              :             gen = TMH_PG_prep_gen_;                     \
     135              :           }                                             \
     136              :         } while (0)
     137              : 
     138              : 
     139              : /**
     140              :  * Prepares SQL statement @a sql under no name ("") for
     141              :  * connection @a pg.  Useful for prepared statements that
     142              :  * should not be cached.
     143              :  * Returns with #GNUNET_DB_STATUS_HARD_ERROR on failure.
     144              :  *
     145              :  * @param pg a `struct TALER_MERCHANTDB_PostgresContext`
     146              :  * @param sql actual SQL text
     147              :  */
     148              : #define TMH_PQ_prepare_anon(pg,sql)              \
     149              :         do {                                     \
     150              :           if (GNUNET_OK !=                       \
     151              :               GNUNET_PQ_prepare_anon (pg->conn,  \
     152              :                                       sql)) {    \
     153              :             GNUNET_break (0);                    \
     154              :             return GNUNET_DB_STATUS_HARD_ERROR;  \
     155              :           } } while (0)
     156              : 
     157              : 
     158              : #endif
        

Generated by: LCOV version 2.0-1