-
Notifications
You must be signed in to change notification settings - Fork 10
/
init.postgresql.2tables.sql
123 lines (106 loc) · 3.12 KB
/
init.postgresql.2tables.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
CREATE UNLOGGED TABLE clientes (
id SERIAL PRIMARY KEY,
saldo INTEGER NOT NULL DEFAULT 0,
extrato json
);
CREATE UNLOGGED TABLE transacoes (
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
cliente_id INTEGER NOT NULL,
valor INTEGER NOT NULL,
tipo CHAR(1) NOT NULL,
descricao VARCHAR(10) NOT NULL,
realizada_em TIMESTAMP(6) NOT NULL);
CREATE INDEX idx_cliente_id ON transacoes (cliente_id);
INSERT INTO clientes(id) VALUES (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT);
CREATE EXTENSION IF NOT EXISTS pg_prewarm;
SELECT pg_prewarm('clientes');
SELECT pg_prewarm('transacoes');
CREATE TYPE json_result AS (
status_code INT,
body json
);
CREATE OR REPLACE FUNCTION proc_transacao(p_shard INT, p_cliente_id INT, p_valor INT, p_tipo CHAR, p_descricao CHAR(10))
RETURNS json_result as $$
DECLARE
diff INT;
v_saldo INT;
v_limite INT;
result json_result;
BEGIN
v_limite := CASE p_cliente_id
WHEN 1 THEN 100000
WHEN 2 THEN 80000
WHEN 3 THEN 1000000
WHEN 4 THEN 10000000
WHEN 5 THEN 500000
ELSE -1
END;
SELECT saldo
INTO v_saldo
FROM clientes
WHERE id = p_cliente_id
FOR UPDATE;
IF p_tipo = 'd' AND ((v_saldo - p_valor) < (-1 * v_limite)) THEN
result.body := '{"erro": "Saldo insuficiente"}';
result.status_code := 422;
RETURN result;
END IF;
INSERT INTO transacoes
(cliente_id, valor, tipo, descricao, realizada_em)
VALUES (p_cliente_id, p_valor, p_tipo, p_descricao, now());
UPDATE clientes
SET saldo = CASE
WHEN p_tipo = 'c' THEN saldo + p_valor
WHEN p_tipo = 'd' THEN saldo - p_valor
ELSE saldo
END
WHERE id = p_cliente_id
RETURNING saldo INTO v_saldo;
SELECT json_build_object(
'saldo', v_saldo,
'limite', v_limite
) into result.body;
result.status_code := 200;
RETURN result;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION proc_extrato(p_cliente_id int)
RETURNS json_result AS $$
DECLARE
result json_result;
row_count integer;
v_saldo numeric;
v_limite numeric;
BEGIN
SELECT saldo
INTO v_saldo
FROM clientes
WHERE id = p_cliente_id;
v_limite := CASE p_cliente_id
WHEN 1 THEN 100000
WHEN 2 THEN 80000
WHEN 3 THEN 1000000
WHEN 4 THEN 10000000
WHEN 5 THEN 500000
ELSE -1
END;
SELECT json_build_object(
'saldo', json_build_object(
'total', v_saldo,
'data_extrato', TO_CHAR(now(), 'YYYY-MM-DD HH:MI:SS.US'),
'limite', v_limite
),
'ultimas_transacoes', COALESCE((
SELECT json_agg(row_to_json(t)) FROM (
SELECT valor, tipo, descricao
FROM transacoes
WHERE cliente_id = p_cliente_id
ORDER BY realizada_em DESC
LIMIT 10
) t
), '[]')
) INTO result.body;
result.status_code := 200;
RETURN result;
END;
$$ LANGUAGE plpgsql;