exchange

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

pg_lookup_records_by_table.c (115722B)


      1 /*
      2    This file is part of GNUnet
      3    Copyright (C) 2020-2025 Taler Systems SA
      4 
      5    GNUnet is free software: you can redistribute it and/or modify it
      6    under the terms of the GNU Affero General Public License as published
      7    by the Free Software Foundation, either version 3 of the License,
      8    or (at your option) any later version.
      9 
     10    GNUnet is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13    Affero General Public License for more details.
     14 
     15    You should have received a copy of the GNU Affero General Public License
     16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18      SPDX-License-Identifier: AGPL3.0-or-later
     19  */
     20 /**
     21  * @file exchangedb/pg_lookup_records_by_table.c
     22  * @brief implementation of lookup_records_by_table
     23  * @author Christian Grothoff
     24  * @author Özgür Kesim
     25  */
     26 #include "taler/taler_error_codes.h"
     27 #include "taler/taler_dbevents.h"
     28 #include "taler/taler_pq_lib.h"
     29 #include "taler/exchange-database/lookup_records_by_table.h"
     30 #include "helper.h"
     31 #include <gnunet/gnunet_pq_lib.h>
     32 
     33 
     34 /**
     35  * Closure for callbacks used by #postgres_lookup_records_by_table.
     36  */
     37 struct LookupRecordsByTableContext
     38 {
     39   /**
     40    * Plugin context.
     41    */
     42   struct TALER_EXCHANGEDB_PostgresContext *pg;
     43 
     44   /**
     45    * Function to call with the results.
     46    */
     47   TALER_EXCHANGEDB_ReplicationCallback cb;
     48 
     49   /**
     50    * Closure for @a cb.
     51    */
     52   void *cb_cls;
     53 
     54   /**
     55    * Set to true on errors.
     56    */
     57   bool error;
     58 };
     59 
     60 
     61 /**
     62  * Function called with denominations table entries.
     63  *
     64  * @param cls closure
     65  * @param result the postgres result
     66  * @param num_results the number of results in @a result
     67  */
     68 static void
     69 lrbt_cb_table_denominations (void *cls,
     70                              PGresult *result,
     71                              unsigned int num_results)
     72 {
     73   struct LookupRecordsByTableContext *ctx = cls;
     74   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
     75   struct TALER_EXCHANGEDB_TableData td = {
     76     .table = TALER_EXCHANGEDB_RT_DENOMINATIONS
     77   };
     78 
     79   for (unsigned int i = 0; i<num_results; i++)
     80   {
     81     struct GNUNET_PQ_ResultSpec rs[] = {
     82       GNUNET_PQ_result_spec_uint64 (
     83         "serial",
     84         &td.serial),
     85       GNUNET_PQ_result_spec_uint32 (
     86         "denom_type",
     87         &td.details.denominations.denom_type),
     88       GNUNET_PQ_result_spec_uint32 (
     89         "age_mask",
     90         &td.details.denominations.age_mask),
     91       TALER_PQ_result_spec_denom_pub (
     92         "denom_pub",
     93         &td.details.denominations.denom_pub),
     94       GNUNET_PQ_result_spec_auto_from_type (
     95         "master_sig",
     96         &td.details.denominations.master_sig),
     97       GNUNET_PQ_result_spec_timestamp (
     98         "valid_from",
     99         &td.details.denominations.valid_from),
    100       GNUNET_PQ_result_spec_timestamp (
    101         "expire_withdraw",
    102         &td.details.denominations.
    103         expire_withdraw),
    104       GNUNET_PQ_result_spec_timestamp (
    105         "expire_deposit",
    106         &td.details.denominations.
    107         expire_deposit),
    108       GNUNET_PQ_result_spec_timestamp (
    109         "expire_legal",
    110         &td.details.denominations.expire_legal),
    111       TALER_PQ_RESULT_SPEC_AMOUNT (
    112         "coin",
    113         &td.details.denominations.coin),
    114       TALER_PQ_RESULT_SPEC_AMOUNT (
    115         "fee_withdraw",
    116         &td.details.denominations.fees.withdraw),
    117       TALER_PQ_RESULT_SPEC_AMOUNT (
    118         "fee_deposit",
    119         &td.details.denominations.fees.deposit),
    120       TALER_PQ_RESULT_SPEC_AMOUNT (
    121         "fee_refresh",
    122         &td.details.denominations.fees.refresh),
    123       TALER_PQ_RESULT_SPEC_AMOUNT (
    124         "fee_refund",
    125         &td.details.denominations.fees.refund),
    126       GNUNET_PQ_result_spec_end
    127     };
    128 
    129     if (GNUNET_OK !=
    130         GNUNET_PQ_extract_result (result,
    131                                   rs,
    132                                   i))
    133     {
    134       GNUNET_break (0);
    135       ctx->error = true;
    136       return;
    137     }
    138     ctx->cb (ctx->cb_cls,
    139              &td);
    140     GNUNET_PQ_cleanup_result (rs);
    141   }
    142 }
    143 
    144 
    145 /**
    146  * Function called with denomination_revocations table entries.
    147  *
    148  * @param cls closure
    149  * @param result the postgres result
    150  * @param num_results the number of results in @a result
    151  */
    152 static void
    153 lrbt_cb_table_denomination_revocations (void *cls,
    154                                         PGresult *result,
    155                                         unsigned int num_results)
    156 {
    157   struct LookupRecordsByTableContext *ctx = cls;
    158   struct TALER_EXCHANGEDB_TableData td = {
    159     .table = TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS
    160   };
    161 
    162   for (unsigned int i = 0; i<num_results; i++)
    163   {
    164     struct GNUNET_PQ_ResultSpec rs[] = {
    165       GNUNET_PQ_result_spec_uint64 ("serial",
    166                                     &td.serial),
    167       GNUNET_PQ_result_spec_uint64 (
    168         "denominations_serial",
    169         &td.details.denomination_revocations.denominations_serial),
    170       GNUNET_PQ_result_spec_auto_from_type (
    171         "master_sig",
    172         &td.details.denomination_revocations.master_sig),
    173       GNUNET_PQ_result_spec_end
    174     };
    175 
    176     if (GNUNET_OK !=
    177         GNUNET_PQ_extract_result (result,
    178                                   rs,
    179                                   i))
    180     {
    181       GNUNET_break (0);
    182       ctx->error = true;
    183       return;
    184     }
    185     ctx->cb (ctx->cb_cls,
    186              &td);
    187     GNUNET_PQ_cleanup_result (rs);
    188   }
    189 }
    190 
    191 
    192 /**
    193  * Function called with wire_targets table entries.
    194  *
    195  * @param cls closure
    196  * @param result the postgres result
    197  * @param num_results the number of results in @a result
    198  */
    199 static void
    200 lrbt_cb_table_wire_targets (void *cls,
    201                             PGresult *result,
    202                             unsigned int num_results)
    203 {
    204   struct LookupRecordsByTableContext *ctx = cls;
    205   struct TALER_EXCHANGEDB_TableData td = {
    206     .table = TALER_EXCHANGEDB_RT_WIRE_TARGETS
    207   };
    208 
    209   for (unsigned int i = 0; i<num_results; i++)
    210   {
    211     struct GNUNET_PQ_ResultSpec rs[] = {
    212       GNUNET_PQ_result_spec_uint64 (
    213         "serial",
    214         &td.serial),
    215       GNUNET_PQ_result_spec_string (
    216         "payto_uri",
    217         &td.details.wire_targets.full_payto_uri.full_payto),
    218       GNUNET_PQ_result_spec_end
    219     };
    220 
    221     if (GNUNET_OK !=
    222         GNUNET_PQ_extract_result (result,
    223                                   rs,
    224                                   i))
    225     {
    226       GNUNET_break (0);
    227       ctx->error = true;
    228       return;
    229     }
    230     ctx->cb (ctx->cb_cls,
    231              &td);
    232     GNUNET_PQ_cleanup_result (rs);
    233   }
    234 }
    235 
    236 
    237 /**
    238  * Function called with wire_targets table entries.
    239  *
    240  * @param cls closure
    241  * @param result the postgres result
    242  * @param num_results the number of results in @a result
    243  */
    244 static void
    245 lrbt_cb_table_kyc_targets (void *cls,
    246                            PGresult *result,
    247                            unsigned int num_results)
    248 {
    249   struct LookupRecordsByTableContext *ctx = cls;
    250   struct TALER_EXCHANGEDB_TableData td = {
    251     .table = TALER_EXCHANGEDB_RT_KYC_TARGETS
    252   };
    253 
    254   for (unsigned int i = 0; i<num_results; i++)
    255   {
    256     struct GNUNET_PQ_ResultSpec rs[] = {
    257       GNUNET_PQ_result_spec_uint64 (
    258         "serial",
    259         &td.serial),
    260       GNUNET_PQ_result_spec_auto_from_type (
    261         "h_normalized_payto",
    262         &td.details.kyc_targets.h_normalized_payto),
    263       GNUNET_PQ_result_spec_auto_from_type (
    264         "access_token",
    265         &td.details.kyc_targets.access_token),
    266       GNUNET_PQ_result_spec_allow_null (
    267         GNUNET_PQ_result_spec_auto_from_type (
    268           "target_pub",
    269           &td.details.kyc_targets.target_pub),
    270         &td.details.kyc_targets.no_account),
    271       GNUNET_PQ_result_spec_bool (
    272         "is_wallet",
    273         &td.details.kyc_targets.is_wallet),
    274       GNUNET_PQ_result_spec_end
    275     };
    276 
    277     if (GNUNET_OK !=
    278         GNUNET_PQ_extract_result (result,
    279                                   rs,
    280                                   i))
    281     {
    282       GNUNET_break (0);
    283       ctx->error = true;
    284       return;
    285     }
    286     ctx->cb (ctx->cb_cls,
    287              &td);
    288     GNUNET_PQ_cleanup_result (rs);
    289   }
    290 }
    291 
    292 
    293 /**
    294  * Function called with reserves table entries.
    295  *
    296  * @param cls closure
    297  * @param result the postgres result
    298  * @param num_results the number of results in @a result
    299  */
    300 static void
    301 lrbt_cb_table_reserves (void *cls,
    302                         PGresult *result,
    303                         unsigned int num_results)
    304 {
    305   struct LookupRecordsByTableContext *ctx = cls;
    306   struct TALER_EXCHANGEDB_TableData td = {
    307     .table = TALER_EXCHANGEDB_RT_RESERVES
    308   };
    309 
    310   for (unsigned int i = 0; i<num_results; i++)
    311   {
    312     struct GNUNET_PQ_ResultSpec rs[] = {
    313       GNUNET_PQ_result_spec_uint64 ("serial",
    314                                     &td.serial),
    315       GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
    316                                             &td.details.reserves.reserve_pub),
    317       GNUNET_PQ_result_spec_timestamp ("expiration_date",
    318                                        &td.details.reserves.expiration_date),
    319       GNUNET_PQ_result_spec_timestamp ("gc_date",
    320                                        &td.details.reserves.gc_date),
    321       GNUNET_PQ_result_spec_end
    322     };
    323 
    324     if (GNUNET_OK !=
    325         GNUNET_PQ_extract_result (result,
    326                                   rs,
    327                                   i))
    328     {
    329       GNUNET_break (0);
    330       ctx->error = true;
    331       return;
    332     }
    333     ctx->cb (ctx->cb_cls,
    334              &td);
    335     GNUNET_PQ_cleanup_result (rs);
    336   }
    337 }
    338 
    339 
    340 /**
    341  * Function called with reserves_in table entries.
    342  *
    343  * @param cls closure
    344  * @param result the postgres result
    345  * @param num_results the number of results in @a result
    346  */
    347 static void
    348 lrbt_cb_table_reserves_in (void *cls,
    349                            PGresult *result,
    350                            unsigned int num_results)
    351 {
    352   struct LookupRecordsByTableContext *ctx = cls;
    353   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
    354   struct TALER_EXCHANGEDB_TableData td = {
    355     .table = TALER_EXCHANGEDB_RT_RESERVES_IN
    356   };
    357 
    358   for (unsigned int i = 0; i<num_results; i++)
    359   {
    360     struct GNUNET_PQ_ResultSpec rs[] = {
    361       GNUNET_PQ_result_spec_uint64 (
    362         "serial",
    363         &td.serial),
    364       GNUNET_PQ_result_spec_auto_from_type (
    365         "reserve_pub",
    366         &td.details.reserves_in.reserve_pub),
    367       GNUNET_PQ_result_spec_uint64 (
    368         "wire_reference",
    369         &td.details.reserves_in.wire_reference),
    370       TALER_PQ_RESULT_SPEC_AMOUNT (
    371         "credit",
    372         &td.details.reserves_in.credit),
    373       GNUNET_PQ_result_spec_auto_from_type (
    374         "wire_source_h_payto",
    375         &td.details.reserves_in.sender_account_h_payto),
    376       GNUNET_PQ_result_spec_string (
    377         "exchange_account_section",
    378         &td.details.reserves_in.exchange_account_section),
    379       GNUNET_PQ_result_spec_timestamp (
    380         "execution_date",
    381         &td.details.reserves_in.execution_date),
    382       GNUNET_PQ_result_spec_end
    383     };
    384 
    385     if (GNUNET_OK !=
    386         GNUNET_PQ_extract_result (result,
    387                                   rs,
    388                                   i))
    389     {
    390       GNUNET_break (0);
    391       ctx->error = true;
    392       return;
    393     }
    394     ctx->cb (ctx->cb_cls,
    395              &td);
    396     GNUNET_PQ_cleanup_result (rs);
    397   }
    398 }
    399 
    400 
    401 /**
    402  * Function called with kycauth_in table entries.
    403  *
    404  * @param cls closure
    405  * @param result the postgres result
    406  * @param num_results the number of results in @a result
    407  */
    408 static void
    409 lrbt_cb_table_kycauth_in (void *cls,
    410                           PGresult *result,
    411                           unsigned int num_results)
    412 {
    413   struct LookupRecordsByTableContext *ctx = cls;
    414   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
    415   struct TALER_EXCHANGEDB_TableData td = {
    416     .table = TALER_EXCHANGEDB_RT_KYCAUTHS_IN
    417   };
    418 
    419   for (unsigned int i = 0; i<num_results; i++)
    420   {
    421     struct GNUNET_PQ_ResultSpec rs[] = {
    422       GNUNET_PQ_result_spec_uint64 (
    423         "serial",
    424         &td.serial),
    425       GNUNET_PQ_result_spec_auto_from_type (
    426         "account_pub",
    427         &td.details.kycauth_in.account_pub),
    428       GNUNET_PQ_result_spec_uint64 (
    429         "wire_reference",
    430         &td.details.kycauth_in.wire_reference),
    431       TALER_PQ_RESULT_SPEC_AMOUNT (
    432         "credit",
    433         &td.details.kycauth_in.credit),
    434       GNUNET_PQ_result_spec_auto_from_type (
    435         "wire_source_h_payto",
    436         &td.details.kycauth_in.sender_account_h_payto),
    437       GNUNET_PQ_result_spec_string (
    438         "exchange_account_section",
    439         &td.details.kycauth_in.exchange_account_section),
    440       GNUNET_PQ_result_spec_timestamp (
    441         "execution_date",
    442         &td.details.kycauth_in.execution_date),
    443       GNUNET_PQ_result_spec_end
    444     };
    445 
    446     if (GNUNET_OK !=
    447         GNUNET_PQ_extract_result (result,
    448                                   rs,
    449                                   i))
    450     {
    451       GNUNET_break (0);
    452       ctx->error = true;
    453       return;
    454     }
    455     ctx->cb (ctx->cb_cls,
    456              &td);
    457     GNUNET_PQ_cleanup_result (rs);
    458   }
    459 }
    460 
    461 
    462 /**
    463  * Function called with reserves_close table entries.
    464  *
    465  * @param cls closure
    466  * @param result the postgres result
    467  * @param num_results the number of results in @a result
    468  */
    469 static void
    470 lrbt_cb_table_reserves_close (void *cls,
    471                               PGresult *result,
    472                               unsigned int num_results)
    473 {
    474   struct LookupRecordsByTableContext *ctx = cls;
    475   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
    476   struct TALER_EXCHANGEDB_TableData td = {
    477     .table = TALER_EXCHANGEDB_RT_RESERVES_CLOSE
    478   };
    479 
    480   for (unsigned int i = 0; i<num_results; i++)
    481   {
    482     struct GNUNET_PQ_ResultSpec rs[] = {
    483       GNUNET_PQ_result_spec_uint64 (
    484         "serial",
    485         &td.serial),
    486       GNUNET_PQ_result_spec_auto_from_type (
    487         "reserve_pub",
    488         &td.details.reserves_close.reserve_pub),
    489       GNUNET_PQ_result_spec_timestamp (
    490         "execution_date",
    491         &td.details.reserves_close.execution_date),
    492       GNUNET_PQ_result_spec_auto_from_type (
    493         "wtid",
    494         &td.details.reserves_close.wtid),
    495       GNUNET_PQ_result_spec_auto_from_type (
    496         "wire_target_h_payto",
    497         &td.details.reserves_close.sender_account_h_payto),
    498       TALER_PQ_RESULT_SPEC_AMOUNT (
    499         "amount",
    500         &td.details.reserves_close.amount),
    501       TALER_PQ_RESULT_SPEC_AMOUNT (
    502         "closing_fee",
    503         &td.details.reserves_close.closing_fee),
    504       GNUNET_PQ_result_spec_end
    505     };
    506 
    507     if (GNUNET_OK !=
    508         GNUNET_PQ_extract_result (result,
    509                                   rs,
    510                                   i))
    511     {
    512       GNUNET_break (0);
    513       ctx->error = true;
    514       return;
    515     }
    516     ctx->cb (ctx->cb_cls,
    517              &td);
    518     GNUNET_PQ_cleanup_result (rs);
    519   }
    520 }
    521 
    522 
    523 /**
    524  * Function called with reserves_open_requests table entries.
    525  *
    526  * @param cls closure
    527  * @param result the postgres result
    528  * @param num_results the number of results in @a result
    529  */
    530 static void
    531 lrbt_cb_table_reserves_open_requests (void *cls,
    532                                       PGresult *result,
    533                                       unsigned int num_results)
    534 {
    535   struct LookupRecordsByTableContext *ctx = cls;
    536   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
    537   struct TALER_EXCHANGEDB_TableData td = {
    538     .table = TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS
    539   };
    540 
    541   for (unsigned int i = 0; i<num_results; i++)
    542   {
    543     struct GNUNET_PQ_ResultSpec rs[] = {
    544       GNUNET_PQ_result_spec_uint64 ("serial",
    545                                     &td.serial),
    546       GNUNET_PQ_result_spec_auto_from_type (
    547         "reserve_pub",
    548         &td.details.reserves_open_requests.reserve_pub),
    549       GNUNET_PQ_result_spec_timestamp (
    550         "request_timestamp",
    551         &td.details.reserves_open_requests.request_timestamp),
    552       GNUNET_PQ_result_spec_timestamp (
    553         "expiration_date",
    554         &td.details.reserves_open_requests.expiration_date),
    555       GNUNET_PQ_result_spec_auto_from_type (
    556         "reserve_sig",
    557         &td.details.reserves_open_requests.reserve_sig),
    558       TALER_PQ_RESULT_SPEC_AMOUNT (
    559         "reserve_payment",
    560         &td.details.reserves_open_requests.reserve_payment),
    561       GNUNET_PQ_result_spec_uint32 (
    562         "requested_purse_limit",
    563         &td.details.reserves_open_requests.requested_purse_limit),
    564       GNUNET_PQ_result_spec_end
    565     };
    566 
    567     if (GNUNET_OK !=
    568         GNUNET_PQ_extract_result (result,
    569                                   rs,
    570                                   i))
    571     {
    572       GNUNET_break (0);
    573       ctx->error = true;
    574       return;
    575     }
    576     ctx->cb (ctx->cb_cls,
    577              &td);
    578     GNUNET_PQ_cleanup_result (rs);
    579   }
    580 }
    581 
    582 
    583 /**
    584  * Function called with reserves_open_deposits table entries.
    585  *
    586  * @param cls closure
    587  * @param result the postgres result
    588  * @param num_results the number of results in @a result
    589  */
    590 static void
    591 lrbt_cb_table_reserves_open_deposits (void *cls,
    592                                       PGresult *result,
    593                                       unsigned int num_results)
    594 {
    595   struct LookupRecordsByTableContext *ctx = cls;
    596   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
    597   struct TALER_EXCHANGEDB_TableData td = {
    598     .table = TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS
    599   };
    600 
    601   for (unsigned int i = 0; i<num_results; i++)
    602   {
    603     struct GNUNET_PQ_ResultSpec rs[] = {
    604       GNUNET_PQ_result_spec_uint64 ("serial",
    605                                     &td.serial),
    606       GNUNET_PQ_result_spec_auto_from_type (
    607         "reserve_sig",
    608         &td.details.reserves_open_deposits.reserve_sig),
    609       GNUNET_PQ_result_spec_auto_from_type (
    610         "reserve_pub",
    611         &td.details.reserves_open_deposits.reserve_pub),
    612       GNUNET_PQ_result_spec_auto_from_type (
    613         "coin_pub",
    614         &td.details.reserves_open_deposits.coin_pub),
    615       GNUNET_PQ_result_spec_auto_from_type (
    616         "coin_sig",
    617         &td.details.reserves_open_deposits.coin_sig),
    618       TALER_PQ_RESULT_SPEC_AMOUNT (
    619         "contribution",
    620         &td.details.reserves_open_deposits.contribution),
    621       GNUNET_PQ_result_spec_end
    622     };
    623 
    624     if (GNUNET_OK !=
    625         GNUNET_PQ_extract_result (result,
    626                                   rs,
    627                                   i))
    628     {
    629       GNUNET_break (0);
    630       ctx->error = true;
    631       return;
    632     }
    633     ctx->cb (ctx->cb_cls,
    634              &td);
    635     GNUNET_PQ_cleanup_result (rs);
    636   }
    637 }
    638 
    639 
    640 /**
    641  * Function called with auditors table entries.
    642  *
    643  * @param cls closure
    644  * @param result the postgres result
    645  * @param num_results the number of results in @a result
    646  */
    647 static void
    648 lrbt_cb_table_auditors (void *cls,
    649                         PGresult *result,
    650                         unsigned int num_results)
    651 {
    652   struct LookupRecordsByTableContext *ctx = cls;
    653   struct TALER_EXCHANGEDB_TableData td = {
    654     .table = TALER_EXCHANGEDB_RT_AUDITORS
    655   };
    656 
    657   for (unsigned int i = 0; i<num_results; i++)
    658   {
    659     struct GNUNET_PQ_ResultSpec rs[] = {
    660       GNUNET_PQ_result_spec_uint64 ("serial",
    661                                     &td.serial),
    662       GNUNET_PQ_result_spec_auto_from_type ("auditor_pub",
    663                                             &td.details.auditors.auditor_pub),
    664       GNUNET_PQ_result_spec_string ("auditor_url",
    665                                     &td.details.auditors.auditor_url),
    666       GNUNET_PQ_result_spec_string ("auditor_name",
    667                                     &td.details.auditors.auditor_name),
    668       GNUNET_PQ_result_spec_bool ("is_active",
    669                                   &td.details.auditors.is_active),
    670       GNUNET_PQ_result_spec_timestamp ("last_change",
    671                                        &td.details.auditors.last_change),
    672       GNUNET_PQ_result_spec_end
    673     };
    674 
    675     if (GNUNET_OK !=
    676         GNUNET_PQ_extract_result (result,
    677                                   rs,
    678                                   i))
    679     {
    680       GNUNET_break (0);
    681       ctx->error = true;
    682       return;
    683     }
    684     ctx->cb (ctx->cb_cls,
    685              &td);
    686     GNUNET_PQ_cleanup_result (rs);
    687   }
    688 }
    689 
    690 
    691 /**
    692  * Function called with auditor_denom_sigs table entries.
    693  *
    694  * @param cls closure
    695  * @param result the postgres result
    696  * @param num_results the number of results in @a result
    697  */
    698 static void
    699 lrbt_cb_table_auditor_denom_sigs (void *cls,
    700                                   PGresult *result,
    701                                   unsigned int num_results)
    702 {
    703   struct LookupRecordsByTableContext *ctx = cls;
    704   struct TALER_EXCHANGEDB_TableData td = {
    705     .table = TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS
    706   };
    707 
    708   for (unsigned int i = 0; i<num_results; i++)
    709   {
    710     struct GNUNET_PQ_ResultSpec rs[] = {
    711       GNUNET_PQ_result_spec_uint64 (
    712         "serial",
    713         &td.serial),
    714       GNUNET_PQ_result_spec_uint64 (
    715         "auditor_uuid",
    716         &td.details.auditor_denom_sigs.auditor_uuid),
    717       GNUNET_PQ_result_spec_uint64 (
    718         "denominations_serial",
    719         &td.details.auditor_denom_sigs.denominations_serial),
    720       GNUNET_PQ_result_spec_auto_from_type (
    721         "auditor_sig",
    722         &td.details.auditor_denom_sigs.auditor_sig),
    723       GNUNET_PQ_result_spec_end
    724     };
    725 
    726     if (GNUNET_OK !=
    727         GNUNET_PQ_extract_result (result,
    728                                   rs,
    729                                   i))
    730     {
    731       GNUNET_break (0);
    732       ctx->error = true;
    733       return;
    734     }
    735     ctx->cb (ctx->cb_cls,
    736              &td);
    737     GNUNET_PQ_cleanup_result (rs);
    738   }
    739 }
    740 
    741 
    742 /**
    743  * Function called with exchange_sign_keys table entries.
    744  *
    745  * @param cls closure
    746  * @param result the postgres result
    747  * @param num_results the number of results in @a result
    748  */
    749 static void
    750 lrbt_cb_table_exchange_sign_keys (void *cls,
    751                                   PGresult *result,
    752                                   unsigned int num_results)
    753 {
    754   struct LookupRecordsByTableContext *ctx = cls;
    755   struct TALER_EXCHANGEDB_TableData td = {
    756     .table = TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS
    757   };
    758 
    759   for (unsigned int i = 0; i<num_results; i++)
    760   {
    761     struct GNUNET_PQ_ResultSpec rs[] = {
    762       GNUNET_PQ_result_spec_uint64 ("serial",
    763                                     &td.serial),
    764       GNUNET_PQ_result_spec_auto_from_type ("exchange_pub",
    765                                             &td.details.exchange_sign_keys.
    766                                             exchange_pub),
    767       GNUNET_PQ_result_spec_auto_from_type ("master_sig",
    768                                             &td.details.exchange_sign_keys.
    769                                             master_sig),
    770       GNUNET_PQ_result_spec_timestamp ("valid_from",
    771                                        &td.details.exchange_sign_keys.meta.
    772                                        start),
    773       GNUNET_PQ_result_spec_timestamp ("expire_sign",
    774                                        &td.details.exchange_sign_keys.meta.
    775                                        expire_sign),
    776       GNUNET_PQ_result_spec_timestamp ("expire_legal",
    777                                        &td.details.exchange_sign_keys.meta.
    778                                        expire_legal),
    779       GNUNET_PQ_result_spec_end
    780     };
    781 
    782     if (GNUNET_OK !=
    783         GNUNET_PQ_extract_result (result,
    784                                   rs,
    785                                   i))
    786     {
    787       GNUNET_break (0);
    788       ctx->error = true;
    789       return;
    790     }
    791     ctx->cb (ctx->cb_cls,
    792              &td);
    793     GNUNET_PQ_cleanup_result (rs);
    794   }
    795 }
    796 
    797 
    798 /**
    799  * Function called with signkey_revocations table entries.
    800  *
    801  * @param cls closure
    802  * @param result the postgres result
    803  * @param num_results the number of results in @a result
    804  */
    805 static void
    806 lrbt_cb_table_signkey_revocations (void *cls,
    807                                    PGresult *result,
    808                                    unsigned int num_results)
    809 {
    810   struct LookupRecordsByTableContext *ctx = cls;
    811   struct TALER_EXCHANGEDB_TableData td = {
    812     .table = TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS
    813   };
    814 
    815   for (unsigned int i = 0; i<num_results; i++)
    816   {
    817     struct GNUNET_PQ_ResultSpec rs[] = {
    818       GNUNET_PQ_result_spec_uint64 ("serial",
    819                                     &td.serial),
    820       GNUNET_PQ_result_spec_uint64 ("esk_serial",
    821                                     &td.details.signkey_revocations.esk_serial),
    822       GNUNET_PQ_result_spec_auto_from_type ("master_sig",
    823                                             &td.details.signkey_revocations.
    824                                             master_sig),
    825       GNUNET_PQ_result_spec_end
    826     };
    827 
    828     if (GNUNET_OK !=
    829         GNUNET_PQ_extract_result (result,
    830                                   rs,
    831                                   i))
    832     {
    833       GNUNET_break (0);
    834       ctx->error = true;
    835       return;
    836     }
    837     ctx->cb (ctx->cb_cls,
    838              &td);
    839     GNUNET_PQ_cleanup_result (rs);
    840   }
    841 }
    842 
    843 
    844 /**
    845  * Function called with known_coins table entries.
    846  *
    847  * @param cls closure
    848  * @param result the postgres result
    849  * @param num_results the number of results in @a result
    850  */
    851 static void
    852 lrbt_cb_table_known_coins (void *cls,
    853                            PGresult *result,
    854                            unsigned int num_results)
    855 {
    856   struct LookupRecordsByTableContext *ctx = cls;
    857   struct TALER_EXCHANGEDB_TableData td = {
    858     .table = TALER_EXCHANGEDB_RT_KNOWN_COINS
    859   };
    860 
    861   for (unsigned int i = 0; i<num_results; i++)
    862   {
    863     struct GNUNET_PQ_ResultSpec rs[] = {
    864       GNUNET_PQ_result_spec_uint64 (
    865         "serial",
    866         &td.serial),
    867       GNUNET_PQ_result_spec_auto_from_type (
    868         "coin_pub",
    869         &td.details.known_coins.coin_pub),
    870       TALER_PQ_result_spec_denom_sig (
    871         "denom_sig",
    872         &td.details.known_coins.denom_sig),
    873       GNUNET_PQ_result_spec_uint64 (
    874         "denominations_serial",
    875         &td.details.known_coins.denominations_serial),
    876       GNUNET_PQ_result_spec_end
    877     };
    878 
    879     if (GNUNET_OK !=
    880         GNUNET_PQ_extract_result (result,
    881                                   rs,
    882                                   i))
    883     {
    884       GNUNET_break (0);
    885       ctx->error = true;
    886       return;
    887     }
    888     ctx->cb (ctx->cb_cls,
    889              &td);
    890     GNUNET_PQ_cleanup_result (rs);
    891   }
    892 }
    893 
    894 
    895 /**
    896  * Function called with refresh table entries.
    897  *
    898  * @param cls closure
    899  * @param result the postgres result
    900  * @param num_results the number of results in @a result
    901  */
    902 static void
    903 lrbt_cb_table_refresh (void *cls,
    904                        PGresult *result,
    905                        unsigned int num_results)
    906 {
    907   struct LookupRecordsByTableContext *ctx = cls;
    908   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
    909   struct TALER_EXCHANGEDB_TableData td = {
    910     .table = TALER_EXCHANGEDB_RT_REFRESH
    911   };
    912 
    913   for (unsigned int i = 0; i<num_results; i++)
    914   {
    915     bool no_cs_r_values;
    916     bool no_cs_r_choices;
    917     size_t num_denom_sigs;
    918     struct GNUNET_PQ_ResultSpec rs[] = {
    919       GNUNET_PQ_result_spec_uint64 (
    920         "serial",
    921         &td.serial),
    922       GNUNET_PQ_result_spec_auto_from_type (
    923         "rc",
    924         &td.details.refresh.rc),
    925       GNUNET_PQ_result_spec_auto_from_type (
    926         "execution_date",
    927         &td.details.refresh.execution_date),
    928       TALER_PQ_RESULT_SPEC_AMOUNT (
    929         "amount_with_fee",
    930         &td.details.refresh.amount_with_fee),
    931       GNUNET_PQ_result_spec_auto_from_type (
    932         "old_coin_pub",
    933         &td.details.refresh.old_coin_pub),
    934       GNUNET_PQ_result_spec_auto_from_type (
    935         "old_coin_sig",
    936         &td.details.refresh.old_coin_sig),
    937       GNUNET_PQ_result_spec_auto_from_type (
    938         "refresh_seed",
    939         &td.details.refresh.refresh_seed),
    940       GNUNET_PQ_result_spec_uint32 (
    941         "noreveal_index",
    942         &td.details.refresh.noreveal_index),
    943       GNUNET_PQ_result_spec_auto_from_type (
    944         "planchets_h",
    945         &td.details.refresh.planchets_h),
    946       GNUNET_PQ_result_spec_auto_from_type (
    947         "selected_h",
    948         &td.details.refresh.selected_h),
    949       GNUNET_PQ_result_spec_allow_null (
    950         GNUNET_PQ_result_spec_auto_from_type (
    951           "blinding_seed",
    952           &td.details.refresh.blinding_seed),
    953         &td.details.refresh.no_blinding_seed),
    954       GNUNET_PQ_result_spec_allow_null (
    955         TALER_PQ_result_spec_array_cs_r_pub (
    956           pg->conn,
    957           "cs_r_values",
    958           &td.details.refresh.num_cs_r_values,
    959           &td.details.refresh.cs_r_values),
    960         &no_cs_r_values),
    961       GNUNET_PQ_result_spec_allow_null (
    962         GNUNET_PQ_result_spec_uint64 (
    963           "cs_r_choices",
    964           &td.details.refresh.cs_r_choices),
    965         &no_cs_r_choices),
    966       GNUNET_PQ_result_spec_array_uint64 (
    967         pg->conn,
    968         "denom_serials",
    969         &td.details.refresh.num_coins,
    970         &td.details.refresh.denom_serials),
    971       TALER_PQ_result_spec_array_blinded_denom_sig (
    972         pg->conn,
    973         "denom_sigs",
    974         &num_denom_sigs,
    975         &td.details.refresh.denom_sigs),
    976       GNUNET_PQ_result_spec_end
    977     };
    978 
    979     if (GNUNET_OK !=
    980         GNUNET_PQ_extract_result (result,
    981                                   rs,
    982                                   i))
    983     {
    984       GNUNET_break (0);
    985       ctx->error = true;
    986       GNUNET_PQ_cleanup_result (rs);
    987       return;
    988     }
    989     ctx->cb (ctx->cb_cls,
    990              &td);
    991     GNUNET_PQ_cleanup_result (rs);
    992   }
    993 }
    994 
    995 
    996 /**
    997  * Function called with batch deposits table entries.
    998  *
    999  * @param cls closure
   1000  * @param result the postgres result
   1001  * @param num_results the number of results in @a result
   1002  */
   1003 static void
   1004 lrbt_cb_table_batch_deposits (void *cls,
   1005                               PGresult *result,
   1006                               unsigned int num_results)
   1007 {
   1008   struct LookupRecordsByTableContext *ctx = cls;
   1009   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   1010   struct TALER_EXCHANGEDB_TableData td = {
   1011     .table = TALER_EXCHANGEDB_RT_BATCH_DEPOSITS
   1012   };
   1013 
   1014   for (unsigned int i = 0; i<num_results; i++)
   1015   {
   1016     struct GNUNET_PQ_ResultSpec rs[] = {
   1017       GNUNET_PQ_result_spec_uint64 (
   1018         "serial",
   1019         &td.serial),
   1020       GNUNET_PQ_result_spec_uint64 (
   1021         "shard",
   1022         &td.details.batch_deposits.shard),
   1023       GNUNET_PQ_result_spec_auto_from_type (
   1024         "merchant_pub",
   1025         &td.details.batch_deposits.merchant_pub),
   1026       GNUNET_PQ_result_spec_timestamp (
   1027         "wallet_timestamp",
   1028         &td.details.batch_deposits.wallet_timestamp),
   1029       GNUNET_PQ_result_spec_timestamp (
   1030         "exchange_timestamp",
   1031         &td.details.batch_deposits.exchange_timestamp),
   1032       GNUNET_PQ_result_spec_timestamp (
   1033         "refund_deadline",
   1034         &td.details.batch_deposits.refund_deadline),
   1035       GNUNET_PQ_result_spec_timestamp (
   1036         "wire_deadline",
   1037         &td.details.batch_deposits.wire_deadline),
   1038       GNUNET_PQ_result_spec_auto_from_type (
   1039         "h_contract_terms",
   1040         &td.details.batch_deposits.h_contract_terms),
   1041       GNUNET_PQ_result_spec_allow_null (
   1042         GNUNET_PQ_result_spec_auto_from_type (
   1043           "wallet_data_hash",
   1044           &td.details.batch_deposits.wallet_data_hash),
   1045         &td.details.batch_deposits.no_wallet_data_hash),
   1046       GNUNET_PQ_result_spec_auto_from_type (
   1047         "wire_salt",
   1048         &td.details.batch_deposits.wire_salt),
   1049       GNUNET_PQ_result_spec_auto_from_type (
   1050         "wire_target_h_payto",
   1051         &td.details.batch_deposits.wire_target_h_payto),
   1052       GNUNET_PQ_result_spec_allow_null (
   1053         GNUNET_PQ_result_spec_uint64 (
   1054           "policy_details_serial_id",
   1055           &td.details.batch_deposits.policy_details_serial_id),
   1056         &td.details.batch_deposits.no_policy_details),
   1057       GNUNET_PQ_result_spec_bool (
   1058         "policy_blocked",
   1059         &td.details.batch_deposits.policy_blocked),
   1060       TALER_PQ_RESULT_SPEC_AMOUNT (
   1061         "total_amount",
   1062         &td.details.batch_deposits.total_amount),
   1063       TALER_PQ_RESULT_SPEC_AMOUNT (
   1064         "total_without_fee",
   1065         &td.details.batch_deposits.total_without_fee),
   1066       GNUNET_PQ_result_spec_auto_from_type (
   1067         "merchant_sig",
   1068         &td.details.batch_deposits.merchant_sig),
   1069       GNUNET_PQ_result_spec_bool (
   1070         "done",
   1071         &td.details.batch_deposits.done),
   1072       GNUNET_PQ_result_spec_end
   1073     };
   1074 
   1075     td.details.batch_deposits.policy_details_serial_id = 0;
   1076     if (GNUNET_OK !=
   1077         GNUNET_PQ_extract_result (result,
   1078                                   rs,
   1079                                   i))
   1080     {
   1081       GNUNET_break (0);
   1082       ctx->error = true;
   1083       return;
   1084     }
   1085     ctx->cb (ctx->cb_cls,
   1086              &td);
   1087     GNUNET_PQ_cleanup_result (rs);
   1088   }
   1089 }
   1090 
   1091 
   1092 /**
   1093  * Function called with coin deposits table entries.
   1094  *
   1095  * @param cls closure
   1096  * @param result the postgres result
   1097  * @param num_results the number of results in @a result
   1098  */
   1099 static void
   1100 lrbt_cb_table_coin_deposits (void *cls,
   1101                              PGresult *result,
   1102                              unsigned int num_results)
   1103 {
   1104   struct LookupRecordsByTableContext *ctx = cls;
   1105   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   1106   struct TALER_EXCHANGEDB_TableData td = {
   1107     .table = TALER_EXCHANGEDB_RT_COIN_DEPOSITS
   1108   };
   1109 
   1110   for (unsigned int i = 0; i<num_results; i++)
   1111   {
   1112     struct GNUNET_PQ_ResultSpec rs[] = {
   1113       GNUNET_PQ_result_spec_uint64 (
   1114         "serial",
   1115         &td.serial),
   1116       GNUNET_PQ_result_spec_uint64 (
   1117         "batch_deposit_serial_id",
   1118         &td.details.coin_deposits.batch_deposit_serial_id),
   1119       GNUNET_PQ_result_spec_auto_from_type (
   1120         "coin_pub",
   1121         &td.details.coin_deposits.coin_pub),
   1122       GNUNET_PQ_result_spec_auto_from_type (
   1123         "coin_sig",
   1124         &td.details.coin_deposits.coin_sig),
   1125       TALER_PQ_RESULT_SPEC_AMOUNT (
   1126         "amount_with_fee",
   1127         &td.details.coin_deposits.amount_with_fee),
   1128       GNUNET_PQ_result_spec_end
   1129     };
   1130 
   1131     if (GNUNET_OK !=
   1132         GNUNET_PQ_extract_result (result,
   1133                                   rs,
   1134                                   i))
   1135     {
   1136       GNUNET_break (0);
   1137       ctx->error = true;
   1138       return;
   1139     }
   1140     ctx->cb (ctx->cb_cls,
   1141              &td);
   1142     GNUNET_PQ_cleanup_result (rs);
   1143   }
   1144 }
   1145 
   1146 
   1147 /**
   1148  * Function called with refunds table entries.
   1149  *
   1150  * @param cls closure
   1151  * @param result the postgres result
   1152  * @param num_results the number of results in @a result
   1153  */
   1154 static void
   1155 lrbt_cb_table_refunds (void *cls,
   1156                        PGresult *result,
   1157                        unsigned int num_results)
   1158 {
   1159   struct LookupRecordsByTableContext *ctx = cls;
   1160   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   1161   struct TALER_EXCHANGEDB_TableData td = {
   1162     .table = TALER_EXCHANGEDB_RT_REFUNDS
   1163   };
   1164 
   1165   for (unsigned int i = 0; i<num_results; i++)
   1166   {
   1167     struct GNUNET_PQ_ResultSpec rs[] = {
   1168       GNUNET_PQ_result_spec_uint64 (
   1169         "serial",
   1170         &td.serial),
   1171       GNUNET_PQ_result_spec_auto_from_type (
   1172         "coin_pub",
   1173         &td.details.refunds.coin_pub),
   1174       GNUNET_PQ_result_spec_auto_from_type (
   1175         "merchant_sig",
   1176         &td.details.refunds.merchant_sig),
   1177       GNUNET_PQ_result_spec_uint64 (
   1178         "rtransaction_id",
   1179         &td.details.refunds.rtransaction_id),
   1180       TALER_PQ_RESULT_SPEC_AMOUNT (
   1181         "amount_with_fee",
   1182         &td.details.refunds.amount_with_fee),
   1183       GNUNET_PQ_result_spec_uint64 (
   1184         "batch_deposit_serial_id",
   1185         &td.details.refunds.batch_deposit_serial_id),
   1186       GNUNET_PQ_result_spec_end
   1187     };
   1188 
   1189     if (GNUNET_OK !=
   1190         GNUNET_PQ_extract_result (result,
   1191                                   rs,
   1192                                   i))
   1193     {
   1194       GNUNET_break (0);
   1195       ctx->error = true;
   1196       return;
   1197     }
   1198     ctx->cb (ctx->cb_cls,
   1199              &td);
   1200     GNUNET_PQ_cleanup_result (rs);
   1201   }
   1202 }
   1203 
   1204 
   1205 /**
   1206  * Function called with wire_out table entries.
   1207  *
   1208  * @param cls closure
   1209  * @param result the postgres result
   1210  * @param num_results the number of results in @a result
   1211  */
   1212 static void
   1213 lrbt_cb_table_wire_out (void *cls,
   1214                         PGresult *result,
   1215                         unsigned int num_results)
   1216 {
   1217   struct LookupRecordsByTableContext *ctx = cls;
   1218   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   1219   struct TALER_EXCHANGEDB_TableData td = {
   1220     .table = TALER_EXCHANGEDB_RT_WIRE_OUT
   1221   };
   1222 
   1223   for (unsigned int i = 0; i<num_results; i++)
   1224   {
   1225     struct GNUNET_PQ_ResultSpec rs[] = {
   1226       GNUNET_PQ_result_spec_uint64 ("serial",
   1227                                     &td.serial),
   1228       GNUNET_PQ_result_spec_timestamp (
   1229         "execution_date",
   1230         &td.details.wire_out.execution_date),
   1231       GNUNET_PQ_result_spec_auto_from_type (
   1232         "wtid_raw",
   1233         &td.details.wire_out.wtid_raw),
   1234       GNUNET_PQ_result_spec_auto_from_type (
   1235         "wire_target_h_payto",
   1236         &td.details.wire_out.wire_target_h_payto),
   1237       GNUNET_PQ_result_spec_string (
   1238         "exchange_account_section",
   1239         &td.details.wire_out.exchange_account_section),
   1240       TALER_PQ_RESULT_SPEC_AMOUNT (
   1241         "amount",
   1242         &td.details.wire_out.amount),
   1243       GNUNET_PQ_result_spec_end
   1244     };
   1245 
   1246     if (GNUNET_OK !=
   1247         GNUNET_PQ_extract_result (result,
   1248                                   rs,
   1249                                   i))
   1250     {
   1251       GNUNET_break (0);
   1252       ctx->error = true;
   1253       return;
   1254     }
   1255     ctx->cb (ctx->cb_cls,
   1256              &td);
   1257     GNUNET_PQ_cleanup_result (rs);
   1258   }
   1259 }
   1260 
   1261 
   1262 /**
   1263  * Function called with aggregation_tracking table entries.
   1264  *
   1265  * @param cls closure
   1266  * @param result the postgres result
   1267  * @param num_results the number of results in @a result
   1268  */
   1269 static void
   1270 lrbt_cb_table_aggregation_tracking (void *cls,
   1271                                     PGresult *result,
   1272                                     unsigned int num_results)
   1273 {
   1274   struct LookupRecordsByTableContext *ctx = cls;
   1275   struct TALER_EXCHANGEDB_TableData td = {
   1276     .table = TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING
   1277   };
   1278 
   1279   for (unsigned int i = 0; i<num_results; i++)
   1280   {
   1281     struct GNUNET_PQ_ResultSpec rs[] = {
   1282       GNUNET_PQ_result_spec_uint64 (
   1283         "serial",
   1284         &td.serial),
   1285       GNUNET_PQ_result_spec_uint64 (
   1286         "batch_deposit_serial_id",
   1287         &td.details.aggregation_tracking.batch_deposit_serial_id),
   1288       GNUNET_PQ_result_spec_auto_from_type (
   1289         "wtid_raw",
   1290         &td.details.aggregation_tracking.wtid_raw),
   1291       GNUNET_PQ_result_spec_end
   1292     };
   1293 
   1294     if (GNUNET_OK !=
   1295         GNUNET_PQ_extract_result (result,
   1296                                   rs,
   1297                                   i))
   1298     {
   1299       GNUNET_break (0);
   1300       ctx->error = true;
   1301       return;
   1302     }
   1303     ctx->cb (ctx->cb_cls,
   1304              &td);
   1305     GNUNET_PQ_cleanup_result (rs);
   1306   }
   1307 }
   1308 
   1309 
   1310 /**
   1311  * Function called with wire_fee table entries.
   1312  *
   1313  * @param cls closure
   1314  * @param result the postgres result
   1315  * @param num_results the number of results in @a result
   1316  */
   1317 static void
   1318 lrbt_cb_table_wire_fee (void *cls,
   1319                         PGresult *result,
   1320                         unsigned int num_results)
   1321 {
   1322   struct LookupRecordsByTableContext *ctx = cls;
   1323   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   1324   struct TALER_EXCHANGEDB_TableData td = {
   1325     .table = TALER_EXCHANGEDB_RT_WIRE_FEE
   1326   };
   1327 
   1328   for (unsigned int i = 0; i<num_results; i++)
   1329   {
   1330     struct GNUNET_PQ_ResultSpec rs[] = {
   1331       GNUNET_PQ_result_spec_uint64 ("serial",
   1332                                     &td.serial),
   1333       GNUNET_PQ_result_spec_string ("wire_method",
   1334                                     &td.details.wire_fee.wire_method),
   1335       GNUNET_PQ_result_spec_timestamp ("start_date",
   1336                                        &td.details.wire_fee.start_date),
   1337       GNUNET_PQ_result_spec_timestamp ("end_date",
   1338                                        &td.details.wire_fee.end_date),
   1339       TALER_PQ_RESULT_SPEC_AMOUNT ("wire_fee",
   1340                                    &td.details.wire_fee.fees.wire),
   1341       TALER_PQ_RESULT_SPEC_AMOUNT ("closing_fee",
   1342                                    &td.details.wire_fee.fees.closing),
   1343       GNUNET_PQ_result_spec_auto_from_type ("master_sig",
   1344                                             &td.details.wire_fee.master_sig),
   1345       GNUNET_PQ_result_spec_end
   1346     };
   1347 
   1348     if (GNUNET_OK !=
   1349         GNUNET_PQ_extract_result (result,
   1350                                   rs,
   1351                                   i))
   1352     {
   1353       GNUNET_break (0);
   1354       ctx->error = true;
   1355       return;
   1356     }
   1357     ctx->cb (ctx->cb_cls,
   1358              &td);
   1359     GNUNET_PQ_cleanup_result (rs);
   1360   }
   1361 }
   1362 
   1363 
   1364 /**
   1365  * Function called with wire_fee table entries.
   1366  *
   1367  * @param cls closure
   1368  * @param result the postgres result
   1369  * @param num_results the number of results in @a result
   1370  */
   1371 static void
   1372 lrbt_cb_table_global_fee (void *cls,
   1373                           PGresult *result,
   1374                           unsigned int num_results)
   1375 {
   1376   struct LookupRecordsByTableContext *ctx = cls;
   1377   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   1378   struct TALER_EXCHANGEDB_TableData td = {
   1379     .table = TALER_EXCHANGEDB_RT_GLOBAL_FEE
   1380   };
   1381 
   1382   for (unsigned int i = 0; i<num_results; i++)
   1383   {
   1384     struct GNUNET_PQ_ResultSpec rs[] = {
   1385       GNUNET_PQ_result_spec_uint64 (
   1386         "serial",
   1387         &td.serial),
   1388       GNUNET_PQ_result_spec_timestamp (
   1389         "start_date",
   1390         &td.details.global_fee.start_date),
   1391       GNUNET_PQ_result_spec_timestamp (
   1392         "end_date",
   1393         &td.details.global_fee.end_date),
   1394       TALER_PQ_RESULT_SPEC_AMOUNT (
   1395         "history_fee",
   1396         &td.details.global_fee.fees.history),
   1397       TALER_PQ_RESULT_SPEC_AMOUNT (
   1398         "account_fee",
   1399         &td.details.global_fee.fees.account),
   1400       TALER_PQ_RESULT_SPEC_AMOUNT (
   1401         "purse_fee",
   1402         &td.details.global_fee.fees.purse),
   1403       GNUNET_PQ_result_spec_relative_time (
   1404         "purse_timeout",
   1405         &td.details.global_fee.purse_timeout),
   1406       GNUNET_PQ_result_spec_relative_time (
   1407         "history_expiration",
   1408         &td.details.global_fee.history_expiration),
   1409       GNUNET_PQ_result_spec_uint32 (
   1410         "purse_account_limit",
   1411         &td.details.global_fee.purse_account_limit),
   1412       GNUNET_PQ_result_spec_auto_from_type (
   1413         "master_sig",
   1414         &td.details.global_fee.master_sig),
   1415       GNUNET_PQ_result_spec_end
   1416     };
   1417 
   1418     if (GNUNET_OK !=
   1419         GNUNET_PQ_extract_result (result,
   1420                                   rs,
   1421                                   i))
   1422     {
   1423       GNUNET_break (0);
   1424       ctx->error = true;
   1425       return;
   1426     }
   1427     ctx->cb (ctx->cb_cls,
   1428              &td);
   1429     GNUNET_PQ_cleanup_result (rs);
   1430   }
   1431 }
   1432 
   1433 
   1434 /**
   1435  * Function called with recoup table entries.
   1436  *
   1437  * @param cls closure
   1438  * @param result the postgres result
   1439  * @param num_results the number of results in @a result
   1440  */
   1441 static void
   1442 lrbt_cb_table_recoup (void *cls,
   1443                       PGresult *result,
   1444                       unsigned int num_results)
   1445 {
   1446   struct LookupRecordsByTableContext *ctx = cls;
   1447   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   1448   struct TALER_EXCHANGEDB_TableData td = {
   1449     .table = TALER_EXCHANGEDB_RT_RECOUP
   1450   };
   1451 
   1452   for (unsigned int i = 0; i<num_results; i++)
   1453   {
   1454     struct GNUNET_PQ_ResultSpec rs[] = {
   1455       GNUNET_PQ_result_spec_uint64 ("serial",
   1456                                     &td.serial),
   1457       GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
   1458                                             &td.details.recoup.coin_sig),
   1459       GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
   1460                                             &td.details.recoup.coin_blind),
   1461       TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
   1462                                    &td.details.recoup.amount),
   1463       GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
   1464                                        &td.details.recoup.timestamp),
   1465       GNUNET_PQ_result_spec_auto_from_type (
   1466         "coin_pub",
   1467         &td.details.recoup.coin_pub),
   1468       GNUNET_PQ_result_spec_uint64 ("withdraw_serial_id",
   1469                                     &td.details.recoup.withdraw_serial_id),
   1470       GNUNET_PQ_result_spec_end
   1471     };
   1472 
   1473     if (GNUNET_OK !=
   1474         GNUNET_PQ_extract_result (result,
   1475                                   rs,
   1476                                   i))
   1477     {
   1478       GNUNET_break (0);
   1479       ctx->error = true;
   1480       return;
   1481     }
   1482     ctx->cb (ctx->cb_cls,
   1483              &td);
   1484     GNUNET_PQ_cleanup_result (rs);
   1485   }
   1486 }
   1487 
   1488 
   1489 /**
   1490  * Function called with recoup_refresh table entries.
   1491  *
   1492  * @param cls closure
   1493  * @param result the postgres result
   1494  * @param num_results the number of results in @a result
   1495  */
   1496 static void
   1497 lrbt_cb_table_recoup_refresh (void *cls,
   1498                               PGresult *result,
   1499                               unsigned int num_results)
   1500 {
   1501   struct LookupRecordsByTableContext *ctx = cls;
   1502   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   1503   struct TALER_EXCHANGEDB_TableData td = {
   1504     .table = TALER_EXCHANGEDB_RT_RECOUP_REFRESH
   1505   };
   1506 
   1507   for (unsigned int i = 0; i<num_results; i++)
   1508   {
   1509     struct GNUNET_PQ_ResultSpec rs[] = {
   1510       GNUNET_PQ_result_spec_uint64 ("serial",
   1511                                     &td.serial),
   1512       GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
   1513                                             &td.details.recoup_refresh.coin_sig)
   1514       ,
   1515       GNUNET_PQ_result_spec_auto_from_type (
   1516         "coin_blind",
   1517         &td.details.recoup_refresh.coin_blind),
   1518       TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
   1519                                    &td.details.recoup_refresh.amount),
   1520       GNUNET_PQ_result_spec_timestamp ("recoup_timestamp",
   1521                                        &td.details.recoup_refresh.timestamp),
   1522       GNUNET_PQ_result_spec_uint64 ("known_coin_id",
   1523                                     &td.details.recoup_refresh.known_coin_id),
   1524       GNUNET_PQ_result_spec_auto_from_type (
   1525         "coin_pub",
   1526         &td.details.recoup_refresh.coin_pub),
   1527       GNUNET_PQ_result_spec_uint64 ("rrc_serial",
   1528                                     &td.details.recoup_refresh.rrc_serial),
   1529       GNUNET_PQ_result_spec_end
   1530     };
   1531 
   1532     if (GNUNET_OK !=
   1533         GNUNET_PQ_extract_result (result,
   1534                                   rs,
   1535                                   i))
   1536     {
   1537       GNUNET_break (0);
   1538       ctx->error = true;
   1539       return;
   1540     }
   1541     ctx->cb (ctx->cb_cls,
   1542              &td);
   1543     GNUNET_PQ_cleanup_result (rs);
   1544   }
   1545 }
   1546 
   1547 
   1548 /**
   1549  * Function called with extensions table entries.
   1550  *
   1551  * @param cls closure
   1552  * @param result the postgres result
   1553  * @param num_results the number of results in @a result
   1554  */
   1555 static void
   1556 lrbt_cb_table_extensions (void *cls,
   1557                           PGresult *result,
   1558                           unsigned int num_results)
   1559 {
   1560   struct LookupRecordsByTableContext *ctx = cls;
   1561   struct TALER_EXCHANGEDB_TableData td = {
   1562     .table = TALER_EXCHANGEDB_RT_EXTENSIONS
   1563   };
   1564   bool no_manifest = false;
   1565 
   1566   for (unsigned int i = 0; i<num_results; i++)
   1567   {
   1568     struct GNUNET_PQ_ResultSpec rs[] = {
   1569       GNUNET_PQ_result_spec_uint64 ("extension_id",
   1570                                     &td.serial),
   1571       GNUNET_PQ_result_spec_string ("name",
   1572                                     &td.details.extensions.name),
   1573       GNUNET_PQ_result_spec_allow_null (
   1574         GNUNET_PQ_result_spec_string ("manifest",
   1575                                       &td.details.extensions.manifest),
   1576         &no_manifest),
   1577       GNUNET_PQ_result_spec_end
   1578     };
   1579 
   1580     if (GNUNET_OK !=
   1581         GNUNET_PQ_extract_result (result,
   1582                                   rs,
   1583                                   i))
   1584     {
   1585       GNUNET_break (0);
   1586       ctx->error = true;
   1587       return;
   1588     }
   1589     ctx->cb (ctx->cb_cls,
   1590              &td);
   1591     GNUNET_PQ_cleanup_result (rs);
   1592   }
   1593 }
   1594 
   1595 
   1596 /**
   1597  * Function called with policy_details table entries.
   1598  *
   1599  * @param cls closure
   1600  * @param result the postgres result
   1601  * @param num_results the number of results in @a result
   1602  */
   1603 static void
   1604 lrbt_cb_table_policy_details (void *cls,
   1605                               PGresult *result,
   1606                               unsigned int num_results)
   1607 {
   1608   struct LookupRecordsByTableContext *ctx = cls;
   1609   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   1610   struct TALER_EXCHANGEDB_TableData td = {
   1611     .table = TALER_EXCHANGEDB_RT_POLICY_DETAILS
   1612   };
   1613 
   1614   for (unsigned int i = 0; i<num_results; i++)
   1615   {
   1616     struct GNUNET_PQ_ResultSpec rs[] = {
   1617       GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id",
   1618                                     &td.serial),
   1619       GNUNET_PQ_result_spec_auto_from_type ("hash_code",
   1620                                             &td.details.policy_details.
   1621                                             hash_code),
   1622       GNUNET_PQ_result_spec_allow_null (
   1623         TALER_PQ_result_spec_json ("policy_json",
   1624                                    &td.details.policy_details.
   1625                                    policy_json),
   1626         &td.details.policy_details.no_policy_json),
   1627       GNUNET_PQ_result_spec_timestamp ("deadline",
   1628                                        &td.details.policy_details.
   1629                                        deadline),
   1630       TALER_PQ_RESULT_SPEC_AMOUNT ("commitment",
   1631                                    &td.details.policy_details.
   1632                                    commitment),
   1633       TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total",
   1634                                    &td.details.policy_details.
   1635                                    accumulated_total),
   1636       TALER_PQ_RESULT_SPEC_AMOUNT ("fee",
   1637                                    &td.details.policy_details.
   1638                                    fee),
   1639       TALER_PQ_RESULT_SPEC_AMOUNT ("transferable",
   1640                                    &td.details.policy_details.
   1641                                    transferable),
   1642       GNUNET_PQ_result_spec_uint16 ("fulfillment_state",
   1643                                     &td.details.policy_details.
   1644                                     fulfillment_state),
   1645       GNUNET_PQ_result_spec_allow_null (
   1646         GNUNET_PQ_result_spec_uint64 ("fulfillment_id",
   1647                                       &td.details.policy_details.
   1648                                       fulfillment_id),
   1649         &td.details.policy_details.no_fulfillment_id),
   1650       GNUNET_PQ_result_spec_end
   1651     };
   1652 
   1653     if (GNUNET_OK !=
   1654         GNUNET_PQ_extract_result (result,
   1655                                   rs,
   1656                                   i))
   1657     {
   1658       GNUNET_break (0);
   1659       ctx->error = true;
   1660       return;
   1661     }
   1662     ctx->cb (ctx->cb_cls,
   1663              &td);
   1664     GNUNET_PQ_cleanup_result (rs);
   1665   }
   1666 }
   1667 
   1668 
   1669 /**
   1670  * Function called with policy_fulfillments table entries.
   1671  *
   1672  * @param cls closure
   1673  * @param result the postgres result
   1674  * @param num_results the number of results in @a result
   1675  */
   1676 static void
   1677 lrbt_cb_table_policy_fulfillments (void *cls,
   1678                                    PGresult *result,
   1679                                    unsigned int num_results)
   1680 {
   1681   struct LookupRecordsByTableContext *ctx = cls;
   1682   struct TALER_EXCHANGEDB_TableData td = {
   1683     .table = TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS
   1684   };
   1685 
   1686   for (unsigned int i = 0; i<num_results; i++)
   1687   {
   1688     bool no_proof = false;
   1689     bool no_timestamp = false;
   1690     struct GNUNET_PQ_ResultSpec rs[] = {
   1691       GNUNET_PQ_result_spec_uint64 ("fulfillment_id",
   1692                                     &td.serial),
   1693       GNUNET_PQ_result_spec_allow_null (
   1694         GNUNET_PQ_result_spec_timestamp ("fulfillment_timestamp",
   1695                                          &td.details.policy_fulfillments.
   1696                                          fulfillment_timestamp),
   1697         &no_timestamp),
   1698       GNUNET_PQ_result_spec_allow_null (
   1699         GNUNET_PQ_result_spec_string ("fulfillment_proof",
   1700                                       &td.details.policy_fulfillments.
   1701                                       fulfillment_proof),
   1702         &no_proof),
   1703       GNUNET_PQ_result_spec_end
   1704     };
   1705 
   1706     if (GNUNET_OK !=
   1707         GNUNET_PQ_extract_result (result,
   1708                                   rs,
   1709                                   i))
   1710     {
   1711       GNUNET_break (0);
   1712       ctx->error = true;
   1713       return;
   1714     }
   1715     ctx->cb (ctx->cb_cls,
   1716              &td);
   1717     GNUNET_PQ_cleanup_result (rs);
   1718   }
   1719 }
   1720 
   1721 
   1722 /**
   1723  * Function called with purse_requests table entries.
   1724  *
   1725  * @param cls closure
   1726  * @param result the postgres result
   1727  * @param num_results the number of results in @a result
   1728  */
   1729 static void
   1730 lrbt_cb_table_purse_requests (void *cls,
   1731                               PGresult *result,
   1732                               unsigned int num_results)
   1733 {
   1734   struct LookupRecordsByTableContext *ctx = cls;
   1735   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   1736   struct TALER_EXCHANGEDB_TableData td = {
   1737     .table = TALER_EXCHANGEDB_RT_PURSE_REQUESTS
   1738   };
   1739 
   1740   for (unsigned int i = 0; i<num_results; i++)
   1741   {
   1742     struct GNUNET_PQ_ResultSpec rs[] = {
   1743       GNUNET_PQ_result_spec_uint64 (
   1744         "purse_requests_serial_id",
   1745         &td.serial),
   1746       GNUNET_PQ_result_spec_auto_from_type (
   1747         "purse_pub",
   1748         &td.details.purse_requests.purse_pub),
   1749       GNUNET_PQ_result_spec_auto_from_type (
   1750         "merge_pub",
   1751         &td.details.purse_requests.merge_pub),
   1752       GNUNET_PQ_result_spec_timestamp (
   1753         "purse_creation",
   1754         &td.details.purse_requests.purse_creation),
   1755       GNUNET_PQ_result_spec_timestamp (
   1756         "purse_expiration",
   1757         &td.details.purse_requests.purse_expiration),
   1758       GNUNET_PQ_result_spec_auto_from_type (
   1759         "h_contract_terms",
   1760         &td.details.purse_requests.h_contract_terms),
   1761       GNUNET_PQ_result_spec_uint32 (
   1762         "age_limit",
   1763         &td.details.purse_requests.age_limit),
   1764       GNUNET_PQ_result_spec_uint32 (
   1765         "flags",
   1766         &td.details.purse_requests.flags),
   1767       TALER_PQ_RESULT_SPEC_AMOUNT (
   1768         "amount_with_fee",
   1769         &td.details.purse_requests.amount_with_fee),
   1770       TALER_PQ_RESULT_SPEC_AMOUNT (
   1771         "purse_fee",
   1772         &td.details.purse_requests.purse_fee),
   1773       GNUNET_PQ_result_spec_auto_from_type (
   1774         "purse_sig",
   1775         &td.details.purse_requests.purse_sig),
   1776       GNUNET_PQ_result_spec_end
   1777     };
   1778 
   1779     if (GNUNET_OK !=
   1780         GNUNET_PQ_extract_result (result,
   1781                                   rs,
   1782                                   i))
   1783     {
   1784       GNUNET_break (0);
   1785       ctx->error = true;
   1786       return;
   1787     }
   1788     ctx->cb (ctx->cb_cls,
   1789              &td);
   1790     GNUNET_PQ_cleanup_result (rs);
   1791   }
   1792 }
   1793 
   1794 
   1795 /**
   1796  * Function called with purse_decision table entries.
   1797  *
   1798  * @param cls closure
   1799  * @param result the postgres result
   1800  * @param num_results the number of results in @a result
   1801  */
   1802 static void
   1803 lrbt_cb_table_purse_decision (void *cls,
   1804                               PGresult *result,
   1805                               unsigned int num_results)
   1806 {
   1807   struct LookupRecordsByTableContext *ctx = cls;
   1808   struct TALER_EXCHANGEDB_TableData td = {
   1809     .table = TALER_EXCHANGEDB_RT_PURSE_DECISION
   1810   };
   1811 
   1812   for (unsigned int i = 0; i<num_results; i++)
   1813   {
   1814     struct GNUNET_PQ_ResultSpec rs[] = {
   1815       GNUNET_PQ_result_spec_uint64 (
   1816         "purse_refunds_serial_id",
   1817         &td.serial),
   1818       GNUNET_PQ_result_spec_auto_from_type (
   1819         "purse_pub",
   1820         &td.details.purse_decision.purse_pub),
   1821       GNUNET_PQ_result_spec_timestamp (
   1822         "action_timestamp",
   1823         &td.details.purse_decision.action_timestamp),
   1824       GNUNET_PQ_result_spec_bool (
   1825         "refunded",
   1826         &td.details.purse_decision.refunded),
   1827       GNUNET_PQ_result_spec_end
   1828     };
   1829 
   1830     if (GNUNET_OK !=
   1831         GNUNET_PQ_extract_result (result,
   1832                                   rs,
   1833                                   i))
   1834     {
   1835       GNUNET_break (0);
   1836       ctx->error = true;
   1837       return;
   1838     }
   1839     ctx->cb (ctx->cb_cls,
   1840              &td);
   1841     GNUNET_PQ_cleanup_result (rs);
   1842   }
   1843 }
   1844 
   1845 
   1846 /**
   1847  * Function called with purse_merges table entries.
   1848  *
   1849  * @param cls closure
   1850  * @param result the postgres result
   1851  * @param num_results the number of results in @a result
   1852  */
   1853 static void
   1854 lrbt_cb_table_purse_merges (void *cls,
   1855                             PGresult *result,
   1856                             unsigned int num_results)
   1857 {
   1858   struct LookupRecordsByTableContext *ctx = cls;
   1859   struct TALER_EXCHANGEDB_TableData td = {
   1860     .table = TALER_EXCHANGEDB_RT_PURSE_MERGES
   1861   };
   1862 
   1863   for (unsigned int i = 0; i<num_results; i++)
   1864   {
   1865     struct GNUNET_PQ_ResultSpec rs[] = {
   1866       GNUNET_PQ_result_spec_uint64 (
   1867         "purse_merge_request_serial_id",
   1868         &td.serial),
   1869       GNUNET_PQ_result_spec_uint64 (
   1870         "partner_serial_id",
   1871         &td.details.purse_merges.partner_serial_id),
   1872       GNUNET_PQ_result_spec_auto_from_type (
   1873         "reserve_pub",
   1874         &td.details.purse_merges.reserve_pub),
   1875       GNUNET_PQ_result_spec_auto_from_type (
   1876         "purse_pub",
   1877         &td.details.purse_merges.purse_pub),
   1878       GNUNET_PQ_result_spec_auto_from_type (
   1879         "merge_sig",
   1880         &td.details.purse_merges.merge_sig),
   1881       GNUNET_PQ_result_spec_timestamp (
   1882         "merge_timestamp",
   1883         &td.details.purse_merges.merge_timestamp),
   1884       GNUNET_PQ_result_spec_end
   1885     };
   1886 
   1887     if (GNUNET_OK !=
   1888         GNUNET_PQ_extract_result (result,
   1889                                   rs,
   1890                                   i))
   1891     {
   1892       GNUNET_break (0);
   1893       ctx->error = true;
   1894       return;
   1895     }
   1896     ctx->cb (ctx->cb_cls,
   1897              &td);
   1898     GNUNET_PQ_cleanup_result (rs);
   1899   }
   1900 }
   1901 
   1902 
   1903 /**
   1904  * Function called with purse_deposits table entries.
   1905  *
   1906  * @param cls closure
   1907  * @param result the postgres result
   1908  * @param num_results the number of results in @a result
   1909  */
   1910 static void
   1911 lrbt_cb_table_purse_deposits (void *cls,
   1912                               PGresult *result,
   1913                               unsigned int num_results)
   1914 {
   1915   struct LookupRecordsByTableContext *ctx = cls;
   1916   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   1917   struct TALER_EXCHANGEDB_TableData td = {
   1918     .table = TALER_EXCHANGEDB_RT_PURSE_DEPOSITS
   1919   };
   1920 
   1921   for (unsigned int i = 0; i<num_results; i++)
   1922   {
   1923     struct GNUNET_PQ_ResultSpec rs[] = {
   1924       GNUNET_PQ_result_spec_uint64 (
   1925         "purse_deposit_serial_id",
   1926         &td.serial),
   1927       GNUNET_PQ_result_spec_uint64 (
   1928         "partner_serial_id",
   1929         &td.details.purse_deposits.partner_serial_id),
   1930       GNUNET_PQ_result_spec_auto_from_type (
   1931         "purse_pub",
   1932         &td.details.purse_deposits.purse_pub),
   1933       GNUNET_PQ_result_spec_auto_from_type (
   1934         "coin_pub",
   1935         &td.details.purse_deposits.coin_pub),
   1936       TALER_PQ_RESULT_SPEC_AMOUNT (
   1937         "amount_with_fee",
   1938         &td.details.purse_deposits.amount_with_fee),
   1939       GNUNET_PQ_result_spec_auto_from_type (
   1940         "coin_sig",
   1941         &td.details.purse_deposits.coin_sig),
   1942       GNUNET_PQ_result_spec_end
   1943     };
   1944 
   1945     if (GNUNET_OK !=
   1946         GNUNET_PQ_extract_result (result,
   1947                                   rs,
   1948                                   i))
   1949     {
   1950       GNUNET_break (0);
   1951       ctx->error = true;
   1952       return;
   1953     }
   1954     ctx->cb (ctx->cb_cls,
   1955              &td);
   1956     GNUNET_PQ_cleanup_result (rs);
   1957   }
   1958 }
   1959 
   1960 
   1961 /**
   1962  * Function called with account_merges table entries.
   1963  *
   1964  * @param cls closure
   1965  * @param result the postgres result
   1966  * @param num_results the number of results in @a result
   1967  */
   1968 static void
   1969 lrbt_cb_table_account_merges (void *cls,
   1970                               PGresult *result,
   1971                               unsigned int num_results)
   1972 {
   1973   struct LookupRecordsByTableContext *ctx = cls;
   1974   struct TALER_EXCHANGEDB_TableData td = {
   1975     .table = TALER_EXCHANGEDB_RT_ACCOUNT_MERGES
   1976   };
   1977 
   1978   for (unsigned int i = 0; i<num_results; i++)
   1979   {
   1980     struct GNUNET_PQ_ResultSpec rs[] = {
   1981       GNUNET_PQ_result_spec_uint64 (
   1982         "account_merge_request_serial_id",
   1983         &td.serial),
   1984       GNUNET_PQ_result_spec_auto_from_type (
   1985         "reserve_pub",
   1986         &td.details.account_merges.reserve_pub),
   1987       GNUNET_PQ_result_spec_auto_from_type (
   1988         "reserve_sig",
   1989         &td.details.account_merges.reserve_sig),
   1990       GNUNET_PQ_result_spec_auto_from_type (
   1991         "purse_pub",
   1992         &td.details.account_merges.purse_pub),
   1993       GNUNET_PQ_result_spec_auto_from_type (
   1994         "wallet_h_payto",
   1995         &td.details.account_merges.wallet_h_payto),
   1996       GNUNET_PQ_result_spec_end
   1997     };
   1998 
   1999     if (GNUNET_OK !=
   2000         GNUNET_PQ_extract_result (result,
   2001                                   rs,
   2002                                   i))
   2003     {
   2004       GNUNET_break (0);
   2005       ctx->error = true;
   2006       return;
   2007     }
   2008     ctx->cb (ctx->cb_cls,
   2009              &td);
   2010     GNUNET_PQ_cleanup_result (rs);
   2011   }
   2012 }
   2013 
   2014 
   2015 /**
   2016  * Function called with history_requests table entries.
   2017  *
   2018  * @param cls closure
   2019  * @param result the postgres result
   2020  * @param num_results the number of results in @a result
   2021  */
   2022 static void
   2023 lrbt_cb_table_history_requests (void *cls,
   2024                                 PGresult *result,
   2025                                 unsigned int num_results)
   2026 {
   2027   struct LookupRecordsByTableContext *ctx = cls;
   2028   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   2029   struct TALER_EXCHANGEDB_TableData td = {
   2030     .table = TALER_EXCHANGEDB_RT_HISTORY_REQUESTS
   2031   };
   2032 
   2033   for (unsigned int i = 0; i<num_results; i++)
   2034   {
   2035     struct GNUNET_PQ_ResultSpec rs[] = {
   2036       GNUNET_PQ_result_spec_uint64 (
   2037         "history_request_serial_id",
   2038         &td.serial),
   2039       GNUNET_PQ_result_spec_auto_from_type (
   2040         "reserve_pub",
   2041         &td.details.history_requests.reserve_pub),
   2042       GNUNET_PQ_result_spec_auto_from_type (
   2043         "reserve_sig",
   2044         &td.details.history_requests.reserve_sig),
   2045       TALER_PQ_RESULT_SPEC_AMOUNT (
   2046         "history_fee",
   2047         &td.details.history_requests.history_fee),
   2048       GNUNET_PQ_result_spec_end
   2049     };
   2050 
   2051     if (GNUNET_OK !=
   2052         GNUNET_PQ_extract_result (result,
   2053                                   rs,
   2054                                   i))
   2055     {
   2056       GNUNET_break (0);
   2057       ctx->error = true;
   2058       return;
   2059     }
   2060     ctx->cb (ctx->cb_cls,
   2061              &td);
   2062     GNUNET_PQ_cleanup_result (rs);
   2063   }
   2064 }
   2065 
   2066 
   2067 /**
   2068  * Function called with close_requests table entries.
   2069  *
   2070  * @param cls closure
   2071  * @param result the postgres result
   2072  * @param num_results the number of results in @a result
   2073  */
   2074 static void
   2075 lrbt_cb_table_close_requests (void *cls,
   2076                               PGresult *result,
   2077                               unsigned int num_results)
   2078 {
   2079   struct LookupRecordsByTableContext *ctx = cls;
   2080   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   2081   struct TALER_EXCHANGEDB_TableData td = {
   2082     .table = TALER_EXCHANGEDB_RT_CLOSE_REQUESTS
   2083   };
   2084 
   2085   for (unsigned int i = 0; i<num_results; i++)
   2086   {
   2087     struct GNUNET_PQ_ResultSpec rs[] = {
   2088       GNUNET_PQ_result_spec_uint64 (
   2089         "close_request_serial_id",
   2090         &td.serial),
   2091       GNUNET_PQ_result_spec_auto_from_type (
   2092         "reserve_pub",
   2093         &td.details.close_requests.reserve_pub),
   2094       GNUNET_PQ_result_spec_timestamp (
   2095         "close_timestamp",
   2096         &td.details.close_requests.close_timestamp),
   2097       GNUNET_PQ_result_spec_auto_from_type (
   2098         "reserve_sig",
   2099         &td.details.close_requests.reserve_sig),
   2100       TALER_PQ_RESULT_SPEC_AMOUNT (
   2101         "close",
   2102         &td.details.close_requests.close),
   2103       TALER_PQ_RESULT_SPEC_AMOUNT (
   2104         "close_fee",
   2105         &td.details.close_requests.close_fee),
   2106       GNUNET_PQ_result_spec_string (
   2107         "payto_uri",
   2108         &td.details.close_requests.payto_uri.full_payto),
   2109       GNUNET_PQ_result_spec_end
   2110     };
   2111 
   2112     if (GNUNET_OK !=
   2113         GNUNET_PQ_extract_result (result,
   2114                                   rs,
   2115                                   i))
   2116     {
   2117       GNUNET_break (0);
   2118       ctx->error = true;
   2119       return;
   2120     }
   2121     ctx->cb (ctx->cb_cls,
   2122              &td);
   2123     GNUNET_PQ_cleanup_result (rs);
   2124   }
   2125 }
   2126 
   2127 
   2128 /**
   2129  * Function called with wads_out table entries.
   2130  *
   2131  * @param cls closure
   2132  * @param result the postgres result
   2133  * @param num_results the number of results in @a result
   2134  */
   2135 static void
   2136 lrbt_cb_table_wads_out (void *cls,
   2137                         PGresult *result,
   2138                         unsigned int num_results)
   2139 {
   2140   struct LookupRecordsByTableContext *ctx = cls;
   2141   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   2142   struct TALER_EXCHANGEDB_TableData td = {
   2143     .table = TALER_EXCHANGEDB_RT_WADS_OUT
   2144   };
   2145 
   2146   for (unsigned int i = 0; i<num_results; i++)
   2147   {
   2148     struct GNUNET_PQ_ResultSpec rs[] = {
   2149       GNUNET_PQ_result_spec_uint64 (
   2150         "wad_out_serial_id",
   2151         &td.serial),
   2152       GNUNET_PQ_result_spec_auto_from_type (
   2153         "wad_id",
   2154         &td.details.wads_out.wad_id),
   2155       GNUNET_PQ_result_spec_uint64 (
   2156         "partner_serial_id",
   2157         &td.details.wads_out.partner_serial_id),
   2158       TALER_PQ_RESULT_SPEC_AMOUNT (
   2159         "amount",
   2160         &td.details.wads_out.amount),
   2161       GNUNET_PQ_result_spec_timestamp (
   2162         "execution_time",
   2163         &td.details.wads_out.execution_time),
   2164       GNUNET_PQ_result_spec_end
   2165     };
   2166 
   2167     if (GNUNET_OK !=
   2168         GNUNET_PQ_extract_result (result,
   2169                                   rs,
   2170                                   i))
   2171     {
   2172       GNUNET_break (0);
   2173       ctx->error = true;
   2174       return;
   2175     }
   2176     ctx->cb (ctx->cb_cls,
   2177              &td);
   2178     GNUNET_PQ_cleanup_result (rs);
   2179   }
   2180 }
   2181 
   2182 
   2183 /**
   2184  * Function called with wads_out_entries table entries.
   2185  *
   2186  * @param cls closure
   2187  * @param result the postgres result
   2188  * @param num_results the number of results in @a result
   2189  */
   2190 static void
   2191 lrbt_cb_table_wads_out_entries (void *cls,
   2192                                 PGresult *result,
   2193                                 unsigned int num_results)
   2194 {
   2195   struct LookupRecordsByTableContext *ctx = cls;
   2196   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   2197   struct TALER_EXCHANGEDB_TableData td = {
   2198     .table = TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES
   2199   };
   2200 
   2201   for (unsigned int i = 0; i<num_results; i++)
   2202   {
   2203     struct GNUNET_PQ_ResultSpec rs[] = {
   2204       GNUNET_PQ_result_spec_uint64 (
   2205         "wad_out_entry_serial_id",
   2206         &td.serial),
   2207       GNUNET_PQ_result_spec_auto_from_type (
   2208         "reserve_pub",
   2209         &td.details.wads_out_entries.reserve_pub),
   2210       GNUNET_PQ_result_spec_auto_from_type (
   2211         "purse_pub",
   2212         &td.details.wads_out_entries.purse_pub),
   2213       GNUNET_PQ_result_spec_auto_from_type (
   2214         "h_contract",
   2215         &td.details.wads_out_entries.h_contract),
   2216       GNUNET_PQ_result_spec_timestamp (
   2217         "purse_expiration",
   2218         &td.details.wads_out_entries.purse_expiration),
   2219       GNUNET_PQ_result_spec_timestamp (
   2220         "merge_timestamp",
   2221         &td.details.wads_out_entries.merge_timestamp),
   2222       TALER_PQ_RESULT_SPEC_AMOUNT (
   2223         "amount_with_fee",
   2224         &td.details.wads_out_entries.amount_with_fee),
   2225       TALER_PQ_RESULT_SPEC_AMOUNT (
   2226         "wad_fee",
   2227         &td.details.wads_out_entries.wad_fee),
   2228       TALER_PQ_RESULT_SPEC_AMOUNT (
   2229         "deposit_fees",
   2230         &td.details.wads_out_entries.deposit_fees),
   2231       GNUNET_PQ_result_spec_auto_from_type (
   2232         "reserve_sig",
   2233         &td.details.wads_out_entries.reserve_sig),
   2234       GNUNET_PQ_result_spec_auto_from_type (
   2235         "purse_sig",
   2236         &td.details.wads_out_entries.purse_sig),
   2237       GNUNET_PQ_result_spec_end
   2238     };
   2239 
   2240     if (GNUNET_OK !=
   2241         GNUNET_PQ_extract_result (result,
   2242                                   rs,
   2243                                   i))
   2244     {
   2245       GNUNET_break (0);
   2246       ctx->error = true;
   2247       return;
   2248     }
   2249     ctx->cb (ctx->cb_cls,
   2250              &td);
   2251     GNUNET_PQ_cleanup_result (rs);
   2252   }
   2253 }
   2254 
   2255 
   2256 /**
   2257  * Function called with wads_in table entries.
   2258  *
   2259  * @param cls closure
   2260  * @param result the postgres result
   2261  * @param num_results the number of results in @a result
   2262  */
   2263 static void
   2264 lrbt_cb_table_wads_in (void *cls,
   2265                        PGresult *result,
   2266                        unsigned int num_results)
   2267 {
   2268   struct LookupRecordsByTableContext *ctx = cls;
   2269   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   2270   struct TALER_EXCHANGEDB_TableData td = {
   2271     .table = TALER_EXCHANGEDB_RT_WADS_IN
   2272   };
   2273 
   2274   for (unsigned int i = 0; i<num_results; i++)
   2275   {
   2276     struct GNUNET_PQ_ResultSpec rs[] = {
   2277       GNUNET_PQ_result_spec_uint64 (
   2278         "wad_in_serial_id",
   2279         &td.serial),
   2280       GNUNET_PQ_result_spec_auto_from_type (
   2281         "wad_id",
   2282         &td.details.wads_in.wad_id),
   2283       GNUNET_PQ_result_spec_string (
   2284         "origin_exchange_url",
   2285         &td.details.wads_in.origin_exchange_url),
   2286       TALER_PQ_RESULT_SPEC_AMOUNT (
   2287         "amount",
   2288         &td.details.wads_in.amount),
   2289       GNUNET_PQ_result_spec_timestamp (
   2290         "arrival_time",
   2291         &td.details.wads_in.arrival_time),
   2292       GNUNET_PQ_result_spec_end
   2293     };
   2294 
   2295     if (GNUNET_OK !=
   2296         GNUNET_PQ_extract_result (result,
   2297                                   rs,
   2298                                   i))
   2299     {
   2300       GNUNET_break (0);
   2301       ctx->error = true;
   2302       return;
   2303     }
   2304     ctx->cb (ctx->cb_cls,
   2305              &td);
   2306     GNUNET_PQ_cleanup_result (rs);
   2307   }
   2308 }
   2309 
   2310 
   2311 /**
   2312  * Function called with wads_in_entries table entries.
   2313  *
   2314  * @param cls closure
   2315  * @param result the postgres result
   2316  * @param num_results the number of results in @a result
   2317  */
   2318 static void
   2319 lrbt_cb_table_wads_in_entries (void *cls,
   2320                                PGresult *result,
   2321                                unsigned int num_results)
   2322 {
   2323   struct LookupRecordsByTableContext *ctx = cls;
   2324   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   2325   struct TALER_EXCHANGEDB_TableData td = {
   2326     .table = TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES
   2327   };
   2328 
   2329   for (unsigned int i = 0; i<num_results; i++)
   2330   {
   2331     struct GNUNET_PQ_ResultSpec rs[] = {
   2332       GNUNET_PQ_result_spec_uint64 (
   2333         "wad_in_entry_serial_id",
   2334         &td.serial),
   2335       GNUNET_PQ_result_spec_auto_from_type (
   2336         "reserve_pub",
   2337         &td.details.wads_in_entries.reserve_pub),
   2338       GNUNET_PQ_result_spec_auto_from_type (
   2339         "purse_pub",
   2340         &td.details.wads_in_entries.purse_pub),
   2341       GNUNET_PQ_result_spec_auto_from_type (
   2342         "h_contract",
   2343         &td.details.wads_in_entries.h_contract),
   2344       GNUNET_PQ_result_spec_timestamp (
   2345         "purse_expiration",
   2346         &td.details.wads_in_entries.purse_expiration),
   2347       GNUNET_PQ_result_spec_timestamp (
   2348         "merge_timestamp",
   2349         &td.details.wads_in_entries.merge_timestamp),
   2350       TALER_PQ_RESULT_SPEC_AMOUNT (
   2351         "amount_with_fee",
   2352         &td.details.wads_in_entries.amount_with_fee),
   2353       TALER_PQ_RESULT_SPEC_AMOUNT (
   2354         "wad_fee",
   2355         &td.details.wads_in_entries.wad_fee),
   2356       TALER_PQ_RESULT_SPEC_AMOUNT (
   2357         "deposit_fees",
   2358         &td.details.wads_in_entries.deposit_fees),
   2359       GNUNET_PQ_result_spec_auto_from_type (
   2360         "reserve_sig",
   2361         &td.details.wads_in_entries.reserve_sig),
   2362       GNUNET_PQ_result_spec_auto_from_type (
   2363         "purse_sig",
   2364         &td.details.wads_in_entries.purse_sig),
   2365       GNUNET_PQ_result_spec_end
   2366     };
   2367 
   2368     if (GNUNET_OK !=
   2369         GNUNET_PQ_extract_result (result,
   2370                                   rs,
   2371                                   i))
   2372     {
   2373       GNUNET_break (0);
   2374       ctx->error = true;
   2375       return;
   2376     }
   2377     ctx->cb (ctx->cb_cls,
   2378              &td);
   2379     GNUNET_PQ_cleanup_result (rs);
   2380   }
   2381 }
   2382 
   2383 
   2384 /**
   2385  * Function called with profit_drains table entries.
   2386  *
   2387  * @param cls closure
   2388  * @param result the postgres result
   2389  * @param num_results the number of results in @a result
   2390  */
   2391 static void
   2392 lrbt_cb_table_profit_drains (void *cls,
   2393                              PGresult *result,
   2394                              unsigned int num_results)
   2395 {
   2396   struct LookupRecordsByTableContext *ctx = cls;
   2397   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   2398   struct TALER_EXCHANGEDB_TableData td = {
   2399     .table = TALER_EXCHANGEDB_RT_PROFIT_DRAINS
   2400   };
   2401 
   2402   for (unsigned int i = 0; i<num_results; i++)
   2403   {
   2404     struct GNUNET_PQ_ResultSpec rs[] = {
   2405       GNUNET_PQ_result_spec_uint64 (
   2406         "profit_drain_serial_id",
   2407         &td.serial),
   2408       GNUNET_PQ_result_spec_auto_from_type (
   2409         "wtid",
   2410         &td.details.profit_drains.wtid),
   2411       GNUNET_PQ_result_spec_string (
   2412         "account_section",
   2413         &td.details.profit_drains.account_section),
   2414       GNUNET_PQ_result_spec_string (
   2415         "payto_uri",
   2416         &td.details.profit_drains.payto_uri.full_payto),
   2417       GNUNET_PQ_result_spec_timestamp (
   2418         "trigger_date",
   2419         &td.details.profit_drains.trigger_date),
   2420       TALER_PQ_RESULT_SPEC_AMOUNT (
   2421         "amount",
   2422         &td.details.profit_drains.amount),
   2423       GNUNET_PQ_result_spec_auto_from_type (
   2424         "master_sig",
   2425         &td.details.profit_drains.master_sig),
   2426       GNUNET_PQ_result_spec_end
   2427     };
   2428 
   2429     if (GNUNET_OK !=
   2430         GNUNET_PQ_extract_result (result,
   2431                                   rs,
   2432                                   i))
   2433     {
   2434       GNUNET_break (0);
   2435       ctx->error = true;
   2436       return;
   2437     }
   2438     ctx->cb (ctx->cb_cls,
   2439              &td);
   2440     GNUNET_PQ_cleanup_result (rs);
   2441   }
   2442 }
   2443 
   2444 
   2445 /**
   2446  * Function called with aml_staff table entries.
   2447  *
   2448  * @param cls closure
   2449  * @param result the postgres result
   2450  * @param num_results the number of results in @a result
   2451  */
   2452 static void
   2453 lrbt_cb_table_aml_staff (void *cls,
   2454                          PGresult *result,
   2455                          unsigned int num_results)
   2456 {
   2457   struct LookupRecordsByTableContext *ctx = cls;
   2458   struct TALER_EXCHANGEDB_TableData td = {
   2459     .table = TALER_EXCHANGEDB_RT_AML_STAFF
   2460   };
   2461 
   2462   for (unsigned int i = 0; i<num_results; i++)
   2463   {
   2464     struct GNUNET_PQ_ResultSpec rs[] = {
   2465       GNUNET_PQ_result_spec_uint64 (
   2466         "aml_staff_uuid",
   2467         &td.serial),
   2468       GNUNET_PQ_result_spec_auto_from_type (
   2469         "decider_pub",
   2470         &td.details.aml_staff.decider_pub),
   2471       GNUNET_PQ_result_spec_auto_from_type (
   2472         "master_sig",
   2473         &td.details.aml_staff.master_sig),
   2474       GNUNET_PQ_result_spec_string (
   2475         "decider_name",
   2476         &td.details.aml_staff.decider_name),
   2477       GNUNET_PQ_result_spec_bool (
   2478         "is_active",
   2479         &td.details.aml_staff.is_active),
   2480       GNUNET_PQ_result_spec_bool (
   2481         "read_only",
   2482         &td.details.aml_staff.read_only),
   2483       GNUNET_PQ_result_spec_timestamp (
   2484         "last_change",
   2485         &td.details.aml_staff.last_change),
   2486       GNUNET_PQ_result_spec_end
   2487     };
   2488 
   2489     if (GNUNET_OK !=
   2490         GNUNET_PQ_extract_result (result,
   2491                                   rs,
   2492                                   i))
   2493     {
   2494       GNUNET_break (0);
   2495       ctx->error = true;
   2496       return;
   2497     }
   2498     ctx->cb (ctx->cb_cls,
   2499              &td);
   2500     GNUNET_PQ_cleanup_result (rs);
   2501   }
   2502 }
   2503 
   2504 
   2505 /**
   2506  * Function called with purse_deletion table entries.
   2507  *
   2508  * @param cls closure
   2509  * @param result the postgres result
   2510  * @param num_results the number of results in @a result
   2511  */
   2512 static void
   2513 lrbt_cb_table_purse_deletion (void *cls,
   2514                               PGresult *result,
   2515                               unsigned int num_results)
   2516 {
   2517   struct LookupRecordsByTableContext *ctx = cls;
   2518   struct TALER_EXCHANGEDB_TableData td = {
   2519     .table = TALER_EXCHANGEDB_RT_PURSE_DELETION
   2520   };
   2521 
   2522   for (unsigned int i = 0; i<num_results; i++)
   2523   {
   2524     struct GNUNET_PQ_ResultSpec rs[] = {
   2525       GNUNET_PQ_result_spec_uint64 (
   2526         "purse_deletion_serial_id",
   2527         &td.serial),
   2528       GNUNET_PQ_result_spec_auto_from_type (
   2529         "purse_sig",
   2530         &td.details.purse_deletion.purse_sig),
   2531       GNUNET_PQ_result_spec_auto_from_type (
   2532         "purse_pub",
   2533         &td.details.purse_deletion.purse_pub),
   2534       GNUNET_PQ_result_spec_end
   2535     };
   2536 
   2537     if (GNUNET_OK !=
   2538         GNUNET_PQ_extract_result (result,
   2539                                   rs,
   2540                                   i))
   2541     {
   2542       GNUNET_break (0);
   2543       ctx->error = true;
   2544       return;
   2545     }
   2546     ctx->cb (ctx->cb_cls,
   2547              &td);
   2548     GNUNET_PQ_cleanup_result (rs);
   2549   }
   2550 }
   2551 
   2552 
   2553 /**
   2554  * Function called with withdraw table entries.
   2555  *
   2556  * @param cls closure
   2557  * @param result the postgres result
   2558  * @param num_results the number of results in @a result
   2559  */
   2560 static void
   2561 lrbt_cb_table_withdraw (void *cls,
   2562                         PGresult *result,
   2563                         unsigned int num_results)
   2564 {
   2565   struct LookupRecordsByTableContext *ctx = cls;
   2566   struct TALER_EXCHANGEDB_PostgresContext *pg = ctx->pg;
   2567   struct TALER_EXCHANGEDB_TableData td = {
   2568     .table = TALER_EXCHANGEDB_RT_WITHDRAW
   2569   };
   2570 
   2571   for (unsigned int i = 0; i<num_results; i++)
   2572   {
   2573     bool no_max_age;
   2574     bool no_noreveal_index;
   2575     bool no_selected_h;
   2576     bool no_cs_r_values;
   2577     bool no_cs_r_choices;
   2578     size_t num_sigs;
   2579     struct GNUNET_PQ_ResultSpec rs[] = {
   2580       GNUNET_PQ_result_spec_uint64 (
   2581         "withdraw_id",
   2582         &td.serial),
   2583       GNUNET_PQ_result_spec_auto_from_type (
   2584         "planchets_h",
   2585         &td.details.withdraw.planchets_h),
   2586       GNUNET_PQ_result_spec_timestamp (
   2587         "execution_date",
   2588         &td.details.withdraw.execution_date),
   2589       TALER_PQ_RESULT_SPEC_AMOUNT (
   2590         "amount_with_fee",
   2591         &td.details.withdraw.amount_with_fee),
   2592       GNUNET_PQ_result_spec_auto_from_type (
   2593         "reserve_pub",
   2594         &td.details.withdraw.reserve_pub),
   2595       GNUNET_PQ_result_spec_auto_from_type (
   2596         "reserve_sig",
   2597         &td.details.withdraw.reserve_sig),
   2598       GNUNET_PQ_result_spec_allow_null (
   2599         GNUNET_PQ_result_spec_uint16 (
   2600           "max_age",
   2601           &td.details.withdraw.max_age),
   2602         &no_max_age),
   2603       GNUNET_PQ_result_spec_allow_null (
   2604         GNUNET_PQ_result_spec_uint16 (
   2605           "noreveal_index",
   2606           &td.details.withdraw.noreveal_index),
   2607         &no_noreveal_index),
   2608       GNUNET_PQ_result_spec_allow_null (
   2609         GNUNET_PQ_result_spec_auto_from_type (
   2610           "selected_h",
   2611           &td.details.withdraw.selected_h),
   2612         &no_selected_h),
   2613       GNUNET_PQ_result_spec_allow_null (
   2614         GNUNET_PQ_result_spec_auto_from_type (
   2615           "blinding_seed",
   2616           &td.details.withdraw.blinding_seed),
   2617         &td.details.withdraw.no_blinding_seed),
   2618       GNUNET_PQ_result_spec_allow_null (
   2619         TALER_PQ_result_spec_array_cs_r_pub (
   2620           pg->conn,
   2621           "cs_r_values",
   2622           &td.details.withdraw.num_cs_r_values,
   2623           &td.details.withdraw.cs_r_values),
   2624         &no_cs_r_values),
   2625       GNUNET_PQ_result_spec_allow_null (
   2626         GNUNET_PQ_result_spec_uint64 (
   2627           "cs_r_choices",
   2628           &td.details.withdraw.cs_r_choices),
   2629         &no_cs_r_choices),
   2630       GNUNET_PQ_result_spec_array_uint64 (
   2631         pg->conn,
   2632         "denom_serials",
   2633         &td.details.withdraw.num_coins,
   2634         &td.details.withdraw.denom_serials),
   2635       TALER_PQ_result_spec_array_blinded_denom_sig (
   2636         pg->conn,
   2637         "denom_sigs",
   2638         &num_sigs,
   2639         &td.details.withdraw.denom_sigs),
   2640       GNUNET_PQ_result_spec_end
   2641     };
   2642 
   2643     if (GNUNET_OK !=
   2644         GNUNET_PQ_extract_result (result,
   2645                                   rs,
   2646                                   i))
   2647     {
   2648       GNUNET_break (0);
   2649       ctx->error = true;
   2650       GNUNET_PQ_cleanup_result (rs);
   2651       return;
   2652     }
   2653     if (num_sigs != td.details.withdraw.num_coins)
   2654     {
   2655       GNUNET_break (0);
   2656       ctx->error = true;
   2657       GNUNET_PQ_cleanup_result (rs);
   2658       return;
   2659     }
   2660     if (no_max_age != no_noreveal_index)
   2661     {
   2662       GNUNET_break (0);
   2663       ctx->error = true;
   2664       GNUNET_PQ_cleanup_result (rs);
   2665       return;
   2666     }
   2667     if (no_max_age != no_selected_h)
   2668     {
   2669       GNUNET_break (0);
   2670       ctx->error = true;
   2671       GNUNET_PQ_cleanup_result (rs);
   2672       return;
   2673     }
   2674     if (no_cs_r_values != no_cs_r_choices)
   2675     {
   2676       GNUNET_break (0);
   2677       ctx->error = true;
   2678       GNUNET_PQ_cleanup_result (rs);
   2679       return;
   2680     }
   2681     if (no_cs_r_values != td.details.withdraw.no_blinding_seed)
   2682     {
   2683       GNUNET_break (0);
   2684       ctx->error = true;
   2685       GNUNET_PQ_cleanup_result (rs);
   2686       return;
   2687     }
   2688     td.details.withdraw.age_proof_required = ! no_max_age;
   2689     ctx->cb (ctx->cb_cls,
   2690              &td);
   2691     GNUNET_PQ_cleanup_result (rs);
   2692   }
   2693 }
   2694 
   2695 
   2696 /**
   2697  * Function called with legitimization_measures table entries.
   2698  *
   2699  * @param cls closure
   2700  * @param result the postgres result
   2701  * @param num_results the number of results in @a result
   2702  */
   2703 static void
   2704 lrbt_cb_table_legitimization_measures (void *cls,
   2705                                        PGresult *result,
   2706                                        unsigned int num_results)
   2707 {
   2708   struct LookupRecordsByTableContext *ctx = cls;
   2709   struct TALER_EXCHANGEDB_TableData td = {
   2710     .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES
   2711   };
   2712 
   2713   for (unsigned int i = 0; i<num_results; i++)
   2714   {
   2715     struct GNUNET_PQ_ResultSpec rs[] = {
   2716       GNUNET_PQ_result_spec_uint64 ("serial",
   2717                                     &td.serial),
   2718       GNUNET_PQ_result_spec_auto_from_type (
   2719         "access_token",
   2720         &td.details.legitimization_measures.target_token),
   2721       GNUNET_PQ_result_spec_timestamp (
   2722         "start_time",
   2723         &td.details.legitimization_measures.start_time),
   2724       TALER_PQ_result_spec_json (
   2725         "jmeasures",
   2726         &td.details.legitimization_measures.measures),
   2727       GNUNET_PQ_result_spec_uint32 (
   2728         "display_priority",
   2729         &td.details.legitimization_measures.display_priority),
   2730       GNUNET_PQ_result_spec_end
   2731     };
   2732 
   2733     if (GNUNET_OK !=
   2734         GNUNET_PQ_extract_result (result,
   2735                                   rs,
   2736                                   i))
   2737     {
   2738       GNUNET_break (0);
   2739       ctx->error = true;
   2740       return;
   2741     }
   2742     ctx->cb (ctx->cb_cls,
   2743              &td);
   2744     GNUNET_PQ_cleanup_result (rs);
   2745   }
   2746 }
   2747 
   2748 
   2749 /**
   2750  * Function called with legitimization_outcomes table entries.
   2751  *
   2752  * @param cls closure
   2753  * @param result the postgres result
   2754  * @param num_results the number of results in @a result
   2755  */
   2756 static void
   2757 lrbt_cb_table_legitimization_outcomes (void *cls,
   2758                                        PGresult *result,
   2759                                        unsigned int num_results)
   2760 {
   2761   struct LookupRecordsByTableContext *ctx = cls;
   2762   struct TALER_EXCHANGEDB_TableData td = {
   2763     .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES
   2764   };
   2765 
   2766   for (unsigned int i = 0; i<num_results; i++)
   2767   {
   2768     struct GNUNET_PQ_ResultSpec rs[] = {
   2769       GNUNET_PQ_result_spec_uint64 ("serial",
   2770                                     &td.serial),
   2771       GNUNET_PQ_result_spec_auto_from_type (
   2772         "h_payto",
   2773         &td.details.legitimization_outcomes.h_payto),
   2774       GNUNET_PQ_result_spec_timestamp (
   2775         "decision_time",
   2776         &td.details.legitimization_outcomes.decision_time),
   2777       GNUNET_PQ_result_spec_timestamp (
   2778         "expiration_time",
   2779         &td.details.legitimization_outcomes.expiration_time),
   2780       GNUNET_PQ_result_spec_allow_null (
   2781         TALER_PQ_result_spec_json (
   2782           "jproperties",
   2783           &td.details.legitimization_outcomes.properties),
   2784         NULL),
   2785       GNUNET_PQ_result_spec_bool (
   2786         "to_investigate_id",
   2787         &td.details.legitimization_outcomes.to_investigate),
   2788       TALER_PQ_result_spec_json (
   2789         "jnew_rules",
   2790         &td.details.legitimization_outcomes.new_rules),
   2791       GNUNET_PQ_result_spec_end
   2792     };
   2793 
   2794     if (GNUNET_OK !=
   2795         GNUNET_PQ_extract_result (result,
   2796                                   rs,
   2797                                   i))
   2798     {
   2799       GNUNET_break (0);
   2800       ctx->error = true;
   2801       return;
   2802     }
   2803     ctx->cb (ctx->cb_cls,
   2804              &td);
   2805     GNUNET_PQ_cleanup_result (rs);
   2806   }
   2807 }
   2808 
   2809 
   2810 /**
   2811  * Function called with legitimization_processes table entries.
   2812  *
   2813  * @param cls closure
   2814  * @param result the postgres result
   2815  * @param num_results the number of results in @a result
   2816  */
   2817 static void
   2818 lrbt_cb_table_legitimization_processes (void *cls,
   2819                                         PGresult *result,
   2820                                         unsigned int num_results)
   2821 {
   2822   struct LookupRecordsByTableContext *ctx = cls;
   2823   struct TALER_EXCHANGEDB_TableData td = {
   2824     .table = TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES
   2825   };
   2826 
   2827   for (unsigned int i = 0; i<num_results; i++)
   2828   {
   2829     struct GNUNET_PQ_ResultSpec rs[] = {
   2830       GNUNET_PQ_result_spec_uint64 ("serial",
   2831                                     &td.serial),
   2832       GNUNET_PQ_result_spec_auto_from_type (
   2833         "h_payto",
   2834         &td.details.legitimization_processes.h_payto),
   2835       GNUNET_PQ_result_spec_timestamp (
   2836         "start_time",
   2837         &td.details.legitimization_processes.start_time),
   2838       GNUNET_PQ_result_spec_timestamp (
   2839         "expiration_time",
   2840         &td.details.legitimization_processes.expiration_time),
   2841       GNUNET_PQ_result_spec_uint64 (
   2842         "legitimization_measure_serial_id",
   2843         &td.details.legitimization_processes.legitimization_measure_serial_id),
   2844       GNUNET_PQ_result_spec_uint32 (
   2845         "measure_index",
   2846         &td.details.legitimization_processes.measure_index),
   2847       GNUNET_PQ_result_spec_string (
   2848         "provider_name",
   2849         &td.details.legitimization_processes.provider_name),
   2850       GNUNET_PQ_result_spec_string (
   2851         "provider_user_id",
   2852         &td.details.legitimization_processes.provider_user_id),
   2853       GNUNET_PQ_result_spec_string (
   2854         "provider_legitimization_id",
   2855         &td.details.legitimization_processes.provider_legitimization_id),
   2856       GNUNET_PQ_result_spec_string (
   2857         "redirect_url",
   2858         &td.details.legitimization_processes.redirect_url),
   2859       GNUNET_PQ_result_spec_end
   2860     };
   2861 
   2862     if (GNUNET_OK !=
   2863         GNUNET_PQ_extract_result (result,
   2864                                   rs,
   2865                                   i))
   2866     {
   2867       GNUNET_break (0);
   2868       ctx->error = true;
   2869       return;
   2870     }
   2871     ctx->cb (ctx->cb_cls,
   2872              &td);
   2873     GNUNET_PQ_cleanup_result (rs);
   2874   }
   2875 }
   2876 
   2877 
   2878 /**
   2879  * Function called with kyc_attributes table entries.
   2880  *
   2881  * @param cls closure
   2882  * @param result the postgres result
   2883  * @param num_results the number of results in @a result
   2884  */
   2885 static void
   2886 lrbt_cb_table_kyc_attributes (void *cls,
   2887                               PGresult *result,
   2888                               unsigned int num_results)
   2889 {
   2890   struct LookupRecordsByTableContext *ctx = cls;
   2891   struct TALER_EXCHANGEDB_TableData td = {
   2892     .table = TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES
   2893   };
   2894 
   2895   for (unsigned int i = 0; i<num_results; i++)
   2896   {
   2897     struct GNUNET_PQ_ResultSpec rs[] = {
   2898       GNUNET_PQ_result_spec_uint64 (
   2899         "kyc_attributes_serial_id",
   2900         &td.serial),
   2901       GNUNET_PQ_result_spec_auto_from_type (
   2902         "h_payto",
   2903         &td.details.kyc_attributes.h_payto),
   2904       GNUNET_PQ_result_spec_uint64 (
   2905         "legitimization_serial",
   2906         &td.details.kyc_attributes.legitimization_serial),
   2907       GNUNET_PQ_result_spec_timestamp (
   2908         "collection_time",
   2909         &td.details.kyc_attributes.collection_time),
   2910       GNUNET_PQ_result_spec_timestamp (
   2911         "expiration_time",
   2912         &td.details.kyc_attributes.expiration_time),
   2913       GNUNET_PQ_result_spec_uint64 (
   2914         "trigger_outcome_serial",
   2915         &td.details.kyc_attributes.trigger_outcome_serial),
   2916       GNUNET_PQ_result_spec_variable_size (
   2917         "encrypted_attributes",
   2918         &td.details.kyc_attributes.encrypted_attributes,
   2919         &td.details.kyc_attributes.encrypted_attributes_size),
   2920       GNUNET_PQ_result_spec_end
   2921     };
   2922 
   2923     if (GNUNET_OK !=
   2924         GNUNET_PQ_extract_result (result,
   2925                                   rs,
   2926                                   i))
   2927     {
   2928       GNUNET_break (0);
   2929       ctx->error = true;
   2930       return;
   2931     }
   2932     ctx->cb (ctx->cb_cls,
   2933              &td);
   2934     GNUNET_PQ_cleanup_result (rs);
   2935   }
   2936 }
   2937 
   2938 
   2939 /**
   2940  * Function called with aml_history table entries.
   2941  *
   2942  * @param cls closure
   2943  * @param result the postgres result
   2944  * @param num_results the number of results in @a result
   2945  */
   2946 static void
   2947 lrbt_cb_table_aml_history (void *cls,
   2948                            PGresult *result,
   2949                            unsigned int num_results)
   2950 {
   2951   struct LookupRecordsByTableContext *ctx = cls;
   2952   struct TALER_EXCHANGEDB_TableData td = {
   2953     .table = TALER_EXCHANGEDB_RT_AML_HISTORY
   2954   };
   2955 
   2956   for (unsigned int i = 0; i<num_results; i++)
   2957   {
   2958     struct GNUNET_PQ_ResultSpec rs[] = {
   2959       GNUNET_PQ_result_spec_uint64 (
   2960         "aml_history_serial_id",
   2961         &td.serial),
   2962       GNUNET_PQ_result_spec_auto_from_type (
   2963         "h_payto",
   2964         &td.details.aml_history.h_payto),
   2965       GNUNET_PQ_result_spec_uint64 (
   2966         "outcome_serial_id",
   2967         &td.details.aml_history.outcome_serial_id),
   2968       GNUNET_PQ_result_spec_string (
   2969         "justification",
   2970         &td.details.aml_history.justification),
   2971       GNUNET_PQ_result_spec_auto_from_type (
   2972         "decider_pub",
   2973         &td.details.aml_history.decider_pub),
   2974       GNUNET_PQ_result_spec_auto_from_type (
   2975         "decider_sig",
   2976         &td.details.aml_history.decider_sig),
   2977       GNUNET_PQ_result_spec_end
   2978     };
   2979 
   2980     if (GNUNET_OK !=
   2981         GNUNET_PQ_extract_result (result,
   2982                                   rs,
   2983                                   i))
   2984     {
   2985       GNUNET_break (0);
   2986       ctx->error = true;
   2987       return;
   2988     }
   2989     ctx->cb (ctx->cb_cls,
   2990              &td);
   2991     GNUNET_PQ_cleanup_result (rs);
   2992   }
   2993 }
   2994 
   2995 
   2996 /**
   2997  * Function called with kyc_events table entries.
   2998  *
   2999  * @param cls closure
   3000  * @param result the postgres result
   3001  * @param num_results the number of results in @a result
   3002  */
   3003 static void
   3004 lrbt_cb_table_kyc_events (void *cls,
   3005                           PGresult *result,
   3006                           unsigned int num_results)
   3007 {
   3008   struct LookupRecordsByTableContext *ctx = cls;
   3009   struct TALER_EXCHANGEDB_TableData td = {
   3010     .table = TALER_EXCHANGEDB_RT_KYC_EVENTS
   3011   };
   3012 
   3013   for (unsigned int i = 0; i<num_results; i++)
   3014   {
   3015     struct GNUNET_PQ_ResultSpec rs[] = {
   3016       GNUNET_PQ_result_spec_uint64 (
   3017         "kyc_event_serial_id",
   3018         &td.serial),
   3019       GNUNET_PQ_result_spec_timestamp (
   3020         "event_timestamp",
   3021         &td.details.kyc_events.event_timestamp),
   3022       GNUNET_PQ_result_spec_string (
   3023         "event_type",
   3024         &td.details.kyc_events.event_type),
   3025       GNUNET_PQ_result_spec_end
   3026     };
   3027 
   3028     if (GNUNET_OK !=
   3029         GNUNET_PQ_extract_result (result,
   3030                                   rs,
   3031                                   i))
   3032     {
   3033       GNUNET_break (0);
   3034       ctx->error = true;
   3035       return;
   3036     }
   3037     ctx->cb (ctx->cb_cls,
   3038              &td);
   3039     GNUNET_PQ_cleanup_result (rs);
   3040   }
   3041 }
   3042 
   3043 
   3044 /**
   3045  * Assign statement to @a n and PREPARE
   3046  * @a sql under name @a n.
   3047  */
   3048 #define XPREPARE(n,sql) \
   3049         statement = n;        \
   3050         PREPARE (pg, n, sql);
   3051 
   3052 
   3053 enum GNUNET_DB_QueryStatus
   3054 TALER_EXCHANGEDB_lookup_records_by_table (
   3055   struct TALER_EXCHANGEDB_PostgresContext *pg,
   3056   enum TALER_EXCHANGEDB_ReplicatedTable table,
   3057   uint64_t serial,
   3058   TALER_EXCHANGEDB_ReplicationCallback cb,
   3059   void *cb_cls)
   3060 {
   3061   struct GNUNET_PQ_QueryParam params[] = {
   3062     GNUNET_PQ_query_param_uint64 (&serial),
   3063     GNUNET_PQ_query_param_end
   3064   };
   3065   struct LookupRecordsByTableContext ctx = {
   3066     .pg = pg,
   3067     .cb = cb,
   3068     .cb_cls = cb_cls
   3069   };
   3070   GNUNET_PQ_PostgresResultHandler rh = NULL;
   3071   const char *statement = NULL;
   3072   enum GNUNET_DB_QueryStatus qs;
   3073 
   3074   switch (table)
   3075   {
   3076   case TALER_EXCHANGEDB_RT_DENOMINATIONS:
   3077     XPREPARE ("select_above_serial_by_table_denominations",
   3078               "SELECT"
   3079               " denominations_serial AS serial"
   3080               ",denom_type"
   3081               ",denom_pub"
   3082               ",master_sig"
   3083               ",valid_from"
   3084               ",expire_withdraw"
   3085               ",expire_deposit"
   3086               ",expire_legal"
   3087               ",coin"
   3088               ",fee_withdraw"
   3089               ",fee_deposit"
   3090               ",fee_refresh"
   3091               ",fee_refund"
   3092               ",age_mask"
   3093               " FROM denominations"
   3094               " WHERE denominations_serial > $1"
   3095               " ORDER BY denominations_serial ASC;");
   3096     rh = &lrbt_cb_table_denominations;
   3097     break;
   3098   case TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS:
   3099     XPREPARE ("select_above_serial_by_table_denomination_revocations",
   3100               "SELECT"
   3101               " denom_revocations_serial_id AS serial"
   3102               ",master_sig"
   3103               ",denominations_serial"
   3104               " FROM denomination_revocations"
   3105               " WHERE denom_revocations_serial_id > $1"
   3106               " ORDER BY denom_revocations_serial_id ASC;");
   3107     rh = &lrbt_cb_table_denomination_revocations;
   3108     break;
   3109   case TALER_EXCHANGEDB_RT_WIRE_TARGETS:
   3110     XPREPARE ("select_above_serial_by_table_wire_targets",
   3111               "SELECT"
   3112               " wire_target_serial_id AS serial"
   3113               ",payto_uri"
   3114               " FROM wire_targets"
   3115               " WHERE wire_target_serial_id > $1"
   3116               " ORDER BY wire_target_serial_id ASC;");
   3117     rh = &lrbt_cb_table_wire_targets;
   3118     break;
   3119   case TALER_EXCHANGEDB_RT_KYC_TARGETS:
   3120     XPREPARE ("select_above_serial_by_table_kyc_targets",
   3121               "SELECT"
   3122               " kyc_target_serial_id AS serial"
   3123               ",h_normalized_payto"
   3124               ",access_token"
   3125               ",target_pub"
   3126               ",is_wallet"
   3127               " FROM kyc_targets"
   3128               " WHERE kyc_target_serial_id > $1"
   3129               " ORDER BY kyc_target_serial_id ASC;");
   3130     rh = &lrbt_cb_table_kyc_targets;
   3131     break;
   3132   case TALER_EXCHANGEDB_RT_RESERVES:
   3133     XPREPARE ("select_above_serial_by_table_reserves",
   3134               "SELECT"
   3135               " reserve_uuid AS serial"
   3136               ",reserve_pub"
   3137               ",expiration_date"
   3138               ",gc_date"
   3139               " FROM reserves"
   3140               " WHERE reserve_uuid > $1"
   3141               " ORDER BY reserve_uuid ASC;");
   3142     rh = &lrbt_cb_table_reserves;
   3143     break;
   3144   case TALER_EXCHANGEDB_RT_RESERVES_IN:
   3145     XPREPARE ("select_above_serial_by_table_reserves_in",
   3146               "SELECT"
   3147               " reserve_in_serial_id AS serial"
   3148               ",reserve_pub"
   3149               ",wire_reference"
   3150               ",credit"
   3151               ",wire_source_h_payto"
   3152               ",exchange_account_section"
   3153               ",execution_date"
   3154               " FROM reserves_in"
   3155               " WHERE reserve_in_serial_id > $1"
   3156               " ORDER BY reserve_in_serial_id ASC;");
   3157     rh = &lrbt_cb_table_reserves_in;
   3158     break;
   3159   case TALER_EXCHANGEDB_RT_KYCAUTHS_IN:
   3160     XPREPARE ("select_above_serial_by_table_kycauth_in",
   3161               "SELECT"
   3162               " kycauth_in_serial_id AS serial"
   3163               ",account_pub"
   3164               ",wire_reference"
   3165               ",credit"
   3166               ",wire_source_h_payto"
   3167               ",exchange_account_section"
   3168               ",execution_date"
   3169               " FROM kycauths_in"
   3170               " WHERE kycauth_in_serial_id > $1"
   3171               " ORDER BY kycauth_in_serial_id ASC;");
   3172     rh = &lrbt_cb_table_kycauth_in;
   3173     break;
   3174   case TALER_EXCHANGEDB_RT_RESERVES_CLOSE:
   3175     XPREPARE ("select_above_serial_by_table_reserves_close",
   3176               "SELECT"
   3177               " close_uuid AS serial"
   3178               ",reserve_pub"
   3179               ",execution_date"
   3180               ",wtid"
   3181               ",wire_target_h_payto"
   3182               ",amount"
   3183               ",closing_fee"
   3184               " FROM reserves_close"
   3185               " WHERE close_uuid > $1"
   3186               " ORDER BY close_uuid ASC;");
   3187     rh = &lrbt_cb_table_reserves_close;
   3188     break;
   3189   case TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS:
   3190     XPREPARE ("select_above_serial_by_table_reserves_open_requests",
   3191               "SELECT"
   3192               " open_request_uuid AS serial"
   3193               ",reserve_pub"
   3194               ",request_timestamp"
   3195               ",expiration_date"
   3196               ",reserve_sig"
   3197               ",reserve_payment"
   3198               ",requested_purse_limit"
   3199               " FROM reserves_open_requests"
   3200               " WHERE open_request_uuid > $1"
   3201               " ORDER BY open_request_uuid ASC;");
   3202     rh = &lrbt_cb_table_reserves_open_requests;
   3203     break;
   3204   case TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS:
   3205     XPREPARE ("select_above_serial_by_table_reserves_open_deposits",
   3206               "SELECT"
   3207               " reserves_open_deposit_uuid AS serial"
   3208               ",reserve_sig"
   3209               ",reserve_pub"
   3210               ",coin_pub"
   3211               ",coin_sig"
   3212               ",contribution"
   3213               " FROM reserves_open_deposits"
   3214               " WHERE reserves_open_deposit_uuid > $1"
   3215               " ORDER BY reserves_open_deposit_uuid ASC;");
   3216     rh = &lrbt_cb_table_reserves_open_deposits;
   3217     break;
   3218   case TALER_EXCHANGEDB_RT_AUDITORS:
   3219     XPREPARE ("select_above_serial_by_table_auditors",
   3220               "SELECT"
   3221               " auditor_uuid AS serial"
   3222               ",auditor_pub"
   3223               ",auditor_name"
   3224               ",auditor_url"
   3225               ",is_active"
   3226               ",last_change"
   3227               " FROM auditors"
   3228               " WHERE auditor_uuid > $1"
   3229               " ORDER BY auditor_uuid ASC;");
   3230     rh = &lrbt_cb_table_auditors;
   3231     break;
   3232   case TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS:
   3233     XPREPARE ("select_above_serial_by_table_auditor_denom_sigs",
   3234               "SELECT"
   3235               " auditor_denom_serial AS serial"
   3236               ",auditor_uuid"
   3237               ",denominations_serial"
   3238               ",auditor_sig"
   3239               " FROM auditor_denom_sigs"
   3240               " WHERE auditor_denom_serial > $1"
   3241               " ORDER BY auditor_denom_serial ASC;");
   3242     rh = &lrbt_cb_table_auditor_denom_sigs;
   3243     break;
   3244   case TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS:
   3245     XPREPARE ("select_above_serial_by_table_exchange_sign_keys",
   3246               "SELECT"
   3247               " esk_serial AS serial"
   3248               ",exchange_pub"
   3249               ",master_sig"
   3250               ",valid_from"
   3251               ",expire_sign"
   3252               ",expire_legal"
   3253               " FROM exchange_sign_keys"
   3254               " WHERE esk_serial > $1"
   3255               " ORDER BY esk_serial ASC;");
   3256     rh = &lrbt_cb_table_exchange_sign_keys;
   3257     break;
   3258   case TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS:
   3259     XPREPARE ("select_above_serial_by_table_signkey_revocations",
   3260               "SELECT"
   3261               " signkey_revocations_serial_id AS serial"
   3262               ",esk_serial"
   3263               ",master_sig"
   3264               " FROM signkey_revocations"
   3265               " WHERE signkey_revocations_serial_id > $1"
   3266               " ORDER BY signkey_revocations_serial_id ASC;");
   3267     rh = &lrbt_cb_table_signkey_revocations;
   3268     break;
   3269   case TALER_EXCHANGEDB_RT_KNOWN_COINS:
   3270     XPREPARE ("select_above_serial_by_table_known_coins",
   3271               "SELECT"
   3272               " known_coin_id AS serial"
   3273               ",coin_pub"
   3274               ",denom_sig"
   3275               ",denominations_serial"
   3276               " FROM known_coins"
   3277               " WHERE known_coin_id > $1"
   3278               " ORDER BY known_coin_id ASC;");
   3279     rh = &lrbt_cb_table_known_coins;
   3280     break;
   3281   case TALER_EXCHANGEDB_RT_REFRESH:
   3282     XPREPARE ("select_above_serial_by_table_refresh",
   3283               "SELECT"
   3284               " refresh_id AS serial"
   3285               ",rc"
   3286               ",execution_date"
   3287               ",amount_with_fee"
   3288               ",old_coin_pub"
   3289               ",old_coin_sig"
   3290               ",refresh_seed"
   3291               ",noreveal_index"
   3292               ",planchets_h"
   3293               ",selected_h"
   3294               ",blinding_seed"
   3295               ",cs_r_values"
   3296               ",cs_r_choices"
   3297               ",denom_serials"
   3298               ",denom_sigs"
   3299               " FROM refresh"
   3300               " WHERE refresh_id > $1"
   3301               " ORDER BY refresh_id ASC;");
   3302     rh = &lrbt_cb_table_refresh;
   3303     break;
   3304   case TALER_EXCHANGEDB_RT_BATCH_DEPOSITS:
   3305     XPREPARE ("select_above_serial_by_table_batch_deposits",
   3306               "SELECT"
   3307               " batch_deposit_serial_id AS serial"
   3308               ",shard"
   3309               ",merchant_pub"
   3310               ",wallet_timestamp"
   3311               ",exchange_timestamp"
   3312               ",refund_deadline"
   3313               ",wire_deadline"
   3314               ",h_contract_terms"
   3315               ",wallet_data_hash"
   3316               ",wire_salt"
   3317               ",wire_target_h_payto"
   3318               ",policy_details_serial_id"
   3319               ",policy_blocked"
   3320               ",total_amount"
   3321               ",total_without_fee"
   3322               ",merchant_sig"
   3323               ",done"
   3324               " FROM batch_deposits"
   3325               " WHERE batch_deposit_serial_id > $1"
   3326               " ORDER BY batch_deposit_serial_id ASC;");
   3327     rh = &lrbt_cb_table_batch_deposits;
   3328     break;
   3329   case TALER_EXCHANGEDB_RT_COIN_DEPOSITS:
   3330     XPREPARE ("select_above_serial_by_table_coin_deposits",
   3331               "SELECT"
   3332               " coin_deposit_serial_id AS serial"
   3333               ",batch_deposit_serial_id"
   3334               ",coin_pub"
   3335               ",coin_sig"
   3336               ",amount_with_fee"
   3337               " FROM coin_deposits"
   3338               " WHERE coin_deposit_serial_id > $1"
   3339               " ORDER BY coin_deposit_serial_id ASC;");
   3340     rh = &lrbt_cb_table_coin_deposits;
   3341     break;
   3342   case TALER_EXCHANGEDB_RT_REFUNDS:
   3343     XPREPARE ("select_above_serial_by_table_refunds",
   3344               "SELECT"
   3345               " refund_serial_id AS serial"
   3346               ",coin_pub"
   3347               ",merchant_sig"
   3348               ",rtransaction_id"
   3349               ",amount_with_fee"
   3350               ",batch_deposit_serial_id"
   3351               " FROM refunds"
   3352               " WHERE refund_serial_id > $1"
   3353               " ORDER BY refund_serial_id ASC;");
   3354     rh = &lrbt_cb_table_refunds;
   3355     break;
   3356   case TALER_EXCHANGEDB_RT_WIRE_OUT:
   3357     XPREPARE ("select_above_serial_by_table_wire_out",
   3358               "SELECT"
   3359               " wireout_uuid AS serial"
   3360               ",execution_date"
   3361               ",wtid_raw"
   3362               ",wire_target_h_payto"
   3363               ",exchange_account_section"
   3364               ",amount"
   3365               " FROM wire_out"
   3366               " WHERE wireout_uuid > $1"
   3367               " ORDER BY wireout_uuid ASC;");
   3368     rh = &lrbt_cb_table_wire_out;
   3369     break;
   3370   case TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING:
   3371     XPREPARE ("select_above_serial_by_table_aggregation_tracking",
   3372               "SELECT"
   3373               " aggregation_serial_id AS serial"
   3374               ",batch_deposit_serial_id"
   3375               ",wtid_raw"
   3376               " FROM aggregation_tracking"
   3377               " WHERE aggregation_serial_id > $1"
   3378               " ORDER BY aggregation_serial_id ASC;");
   3379     rh = &lrbt_cb_table_aggregation_tracking;
   3380     break;
   3381   case TALER_EXCHANGEDB_RT_WIRE_FEE:
   3382     XPREPARE ("select_above_serial_by_table_wire_fee",
   3383               "SELECT"
   3384               " wire_fee_serial AS serial"
   3385               ",wire_method"
   3386               ",start_date"
   3387               ",end_date"
   3388               ",wire_fee"
   3389               ",closing_fee"
   3390               ",master_sig"
   3391               " FROM wire_fee"
   3392               " WHERE wire_fee_serial > $1"
   3393               " ORDER BY wire_fee_serial ASC;");
   3394     rh = &lrbt_cb_table_wire_fee;
   3395     break;
   3396   case TALER_EXCHANGEDB_RT_GLOBAL_FEE:
   3397     XPREPARE ("select_above_serial_by_table_global_fee",
   3398               "SELECT"
   3399               " global_fee_serial AS serial"
   3400               ",start_date"
   3401               ",end_date"
   3402               ",history_fee"
   3403               ",account_fee"
   3404               ",purse_fee"
   3405               ",purse_timeout"
   3406               ",history_expiration"
   3407               ",purse_account_limit"
   3408               ",master_sig"
   3409               " FROM global_fee"
   3410               " WHERE global_fee_serial > $1"
   3411               " ORDER BY global_fee_serial ASC;");
   3412     rh = &lrbt_cb_table_global_fee;
   3413     break;
   3414   case TALER_EXCHANGEDB_RT_RECOUP:
   3415     XPREPARE ("select_above_serial_by_table_recoup",
   3416               "SELECT"
   3417               " recoup_uuid AS serial"
   3418               ",coin_sig"
   3419               ",coin_blind"
   3420               ",amount"
   3421               ",recoup_timestamp"
   3422               ",coin_pub"
   3423               ",reserve_out_serial_id"
   3424               " FROM recoup"
   3425               " WHERE recoup_uuid > $1"
   3426               " ORDER BY recoup_uuid ASC;");
   3427     rh = &lrbt_cb_table_recoup;
   3428     break;
   3429   case TALER_EXCHANGEDB_RT_RECOUP_REFRESH:
   3430     XPREPARE ("select_above_serial_by_table_recoup_refresh",
   3431               "SELECT"
   3432               " recoup_refresh_uuid AS serial"
   3433               ",coin_sig"
   3434               ",coin_blind"
   3435               ",amount"
   3436               ",recoup_timestamp"
   3437               ",coin_pub"
   3438               ",known_coin_id"
   3439               ",rrc_serial"
   3440               " FROM recoup_refresh"
   3441               " WHERE recoup_refresh_uuid > $1"
   3442               " ORDER BY recoup_refresh_uuid ASC;");
   3443     rh = &lrbt_cb_table_recoup_refresh;
   3444     break;
   3445   case TALER_EXCHANGEDB_RT_EXTENSIONS:
   3446     // FIXME: this seems broken! -- where is the SQL!?
   3447     statement = "select_above_serial_by_table_extensions";
   3448     rh = &lrbt_cb_table_extensions;
   3449     break;
   3450   case TALER_EXCHANGEDB_RT_POLICY_DETAILS:
   3451     // FIXME: this seems broken! -- where is the SQL!?
   3452     statement = "select_above_serial_by_table_policy_details";
   3453     rh = &lrbt_cb_table_policy_details;
   3454     break;
   3455   case TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS:
   3456     // FIXME: this seems broken! -- where is the SQL!?
   3457     statement = "select_above_serial_by_table_policy_fulfillments";
   3458     rh = &lrbt_cb_table_policy_fulfillments;
   3459     break;
   3460   case TALER_EXCHANGEDB_RT_PURSE_REQUESTS:
   3461     XPREPARE ("select_above_serial_by_table_purse_requests",
   3462               "SELECT"
   3463               " purse_requests_serial_id"
   3464               ",purse_pub"
   3465               ",merge_pub"
   3466               ",purse_creation"
   3467               ",purse_expiration"
   3468               ",h_contract_terms"
   3469               ",age_limit"
   3470               ",flags"
   3471               ",amount_with_fee"
   3472               ",purse_fee"
   3473               ",purse_sig"
   3474               " FROM purse_requests"
   3475               " WHERE purse_requests_serial_id > $1"
   3476               " ORDER BY purse_requests_serial_id ASC;");
   3477     rh = &lrbt_cb_table_purse_requests;
   3478     break;
   3479   case TALER_EXCHANGEDB_RT_PURSE_DECISION:
   3480     XPREPARE ("select_above_serial_by_table_purse_decision",
   3481               "SELECT"
   3482               " purse_decision_serial_id"
   3483               ",action_timestamp"
   3484               ",refunded"
   3485               ",purse_pub"
   3486               " FROM purse_decision"
   3487               " WHERE purse_decision_serial_id > $1"
   3488               " ORDER BY purse_decision_serial_id ASC;");
   3489     rh = &lrbt_cb_table_purse_decision;
   3490     break;
   3491   case TALER_EXCHANGEDB_RT_PURSE_MERGES:
   3492     XPREPARE ("select_above_serial_by_table_purse_merges",
   3493               "SELECT"
   3494               " purse_merge_request_serial_id"
   3495               ",partner_serial_id"
   3496               ",reserve_pub"
   3497               ",purse_pub"
   3498               ",merge_sig"
   3499               ",merge_timestamp"
   3500               " FROM purse_merges"
   3501               " WHERE purse_merge_request_serial_id > $1"
   3502               " ORDER BY purse_merge_request_serial_id ASC;");
   3503     rh = &lrbt_cb_table_purse_merges;
   3504     break;
   3505   case TALER_EXCHANGEDB_RT_PURSE_DEPOSITS:
   3506     XPREPARE ("select_above_serial_by_table_purse_deposits",
   3507               "SELECT"
   3508               " purse_deposit_serial_id"
   3509               ",partner_serial_id"
   3510               ",purse_pub"
   3511               ",coin_pub"
   3512               ",amount_with_fee"
   3513               ",coin_sig"
   3514               " FROM purse_deposits"
   3515               " WHERE purse_deposit_serial_id > $1"
   3516               " ORDER BY purse_deposit_serial_id ASC;");
   3517     rh = &lrbt_cb_table_purse_deposits;
   3518     break;
   3519   case TALER_EXCHANGEDB_RT_ACCOUNT_MERGES:
   3520     XPREPARE ("select_above_serial_by_table_account_merges",
   3521               "SELECT"
   3522               " account_merge_request_serial_id"
   3523               ",reserve_pub"
   3524               ",reserve_sig"
   3525               ",purse_pub"
   3526               ",wallet_h_payto"
   3527               " FROM account_merges"
   3528               " WHERE account_merge_request_serial_id > $1"
   3529               " ORDER BY account_merge_request_serial_id ASC;");
   3530     rh = &lrbt_cb_table_account_merges;
   3531     break;
   3532   case TALER_EXCHANGEDB_RT_HISTORY_REQUESTS:
   3533     XPREPARE ("select_above_serial_by_table_history_requests",
   3534               "SELECT"
   3535               " history_request_serial_id"
   3536               ",reserve_pub"
   3537               ",request_timestamp"
   3538               ",reserve_sig"
   3539               ",history_fee"
   3540               " FROM history_requests"
   3541               " WHERE history_request_serial_id > $1"
   3542               " ORDER BY history_request_serial_id ASC;");
   3543     rh = &lrbt_cb_table_history_requests;
   3544     break;
   3545   case TALER_EXCHANGEDB_RT_CLOSE_REQUESTS:
   3546     XPREPARE ("select_above_serial_by_table_close_requests",
   3547               "SELECT"
   3548               " close_request_serial_id"
   3549               ",reserve_pub"
   3550               ",close_timestamp"
   3551               ",reserve_sig"
   3552               ",close"
   3553               " FROM close_requests"
   3554               " WHERE close_request_serial_id > $1"
   3555               " ORDER BY close_request_serial_id ASC;");
   3556     rh = &lrbt_cb_table_close_requests;
   3557     break;
   3558   case TALER_EXCHANGEDB_RT_WADS_OUT:
   3559     XPREPARE ("select_above_serial_by_table_wads_out",
   3560               "SELECT"
   3561               " wad_out_serial_id"
   3562               ",wad_id"
   3563               ",partner_serial_id"
   3564               ",amount"
   3565               ",execution_time"
   3566               " FROM wads_out"
   3567               " WHERE wad_out_serial_id > $1"
   3568               " ORDER BY wad_out_serial_id ASC;");
   3569     rh = &lrbt_cb_table_wads_out;
   3570     break;
   3571   case TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES:
   3572     XPREPARE ("select_above_serial_by_table_wads_out_entries",
   3573               "SELECT"
   3574               " wad_out_entry_serial_id"
   3575               ",reserve_pub"
   3576               ",purse_pub"
   3577               ",h_contract"
   3578               ",purse_expiration"
   3579               ",merge_timestamp"
   3580               ",amount_with_fee"
   3581               ",wad_fee"
   3582               ",deposit_fees"
   3583               ",reserve_sig"
   3584               ",purse_sig"
   3585               " FROM wad_out_entries"
   3586               " WHERE wad_out_entry_serial_id > $1"
   3587               " ORDER BY wad_out_entry_serial_id ASC;");
   3588     rh = &lrbt_cb_table_wads_out_entries;
   3589     break;
   3590   case TALER_EXCHANGEDB_RT_WADS_IN:
   3591     XPREPARE ("select_above_serial_by_table_wads_in",
   3592               "SELECT"
   3593               " wad_in_serial_id"
   3594               ",wad_id"
   3595               ",origin_exchange_url"
   3596               ",amount"
   3597               ",arrival_time"
   3598               " FROM wads_in"
   3599               " WHERE wad_in_serial_id > $1"
   3600               " ORDER BY wad_in_serial_id ASC;");
   3601     rh = &lrbt_cb_table_wads_in;
   3602     break;
   3603   case TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES:
   3604     XPREPARE ("select_above_serial_by_table_wads_in_entries",
   3605               "SELECT"
   3606               " wad_in_entry_serial_id"
   3607               ",reserve_pub"
   3608               ",purse_pub"
   3609               ",h_contract"
   3610               ",purse_expiration"
   3611               ",merge_timestamp"
   3612               ",amount_with_fee"
   3613               ",wad_fee"
   3614               ",deposit_fees"
   3615               ",reserve_sig"
   3616               ",purse_sig"
   3617               " FROM wad_in_entries"
   3618               " WHERE wad_in_entry_serial_id > $1"
   3619               " ORDER BY wad_in_entry_serial_id ASC;");
   3620     rh = &lrbt_cb_table_wads_in_entries;
   3621     break;
   3622   case TALER_EXCHANGEDB_RT_PROFIT_DRAINS:
   3623     XPREPARE ("select_above_serial_by_table_profit_drains",
   3624               "SELECT"
   3625               " profit_drain_serial_id"
   3626               ",wtid"
   3627               ",account_section"
   3628               ",payto_uri"
   3629               ",trigger_date"
   3630               ",amount"
   3631               ",master_sig"
   3632               " FROM profit_drains"
   3633               " WHERE profit_drain_serial_id > $1"
   3634               " ORDER BY profit_drain_serial_id ASC;");
   3635     rh = &lrbt_cb_table_profit_drains;
   3636     break;
   3637 
   3638   case TALER_EXCHANGEDB_RT_AML_STAFF:
   3639     XPREPARE ("select_above_serial_by_table_aml_staff",
   3640               "SELECT"
   3641               " aml_staff_uuid"
   3642               ",decider_pub"
   3643               ",master_sig"
   3644               ",decider_name"
   3645               ",is_active"
   3646               ",read_only"
   3647               ",last_change"
   3648               " FROM aml_staff"
   3649               " WHERE aml_staff_uuid > $1"
   3650               " ORDER BY aml_staff_uuid ASC;");
   3651     rh = &lrbt_cb_table_aml_staff;
   3652     break;
   3653   case TALER_EXCHANGEDB_RT_PURSE_DELETION:
   3654     XPREPARE ("select_above_serial_by_table_purse_deletion",
   3655               "SELECT"
   3656               " purse_deletion_serial_id"
   3657               ",purse_pub"
   3658               ",purse_sig"
   3659               " FROM purse_deletion"
   3660               " WHERE purse_deletion_serial_id > $1"
   3661               " ORDER BY purse_deletion_serial_id ASC;");
   3662     rh = &lrbt_cb_table_purse_deletion;
   3663     break;
   3664   case TALER_EXCHANGEDB_RT_WITHDRAW:
   3665     XPREPARE ("select_above_serial_by_table_withdraw",
   3666               "SELECT"
   3667               " withdraw_id"
   3668               ",planchets_h"
   3669               ",execution_date"
   3670               ",amount_with_fee"
   3671               ",reserve_pub"
   3672               ",reserve_sig"
   3673               ",max_age"
   3674               ",noreveal_index"
   3675               ",selected_h"
   3676               ",blinding_seed"
   3677               ",cs_r_values"
   3678               ",cs_r_choices"
   3679               ",denom_serials"
   3680               ",denom_sigs"
   3681               " FROM withdraw"
   3682               " WHERE withdraw_id > $1"
   3683               " ORDER BY withdraw_id ASC;");
   3684     rh = &lrbt_cb_table_withdraw;
   3685     break;
   3686   case TALER_EXCHANGEDB_RT_LEGITIMIZATION_MEASURES:
   3687     XPREPARE ("select_above_serial_by_table_legitimization_measures",
   3688               "SELECT"
   3689               " legitimization_measure_serial_id AS serial"
   3690               ",access_token"
   3691               ",start_time"
   3692               ",jmeasures::TEXT"
   3693               ",display_priority"
   3694               " FROM legitimization_measures"
   3695               " WHERE legitimization_measure_serial_id > $1"
   3696               " ORDER BY legitimization_measure_serial_id ASC;");
   3697     rh = &lrbt_cb_table_legitimization_measures;
   3698     break;
   3699   case TALER_EXCHANGEDB_RT_LEGITIMIZATION_OUTCOMES:
   3700     XPREPARE ("select_above_serial_by_table_legitimization_outcomes",
   3701               "SELECT"
   3702               " outcome_serial_id AS serial"
   3703               ",h_payto"
   3704               ",decision_time"
   3705               ",expiration_time"
   3706               ",jproperties::TEXT"
   3707               ",to_investigate"
   3708               ",jnew_rules::TEXT"
   3709               " FROM legitimization_outcomes"
   3710               " WHERE outcome_serial_id > $1"
   3711               " ORDER BY outcome_serial_id ASC;");
   3712     rh = &lrbt_cb_table_legitimization_outcomes;
   3713     break;
   3714   case TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES:
   3715     XPREPARE ("select_above_serial_by_table_legitimization_processes",
   3716               "SELECT"
   3717               " legitimization_process_serial_id AS serial"
   3718               ",h_payto"
   3719               ",start_time"
   3720               ",expiration_time"
   3721               ",legitimization_measure_serial_id"
   3722               ",measure_index"
   3723               ",provider_name"
   3724               ",provider_user_id"
   3725               ",provider_legitimization_id"
   3726               ",redirect_url"
   3727               " FROM legitimization_processes"
   3728               " WHERE legitimization_process_serial_id > $1"
   3729               " ORDER BY legitimization_process_serial_id ASC;");
   3730     rh = &lrbt_cb_table_legitimization_processes;
   3731     break;
   3732   case TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES:
   3733     XPREPARE ("select_above_serial_by_table_kyc_attributes",
   3734               "SELECT"
   3735               " kyc_attributes_serial_id"
   3736               ",h_payto"
   3737               ",legitimization_serial"
   3738               ",collection_time"
   3739               ",expiration_time"
   3740               ",trigger_outcome_serial"
   3741               ",encrypted_attributes"
   3742               " FROM kyc_attributes"
   3743               " WHERE kyc_attributes_serial_id > $1"
   3744               " ORDER BY kyc_attributes_serial_id ASC;");
   3745     rh = &lrbt_cb_table_kyc_attributes;
   3746     break;
   3747   case TALER_EXCHANGEDB_RT_AML_HISTORY:
   3748     XPREPARE ("select_above_serial_by_table_aml_history",
   3749               "SELECT"
   3750               " aml_history_serial_id"
   3751               ",h_payto"
   3752               ",outcome_serial_id"
   3753               ",justification"
   3754               ",decider_pub"
   3755               ",decider_sig"
   3756               " FROM aml_history"
   3757               " WHERE aml_history_serial_id > $1"
   3758               " ORDER BY aml_history_serial_id ASC;");
   3759     rh = &lrbt_cb_table_aml_history;
   3760     break;
   3761   case TALER_EXCHANGEDB_RT_KYC_EVENTS:
   3762     XPREPARE ("select_above_serial_by_table_kyc_events",
   3763               "SELECT"
   3764               " kyc_event_serial_id AS serial"
   3765               ",event_timestamp"
   3766               ",event_type"
   3767               " FROM kyc_events"
   3768               " WHERE kyc_event_serial_id > $1"
   3769               " ORDER BY kyc_event_serial_id ASC;");
   3770     rh = &lrbt_cb_table_kyc_events;
   3771     break;
   3772   }
   3773   if (NULL == rh)
   3774   {
   3775     GNUNET_break (0);
   3776     return GNUNET_DB_STATUS_HARD_ERROR;
   3777   }
   3778 
   3779   qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
   3780                                              statement,
   3781                                              params,
   3782                                              rh,
   3783                                              &ctx);
   3784   if (qs < 0)
   3785   {
   3786     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3787                 "Failed to run `%s'\n",
   3788                 statement);
   3789     return qs;
   3790   }
   3791   if (ctx.error)
   3792   {
   3793     GNUNET_break (0);
   3794     return GNUNET_DB_STATUS_HARD_ERROR;
   3795   }
   3796   return qs;
   3797 }
   3798 
   3799 
   3800 #undef XPREPARE
   3801 
   3802 /* end of pg_lookup_records_by_table.c */