-
Notifications
You must be signed in to change notification settings - Fork 0
/
2-create-all-functions-and-triggers.sql
220 lines (184 loc) · 9.23 KB
/
2-create-all-functions-and-triggers.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
------------ Archivace založená na spouštěčích (triggers) --------------
CREATE TABLE archive_orders (LIKE orders) PARTITION BY RANGE (orderdate);
CREATE TABLE archive_orderlines (LIKE orderlines) PARTITION BY RANGE (orderdate);
---------------- Aktuálni rozdelení archivu -----------------
CREATE TABLE archive_orders2004_0101_0201 partition of archive_orders for values from ('2004-01-01') to ('2004-02-01');
CREATE TABLE archive_orders2004_0201_0301 partition of archive_orders for values from ('2004-02-01') to ('2004-03-01');
CREATE TABLE archive_orders2004_0301_0401 partition of archive_orders for values from ('2004-03-01') to ('2004-04-01');
CREATE TABLE archive_orders2004_0401_0501 partition of archive_orders for values from ('2004-04-01') to ('2004-05-01');
CREATE TABLE archive_orders2004_0501_0601 partition of archive_orders for values from ('2004-05-01') to ('2004-06-01');
CREATE TABLE archive_orders2004_0601_0701 partition of archive_orders for values from ('2004-06-01') to ('2004-07-01');
CREATE TABLE archive_orders2004_0701_0801 partition of archive_orders for values from ('2004-07-01') to ('2004-08-01');
CREATE TABLE archive_orders2004_0801_0901 partition of archive_orders for values from ('2004-08-01') to ('2004-09-01');
CREATE TABLE archive_orders2004_0901_1001 partition of archive_orders for values from ('2004-09-01') to ('2004-10-01');
CREATE TABLE archive_orders2004_1001_1101 partition of archive_orders for values from ('2004-10-01') to ('2004-11-01');
CREATE TABLE archive_orders2004_1101_1201 partition of archive_orders for values from ('2004-11-01') to ('2004-12-01');
CREATE TABLE archive_orders2004_1201_0101 partition of archive_orders for values from ('2004-12-01') to ('2005-01-01');
-- =======
CREATE TABLE archive_orderlines2004_0101_0201 partition of archive_orderlines for values from ('2004-01-01') to ('2004-02-01');
CREATE TABLE archive_orderlines2004_0201_0301 partition of archive_orderlines for values from ('2004-02-01') to ('2004-03-01');
CREATE TABLE archive_orderlines2004_0301_0401 partition of archive_orderlines for values from ('2004-03-01') to ('2004-04-01');
CREATE TABLE archive_orderlines2004_0401_0501 partition of archive_orderlines for values from ('2004-04-01') to ('2004-05-01');
CREATE TABLE archive_orderlines2004_0501_0601 partition of archive_orderlines for values from ('2004-05-01') to ('2004-06-01');
CREATE TABLE archive_orderlines2004_0601_0701 partition of archive_orderlines for values from ('2004-06-01') to ('2004-07-01');
CREATE TABLE archive_orderlines2004_0701_0801 partition of archive_orderlines for values from ('2004-07-01') to ('2004-08-01');
CREATE TABLE archive_orderlines2004_0801_0901 partition of archive_orderlines for values from ('2004-08-01') to ('2004-09-01');
CREATE TABLE archive_orderlines2004_0901_1001 partition of archive_orderlines for values from ('2004-09-01') to ('2004-10-01');
CREATE TABLE archive_orderlines2004_1001_1101 partition of archive_orderlines for values from ('2004-10-01') to ('2004-11-01');
CREATE TABLE archive_orderlines2004_1101_1201 partition of archive_orderlines for values from ('2004-11-01') to ('2004-12-01');
CREATE TABLE archive_orderlines2004_1201_0101 partition of archive_orderlines for values from ('2004-12-01') to ('2005-01-01');
---------------------------------------------------
CREATE OR REPLACE FUNCTION archive_on_delete_orders() RETURNS trigger
AS $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM archive_orders WHERE archive_orders.orderid = OLD.orderid) THEN
INSERT INTO archive_orders VALUES((OLD).*) ;
END IF;
RETURN OLD;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER archive_deleted_rows_orders
AFTER DELETE ON orders
FOR EACH ROW EXECUTE PROCEDURE archive_on_delete_orders();
CREATE OR REPLACE FUNCTION archive_on_delete_orderlines() RETURNS trigger
AS $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM archive_orderlines WHERE archive_orderlines.orderid = OLD.orderid AND archive_orderlines.orderlineid = OLD.orderlineid ) THEN
INSERT INTO archive_orderlines VALUES((OLD).*) ;
END IF;
RETURN OLD;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER archive_deleted_rows_orderlines
AFTER DELETE ON orderlines
FOR EACH ROW EXECUTE PROCEDURE archive_on_delete_orderlines();
---------------------------------------------------
CREATE OR REPLACE FUNCTION archive_on_insert_orders() RETURNS trigger
AS $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM archive_orders WHERE archive_orders.orderid = NEW.orderid) THEN
INSERT INTO archive_orders VALUES((NEW).*);
END IF;
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER archive_inserted_rows_orders
BEFORE INSERT ON orders
FOR EACH ROW EXECUTE PROCEDURE archive_on_insert_orders();
CREATE OR REPLACE FUNCTION archive_on_insert_orderlines() RETURNS trigger
AS $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM archive_orderlines WHERE archive_orderlines.orderid = NEW.orderid AND archive_orderlines.orderlineid = NEW.orderlineid) THEN
INSERT INTO archive_orderlines VALUES((NEW).*);
END IF;
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER archive_inserted_rows_orderlines
BEFORE INSERT ON orderlines
FOR EACH ROW EXECUTE PROCEDURE archive_on_insert_orderlines();
------------------------------------------------
CREATE OR REPLACE FUNCTION archive_on_update_orders() RETURNS trigger
AS $$
BEGIN
IF (
OLD.orderdate IS DISTINCT FROM NEW.orderdate OR
OLD.customerid IS DISTINCT FROM NEW.customerid OR
OLD.netamount IS DISTINCT FROM NEW.netamount OR
OLD.tax IS DISTINCT FROM NEW.tax OR
OLD.totalamount IS DISTINCT FROM NEW.totalamount
) THEN
UPDATE archive_orders SET
orderdate = NEW.orderdate,
customerid = NEW.customerid,
netamount = NEW.netamount,
tax = NEW.tax,
totalamount = NEW.totalamount
WHERE archive_orders.orderid = NEW.orderid;
END IF;
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER update_archived_rows_orders
BEFORE UPDATE ON orders
FOR EACH ROW EXECUTE PROCEDURE archive_on_update_orders();
CREATE OR REPLACE FUNCTION archive_on_update_orderlines() RETURNS trigger
AS $$
BEGIN
IF (
OLD.orderid IS DISTINCT FROM NEW.orderid OR
OLD.prod_id IS DISTINCT FROM NEW.prod_id OR
OLD.quantity IS DISTINCT FROM NEW.quantity OR
OLD.orderdate IS DISTINCT FROM NEW.orderdate
) THEN
UPDATE archive_orderlines SET
prod_id = NEW.prod_id,
quantity = NEW.quantity,
orderdate = NEW.orderdate
WHERE archive_orderlines.orderlineid = NEW.orderlineid AND archive_orders.orderid = NEW.orderid;
END IF;
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER update_archived_rows_orderlines
BEFORE UPDATE ON orderlines
FOR EACH ROW EXECUTE PROCEDURE archive_on_update_orderlines();
------------ Automatická archivace --------------
CREATE OR REPLACE FUNCTION archive() RETURNS VOID
AS $$
BEGIN
WITH orderlines_rows_to_archive AS (
DELETE FROM orderlines a
WHERE orderdate < current_timestamp - interval '3 month'
RETURNING a.*
)
INSERT INTO archive_orderlines
SELECT DISTINCT * FROM orderlines_rows_to_archive WHERE orderlines_rows_to_archive.orderlineid NOT IN (select orderlineid from archive_orderlines) AND orderlines_rows_to_archive.orderid NOT IN (select orderid from archive_orderlines);
WITH orders_rows_to_archive AS (
DELETE FROM orders a
WHERE orderdate < current_timestamp - interval '3 month'
RETURNING a.*
)
INSERT INTO archive_orders
SELECT DISTINCT * FROM orders_rows_to_archive WHERE orders_rows_to_archive.orderid NOT IN (select orderid from archive_orders);
END;
$$ LANGUAGE plpgsql;
---------------- Obnovení -----------------------
CREATE OR REPLACE FUNCTION restore(a date,b date) RETURNS VOID
AS $$
BEGIN
insert into orders select * from archive_orders WHERE orderdate BETWEEN a AND b;
insert into orderlines select * from archive_orderlines WHERE orderdate BETWEEN a AND b;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION restore_order_by_id(a integer) RETURNS VOID
AS $$
BEGIN
insert into orders select * from archive_orders WHERE orderid=a;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION restore_orderline_by_id(a integer, b integer) RETURNS VOID
AS $$
BEGIN
insert into orderlines select * from archive_orderlines WHERE orderid=a and orderlineid=b;
END;
$$ LANGUAGE plpgsql;
---------------- Dělení archivu -----------------
CREATE OR REPLACE FUNCTION partition_archive() RETURNS void AS $$
BEGIN
EXECUTE 'CREATE TABLE archive_orders' ||
to_char(current_timestamp + interval '1 month', 'YYYY_MM01') ||
to_char(current_timestamp + interval '2 month', '_MM01') ||
' partition of archive_orders for values from ' ||
to_char(current_timestamp + interval '1 month', '(''YYYY-MM-01'')') ||
' to ' ||
to_char(current_timestamp + interval '2 month', '(''YYYY-MM-01'');');
EXECUTE 'CREATE TABLE archive_orderlines' ||
to_char(current_timestamp + interval '1 month', 'YYYY_MM01') ||
to_char(current_timestamp + interval '2 month', '_MM01') ||
' partition of archive_orderlines for values from ' ||
to_char(current_timestamp + interval '1 month', '(''YYYY-MM-01'')') ||
' to ' ||
to_char(current_timestamp + interval '2 month', '(''YYYY-MM-01'');');
END;
$$ LANGUAGE PLPGSQL;