merchant

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

plugin_merchantdb_postgres.c (27596B)


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