@haathie/pgmb 0.2.16 → 0.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/sql/pgmb-0.2.0-0.2.2.sql +54 -0
- package/sql/pgmb-0.2.0-0.2.8.sql +2 -0
- package/sql/pgmb-0.2.15-0.2.17.sql +57 -0
- package/sql/pgmb.sql +4 -2
package/package.json
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
SET search_path TO pgmb;
|
|
2
|
+
-- Trigger that pushes changes to the events table
|
|
3
|
+
CREATE OR REPLACE FUNCTION push_table_event()
|
|
4
|
+
RETURNS TRIGGER AS $$
|
|
5
|
+
DECLARE
|
|
6
|
+
start_num BIGINT = create_random_bigint();
|
|
7
|
+
BEGIN
|
|
8
|
+
IF TG_OP = 'INSERT' THEN
|
|
9
|
+
INSERT INTO events(id, topic, payload)
|
|
10
|
+
SELECT
|
|
11
|
+
create_event_id(clock_timestamp(), rand := start_num + row_number() OVER ()),
|
|
12
|
+
create_topic(TG_TABLE_SCHEMA, TG_TABLE_NAME, TG_OP),
|
|
13
|
+
jsonb_strip_nulls(s.data)
|
|
14
|
+
FROM NEW n
|
|
15
|
+
CROSS JOIN LATERAL
|
|
16
|
+
serialise_record_for_event(TG_RELID, TG_OP, n) AS s(data, emit)
|
|
17
|
+
WHERE s.emit;
|
|
18
|
+
ELSIF TG_OP = 'DELETE' THEN
|
|
19
|
+
INSERT INTO events(id, topic, payload)
|
|
20
|
+
SELECT
|
|
21
|
+
create_event_id(clock_timestamp(), rand := start_num + row_number() OVER ()),
|
|
22
|
+
create_topic(TG_TABLE_SCHEMA, TG_TABLE_NAME, TG_OP),
|
|
23
|
+
jsonb_strip_nulls(to_jsonb(s.data))
|
|
24
|
+
FROM OLD o
|
|
25
|
+
CROSS JOIN LATERAL
|
|
26
|
+
serialise_record_for_event(TG_RELID, TG_OP, o) AS s(data, emit)
|
|
27
|
+
WHERE s.emit;
|
|
28
|
+
ELSIF TG_OP = 'UPDATE' THEN
|
|
29
|
+
-- For updates, we can send both old and new data
|
|
30
|
+
INSERT INTO events(id, topic, payload, metadata)
|
|
31
|
+
SELECT
|
|
32
|
+
create_event_id(clock_timestamp(), rand := start_num + n.rn),
|
|
33
|
+
create_topic(TG_TABLE_SCHEMA, TG_TABLE_NAME, TG_OP),
|
|
34
|
+
jsonb_diff(n.data, o.data),
|
|
35
|
+
jsonb_build_object('old', jsonb_strip_nulls(o.data))
|
|
36
|
+
FROM (
|
|
37
|
+
SELECT s.data, s.emit, row_number() OVER () AS rn
|
|
38
|
+
FROM NEW n
|
|
39
|
+
CROSS JOIN LATERAL
|
|
40
|
+
serialise_record_for_event(TG_RELID, TG_OP, n) AS s(data, emit)
|
|
41
|
+
) AS n
|
|
42
|
+
INNER JOIN (
|
|
43
|
+
SELECT s.data, row_number() OVER () AS rn FROM OLD o
|
|
44
|
+
CROSS JOIN LATERAL
|
|
45
|
+
serialise_record_for_event(TG_RELID, TG_OP, o) AS s(data, emit)
|
|
46
|
+
) AS o ON n.rn = o.rn
|
|
47
|
+
-- ignore rows where data didn't change
|
|
48
|
+
WHERE jsonb_diff(n.data, o.data) is not null AND n.emit;
|
|
49
|
+
END IF;
|
|
50
|
+
|
|
51
|
+
RETURN NULL;
|
|
52
|
+
END
|
|
53
|
+
$$ LANGUAGE plpgsql SECURITY DEFINER VOLATILE PARALLEL UNSAFE
|
|
54
|
+
SET search_path TO pgmb;
|
package/sql/pgmb-0.2.0-0.2.8.sql
CHANGED
|
@@ -4,6 +4,8 @@ ALTER TYPE config_type ADD VALUE 'use_pg_cron';
|
|
|
4
4
|
ALTER TYPE config_type ADD VALUE 'pg_cron_poll_for_events_cron';
|
|
5
5
|
ALTER TYPE config_type ADD VALUE 'pg_cron_partition_maintenance_cron';
|
|
6
6
|
|
|
7
|
+
COMMIT; -- prevents unsafe enum use
|
|
8
|
+
|
|
7
9
|
INSERT INTO config(id, value) VALUES
|
|
8
10
|
('pg_cron_poll_for_events_cron', '1 second'),
|
|
9
11
|
-- every 30 minutes
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
SET search_path TO pgmb;
|
|
2
|
+
|
|
3
|
+
CREATE OR REPLACE FUNCTION prepare_poll_for_events_fn(
|
|
4
|
+
sql_statements TEXT[]
|
|
5
|
+
) RETURNS VOID AS $$
|
|
6
|
+
DECLARE
|
|
7
|
+
tmpl_proc_name constant TEXT :=
|
|
8
|
+
'poll_for_events_tmpl';
|
|
9
|
+
tmpl_proc_placeholder constant TEXT :=
|
|
10
|
+
'TRUE -- CONDITIONS_SQL_PLACEHOLDER --';
|
|
11
|
+
condition_sql TEXT;
|
|
12
|
+
proc_src TEXT;
|
|
13
|
+
BEGIN
|
|
14
|
+
IF sql_statements = '{}' THEN
|
|
15
|
+
-- no subscriptions, so just use 'FALSE' to avoid any matches
|
|
16
|
+
sql_statements := ARRAY['FALSE'];
|
|
17
|
+
END IF;
|
|
18
|
+
-- build the condition SQL
|
|
19
|
+
condition_sql := FORMAT(
|
|
20
|
+
'('
|
|
21
|
+
|| array_to_string(
|
|
22
|
+
ARRAY(
|
|
23
|
+
SELECT
|
|
24
|
+
'(' || stmt || ') AND s.conditions_sql = %L'
|
|
25
|
+
FROM unnest(sql_statements) AS arr(stmt)
|
|
26
|
+
),
|
|
27
|
+
') OR ('
|
|
28
|
+
)
|
|
29
|
+
|| ')',
|
|
30
|
+
VARIADIC sql_statements
|
|
31
|
+
);
|
|
32
|
+
condition_sql := FORMAT('/* updated at %s */', NOW()) || condition_sql;
|
|
33
|
+
|
|
34
|
+
-- fetch the source of the template procedure
|
|
35
|
+
select pg_get_functiondef(oid) INTO proc_src
|
|
36
|
+
from pg_proc where proname = tmpl_proc_name and
|
|
37
|
+
pronamespace = 'pgmb'::regnamespace;
|
|
38
|
+
IF proc_src IS NULL THEN
|
|
39
|
+
RAISE EXCEPTION 'Template procedure % not found', tmpl_proc_name;
|
|
40
|
+
END IF;
|
|
41
|
+
|
|
42
|
+
-- replace the placeholder with the actual condition SQL
|
|
43
|
+
proc_src := REPLACE(proc_src, tmpl_proc_placeholder, condition_sql);
|
|
44
|
+
proc_src := REPLACE(proc_src, tmpl_proc_name, 'poll_for_events');
|
|
45
|
+
|
|
46
|
+
-- the new poll_for_events function will be created with
|
|
47
|
+
-- the pgmb_reader role, to avoid a bad "conditions_sql"
|
|
48
|
+
-- from having any destructive access to the database.
|
|
49
|
+
EXECUTE proc_src;
|
|
50
|
+
-- changing the owner will ensure that the function is executed with
|
|
51
|
+
-- the pgmb_reader's permissions.
|
|
52
|
+
-- https://www.postgresql.org/docs/current/sql-alterfunction.html
|
|
53
|
+
EXECUTE 'ALTER FUNCTION poll_for_events() OWNER TO pgmb_reader';
|
|
54
|
+
END;
|
|
55
|
+
$$ LANGUAGE plpgsql VOLATILE STRICT PARALLEL UNSAFE
|
|
56
|
+
SET search_path TO pgmb
|
|
57
|
+
SECURITY INVOKER;
|
package/sql/pgmb.sql
CHANGED
|
@@ -589,9 +589,11 @@ BEGIN
|
|
|
589
589
|
-- the new poll_for_events function will be created with
|
|
590
590
|
-- the pgmb_reader role, to avoid a bad "conditions_sql"
|
|
591
591
|
-- from having any destructive access to the database.
|
|
592
|
-
SET ROLE pgmb_reader;
|
|
593
592
|
EXECUTE proc_src;
|
|
594
|
-
|
|
593
|
+
-- changing the owner will ensure that the function is executed with
|
|
594
|
+
-- the pgmb_reader's permissions.
|
|
595
|
+
-- https://www.postgresql.org/docs/current/sql-alterfunction.html
|
|
596
|
+
EXECUTE 'ALTER FUNCTION poll_for_events() OWNER TO pgmb_reader';
|
|
595
597
|
END;
|
|
596
598
|
$$ LANGUAGE plpgsql VOLATILE STRICT PARALLEL UNSAFE
|
|
597
599
|
SET search_path TO pgmb
|