more work on SQL refactoring

This commit is contained in:
Christian Grothoff 2022-11-27 21:21:04 +01:00
parent f2ba02aab2
commit cf2e37cd87
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
51 changed files with 271 additions and 578 deletions

View File

@ -91,7 +91,9 @@ run (void *cls,
} }
} }
if (GNUNET_OK != if (GNUNET_OK !=
plugin->create_tables (plugin->cls)) plugin->create_tables (plugin->cls,
force_create_partitions || num_partitions > 0,
num_partitions))
{ {
fprintf (stderr, fprintf (stderr,
"Failed to initialize database.\n"); "Failed to initialize database.\n");
@ -100,31 +102,6 @@ run (void *cls,
global_ret = EXIT_NOPERMISSION; global_ret = EXIT_NOPERMISSION;
return; return;
} }
if (1 <
num_partitions
|| (
1 == num_partitions
&& force_create_partitions))
{
enum GNUNET_GenericReturnValue r = GNUNET_OK;
r = plugin->setup_partitions (plugin->cls,
num_partitions);
if (GNUNET_OK != r)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not setup partitions. Dropping default ones again\n");
if (GNUNET_OK != plugin->drop_tables (plugin->cls))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not drop tables after failed partitioning, please delete the DB manually\n");
}
TALER_EXCHANGEDB_plugin_unload (plugin);
plugin = NULL;
global_ret = EXIT_NOTINSTALLED;
return;
}
}
if (gc_db || clear_shards) if (gc_db || clear_shards)
{ {
if (GNUNET_OK != if (GNUNET_OK !=

View File

@ -99,8 +99,10 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_reserve_pub' ' ADD CONSTRAINT ' || table_name || '_foreign_reserve_pub'
' FOREIGN KEY (reserve_pub) '
' REFERENCES reserves (reserve_pub) ON DELETE CASCADE' ' REFERENCES reserves (reserve_pub) ON DELETE CASCADE'
',ADD CONSTRAINT ' || table_name || '_foreign_purse_pub' ',ADD CONSTRAINT ' || table_name || '_foreign_purse_pub'
' FOREIGN KEY (purse_pub) '
' REFERENCES purse_requests (purse_pub)' ' REFERENCES purse_requests (purse_pub)'
); );
END END

View File

@ -15,7 +15,7 @@
-- --
CREATE FUNCTION create_table_aggregation_tracking( CREATE FUNCTION create_table_aggregation_tracking(
IN shard_suffix VARCHAR DEFAULT NULL IN partition_suffix VARCHAR DEFAULT NULL
) )
RETURNS VOID RETURNS VOID
LANGUAGE plpgsql LANGUAGE plpgsql
@ -31,18 +31,18 @@ BEGIN
') %s ;' ') %s ;'
,table_name ,table_name
,'PARTITION BY HASH (deposit_serial_id)' ,'PARTITION BY HASH (deposit_serial_id)'
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_table( PERFORM comment_partitioned_table(
'mapping from wire transfer identifiers (WTID) to deposits (and back)' 'mapping from wire transfer identifiers (WTID) to deposits (and back)'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'identifier of the wire transfer' 'identifier of the wire transfer'
,'wtid_raw' ,'wtid_raw'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
END END
$$; $$;
@ -57,7 +57,7 @@ AS $$
DECLARE DECLARE
table_name VARCHAR DEFAULT 'aggregation_tracking'; table_name VARCHAR DEFAULT 'aggregation_tracking';
BEGIN BEGIN
table_name = concat_ws('_', table_name, shard_suffix); table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT ( EXECUTE FORMAT (
'CREATE INDEX ' || table_name || '_by_wtid_raw_index ' 'CREATE INDEX ' || table_name || '_by_wtid_raw_index '
'ON ' || table_name || ' ' 'ON ' || table_name || ' '
@ -86,8 +86,10 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_deposit' ' ADD CONSTRAINT ' || table_name || '_foreign_deposit'
' FOREIGN KEY (deposit_serial_id) '
' REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE' -- FIXME change to coin_pub + deposit_serial_id for more efficient deposit??? ' REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE' -- FIXME change to coin_pub + deposit_serial_id for more efficient deposit???
',ADD CONSTRAINT ' || table_name || '_foreign_wtid_raw' ',ADD CONSTRAINT ' || table_name || '_foreign_wtid_raw'
' FOREIGN KEY (wtid_raw) '
' REFERENCES wire_out(wtid_raw) ON DELETE CASCADE DEFERRABLE' ' REFERENCES wire_out(wtid_raw) ON DELETE CASCADE DEFERRABLE'
); );
END END

View File

@ -15,7 +15,7 @@
-- --
CREATE TABLE IF NOT EXISTS auditor_denom_sigs CREATE TABLE auditor_denom_sigs
(auditor_denom_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE (auditor_denom_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,auditor_uuid INT8 NOT NULL REFERENCES auditors (auditor_uuid) ON DELETE CASCADE ,auditor_uuid INT8 NOT NULL REFERENCES auditors (auditor_uuid) ON DELETE CASCADE
,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ON DELETE CASCADE ,denominations_serial INT8 NOT NULL REFERENCES denominations (denominations_serial) ON DELETE CASCADE
@ -30,17 +30,3 @@ COMMENT ON COLUMN auditor_denom_sigs.denominations_serial
IS 'Denomination the signature is for.'; IS 'Denomination the signature is for.';
COMMENT ON COLUMN auditor_denom_sigs.auditor_sig COMMENT ON COLUMN auditor_denom_sigs.auditor_sig
IS 'Signature of the auditor, of purpose TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS.'; IS 'Signature of the auditor, of purpose TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS.';
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('auditor_denom_sigs'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -15,7 +15,7 @@
-- --
CREATE TABLE IF NOT EXISTS auditors CREATE TABLE auditors
(auditor_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE (auditor_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,auditor_pub BYTEA PRIMARY KEY CHECK (LENGTH(auditor_pub)=32) ,auditor_pub BYTEA PRIMARY KEY CHECK (LENGTH(auditor_pub)=32)
,auditor_name VARCHAR NOT NULL ,auditor_name VARCHAR NOT NULL
@ -33,17 +33,3 @@ COMMENT ON COLUMN auditors.is_active
IS 'true if we are currently supporting the use of this auditor.'; IS 'true if we are currently supporting the use of this auditor.';
COMMENT ON COLUMN auditors.last_change COMMENT ON COLUMN auditors.last_change
IS 'Latest time when active status changed. Used to detect replays of old messages.'; IS 'Latest time when active status changed. Used to detect replays of old messages.';
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('auditors'
,'exchange-0001'
,'create'
,FALSE
,FALSE);

View File

@ -112,6 +112,7 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_reserve_pub' ' ADD CONSTRAINT ' || table_name || '_foreign_reserve_pub'
' FOREIGN KEY (reserve_pub) '
' REFERENCES reserves(reserve_pub) ON DELETE CASCADE' ' REFERENCES reserves(reserve_pub) ON DELETE CASCADE'
); );
END END

View File

@ -68,7 +68,7 @@ AS $$
DECLARE DECLARE
table_name VARCHAR DEFAULT 'cs_nonce_locks'; table_name VARCHAR DEFAULT 'cs_nonce_locks';
BEGIN BEGIN
table_name = concat_ws('_', table_name, shard_suffix); table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_cs_nonce_lock_serial_id_key' ' ADD CONSTRAINT ' || table_name || '_cs_nonce_lock_serial_id_key'

View File

@ -26,7 +26,7 @@ BEGIN
PERFORM create_partitioned_table( PERFORM create_partitioned_table(
'CREATE TABLE %I' 'CREATE TABLE %I'
'(deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY' '(deposit_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY'
',partition INT8 NOT NULL' ',shard INT8 NOT NULL'
',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)' ',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)'
',known_coin_id INT8 NOT NULL' -- FIXME: column needed!? ',known_coin_id INT8 NOT NULL' -- FIXME: column needed!?
',amount_with_fee_val INT8 NOT NULL' ',amount_with_fee_val INT8 NOT NULL'
@ -130,10 +130,13 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_coin_pub' ' ADD CONSTRAINT ' || table_name || '_foreign_coin_pub'
' FOREIGN KEY (coin_pub) '
' REFERENCES known_coins (coin_pub) ON DELETE CASCADE' ' REFERENCES known_coins (coin_pub) ON DELETE CASCADE'
',ADD CONSTRAINT ' || table_name || '_foreign_coin_id' ',ADD CONSTRAINT ' || table_name || '_foreign_coin_id'
' FOREIGN KEY (known_coin_id) '
' REFERENCES known_coins (known_coin_id) ON DELETE CASCADE' ' REFERENCES known_coins (known_coin_id) ON DELETE CASCADE'
',ADD CONSTRAINT ' || table_name || '_foreign_policy_details' ',ADD CONSTRAINT ' || table_name || '_foreign_policy_details'
' FOREIGN KEY (policy_details_serial_id) '
' REFERENCES policy_details (policy_details_serial_id) ON DELETE CASCADE' ' REFERENCES policy_details (policy_details_serial_id) ON DELETE CASCADE'
); );
END END
@ -152,7 +155,7 @@ BEGIN
PERFORM create_partitioned_table( PERFORM create_partitioned_table(
'CREATE TABLE %I' 'CREATE TABLE %I'
'(wire_deadline INT8 NOT NULL' '(wire_deadline INT8 NOT NULL'
',partition INT8 NOT NULL' ',shard INT8 NOT NULL'
',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)' ',coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)'
',deposit_serial_id INT8' ',deposit_serial_id INT8'
') %s ;' ') %s ;'
@ -182,7 +185,7 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'CREATE INDEX ' || table_name || '_main_index ' 'CREATE INDEX ' || table_name || '_main_index '
'ON ' || table_name || ' ' 'ON ' || table_name || ' '
'(wire_deadline ASC, partition ASC, coin_pub);' '(wire_deadline ASC, shard ASC, coin_pub);'
); );
END END
$$; $$;

View File

@ -14,7 +14,7 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-- --
CREATE TABLE IF NOT EXISTS exchange_sign_keys CREATE TABLE exchange_sign_keys
(esk_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE (esk_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,exchange_pub BYTEA PRIMARY KEY CHECK (LENGTH(exchange_pub)=32) ,exchange_pub BYTEA PRIMARY KEY CHECK (LENGTH(exchange_pub)=32)
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64) ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
@ -34,17 +34,3 @@ COMMENT ON COLUMN exchange_sign_keys.expire_sign
IS 'Time when this online signing key will no longer be used to sign.'; IS 'Time when this online signing key will no longer be used to sign.';
COMMENT ON COLUMN exchange_sign_keys.expire_legal COMMENT ON COLUMN exchange_sign_keys.expire_legal
IS 'Time when this online signing key legally expires.'; IS 'Time when this online signing key legally expires.';
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('exchange_sign_keys'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -14,7 +14,7 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-- --
CREATE TABLE IF NOT EXISTS extensions CREATE TABLE extensions
(extension_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE (extension_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,name VARCHAR NOT NULL UNIQUE ,name VARCHAR NOT NULL UNIQUE
,manifest BYTEA ,manifest BYTEA
@ -25,17 +25,3 @@ COMMENT ON COLUMN extensions.name
IS 'Name of the extension'; IS 'Name of the extension';
COMMENT ON COLUMN extensions.manifest COMMENT ON COLUMN extensions.manifest
IS 'Manifest of the extension as JSON-blob, maybe NULL. It contains common meta-information and extension-specific configuration.'; IS 'Manifest of the extension as JSON-blob, maybe NULL. It contains common meta-information and extension-specific configuration.';
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('extensions'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -14,7 +14,7 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-- --
CREATE TABLE IF NOT EXISTS global_fee CREATE TABLE global_fee
(global_fee_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE (global_fee_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,start_date INT8 NOT NULL ,start_date INT8 NOT NULL
,end_date INT8 NOT NULL ,end_date INT8 NOT NULL
@ -35,20 +35,6 @@ COMMENT ON TABLE global_fee
COMMENT ON COLUMN global_fee.global_fee_serial COMMENT ON COLUMN global_fee.global_fee_serial
IS 'needed for exchange-auditor replication logic'; IS 'needed for exchange-auditor replication logic';
CREATE INDEX IF NOT EXISTS global_fee_by_end_date_index CREATE INDEX global_fee_by_end_date_index
ON global_fee ON global_fee
(end_date); (end_date);
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('global_fee'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -74,6 +74,7 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_reserve_pub' ' ADD CONSTRAINT ' || table_name || '_foreign_reserve_pub'
' FOREIGN KEY (reserve_pub) '
' REFERENCES reserves(reserve_pub) ON DELETE CASCADE' ' REFERENCES reserves(reserve_pub) ON DELETE CASCADE'
); );
END $$; END $$;

View File

@ -16,7 +16,7 @@
CREATE FUNCTION create_table_known_coins( CREATE FUNCTION create_table_known_coins(
IN shard_suffix VARCHAR DEFAULT NULL IN partition_suffix VARCHAR DEFAULT NULL
) )
RETURNS VOID RETURNS VOID
LANGUAGE plpgsql LANGUAGE plpgsql
@ -36,42 +36,42 @@ BEGIN
') %s ;' ') %s ;'
,table_name ,table_name
,'PARTITION BY HASH (coin_pub)' ,'PARTITION BY HASH (coin_pub)'
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_table( PERFORM comment_partitioned_table(
'information about coins and their signatures, so we do not have to store the signatures more than once if a coin is involved in multiple operations' 'information about coins and their signatures, so we do not have to store the signatures more than once if a coin is involved in multiple operations'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Denomination of the coin, determines the value of the original coin and applicable fees for coin-specific operations.' 'Denomination of the coin, determines the value of the original coin and applicable fees for coin-specific operations.'
,'denominations_serial' ,'denominations_serial'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'EdDSA public key of the coin' 'EdDSA public key of the coin'
,'coin_pub' ,'coin_pub'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Value of the coin that remains to be spent' 'Value of the coin that remains to be spent'
,'remaining_val' ,'remaining_val'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Optional hash of the age commitment for age restrictions as per DD 24 (active if denom_type has the respective bit set)' 'Optional hash of the age commitment for age restrictions as per DD 24 (active if denom_type has the respective bit set)'
,'age_commitment_hash' ,'age_commitment_hash'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'This is the signature of the exchange that affirms that the coin is a valid coin. The specific signature type depends on denom_type of the denomination.' 'This is the signature of the exchange that affirms that the coin is a valid coin. The specific signature type depends on denom_type of the denomination.'
,'denom_sig' ,'denom_sig'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
END END
$$; $$;
@ -86,7 +86,7 @@ AS $$
DECLARE DECLARE
table_name VARCHAR default 'known_coins'; table_name VARCHAR default 'known_coins';
BEGIN BEGIN
table_name = concat_ws('_', table_name, shard_suffix); table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_known_coin_id_key' ' ADD CONSTRAINT ' || table_name || '_known_coin_id_key'
@ -106,6 +106,7 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_denominations' ' ADD CONSTRAINT ' || table_name || '_foreign_denominations'
' FOREIGN KEY (denominations_serial) '
' REFERENCES denominations (denominations_serial) ON DELETE CASCADE' ' REFERENCES denominations (denominations_serial) ON DELETE CASCADE'
); );
END END

View File

@ -14,7 +14,7 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-- --
CREATE TABLE IF NOT EXISTS kyc_alerts CREATE TABLE kyc_alerts
(h_payto BYTEA PRIMARY KEY CHECK (LENGTH(h_payto)=32) (h_payto BYTEA PRIMARY KEY CHECK (LENGTH(h_payto)=32)
,trigger_type INT4 NOT NULL ,trigger_type INT4 NOT NULL
,UNIQUE(trigger_type,h_payto) ,UNIQUE(trigger_type,h_payto)
@ -25,17 +25,3 @@ COMMENT ON COLUMN kyc_alerts.h_payto
IS 'hash of the payto://-URI for which the KYC status changed'; IS 'hash of the payto://-URI for which the KYC status changed';
COMMENT ON COLUMN kyc_alerts.trigger_type COMMENT ON COLUMN kyc_alerts.trigger_type
IS 'identifies the receiver of the alert, as the same h_payto may require multiple components to be notified'; IS 'identifies the receiver of the alert, as the same h_payto may require multiple components to be notified';
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('kyc_alerts'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -15,7 +15,7 @@
-- --
CREATE TABLE IF NOT EXISTS partner_accounts CREATE TABLE partner_accounts
(payto_uri VARCHAR PRIMARY KEY (payto_uri VARCHAR PRIMARY KEY
,partner_serial_id INT8 REFERENCES partners(partner_serial_id) ON DELETE CASCADE ,partner_serial_id INT8 REFERENCES partners(partner_serial_id) ON DELETE CASCADE
,partner_master_sig BYTEA CHECK (LENGTH(partner_master_sig)=64) ,partner_master_sig BYTEA CHECK (LENGTH(partner_master_sig)=64)
@ -31,17 +31,3 @@ COMMENT ON COLUMN partner_accounts.partner_master_sig
IS 'Signature of purpose TALER_SIGNATURE_MASTER_WIRE_DETAILS by the partner master public key'; IS 'Signature of purpose TALER_SIGNATURE_MASTER_WIRE_DETAILS by the partner master public key';
COMMENT ON COLUMN partner_accounts.last_seen COMMENT ON COLUMN partner_accounts.last_seen
IS 'Last time we saw this account as being active at the partner exchange. Used to select the most recent entry, and to detect when we should check again.'; IS 'Last time we saw this account as being active at the partner exchange. Used to select the most recent entry, and to detect when we should check again.';
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('partner_accounts'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -14,7 +14,7 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-- --
CREATE TABLE IF NOT EXISTS partners CREATE TABLE partners
(partner_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE (partner_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,partner_master_pub BYTEA NOT NULL CHECK(LENGTH(partner_master_pub)=32) ,partner_master_pub BYTEA NOT NULL CHECK(LENGTH(partner_master_pub)=32)
,start_date INT8 NOT NULL ,start_date INT8 NOT NULL
@ -47,17 +47,3 @@ COMMENT ON COLUMN partners.master_sig
CREATE INDEX IF NOT EXISTS partner_by_wad_time CREATE INDEX IF NOT EXISTS partner_by_wad_time
ON partners (next_wad ASC); ON partners (next_wad ASC);
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('partners'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -16,8 +16,8 @@
-- FIXME: this table should be sharded! -- FIXME: this table should be sharded!
CREATE TABLE IF NOT EXISTS policy_details CREATE TABLE policy_details
(policy_details_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY (policy_details_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,policy_hash_code BYTEA PRIMARY KEY CHECK(LENGTH(policy_hash_code)=16) ,policy_hash_code BYTEA PRIMARY KEY CHECK(LENGTH(policy_hash_code)=16)
,policy_json VARCHAR ,policy_json VARCHAR
,deadline INT8 NOT NULL ,deadline INT8 NOT NULL
@ -57,17 +57,3 @@ COMMENT ON COLUMN policy_details.fulfillment_state
- 5 (Timeout)'; - 5 (Timeout)';
COMMENT ON COLUMN policy_details.fulfillment_id COMMENT ON COLUMN policy_details.fulfillment_id
IS 'Reference to the proof of the fulfillment of this policy, if it exists. Invariant: If not NULL, this entry''s .hash_code MUST be part of the corresponding policy_fulfillments.policy_hash_codes array.'; IS 'Reference to the proof of the fulfillment of this policy, if it exists. Invariant: If not NULL, this entry''s .hash_code MUST be part of the corresponding policy_fulfillments.policy_hash_codes array.';
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('policy_details'
,'exchange-0002'
,'create'
,FALSE -- BAD! FIXME!
,FALSE);

View File

@ -16,7 +16,7 @@
-- FIXME: this table should be sharded! -- FIXME: this table should be sharded!
CREATE TABLE IF NOT EXISTS policy_fulfillments CREATE TABLE policy_fulfillments
(fulfillment_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE PRIMARY KEY (fulfillment_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE PRIMARY KEY
,fulfillment_timestamp INT8 NOT NULL ,fulfillment_timestamp INT8 NOT NULL
,fulfillment_proof VARCHAR ,fulfillment_proof VARCHAR
@ -33,17 +33,3 @@ COMMENT ON COLUMN policy_fulfillments.h_fulfillment_proof
IS 'Hash of the fulfillment_proof'; IS 'Hash of the fulfillment_proof';
COMMENT ON COLUMN policy_fulfillments.policy_hash_codes COMMENT ON COLUMN policy_fulfillments.policy_hash_codes
IS 'Concatenation of the policy_hash_code of all policy_details that are fulfilled by this proof'; IS 'Concatenation of the policy_hash_code of all policy_details that are fulfilled by this proof';
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('policy_fulfillments'
,'exchange-0002'
,'create'
,FALSE -- BAD! FIXME!
,FALSE);

View File

@ -14,7 +14,7 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-- --
CREATE TABLE IF NOT EXISTS profit_drains CREATE TABLE profit_drains
(profit_drain_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE (profit_drain_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,wtid BYTEA PRIMARY KEY CHECK (LENGTH(wtid)=32) ,wtid BYTEA PRIMARY KEY CHECK (LENGTH(wtid)=32)
,account_section VARCHAR NOT NULL ,account_section VARCHAR NOT NULL
@ -41,17 +41,3 @@ COMMENT ON COLUMN profit_drains.master_sig
IS 'EdDSA signature of type TALER_SIGNATURE_MASTER_DRAIN_PROFIT'; IS 'EdDSA signature of type TALER_SIGNATURE_MASTER_DRAIN_PROFIT';
COMMENT ON COLUMN profit_drains.executed COMMENT ON COLUMN profit_drains.executed
IS 'set to TRUE by taler-exchange-drain on execution of the transaction, not replicated to auditor'; IS 'set to TRUE by taler-exchange-drain on execution of the transaction, not replicated to auditor';
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('profit_drains'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -16,7 +16,7 @@
CREATE FUNCTION create_table_purse_decision( CREATE FUNCTION create_table_purse_decision(
IN shard_suffix VARCHAR DEFAULT NULL IN partition_suffix VARCHAR DEFAULT NULL
) )
RETURNS VOID RETURNS VOID
LANGUAGE plpgsql LANGUAGE plpgsql
@ -34,18 +34,18 @@ BEGIN
') %s ;' ') %s ;'
,table_name ,table_name
,'PARTITION BY HASH (purse_pub)' ,'PARTITION BY HASH (purse_pub)'
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_table( PERFORM comment_partitioned_table(
'Purses that were decided upon (refund or merge)' 'Purses that were decided upon (refund or merge)'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Public key of the purse' 'Public key of the purse'
,'purse_pub' ,'purse_pub'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
END END
$$; $$;
@ -59,7 +59,7 @@ AS $$
DECLARE DECLARE
table_name VARCHAR DEFAULT 'purse_decision'; table_name VARCHAR DEFAULT 'purse_decision';
BEGIN BEGIN
table_name = concat_ws('_', table_name, shard_suffix); table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_purse_action_serial_id_key' ' ADD CONSTRAINT ' || table_name || '_purse_action_serial_id_key'

View File

@ -112,8 +112,10 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_partner' ' ADD CONSTRAINT ' || table_name || '_foreign_partner'
' FOREIGN KEY (partner_serial_id) '
' REFERENCES partners(partner_serial_id) ON DELETE CASCADE' ' REFERENCES partners(partner_serial_id) ON DELETE CASCADE'
',ADD CONSTRAINT ' || table_name || '_foreign_coin_pub' ',ADD CONSTRAINT ' || table_name || '_foreign_coin_pub'
' FOREIGN KEY (coin_pub) '
' REFERENCES known_coins (coin_pub) ON DELETE CASCADE' ' REFERENCES known_coins (coin_pub) ON DELETE CASCADE'
); );
END END
@ -127,17 +129,17 @@ INSERT INTO exchange_tables
,partitioned ,partitioned
,by_range) ,by_range)
VALUES VALUES
('purse-deposits' ('purse_deposits'
,'exchange-0002' ,'exchange-0002'
,'create' ,'create'
,TRUE ,TRUE
,FALSE), ,FALSE),
('purse-deposits' ('purse_deposits'
,'exchange-0002' ,'exchange-0002'
,'constrain' ,'constrain'
,TRUE ,TRUE
,FALSE), ,FALSE),
('purse-deposits' ('purse_deposits'
,'exchange-0002' ,'exchange-0002'
,'foreign' ,'foreign'
,TRUE ,TRUE

View File

@ -15,7 +15,7 @@
-- --
CREATE FUNCTION create_table_purse_merges( CREATE FUNCTION create_table_purse_merges(
IN shard_suffix VARCHAR DEFAULT NULL IN partition_suffix VARCHAR DEFAULT NULL
) )
RETURNS VOID RETURNS VOID
LANGUAGE plpgsql LANGUAGE plpgsql
@ -35,42 +35,42 @@ BEGIN
') %s ;' ') %s ;'
,table_name ,table_name
,'PARTITION BY HASH (purse_pub)' ,'PARTITION BY HASH (purse_pub)'
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_table( PERFORM comment_partitioned_table(
'Merge requests where a purse-owner requested merging the purse into the account' 'Merge requests where a purse-owner requested merging the purse into the account'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'identifies the partner exchange, NULL in case the target reserve lives at this exchange' 'identifies the partner exchange, NULL in case the target reserve lives at this exchange'
,'partner_serial_id' ,'partner_serial_id'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'public key of the target reserve' 'public key of the target reserve'
,'reserve_pub' ,'reserve_pub'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'public key of the purse' 'public key of the purse'
,'purse_pub' ,'purse_pub'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'signature by the purse private key affirming the merge, of type TALER_SIGNATURE_WALLET_PURSE_MERGE' 'signature by the purse private key affirming the merge, of type TALER_SIGNATURE_WALLET_PURSE_MERGE'
,'merge_sig' ,'merge_sig'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'when was the merge message signed' 'when was the merge message signed'
,'merge_timestamp' ,'merge_timestamp'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
END END
$$; $$;
@ -85,7 +85,7 @@ AS $$
DECLARE DECLARE
table_name VARCHAR DEFAULT 'purse_merges'; table_name VARCHAR DEFAULT 'purse_merges';
BEGIN BEGIN
table_name = concat_ws('_', table_name, shard_suffix); table_name = concat_ws('_', table_name, partition_suffix);
-- FIXME: change to materialized index by reserve_pub! -- FIXME: change to materialized index by reserve_pub!
EXECUTE FORMAT ( EXECUTE FORMAT (
'CREATE INDEX ' || table_name || '_reserve_pub ' 'CREATE INDEX ' || table_name || '_reserve_pub '
@ -115,10 +115,13 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_partner_serial_id' ' ADD CONSTRAINT ' || table_name || '_foreign_partner_serial_id'
' FOREIGN KEY (partner_serial_id) '
' REFERENCES partners(partner_serial_id) ON DELETE CASCADE' ' REFERENCES partners(partner_serial_id) ON DELETE CASCADE'
',ADD CONSTRAINT ' || table_name || '_foreign_reserve_pub' ',ADD CONSTRAINT ' || table_name || '_foreign_reserve_pub'
' FOREIGN KEY (reserve_pub) '
' REFERENCES reserves (reserve_pub) ON DELETE CASCADE' ' REFERENCES reserves (reserve_pub) ON DELETE CASCADE'
',ADD CONSTRAINT ' || table_name || '_foreign_purse_pub' ',ADD CONSTRAINT ' || table_name || '_foreign_purse_pub'
' FOREIGN KEY (purse_pub) '
' REFERENCES purse_requests (purse_pub) ON DELETE CASCADE' ' REFERENCES purse_requests (purse_pub) ON DELETE CASCADE'
); );
END END

View File

@ -15,7 +15,7 @@
-- --
CREATE FUNCTION create_table_purse_requests( CREATE FUNCTION create_table_purse_requests(
IN shard_suffix VARCHAR DEFAULT NULL IN partition_suffix VARCHAR DEFAULT NULL
) )
RETURNS VOID RETURNS VOID
LANGUAGE plpgsql LANGUAGE plpgsql
@ -45,72 +45,72 @@ BEGIN
') %s ;' ') %s ;'
,table_name ,table_name
,'PARTITION BY HASH (purse_pub)' ,'PARTITION BY HASH (purse_pub)'
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_table( PERFORM comment_partitioned_table(
'Requests establishing purses, associating them with a contract but without a target reserve' 'Requests establishing purses, associating them with a contract but without a target reserve'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Public key of the purse' 'Public key of the purse'
,'purse_pub' ,'purse_pub'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Local time when the purse was created. Determines applicable purse fees.' 'Local time when the purse was created. Determines applicable purse fees.'
,'purse_creation' ,'purse_creation'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'When the purse is set to expire' 'When the purse is set to expire'
,'purse_expiration' ,'purse_expiration'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Hash of the contract the parties are to agree to' 'Hash of the contract the parties are to agree to'
,'h_contract_terms' ,'h_contract_terms'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'see the enum TALER_WalletAccountMergeFlags' 'see the enum TALER_WalletAccountMergeFlags'
,'flags' ,'flags'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'set to TRUE if this purse currently counts against the number of free purses in the respective reserve' 'set to TRUE if this purse currently counts against the number of free purses in the respective reserve'
,'in_reserve_quota' ,'in_reserve_quota'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Total amount expected to be in the purse' 'Total amount expected to be in the purse'
,'amount_with_fee_val' ,'amount_with_fee_val'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Purse fee the client agreed to pay from the reserve (accepted by the exchange at the time the purse was created). Zero if in_reserve_quota is TRUE.' 'Purse fee the client agreed to pay from the reserve (accepted by the exchange at the time the purse was created). Zero if in_reserve_quota is TRUE.'
,'purse_fee_val' ,'purse_fee_val'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Total amount actually in the purse (updated)' 'Total amount actually in the purse (updated)'
,'balance_val' ,'balance_val'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Signature of the purse affirming the purse parameters, of type TALER_SIGNATURE_PURSE_REQUEST' 'Signature of the purse affirming the purse parameters, of type TALER_SIGNATURE_PURSE_REQUEST'
,'purse_sig' ,'purse_sig'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
END END
$$; $$;
@ -124,7 +124,7 @@ AS $$
DECLARE DECLARE
table_name VARCHAR DEFAULT 'purse_requests'; table_name VARCHAR DEFAULT 'purse_requests';
BEGIN BEGIN
table_name = concat_ws('_', table_name, shard_suffix); table_name = concat_ws('_', table_name, partition_suffix);
-- FIXME: change to materialized index by merge_pub! -- FIXME: change to materialized index by merge_pub!
EXECUTE FORMAT ( EXECUTE FORMAT (
@ -132,7 +132,7 @@ BEGIN
'ON ' || table_name || ' ' 'ON ' || table_name || ' '
'(merge_pub);' '(merge_pub);'
); );
-- FIXME: drop index on master (crosses shards)? -- FIXME: drop index on master (crosses partitions)?
-- Or use materialized index? (needed?) -- Or use materialized index? (needed?)
EXECUTE FORMAT ( EXECUTE FORMAT (
'CREATE INDEX ' || table_name || '_purse_expiration ' 'CREATE INDEX ' || table_name || '_purse_expiration '

View File

@ -105,8 +105,10 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_reserves_out' ' ADD CONSTRAINT ' || table_name || '_foreign_reserves_out'
' FOREIGN KEY (reserve_out_serial_id) '
' REFERENCES reserves_out (reserve_out_serial_id) ON DELETE CASCADE' ' REFERENCES reserves_out (reserve_out_serial_id) ON DELETE CASCADE'
',ADD CONSTRAINT ' || table_name || '_foreign_coin_pub' ',ADD CONSTRAINT ' || table_name || '_foreign_coin_pub'
' FOREIGN KEY (coin_pub) '
' REFERENCES known_coins (coin_pub)' ' REFERENCES known_coins (coin_pub)'
); );
END END

View File

@ -16,7 +16,7 @@
CREATE FUNCTION create_table_recoup_refresh( CREATE FUNCTION create_table_recoup_refresh(
IN shard_suffix VARCHAR DEFAULT NULL IN partition_suffix VARCHAR DEFAULT NULL
) )
RETURNS VOID RETURNS VOID
LANGUAGE plpgsql LANGUAGE plpgsql
@ -38,36 +38,36 @@ BEGIN
') %s ;' ') %s ;'
,table_name ,table_name
,'PARTITION BY HASH (coin_pub)' ,'PARTITION BY HASH (coin_pub)'
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_table( 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 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 ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( 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!' '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' ,'coin_pub'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'FIXME: (To be) used for garbage collection (in the absence of foreign constraints, in the future)' 'FIXME: (To be) used for garbage collection (in the absence of foreign constraints, in the future)'
,'known_coin_id' ,'known_coin_id'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Link to the refresh operation. Also identifies the h_blind_ev of the recouped coin (as h_coin_ev).' 'Link to the refresh operation. Also identifies the h_blind_ev of the recouped coin (as h_coin_ev).'
,'rrc_serial' ,'rrc_serial'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( 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.' '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' ,'coin_blind'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
END END
$$; $$;
@ -82,7 +82,7 @@ AS $$
DECLARE DECLARE
table_name VARCHAR DEFAULT 'recoup_refresh'; table_name VARCHAR DEFAULT 'recoup_refresh';
BEGIN BEGIN
table_name = concat_ws('_', table_name, shard_suffix); table_name = concat_ws('_', table_name, partition_suffix);
-- FIXME: any query using this index will be slow. Materialize index or change query? -- FIXME: any query using this index will be slow. Materialize index or change query?
-- Also: which query uses this index? -- Also: which query uses this index?
EXECUTE FORMAT ( EXECUTE FORMAT (
@ -114,10 +114,13 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_coin_pub' ' ADD CONSTRAINT ' || table_name || '_foreign_coin_pub'
' FOREIGN KEY (coin_pub) '
' REFERENCES known_coins (coin_pub)' ' REFERENCES known_coins (coin_pub)'
' ADD CONSTRAINT ' || table_name || '_foreign_known_coin_id' ',ADD CONSTRAINT ' || table_name || '_foreign_known_coin_id'
' FOREIGN KEY (known_coin_id) '
' REFERENCES known_coins (known_coin_id) ON DELETE CASCADE' ' REFERENCES known_coins (known_coin_id) ON DELETE CASCADE'
' ADD CONSTRAINT ' || table_name || '_foreign_rrc_serial' ',ADD CONSTRAINT ' || table_name || '_foreign_rrc_serial'
' FOREIGN KEY (rrc_serial) '
' REFERENCES refresh_revealed_coins (rrc_serial) ON DELETE CASCADE' ' REFERENCES refresh_revealed_coins (rrc_serial) ON DELETE CASCADE'
); );
END END

View File

@ -100,6 +100,7 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_coin_pub' ' ADD CONSTRAINT ' || table_name || '_foreign_coin_pub'
' FOREIGN KEY (old_coin_pub) '
' REFERENCES known_coins (coin_pub) ON DELETE CASCADE' ' REFERENCES known_coins (coin_pub) ON DELETE CASCADE'
); );
END END

View File

@ -15,7 +15,7 @@
-- --
CREATE FUNCTION create_table_refresh_revealed_coins( CREATE FUNCTION create_table_refresh_revealed_coins(
IN shard_suffix VARCHAR DEFAULT NULL IN partition_suffix VARCHAR DEFAULT NULL
) )
RETURNS VOID RETURNS VOID
LANGUAGE plpgsql LANGUAGE plpgsql
@ -37,54 +37,54 @@ BEGIN
') %s ;' ') %s ;'
,table_name ,table_name
,'PARTITION BY HASH (melt_serial_id)' ,'PARTITION BY HASH (melt_serial_id)'
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_table( PERFORM comment_partitioned_table(
'Revelations about the new coins that are to be created during a melting session.' 'Revelations about the new coins that are to be created during a melting session.'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'needed for exchange-auditor replication logic' 'needed for exchange-auditor replication logic'
,'rrc_serial' ,'rrc_serial'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Identifies the refresh commitment (rc) of the melt operation.' 'Identifies the refresh commitment (rc) of the melt operation.'
,'melt_serial_id' ,'melt_serial_id'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'index of the fresh coin being created (one melt operation may result in multiple fresh coins)' 'index of the fresh coin being created (one melt operation may result in multiple fresh coins)'
,'freshcoin_index' ,'freshcoin_index'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'envelope of the new coin to be signed' 'envelope of the new coin to be signed'
,'coin_ev' ,'coin_ev'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'exchange contributed values in the creation of the fresh coin (see /csr)' 'exchange contributed values in the creation of the fresh coin (see /csr)'
,'ewv' ,'ewv'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'hash of the envelope of the new coin to be signed (for lookups)' 'hash of the envelope of the new coin to be signed (for lookups)'
,'h_coin_ev' ,'h_coin_ev'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'exchange signature over the envelope' 'exchange signature over the envelope'
,'ev_sig' ,'ev_sig'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
END END
$$; $$;
@ -99,7 +99,7 @@ AS $$
DECLARE DECLARE
table_name VARCHAR DEFAULT 'refresh_revealed_coins'; table_name VARCHAR DEFAULT 'refresh_revealed_coins';
BEGIN BEGIN
table_name = concat_ws('_', table_name, shard_suffix); table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT ( EXECUTE FORMAT (
'CREATE INDEX ' || table_name || '_coins_by_melt_serial_id_index ' 'CREATE INDEX ' || table_name || '_coins_by_melt_serial_id_index '
'ON ' || table_name || ' ' 'ON ' || table_name || ' '
@ -129,8 +129,10 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_melt' ' ADD CONSTRAINT ' || table_name || '_foreign_melt'
' FOREIGN KEY (melt_serial_id)'
' REFERENCES refresh_commitments (melt_serial_id) ON DELETE CASCADE' ' REFERENCES refresh_commitments (melt_serial_id) ON DELETE CASCADE'
',ADD CONSTRAINT ' || table_name || '_foreign_denom' ',ADD CONSTRAINT ' || table_name || '_foreign_denom'
' FOREIGN KEY (denominations_serial)'
' REFERENCES denominations (denominations_serial) ON DELETE CASCADE' ' REFERENCES denominations (denominations_serial) ON DELETE CASCADE'
); );
END END

View File

@ -86,19 +86,17 @@ END
$$; $$;
CREATE FUNCTION foreign_table_refresh_transfer_keys( CREATE FUNCTION foreign_table_refresh_transfer_keys()
IN partition_suffix VARCHAR
)
RETURNS void RETURNS void
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
DECLARE DECLARE
table_name VARCHAR DEFAULT 'refresh_transfer_keys'; table_name VARCHAR DEFAULT 'refresh_transfer_keys';
BEGIN BEGIN
table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || 'foreign_melt_serial_id' ' ADD CONSTRAINT ' || table_name || 'foreign_melt_serial_id'
' FOREIGN KEY (melt_serial_id)'
' REFERENCES refresh_commitments (melt_serial_id) ON DELETE CASCADE' ' REFERENCES refresh_commitments (melt_serial_id) ON DELETE CASCADE'
); );
END END

View File

@ -93,8 +93,10 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_coin_pub' ' ADD CONSTRAINT ' || table_name || '_foreign_coin_pub'
' FOREIGN KEY (coin_pub) '
' REFERENCES known_coins (coin_pub) ON DELETE CASCADE' ' REFERENCES known_coins (coin_pub) ON DELETE CASCADE'
',ADD CONSTRAINT ' || table_name || '_foreign_deposit' ',ADD CONSTRAINT ' || table_name || '_foreign_deposit'
' FOREIGN KEY (deposit_serial_id) '
' REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE' ' REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE'
); );
END END

View File

@ -94,6 +94,11 @@ DECLARE
table_name VARCHAR DEFAULT 'reserves'; table_name VARCHAR DEFAULT 'reserves';
BEGIN BEGIN
table_name = concat_ws('_', table_name, partition_suffix); table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT (
'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_unique_uuid'
' UNIQUE (reserve_uuid)'
);
EXECUTE FORMAT ( EXECUTE FORMAT (
'CREATE INDEX ' || table_name || '_by_expiration_index ' 'CREATE INDEX ' || table_name || '_by_expiration_index '
'ON ' || table_name || ' ' 'ON ' || table_name || ' '

View File

@ -15,7 +15,7 @@
-- --
CREATE FUNCTION create_table_reserves_close( CREATE FUNCTION create_table_reserves_close(
IN shard_suffix VARCHAR DEFAULT NULL IN partition_suffix VARCHAR DEFAULT NULL
) )
RETURNS VOID RETURNS VOID
LANGUAGE plpgsql LANGUAGE plpgsql
@ -25,8 +25,8 @@ DECLARE
BEGIN BEGIN
PERFORM create_partitioned_table( PERFORM create_partitioned_table(
'CREATE TABLE %I' 'CREATE TABLE %I'
'(close_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY' -- UNIQUE / PRIMARY KEY' '(close_uuid BIGINT GENERATED BY DEFAULT AS IDENTITY'
',reserve_pub BYTEA NOT NULL' -- REFERENCES reserves (reserve_pub) ON DELETE CASCADE' ',reserve_pub BYTEA NOT NULL'
',execution_date INT8 NOT NULL' ',execution_date INT8 NOT NULL'
',wtid BYTEA NOT NULL CHECK (LENGTH(wtid)=32)' ',wtid BYTEA NOT NULL CHECK (LENGTH(wtid)=32)'
',wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32)' ',wire_target_h_payto BYTEA CHECK (LENGTH(wire_target_h_payto)=32)'
@ -38,18 +38,18 @@ BEGIN
') %s ;' ') %s ;'
,table_name ,table_name
,'PARTITION BY HASH (reserve_pub)' ,'PARTITION BY HASH (reserve_pub)'
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_table( PERFORM comment_partitioned_table(
'wire transfers executed by the reserve to close reserves' 'wire transfers executed by the reserve to close reserves'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Identifies the credited bank account (and KYC status). Note that closing does not depend on KYC.' 'Identifies the credited bank account (and KYC status). Note that closing does not depend on KYC.'
,'wire_target_h_payto' ,'wire_target_h_payto'
,table_name ,table_name
,shard_suffix ,partition_suffix
); );
END END
$$; $$;
@ -64,19 +64,33 @@ AS $$
DECLARE DECLARE
table_name VARCHAR default 'reserves_close'; table_name VARCHAR default 'reserves_close';
BEGIN BEGIN
table_name = concat_ws('_', table_name, shard_suffix); table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || ' ' 'ALTER TABLE ' || table_name ||
'ADD CONSTRAINT ' || table_name || '_close_uuid_pkey ' ' ADD CONSTRAINT ' || table_name || '_close_uuid_pkey'
'PRIMARY KEY (close_uuid)' ' PRIMARY KEY (close_uuid)'
); );
EXECUTE FORMAT ( EXECUTE FORMAT (
'CREATE INDEX ' || table_name || '_by_reserve_pub_index ' 'CREATE INDEX ' || table_name || '_by_reserve_pub_index '
'ON ' || table_name || ' ' 'ON ' || table_name || ' (reserve_pub);'
'(reserve_pub);'
); );
END END $$;
$$;
CREATE FUNCTION foreign_table_reserves_close()
RETURNS void
LANGUAGE plpgsql
AS $$
DECLARE
table_name VARCHAR default 'reserves_close';
BEGIN
EXECUTE FORMAT (
'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_reserve_pub'
' FOREIGN KEY (reserve_pub) '
' REFERENCES reserves (reserve_pub) ON DELETE CASCADE'
);
END $$;
INSERT INTO exchange_tables INSERT INTO exchange_tables
@ -95,4 +109,9 @@ INSERT INTO exchange_tables
,'exchange-0002' ,'exchange-0002'
,'constrain' ,'constrain'
,TRUE ,TRUE
,FALSE),
('reserves_close'
,'exchange-0002'
,'foreign'
,TRUE
,FALSE); ,FALSE);

View File

@ -61,8 +61,7 @@ BEGIN
,table_name ,table_name
,partition_suffix ,partition_suffix
); );
END END $$;
$$;
CREATE FUNCTION constrain_table_reserves_in( CREATE FUNCTION constrain_table_reserves_in(
@ -76,9 +75,9 @@ DECLARE
BEGIN BEGIN
table_name = concat_ws('_', table_name, partition_suffix); table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE reserves_in_' || partition_suffix || ' ' 'ALTER TABLE ' || table_name ||
'ADD CONSTRAINT reserves_in_' || partition_suffix || '_reserve_in_serial_id_key ' ' ADD CONSTRAINT ' || table_name || '_reserve_in_serial_id_key'
'UNIQUE (reserve_in_serial_id)' ' UNIQUE (reserve_in_serial_id)'
); );
EXECUTE FORMAT ( EXECUTE FORMAT (
'CREATE INDEX ' || table_name || '_by_reserve_in_serial_id_index ' 'CREATE INDEX ' || table_name || '_by_reserve_in_serial_id_index '

View File

@ -64,11 +64,11 @@ DECLARE
BEGIN BEGIN
table_name = concat_ws('_', table_name, partition_suffix); table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || ' ' 'ALTER TABLE ' || table_name ||
'ADD CONSTRAINT ' || table_name || '_by_uuid ' ' ADD CONSTRAINT ' || table_name || '_by_uuid'
'PRIMARY KEY (open_request_uuid),' ' PRIMARY KEY (open_request_uuid)'
'ADD CONSTRAINT ' || table_name || '_by_time ' ',ADD CONSTRAINT ' || table_name || '_by_time'
'UNIQUE (reserve_pub,request_timestamp)' ' UNIQUE (reserve_pub,request_timestamp)'
); );
END END
$$; $$;
@ -82,9 +82,10 @@ DECLARE
table_name VARCHAR default 'reserves_open_requests'; table_name VARCHAR default 'reserves_open_requests';
BEGIN BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || ' ' 'ALTER TABLE ' || table_name ||
'ADD CONSTRAINT ' || table_name || '_foreign_reserve_pub ' ' ADD CONSTRAINT ' || table_name || '_foreign_reserve_pub '
'REFERENCES reserves (reserve_pub) ON DELETE CASCADE' ' FOREIGN KEY (reserve_pub)'
' REFERENCES reserves (reserve_pub) ON DELETE CASCADE'
); );
END END
$$; $$;

View File

@ -71,9 +71,9 @@ DECLARE
BEGIN BEGIN
table_name = concat_ws('_', table_name, partition_suffix); table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || ' ' 'ALTER TABLE ' || table_name ||
'ADD CONSTRAINT ' || table_name || '_reserve_out_serial_id_key ' ' ADD CONSTRAINT ' || table_name || '_reserve_out_serial_id_key'
'UNIQUE (reserve_out_serial_id)' ' UNIQUE (reserve_out_serial_id)'
); );
-- FIXME: change query to use reserves_out_by_reserve instead and materialize execution_date there as well??? -- FIXME: change query to use reserves_out_by_reserve instead and materialize execution_date there as well???
EXECUTE FORMAT ( EXECUTE FORMAT (
@ -97,11 +97,13 @@ DECLARE
table_name VARCHAR default 'reserves_out'; table_name VARCHAR default 'reserves_out';
BEGIN BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || ' ' 'ALTER TABLE ' || table_name ||
'ADD CONSTRAINT ' || table_name || '_foreign_denom ' ' ADD CONSTRAINT ' || table_name || '_foreign_denom'
'REFERENCES denominations (denominations_serial)' ' FOREIGN KEY (denominations_serial)'
'ADD CONSTRAINT ' || table_name || '_foreign_reserve ' ' REFERENCES denominations (denominations_serial)'
'REFERENCES reserves (reserve_uuid) ON DELETE CASCADE' ',ADD CONSTRAINT ' || table_name || '_foreign_reserve '
' FOREIGN KEY (reserve_uuid)'
' REFERENCES reserves (reserve_uuid) ON DELETE CASCADE'
); );
END END
$$; $$;
@ -125,7 +127,7 @@ BEGIN
,'PARTITION BY HASH (reserve_uuid)' ,'PARTITION BY HASH (reserve_uuid)'
,partition_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column ( PERFORM comment_partitioned_table (
'Information in this table is strictly redundant with that of reserves_out, but saved by a different primary key for fast lookups by reserve public key/uuid.' 'Information in this table is strictly redundant with that of reserves_out, but saved by a different primary key for fast lookups by reserve public key/uuid.'
,table_name ,table_name
,partition_suffix ,partition_suffix

View File

@ -14,7 +14,7 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-- --
CREATE UNLOGGED TABLE IF NOT EXISTS revolving_work_shards CREATE UNLOGGED TABLE revolving_work_shards
(shard_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE (shard_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,last_attempt INT8 NOT NULL ,last_attempt INT8 NOT NULL
,start_row INT4 NOT NULL ,start_row INT4 NOT NULL
@ -38,23 +38,9 @@ COMMENT ON COLUMN revolving_work_shards.end_row
COMMENT ON COLUMN revolving_work_shards.job_name COMMENT ON COLUMN revolving_work_shards.job_name
IS 'unique name of the job the workers on this shard are performing'; IS 'unique name of the job the workers on this shard are performing';
CREATE INDEX IF NOT EXISTS revolving_work_shards_by_job_name_active_last_attempt_index CREATE INDEX revolving_work_shards_by_job_name_active_last_attempt_index
ON revolving_work_shards ON revolving_work_shards
(job_name (job_name
,active ,active
,last_attempt ,last_attempt
); );
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('revolving_work_shards'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -14,24 +14,10 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-- --
CREATE TABLE IF NOT EXISTS signkey_revocations CREATE TABLE signkey_revocations
(signkey_revocations_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE (signkey_revocations_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,esk_serial INT8 PRIMARY KEY REFERENCES exchange_sign_keys (esk_serial) ON DELETE CASCADE ,esk_serial INT8 PRIMARY KEY REFERENCES exchange_sign_keys (esk_serial) ON DELETE CASCADE
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64) ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
); );
COMMENT ON TABLE signkey_revocations COMMENT ON TABLE signkey_revocations
IS 'Table storing which online signing keys have been revoked'; IS 'Table storing which online signing keys have been revoked';
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('signkey_revocations'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -158,6 +158,7 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_wad_in' ' ADD CONSTRAINT ' || table_name || '_foreign_wad_in'
' FOREIGN KEY(wad_in_serial_id)'
' REFERENCES wads_in (wad_in_serial_id) ON DELETE CASCADE' ' REFERENCES wads_in (wad_in_serial_id) ON DELETE CASCADE'
); );
END $$; END $$;

View File

@ -157,6 +157,7 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_wad_out' ' ADD CONSTRAINT ' || table_name || '_foreign_wad_out'
' FOREIGN KEY(wad_out_serial_id)'
' REFERENCES wads_out (wad_out_serial_id) ON DELETE CASCADE' ' REFERENCES wads_out (wad_out_serial_id) ON DELETE CASCADE'
); );
END END

View File

@ -98,6 +98,7 @@ BEGIN
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE ' || table_name || 'ALTER TABLE ' || table_name ||
' ADD CONSTRAINT ' || table_name || '_foreign_partner' ' ADD CONSTRAINT ' || table_name || '_foreign_partner'
' FOREIGN KEY(partner_serial_id)'
' REFERENCES partners(partner_serial_id) ON DELETE CASCADE' ' REFERENCES partners(partner_serial_id) ON DELETE CASCADE'
); );
END END

View File

@ -14,7 +14,7 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-- --
CREATE TABLE IF NOT EXISTS wire_accounts CREATE TABLE wire_accounts
(payto_uri VARCHAR PRIMARY KEY (payto_uri VARCHAR PRIMARY KEY
,master_sig BYTEA CHECK (LENGTH(master_sig)=64) ,master_sig BYTEA CHECK (LENGTH(master_sig)=64)
,is_active BOOLEAN NOT NULL ,is_active BOOLEAN NOT NULL
@ -32,17 +32,3 @@ COMMENT ON COLUMN wire_accounts.last_change
IS 'Latest time when active status changed. Used to detect replays of old messages.'; IS 'Latest time when active status changed. Used to detect replays of old messages.';
-- "wire_accounts" has no sequence because it is a 'mutable' table -- "wire_accounts" has no sequence because it is a 'mutable' table
-- and is of no concern to the auditor -- and is of no concern to the auditor
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('wire_accounts'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -14,7 +14,7 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-- --
CREATE TABLE IF NOT EXISTS wire_fee CREATE TABLE wire_fee
(wire_fee_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE (wire_fee_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,wire_method VARCHAR NOT NULL ,wire_method VARCHAR NOT NULL
,start_date INT8 NOT NULL ,start_date INT8 NOT NULL
@ -31,20 +31,6 @@ COMMENT ON TABLE wire_fee
COMMENT ON COLUMN wire_fee.wire_fee_serial COMMENT ON COLUMN wire_fee.wire_fee_serial
IS 'needed for exchange-auditor replication logic'; IS 'needed for exchange-auditor replication logic';
CREATE INDEX IF NOT EXISTS wire_fee_by_end_date_index CREATE INDEX wire_fee_by_end_date_index
ON wire_fee ON wire_fee
(end_date); (end_date);
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('wire_fee'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -15,7 +15,7 @@
-- --
CREATE FUNCTION create_table_wire_targets( CREATE FUNCTION create_table_wire_targets(
IN shard_suffix VARCHAR DEFAULT NULL IN partition_suffix VARCHAR DEFAULT NULL
) )
RETURNS VOID RETURNS VOID
LANGUAGE plpgsql LANGUAGE plpgsql
@ -29,23 +29,24 @@ BEGIN
') %s ;' ') %s ;'
,'wire_targets' ,'wire_targets'
,'PARTITION BY HASH (wire_target_h_payto)' ,'PARTITION BY HASH (wire_target_h_payto)'
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_table( PERFORM comment_partitioned_table(
'All senders and recipients of money via the exchange' 'All senders and recipients of money via the exchange'
,'wire_targets' ,'wire_targets'
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Can be a regular bank account, or also be a URI identifying a reserve-account (for P2P payments)' 'Can be a regular bank account, or also be a URI identifying a reserve-account (for P2P payments)'
,'payto_uri' ,'payto_uri'
,'wire_targets' ,'wire_targets'
,shard_suffix ,partition_suffix
); );
PERFORM comment_partitioned_column( PERFORM comment_partitioned_column(
'Unsalted hash of payto_uri' 'Unsalted hash of payto_uri'
,'wire_target_h_payto' ,'wire_target_h_payto'
,shard_suffix ,'wire_targets'
,partition_suffix
); );
END $$; END $$;
@ -56,11 +57,14 @@ CREATE FUNCTION constrain_table_wire_targets(
RETURNS void RETURNS void
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
DECLARE
table_name VARCHAR DEFAULT 'wire_targets';
BEGIN BEGIN
table_name = concat_ws('_', table_name, partition_suffix);
EXECUTE FORMAT ( EXECUTE FORMAT (
'ALTER TABLE wire_targets_' || partition_suffix || ' ' 'ALTER TABLE ' || table_name ||
'ADD CONSTRAINT wire_targets_' || partition_suffix || '_wire_target_serial_id_key ' ' ADD CONSTRAINT ' || table_name || '_wire_target_serial_id_key'
'UNIQUE (wire_target_serial_id)' ' UNIQUE (wire_target_serial_id)'
); );
END END
$$; $$;

View File

@ -14,7 +14,7 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-- --
CREATE TABLE IF NOT EXISTS work_shards CREATE TABLE work_shards
(shard_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE (shard_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,last_attempt INT8 NOT NULL ,last_attempt INT8 NOT NULL
,start_row INT8 NOT NULL ,start_row INT8 NOT NULL
@ -38,23 +38,9 @@ COMMENT ON COLUMN work_shards.end_row
COMMENT ON COLUMN work_shards.job_name COMMENT ON COLUMN work_shards.job_name
IS 'unique name of the job the workers on this shard are performing'; IS 'unique name of the job the workers on this shard are performing';
CREATE INDEX IF NOT EXISTS work_shards_by_job_name_completed_last_attempt_index CREATE INDEX work_shards_by_job_name_completed_last_attempt_index
ON work_shards ON work_shards
(job_name (job_name
,completed ,completed
,last_attempt ASC ,last_attempt ASC
); );
INSERT INTO exchange_tables
(name
,version
,action
,partitioned
,by_range)
VALUES
('work_shards'
,'exchange-0002'
,'create'
,FALSE
,FALSE);

View File

@ -213,7 +213,6 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \
pg_get_expired_reserves.c pg_get_expired_reserves.h \ pg_get_expired_reserves.c pg_get_expired_reserves.h \
pg_start.h pg_start.c \ pg_start.h pg_start.c \
pg_rollback.h pg_rollback.c \ pg_rollback.h pg_rollback.c \
pg_setup_partitions.h pg_setup_partitions.c \
pg_get_purse_request.c pg_get_purse_request.h \ pg_get_purse_request.c pg_get_purse_request.h \
pg_get_reserve_history.c pg_get_reserve_history.h \ pg_get_reserve_history.c pg_get_reserve_history.h \
pg_get_unfinished_close_requests.c pg_get_unfinished_close_requests.h \ pg_get_unfinished_close_requests.c pg_get_unfinished_close_requests.h \

View File

@ -61,12 +61,12 @@ RETURNS VOID
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
BEGIN BEGIN
IF partition_suffix IS NULL IF (partition_suffix IS NULL)
THEN THEN
-- no partitioning, disable option -- no partitioning, disable option
main_table_partition_str = ''; main_table_partition_str = '';
ELSE ELSE
IF partition_suffix > 0 IF (partition_suffix::int > 0)
THEN THEN
-- sharding, add shard name -- sharding, add shard name
table_name=table_name || '_' || partition_suffix; table_name=table_name || '_' || partition_suffix;
@ -93,7 +93,7 @@ LANGUAGE plpgsql
AS $$ AS $$
BEGIN BEGIN
IF ( (partition_suffix IS NOT NULL) AND IF ( (partition_suffix IS NOT NULL) AND
(partition_suffix > 0) ) (partition_suffix::int > 0) )
THEN THEN
-- sharding, add shard name -- sharding, add shard name
table_name=table_name || '_' || partition_suffix; table_name=table_name || '_' || partition_suffix;
@ -120,7 +120,7 @@ LANGUAGE plpgsql
AS $$ AS $$
BEGIN BEGIN
IF ( (partition_suffix IS NOT NULL) AND IF ( (partition_suffix IS NOT NULL) AND
(partition_suffix > 0) ) (partition_suffix::int > 0) )
THEN THEN
-- sharding, add shard name -- sharding, add shard name
table_name=table_name || '_' || partition_suffix; table_name=table_name || '_' || partition_suffix;
@ -142,7 +142,7 @@ COMMENT ON FUNCTION comment_partitioned_column
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
CREATE FUNCTION create_tables( CREATE FUNCTION do_create_tables(
num_partitions INTEGER num_partitions INTEGER
-- NULL: no partitions, add foreign constraints -- NULL: no partitions, add foreign constraints
-- 0: no partitions, no foreign constraints -- 0: no partitions, no foreign constraints
@ -159,7 +159,7 @@ DECLARE
,action ,action
,partitioned ,partitioned
,by_range ,by_range
FROM exchange_tables FROM exchange.exchange_tables
WHERE NOT finished WHERE NOT finished
ORDER BY table_serial_id ASC; ORDER BY table_serial_id ASC;
BEGIN BEGIN
@ -167,14 +167,14 @@ BEGIN
LOOP LOOP
CASE rec.action CASE rec.action
-- "create" actions apply to master and partitions -- "create" actions apply to master and partitions
WHEN "create" WHEN 'create'
THEN THEN
IF (rec.partitioned AND IF (rec.partitioned AND
(num_partitions IS NOT NULL)) (num_partitions IS NOT NULL))
THEN THEN
-- Create master table with partitioning. -- Create master table with partitioning.
EXECUTE FORMAT( EXECUTE FORMAT(
'PERFORM %s_table_%s (%s)'::text 'SELECT exchange.%s_table_%s (%s)'::text
,rec.action ,rec.action
,rec.name ,rec.name
,0 ,0
@ -187,7 +187,7 @@ BEGIN
THEN THEN
-- Range partition -- Range partition
EXECUTE FORMAT( EXECUTE FORMAT(
'CREATE TABLE IF NOT EXISTS %s_default' 'CREATE TABLE exchange.%s_default'
' PARTITION OF %s' ' PARTITION OF %s'
' FOR DEFAULT' ' FOR DEFAULT'
,rec.name ,rec.name
@ -196,7 +196,7 @@ BEGIN
ELSE ELSE
-- Hash partition -- Hash partition
EXECUTE FORMAT( EXECUTE FORMAT(
'CREATE TABLE IF NOT EXISTS %s_default' 'CREATE TABLE exchange.%s_default'
' PARTITION OF %s' ' PARTITION OF %s'
' FOR VALUES WITH (MODULUS 1, REMAINDER 0)' ' FOR VALUES WITH (MODULUS 1, REMAINDER 0)'
,rec.name ,rec.name
@ -207,7 +207,7 @@ BEGIN
FOR i IN 1..num_partitions LOOP FOR i IN 1..num_partitions LOOP
-- Create num_partitions -- Create num_partitions
EXECUTE FORMAT( EXECUTE FORMAT(
'CREATE TABLE IF NOT EXISTS %I' 'CREATE TABLE exchange.%I'
' PARTITION OF %I' ' PARTITION OF %I'
' FOR VALUES WITH (MODULUS %s, REMAINDER %s)' ' FOR VALUES WITH (MODULUS %s, REMAINDER %s)'
,rec.name || '_' || i ,rec.name || '_' || i
@ -220,31 +220,29 @@ BEGIN
ELSE ELSE
-- Only create master table. No partitions. -- Only create master table. No partitions.
EXECUTE FORMAT( EXECUTE FORMAT(
'PERFORM %s_table_%s (%s)'::text 'SELECT exchange.%s_table_%s ()'::text
,rec.action ,rec.action
,rec.name ,rec.name
,NULL
); );
END IF; END IF;
-- Constrain action apply to master OR each partition -- Constrain action apply to master OR each partition
WHEN "constrain" WHEN 'constrain'
THEN THEN
ASSERT rec.partitioned, 'constrain action only applies to partitioned tables'; ASSERT rec.partitioned, 'constrain action only applies to partitioned tables';
IF (num_partitions IS NULL) IF (num_partitions IS NULL)
THEN THEN
-- Constrain master table -- Constrain master table
EXECUTE FORMAT( EXECUTE FORMAT(
'PERFORM %s_table_%s (%s)'::text 'SELECT exchange.%s_table_%s (NULL)'::text
,rec.action ,rec.action
,rec.name ,rec.name
,NULL
); );
ELSE ELSE
IF (num_partitions = 0) IF (num_partitions = 0)
THEN THEN
-- Constrain default table -- Constrain default table
EXECUTE FORMAT( EXECUTE FORMAT(
'PERFORM %s_table_%s (%s)'::text 'SELECT exchange.%s_table_%s (%s)'::text
,rec.action ,rec.action
,rec.name ,rec.name
,'default' ,'default'
@ -253,7 +251,7 @@ BEGIN
-- Constrain each partition -- Constrain each partition
FOR i IN 1..num_partitions LOOP FOR i IN 1..num_partitions LOOP
EXECUTE FORMAT( EXECUTE FORMAT(
'PERFORM %s_table_%s (%s)'::text 'SELECT exchange.%s_table_%s (%s)'::text
,rec.action ,rec.action
,rec.name ,rec.name
,i ,i
@ -262,22 +260,22 @@ BEGIN
END IF; END IF;
END IF; END IF;
-- Foreign actions only apply if partitioning is off -- Foreign actions only apply if partitioning is off
WHEN "foreign" WHEN 'foreign'
THEN THEN
IF (num_partitions IS NULL) IF (num_partitions IS NULL)
THEN THEN
-- Only create master table. No partitions. -- Add foreign constraints
EXECUTE FORMAT( EXECUTE FORMAT(
'PERFORM %s_table_%s (%s)'::text 'SELECT exchange.%s_table_%s (%s)'::text
,rec.action ,rec.action
,rec.name ,rec.name
,NULL ,NULL
); );
END IF; END IF;
WHEN "master" WHEN 'master'
THEN THEN
EXECUTE FORMAT( EXECUTE FORMAT(
'PERFORM %s_table_%s'::text 'SELECT exchange.%s_table_%s ()'::text
,rec.action ,rec.action
,rec.name ,rec.name
); );
@ -285,13 +283,13 @@ BEGIN
ASSERT FALSE, 'unsupported action type: ' || rec.action; ASSERT FALSE, 'unsupported action type: ' || rec.action;
END CASE; -- END CASE (rec.action) END CASE; -- END CASE (rec.action)
-- Mark as finished -- Mark as finished
UPDATE exchange_tables UPDATE exchange.exchange_tables
SET finished=TRUE SET finished=TRUE
WHERE table_serial_id=rec.table_serial_id; WHERE table_serial_id=rec.table_serial_id;
END LOOP; -- create/alter/drop actions END LOOP; -- create/alter/drop actions
END $$; END $$;
COMMENT ON FUNCTION create_tables COMMENT ON FUNCTION do_create_tables
IS 'Creates all tables for the given number of partitions that need creating. Does NOT support sharding.'; IS 'Creates all tables for the given number of partitions that need creating. Does NOT support sharding.';

View File

@ -27,21 +27,47 @@
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue
TEH_PG_create_tables (void *cls) TEH_PG_create_tables (void *cls,
bool support_partitions,
uint32_t num_partitions)
{ {
struct PostgresClosure *pg = cls; struct PostgresClosure *pg = cls;
struct GNUNET_PQ_Context *conn; struct GNUNET_PQ_Context *conn;
enum GNUNET_GenericReturnValue ret; enum GNUNET_GenericReturnValue ret = GNUNET_OK;
struct GNUNET_PQ_QueryParam params[] = {
support_partitions
? GNUNET_PQ_query_param_uint32 (&num_partitions)
: GNUNET_PQ_query_param_null (),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_PreparedStatement ps[] = {
GNUNET_PQ_make_prepare ("create_tables",
"SELECT"
" exchange.do_create_tables"
" ($1);"),
GNUNET_PQ_PREPARED_STATEMENT_END
};
struct GNUNET_PQ_ExecuteStatement es[] = {
GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
GNUNET_PQ_EXECUTE_STATEMENT_END
};
conn = GNUNET_PQ_connect_with_cfg (pg->cfg, conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
"exchangedb-postgres", "exchangedb-postgres",
"exchange-", "exchange-",
NULL, es,
NULL); ps);
if (NULL == conn) if (NULL == conn)
return GNUNET_SYSERR; return GNUNET_SYSERR;
ret = GNUNET_PQ_exec_sql (conn, if (0 >
"procedures"); GNUNET_PQ_eval_prepared_non_select (conn,
"create_tables",
params))
ret = GNUNET_SYSERR;
if (GNUNET_OK == ret)
ret = GNUNET_PQ_exec_sql (conn,
"procedures");
GNUNET_PQ_disconnect (conn); GNUNET_PQ_disconnect (conn);
return ret; return ret;
} }

View File

@ -29,9 +29,16 @@
* Create the necessary tables if they are not present * Create the necessary tables if they are not present
* *
* @param cls the `struct PostgresClosure` with the plugin-specific state * @param cls the `struct PostgresClosure` with the plugin-specific state
* @param support_partitions true to enable partitioning support (disables foreign key constraints)
* @param num_partitions number of partitions to create,
* (0 to not actually use partitions, 1 to only
* setup a default partition, >1 for real partitions)
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
*/ */
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue
TEH_PG_create_tables (void *cls); TEH_PG_create_tables (void *cls,
bool support_partitions,
uint32_t num_partitions);
#endif #endif

View File

@ -1,73 +0,0 @@
/*
This file is part of TALER
Copyright (C) 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 <http://www.gnu.org/licenses/>
*/
/**
* @file exchangedb/pg_setup_partitions.c
* @brief Implementation of the setup_partitions function for Postgres
* @author Christian Grothoff
*/
#include "platform.h"
#include "taler_error_codes.h"
#include "taler_dbevents.h"
#include "taler_pq_lib.h"
#include "pg_setup_partitions.h"
#include "pg_helper.h"
/**
* Setup partitions of already existing tables
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param num the number of partitions to create for each partitioned table
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
*/
enum GNUNET_GenericReturnValue
TEH_PG_setup_partitions (void *cls,
uint32_t num)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_Context *conn;
enum GNUNET_GenericReturnValue ret = GNUNET_OK;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_uint32 (&num),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_PreparedStatement ps[] = {
GNUNET_PQ_make_prepare ("setup_partitions",
"SELECT"
" create_partitions"
" ($1);"),
GNUNET_PQ_PREPARED_STATEMENT_END
};
struct GNUNET_PQ_ExecuteStatement es[] = {
GNUNET_PQ_make_try_execute ("SET search_path TO exchange;"),
GNUNET_PQ_EXECUTE_STATEMENT_END
};
conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
"exchangedb-postgres",
NULL,
es,
ps);
if (NULL == conn)
return GNUNET_SYSERR;
ret = GNUNET_OK;
if (0 > GNUNET_PQ_eval_prepared_non_select (conn,
"setup_partitions",
params))
ret = GNUNET_SYSERR;
GNUNET_PQ_disconnect (conn);
return ret;
}

View File

@ -1,39 +0,0 @@
/*
This file is part of TALER
Copyright (C) 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 <http://www.gnu.org/licenses/>
*/
/**
* @file exchangedb/pg_setup_partitions.h
* @brief implementation of the setup_partitions function for Postgres
* @author Christian Grothoff
*/
#ifndef PG_SETUP_PARTITIONS_H
#define PG_SETUP_PARTITIONS_H
#include "taler_util.h"
#include "taler_json_lib.h"
#include "taler_exchangedb_plugin.h"
/**
* Setup partitions of already existing tables
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param num the number of partitions to create for each partitioned table
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
*/
enum GNUNET_GenericReturnValue
TEH_PG_setup_partitions (void *cls,
uint32_t num);
#endif

View File

@ -120,7 +120,6 @@
#include "pg_get_policy_details.h" #include "pg_get_policy_details.h"
#include "pg_persist_policy_details.h" #include "pg_persist_policy_details.h"
#include "pg_do_deposit.h" #include "pg_do_deposit.h"
#include "pg_setup_partitions.h"
#include "pg_add_policy_fulfillment_proof.h" #include "pg_add_policy_fulfillment_proof.h"
#include "pg_do_melt.h" #include "pg_do_melt.h"
#include "pg_do_refund.h" #include "pg_do_refund.h"
@ -5434,8 +5433,6 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &TEH_PG_select_purse_by_merge_pub; = &TEH_PG_select_purse_by_merge_pub;
plugin->set_purse_balance plugin->set_purse_balance
= &TEH_PG_set_purse_balance; = &TEH_PG_set_purse_balance;
plugin->setup_partitions
= &TEH_PG_setup_partitions;
plugin->batch_reserves_in_insert plugin->batch_reserves_in_insert
= &TEH_PG_batch_reserves_in_insert; = &TEH_PG_batch_reserves_in_insert;

View File

@ -3132,49 +3132,17 @@ struct TALER_EXCHANGEDB_Plugin
* Create the necessary tables if they are not present * Create the necessary tables if they are not present
* *
* @param cls the @e cls of this struct with the plugin-specific state * @param cls the @e cls of this struct with the plugin-specific state
* @param support_partitions true to enable partitioning support (disables foreign key constraints)
* @param num_partitions number of partitions to create,
* (0 to not actually use partitions, 1 to only
* setup a default partition, >1 for real partitions)
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
*/ */
enum GNUNET_GenericReturnValue enum GNUNET_GenericReturnValue
(*create_tables)(void *cls); (*create_tables)(void *cls,
bool support_partitions,
uint32_t num_partitions);
/**
* Initialize the database of a shard node
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param idx the current shard index, will be appended to tables as suffix
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
*/
enum GNUNET_GenericReturnValue
(*create_shard_tables)(void *cls,
uint32_t idx);
/**
* Change already present tables of the database to num partitions
* Only has an effect if there are default partitions only
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param num the number of partitions to create for each partitioned table
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
*/
enum GNUNET_GenericReturnValue
(*setup_partitions)(void *cls,
uint32_t num);
/**
* Change already present tables of the database to num foreign tables on
* num foreign servers (shards).
* Only has an effect if there are default partitions only
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param num the number of shard servers to create. The shard servers
* must follow the numbering of [1-N], have the same user as
* the master and have tables named $TABLE_$N where $N is the same
* as the servers index of N.
* @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
*/
enum GNUNET_GenericReturnValue
(*setup_foreign_servers)(void *cls,
uint32_t num);
/** /**
* Start a transaction. * Start a transaction.
@ -3480,7 +3448,8 @@ struct TALER_EXCHANGEDB_Plugin
*/ */
enum GNUNET_DB_QueryStatus enum GNUNET_DB_QueryStatus
(*batch_reserves_in_insert)(void *cls, (*batch_reserves_in_insert)(void *cls,
const struct TALER_EXCHANGEDB_ReserveInInfo *reserves, const struct
TALER_EXCHANGEDB_ReserveInInfo *reserves,
unsigned int reserves_length, unsigned int reserves_length,
enum GNUNET_DB_QueryStatus *results); enum GNUNET_DB_QueryStatus *results);