-
Notifications
You must be signed in to change notification settings - Fork 1
/
tie.sql.jinja2
131 lines (111 loc) · 3.04 KB
/
tie.sql.jinja2
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
{% import 'util.jinja2' as util %}
-- TIE
{%- macro insert() %}
INSERT INTO "{{table}}" (metadata {% for fk in tie.fks %}, "{{fk.name}}"{% endfor %})
VALUES (NEW.metadata {% for fk in tie.fks %},NEW."{{fk.name}}"{% endfor %});
{%- endmacro %}
{%- macro default_metadata() %}
-- For now, allow empty metadata:
IF NEW.metadata IS NULL THEN
NEW.metadata := 0;
END IF;
{%- endmacro %}
{%- macro default_valid_time() %}
IF NEW.valid_time IS NULL THEN
NEW.valid_time := {{tie.valid_type}}({{v_current_time}}, 'infinity', '[)');
END IF;
{%- endmacro %}
{%- macro insert_expression() %}
INSERT INTO "{{table}}" (
metadata
,valid_time
{%- for fk in tie.fks %}
,"{{fk.name}}"
{%- endfor %}
)
VALUES (
NEW.metadata
,NEW.valid_time
{%- for fk in tie.fks %}
,NEW."{{fk.name}}"
{%- endfor %}
);
{%- endmacro %}
create table if not exists "{{table}}" (
metadata integer not null
{%- for fk in tie.fks %}
,"{{fk.name}}" {{typeof_fk(fk)}} not null references "{{fk.table}}"("{{fk.ref_id}}")
{%- endfor %}
,EXCLUDE USING gist (
{%- for fk in tie.fks %}
"{{fk.name}}" with =,
{%- endfor %}
transaction_time with &&,
valid_time with &&
)
) INHERITS (transaction_valid_{{tie.valid_type}});
create or replace view "l_{{table}}"
as select
metadata
,"{{table}}".valid_time
{%- for fk in tie.fks %}
,"{{fk.name}}"
{%- endfor %}
from "{{table}}"
where {{v_current_time}} <@ "{{table}}".valid_time
and {{t_current_time}} <@ "{{table}}".transaction_time
;
-- Tie triggers:
CREATE OR REPLACE FUNCTION "delete_l_{{table}}"()
RETURNS TRIGGER AS $$
DECLARE
_count int;
BEGIN
UPDATE "{{table}}" t
SET transaction_time = tstzrange(lower(transaction_time), current_timestamp, '[)')
WHERE current_timestamp <@ transaction_time
{%- for fk in tie.fks %}
AND "{{fk.name}}" = OLD."{{fk.name}}"
{%- endfor %}
;
-- For compatibility with non-temporal-DB aware software (e.g. SQLAlchemy/Flask-Admin):
GET DIAGNOSTICS _count = ROW_COUNT;
create temporary table if not exists tmp (
a int not null
) on commit drop;
insert into tmp select generate_series(1, _count);
delete from tmp;
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION "update_l_{{table}}"()
RETURNS TRIGGER AS $$
BEGIN
{{default_metadata()}}
{{default_valid_time()}}
IF NEW.* IS DISTINCT FROM OLD.* THEN
-- First invalidate the old version of the tie:
UPDATE "{{table}}"
SET transaction_time = tstzrange(lower(transaction_time), current_timestamp, '[)')
WHERE current_timestamp <@ transaction_time
AND valid_time = OLD.valid_time
{%- for fk in tie.fks %}
AND "{{fk.name}}" = OLD."{{fk.name}}"
{%- endfor %}
;
-- Then insert a new validity time period for the tie:
{{insert_expression()}}
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION "insert_l_{{table}}"()
RETURNS TRIGGER AS $$
BEGIN
{{default_metadata()}}
{{default_valid_time()}}
{{insert_expression()}}
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
{{util.create_trigger_references(table, 'l_')}}