commit 291363e2c291543b59203145e039f16446153318
parent ed83bf53a07ba09d174a7bc6472ea69260eb96ff
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 3 Jun 2026 00:59:51 +0200
another fix
Diffstat:
2 files changed, 243 insertions(+), 135 deletions(-)
diff --git a/src/backenddb/pg_statistics_helpers.sql b/src/backenddb/pg_statistics_helpers.sql
@@ -215,7 +215,7 @@ BEGIN
(my_meta
,my_start
,in_delta)
- ON CONFLICT (imeta_serial_id, merchant_serial, slot)
+ ON CONFLICT (imeta_serial_id, slot)
DO UPDATE SET
delta = msce.delta + in_delta
RETURNING nevent_serial_id
@@ -311,7 +311,7 @@ BEGIN
,(in_delta).val
,(in_delta).frac
)
- ON CONFLICT (imeta_serial_id, merchant_serial, slot, delta_curr)
+ ON CONFLICT (imeta_serial_id, slot, delta_curr)
DO UPDATE SET
delta_value = msae.delta_value + (in_delta).val
+ CASE
diff --git a/src/backenddb/sql-schema/merchant-0037.sql b/src/backenddb/sql-schema/merchant-0037.sql
@@ -29,141 +29,249 @@ CREATE PROCEDURE merchant.merchant_0037_init(s TEXT)
LANGUAGE plpgsql
AS $OUTER$
BEGIN
- EXECUTE format('CREATE TABLE %I.merchant_tos_accepted ('
- || ' tos_accepted_serial INT8 GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
- || ' exchange_url TEXT NOT NULL UNIQUE,'
- || ' tos_version TEXT NOT NULL'
- || ')', s);
- EXECUTE format('COMMENT ON TABLE %I.merchant_tos_accepted IS %L', s,
+ EXECUTE format('SET LOCAL search_path TO %I', s);
+
+ CREATE TABLE merchant_tos_accepted (
+ tos_accepted_serial INT8 GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
+ exchange_url TEXT NOT NULL UNIQUE,
+ tos_version TEXT NOT NULL
+ );
+ COMMENT ON TABLE merchant_tos_accepted IS
'Latest Taler-Terms-Version (etag) of the terms of service accepted'
- ' early (ahead of the KYC flow) by the user, one row per exchange.');
- EXECUTE format('COMMENT ON COLUMN %I.merchant_tos_accepted.exchange_url IS %L',
- s, 'Base URL of the exchange the terms of service were accepted for.');
- EXECUTE format('COMMENT ON COLUMN %I.merchant_tos_accepted.tos_version IS %L',
- s, 'Accepted Taler-Terms-Version of the exchange terms of service.');
-
- -- merchant_categories
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.handle_category_changes()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER trigger_category_changes'
- || ' AFTER INSERT OR UPDATE OR DELETE'
- || ' ON %I.merchant_categories'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.handle_category_changes()', s, s);
-
- -- recreate triggers lost in merchant-0036...
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.handle_inventory_changes()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER trigger_inventory_changes'
- || ' AFTER INSERT OR UPDATE OR DELETE'
- || ' ON %I.merchant_inventory'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.handle_inventory_changes()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_orders_insert_statistics_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_orders_on_insert_statistic'
- || ' AFTER INSERT'
- || ' ON %I.merchant_orders'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_orders_insert_statistics_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_contract_terms_insert_statistics_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_contract_terms_on_insert_statistic'
- || ' AFTER INSERT'
- || ' ON %I.merchant_contract_terms'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_contract_terms_insert_statistics_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_contract_terms_update_statistics_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_contract_terms_on_update_statistic'
- || ' AFTER UPDATE'
- || ' ON %I.merchant_contract_terms'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_contract_terms_update_statistics_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_refunds_insert_statistics_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_refunds_on_insert_statistic'
- || ' AFTER INSERT'
- || ' ON %I.merchant_refunds'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_refunds_insert_statistics_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_transfer_signatures_insert_statistics_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_transfer_signatures_on_insert_statistic'
- || ' AFTER INSERT'
- || ' ON %I.merchant_transfer_signatures'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_transfer_signatures_insert_statistics_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_issued_tokens_insert_statistics_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_issued_tokens_on_insert_statistic'
- || ' AFTER INSERT'
- || ' ON %I.merchant_issued_tokens'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_issued_tokens_insert_statistics_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_used_tokens_insert_statistics_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_used_tokens_on_insert_statistic'
- || ' AFTER INSERT'
- || ' ON %I.merchant_used_tokens'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_used_tokens_insert_statistics_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_deposits_insert_statistics_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_deposits_on_insert_statistic'
- || ' AFTER INSERT'
- || ' ON %I.merchant_deposits'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_deposits_insert_statistics_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_expected_transfers_insert_statistics_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_expected_transfers_on_insert_statistic'
- || ' AFTER INSERT'
- || ' ON %I.merchant_expected_transfers'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_expected_transfers_insert_statistics_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_expected_transfers_update_statistics_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_expected_transfers_on_update_statistic'
- || ' AFTER INSERT'
- || ' ON %I.merchant_expected_transfers'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_expected_transfers_update_statistics_trigger()', s, s);
-
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_expected_transfers_insert_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_expected_transfers_on_insert'
- || ' BEFORE INSERT'
- || ' ON %I.merchant_expected_transfers'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_expected_transfers_insert_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_expected_transfers_update_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_expected_transfers_on_update'
- || ' BEFORE UPDATE'
- || ' ON %I.merchant_expected_transfers'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_expected_transfers_update_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_transfers_insert_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_transfers_on_insert'
- || ' BEFORE INSERT'
- || ' ON %I.merchant_transfers'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_transfers_insert_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_kyc_insert_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_kyc_on_insert'
- || ' AFTER INSERT'
- || ' ON %I.merchant_kyc'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_kyc_insert_trigger()', s, s);
-
- EXECUTE format('CREATE OR REPLACE FUNCTION %I.merchant_kyc_update_trigger()'
- || ' RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;', s);
- EXECUTE format('CREATE TRIGGER merchant_kyc_on_update'
- || ' AFTER UPDATE'
- || ' ON %I.merchant_kyc'
- || ' FOR EACH ROW EXECUTE FUNCTION %I.merchant_kyc_update_trigger()', s, s);
+ ' early (ahead of the KYC flow) by the user, one row per exchange.';
+ COMMENT ON COLUMN merchant_tos_accepted.exchange_url IS
+ 'Base URL of the exchange the terms of service were accepted for.';
+ COMMENT ON COLUMN merchant_tos_accepted.tos_version IS
+ 'Accepted Taler-Terms-Version of the exchange terms of service.';
+
+ -- Restore triggers previously lost in merchant-0036
+ CREATE OR REPLACE FUNCTION handle_category_changes()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER trigger_category_changes
+ AFTER INSERT OR UPDATE OR DELETE
+ ON merchant_categories
+ FOR EACH ROW EXECUTE FUNCTION handle_category_changes();
+
+ CREATE OR REPLACE FUNCTION handle_inventory_changes()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER trigger_inventory_changes
+ AFTER INSERT OR UPDATE OR DELETE
+ ON merchant_inventory
+ FOR EACH ROW EXECUTE FUNCTION handle_inventory_changes();
+
+ CREATE OR REPLACE FUNCTION merchant_orders_insert_statistics_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_orders_on_insert_statistic
+ AFTER INSERT
+ ON merchant_orders
+ FOR EACH ROW EXECUTE FUNCTION merchant_orders_insert_statistics_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_contract_terms_insert_statistics_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_contract_terms_on_insert_statistic
+ AFTER INSERT
+ ON merchant_contract_terms
+ FOR EACH ROW EXECUTE FUNCTION merchant_contract_terms_insert_statistics_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_contract_terms_update_statistics_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_contract_terms_on_update_statistic
+ AFTER UPDATE
+ ON merchant_contract_terms
+ FOR EACH ROW EXECUTE FUNCTION merchant_contract_terms_update_statistics_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_refunds_insert_statistics_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_refunds_on_insert_statistic
+ AFTER INSERT
+ ON merchant_refunds
+ FOR EACH ROW EXECUTE FUNCTION merchant_refunds_insert_statistics_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_transfer_signatures_insert_statistics_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_transfer_signatures_on_insert_statistic
+ AFTER INSERT
+ ON merchant_transfer_signatures
+ FOR EACH ROW EXECUTE FUNCTION merchant_transfer_signatures_insert_statistics_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_issued_tokens_insert_statistics_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_issued_tokens_on_insert_statistic
+ AFTER INSERT
+ ON merchant_issued_tokens
+ FOR EACH ROW EXECUTE FUNCTION merchant_issued_tokens_insert_statistics_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_used_tokens_insert_statistics_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_used_tokens_on_insert_statistic
+ AFTER INSERT
+ ON merchant_used_tokens
+ FOR EACH ROW EXECUTE FUNCTION merchant_used_tokens_insert_statistics_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_deposits_insert_statistics_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_deposits_on_insert_statistic
+ AFTER INSERT
+ ON merchant_deposits
+ FOR EACH ROW EXECUTE FUNCTION merchant_deposits_insert_statistics_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_expected_transfers_insert_statistics_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_expected_transfers_on_insert_statistic
+ AFTER INSERT
+ ON merchant_expected_transfers
+ FOR EACH ROW EXECUTE FUNCTION merchant_expected_transfers_insert_statistics_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_expected_transfers_update_statistics_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_expected_transfers_on_update_statistic
+ AFTER INSERT
+ ON merchant_expected_transfers
+ FOR EACH ROW EXECUTE FUNCTION merchant_expected_transfers_update_statistics_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_expected_transfers_insert_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_expected_transfers_on_insert
+ BEFORE INSERT
+ ON merchant_expected_transfers
+ FOR EACH ROW EXECUTE FUNCTION merchant_expected_transfers_insert_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_expected_transfers_update_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_expected_transfers_on_update
+ BEFORE UPDATE
+ ON merchant_expected_transfers
+ FOR EACH ROW EXECUTE FUNCTION merchant_expected_transfers_update_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_transfers_insert_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_transfers_on_insert
+ BEFORE INSERT
+ ON merchant_transfers
+ FOR EACH ROW EXECUTE FUNCTION merchant_transfers_insert_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_kyc_insert_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_kyc_on_insert
+ AFTER INSERT
+ ON merchant_kyc
+ FOR EACH ROW EXECUTE FUNCTION merchant_kyc_insert_trigger();
+
+ CREATE OR REPLACE FUNCTION merchant_kyc_update_trigger()
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NEW; END $$;
+ CREATE TRIGGER merchant_kyc_on_update
+ AFTER UPDATE
+ ON merchant_kyc
+ FOR EACH ROW EXECUTE FUNCTION merchant_kyc_update_trigger();
+
+ -- Install default statistics tracking, if not already present
+ -- (for existing instances, we would have copied it over, but
+ -- not for new instances created after the initial migration).
+ -- Enable interval statistics
+ INSERT INTO merchant_statistic_interval_meta
+ (slug
+ ,description
+ ,stype
+ ,ranges
+ ,precisions)
+ VALUES
+ ('orders-created'
+ ,'number of orders created (but not necessarily claimed by wallets)'
+ ,'number'
+ ,ARRAY(SELECT generate_series (1, 60*60, 60)) -- for last hour, per minute
+ || ARRAY(SELECT generate_series (60*60*2, 60*60*48, 60 * 60)) -- for last 2 days, per hour
+ ,array_fill (5, ARRAY[60]) -- precision: 5s
+ || array_fill (5 * 60, ARRAY[48-1]) -- precision: 5 minutes
+ ),
+ ('orders-claimed'
+ ,'number of orders claimed by a wallet (but not necessarily paid)'
+ ,'number'
+ ,ARRAY(SELECT generate_series (1, 60*60, 60)) -- for last hour, per minute
+ || ARRAY(SELECT generate_series (60*60*2, 60*60*48, 60 * 60)) -- for last 2 days, per hour
+ ,array_fill (5, ARRAY[60]) -- precision: 5s
+ || array_fill (5 * 60, ARRAY[48-1]) -- precision: 5 minutes
+ ),
+ ('orders-paid'
+ ,'number of orders paid (but not necessarily settled by the exchange)'
+ ,'number'
+ ,ARRAY(SELECT generate_series (1, 60*60, 60)) -- for last hour, per minute
+ || ARRAY(SELECT generate_series (60*60*2, 60*60*48, 60 * 60)) -- for last 2 days, per hour
+ ,array_fill (5, ARRAY[60]) -- precision: 5s
+ || array_fill (5 * 60, ARRAY[48-1]) -- precision: 5 minutes
+ ),
+ ('orders-settled'
+ ,'number of orders settled'
+ ,'number'
+ ,ARRAY(SELECT generate_series (1, 60*60, 60)) -- for last hour, per minute
+ || ARRAY(SELECT generate_series (60*60*2, 60*60*48, 60 * 60)) -- for last 2 days, per hour
+ ,array_fill (5, ARRAY[60]) -- precision: 5s
+ || array_fill (5 * 60, ARRAY[48-1]) -- precision: 5 minutes
+ ),
+ ('tokens-issued'
+ ,'number of tokens issued to customers'
+ ,'number'
+ ,ARRAY(SELECT generate_series (1, 60*60, 60)) -- for last hour, per minute
+ || ARRAY(SELECT generate_series (60*60*2, 60*60*48, 60 * 60)) -- for last 2 days, per hour
+ ,array_fill (5, ARRAY[60]) -- precision: 5s
+ || array_fill (5 * 60, ARRAY[48-1]) -- precision: 5 minutes
+ ),
+ ('tokens-used'
+ ,'number of tokens used by customers'
+ ,'number'
+ ,ARRAY(SELECT generate_series (1, 60*60, 60)) -- for last hour, per minute
+ || ARRAY(SELECT generate_series (60*60*2, 60*60*48, 60 * 60)) -- for last 2 days, per hour
+ ,array_fill (5, ARRAY[60]) -- precision: 5s
+ || array_fill (5 * 60, ARRAY[48-1]) -- precision: 5 minutes
+ )
+ ON CONFLICT DO NOTHING;
+
+ -- Enable bucket statistics
+ INSERT INTO merchant_statistic_bucket_meta
+ (slug
+ ,description
+ ,stype
+ ,ranges
+ ,ages)
+ VALUES
+ ('payments-received-after-deposit-fee'
+ ,'amount customers paid to us (excluded deposit fees paid by us or customers, wire fees are still deducted by the exchange)'
+ ,'amount'
+ ,ARRAY['hour'::merchant.statistic_range, 'day', 'week', 'month', 'quarter', 'year']
+ ,ARRAY[72, 14, 12, 24, 12, 10]
+ ),
+ ('total-deposit-fees-paid'
+ ,'deposit fees we or our customers paid to the exchange (includes those waived on refunds)'
+ ,'amount'
+ ,ARRAY['hour'::merchant.statistic_range, 'day', 'week', 'month', 'quarter', 'year']
+ ,ARRAY[72, 14, 12, 24, 12, 10]
+ ),
+ ('total-wire-fees-paid'
+ ,'wire fees we paid to the exchange'
+ ,'amount'
+ ,ARRAY['hour'::merchant.statistic_range, 'day', 'week', 'month', 'quarter', 'year']
+ ,ARRAY[72, 12, 12, 24, 12, 10]
+ ),
+ ('refunds-granted'
+ ,'refunds granted by us to our customers'
+ ,'amount'
+ ,ARRAY['hour'::merchant.statistic_range, 'day', 'week', 'month', 'quarter', 'year']
+ ,ARRAY[72, 14, 12, 24, 12, 10]
+ ),
+ ('tokens-issued'
+ ,'number of tokens issued to customers'
+ ,'number'
+ ,ARRAY['hour'::merchant.statistic_range, 'day', 'week', 'month', 'quarter', 'year']
+ ,ARRAY[72, 14, 12, 24, 12, 10]
+ ),
+ ('tokens-used'
+ ,'number of tokens used by customers'
+ ,'number'
+ ,ARRAY['hour'::merchant.statistic_range, 'day', 'week', 'month', 'quarter', 'year']
+ ,ARRAY[72, 14, 12, 24, 12, 10]
+ )
+ ON CONFLICT DO NOTHING;
+ SET LOCAL search_path TO merchant;
END
$OUTER$;