gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] 01/03: update


From: gnunet
Subject: [taler-exchange] 01/03: update
Date: Mon, 20 Feb 2023 18:17:15 +0100

This is an automated email from the git hooks/post-receive script.

priscilla-huang pushed a commit to branch master
in repository exchange.

commit 3e6a6f0ee66f5b47841c5352da503ab298598cc3
Author: priscilla <priscilla.huang@efrei.net>
AuthorDate: Tue Jan 31 07:37:56 2023 -0500

    update
---
 src/exchange/taler-exchange-httpd.h                |   22 +-
 src/exchangedb/shard-0001.sql                      | 2575 ++++++++++++++++++++
 ...angedb-populate-select-refunds-by-coin-postgres |  210 ++
 3 files changed, 2796 insertions(+), 11 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd.h 
b/src/exchange/taler-exchange-httpd.h
index 96003626..5ab0ea92 100644
--- a/src/exchange/taler-exchange-httpd.h
+++ b/src/exchange/taler-exchange-httpd.h
@@ -246,17 +246,6 @@ struct TEH_RequestHandler
 
   } handler;
 
-  /**
-   * Number of arguments this handler expects in the @a args array.
-   */
-  unsigned int nargs;
-
-  /**
-   * Is the number of arguments given in @e nargs only an upper bound,
-   * and calling with fewer arguments could be OK?
-   */
-  bool nargs_is_upper_bound;
-
   /**
    * Mime type to use in reply (hint, can be NULL).
    */
@@ -276,6 +265,17 @@ struct TEH_RequestHandler
    * Default response code. 0 for none provided.
    */
   unsigned int response_code;
+
+  /**
+   * Number of arguments this handler expects in the @a args array.
+   */
+  unsigned int nargs;
+
+  /**
+   * Is the number of arguments given in @e nargs only an upper bound,
+   * and calling with fewer arguments could be OK?
+   */
+  bool nargs_is_upper_bound;
 };
 
 
