-
Notifications
You must be signed in to change notification settings - Fork 10
/
init.postgresql.1table.proc.sql
116 lines (97 loc) · 3.32 KB
/
init.postgresql.1table.proc.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
-- Criando a tabela de transações com a coluna adicional saldo
CREATE UNLOGGED TABLE IF NOT EXISTS transacoes (
id SERIAL PRIMARY KEY,
cliente_id INTEGER NOT NULL,
valor INTEGER NOT NULL,
tipo CHAR(1) NOT NULL,
descricao VARCHAR(255) NOT NULL,
realizada_em TIMESTAMP NOT NULL DEFAULT NOW(),
saldo INTEGER NOT NULL DEFAULT 0
);
-- Inserções iniciais
INSERT INTO transacoes (cliente_id, valor, tipo, descricao, saldo)
VALUES
(1, 0, 'c', 'Deposito inicial', 0),
(2, 0, 'c', 'Deposito inicial', 0),
(3, 0, 'c', 'Deposito inicial', 0),
(4, 0, 'c', 'Deposito inicial', 0),
(5, 0, 'c', 'Deposito inicial', 0);
-- Preparando o ambiente
CREATE EXTENSION IF NOT EXISTS pg_prewarm;
SELECT pg_prewarm('transacoes');
-- Definindo o tipo para o resultado da transação
CREATE TYPE transacao_result AS (saldo INT, limite INT);
-- Função para obter o limite do cliente
CREATE OR REPLACE FUNCTION limite_cliente(p_cliente_id INTEGER)
RETURNS INTEGER AS $$
BEGIN
RETURN 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 -- Valor padrão caso o id do cliente não esteja entre 1 e 5
END;
END;
$$ LANGUAGE plpgsql;
-- Procedure para realizar transações com lógica de limite
CREATE OR REPLACE PROCEDURE proc_transacao(p_cliente_id INT, p_valor INT, p_tipo VARCHAR, p_descricao VARCHAR)
LANGUAGE plpgsql AS $$
DECLARE
diff INT;
v_saldo_atual INT;
v_novo_saldo INT;
v_limite INT;
BEGIN
PERFORM pg_advisory_xact_lock(p_cliente_id);
IF p_tipo = 'd' THEN
diff := -p_valor;
ELSE
diff := p_valor;
END IF;
-- Chamada para obter o limite do cliente
v_limite := limite_cliente(p_cliente_id);
SELECT saldo
INTO v_saldo_atual
FROM transacoes
WHERE cliente_id = p_cliente_id
ORDER BY id
DESC LIMIT 1;
IF NOT FOUND THEN
v_saldo_atual := 0;
END IF;
v_novo_saldo := v_saldo_atual + diff;
IF p_tipo = 'd' AND v_novo_saldo < (-1 * v_limite) THEN
RAISE EXCEPTION 'LIMITE_INDISPONIVEL';
END IF;
INSERT INTO transacoes (cliente_id, valor, tipo, descricao, saldo)
VALUES (p_cliente_id, valor, p_tipo, p_descricao, v_novo_saldo);
END;
$$;
-- Procedure para obter extrato do cliente
CREATE OR REPLACE PROCEDURE proc_extrato(p_cliente_id INTEGER)
LANGUAGE plpgsql AS $$
DECLARE
v_saldo INTEGER;
v_limite INTEGER;
transacoes json;
BEGIN
PERFORM pg_advisory_xact_lock(p_cliente_id);
-- Chamada para obter o limite do cliente
v_limite := limite_cliente(p_cliente_id);
SELECT saldo INTO v_saldo FROM transacoes WHERE cliente_id = p_cliente_id ORDER BY realizada_em DESC LIMIT 1;
IF NOT FOUND THEN
v_saldo := 0;
END IF;
SELECT json_agg(row_to_json(t.*)) INTO transacoes FROM (
SELECT valor, tipo, descricao, TO_CHAR(realizada_em, 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') AS realizada_em
FROM transacoes
WHERE cliente_id = p_cliente_id
ORDER BY id DESC
LIMIT 10
) t;
-- Nota: A exibição do resultado para o cliente deve ser feita por meio de uma aplicação ou consulta que chame esta procedure.
-- Este script SQL não retorna diretamente o JSON, mas prepara os dados para serem consumidos.
END;
$$;