-- -- This file is part of TALER -- Copyright (C) 2014--2022 Taler Systems SA -- -- TALER is free software; you can redistribute it and/or modify it under the -- terms of the GNU General Public License as published by the Free Software -- Foundation; either version 3, or (at your option) any later version. -- -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License along with -- TALER; see the file COPYING. If not, see -- CREATE FUNCTION create_table_recoup_refresh( IN partition_suffix VARCHAR DEFAULT NULL ) RETURNS VOID LANGUAGE plpgsql AS $$ DECLARE table_name VARCHAR DEFAULT 'recoup_refresh'; BEGIN PERFORM create_partitioned_table( 'CREATE TABLE %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)' ,partition_suffix ); PERFORM comment_partitioned_table( 'Table of coins that originated from a refresh operation and that were recouped. Links the (fresh) coin to the melted operation (and thus the old coin). A recoup on a refreshed coin credits the old coin and debits the fresh coin.' ,table_name ,partition_suffix ); PERFORM comment_partitioned_column( 'Refreshed coin of a revoked denomination where the residual value is credited to the old coin. Do not CASCADE ON DROP on the coin_pub, as we may keep the coin alive!' ,'coin_pub' ,table_name ,partition_suffix ); PERFORM comment_partitioned_column( 'FIXME: (To be) used for garbage collection (in the absence of foreign constraints, in the future)' ,'known_coin_id' ,table_name ,partition_suffix ); PERFORM comment_partitioned_column( 'Link to the refresh operation. Also identifies the h_blind_ev of the recouped coin (as h_coin_ev).' ,'rrc_serial' ,table_name ,partition_suffix ); PERFORM comment_partitioned_column( 'Denomination blinding key used when creating the blinded coin from the planchet. Secret revealed during the recoup to provide the linkage between the coin and the refresh operation.' ,'coin_blind' ,table_name ,partition_suffix ); END $$; CREATE FUNCTION constrain_table_recoup_refresh( IN partition_suffix VARCHAR ) RETURNS VOID LANGUAGE plpgsql AS $$ DECLARE table_name VARCHAR DEFAULT 'recoup_refresh'; BEGIN table_name = concat_ws('_', table_name, partition_suffix); -- FIXME: any query using this index will be slow. Materialize index or change query? -- Also: which query uses this index? EXECUTE FORMAT ( 'CREATE INDEX ' || table_name || '_by_rrc_serial_index' ' ON ' || table_name || ' ' '(rrc_serial);' ); EXECUTE FORMAT ( 'CREATE INDEX ' || table_name || '_by_coin_pub_index' ' ON ' || table_name || ' ' '(coin_pub);' ); EXECUTE FORMAT ( 'ALTER TABLE ' || table_name || ' ADD CONSTRAINT ' || table_name || '_recoup_refresh_uuid_key' ' UNIQUE (recoup_refresh_uuid) ' ); END $$; CREATE FUNCTION foreign_table_recoup_refresh() RETURNS VOID LANGUAGE plpgsql AS $$ DECLARE table_name VARCHAR DEFAULT 'recoup_refresh'; BEGIN EXECUTE FORMAT ( 'ALTER TABLE ' || table_name || ' ADD CONSTRAINT ' || table_name || '_foreign_coin_pub' ' FOREIGN KEY (coin_pub) ' ' REFERENCES known_coins (coin_pub)' ',ADD CONSTRAINT ' || table_name || '_foreign_known_coin_id' ' FOREIGN KEY (known_coin_id) ' ' REFERENCES known_coins (known_coin_id) ON DELETE CASCADE' ',ADD CONSTRAINT ' || table_name || '_foreign_rrc_serial' ' FOREIGN KEY (rrc_serial) ' ' REFERENCES refresh_revealed_coins (rrc_serial) ON DELETE CASCADE' ); END $$; INSERT INTO exchange_tables (name ,version ,action ,partitioned ,by_range) VALUES ('recoup_refresh' ,'exchange-0002' ,'create' ,TRUE ,FALSE), ('recoup_refresh' ,'exchange-0002' ,'constrain' ,TRUE ,FALSE), ('recoup_refresh' ,'exchange-0002' ,'foreign' ,TRUE ,FALSE);