diff --git a/src/exchangedb/shard-0001.sql b/src/exchangedb/shard-0001.sql
new file mode 100644
index 00000000..89c79f17
--- /dev/null
+++ b/src/exchangedb/shard-0001.sql
@@ -0,0 +1,2575 @@
+BEGIN;
+SELECT _v.register_patch('shard-0001', NULL, NULL);
+CREATE SCHEMA exchange;
+COMMENT ON SCHEMA exchange IS 'taler-exchange data';
+SET search_path TO exchange;
+CREATE OR REPLACE FUNCTION create_partitioned_table(
+   IN table_definition VARCHAR
+  ,IN table_name VARCHAR
+  ,IN main_table_partition_str VARCHAR 
+  ,IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  IF shard_suffix IS NOT NULL THEN
+    table_name=table_name || '_' || shard_suffix;
+    main_table_partition_str = '';
+  END IF;
+  EXECUTE FORMAT(
+    table_definition,
+    table_name,
+    main_table_partition_str
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_wire_targets(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(wire_target_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',wire_target_h_payto BYTEA PRIMARY KEY CHECK 
(LENGTH(wire_target_h_payto)=32)'
+      ',payto_uri VARCHAR NOT NULL'
+    ') %s ;'
+    ,'wire_targets'
+    ,'PARTITION BY HASH (wire_target_h_payto)'
+    ,shard_suffix
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_wire_targets_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE wire_targets_' || partition_suffix || ' '
+      'ADD CONSTRAINT wire_targets_' || partition_suffix || 
'_wire_target_serial_id_key '
+        'UNIQUE (wire_target_serial_id)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_legitimization_processes(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(legitimization_process_serial_id BIGINT GENERATED BY DEFAULT AS 
IDENTITY' 
+      ',h_payto BYTEA NOT NULL CHECK (LENGTH(h_payto)=32)'
+      ',expiration_time INT8 NOT NULL DEFAULT (0)'
+      ',provider_section VARCHAR NOT NULL'
+      ',provider_user_id VARCHAR DEFAULT NULL'
+      ',provider_legitimization_id VARCHAR DEFAULT NULL'
+      ',UNIQUE (h_payto, provider_section)'
+    ') %s ;'
+    ,'legitimization_processes'
+    ,'PARTITION BY HASH (h_payto)'
+    ,shard_suffix
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION 
add_constraints_to_legitimization_processes_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  partition_name VARCHAR;
+BEGIN
+  partition_name = concat_ws('_', 'legitimization_processes', 
partition_suffix);
+  EXECUTE FORMAT (
+    'ALTER TABLE ' || partition_name
+    || ' '
+      'ADD CONSTRAINT ' || partition_name || '_serial_key '
+        'UNIQUE (legitimization_process_serial_id)');
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || partition_name || 
'_by_provider_and_legi_index '
+        'ON '|| partition_name || ' '
+        '(provider_section,provider_legitimization_id)'
+  );
+  EXECUTE FORMAT (
+    'COMMENT ON INDEX ' || partition_name || '_by_provider_and_legi_index '
+    'IS ' || quote_literal('used (rarely) in kyc_provider_account_lookup') || 
';'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_legitimization_requirements(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(legitimization_requirement_serial_id BIGINT GENERATED BY DEFAULT AS 
IDENTITY' 
+      ',h_payto BYTEA NOT NULL CHECK (LENGTH(h_payto)=32)'
+      ',required_checks VARCHAR NOT NULL'
+      ',UNIQUE (h_payto, required_checks)'
+    ') %s ;'
+    ,'legitimization_requirements'
+    ,'PARTITION BY HASH (h_payto)'
+    ,shard_suffix
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION 
add_constraints_to_legitimization_requirements_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  partition_name VARCHAR;
+BEGIN
+  partition_name = concat_ws('_', 'legitimization_requirements', 
partition_suffix);
+  EXECUTE FORMAT (
+    'ALTER TABLE ' || partition_name
+    || ' '
+      'ADD CONSTRAINT ' || partition_name || '_serial_id_key '
+        'UNIQUE (legitimization_requirement_serial_id)');
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_reserves(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'reserves';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(reserve_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY'
+      ',reserve_pub BYTEA PRIMARY KEY CHECK(LENGTH(reserve_pub)=32)'
+      ',current_balance_val INT8 NOT NULL DEFAULT(0)'
+      ',current_balance_frac INT4 NOT NULL DEFAULT(0)'
+      ',purses_active INT8 NOT NULL DEFAULT(0)'
+      ',purses_allowed INT8 NOT NULL DEFAULT(0)'
+      ',max_age INT4 NOT NULL DEFAULT(120)'
+      ',expiration_date INT8 NOT NULL'
+      ',gc_date INT8 NOT NULL'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (reserve_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_expiration_index '
+    'ON ' || table_name || ' '
+    '(expiration_date'
+    ',current_balance_val'
+    ',current_balance_frac'
+    ');'
+  );
+  EXECUTE FORMAT (
+    'COMMENT ON INDEX ' || table_name || '_by_expiration_index '
+    'IS ' || quote_literal('used in get_expired_reserves') || ';'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_reserve_uuid_index '
+    'ON ' || table_name || ' '
+    '(reserve_uuid);'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_gc_date_index '
+    'ON ' || table_name || ' '
+    '(gc_date);'
+  );
+  EXECUTE FORMAT (
+    'COMMENT ON INDEX ' || table_name || '_by_gc_date_index '
+    'IS ' || quote_literal('for reserve garbage collection') || ';'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_reserves_in(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR default 'reserves_in';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(reserve_in_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',reserve_pub BYTEA PRIMARY KEY' 
+      ',wire_reference INT8 NOT NULL'
+      ',credit_val INT8 NOT NULL'
+      ',credit_frac INT4 NOT NULL'
+      ',wire_source_h_payto BYTEA CHECK (LENGTH(wire_source_h_payto)=32)'
+      ',exchange_account_section TEXT NOT NULL'
+      ',execution_date INT8 NOT NULL'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (reserve_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_by_reserve_in_serial_id_index '
+    'ON ' || table_name || ' '
+    '(reserve_in_serial_id);'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_by_exch_accnt_section_execution_date_idx '
+    'ON ' || table_name || ' '
+    '(exchange_account_section '
+    ',execution_date'
+    ');'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_by_exch_accnt_reserve_in_serial_id_idx '
+    'ON ' || table_name || ' '
+    '(exchange_account_section,'
+    'reserve_in_serial_id DESC'
+    ');'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_reserves_in_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE reserves_in_' || partition_suffix || ' '
+      'ADD CONSTRAINT reserves_in_' || partition_suffix || 
'_reserve_in_serial_id_key '
+        'UNIQUE (reserve_in_serial_id)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_reserves_close(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR default 'reserves_close';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(close_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',reserve_pub BYTEA NOT NULL' 
+      ',execution_date INT8 NOT NULL'
+      ',wtid BYTEA NOT NULL CHECK (LENGTH(wtid)=32)'
+      ',wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32)'
+      ',amount_val INT8 NOT NULL'
+      ',amount_frac INT4 NOT NULL'
+      ',closing_fee_val INT8 NOT NULL'
+      ',closing_fee_frac INT4 NOT NULL'
+      ',close_request_row INT8 NOT NULL DEFAULT(0)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (reserve_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_close_uuid_index '
+    'ON ' || table_name || ' '
+    '(close_uuid);'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_reserve_pub_index '
+    'ON ' || table_name || ' '
+    '(reserve_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_reserves_close_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE reserves_close_' || partition_suffix || ' '
+      'ADD CONSTRAINT reserves_close_' || partition_suffix || 
'_close_uuid_pkey '
+        'PRIMARY KEY (close_uuid)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_close_requests(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'close_requests';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(close_request_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_pub)=32)' 
+      ',close_timestamp INT8 NOT NULL'
+      ',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)'
+      ',close_val INT8 NOT NULL'
+      ',close_frac INT4 NOT NULL'
+      ',close_fee_val INT8 NOT NULL'
+      ',close_fee_frac INT4 NOT NULL'
+      ',payto_uri VARCHAR NOT NULL'
+      ',done BOOL NOT NULL DEFAULT(FALSE)'
+      ',PRIMARY KEY (reserve_pub,close_timestamp)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (reserve_pub)'
+    ,shard_suffix
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_close_requests(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'close_requests';
+BEGIN
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_by_close_request_uuid_index '
+    'ON ' || table_name || ' '
+    '(close_request_serial_id);'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_by_close_request_done_index '
+    'ON ' || table_name || ' '
+    '(done);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_close_requests_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE close_requests_' || partition_suffix || ' '
+      'ADD CONSTRAINT close_requests_' || partition_suffix || 
'_close_request_uuid_pkey '
+        'UNIQUE (close_request_serial_id)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_reserves_open_requests(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR default 'reserves_open_requests';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(open_request_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',reserve_pub BYTEA NOT NULL' 
+      ',request_timestamp INT8 NOT NULL'
+      ',expiration_date INT8 NOT NULL'
+      ',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)'
+      ',reserve_payment_val INT8 NOT NULL'
+      ',reserve_payment_frac INT4 NOT NULL'
+      ',requested_purse_limit INT4 NOT NULL'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (reserve_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_by_reserve_open_uuid_index '
+    'ON ' || table_name || ' '
+    '(open_request_uuid);'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_reserve_pub_index '
+    'ON ' || table_name || ' '
+    '(reserve_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_reserves_open_request_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE reserves_open_requests_' || partition_suffix || ' '
+      'ADD CONSTRAINT reserves_open_requests_' || partition_suffix || 
'_by_uuid '
+        'PRIMARY KEY (open_request_uuid),'
+      'ADD CONSTRAINT reserves_open_requests_' || partition_suffix || 
'_by_time '
+        'UNIQUE (reserve_pub,request_timestamp)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_reserves_open_deposits(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR default 'reserves_open_deposits';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(reserve_open_deposit_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)'
+      ',reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_pub)=32)'
+      ',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)'
+      ',coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)'
+      ',contribution_val INT8 NOT NULL'
+      ',contribution_frac INT4 NOT NULL'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (coin_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_uuid '
+    'ON ' || table_name || ' '
+    '(reserve_open_deposit_uuid);'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_reserve '
+    'ON ' || table_name || ' '
+    '(reserve_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_reserves_open_deposits_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE reserves_open_deposits_' || partition_suffix || ' '
+      'ADD CONSTRAINT reserves_open_deposits_' || partition_suffix || 
'_coin_unique '
+        'PRIMARY KEY (coin_pub,coin_sig)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_reserves_out(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR default 'reserves_out';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(reserve_out_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',h_blind_ev BYTEA CHECK (LENGTH(h_blind_ev)=64) UNIQUE'
+      ',denominations_serial INT8 NOT NULL' 
+      ',denom_sig BYTEA NOT NULL'
+      ',reserve_uuid INT8 NOT NULL' 
+      ',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)'
+      ',execution_date INT8 NOT NULL'
+      ',amount_with_fee_val INT8 NOT NULL'
+      ',amount_with_fee_frac INT4 NOT NULL'
+    ') %s ;'
+    ,'reserves_out'
+    ,'PARTITION BY HASH (h_blind_ev)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_by_reserve_out_serial_id_index '
+    'ON ' || table_name || ' '
+    '(reserve_out_serial_id);'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_by_reserve_uuid_and_execution_date_index '
+    'ON ' || table_name || ' '
+    '(reserve_uuid, execution_date);'
+  );
+  EXECUTE FORMAT (
+    'COMMENT ON INDEX ' || table_name || 
'_by_reserve_uuid_and_execution_date_index '
+    'IS ' || quote_literal('for get_reserves_out and 
exchange_do_withdraw_limit_check') || ';'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_reserves_out_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE reserves_out_' || partition_suffix || ' '
+      'ADD CONSTRAINT reserves_out_' || partition_suffix || 
'_reserve_out_serial_id_key '
+        'UNIQUE (reserve_out_serial_id)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_reserves_out_by_reserve(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'reserves_out_by_reserve';
+BEGIN
+  PERFORM create_partitioned_table(
+  'CREATE TABLE IF NOT EXISTS %I'
+    '(reserve_uuid INT8 NOT NULL' 
+    ',h_blind_ev BYTEA CHECK (LENGTH(h_blind_ev)=64)'
+    ') %s '
+    ,table_name
+    ,'PARTITION BY HASH (reserve_uuid)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_main_index '
+    'ON ' || table_name || ' '
+    '(reserve_uuid);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_known_coins(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR default 'known_coins';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(known_coin_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',denominations_serial INT8 NOT NULL' 
+      ',coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (LENGTH(coin_pub)=32)'
+      ',age_commitment_hash BYTEA CHECK (LENGTH(age_commitment_hash)=32)'
+      ',denom_sig BYTEA NOT NULL'
+      ',remaining_val INT8 NOT NULL DEFAULT(0)'
+      ',remaining_frac INT4 NOT NULL DEFAULT(0)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (coin_pub)' 
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_known_coins_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE known_coins_' || partition_suffix || ' '
+      'ADD CONSTRAINT known_coins_' || partition_suffix || '_known_coin_id_key 
'
+        'UNIQUE (known_coin_id)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_refresh_commitments(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'refresh_commitments';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(melt_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',rc BYTEA PRIMARY KEY CHECK (LENGTH(rc)=64)'
+      ',old_coin_pub BYTEA NOT NULL' 
+      ',old_coin_sig BYTEA NOT NULL CHECK(LENGTH(old_coin_sig)=64)'
+      ',amount_with_fee_val INT8 NOT NULL'
+      ',amount_with_fee_frac INT4 NOT NULL'
+      ',noreveal_index INT4 NOT NULL'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (rc)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_old_coin_pub_index '
+    'ON ' || table_name || ' '
+    '(old_coin_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_refresh_commitments_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE refresh_commitments_' || partition_suffix || ' '
+      'ADD CONSTRAINT refresh_commitments_' || partition_suffix || 
'_melt_serial_id_key '
+        'UNIQUE (melt_serial_id)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_refresh_revealed_coins(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'refresh_revealed_coins';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(rrc_serial BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',melt_serial_id INT8 NOT NULL' 
+      ',freshcoin_index INT4 NOT NULL'
+      ',link_sig BYTEA NOT NULL CHECK(LENGTH(link_sig)=64)'
+      ',denominations_serial INT8 NOT NULL' 
+      ',coin_ev BYTEA NOT NULL' 
+      ',h_coin_ev BYTEA NOT NULL CHECK(LENGTH(h_coin_ev)=64)' 
+      ',ev_sig BYTEA NOT NULL'
+      ',ewv BYTEA NOT NULL'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (melt_serial_id)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_coins_by_melt_serial_id_index '
+    'ON ' || table_name || ' '
+    '(melt_serial_id);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_refresh_revealed_coins_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE refresh_revealed_coins_' || partition_suffix || ' '
+      'ADD CONSTRAINT refresh_revealed_coins_' || partition_suffix || 
'_rrc_serial_key '
+        'UNIQUE (rrc_serial) '
+      ',ADD CONSTRAINT refresh_revealed_coins_' || partition_suffix || 
'_coin_ev_key '
+        'UNIQUE (coin_ev) '
+      ',ADD CONSTRAINT refresh_revealed_coins_' || partition_suffix || 
'_h_coin_ev_key '
+        'UNIQUE (h_coin_ev) '
+      ',ADD PRIMARY KEY (melt_serial_id, freshcoin_index) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_refresh_transfer_keys(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'refresh_transfer_keys';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(rtc_serial BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',melt_serial_id INT8 PRIMARY KEY' 
+      ',transfer_pub BYTEA NOT NULL CHECK(LENGTH(transfer_pub)=32)'
+      ',transfer_privs BYTEA NOT NULL'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (melt_serial_id)'
+    ,shard_suffix
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_refresh_transfer_keys_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE refresh_transfer_keys_' || partition_suffix || ' '
+      'ADD CONSTRAINT refresh_transfer_keys_' || partition_suffix || 
'_rtc_serial_key '
+        'UNIQUE (rtc_serial)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_deposits(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'deposits';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',shard INT8 NOT NULL'
+      ',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)' 
+      ',known_coin_id INT8 NOT NULL' 
+      ',amount_with_fee_val INT8 NOT NULL'
+      ',amount_with_fee_frac INT4 NOT NULL'
+      ',wallet_timestamp INT8 NOT NULL'
+      ',exchange_timestamp INT8 NOT NULL'
+      ',refund_deadline INT8 NOT NULL'
+      ',wire_deadline INT8 NOT NULL'
+      ',merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)'
+      ',h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64)'
+      ',coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)'
+      ',wire_salt BYTEA NOT NULL CHECK (LENGTH(wire_salt)=16)'
+      ',wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32)'
+      ',done BOOLEAN NOT NULL DEFAULT FALSE'
+      ',policy_blocked BOOLEAN NOT NULL DEFAULT FALSE'
+      ',policy_details_serial_id INT8' 
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (coin_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_coin_pub_index '
+    'ON ' || table_name || ' '
+    '(coin_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_deposits_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE deposits_' || partition_suffix || ' '
+      'ADD CONSTRAINT deposits_' || partition_suffix || 
'_deposit_serial_id_pkey '
+        'PRIMARY KEY (deposit_serial_id) '
+      ',ADD CONSTRAINT deposits_' || partition_suffix || 
'_coin_pub_merchant_pub_h_contract_terms_key '
+        'UNIQUE (coin_pub, merchant_pub, h_contract_terms)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_deposits_by_ready(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'deposits_by_ready';
+BEGIN
+  PERFORM create_partitioned_table(
+  'CREATE TABLE IF NOT EXISTS %I'
+    '(wire_deadline INT8 NOT NULL'
+    ',shard INT8 NOT NULL'
+    ',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)'
+    ',deposit_serial_id INT8'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY RANGE (wire_deadline)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_main_index '
+    'ON ' || table_name || ' '
+    '(wire_deadline ASC, shard ASC, coin_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_deposits_for_matching(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'deposits_for_matching';
+BEGIN
+  PERFORM create_partitioned_table(
+  'CREATE TABLE IF NOT EXISTS %I'
+    '(refund_deadline INT8 NOT NULL'
+    ',merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)'
+    ',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)' 
+    ',deposit_serial_id INT8'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY RANGE (refund_deadline)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_main_index '
+    'ON ' || table_name || ' '
+    '(refund_deadline ASC, merchant_pub, coin_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_refunds(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'refunds';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(refund_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)' 
+      ',deposit_serial_id INT8 NOT NULL' 
+      ',merchant_sig BYTEA NOT NULL CHECK(LENGTH(merchant_sig)=64)'
+      ',rtransaction_id INT8 NOT NULL'
+      ',amount_with_fee_val INT8 NOT NULL'
+      ',amount_with_fee_frac INT4 NOT NULL'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (coin_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_coin_pub_index '
+    'ON ' || table_name || ' '
+    '(coin_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_refunds_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE refunds_' || partition_suffix || ' '
+      'ADD CONSTRAINT refunds_' || partition_suffix || '_refund_serial_id_key '
+        'UNIQUE (refund_serial_id) '
+      ',ADD PRIMARY KEY (deposit_serial_id, rtransaction_id) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_wire_out(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'wire_out';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(wireout_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',execution_date INT8 NOT NULL'
+      ',wtid_raw BYTEA UNIQUE NOT NULL CHECK (LENGTH(wtid_raw)=32)'
+      ',wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32)'
+      ',exchange_account_section TEXT NOT NULL'
+      ',amount_val INT8 NOT NULL'
+      ',amount_frac INT4 NOT NULL'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (wtid_raw)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || 
'_by_wire_target_h_payto_index '
+    'ON ' || table_name || ' '
+    '(wire_target_h_payto);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_wire_out_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS void
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE wire_out_' || partition_suffix || ' '
+      'ADD CONSTRAINT wire_out_' || partition_suffix || '_wireout_uuid_pkey '
+        'PRIMARY KEY (wireout_uuid)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_aggregation_transient(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'aggregation_transient';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(amount_val INT8 NOT NULL'
+      ',amount_frac INT4 NOT NULL'
+      ',wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32)'
+      ',merchant_pub BYTEA CHECK (LENGTH(merchant_pub)=32)'
+      ',exchange_account_section TEXT NOT NULL'
+      ',legitimization_requirement_serial_id INT8 NOT NULL DEFAULT(0)'
+      ',wtid_raw BYTEA NOT NULL CHECK (LENGTH(wtid_raw)=32)'
+      ') %s ;'
+      ,table_name
+      ,'PARTITION BY HASH (wire_target_h_payto)'
+      ,shard_suffix
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_aggregation_tracking(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'aggregation_tracking';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(aggregation_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+     ',deposit_serial_id INT8 PRIMARY KEY' 
+      ',wtid_raw BYTEA NOT NULL' 
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (deposit_serial_id)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_wtid_raw_index '
+    'ON ' || table_name || ' '
+    '(wtid_raw);'
+  );
+  EXECUTE FORMAT (
+    'COMMENT ON INDEX ' || table_name || '_by_wtid_raw_index '
+    'IS ' || quote_literal('for lookup_transactions') || ';'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_aggregation_tracking_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE aggregation_tracking_' || partition_suffix || ' '
+      'ADD CONSTRAINT aggregation_tracking_' || partition_suffix || 
'_aggregation_serial_id_key '
+        'UNIQUE (aggregation_serial_id) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_recoup(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'recoup';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(recoup_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)' 
+      ',coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)'
+      ',coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)'
+      ',amount_val INT8 NOT NULL'
+      ',amount_frac INT4 NOT NULL'
+      ',recoup_timestamp INT8 NOT NULL'
+      ',reserve_out_serial_id INT8 NOT NULL' 
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (coin_pub);'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_coin_pub_index '
+    'ON ' || table_name || ' '
+    '(coin_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_recoup_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE recoup_' || partition_suffix || ' '
+      'ADD CONSTRAINT recoup_' || partition_suffix || '_recoup_uuid_key '
+        'UNIQUE (recoup_uuid) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_recoup_by_reserve(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'recoup_by_reserve';
+BEGIN
+  PERFORM create_partitioned_table(
+  'CREATE TABLE IF NOT EXISTS %I'
+    '(reserve_out_serial_id INT8 NOT NULL' 
+    ',coin_pub BYTEA CHECK (LENGTH(coin_pub)=32)' 
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (reserve_out_serial_id)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_main_index '
+    'ON ' || table_name || ' '
+    '(reserve_out_serial_id);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_recoup_refresh(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'recoup_refresh';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(recoup_refresh_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)' 
+      ',known_coin_id BIGINT NOT NULL' 
+      ',coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)'
+      ',coin_blind BYTEA NOT NULL CHECK(LENGTH(coin_blind)=32)'
+      ',amount_val INT8 NOT NULL'
+      ',amount_frac INT4 NOT NULL'
+      ',recoup_timestamp INT8 NOT NULL'
+      ',rrc_serial INT8 NOT NULL' 
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (coin_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_rrc_serial_index '
+    'ON ' || table_name || ' '
+    '(rrc_serial);'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_coin_pub_index '
+    'ON ' || table_name || ' '
+    '(coin_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_recoup_refresh_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE recoup_refresh_' || partition_suffix || ' '
+      'ADD CONSTRAINT recoup_refresh_' || partition_suffix || 
'_recoup_refresh_uuid_key '
+        'UNIQUE (recoup_refresh_uuid) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_prewire(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'prewire';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(prewire_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY'
+      ',wire_method TEXT NOT NULL'
+      ',finished BOOLEAN NOT NULL DEFAULT false'
+      ',failed BOOLEAN NOT NULL DEFAULT false'
+      ',buf BYTEA NOT NULL'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (prewire_uuid)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_finished_index '
+    'ON ' || table_name || ' '
+    '(finished);'
+  );
+  EXECUTE FORMAT (
+    'COMMENT ON INDEX ' || table_name || '_by_finished_index '
+    'IS ' || quote_literal('for gc_prewire') || ';'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_failed_finished_index '
+    'ON ' || table_name || ' '
+    '(failed,finished);'
+  );
+  EXECUTE FORMAT (
+    'COMMENT ON INDEX ' || table_name || '_by_failed_finished_index '
+    'IS ' || quote_literal('for wire_prepare_data_get') || ';'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_cs_nonce_locks(
+  shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I'
+      '(cs_nonce_lock_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',nonce BYTEA PRIMARY KEY CHECK (LENGTH(nonce)=32)'
+      ',op_hash BYTEA NOT NULL CHECK (LENGTH(op_hash)=64)'
+      ',max_denomination_serial INT8 NOT NULL'
+    ') %s ;'
+    ,'cs_nonce_locks'
+    ,'PARTITION BY HASH (nonce)'
+    ,shard_suffix
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_cs_nonce_locks_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE cs_nonce_locks_' || partition_suffix || ' '
+      'ADD CONSTRAINT cs_nonce_locks_' || partition_suffix || 
'_cs_nonce_lock_serial_id_key '
+        'UNIQUE (cs_nonce_lock_serial_id)'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_purse_requests(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'purse_requests';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(purse_requests_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',purse_pub BYTEA NOT NULL CHECK (LENGTH(purse_pub)=32)'
+      ',merge_pub BYTEA NOT NULL CHECK (LENGTH(merge_pub)=32)'
+      ',purse_creation INT8 NOT NULL'
+      ',purse_expiration INT8 NOT NULL'
+      ',h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64)'
+      ',age_limit INT4 NOT NULL'
+      ',flags INT4 NOT NULL'
+      ',in_reserve_quota BOOLEAN NOT NULL DEFAULT(FALSE)'
+      ',amount_with_fee_val INT8 NOT NULL'
+      ',amount_with_fee_frac INT4 NOT NULL'
+      ',purse_fee_val INT8 NOT NULL'
+      ',purse_fee_frac INT4 NOT NULL'
+      ',balance_val INT8 NOT NULL DEFAULT (0)'
+      ',balance_frac INT4 NOT NULL DEFAULT (0)'
+      ',purse_sig BYTEA NOT NULL CHECK(LENGTH(purse_sig)=64)'
+      ',PRIMARY KEY (purse_pub)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (purse_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_merge_pub '
+    'ON ' || table_name || ' '
+    '(merge_pub);'
+  );
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_purse_expiration '
+    'ON ' || table_name || ' '
+    '(purse_expiration);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_purse_requests_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE purse_requests_' || partition_suffix || ' '
+      'ADD CONSTRAINT purse_requests_' || partition_suffix || 
'_purse_requests_serial_id_key '
+        'UNIQUE (purse_requests_serial_id) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_purse_merges(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'purse_merges';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(purse_merge_request_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY '
+      ',partner_serial_id INT8' 
+      ',reserve_pub BYTEA NOT NULL CHECK(length(reserve_pub)=32)'
+      ',purse_pub BYTEA NOT NULL CHECK (LENGTH(purse_pub)=32)' 
+      ',merge_sig BYTEA NOT NULL CHECK (LENGTH(merge_sig)=64)'
+      ',merge_timestamp INT8 NOT NULL'
+      ',PRIMARY KEY (purse_pub)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (purse_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_reserve_pub '
+    'ON ' || table_name || ' '
+    '(reserve_pub);'
+  );
+  EXECUTE FORMAT (
+    'COMMENT ON INDEX ' || table_name || '_reserve_pub '
+    'IS ' || quote_literal('needed in reserve history computation') || ';'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_purse_merges_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE purse_merges_' || partition_suffix || ' '
+      'ADD CONSTRAINT purse_merges_' || partition_suffix || 
'_purse_merge_request_serial_id_key '
+        'UNIQUE (purse_merge_request_serial_id) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_account_merges(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'account_merges';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(account_merge_request_serial_id BIGINT GENERATED BY DEFAULT AS 
IDENTITY' 
+      ',reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_pub)=32)' 
+      ',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)'
+      ',purse_pub BYTEA NOT NULL CHECK (LENGTH(purse_pub)=32)' 
+      ',wallet_h_payto BYTEA NOT NULL CHECK (LENGTH(wallet_h_payto)=32)'
+      ',PRIMARY KEY (purse_pub)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (purse_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_reserve_pub '
+    'ON ' || table_name || ' '
+    '(reserve_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_account_merges_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE account_merges_' || partition_suffix || ' '
+      'ADD CONSTRAINT account_merges_' || partition_suffix || 
'_account_merge_request_serial_id_key '
+        'UNIQUE (account_merge_request_serial_id) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_purse_decision(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'purse_decision';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(purse_decision_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',purse_pub BYTEA NOT NULL CHECK (LENGTH(purse_pub)=32)'
+      ',action_timestamp INT8 NOT NULL'
+      ',refunded BOOL NOT NULL'
+      ',PRIMARY KEY (purse_pub)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (purse_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_purse_decision_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE purse_decision_' || partition_suffix || ' '
+      'ADD CONSTRAINT purse_decision_' || partition_suffix || 
'_purse_action_serial_id_key '
+        'UNIQUE (purse_decision_serial_id) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_contracts(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'contracts';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(contract_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',purse_pub BYTEA NOT NULL CHECK (LENGTH(purse_pub)=32)'
+      ',pub_ckey BYTEA NOT NULL CHECK (LENGTH(pub_ckey)=32)'
+      ',contract_sig BYTEA NOT NULL CHECK (LENGTH(contract_sig)=64)'
+      ',e_contract BYTEA NOT NULL'
+      ',purse_expiration INT8 NOT NULL'
+      ',PRIMARY KEY (purse_pub)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (purse_pub)'
+    ,shard_suffix
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_contracts_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE contracts_' || partition_suffix || ' '
+      'ADD CONSTRAINT contracts_' || partition_suffix || 
'_contract_serial_id_key '
+        'UNIQUE (contract_serial_id) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_history_requests(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'history_requests';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(history_request_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',reserve_pub BYTEA NOT NULL CHECK (LENGTH(reserve_pub)=32)' 
+      ',request_timestamp INT8 NOT NULL'
+      ',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)'
+      ',history_fee_val INT8 NOT NULL'
+      ',history_fee_frac INT4 NOT NULL'
+      ',PRIMARY KEY (reserve_pub,request_timestamp)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (reserve_pub)'
+    ,shard_suffix
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_purse_deposits(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'purse_deposits';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(purse_deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',partner_serial_id INT8' 
+      ',purse_pub BYTEA NOT NULL CHECK (LENGTH(purse_pub)=32)'
+      ',coin_pub BYTEA NOT NULL' 
+      ',amount_with_fee_val INT8 NOT NULL'
+      ',amount_with_fee_frac INT4 NOT NULL'
+      ',coin_sig BYTEA NOT NULL CHECK(LENGTH(coin_sig)=64)'
+      ',PRIMARY KEY (purse_pub,coin_pub)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (purse_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_coin_pub '
+    'ON ' || table_name || ' '
+    '(coin_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_purse_deposits_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE purse_deposits_' || partition_suffix || ' '
+      'ADD CONSTRAINT purse_deposits_' || partition_suffix || 
'_purse_deposit_serial_id_key '
+        'UNIQUE (purse_deposit_serial_id) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_wads_out(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'wads_out';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(wad_out_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',wad_id BYTEA PRIMARY KEY CHECK (LENGTH(wad_id)=24)'
+      ',partner_serial_id INT8 NOT NULL' 
+      ',amount_val INT8 NOT NULL'
+      ',amount_frac INT4 NOT NULL'
+      ',execution_time INT8 NOT NULL'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (wad_id)'
+    ,shard_suffix
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_wads_out_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE wads_out_' || partition_suffix || ' '
+      'ADD CONSTRAINT wads_out_' || partition_suffix || 
'_wad_out_serial_id_key '
+        'UNIQUE (wad_out_serial_id) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_wad_out_entries(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'wad_out_entries';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(wad_out_entry_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',wad_out_serial_id INT8' 
+      ',reserve_pub BYTEA NOT NULL CHECK(LENGTH(reserve_pub)=32)'
+      ',purse_pub BYTEA PRIMARY KEY CHECK(LENGTH(purse_pub)=32)'
+      ',h_contract BYTEA NOT NULL CHECK(LENGTH(h_contract)=64)'
+      ',purse_expiration INT8 NOT NULL'
+      ',merge_timestamp INT8 NOT NULL'
+      ',amount_with_fee_val INT8 NOT NULL'
+      ',amount_with_fee_frac INT4 NOT NULL'
+      ',wad_fee_val INT8 NOT NULL'
+      ',wad_fee_frac INT4 NOT NULL'
+      ',deposit_fees_val INT8 NOT NULL'
+      ',deposit_fees_frac INT4 NOT NULL'
+      ',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)'
+      ',purse_sig BYTEA NOT NULL CHECK (LENGTH(purse_sig)=64)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (purse_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_by_reserve_pub '
+    'ON ' || table_name || ' '
+    '(reserve_pub);'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_wad_out_entries_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE wad_out_entries_' || partition_suffix || ' '
+      'ADD CONSTRAINT wad_out_entries_' || partition_suffix || 
'_wad_out_entry_serial_id_key '
+        'UNIQUE (wad_out_entry_serial_id) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_wads_in(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'wads_in';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(wad_in_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',wad_id BYTEA PRIMARY KEY CHECK (LENGTH(wad_id)=24)'
+      ',origin_exchange_url TEXT NOT NULL'
+      ',amount_val INT8 NOT NULL'
+      ',amount_frac INT4 NOT NULL'
+      ',arrival_time INT8 NOT NULL'
+      ',UNIQUE (wad_id, origin_exchange_url)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (wad_id)'
+    ,shard_suffix
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_wads_in_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE wads_in_' || partition_suffix || ' '
+      'ADD CONSTRAINT wads_in_' || partition_suffix || '_wad_in_serial_id_key '
+        'UNIQUE (wad_in_serial_id) '
+      ',ADD CONSTRAINT wads_in_' || partition_suffix || 
'_wad_is_origin_exchange_url_key '
+        'UNIQUE (wad_id, origin_exchange_url) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_table_wad_in_entries(
+  IN shard_suffix VARCHAR DEFAULT NULL
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  table_name VARCHAR DEFAULT 'wad_in_entries';
+BEGIN
+  PERFORM create_partitioned_table(
+    'CREATE TABLE IF NOT EXISTS %I '
+      '(wad_in_entry_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' 
+      ',wad_in_serial_id INT8' 
+      ',reserve_pub BYTEA NOT NULL CHECK(LENGTH(reserve_pub)=32)'
+      ',purse_pub BYTEA PRIMARY KEY CHECK(LENGTH(purse_pub)=32)'
+      ',h_contract BYTEA NOT NULL CHECK(LENGTH(h_contract)=64)'
+      ',purse_expiration INT8 NOT NULL'
+      ',merge_timestamp INT8 NOT NULL'
+      ',amount_with_fee_val INT8 NOT NULL'
+      ',amount_with_fee_frac INT4 NOT NULL'
+      ',wad_fee_val INT8 NOT NULL'
+      ',wad_fee_frac INT4 NOT NULL'
+      ',deposit_fees_val INT8 NOT NULL'
+      ',deposit_fees_frac INT4 NOT NULL'
+      ',reserve_sig BYTEA NOT NULL CHECK (LENGTH(reserve_sig)=64)'
+      ',purse_sig BYTEA NOT NULL CHECK (LENGTH(purse_sig)=64)'
+    ') %s ;'
+    ,table_name
+    ,'PARTITION BY HASH (purse_pub)'
+    ,shard_suffix
+  );
+  table_name = concat_ws('_', table_name, shard_suffix);
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_reserve_pub '
+    'ON ' || table_name || ' '
+    '(reserve_pub);'
+  );
+  EXECUTE FORMAT (
+    'COMMENT ON INDEX ' || table_name || '_reserve_pub '
+    'IS ' || quote_literal('needed in reserve history computation') || ';'
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION add_constraints_to_wad_in_entries_partition(
+  IN partition_suffix VARCHAR
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  EXECUTE FORMAT (
+    'ALTER TABLE wad_in_entries_' || partition_suffix || ' '
+      'ADD CONSTRAINT wad_in_entries_' || partition_suffix || 
'_wad_in_entry_serial_id_key '
+        'UNIQUE (wad_in_entry_serial_id) '
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_hash_partition(
+    source_table_name VARCHAR
+    ,modulus INTEGER
+    ,partition_num INTEGER
+  )
+  RETURNS VOID
+  LANGUAGE plpgsql
+AS $$
+BEGIN
+  RAISE NOTICE 'Creating partition %_%', source_table_name, partition_num;
+  EXECUTE FORMAT(
+    'CREATE TABLE IF NOT EXISTS %I '
+      'PARTITION OF %I '
+      'FOR VALUES WITH (MODULUS %s, REMAINDER %s)'
+    ,source_table_name || '_' || partition_num
+    ,source_table_name
+    ,modulus
+    ,partition_num-1
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_range_partition(
+  source_table_name VARCHAR
+  ,partition_num INTEGER
+)
+  RETURNS void
+  LANGUAGE plpgsql
+AS $$
+BEGIN
+  RAISE NOTICE 'TODO';
+END
+$$;
+CREATE OR REPLACE FUNCTION detach_default_partitions()
+  RETURNS VOID
+  LANGUAGE plpgsql
+AS $$
+BEGIN
+  RAISE NOTICE 'Detaching all default table partitions';
+  ALTER TABLE IF EXISTS wire_targets
+    DETACH PARTITION wire_targets_default;
+  ALTER TABLE IF EXISTS reserves
+    DETACH PARTITION reserves_default;
+  ALTER TABLE IF EXISTS reserves_in
+    DETACH PARTITION reserves_in_default;
+  ALTER TABLE IF EXISTS reserves_close
+    DETACH PARTITION reserves_close_default;
+  ALTER TABLE IF EXISTS history_requests
+    DETACH partition history_requests_default;
+  ALTER TABLE IF EXISTS close_requests
+    DETACH partition close_requests_default;
+  ALTER TABLE IF EXISTS reserves_open_requests
+    DETACH partition reserves_open_requests_default;
+  ALTER TABLE IF EXISTS reserves_out
+    DETACH PARTITION reserves_out_default;
+  ALTER TABLE IF EXISTS reserves_out_by_reserve
+    DETACH PARTITION reserves_out_by_reserve_default;
+  ALTER TABLE IF EXISTS known_coins
+    DETACH PARTITION known_coins_default;
+  ALTER TABLE IF EXISTS refresh_commitments
+    DETACH PARTITION refresh_commitments_default;
+  ALTER TABLE IF EXISTS refresh_revealed_coins
+    DETACH PARTITION refresh_revealed_coins_default;
+  ALTER TABLE IF EXISTS refresh_transfer_keys
+    DETACH PARTITION refresh_transfer_keys_default;
+  ALTER TABLE IF EXISTS deposits
+    DETACH PARTITION deposits_default;
+  ALTER TABLE IF EXISTS refunds
+    DETACH PARTITION refunds_default;
+  ALTER TABLE IF EXISTS wire_out
+    DETACH PARTITION wire_out_default;
+  ALTER TABLE IF EXISTS aggregation_transient
+    DETACH PARTITION aggregation_transient_default;
+  ALTER TABLE IF EXISTS aggregation_tracking
+    DETACH PARTITION aggregation_tracking_default;
+  ALTER TABLE IF EXISTS recoup
+    DETACH PARTITION recoup_default;
+  ALTER TABLE IF EXISTS recoup_by_reserve
+    DETACH PARTITION recoup_by_reserve_default;
+  ALTER TABLE IF EXISTS recoup_refresh
+    DETACH PARTITION recoup_refresh_default;
+  ALTER TABLE IF EXISTS prewire
+    DETACH PARTITION prewire_default;
+  ALTER TABLE IF EXISTS cs_nonce_locks
+    DETACH partition cs_nonce_locks_default;
+  ALTER TABLE IF EXISTS purse_requests
+    DETACH partition purse_requests_default;
+  ALTER TABLE IF EXISTS purse_decision
+    DETACH partition purse_decision_default;
+  ALTER TABLE IF EXISTS purse_merges
+    DETACH partition purse_merges_default;
+  ALTER TABLE IF EXISTS account_merges
+    DETACH partition account_merges_default;
+  ALTER TABLE IF EXISTS contracts
+    DETACH partition contracts_default;
+  ALTER TABLE IF EXISTS purse_deposits
+    DETACH partition purse_deposits_default;
+  ALTER TABLE IF EXISTS wad_out_entries
+    DETACH partition wad_out_entries_default;
+  ALTER TABLE IF EXISTS wads_in
+    DETACH partition wads_in_default;
+  ALTER TABLE IF EXISTS wad_in_entries
+    DETACH partition wad_in_entries_default;
+END
+$$;
+COMMENT ON FUNCTION detach_default_partitions
+  IS 'We need to drop default and create new one before deleting the default 
partitions
+      otherwise constraints get lost too. Might be needed in sharding too';
+CREATE OR REPLACE FUNCTION drop_default_partitions()
+  RETURNS VOID
+  LANGUAGE plpgsql
+AS $$
+BEGIN
+  RAISE NOTICE 'Dropping default table partitions';
+  DROP TABLE IF EXISTS wire_targets_default;
+  DROP TABLE IF EXISTS reserves_default;
+  DROP TABLE IF EXISTS reserves_in_default;
+  DROP TABLE IF EXISTS reserves_close_default;
+  DROP TABLE IF EXISTS reserves_open_requests_default;
+  DROP TABLE IF EXISTS history_requests_default;
+  DROP TABLE IF EXISTS close_requests_default;
+  DROP TABLE IF EXISTS reserves_out_default;
+  DROP TABLE IF EXISTS reserves_out_by_reserve_default;
+  DROP TABLE IF EXISTS known_coins_default;
+  DROP TABLE IF EXISTS refresh_commitments_default;
+  DROP TABLE IF EXISTS refresh_revealed_coins_default;
+  DROP TABLE IF EXISTS refresh_transfer_keys_default;
+  DROP TABLE IF EXISTS deposits_default;
+  DROP TABLE IF EXISTS refunds_default;
+  DROP TABLE IF EXISTS wire_out_default;
+  DROP TABLE IF EXISTS aggregation_transient_default;
+  DROP TABLE IF EXISTS aggregation_tracking_default;
+  DROP TABLE IF EXISTS recoup_default;
+  DROP TABLE IF EXISTS recoup_by_reserve_default;
+  DROP TABLE IF EXISTS recoup_refresh_default;
+  DROP TABLE IF EXISTS prewire_default;
+  DROP TABLE IF EXISTS cs_nonce_locks_default;
+  DROP TABLE IF EXISTS purse_requests_default;
+  DROP TABLE IF EXISTS purse_decision_default;
+  DROP TABLE IF EXISTS purse_merges_default;
+  DROP TABLE IF EXISTS account_merges_default;
+  DROP TABLE IF EXISTS purse_deposits_default;
+  DROP TABLE IF EXISTS contracts_default;
+  DROP TABLE IF EXISTS wad_out_entries_default;
+  DROP TABLE IF EXISTS wads_in_default;
+  DROP TABLE IF EXISTS wad_in_entries_default;
+END
+$$;
+COMMENT ON FUNCTION drop_default_partitions
+  IS 'Drop all default partitions once other partitions are attached.
+      Might be needed in sharding too.';
+CREATE OR REPLACE FUNCTION create_partitions(
+    num_partitions INTEGER
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  modulus INTEGER;
+BEGIN
+  modulus := num_partitions;
+  PERFORM detach_default_partitions();
+  LOOP
+    PERFORM create_hash_partition(
+      'wire_targets'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM add_constraints_to_wire_targets_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'reserves'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM create_hash_partition(
+      'reserves_in'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM add_constraints_to_reserves_in_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'reserves_close'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_reserves_close_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'reserves_out'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM add_constraints_to_reserves_out_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'reserves_out_by_reserve'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM create_hash_partition(
+      'known_coins'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM add_constraints_to_known_coins_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'refresh_commitments'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_refresh_commitments_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'refresh_revealed_coins'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_refresh_revealed_coins_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'refresh_transfer_keys'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_refresh_transfer_keys_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'deposits'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM add_constraints_to_deposits_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'refunds'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM add_constraints_to_refunds_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'wire_out'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM add_constraints_to_wire_out_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'aggregation_transient'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM create_hash_partition(
+      'aggregation_tracking'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_aggregation_tracking_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'recoup'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM add_constraints_to_recoup_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'recoup_by_reserve'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM create_hash_partition(
+      'recoup_refresh'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_recoup_refresh_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'prewire'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM create_hash_partition(
+      'cs_nonce_locks'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_cs_nonce_locks_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'close_requests'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM create_hash_partition(
+      'reserves_open_requests'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_reserves_open_request_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'history_requests'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM create_hash_partition(
+      'purse_requests'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_purse_requests_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'purse_decision'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_purse_decision_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'purse_merges'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM add_constraints_to_purse_merges_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'account_merges'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_account_merges_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'contracts'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM add_constraints_to_contracts_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'purse_deposits'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_purse_deposits_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'wad_out_entries'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_wad_out_entries_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'wads_in'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM add_constraints_to_wads_in_partition(num_partitions::varchar);
+    PERFORM create_hash_partition(
+      'wad_in_entries'
+      ,modulus
+      ,num_partitions
+    );
+    PERFORM 
add_constraints_to_wad_in_entries_partition(num_partitions::varchar);
+    num_partitions=num_partitions-1;
+    EXIT WHEN num_partitions=0;
+  END LOOP;
+  PERFORM drop_default_partitions();
+END
+$$;
+CREATE OR REPLACE FUNCTION create_foreign_hash_partition(
+    source_table_name VARCHAR
+    ,modulus INTEGER
+    ,shard_suffix VARCHAR
+    ,current_shard_num INTEGER
+    ,local_user VARCHAR DEFAULT 'taler-exchange-httpd'
+  )
+  RETURNS VOID
+  LANGUAGE plpgsql
+AS $$
+BEGIN
+  RAISE NOTICE 'Creating %_% on %', source_table_name, shard_suffix, 
shard_suffix;
+  EXECUTE FORMAT(
+    'CREATE FOREIGN TABLE IF NOT EXISTS %I '
+      'PARTITION OF %I '
+      'FOR VALUES WITH (MODULUS %s, REMAINDER %s) '
+      'SERVER %I'
+    ,source_table_name || '_' || shard_suffix
+    ,source_table_name
+    ,modulus
+    ,current_shard_num-1
+    ,shard_suffix
+  );
+  EXECUTE FORMAT(
+    'ALTER FOREIGN TABLE %I OWNER TO %I'
+    ,source_table_name || '_' || shard_suffix
+    ,local_user
+  );
+END
+$$;
+CREATE OR REPLACE FUNCTION create_foreign_range_partition(
+  source_table_name VARCHAR
+  ,partition_num INTEGER
+)
+  RETURNS VOID
+  LANGUAGE plpgsql
+AS $$
+BEGIN
+   RAISE NOTICE 'TODO';
+END
+$$;
+CREATE OR REPLACE FUNCTION prepare_sharding()
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  CREATE EXTENSION IF NOT EXISTS postgres_fdw;
+  PERFORM detach_default_partitions();
+  ALTER TABLE IF EXISTS wire_targets
+    DROP CONSTRAINT IF EXISTS wire_targets_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS reserves
+    DROP CONSTRAINT IF EXISTS reserves_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS reserves_in
+    DROP CONSTRAINT IF EXISTS reserves_in_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS reserves_close
+    DROP CONSTRAINT IF EXISTS reserves_close_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS reserves_out
+    DROP CONSTRAINT IF EXISTS reserves_out_pkey CASCADE
+    ,DROP CONSTRAINT IF EXISTS reserves_out_denominations_serial_fkey
+    ,DROP CONSTRAINT IF EXISTS reserves_out_h_blind_ev_key
+  ;
+  ALTER TABLE IF EXISTS known_coins
+    DROP CONSTRAINT IF EXISTS known_coins_pkey CASCADE
+    ,DROP CONSTRAINT IF EXISTS known_coins_denominations_serial_fkey
+  ;
+  ALTER TABLE IF EXISTS refresh_commitments
+    DROP CONSTRAINT IF EXISTS refresh_commitments_pkey CASCADE
+    ,DROP CONSTRAINT IF EXISTS refresh_old_coin_pub_fkey
+  ;
+  ALTER TABLE IF EXISTS refresh_revealed_coins
+    DROP CONSTRAINT IF EXISTS refresh_revealed_coins_pkey CASCADE
+    ,DROP CONSTRAINT IF EXISTS refresh_revealed_coins_denominations_serial_fkey
+  ;
+  ALTER TABLE IF EXISTS refresh_transfer_keys
+    DROP CONSTRAINT IF EXISTS refresh_transfer_keys_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS deposits
+    DROP CONSTRAINT IF EXISTS deposits_pkey CASCADE
+    ,DROP CONSTRAINT IF EXISTS deposits_policy_details_serial_id_fkey
+    ,DROP CONSTRAINT IF EXISTS 
deposits_coin_pub_merchant_pub_h_contract_terms_key CASCADE
+  ;
+  ALTER TABLE IF EXISTS refunds
+    DROP CONSTRAINT IF EXISTS refunds_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS wire_out
+    DROP CONSTRAINT IF EXISTS wire_out_pkey CASCADE
+    ,DROP CONSTRAINT IF EXISTS wire_out_wtid_raw_key CASCADE
+  ;
+  ALTER TABLE IF EXISTS aggregation_tracking
+    DROP CONSTRAINT IF EXISTS aggregation_tracking_pkey CASCADE
+    ,DROP CONSTRAINT IF EXISTS aggregation_tracking_wtid_raw_fkey
+  ;
+  ALTER TABLE IF EXISTS recoup
+    DROP CONSTRAINT IF EXISTS recoup_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS recoup_refresh
+    DROP CONSTRAINT IF EXISTS recoup_refresh_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS prewire
+    DROP CONSTRAINT IF EXISTS prewire_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS cs_nonce_locks
+    DROP CONSTRAINT IF EXISTS cs_nonce_locks_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS purse_requests
+    DROP CONSTRAINT IF EXISTS purse_requests_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS purse_decision
+    DROP CONSTRAINT IF EXISTS purse_decision_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS purse_merges
+    DROP CONSTRAINT IF EXISTS purse_merges_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS account_merges
+    DROP CONSTRAINT IF EXISTS account_merges_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS contracts
+    DROP CONSTRAINT IF EXISTS contracts_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS history_requests
+    DROP CONSTRAINT IF EXISTS history_requests_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS close_requests
+    DROP CONSTRAINT IF EXISTS close_requests_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS purse_deposits
+    DROP CONSTRAINT IF EXISTS purse_deposits_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS wads_out
+    DROP CONSTRAINT IF EXISTS wads_out_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS wad_out_entries
+    DROP CONSTRAINT IF EXISTS wad_out_entries_pkey CASCADE
+  ;
+  ALTER TABLE IF EXISTS wads_in
+    DROP CONSTRAINT IF EXISTS wads_in_pkey CASCADE
+    ,DROP CONSTRAINT IF EXISTS wads_in_wad_id_origin_exchange_url_key
+  ;
+  ALTER TABLE IF EXISTS wad_in_entries
+    DROP CONSTRAINT IF EXISTS wad_in_entries_pkey CASCADE
+  ;
+END
+$$;
+CREATE OR REPLACE FUNCTION create_shard_server(
+    shard_suffix VARCHAR
+    ,total_num_shards INTEGER
+    ,current_shard_num INTEGER
+    ,remote_host VARCHAR
+    ,remote_user VARCHAR
+    ,remote_user_password VARCHAR
+    ,remote_db_name VARCHAR DEFAULT 'taler-exchange'
+    ,remote_port INTEGER DEFAULT '5432'
+    ,local_user VARCHAR DEFAULT 'taler-exchange-httpd'
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+BEGIN
+  RAISE NOTICE 'Creating server %', remote_host;
+  EXECUTE FORMAT(
+    'CREATE SERVER IF NOT EXISTS %I '
+      'FOREIGN DATA WRAPPER postgres_fdw '
+      'OPTIONS (dbname %L, host %L, port %L)'
+    ,shard_suffix
+    ,remote_db_name
+    ,remote_host
+    ,remote_port
+  );
+  EXECUTE FORMAT(
+    'CREATE USER MAPPING IF NOT EXISTS '
+      'FOR %I SERVER %I '
+      'OPTIONS (user %L, password %L)'
+    ,local_user
+    ,shard_suffix
+    ,remote_user
+    ,remote_user_password
+  );
+  EXECUTE FORMAT(
+    'GRANT ALL PRIVILEGES '
+      'ON FOREIGN SERVER %I '
+      'TO %I;'
+    ,shard_suffix
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'wire_targets'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'reserves'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'reserves_in'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'reserves_out'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'reserves_out_by_reserve'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'reserves_close'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'history_requests'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'close_requests'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'open_requests'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'known_coins'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'refresh_commitments'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'refresh_revealed_coins'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'refresh_transfer_keys'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'deposits'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'refunds'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'wire_out'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'aggregation_transient'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'aggregation_tracking'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'recoup'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'recoup_by_reserve'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'recoup_refresh'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'prewire'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'cs_nonce_locks'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'purse_requests'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'purse_decision'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'purse_merges'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'account_merges'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'contracts'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'purse_deposits'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'wad_out_entries'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'wads_in'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+  PERFORM create_foreign_hash_partition(
+    'wad_in_entries'
+    ,total_num_shards
+    ,shard_suffix
+    ,current_shard_num
+    ,local_user
+  );
+END
+$$;
+COMMENT ON FUNCTION create_shard_server
+  IS 'Create a shard server on the master
+      node with all foreign tables and user mappings';
+CREATE OR REPLACE FUNCTION create_foreign_servers(
+  amount INTEGER
+  ,domain VARCHAR
+  ,remote_user VARCHAR DEFAULT 'taler'
+  ,remote_user_password VARCHAR DEFAULT 'taler'
+)
+  RETURNS VOID
+  LANGUAGE plpgsql
+AS $$
+BEGIN
+  PERFORM prepare_sharding();
+  FOR i IN 1..amount LOOP
+    PERFORM create_shard_server(
+      i::varchar
+     ,amount
+     ,i
+     ,'shard-' || i::varchar || '.' || domain
+     ,remote_user
+     ,remote_user_password
+     ,'taler-exchange'
+     ,'5432'
+     ,'taler-exchange-httpd'
+    );
+  END LOOP;
+  PERFORM drop_default_partitions();
+END
+$$;
+CREATE OR REPLACE FUNCTION setup_shard(
+  shard_idx INTEGER
+)
+RETURNS VOID
+LANGUAGE plpgsql
+AS $$
+DECLARE
+  shard_suffix VARCHAR;
+BEGIN
+  shard_suffix = shard_idx::varchar;
+  PERFORM create_table_wire_targets(shard_suffix);
+  PERFORM add_constraints_to_wire_targets_partition(shard_suffix);
+  PERFORM create_table_reserves(shard_suffix);
+  PERFORM create_table_legitimization_requirements(shard_suffix);
+  PERFORM 
add_constraints_to_legitimization_requirements_partition(shard_suffix);
+  PERFORM create_table_legitimization_processes(shard_suffix);
+  PERFORM add_constraints_to_legitimization_processes_partition(shard_suffix);
+  PERFORM create_table_reserves_in(shard_suffix);
+  PERFORM add_constraints_to_reserves_in_partition(shard_suffix);
+  PERFORM create_table_reserves_close(shard_suffix);
+  PERFORM add_constraints_to_reserves_close_partition(shard_suffix);
+  PERFORM create_table_reserves_open_requests(shard_suffix);
+  PERFORM add_constraints_to_reserves_open_request_partition(shard_suffix);
+  PERFORM create_table_reserves_open_deposits(shard_suffix);
+  PERFORM add_constraints_to_reserves_open_deposits_partition(shard_suffix);
+  PERFORM create_table_reserves_out(shard_suffix);
+  PERFORM add_constraints_to_reserves_out_partition(shard_suffix);
+  PERFORM create_table_reserves_out_by_reserve(shard_suffix);
+  PERFORM create_table_known_coins(shard_suffix);
+  PERFORM add_constraints_to_known_coins_partition(shard_suffix);
+  PERFORM create_table_refresh_commitments(shard_suffix);
+  PERFORM add_constraints_to_refresh_commitments_partition(shard_suffix);
+  PERFORM create_table_refresh_revealed_coins(shard_suffix);
+  PERFORM add_constraints_to_refresh_revealed_coins_partition(shard_suffix);
+  PERFORM create_table_refresh_transfer_keys(shard_suffix);
+  PERFORM add_constraints_to_refresh_transfer_keys_partition(shard_suffix);
+  PERFORM create_table_deposits(shard_suffix);
+  PERFORM add_constraints_to_deposits_partition(shard_suffix);
+  PERFORM create_table_deposits_by_ready(shard_suffix);
+  PERFORM create_table_deposits_for_matching(shard_suffix);
+  PERFORM create_table_refunds(shard_suffix);
+  PERFORM add_constraints_to_refunds_partition(shard_suffix);
+  PERFORM create_table_wire_out(shard_suffix);
+  PERFORM add_constraints_to_wire_out_partition(shard_suffix);
+  PERFORM create_table_aggregation_transient(shard_suffix);
+  PERFORM create_table_aggregation_tracking(shard_suffix);
+  PERFORM add_constraints_to_aggregation_tracking_partition(shard_suffix);
+  PERFORM create_table_recoup(shard_suffix);
+  PERFORM add_constraints_to_recoup_partition(shard_suffix);
+  PERFORM create_table_recoup_by_reserve(shard_suffix);
+  PERFORM create_table_recoup_refresh(shard_suffix);
+  PERFORM add_constraints_to_recoup_refresh_partition(shard_suffix);
+  PERFORM create_table_prewire(shard_suffix);
+  PERFORM create_table_cs_nonce_locks(shard_suffix);
+  PERFORM add_constraints_to_cs_nonce_locks_partition(shard_suffix);
+  PERFORM create_table_purse_requests(shard_suffix);
+  PERFORM add_constraints_to_purse_requests_partition(shard_suffix);
+  PERFORM create_table_purse_decision(shard_suffix);
+  PERFORM add_constraints_to_purse_decision_partition(shard_suffix);
+  PERFORM create_table_purse_merges(shard_suffix);
+  PERFORM add_constraints_to_purse_merges_partition(shard_suffix);
+  PERFORM create_table_account_merges(shard_suffix);
+  PERFORM add_constraints_to_account_merges_partition(shard_suffix);
+  PERFORM create_table_contracts(shard_suffix);
+  PERFORM add_constraints_to_contracts_partition(shard_suffix);
+  PERFORM create_table_history_requests(shard_suffix);
+  PERFORM create_table_close_requests(shard_suffix);
+  PERFORM add_constraints_to_close_requests_partition(shard_suffix);
+  PERFORM create_table_purse_deposits(shard_suffix);
+  PERFORM add_constraints_to_purse_deposits_partition(shard_suffix);
+  PERFORM create_table_wad_out_entries(shard_suffix);
+  PERFORM add_constraints_to_wad_out_entries_partition(shard_suffix);
+  PERFORM create_table_wads_in(shard_suffix);
+  PERFORM add_constraints_to_wads_in_partition(shard_suffix);
+  PERFORM create_table_wad_in_entries(shard_suffix);
+  PERFORM add_constraints_to_wad_in_entries_partition(shard_suffix);
+END
+$$;
+COMMIT;
diff --git 
a/src/exchangedb/test-exchangedb-populate-select-refunds-by-coin-postgres 
b/src/exchangedb/test-exchangedb-populate-select-refunds-by-coin-postgres
new file mode 100755
index 00000000..ce7ebb71
--- /dev/null
+++ b/src/exchangedb/test-exchangedb-populate-select-refunds-by-coin-postgres
@@ -0,0 +1,210 @@
+#! /bin/bash
+
+# test-exchangedb-populate-select-refunds-by-coin-postgres - temporary wrapper 
script for .libs/test-exchangedb-populate-select-refunds-by-coin-postgres
+# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-15
+#
+# The test-exchangedb-populate-select-refunds-by-coin-postgres program cannot 
be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s|\([`"$\\]\)|\\\1|g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=""
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='2.4.6'
+  notinst_deplibs=' libtalerexchangedb.la ../../src/json/libtalerjson.la 
../../src/util/libtalerutil.la ../../src/pq/libtalerpq.la'
+else
+  # When we are sourced in execute mode, $file and $ECHO are already set.
+  if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+    file="$0"
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+    ECHO="printf %s\\n"
+  fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ that is used only on
+# windows platforms, and (c) all begin with the string --lt-
+# (application programs are unlikely to have options that match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's ../../libtool value, followed by no.
+lt_option_debug=
+func_parse_lt_options ()
+{
+  lt_script_arg0=$0
+  shift
+  for lt_opt
+  do
+    case "$lt_opt" in
+    --lt-debug) lt_option_debug=1 ;;
+    --lt-dump-script)
+        lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 
's%/[^/]*$%%'`
+        test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=.
+        lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 
's%^.*/%%'`
+        cat "$lt_dump_D/$lt_dump_F"
+        exit 0
+      ;;
+    --lt-*)
+        $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
+        exit 1
+      ;;
+    esac
+  done
+
+  # Print the debug banner immediately:
+  if test -n "$lt_option_debug"; then
+    echo 
"test-exchangedb-populate-select-refunds-by-coin-postgres:test-exchangedb-populate-select-refunds-by-coin-postgres:$LINENO:
 libtool wrapper (GNU libtool) 2.4.6 Debian-2.4.6-15" 1>&2
+  fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+  lt_dump_args_N=1;
+  for lt_arg
+  do
+    $ECHO 
"test-exchangedb-populate-select-refunds-by-coin-postgres:test-exchangedb-populate-select-refunds-by-coin-postgres:$LINENO:
 newargv[$lt_dump_args_N]: $lt_arg"
+    lt_dump_args_N=`expr $lt_dump_args_N + 1`
+  done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+
+      if test -n "$lt_option_debug"; then
+        $ECHO 
"test-exchangedb-populate-select-refunds-by-coin-postgres:test-exchangedb-populate-select-refunds-by-coin-postgres:$LINENO:
 newargv[0]: $progdir/$program" 1>&2
+        func_lt_dump_args ${1+"$@"} 1>&2
+      fi
+      exec "$progdir/$program" ${1+"$@"}
+
+      $ECHO "$0: cannot exec $program $*" 1>&2
+      exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from $@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+  case " $* " in
+  *\ --lt-*)
+    for lt_wr_arg
+    do
+      case $lt_wr_arg in
+      --lt-*) ;;
+      *) set x "$@" "$lt_wr_arg"; shift;;
+      esac
+      shift
+    done ;;
+  esac
+  func_exec_program_core ${1+"$@"}
+}
+
+  # Parse options
+  func_parse_lt_options "$0" ${1+"$@"}
+
+  # Find the directory that this script lives in.
+  thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'`
+  test "x$thisdir" = "x$file" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'`
+  while test -n "$file"; do
+    destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'`
+
+    # If there was a directory component, then change thisdir.
+    if test "x$destdir" != "x$file"; then
+      case "$destdir" in
+      [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
+      *) thisdir="$thisdir/$destdir" ;;
+      esac
+    fi
+
+    file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'`
+    file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'`
+  done
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no
+  if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then
+    # special case for '.'
+    if test "$thisdir" = "."; then
+      thisdir=`pwd`
+    fi
+    # remove .libs from thisdir
+    case "$thisdir" in
+    *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 
's%[\\/][^\\/]*$%%'` ;;
+    .libs )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=`cd "$thisdir" && pwd`
+  test -n "$absdir" && thisdir="$absdir"
+
+  program='test-exchangedb-populate-select-refunds-by-coin-postgres'
+  progdir="$thisdir/.libs"
+
+
+  if test -f "$progdir/$program"; then
+    # Add our own library path to LD_LIBRARY_PATH
+    
LD_LIBRARY_PATH="/home/priscilla/exchange/src/exchangedb/.libs:/home/priscilla/exchange/src/json/.libs:/home/priscilla/exchange/src/util/.libs:/home/priscilla/exchange/src/pq/.libs:$LD_LIBRARY_PATH"
+
+    # Some systems cannot cope with colon-terminated LD_LIBRARY_PATH
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    LD_LIBRARY_PATH=`$ECHO "$LD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'`
+
+    export LD_LIBRARY_PATH
+
+    if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
+      # Run the actual program with our arguments.
+      func_exec_program ${1+"$@"}
+    fi
+  else
+    # The program doesn't exist.
+    $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2
+    $ECHO "This script is just a wrapper for $program." 1>&2
+    $ECHO "See the libtool documentation for more information." 1>&2
+    exit 1
+  fi
+fi

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]