merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

plugin_merchantdb_postgres.c (24496B)


      1 /*
      2   This file is part of TALER
      3   (C) 2014--2025 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Lesser General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file plugin_merchantdb_postgres.c
     18  * @brief database helper functions for postgres used by the merchant
     19  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
     20  * @author Christian Grothoff
     21  * @author Marcello Stanisci
     22  * @author Priscilla Huang
     23  * @author Iván Ávalos
     24  */
     25 #include "platform.h"
     26 #include <gnunet/gnunet_util_lib.h>
     27 #include <gnunet/gnunet_pq_lib.h>
     28 #include <taler/taler_util.h>
     29 #include <taler/taler_pq_lib.h>
     30 #include <taler/taler_json_lib.h>
     31 #include <taler/taler_mhd_lib.h>
     32 #include "taler_merchantdb_plugin.h"
     33 #include "pg_helper.h"
     34 #include "pg_gc.h"
     35 #include "pg_insert_otp.h"
     36 #include "pg_get_kyc_status.h"
     37 #include "pg_get_kyc_limits.h"
     38 #include "pg_delete_otp.h"
     39 #include "pg_update_otp.h"
     40 #include "pg_account_kyc_set_failed.h"
     41 #include "pg_select_otp.h"
     42 #include "pg_select_otp_serial.h"
     43 #include "pg_insert_login_token.h"
     44 #include "pg_delete_login_token.h"
     45 #include "pg_select_login_token.h"
     46 #include "pg_lookup_login_tokens.h"
     47 #include "pg_insert_account.h"
     48 #include "pg_update_account.h"
     49 #include "pg_lookup_instances.h"
     50 #include "pg_lookup_transfers.h"
     51 #include "pg_lookup_pending_deposits.h"
     52 #include "pg_lookup_categories.h"
     53 #include "pg_lookup_units.h"
     54 #include "pg_select_category.h"
     55 #include "pg_update_category.h"
     56 #include "pg_insert_category.h"
     57 #include "pg_delete_category.h"
     58 #include "pg_select_unit.h"
     59 #include "pg_insert_unit.h"
     60 #include "pg_update_unit.h"
     61 #include "pg_delete_unit.h"
     62 #include "pg_update_wirewatch_progress.h"
     63 #include "pg_select_wirewatch_accounts.h"
     64 #include "pg_select_open_transfers.h"
     65 #include "pg_delete_exchange_accounts.h"
     66 #include "pg_select_accounts_by_exchange.h"
     67 #include "pg_insert_exchange_account.h"
     68 #include "pg_lookup_instance_auth.h"
     69 #include "pg_lookup_otp_devices.h"
     70 #include "pg_update_transfer_status.h"
     71 #include "pg_lookup_mfa_challenge.h"
     72 #include "pg_solve_mfa_challenge.h"
     73 #include "pg_update_mfa_challenge.h"
     74 #include "pg_create_mfa_challenge.h"
     75 #include "pg_finalize_transfer_status.h"
     76 #include "pg_insert_instance.h"
     77 #include "pg_account_kyc_set_status.h"
     78 #include "pg_account_kyc_get_status.h"
     79 #include "pg_delete_instance_private_key.h"
     80 #include "pg_select_category_by_name.h"
     81 #include "pg_purge_instance.h"
     82 #include "pg_update_instance.h"
     83 #include "pg_update_instance_auth.h"
     84 #include "pg_inactivate_account.h"
     85 #include "pg_activate_account.h"
     86 #include "pg_lookup_products.h"
     87 #include "pg_lookup_all_products.h"
     88 #include "pg_lookup_product.h"
     89 #include "pg_lookup_product_image.h"
     90 #include "pg_delete_product.h"
     91 #include "pg_insert_product.h"
     92 #include "pg_update_product.h"
     93 #include "pg_lookup_token_family_keys.h"
     94 #include "pg_lock_product.h"
     95 #include "pg_expire_locks.h"
     96 #include "pg_delete_order.h"
     97 #include "pg_lookup_order.h"
     98 #include "pg_lookup_order_summary.h"
     99 #include "pg_lookup_orders.h"
    100 #include "pg_insert_order.h"
    101 #include "pg_insert_order_blinded_sigs.h"
    102 #include "pg_unlock_inventory.h"
    103 #include "pg_insert_order_lock.h"
    104 #include "pg_select_order_blinded_sigs.h"
    105 #include "pg_lookup_contract_terms3.h"
    106 #include "pg_lookup_contract_terms2.h"
    107 #include "pg_lookup_contract_terms.h"
    108 #include "pg_insert_contract_terms.h"
    109 #include "pg_update_contract_terms.h"
    110 #include "pg_delete_contract_terms.h"
    111 #include "pg_delete_template.h"
    112 #include "pg_insert_template.h"
    113 #include "pg_update_template.h"
    114 #include "pg_lookup_templates.h"
    115 #include "pg_lookup_template.h"
    116 #include "pg_lookup_deposits.h"
    117 #include "pg_insert_exchange_signkey.h"
    118 #include "pg_insert_deposit.h"
    119 #include "pg_insert_deposit_confirmation.h"
    120 #include "pg_lookup_refunds.h"
    121 #include "pg_mark_contract_paid.h"
    122 #include "pg_select_account_by_uri.h"
    123 #include "pg_refund_coin.h"
    124 #include "pg_lookup_order_status.h"
    125 #include "pg_lookup_order_status_by_serial.h"
    126 #include "pg_lookup_deposits_by_order.h"
    127 #include "pg_lookup_transfer_details_by_order.h"
    128 #include "pg_mark_order_wired.h"
    129 #include "pg_lookup_refunds_detailed.h"
    130 #include "pg_insert_refund_proof.h"
    131 #include "pg_lookup_refund_proof.h"
    132 #include "pg_lookup_order_by_fulfillment.h"
    133 #include "pg_delete_transfer.h"
    134 #include "pg_check_transfer_exists.h"
    135 #include "pg_lookup_account.h"
    136 #include "pg_lookup_expected_transfers.h"
    137 #include "pg_lookup_deposits_by_contract_and_coin.h"
    138 #include "pg_lookup_transfer_summary.h"
    139 #include "pg_lookup_transfer_details.h"
    140 #include "pg_lookup_webhooks.h"
    141 #include "pg_lookup_webhook.h"
    142 #include "pg_lookup_wire_fee.h"
    143 #include "pg_delete_webhook.h"
    144 #include "pg_insert_webhook.h"
    145 #include "pg_update_webhook.h"
    146 #include "pg_lookup_webhook_by_event.h"
    147 #include "pg_delete_pending_webhook.h"
    148 #include "pg_insert_pending_webhook.h"
    149 #include "pg_update_pending_webhook.h"
    150 #include "pg_lookup_pending_webhooks.h"
    151 #include "pg_update_deposit_confirmation_status.h"
    152 #include "pg_insert_exchange_keys.h"
    153 #include "pg_select_exchange_keys.h"
    154 #include "pg_insert_deposit_to_transfer.h"
    155 #include "pg_increase_refund.h"
    156 #include "pg_select_account.h"
    157 #include "pg_select_accounts.h"
    158 #include "pg_insert_transfer.h"
    159 #include "pg_insert_transfer_details.h"
    160 #include "pg_store_wire_fee_by_exchange.h"
    161 #include "pg_insert_token_family.h"
    162 #include "pg_lookup_token_family.h"
    163 #include "pg_lookup_token_families.h"
    164 #include "pg_delete_token_family.h"
    165 #include "pg_update_token_family.h"
    166 #include "pg_insert_token_family_key.h"
    167 #include "pg_lookup_token_family_key.h"
    168 #include "pg_insert_spent_token.h"
    169 #include "pg_insert_issued_token.h"
    170 #include "pg_lookup_spent_tokens_by_order.h"
    171 #include "pg_lookup_statistics_amount_by_bucket.h"
    172 #include "pg_lookup_statistics_amount_by_interval.h"
    173 #include "pg_lookup_statistics_counter_by_bucket.h"
    174 #include "pg_lookup_statistics_counter_by_interval.h"
    175 #include "pg_update_donau_instance_receipts_amount.h"
    176 #include "pg_delete_donau_instance.h"
    177 #include "pg_update_contract_session.h"
    178 
    179 #ifdef HAVE_DONAU_DONAU_SERVICE_H
    180 #include "donau/donau_service.h"
    181 #include "pg_insert_donau_instance.h"
    182 #include "pg_check_donau_instance.h"
    183 #include "pg_select_donau_instance_by_serial.h"
    184 #include "pg_select_all_donau_instances.h"
    185 #include "pg_select_donau_instances.h"
    186 #include "pg_select_donau_instances_filtered.h"
    187 #include "pg_lookup_donau_keys.h"
    188 #include "pg_lookup_order_charity.h"
    189 #include "pg_upsert_donau_keys.h"
    190 #include "pg_update_donau_instance.h"
    191 #endif
    192 
    193 /**
    194  * How often do we re-try if we run into a DB serialization error?
    195  */
    196 #define MAX_RETRIES 3
    197 
    198 
    199 /**
    200  * Drop all Taler tables.  This should only be used by testcases.
    201  *
    202  * @param cls the `struct PostgresClosure` with the plugin-specific state
    203  * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
    204  */
    205 static enum GNUNET_GenericReturnValue
    206 postgres_drop_tables (void *cls)
    207 {
    208   struct PostgresClosure *pc = cls;
    209   struct GNUNET_PQ_Context *conn;
    210   enum GNUNET_GenericReturnValue ret;
    211 
    212   conn = GNUNET_PQ_connect_with_cfg (pc->cfg,
    213                                      "merchantdb-postgres",
    214                                      NULL,
    215                                      NULL,
    216                                      NULL);
    217   if (NULL == conn)
    218     return GNUNET_SYSERR;
    219   ret = GNUNET_PQ_exec_sql (conn,
    220                             "drop");
    221   GNUNET_PQ_disconnect (conn);
    222   return ret;
    223 }
    224 
    225 
    226 /**
    227  * Initialize tables.
    228  *
    229  * @param cls the `struct PostgresClosure` with the plugin-specific state
    230  * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
    231  */
    232 static enum GNUNET_GenericReturnValue
    233 postgres_create_tables (void *cls)
    234 {
    235   struct PostgresClosure *pc = cls;
    236   struct GNUNET_PQ_Context *conn;
    237   struct GNUNET_PQ_ExecuteStatement es[] = {
    238     GNUNET_PQ_make_try_execute ("SET search_path TO merchant;"),
    239     GNUNET_PQ_EXECUTE_STATEMENT_END
    240   };
    241   enum GNUNET_GenericReturnValue ret;
    242 
    243   conn = GNUNET_PQ_connect_with_cfg (pc->cfg,
    244                                      "merchantdb-postgres",
    245                                      "merchant-",
    246                                      es,
    247                                      NULL);
    248   if (NULL == conn)
    249     return GNUNET_SYSERR;
    250   ret = GNUNET_PQ_exec_sql (conn,
    251                             "procedures");
    252   GNUNET_PQ_disconnect (conn);
    253   return ret;
    254 }
    255 
    256 
    257 /**
    258  * Register callback to be invoked on events of type @a es.
    259  *
    260  * @param cls database context to use
    261  * @param es specification of the event to listen for
    262  * @param timeout how long to wait for the event
    263  * @param cb function to call when the event happens, possibly
    264  *         multiple times (until cancel is invoked)
    265  * @param cb_cls closure for @a cb
    266  * @return handle useful to cancel the listener
    267  */
    268 static struct GNUNET_DB_EventHandler *
    269 postgres_event_listen (void *cls,
    270                        const struct GNUNET_DB_EventHeaderP *es,
    271                        struct GNUNET_TIME_Relative timeout,
    272                        GNUNET_DB_EventCallback cb,
    273                        void *cb_cls)
    274 {
    275   struct PostgresClosure *pg = cls;
    276 
    277   return GNUNET_PQ_event_listen (pg->conn,
    278                                  es,
    279                                  timeout,
    280                                  cb,
    281                                  cb_cls);
    282 }
    283 
    284 
    285 /**
    286  * Stop notifications.
    287  *
    288  * @param eh handle to unregister.
    289  */
    290 static void
    291 postgres_event_listen_cancel (struct GNUNET_DB_EventHandler *eh)
    292 {
    293   GNUNET_PQ_event_listen_cancel (eh);
    294 }
    295 
    296 
    297 /**
    298  * Notify all that listen on @a es of an event.
    299  *
    300  * @param cls database context to use
    301  * @param es specification of the event to generate
    302  * @param extra additional event data provided
    303  * @param extra_size number of bytes in @a extra
    304  */
    305 static void
    306 postgres_event_notify (void *cls,
    307                        const struct GNUNET_DB_EventHeaderP *es,
    308                        const void *extra,
    309                        size_t extra_size)
    310 {
    311   struct PostgresClosure *pg = cls;
    312 
    313   return GNUNET_PQ_event_notify (pg->conn,
    314                                  es,
    315                                  extra,
    316                                  extra_size);
    317 }
    318 
    319 
    320 void
    321 postgres_preflight (void *cls)
    322 {
    323   struct PostgresClosure *pg = cls;
    324 
    325   if (NULL == pg->transaction_name)
    326     return; /* all good */
    327   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    328               "BUG: Preflight check detected running transaction `%s'!\n",
    329               pg->transaction_name);
    330   GNUNET_assert (0);
    331 }
    332 
    333 
    334 void
    335 check_connection (struct PostgresClosure *pg)
    336 {
    337   if (NULL != pg->transaction_name)
    338     return;
    339   GNUNET_PQ_reconnect_if_down (pg->conn);
    340 }
    341 
    342 
    343 /**
    344  * Establish connection to the database.
    345  *
    346  * @param cls plugin context
    347  * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
    348  */
    349 static enum GNUNET_GenericReturnValue
    350 postgres_connect (void *cls)
    351 {
    352   struct PostgresClosure *pg = cls;
    353   struct GNUNET_PQ_ExecuteStatement es[] = {
    354     GNUNET_PQ_make_try_execute ("SET search_path TO merchant;"),
    355     GNUNET_PQ_EXECUTE_STATEMENT_END
    356   };
    357 
    358   pg->conn = GNUNET_PQ_connect_with_cfg2 (pg->cfg,
    359                                           "merchantdb-postgres",
    360                                           "merchant-",
    361                                           es,
    362                                           NULL, /* prepared statemetns */
    363                                           GNUNET_PQ_FLAG_CHECK_CURRENT);
    364   pg->prep_gen++;
    365   if (NULL == pg->conn)
    366     return GNUNET_SYSERR;
    367   return GNUNET_OK;
    368 };
    369 
    370 
    371 /**
    372  * Initialize Postgres database subsystem.
    373  *
    374  * @param cls a configuration instance
    375  * @return NULL on error, otherwise a `struct TALER_MERCHANTDB_Plugin`
    376  */
    377 void *
    378 libtaler_plugin_merchantdb_postgres_init (void *cls);
    379 
    380 /* declaration to avoid compiler warning */
    381 void *
    382 libtaler_plugin_merchantdb_postgres_init (void *cls)
    383 {
    384   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
    385   struct PostgresClosure *pg;
    386   struct TALER_MERCHANTDB_Plugin *plugin;
    387 
    388   pg = GNUNET_new (struct PostgresClosure);
    389   pg->cfg = cfg;
    390   if (GNUNET_OK !=
    391       GNUNET_CONFIGURATION_get_value_filename (cfg,
    392                                                "merchantdb-postgres",
    393                                                "SQL_DIR",
    394                                                &pg->sql_dir))
    395   {
    396     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    397                                "merchantdb-postgres",
    398                                "SQL_DIR");
    399     GNUNET_free (pg);
    400     return NULL;
    401   }
    402   plugin = GNUNET_new (struct TALER_MERCHANTDB_Plugin);
    403   plugin->cls = pg;
    404   plugin->connect = &postgres_connect;
    405   plugin->create_tables = &postgres_create_tables;
    406   plugin->drop_tables = &postgres_drop_tables;
    407   plugin->event_listen = &postgres_event_listen;
    408   plugin->event_listen_cancel = &postgres_event_listen_cancel;
    409   plugin->event_notify = &postgres_event_notify;
    410   plugin->preflight = &postgres_preflight;
    411   plugin->start = &TMH_PG_start;
    412   plugin->start_read_committed = &TMH_PG_start_read_committed;
    413   plugin->rollback = &TMH_PG_rollback;
    414   plugin->commit = &TMH_PG_commit;
    415   plugin->insert_login_token
    416     = &TMH_PG_insert_login_token;
    417   plugin->delete_login_token
    418     = &TMH_PG_delete_login_token;
    419   plugin->delete_login_token_serial
    420     = &TMH_PG_delete_login_token_serial;
    421   plugin->select_login_token
    422     = &TMH_PG_select_login_token;
    423   plugin->lookup_login_tokens
    424     = &TMH_PG_lookup_login_tokens;
    425   plugin->select_account_by_uri
    426     = &TMH_PG_select_account_by_uri;
    427   plugin->lookup_instance_auth
    428     = &TMH_PG_lookup_instance_auth;
    429   plugin->insert_instance
    430     = &TMH_PG_insert_instance;
    431   plugin->insert_account
    432     = &TMH_PG_insert_account;
    433   plugin->lookup_otp_devices
    434     = &TMH_PG_lookup_otp_devices;
    435   plugin->delete_template
    436     = &TMH_PG_delete_template;
    437   plugin->insert_template
    438     = &TMH_PG_insert_template;
    439   plugin->update_template
    440     = &TMH_PG_update_template;
    441   plugin->lookup_templates
    442     = &TMH_PG_lookup_templates;
    443   plugin->lookup_template
    444     = &TMH_PG_lookup_template;
    445   plugin->update_account
    446     = &TMH_PG_update_account;
    447   plugin->account_kyc_set_status
    448     = &TMH_PG_account_kyc_set_status;
    449   plugin->account_kyc_get_status
    450     = &TMH_PG_account_kyc_get_status;
    451   plugin->delete_instance_private_key
    452     = &TMH_PG_delete_instance_private_key;
    453   plugin->purge_instance
    454     = &TMH_PG_purge_instance;
    455   plugin->update_instance
    456     = &TMH_PG_update_instance;
    457   plugin->update_instance_auth
    458     = &TMH_PG_update_instance_auth;
    459   plugin->activate_account
    460     = &TMH_PG_activate_account;
    461   plugin->inactivate_account
    462     = &TMH_PG_inactivate_account;
    463   plugin->update_transfer_status
    464     = &TMH_PG_update_transfer_status;
    465   plugin->finalize_transfer_status
    466     = &TMH_PG_finalize_transfer_status;
    467   plugin->lookup_products
    468     = &TMH_PG_lookup_products;
    469   plugin->lookup_all_products
    470     = &TMH_PG_lookup_all_products;
    471   plugin->lookup_product
    472     = &TMH_PG_lookup_product;
    473   plugin->lookup_product_image_by_hash
    474     = &TMH_PG_lookup_product_image_by_hash;
    475   plugin->delete_product
    476     = &TMH_PG_delete_product;
    477   plugin->insert_product
    478     = &TMH_PG_insert_product;
    479   plugin->update_product
    480     = &TMH_PG_update_product;
    481   plugin->insert_otp
    482     = &TMH_PG_insert_otp;
    483   plugin->delete_otp
    484     = &TMH_PG_delete_otp;
    485   plugin->update_otp
    486     = &TMH_PG_update_otp;
    487   plugin->select_otp
    488     = &TMH_PG_select_otp;
    489   plugin->select_otp_serial
    490     = &TMH_PG_select_otp_serial;
    491   plugin->lock_product
    492     = &TMH_PG_lock_product;
    493   plugin->expire_locks
    494     = &TMH_PG_expire_locks;
    495   plugin->delete_order
    496     = &TMH_PG_delete_order;
    497   plugin->lookup_order
    498     = &TMH_PG_lookup_order;
    499   plugin->lookup_order_summary
    500     = &TMH_PG_lookup_order_summary;
    501   plugin->lookup_orders
    502     = &TMH_PG_lookup_orders;
    503   plugin->insert_order
    504     = &TMH_PG_insert_order;
    505   plugin->insert_order_blinded_sigs
    506     = &TMH_PG_insert_order_blinded_sigs;
    507   plugin->unlock_inventory
    508     = &TMH_PG_unlock_inventory;
    509   plugin->insert_order_lock
    510     = &TMH_PG_insert_order_lock;
    511   plugin->select_order_blinded_sigs
    512     = &TMH_PG_select_order_blinded_sigs;
    513   plugin->lookup_contract_terms
    514     = &TMH_PG_lookup_contract_terms;
    515   plugin->lookup_contract_terms2
    516     = &TMH_PG_lookup_contract_terms2;
    517   plugin->lookup_contract_terms3
    518     = &TMH_PG_lookup_contract_terms3;
    519   plugin->insert_contract_terms
    520     = &TMH_PG_insert_contract_terms;
    521   plugin->update_contract_terms
    522     = &TMH_PG_update_contract_terms;
    523   plugin->delete_contract_terms
    524     = &TMH_PG_delete_contract_terms;
    525   plugin->lookup_deposits
    526     = &TMH_PG_lookup_deposits;
    527   plugin->insert_exchange_signkey
    528     = &TMH_PG_insert_exchange_signkey;
    529   plugin->insert_deposit_confirmation
    530     = &TMH_PG_insert_deposit_confirmation;
    531   plugin->insert_deposit
    532     = &TMH_PG_insert_deposit;
    533   plugin->lookup_refunds
    534     = &TMH_PG_lookup_refunds;
    535   plugin->mark_contract_paid
    536     = &TMH_PG_mark_contract_paid;
    537   plugin->refund_coin
    538     = &TMH_PG_refund_coin;
    539   plugin->lookup_order_status
    540     = &TMH_PG_lookup_order_status;
    541   plugin->lookup_order_status_by_serial
    542     = &TMH_PG_lookup_order_status_by_serial;
    543   plugin->lookup_deposits_by_order
    544     = &TMH_PG_lookup_deposits_by_order;
    545   plugin->lookup_transfer_details_by_order
    546     = &TMH_PG_lookup_transfer_details_by_order;
    547   plugin->mark_order_wired
    548     = &TMH_PG_mark_order_wired;
    549   plugin->increase_refund
    550     = &TMH_PG_increase_refund;
    551   plugin->lookup_refunds_detailed
    552     = &TMH_PG_lookup_refunds_detailed;
    553   plugin->insert_refund_proof
    554     = &TMH_PG_insert_refund_proof;
    555   plugin->lookup_refund_proof
    556     = &TMH_PG_lookup_refund_proof;
    557   plugin->lookup_order_by_fulfillment
    558     = &TMH_PG_lookup_order_by_fulfillment;
    559   plugin->delete_transfer
    560     = &TMH_PG_delete_transfer;
    561   plugin->check_transfer_exists
    562     = &TMH_PG_check_transfer_exists;
    563   plugin->lookup_account
    564     = &TMH_PG_lookup_account;
    565   plugin->lookup_wire_fee
    566     = &TMH_PG_lookup_wire_fee;
    567   plugin->lookup_deposits_by_contract_and_coin
    568     = &TMH_PG_lookup_deposits_by_contract_and_coin;
    569   plugin->lookup_transfer_summary
    570     = &TMH_PG_lookup_transfer_summary;
    571   plugin->lookup_transfer_details
    572     = &TMH_PG_lookup_transfer_details;
    573   plugin->lookup_instances
    574     = &TMH_PG_lookup_instances;
    575   plugin->lookup_instance
    576     = &TMH_PG_lookup_instance;
    577   plugin->lookup_transfers
    578     = &TMH_PG_lookup_transfers;
    579   plugin->update_wirewatch_progress
    580     = &TMH_PG_update_wirewatch_progress;
    581   plugin->select_wirewatch_accounts
    582     = &TMH_PG_select_wirewatch_accounts;
    583   plugin->select_account
    584     = &TMH_PG_select_account;
    585   plugin->select_accounts
    586     = &TMH_PG_select_accounts;
    587   plugin->select_open_transfers
    588     = &TMH_PG_select_open_transfers;
    589   plugin->insert_exchange_keys
    590     = &TMH_PG_insert_exchange_keys;
    591   plugin->select_exchange_keys
    592     = &TMH_PG_select_exchange_keys;
    593   plugin->insert_deposit_to_transfer
    594     = &TMH_PG_insert_deposit_to_transfer;
    595   plugin->insert_transfer
    596     = &TMH_PG_insert_transfer;
    597   plugin->lookup_token_family_keys
    598     = &TMH_PG_lookup_token_family_keys;
    599   plugin->insert_transfer_details
    600     = &TMH_PG_insert_transfer_details;
    601   plugin->store_wire_fee_by_exchange
    602     = &TMH_PG_store_wire_fee_by_exchange;
    603   plugin->lookup_webhooks
    604     = &TMH_PG_lookup_webhooks;
    605   plugin->lookup_webhook
    606     = &TMH_PG_lookup_webhook;
    607   plugin->delete_webhook
    608     = &TMH_PG_delete_webhook;
    609   plugin->insert_webhook
    610     = &TMH_PG_insert_webhook;
    611   plugin->update_webhook
    612     = &TMH_PG_update_webhook;
    613   plugin->lookup_pending_deposits
    614     = &TMH_PG_lookup_pending_deposits;
    615   plugin->lookup_webhook_by_event
    616     = &TMH_PG_lookup_webhook_by_event;
    617   plugin->lookup_all_webhooks
    618     = &TMH_PG_lookup_all_webhooks;
    619   plugin->lookup_future_webhook
    620     = &TMH_PG_lookup_future_webhook;
    621   plugin->lookup_pending_webhooks
    622     = &TMH_PG_lookup_pending_webhooks;
    623   plugin->delete_pending_webhook
    624     = &TMH_PG_delete_pending_webhook;
    625   plugin->insert_pending_webhook
    626     = &TMH_PG_insert_pending_webhook;
    627   plugin->update_pending_webhook
    628     = &TMH_PG_update_pending_webhook;
    629   plugin->lookup_categories
    630     = &TMH_PG_lookup_categories;
    631   plugin->lookup_units
    632     = &TMH_PG_lookup_units;
    633   plugin->select_category_by_name
    634     = &TMH_PG_select_category_by_name;
    635   plugin->get_kyc_status
    636     = &TMH_PG_get_kyc_status;
    637   plugin->account_kyc_set_failed
    638     = &TMH_PG_account_kyc_set_failed;
    639   plugin->get_kyc_limits
    640     = &TMH_PG_get_kyc_limits;
    641   plugin->select_category
    642     = &TMH_PG_select_category;
    643   plugin->select_unit
    644     = &TMH_PG_select_unit;
    645   plugin->update_category
    646     = &TMH_PG_update_category;
    647   plugin->update_unit
    648     = &TMH_PG_update_unit;
    649   plugin->insert_category
    650     = &TMH_PG_insert_category;
    651   plugin->insert_unit
    652     = &TMH_PG_insert_unit;
    653   plugin->delete_category
    654     = &TMH_PG_delete_category;
    655   plugin->delete_unit
    656     = &TMH_PG_delete_unit;
    657   plugin->delete_exchange_accounts
    658     = &TMH_PG_delete_exchange_accounts;
    659   plugin->select_accounts_by_exchange
    660     = &TMH_PG_select_accounts_by_exchange;
    661   plugin->insert_exchange_account
    662     = &TMH_PG_insert_exchange_account;
    663   plugin->insert_token_family
    664     = &TMH_PG_insert_token_family;
    665   plugin->lookup_expected_transfers
    666     = &TMH_PG_lookup_expected_transfers;
    667   plugin->lookup_token_family
    668     = &TMH_PG_lookup_token_family;
    669   plugin->lookup_token_families
    670     = &TMH_PG_lookup_token_families;
    671   plugin->delete_token_family
    672     = &TMH_PG_delete_token_family;
    673   plugin->update_token_family
    674     = &TMH_PG_update_token_family;
    675   plugin->insert_token_family_key
    676     = &TMH_PG_insert_token_family_key;
    677   plugin->update_contract_session
    678     = &TMH_PG_update_contract_session;
    679   plugin->lookup_token_family_key
    680     = &TMH_PG_lookup_token_family_key;
    681   plugin->update_deposit_confirmation_status
    682     = &TMH_PG_update_deposit_confirmation_status;
    683   plugin->update_donau_instance_receipts_amount
    684     = &TMH_PG_update_donau_instance_receipts_amount;
    685   plugin->insert_spent_token
    686     = &TMH_PG_insert_spent_token;
    687   plugin->insert_issued_token
    688     = &TMH_PG_insert_issued_token;
    689   plugin->lookup_spent_tokens_by_order
    690     = &TMH_PG_lookup_spent_tokens_by_order;
    691   plugin->lookup_statistics_amount_by_bucket
    692     = &TMH_PG_lookup_statistics_amount_by_bucket;
    693   plugin->lookup_statistics_counter_by_bucket
    694     = &TMH_PG_lookup_statistics_counter_by_bucket;
    695   plugin->lookup_statistics_counter_by_interval
    696     = &TMH_PG_lookup_statistics_counter_by_interval;
    697   plugin->lookup_statistics_amount_by_interval
    698     = &TMH_PG_lookup_statistics_amount_by_interval;
    699   plugin->lookup_mfa_challenge
    700     = &TMH_PG_lookup_mfa_challenge;
    701   plugin->solve_mfa_challenge
    702     = &TMH_PG_solve_mfa_challenge;
    703   plugin->update_mfa_challenge
    704     = &TMH_PG_update_mfa_challenge;
    705   plugin->create_mfa_challenge
    706     = &TMH_PG_create_mfa_challenge;
    707   plugin->gc
    708     = &TMH_PG_gc;
    709 #ifdef HAVE_DONAU_DONAU_SERVICE_H
    710   plugin->insert_donau_instance
    711     = &TMH_PG_insert_donau_instance;
    712   plugin->check_donau_instance
    713     = &TMH_PG_check_donau_instance;
    714   plugin->select_donau_instance_by_serial
    715     = &TMH_PG_select_donau_instance_by_serial;
    716   plugin->select_all_donau_instances
    717     = &TMH_PG_select_all_donau_instances;
    718   plugin->select_donau_instances
    719     = &TMH_PG_select_donau_instances;
    720   plugin->select_donau_instances_filtered
    721     = &TMH_PG_select_donau_instances_filtered;
    722   plugin->delete_donau_instance
    723     = &TMH_PG_delete_donau_instance;
    724   plugin->lookup_donau_keys
    725     = &TMH_PG_lookup_donau_keys;
    726   plugin->lookup_order_charity
    727     = &TMH_PG_lookup_order_charity;
    728   plugin->upsert_donau_keys
    729     = &TMH_PG_upsert_donau_keys;
    730   plugin->update_donau_instance
    731     = &TMH_PG_update_donau_instance;
    732 #endif
    733   return plugin;
    734 }
    735 
    736 
    737 /**
    738  * Shutdown Postgres database subsystem.
    739  *
    740  * @param cls a `struct TALER_MERCHANTDB_Plugin`
    741  * @return NULL (always)
    742  */
    743 void *
    744 libtaler_plugin_merchantdb_postgres_done (void *cls);
    745 
    746 /* declaration to avoid compiler warning */
    747 void *
    748 libtaler_plugin_merchantdb_postgres_done (void *cls)
    749 {
    750   struct TALER_MERCHANTDB_Plugin *plugin = cls;
    751   struct PostgresClosure *pg = plugin->cls;
    752 
    753   if (NULL != pg->conn)
    754   {
    755     GNUNET_PQ_disconnect (pg->conn);
    756     pg->conn = NULL;
    757   }
    758   GNUNET_free (pg->sql_dir);
    759   GNUNET_free (pg);
    760   GNUNET_free (plugin);
    761   return NULL;
    762 }
    763 
    764 
    765 /* end of plugin_merchantdb_postgres.c */