Repository navigation
Expand file tree
/
Copy pathall.sql
More file actions
140 lines (117 loc) · 4.57 KB
/
Copy pathall.sql
File metadata and controls
140 lines (117 loc) · 4.57 KB
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
CREATE SCHEMA "blocks";
CREATE TABLE "blocks"."block"
(
uuid UUID PRIMARY KEY NOT NULL,
settings_type CHARACTER VARYING NOT NULL,
settings JSONB NOT NULL,
title CHARACTER VARYING,
view_type CHARACTER VARYING,
enabled BOOL DEFAULT TRUE NOT NULL,
visibility_settings JSONB
);
CREATE UNIQUE INDEX "block_uuid_uindex"
ON "blocks"."block" (uuid);
CREATE INDEX "enabled_index"
ON "blocks"."block" (enabled);
CREATE TABLE "blocks"."placement"
(
location_name CHARACTER VARYING NOT NULL,
index INT NOT NULL,
block_uuid UUID NOT NULL,
scope_path CHARACTER VARYING NOT NULL,
inherited BOOL DEFAULT FALSE NOT NULL,
excluded_scopes CHARACTER VARYING [],
-- NOTE: Because we UPDATE the primary (location_name, index) key on the placement-table,
-- the constraint behavior on the primary key is set to DEFERRABLE and INITIALLY IMMEDIATE.
--
-- For more inforation, refer to this bug-report:
--
-- https://www.postgresql.org/message-id/flat/20170322123053.1421.55154%40wrigleys.postgresql.org
CONSTRAINT placement_location_name_index_pk PRIMARY KEY (location_name, index) DEFERRABLE INITIALLY IMMEDIATE,
CONSTRAINT placement_block_uuid_fk FOREIGN KEY (block_uuid) REFERENCES "blocks"."block" (uuid) ON DELETE CASCADE
);
CREATE INDEX "placement_location_name_index_index"
ON "blocks".placement (location_name, index);
CREATE INDEX "placement_scope_path_index"
ON "blocks".placement (scope_path);
CREATE INDEX "placement_index_index"
ON "blocks".placement (index);
CREATE TABLE "blocks"."location_hash"
(
location_name CHARACTER VARYING PRIMARY KEY NOT NULL,
hash CHARACTER VARYING NOT NULL
);
CREATE TABLE "blocks"."child_blocks"
(
parent_uuid UUID NOT NULL,
column_index INT NOT NULL,
child_uuids UUID [] NOT NULL,
CONSTRAINT child_blocks_parent_uuid_index_pk PRIMARY KEY (parent_uuid, column_index),
CONSTRAINT child_blocks_block_uuid_fk FOREIGN KEY (parent_uuid) REFERENCES "blocks"."block" (uuid) ON DELETE CASCADE
-- TODO add a trigger to sanitize child_uuids when a block record is deleted
);
CREATE INDEX "child_blocks_parent_uuid_index"
ON "blocks"."child_blocks" (parent_uuid);
CREATE TABLE "blocks"."user_bucket"
(
user_uuid UUID PRIMARY KEY NOT NULL,
block_uuids UUID [] NOT NULL
);
CREATE UNIQUE INDEX "user_bucket_user_uuid_uindex"
ON "blocks"."user_bucket" (user_uuid);
CREATE VIEW "blocks"."block_count" AS
SELECT
b."uuid" AS "block_uuid",
(
(SELECT COUNT(*)
FROM "blocks"."placement" p
WHERE p."block_uuid" = b."uuid")
+
(SELECT COALESCE(SUM((SELECT COUNT(*)
FROM unnest(c."child_uuids") cb
WHERE cb = b."uuid")), 0)
FROM "blocks"."child_blocks" c)
) AS "ref_count",
(SELECT COUNT(*)
FROM "blocks"."user_bucket" k
WHERE "uuid" = ANY (k."block_uuids")) AS "user_count"
FROM "blocks"."block" b;
CREATE OR REPLACE FUNCTION "blocks".delete_orphaned_blocks()
RETURNS TRIGGER
AS $$
BEGIN
LOOP
-- Note that RETURN QUERY does not return from the function - it works
-- more like the yield-statement in PHP, in that records from the
-- DELETE..RETURNING statement are returned, and execution then
-- resumes from the following statement.
DELETE FROM "blocks"."block" b
WHERE b.uuid IN (
SELECT c.block_uuid
FROM "blocks"."block_count" c
WHERE c.ref_count = 0 AND c.user_count = 0
);
-- The FOUND flag is set TRUE/FALSE after executing a query - so we
-- EXIT from the LOOP block when the DELETE..RETURNING statement does
-- not delete and return any records.
EXIT WHEN NOT FOUND;
END LOOP;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER delete_orphans
AFTER UPDATE OR DELETE
ON "blocks"."user_bucket"
FOR EACH STATEMENT
EXECUTE PROCEDURE "blocks".delete_orphaned_blocks();
CREATE TRIGGER delete_orphans
AFTER UPDATE OR DELETE
ON "blocks"."placement"
FOR EACH STATEMENT
EXECUTE PROCEDURE "blocks".delete_orphaned_blocks();
CREATE TRIGGER delete_orphans
AFTER UPDATE OR DELETE
ON "blocks"."child_blocks"
FOR EACH STATEMENT
EXECUTE PROCEDURE "blocks".delete_orphaned_blocks();