-
Notifications
You must be signed in to change notification settings - Fork 923
/
Copy pathscript.sql
132 lines (118 loc) · 4.68 KB
/
script.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
CREATE UNLOGGED TABLE transactions (
transaction_id SERIAL PRIMARY KEY,
client_id INTEGER NOT NULL,
client_limit INTEGER NOT NULL,
client_current INTEGER NOT NULL,
transaction_value INTEGER NOT NULL,
transaction_type CHAR(1) NOT NULL,
transaction_description VARCHAR(10) NOT NULL,
transaction_date TIMESTAMP NOT NULL,
transaction_logical_counter INTEGER NOT NULL
);
ALTER TABLE transactions ADD CONSTRAINT unique_transaction_logical_counter UNIQUE (client_id, transaction_logical_counter);
CREATE INDEX idx_transactions_client_id_date ON transactions (client_id, transaction_logical_counter DESC);
INSERT INTO transactions (client_id, client_limit, client_current, transaction_value, transaction_type, transaction_description, transaction_date, transaction_logical_counter)
VALUES
(1, 1000 * 100, 0, 0, 'n', 'Created', NOW(), 0),
(2, 800 * 100, 0, 0, 'n', 'Created', NOW(), 0),
(3, 10000 * 100, 0, 0, 'n', 'Created', NOW(), 0),
(4, 100000 * 100, 0, 0, 'n', 'Created', NOW(), 0),
(5, 5000 * 100, 0, 0, 'n', 'Created', NOW(), 0)
;
CREATE OR REPLACE FUNCTION create_transaction_for_client(
p_client_id integer,
p_transaction_value integer,
p_transaction_type character,
p_transaction_description character varying,
OUT result_code integer,
OUT out_client_limit integer,
OUT out_client_current integer)
RETURNS RECORD
LANGUAGE 'plpgsql'
AS $$
DECLARE
v_retry BOOLEAN := TRUE;
v_logical_counter INTEGER;
BEGIN
WHILE v_retry LOOP
-- Retrieve the latest transaction for the given client_id
SELECT client_limit, client_current, transaction_logical_counter INTO out_client_limit, out_client_current, v_logical_counter
FROM transactions
WHERE client_id = p_client_id
ORDER BY transaction_logical_counter DESC
LIMIT 1;
-- Check if there's no transaction found
IF NOT FOUND THEN
result_code := 1; -- Indicate an error or invalid client_id
RETURN;
END IF;
-- Calculate the potential new client_current
out_client_current := out_client_current + p_transaction_value;
-- Check if the transaction would cause client_current to go below -1 * client_limit
IF out_client_current < (-1 * out_client_limit) THEN
result_code := 2; -- Indicate transaction would exceed limit
RETURN;
END IF;
BEGIN
INSERT INTO transactions (client_id, client_limit, client_current, transaction_value, transaction_type, transaction_description, transaction_date, transaction_logical_counter)
VALUES (p_client_id, out_client_limit, out_client_current, p_transaction_value, p_transaction_type, p_transaction_description, NOW(), v_logical_counter + 1);
v_retry := FALSE;
result_code := 0;
EXCEPTION WHEN unique_violation THEN
END;
END LOOP;
END;
$$;
CREATE OR REPLACE FUNCTION get_client_transactions(p_client_id INTEGER)
RETURNS TABLE(
client_limit INTEGER,
client_current INTEGER,
transaction_value INTEGER,
transaction_type CHAR(1),
transaction_description VARCHAR(10),
transaction_date TIMESTAMP
)
LANGUAGE 'plpgsql'
AS $$
BEGIN
RETURN QUERY
SELECT t.client_limit, t.client_current, t.transaction_value, t.transaction_type, t.transaction_description, t.transaction_date
FROM transactions t
WHERE t.client_id = p_client_id
ORDER BY t.transaction_logical_counter DESC;
END;
$$;
CREATE OR REPLACE FUNCTION wipe_all_transactions()
RETURNS void
LANGUAGE plpgsql
AS $$
BEGIN
TRUNCATE TABLE transactions;
INSERT INTO transactions (client_id, client_limit, client_current, transaction_value, transaction_type, transaction_description, transaction_date, transaction_logical_counter)
VALUES
(1, 1000 * 100, 0, 0, 'n', 'Created', NOW(), 0),
(2, 800 * 100, 0, 0, 'n', 'Created', NOW(), 0),
(3, 10000 * 100, 0, 0, 'n', 'Created', NOW(), 0),
(4, 100000 * 100, 0, 0, 'n', 'Created', NOW(), 0),
(5, 5000 * 100, 0, 0, 'n', 'Created', NOW(), 0)
;
END;
$$;
CREATE OR REPLACE PROCEDURE prune_transactions(p_client_id INTEGER)
LANGUAGE 'plpgsql'
AS $$
DECLARE
v_threshold_counter INTEGER;
BEGIN
SELECT transaction_logical_counter INTO v_threshold_counter
FROM transactions
WHERE client_id = p_client_id
ORDER BY transaction_logical_counter DESC
LIMIT 1 OFFSET 11;
IF v_threshold_counter IS NULL THEN
RETURN;
END IF;
DELETE FROM transactions
WHERE client_id = p_client_id AND transaction_logical_counter < v_threshold_counter;
END;
$$;