merchant

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

commit cd2a811845569941abe08d34cbdb83b54b9ffe20
parent 4f6fdb48998eae82e7bafa5bbce2f351e8802150
Author: Christian Grothoff <grothoff@gnunet.org>
Date:   Sat, 22 Mar 2025 17:29:35 +0100

-more fixes for merchant statistics

Diffstat:
Msrc/backenddb/merchant-0014.sql | 2+-
Msrc/backenddb/pg_statistics_helpers.sql | 325++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
2 files changed, 181 insertions(+), 146 deletions(-)

diff --git a/src/backenddb/merchant-0014.sql b/src/backenddb/merchant-0014.sql @@ -230,7 +230,7 @@ CREATE TABLE merchant_statistic_interval_amount REFERENCES merchant_statistic_interval_meta (imeta_serial_id) ON DELETE CASCADE ,merchant_serial BIGINT NOT NULL REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE - ,aevent_serial_id INT8 NOT NULL + ,event_delimiter INT8 NOT NULL REFERENCES merchant_statistic_amount_event (aevent_serial_id) ON DELETE RESTRICT ,range INT8 NOT NULL ,curr VARCHAR(12) NOT NULL diff --git a/src/backenddb/pg_statistics_helpers.sql b/src/backenddb/pg_statistics_helpers.sql @@ -384,7 +384,7 @@ BEGIN (imeta_serial_id ,merchant_serial ,range - ,aevent_serial_id + ,event_delimiter ,curr ,cumulative_value ,cumulative_frac @@ -450,11 +450,12 @@ DECLARE my_range INT8; my_delta INT8; my_meta INT8; + my_next_max_serial INT8; my_instance_id INT8; my_rec RECORD; my_irec RECORD; my_i INT; - my_max_serial INT8 DEFAULT NULL; + my_min_serial INT8 DEFAULT NULL; my_rval merchant_statistic_interval_number_get_return_value; BEGIN SELECT merchant_serial @@ -492,67 +493,84 @@ BEGIN AND merchant_serial = my_instance_id; IF FOUND THEN - my_max_serial = my_irec.event_delimiter; + my_min_serial = my_irec.event_delimiter; my_rval.rvalue = my_rval.rvalue + my_irec.cumulative_number; - END IF; - -- Check if we have events that left the applicable range - SELECT MAX(nevent_serial_id) AS max_serial_id - ,SUM(delta) AS delta_sum - INTO my_irec - FROM merchant_statistic_counter_event - WHERE imeta_serial_id = my_meta - AND merchant_serial = my_instance_id - AND slot < my_time - my_range - AND nevent_serial_id >= my_max_serial; - -- FIXME: we don't properly update my_max_serial here! - -- (need to set it to the next still included value, but we set it to the last DELETED value!) - -- => results in double-deletion in the next iteration! - IF FOUND AND my_irec.delta_sum IS NOT NULL - THEN - my_delta = my_irec.delta_sum; - my_max_serial = my_irec.max_serial_id; - -- remove expired events from the sum of the current slot - my_rval.rvalue = my_rval.rvalue - my_delta; - UPDATE merchant_statistic_interval_counter - SET cumulative_number = cumulative_number - my_delta, - event_delimiter = my_max_serial + -- Check if we have events that left the applicable range + SELECT SUM(delta) AS delta_sum + INTO my_irec + FROM merchant_statistic_counter_event WHERE imeta_serial_id = my_meta AND merchant_serial = my_instance_id - AND range = my_range; - IF (my_i < array_length(my_ranges,1)) + AND slot < my_time - my_range + AND nevent_serial_id >= my_min_serial; + + IF FOUND AND my_irec.delta_sum IS NOT NULL THEN - -- carry over events into the next slot - UPDATE merchant_statistic_interval_counter - SET cumulative_number = cumulative_number + my_delta + my_delta = my_irec.delta_sum; + my_rval.rvalue = my_rval.rvalue - my_delta; + + -- First find out the next event delimiter value + SELECT nevent_serial_id + INTO my_next_max_serial + FROM merchant_statistic_counter_event WHERE imeta_serial_id = my_meta AND merchant_serial = my_instance_id - AND range=my_ranges[my_i+1]; - IF NOT FOUND + AND slot >= my_time - my_range + AND nevent_serial_id >= my_min_serial + ORDER BY slot ASC + LIMIT 1; + + IF FOUND THEN - INSERT INTO merchant_statistic_interval_counter - (imeta_serial_id - ,merchant_serial - ,range - ,event_delimiter - ,cumulative_number - ) VALUES ( - my_meta - ,my_instance_id - ,my_ranges[my_i+1] - ,my_max_serial - ,my_delta); + -- remove expired events from the sum of the current slot + + UPDATE merchant_statistic_interval_counter + SET cumulative_number = cumulative_number - my_delta, + event_delimiter = my_next_max_serial + WHERE imeta_serial_id = my_meta + AND merchant_serial = my_instance_id + AND range = my_range; + ELSE + -- actually, slot is now empty, remove it entirely + DELETE FROM merchant_statistic_interval_counter + WHERE imeta_serial_id = my_meta + AND merchant_serial = my_instance_id + AND range = my_range; + END IF; + IF (my_i < array_length(my_ranges,1)) + THEN + -- carry over all events into the next slot + UPDATE merchant_statistic_interval_counter AS usic SET + cumulative_number = cumulative_number + my_delta, + event_delimiter = LEAST(usic.event_delimiter,my_min_serial) + WHERE imeta_serial_id = my_meta + AND merchant_serial = my_instance_id + AND range=my_ranges[my_i+1]; + IF NOT FOUND + THEN + INSERT INTO merchant_statistic_interval_counter + (imeta_serial_id + ,merchant_serial + ,range + ,event_delimiter + ,cumulative_number + ) VALUES ( + my_meta + ,my_instance_id + ,my_ranges[my_i+1] + ,my_min_serial + ,my_delta); + END IF; + ELSE + -- events are obsolete, delete them + DELETE FROM merchant_statistic_counter_event + WHERE imeta_serial_id = my_meta + AND instance_id = my_instance_id + AND slot < my_time - my_range; END IF; - ELSE - -- events are obsolete, delete them - DELETE FROM merchant_statistic_counter_event - WHERE imeta_serial_id = my_meta - AND instance_id = my_instance_id - AND slot < my_time - my_range; END IF; - END IF; - IF my_max_serial IS NOT NULL - THEN + my_rval.range = my_range; RETURN NEXT my_rval; END IF; @@ -579,12 +597,13 @@ DECLARE my_delta_frac INT8; my_meta INT8; my_instance_id INT8; + my_next_max_serial INT8; my_currency TEXT; my_rec RECORD; my_irec RECORD; my_jrec RECORD; my_i INT; - my_max_serial INT8 DEFAULT NULL; + my_min_serial INT8 DEFAULT NULL; my_rval merchant_statistic_interval_amount_get_return_value; BEGIN SELECT merchant_serial @@ -623,7 +642,7 @@ BEGIN FOR my_i IN 1..COALESCE(array_length(my_ranges,1),0) LOOP my_range = my_ranges[my_i]; - SELECT aevent_serial_id + SELECT event_delimiter ,cumulative_value ,cumulative_frac INTO my_irec @@ -635,7 +654,7 @@ BEGIN IF FOUND THEN - my_max_serial = my_irec.aevent_serial_id; + my_min_serial = my_irec.event_delimiter; my_rval.rvalue.val = (my_rval.rvalue).val + my_irec.cumulative_value + my_irec.cumulative_frac / 100000000; my_rval.rvalue.frac = (my_rval.rvalue).frac + my_irec.cumulative_frac % 100000000; IF (my_rval.rvalue).frac > 100000000 @@ -643,104 +662,120 @@ BEGIN my_rval.rvalue.frac = (my_rval.rvalue).frac - 100000000; my_rval.rvalue.val = (my_rval.rvalue).val + 1; END IF; - END IF; - -- Check if we have events that left the applicable range - SELECT MAX(aevent_serial_id) AS max_serial_id - ,SUM(delta_value) AS value_sum - ,SUM(delta_frac) AS frac_sum - INTO my_jrec - FROM merchant_statistic_amount_event - WHERE imeta_serial_id = my_meta - AND merchant_serial = my_instance_id - AND delta_curr = my_currency - AND slot < my_time - my_range - AND aevent_serial_id >= my_max_serial; - -- FIXME: we don't properly update my_max_serial here! - -- (need to set it to the next still included value, but we set it to the last DELETED value!) - -- => results in double-deletion in the next iteration! - - IF FOUND AND my_jrec.value_sum IS NOT NULL - THEN - -- Normalize sum first - my_delta_value = my_jrec.value_sum + my_jrec.frac_sum / 100000000; - my_delta_frac = my_jrec.frac_sum % 100000000; - -- remove expired events from the sum of the current slot - my_rval.rvalue.val = (my_rval.rvalue).val - my_delta_value; - IF ((my_rval.rvalue).frac > my_delta_frac) - THEN - my_rval.rvalue.frac = (my_rval.rvalue).frac - my_delta_frac; - ELSE - my_rval.rvalue.frac = 100000000 + (my_rval.rvalue).frac - my_delta_frac; - my_rval.rvalue.val = (my_rval.rvalue).val - 1; - END IF; - UPDATE merchant_statistic_interval_amount SET - cumulative_value = cumulative_value - my_delta_value - - CASE - WHEN cumulative_frac < my_delta_frac - THEN 1 - ELSE 0 - END, - cumulative_frac = cumulative_frac - my_delta_frac - + CASE - WHEN cumulative_frac < my_delta_frac - THEN 100000000 - ELSE 0 - END, - aevent_serial_id = my_max_serial + -- Check if we have events that left the applicable range + SELECT SUM(delta_value) AS value_sum + ,SUM(delta_frac) AS frac_sum + INTO my_jrec + FROM merchant_statistic_amount_event WHERE imeta_serial_id = my_meta AND merchant_serial = my_instance_id - AND curr = my_currency - AND range = my_range; - IF (my_i < array_length(my_ranges,1)) + AND delta_curr = my_currency + AND slot < my_time - my_range + AND aevent_serial_id >= my_min_serial; + + IF FOUND AND my_jrec.value_sum IS NOT NULL THEN - -- carry over events into the next (larger) slot - UPDATE merchant_statistic_interval_amount SET - cumulative_value = cumulative_value + my_delta_value - + CASE - WHEN cumulative_frac + my_delta_frac > 100000000 - THEN 1 - ELSE 0 - END, - cumulative_frac = cumulative_frac + my_delta_value - - CASE - WHEN cumulative_frac + my_delta_frac > 100000000 - THEN 100000000 - ELSE 0 - END + -- Normalize sum + my_delta_value = my_jrec.value_sum + my_jrec.frac_sum / 100000000; + my_delta_frac = my_jrec.frac_sum % 100000000; + my_rval.rvalue.val = (my_rval.rvalue).val - my_delta_value; + IF ((my_rval.rvalue).frac >= my_delta_frac) + THEN + my_rval.rvalue.frac = (my_rval.rvalue).frac - my_delta_frac; + ELSE + my_rval.rvalue.frac = 100000000 + (my_rval.rvalue).frac - my_delta_frac; + my_rval.rvalue.val = (my_rval.rvalue).val - 1; + END IF; + + -- First find out the next event delimiter value + SELECT aevent_serial_id + INTO my_next_max_serial + FROM merchant_statistic_amount_event WHERE imeta_serial_id = my_meta - AND merchant_serial = my_merchant_id - AND range=my_ranges[my_i+1]; - IF NOT FOUND + AND merchant_serial = my_instance_id + AND delta_curr = my_currency + AND slot >= my_time - my_range + AND aevent_serial_id >= my_min_serial + ORDER BY slot ASC + LIMIT 1; + IF FOUND THEN - INSERT INTO merchant_statistic_interval_amount - (imeta_serial_id - ,merchant_serial - ,aevent_serial_id - ,range - ,curr - ,cumulative_value - ,cumulative_frac - ) VALUES ( - my_meta - ,my_instance_id - ,my_max_serial - ,my_ranges[my_i+1] - ,my_currency - ,in_delta_value - ,in_delta_frac); + -- remove expired events from the sum of the current slot + UPDATE merchant_statistic_interval_amount SET + cumulative_value = cumulative_value - my_delta_value + - CASE + WHEN cumulative_frac < my_delta_frac + THEN 1 + ELSE 0 + END, + cumulative_frac = cumulative_frac - my_delta_frac + + CASE + WHEN cumulative_frac < my_delta_frac + THEN 100000000 + ELSE 0 + END, + event_delimiter = my_next_max_serial + WHERE imeta_serial_id = my_meta + AND merchant_serial = my_instance_id + AND curr = my_currency + AND range = my_range; + ELSE + -- actually, slot is now empty, remove it entirely + DELETE FROM merchant_statistic_interval_amount + WHERE imeta_serial_id = my_meta + AND merchant_serial = my_instance_id + AND curr = my_currency + AND range = my_range; + END IF; + IF (my_i < array_length(my_ranges,1)) + THEN + -- carry over all events into the next (larger) slot + UPDATE merchant_statistic_interval_amount AS msia SET + cumulative_value = cumulative_value + my_delta_value + + CASE + WHEN cumulative_frac + my_delta_frac > 100000000 + THEN 1 + ELSE 0 + END, + cumulative_frac = cumulative_frac + my_delta_value + - CASE + WHEN cumulative_frac + my_delta_frac > 100000000 + THEN 100000000 + ELSE 0 + END, + event_delimiter = LEAST (msia.event_delimiter,my_min_serial) + WHERE imeta_serial_id = my_meta + AND merchant_serial = my_instance_id + AND range=my_ranges[my_i+1]; + IF NOT FOUND + THEN + INSERT INTO merchant_statistic_interval_amount + (imeta_serial_id + ,merchant_serial + ,event_delimiter + ,range + ,curr + ,cumulative_value + ,cumulative_frac + ) VALUES ( + my_meta + ,my_instance_id + ,my_min_serial + ,my_ranges[my_i+1] + ,my_currency + ,my_delta_value + ,my_delta_frac); + END IF; + ELSE + -- events are obsolete, delete them + DELETE FROM merchant_statistic_amount_event + WHERE imeta_serial_id = my_meta + AND instance_id = my_instance_id + AND slot < my_time - my_range; END IF; - ELSE - -- events are obsolete, delete them - DELETE FROM merchant_statistic_amount_event - WHERE imeta_serial_id = my_meta - AND instance_id = my_instance_id - AND slot < my_time - my_range; END IF; - END IF; - IF my_max_serial IS NOT NULL - THEN my_rval.range = my_range; RETURN NEXT my_rval; END IF;