rev |
line source |
jbe@536
|
1 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'unit_created';
|
jbe@536
|
2 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'unit_updated';
|
jbe@539
|
3 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'area_created';
|
jbe@539
|
4 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'area_updated';
|
jbe@536
|
5 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'policy_created';
|
jbe@536
|
6 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'policy_updated';
|
jbe@532
|
7 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'suggestion_removed';
|
jbe@532
|
8 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'member_activated';
|
jbe@532
|
9 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'member_removed';
|
jbe@532
|
10 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'member_active';
|
jbe@532
|
11 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'member_name_updated';
|
jbe@532
|
12 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'member_profile_updated';
|
jbe@532
|
13 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'member_image_updated';
|
jbe@532
|
14 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'interest';
|
jbe@532
|
15 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'initiator';
|
jbe@532
|
16 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'support';
|
jbe@532
|
17 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'support_updated';
|
jbe@532
|
18 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'suggestion_rated';
|
jbe@532
|
19 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'delegation';
|
jbe@532
|
20 ALTER TYPE "event_type" ADD VALUE IF NOT EXISTS 'contact';
|
jbe@532
|
21
|
jbe@532
|
22
|
jbe@532
|
23 BEGIN;
|
jbe@532
|
24
|
jbe@532
|
25
|
jbe@532
|
26 CREATE OR REPLACE VIEW "liquid_feedback_version" AS
|
jbe@532
|
27 SELECT * FROM (VALUES ('4.0-dev', 4, 0, -1))
|
jbe@532
|
28 AS "subquery"("string", "major", "minor", "revision");
|
jbe@532
|
29
|
jbe@532
|
30
|
jbe@532
|
31 ALTER TABLE "system_setting" ADD COLUMN "snapshot_retention" INTERVAL;
|
jbe@532
|
32
|
jbe@532
|
33 COMMENT ON COLUMN "system_setting"."snapshot_retention" IS 'Unreferenced snapshots are retained for the given period of time after creation; set to NULL for infinite retention.';
|
jbe@532
|
34
|
jbe@532
|
35
|
jbe@544
|
36 CREATE TABLE "member_settings" (
|
jbe@544
|
37 "member_id" INT4 PRIMARY KEY REFERENCES "member" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@544
|
38 "settings" JSONB NOT NULL CHECK (jsonb_typeof("settings") = 'object') );
|
jbe@544
|
39
|
jbe@544
|
40 COMMENT ON TABLE "member_settings" IS 'Stores a JSON document for each member containing optional (additional) settings for the respective member';
|
jbe@544
|
41
|
jbe@544
|
42
|
jbe@544
|
43 CREATE TABLE "member_useterms" (
|
jbe@544
|
44 "member_id" INT4 PRIMARY KEY REFERENCES "member" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@544
|
45 "accepted" TIMESTAMPTZ NOT NULL,
|
jbe@544
|
46 "contract_identifier" TEXT NOT NULL );
|
jbe@544
|
47
|
jbe@544
|
48 COMMENT ON TABLE "member_useterms" IS 'Keeps record of accepted terms of use; may contain multiple rows per member';
|
jbe@544
|
49
|
jbe@544
|
50 COMMENT ON COLUMN "member_useterms"."accepted" IS 'Point in time when user accepted the terms of use';
|
jbe@544
|
51 COMMENT ON COLUMN "member_useterms"."contract_identifier" IS 'String identifier to denote the accepted terms of use, including their version or revision';
|
jbe@544
|
52
|
jbe@544
|
53
|
jbe@532
|
54 CREATE TABLE "member_profile" (
|
jbe@532
|
55 "member_id" INT4 PRIMARY KEY REFERENCES "member" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
56 "formatting_engine" TEXT,
|
jbe@532
|
57 "statement" TEXT,
|
jbe@544
|
58 "profile" JSONB NOT NULL DEFAULT '{}' CHECK (jsonb_typeof("profile") = 'object'),
|
jbe@532
|
59 "profile_text_data" TEXT,
|
jbe@532
|
60 "text_search_data" TSVECTOR );
|
jbe@532
|
61 CREATE INDEX "member_profile_text_search_data_idx" ON "member_profile" USING gin ("text_search_data");
|
jbe@532
|
62 CREATE TRIGGER "update_text_search_data"
|
jbe@532
|
63 BEFORE INSERT OR UPDATE ON "member_profile"
|
jbe@532
|
64 FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
65 tsvector_update_trigger('text_search_data', 'pg_catalog.simple',
|
jbe@532
|
66 'statement', 'profile_text_data');
|
jbe@532
|
67
|
jbe@532
|
68 COMMENT ON COLUMN "member_profile"."formatting_engine" IS 'Allows different formatting engines (i.e. wiki formats) to be used for "member_profile"."statement"';
|
jbe@532
|
69 COMMENT ON COLUMN "member_profile"."statement" IS 'Freely chosen text of the member for his/her profile';
|
jbe@532
|
70 COMMENT ON COLUMN "member_profile"."profile" IS 'Additional profile data as JSON document';
|
jbe@532
|
71 COMMENT ON COLUMN "member_profile"."profile_text_data" IS 'Text data from "profile" field for full text search';
|
jbe@532
|
72
|
jbe@532
|
73
|
jbe@532
|
74 INSERT INTO "member_profile"
|
jbe@532
|
75 ( "member_id", "formatting_engine", "statement", "profile")
|
jbe@532
|
76 SELECT
|
jbe@532
|
77 "id" AS "member_id",
|
jbe@532
|
78 "formatting_engine",
|
jbe@532
|
79 "statement",
|
jbe@532
|
80 json_build_object(
|
jbe@532
|
81 'organizational_unit', "organizational_unit",
|
jbe@532
|
82 'internal_posts', "internal_posts",
|
jbe@532
|
83 'realname', "realname",
|
jbe@532
|
84 'birthday', to_char("birthday", 'YYYY-MM-DD'),
|
jbe@532
|
85 'address', "address",
|
jbe@532
|
86 'email', "email",
|
jbe@532
|
87 'xmpp_address', "xmpp_address",
|
jbe@532
|
88 'website', "website",
|
jbe@532
|
89 'phone', "phone",
|
jbe@532
|
90 'mobile_phone', "mobile_phone",
|
jbe@532
|
91 'profession', "profession",
|
jbe@532
|
92 'external_memberships', "external_memberships",
|
jbe@532
|
93 'external_posts', "external_posts"
|
jbe@532
|
94 ) AS "profile"
|
jbe@532
|
95 FROM "member";
|
jbe@532
|
96
|
jbe@532
|
97 UPDATE "member_profile" SET "profile_text_data" =
|
jbe@532
|
98 coalesce(("profile"->>'organizational_unit') || ' ', '') ||
|
jbe@532
|
99 coalesce(("profile"->>'internal_posts') || ' ', '') ||
|
jbe@532
|
100 coalesce(("profile"->>'realname') || ' ', '') ||
|
jbe@532
|
101 coalesce(("profile"->>'birthday') || ' ', '') ||
|
jbe@532
|
102 coalesce(("profile"->>'address') || ' ', '') ||
|
jbe@532
|
103 coalesce(("profile"->>'email') || ' ', '') ||
|
jbe@532
|
104 coalesce(("profile"->>'xmpp_address') || ' ', '') ||
|
jbe@532
|
105 coalesce(("profile"->>'website') || ' ', '') ||
|
jbe@532
|
106 coalesce(("profile"->>'phone') || ' ', '') ||
|
jbe@532
|
107 coalesce(("profile"->>'mobile_phone') || ' ', '') ||
|
jbe@532
|
108 coalesce(("profile"->>'profession') || ' ', '') ||
|
jbe@532
|
109 coalesce(("profile"->>'external_memberships') || ' ', '') ||
|
jbe@532
|
110 coalesce(("profile"->>'external_posts') || ' ', '');
|
jbe@532
|
111
|
jbe@532
|
112
|
jbe@532
|
113 DROP VIEW "newsletter_to_send";
|
jbe@532
|
114 DROP VIEW "scheduled_notification_to_send";
|
jbe@532
|
115 DROP VIEW "member_to_notify";
|
jbe@532
|
116 DROP VIEW "member_eligible_to_be_notified";
|
jbe@532
|
117
|
jbe@532
|
118
|
jbe@532
|
119 ALTER TABLE "member" DROP COLUMN "organizational_unit";
|
jbe@532
|
120 ALTER TABLE "member" DROP COLUMN "internal_posts";
|
jbe@532
|
121 ALTER TABLE "member" DROP COLUMN "realname";
|
jbe@532
|
122 ALTER TABLE "member" DROP COLUMN "birthday";
|
jbe@532
|
123 ALTER TABLE "member" DROP COLUMN "address";
|
jbe@532
|
124 ALTER TABLE "member" DROP COLUMN "email";
|
jbe@532
|
125 ALTER TABLE "member" DROP COLUMN "xmpp_address";
|
jbe@532
|
126 ALTER TABLE "member" DROP COLUMN "website";
|
jbe@532
|
127 ALTER TABLE "member" DROP COLUMN "phone";
|
jbe@532
|
128 ALTER TABLE "member" DROP COLUMN "mobile_phone";
|
jbe@532
|
129 ALTER TABLE "member" DROP COLUMN "profession";
|
jbe@532
|
130 ALTER TABLE "member" DROP COLUMN "external_memberships";
|
jbe@532
|
131 ALTER TABLE "member" DROP COLUMN "external_posts";
|
jbe@532
|
132 ALTER TABLE "member" DROP COLUMN "formatting_engine";
|
jbe@532
|
133 ALTER TABLE "member" DROP COLUMN "statement";
|
jbe@532
|
134
|
jbe@532
|
135 ALTER TABLE "member" ADD COLUMN "location" JSONB;
|
jbe@532
|
136 COMMENT ON COLUMN "member"."location" IS 'Geographic location on earth as GeoJSON object';
|
jbe@532
|
137 CREATE INDEX "member_location_idx" ON "member" USING gist ((GeoJSON_to_ecluster("location")));
|
jbe@532
|
138
|
jbe@532
|
139 DROP TRIGGER "update_text_search_data" ON "member";
|
jbe@532
|
140 CREATE TRIGGER "update_text_search_data"
|
jbe@532
|
141 BEFORE INSERT OR UPDATE ON "member"
|
jbe@532
|
142 FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
143 tsvector_update_trigger('text_search_data', 'pg_catalog.simple',
|
jbe@532
|
144 "name", "identification");
|
jbe@532
|
145
|
jbe@532
|
146
|
jbe@532
|
147 CREATE VIEW "member_eligible_to_be_notified" AS
|
jbe@532
|
148 SELECT * FROM "member"
|
jbe@532
|
149 WHERE "activated" NOTNULL AND "locked" = FALSE;
|
jbe@532
|
150
|
jbe@532
|
151 COMMENT ON VIEW "member_eligible_to_be_notified" IS 'Filtered "member" table containing only activated and non-locked members (used as helper view for "member_to_notify" and "newsletter_to_send")';
|
jbe@532
|
152
|
jbe@532
|
153
|
jbe@532
|
154 CREATE VIEW "member_to_notify" AS
|
jbe@532
|
155 SELECT * FROM "member_eligible_to_be_notified"
|
jbe@532
|
156 WHERE "disable_notifications" = FALSE;
|
jbe@532
|
157
|
jbe@532
|
158 COMMENT ON VIEW "member_to_notify" IS 'Filtered "member" table containing only members that are eligible to and wish to receive notifications; NOTE: "notify_email" may still be NULL and might need to be checked by frontend (this allows other means of messaging)';
|
jbe@532
|
159
|
jbe@532
|
160
|
jbe@532
|
161 CREATE VIEW "scheduled_notification_to_send" AS
|
jbe@532
|
162 SELECT * FROM (
|
jbe@532
|
163 SELECT
|
jbe@532
|
164 "id" AS "recipient_id",
|
jbe@532
|
165 now() - CASE WHEN "notification_dow" ISNULL THEN
|
jbe@532
|
166 ( "notification_sent"::DATE + CASE
|
jbe@532
|
167 WHEN EXTRACT(HOUR FROM "notification_sent") < "notification_hour"
|
jbe@532
|
168 THEN 0 ELSE 1 END
|
jbe@532
|
169 )::TIMESTAMP + '1 hour'::INTERVAL * "notification_hour"
|
jbe@532
|
170 ELSE
|
jbe@532
|
171 ( "notification_sent"::DATE +
|
jbe@532
|
172 ( 7 + "notification_dow" -
|
jbe@532
|
173 EXTRACT(DOW FROM
|
jbe@532
|
174 ( "notification_sent"::DATE + CASE
|
jbe@532
|
175 WHEN EXTRACT(HOUR FROM "notification_sent") < "notification_hour"
|
jbe@532
|
176 THEN 0 ELSE 1 END
|
jbe@532
|
177 )::TIMESTAMP + '1 hour'::INTERVAL * "notification_hour"
|
jbe@532
|
178 )::INTEGER
|
jbe@532
|
179 ) % 7 +
|
jbe@532
|
180 CASE
|
jbe@532
|
181 WHEN EXTRACT(HOUR FROM "notification_sent") < "notification_hour"
|
jbe@532
|
182 THEN 0 ELSE 1
|
jbe@532
|
183 END
|
jbe@532
|
184 )::TIMESTAMP + '1 hour'::INTERVAL * "notification_hour"
|
jbe@532
|
185 END AS "pending"
|
jbe@532
|
186 FROM (
|
jbe@532
|
187 SELECT
|
jbe@532
|
188 "id",
|
jbe@532
|
189 COALESCE("notification_sent", "activated") AS "notification_sent",
|
jbe@532
|
190 "notification_dow",
|
jbe@532
|
191 "notification_hour"
|
jbe@532
|
192 FROM "member_to_notify"
|
jbe@532
|
193 WHERE "notification_hour" NOTNULL
|
jbe@532
|
194 ) AS "subquery1"
|
jbe@532
|
195 ) AS "subquery2"
|
jbe@532
|
196 WHERE "pending" > '0'::INTERVAL;
|
jbe@532
|
197
|
jbe@532
|
198 COMMENT ON VIEW "scheduled_notification_to_send" IS 'Set of members where a scheduled notification mail is pending';
|
jbe@532
|
199
|
jbe@532
|
200 COMMENT ON COLUMN "scheduled_notification_to_send"."recipient_id" IS '"id" of the member who needs to receive a notification mail';
|
jbe@532
|
201 COMMENT ON COLUMN "scheduled_notification_to_send"."pending" IS 'Duration for which the notification mail has already been pending';
|
jbe@532
|
202
|
jbe@532
|
203
|
jbe@532
|
204 CREATE VIEW "newsletter_to_send" AS
|
jbe@532
|
205 SELECT
|
jbe@532
|
206 "member"."id" AS "recipient_id",
|
jbe@532
|
207 "newsletter"."id" AS "newsletter_id",
|
jbe@532
|
208 "newsletter"."published"
|
jbe@532
|
209 FROM "newsletter" CROSS JOIN "member_eligible_to_be_notified" AS "member"
|
jbe@532
|
210 LEFT JOIN "privilege" ON
|
jbe@532
|
211 "privilege"."member_id" = "member"."id" AND
|
jbe@532
|
212 "privilege"."unit_id" = "newsletter"."unit_id" AND
|
jbe@532
|
213 "privilege"."voting_right" = TRUE
|
jbe@532
|
214 LEFT JOIN "subscription" ON
|
jbe@532
|
215 "subscription"."member_id" = "member"."id" AND
|
jbe@532
|
216 "subscription"."unit_id" = "newsletter"."unit_id"
|
jbe@532
|
217 WHERE "newsletter"."published" <= now()
|
jbe@532
|
218 AND "newsletter"."sent" ISNULL
|
jbe@532
|
219 AND (
|
jbe@532
|
220 "member"."disable_notifications" = FALSE OR
|
jbe@532
|
221 "newsletter"."include_all_members" = TRUE )
|
jbe@532
|
222 AND (
|
jbe@532
|
223 "newsletter"."unit_id" ISNULL OR
|
jbe@532
|
224 "privilege"."member_id" NOTNULL OR
|
jbe@532
|
225 "subscription"."member_id" NOTNULL );
|
jbe@532
|
226
|
jbe@532
|
227 COMMENT ON VIEW "newsletter_to_send" IS 'List of "newsletter_id"s for each member that are due to be sent out';
|
jbe@532
|
228
|
jbe@532
|
229 COMMENT ON COLUMN "newsletter"."published" IS 'Timestamp when the newsletter was supposed to be sent out (can be used for ordering)';
|
jbe@532
|
230
|
jbe@532
|
231
|
jbe@532
|
232 DROP VIEW "expired_session";
|
jbe@532
|
233 DROP TABLE "session";
|
jbe@532
|
234
|
jbe@532
|
235
|
jbe@532
|
236 CREATE TABLE "session" (
|
jbe@532
|
237 UNIQUE ("member_id", "id"), -- index needed for foreign-key on table "token"
|
jbe@532
|
238 "id" SERIAL8 PRIMARY KEY,
|
jbe@532
|
239 "ident" TEXT NOT NULL UNIQUE,
|
jbe@532
|
240 "additional_secret" TEXT,
|
jbe@532
|
241 "logout_token" TEXT,
|
jbe@532
|
242 "expiry" TIMESTAMPTZ NOT NULL DEFAULT now() + '24 hours',
|
jbe@532
|
243 "member_id" INT4 REFERENCES "member" ("id") ON DELETE SET NULL,
|
jbe@532
|
244 "authority" TEXT,
|
jbe@532
|
245 "authority_uid" TEXT,
|
jbe@532
|
246 "authority_login" TEXT,
|
jbe@532
|
247 "needs_delegation_check" BOOLEAN NOT NULL DEFAULT FALSE,
|
jbe@532
|
248 "lang" TEXT );
|
jbe@532
|
249 CREATE INDEX "session_expiry_idx" ON "session" ("expiry");
|
jbe@532
|
250
|
jbe@532
|
251 COMMENT ON TABLE "session" IS 'Sessions, i.e. for a web-frontend or API layer';
|
jbe@532
|
252
|
jbe@532
|
253 COMMENT ON COLUMN "session"."ident" IS 'Secret session identifier (i.e. random string)';
|
jbe@532
|
254 COMMENT ON COLUMN "session"."additional_secret" IS 'Additional field to store a secret, which can be used against CSRF attacks';
|
jbe@532
|
255 COMMENT ON COLUMN "session"."logout_token" IS 'Optional token to authorize logout through external component';
|
jbe@532
|
256 COMMENT ON COLUMN "session"."member_id" IS 'Reference to member, who is logged in';
|
jbe@532
|
257 COMMENT ON COLUMN "session"."authority" IS 'Temporary store for "member"."authority" during member account creation';
|
jbe@532
|
258 COMMENT ON COLUMN "session"."authority_uid" IS 'Temporary store for "member"."authority_uid" during member account creation';
|
jbe@532
|
259 COMMENT ON COLUMN "session"."authority_login" IS 'Temporary store for "member"."authority_login" during member account creation';
|
jbe@532
|
260 COMMENT ON COLUMN "session"."needs_delegation_check" IS 'Set to TRUE, if member must perform a delegation check to proceed with login; see column "last_delegation_check" in "member" table';
|
jbe@532
|
261 COMMENT ON COLUMN "session"."lang" IS 'Language code of the selected language';
|
jbe@532
|
262
|
jbe@532
|
263
|
jbe@532
|
264 CREATE TYPE "authflow" AS ENUM ('code', 'token');
|
jbe@532
|
265
|
jbe@532
|
266 COMMENT ON TYPE "authflow" IS 'OAuth 2.0 flows: ''code'' = Authorization Code flow, ''token'' = Implicit flow';
|
jbe@532
|
267
|
jbe@532
|
268
|
jbe@532
|
269 CREATE TABLE "system_application" (
|
jbe@532
|
270 "id" SERIAL4 PRIMARY KEY,
|
jbe@532
|
271 "name" TEXT NOT NULL,
|
jbe@532
|
272 "client_id" TEXT NOT NULL UNIQUE,
|
jbe@532
|
273 "default_redirect_uri" TEXT NOT NULL,
|
jbe@532
|
274 "cert_common_name" TEXT,
|
jbe@532
|
275 "client_cred_scope" TEXT,
|
jbe@532
|
276 "flow" "authflow",
|
jbe@532
|
277 "automatic_scope" TEXT,
|
jbe@532
|
278 "permitted_scope" TEXT,
|
jbe@532
|
279 "forbidden_scope" TEXT );
|
jbe@532
|
280
|
jbe@532
|
281 COMMENT ON TABLE "system_application" IS 'OAuth 2.0 clients that are registered by the system administrator';
|
jbe@532
|
282
|
jbe@532
|
283 COMMENT ON COLUMN "system_application"."name" IS 'Human readable name of application';
|
jbe@532
|
284 COMMENT ON COLUMN "system_application"."client_id" IS 'OAuth 2.0 "client_id"';
|
jbe@532
|
285 COMMENT ON COLUMN "system_application"."cert_common_name" IS 'Value for CN field of TLS client certificate';
|
jbe@532
|
286 COMMENT ON COLUMN "system_application"."client_cred_scope" IS 'Space-separated list of scopes; If set, Client Credentials Grant is allowed; value determines scope';
|
jbe@532
|
287 COMMENT ON COLUMN "system_application"."flow" IS 'If set to ''code'' or ''token'', then Authorization Code or Implicit flow is allowed respectively';
|
jbe@532
|
288 COMMENT ON COLUMN "system_application"."automatic_scope" IS 'Space-separated list of scopes; Automatically granted scope for Authorization Code or Implicit flow';
|
jbe@532
|
289 COMMENT ON COLUMN "system_application"."permitted_scope" IS 'Space-separated list of scopes; If set, scope that members may grant to the application is limited to the given value';
|
jbe@532
|
290 COMMENT ON COLUMN "system_application"."forbidden_scope" IS 'Space-separated list of scopes that may not be granted to the application by a member';
|
jbe@532
|
291
|
jbe@532
|
292
|
jbe@532
|
293 CREATE TABLE "system_application_redirect_uri" (
|
jbe@532
|
294 PRIMARY KEY ("system_application_id", "redirect_uri"),
|
jbe@532
|
295 "system_application_id" INT4 REFERENCES "system_application" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
296 "redirect_uri" TEXT );
|
jbe@532
|
297
|
jbe@532
|
298 COMMENT ON TABLE "system_application_redirect_uri" IS 'Additional OAuth 2.0 redirection endpoints, which may be selected through the "redirect_uri" GET parameter';
|
jbe@532
|
299
|
jbe@532
|
300
|
jbe@532
|
301 CREATE TABLE "dynamic_application_scope" (
|
jbe@532
|
302 PRIMARY KEY ("redirect_uri", "flow", "scope"),
|
jbe@532
|
303 "redirect_uri" TEXT,
|
jbe@532
|
304 "flow" TEXT,
|
jbe@532
|
305 "scope" TEXT,
|
jbe@532
|
306 "expiry" TIMESTAMPTZ NOT NULL DEFAULT now() + '24 hours' );
|
jbe@532
|
307 CREATE INDEX "dynamic_application_scope_redirect_uri_scope_idx" ON "dynamic_application_scope" ("redirect_uri", "flow", "scope");
|
jbe@532
|
308 CREATE INDEX "dynamic_application_scope_expiry_idx" ON "dynamic_application_scope" ("expiry");
|
jbe@532
|
309
|
jbe@532
|
310 COMMENT ON TABLE "dynamic_application_scope" IS 'Dynamic OAuth 2.0 client registration data';
|
jbe@532
|
311
|
jbe@532
|
312 COMMENT ON COLUMN "dynamic_application_scope"."redirect_uri" IS 'Redirection endpoint for which the registration has been done';
|
jbe@532
|
313 COMMENT ON COLUMN "dynamic_application_scope"."flow" IS 'OAuth 2.0 flow for which the registration has been done (see also "system_application"."flow")';
|
jbe@532
|
314 COMMENT ON COLUMN "dynamic_application_scope"."scope" IS 'Single scope without space characters (use multiple rows for more scopes)';
|
jbe@532
|
315 COMMENT ON COLUMN "dynamic_application_scope"."expiry" IS 'Expiry unless renewed';
|
jbe@532
|
316
|
jbe@532
|
317
|
jbe@532
|
318 CREATE TABLE "member_application" (
|
jbe@532
|
319 "id" SERIAL4 PRIMARY KEY,
|
jbe@532
|
320 UNIQUE ("system_application_id", "member_id"),
|
jbe@532
|
321 UNIQUE ("domain", "member_id"),
|
jbe@532
|
322 "member_id" INT4 NOT NULL REFERENCES "member" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
323 "system_application_id" INT4 REFERENCES "system_application" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
324 "domain" TEXT,
|
jbe@532
|
325 "session_id" INT8,
|
jbe@532
|
326 FOREIGN KEY ("member_id", "session_id") REFERENCES "session" ("member_id", "id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
327 "scope" TEXT NOT NULL,
|
jbe@532
|
328 CONSTRAINT "system_application_or_domain_but_not_both" CHECK (
|
jbe@532
|
329 ("system_application_id" NOTNULL AND "domain" ISNULL) OR
|
jbe@532
|
330 ("system_application_id" ISNULL AND "domain" NOTNULL) ) );
|
jbe@532
|
331 CREATE INDEX "member_application_member_id_idx" ON "member_application" ("member_id");
|
jbe@532
|
332
|
jbe@532
|
333 COMMENT ON TABLE "member_application" IS 'Application authorized by a member';
|
jbe@532
|
334
|
jbe@532
|
335 COMMENT ON COLUMN "member_application"."system_application_id" IS 'If set, then application is a system application';
|
jbe@532
|
336 COMMENT ON COLUMN "member_application"."domain" IS 'If set, then application is a dynamically registered OAuth 2.0 client; value is set to client''s domain';
|
jbe@532
|
337 COMMENT ON COLUMN "member_application"."session_id" IS 'If set, registration ends with session';
|
jbe@532
|
338 COMMENT ON COLUMN "member_application"."scope" IS 'Granted scope as space-separated list of strings';
|
jbe@532
|
339
|
jbe@532
|
340
|
jbe@532
|
341 CREATE TYPE "token_type" AS ENUM ('authorization', 'refresh', 'access');
|
jbe@532
|
342
|
jbe@532
|
343 COMMENT ON TYPE "token_type" IS 'Types for entries in "token" table';
|
jbe@532
|
344
|
jbe@532
|
345
|
jbe@532
|
346 CREATE TABLE "token" (
|
jbe@532
|
347 "id" SERIAL8 PRIMARY KEY,
|
jbe@532
|
348 "token" TEXT NOT NULL UNIQUE,
|
jbe@532
|
349 "token_type" "token_type" NOT NULL,
|
jbe@532
|
350 "authorization_token_id" INT8 REFERENCES "token" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
351 "member_id" INT4 NOT NULL REFERENCES "member" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
352 "system_application_id" INT4 REFERENCES "system_application" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
353 "domain" TEXT,
|
jbe@532
|
354 FOREIGN KEY ("member_id", "domain") REFERENCES "member_application" ("member_id", "domain") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
355 "session_id" INT8,
|
jbe@532
|
356 FOREIGN KEY ("member_id", "session_id") REFERENCES "session" ("member_id", "id") ON DELETE RESTRICT ON UPDATE CASCADE, -- NOTE: deletion through "detach_token_from_session" trigger on table "session"
|
jbe@532
|
357 "redirect_uri" TEXT,
|
jbe@532
|
358 "redirect_uri_explicit" BOOLEAN,
|
jbe@532
|
359 "created" TIMESTAMPTZ NOT NULL DEFAULT now(),
|
jbe@532
|
360 "expiry" TIMESTAMPTZ DEFAULT now() + '1 hour',
|
jbe@532
|
361 "used" BOOLEAN NOT NULL DEFAULT FALSE,
|
jbe@532
|
362 "scope" TEXT NOT NULL,
|
jbe@532
|
363 CONSTRAINT "access_token_needs_expiry"
|
jbe@532
|
364 CHECK ("token_type" != 'access'::"token_type" OR "expiry" NOTNULL),
|
jbe@532
|
365 CONSTRAINT "authorization_token_needs_redirect_uri"
|
jbe@532
|
366 CHECK ("token_type" != 'authorization'::"token_type" OR ("redirect_uri" NOTNULL AND "redirect_uri_explicit" NOTNULL) ) );
|
jbe@532
|
367 CREATE INDEX "token_member_id_idx" ON "token" ("member_id");
|
jbe@532
|
368 CREATE INDEX "token_authorization_token_id_idx" ON "token" ("authorization_token_id");
|
jbe@532
|
369 CREATE INDEX "token_expiry_idx" ON "token" ("expiry");
|
jbe@532
|
370
|
jbe@532
|
371 COMMENT ON TABLE "token" IS 'Issued OAuth 2.0 authorization codes and access/refresh tokens';
|
jbe@532
|
372
|
jbe@532
|
373 COMMENT ON COLUMN "token"."token" IS 'String secret (the actual token)';
|
jbe@532
|
374 COMMENT ON COLUMN "token"."authorization_token_id" IS 'Reference to authorization token if tokens were originally created by Authorization Code flow (allows deletion if code is used twice)';
|
jbe@532
|
375 COMMENT ON COLUMN "token"."system_application_id" IS 'If set, then application is a system application';
|
jbe@532
|
376 COMMENT ON COLUMN "token"."domain" IS 'If set, then application is a dynamically registered OAuth 2.0 client; value is set to client''s domain';
|
jbe@532
|
377 COMMENT ON COLUMN "token"."session_id" IS 'If set, then token is tied to a session; Deletion of session sets value to NULL (via trigger) and removes all scopes without suffix ''_detached''';
|
jbe@532
|
378 COMMENT ON COLUMN "token"."redirect_uri" IS 'Authorization codes must be bound to a specific redirect URI';
|
jbe@532
|
379 COMMENT ON COLUMN "token"."redirect_uri_explicit" IS 'True if ''redirect_uri'' parameter was explicitly specified during authorization request of the Authorization Code flow (since RFC 6749 requires it to be included in the access token request in this case)';
|
jbe@532
|
380 COMMENT ON COLUMN "token"."expiry" IS 'Point in time when code or token expired; In case of "used" authorization codes, authorization code must not be deleted as long as tokens exist which refer to the authorization code';
|
jbe@532
|
381 COMMENT ON COLUMN "token"."used" IS 'Can be set to TRUE for authorization codes that have been used (enables deletion of authorization codes that were used twice)';
|
jbe@532
|
382 COMMENT ON COLUMN "token"."scope" IS 'Scope as space-separated list of strings (detached scopes are marked with ''_detached'' suffix)';
|
jbe@532
|
383
|
jbe@532
|
384
|
jbe@532
|
385 CREATE TABLE "token_scope" (
|
jbe@532
|
386 PRIMARY KEY ("token_id", "index"),
|
jbe@532
|
387 "token_id" INT8 REFERENCES "token" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
388 "index" INT4,
|
jbe@532
|
389 "scope" TEXT NOT NULL );
|
jbe@532
|
390
|
jbe@532
|
391 COMMENT ON TABLE "token_scope" IS 'Additional scopes for an authorization code if ''scope1'', ''scope2'', etc. parameters were used during Authorization Code flow to request several access and refresh tokens at once';
|
jbe@532
|
392
|
jbe@532
|
393
|
jbe@532
|
394 ALTER TABLE "policy" ADD COLUMN "issue_quorum" INT4 CHECK ("issue_quorum" >= 1);
|
jbe@532
|
395 ALTER TABLE "policy" ADD COLUMN "initiative_quorum" INT4 CHECK ("initiative_quorum" >= 1);
|
jbe@532
|
396
|
jbe@532
|
397 UPDATE "policy" SET "issue_quorum" = 1 WHERE "issue_quorum_num" NOTNULL;
|
jbe@532
|
398 UPDATE "policy" SET "initiative_quorum" = 1;
|
jbe@532
|
399
|
jbe@532
|
400 ALTER TABLE "policy" ALTER COLUMN "initiative_quorum" SET NOT NULL;
|
jbe@532
|
401
|
jbe@532
|
402 ALTER TABLE "policy" DROP CONSTRAINT "timing";
|
jbe@532
|
403 ALTER TABLE "policy" DROP CONSTRAINT "issue_quorum_if_and_only_if_not_polling";
|
jbe@532
|
404 ALTER TABLE "policy" ADD CONSTRAINT
|
jbe@532
|
405 "issue_quorum_if_and_only_if_not_polling" CHECK (
|
jbe@532
|
406 "polling" = ("issue_quorum" ISNULL) AND
|
jbe@532
|
407 "polling" = ("issue_quorum_num" ISNULL) AND
|
jbe@532
|
408 "polling" = ("issue_quorum_den" ISNULL)
|
jbe@532
|
409 );
|
jbe@532
|
410 ALTER TABLE "policy" ADD CONSTRAINT
|
jbe@532
|
411 "min_admission_time_smaller_than_max_admission_time" CHECK (
|
jbe@532
|
412 "min_admission_time" < "max_admission_time"
|
jbe@532
|
413 );
|
jbe@532
|
414 ALTER TABLE "policy" ADD CONSTRAINT
|
jbe@532
|
415 "timing_null_or_not_null_constraints" CHECK (
|
jbe@532
|
416 ( "polling" = FALSE AND
|
jbe@532
|
417 "min_admission_time" NOTNULL AND "max_admission_time" NOTNULL AND
|
jbe@532
|
418 "discussion_time" NOTNULL AND
|
jbe@532
|
419 "verification_time" NOTNULL AND
|
jbe@532
|
420 "voting_time" NOTNULL ) OR
|
jbe@532
|
421 ( "polling" = TRUE AND
|
jbe@532
|
422 "min_admission_time" ISNULL AND "max_admission_time" ISNULL AND
|
jbe@532
|
423 "discussion_time" NOTNULL AND
|
jbe@532
|
424 "verification_time" NOTNULL AND
|
jbe@532
|
425 "voting_time" NOTNULL ) OR
|
jbe@532
|
426 ( "polling" = TRUE AND
|
jbe@532
|
427 "min_admission_time" ISNULL AND "max_admission_time" ISNULL AND
|
jbe@532
|
428 "discussion_time" ISNULL AND
|
jbe@532
|
429 "verification_time" ISNULL AND
|
jbe@532
|
430 "voting_time" ISNULL )
|
jbe@532
|
431 );
|
jbe@532
|
432
|
jbe@532
|
433 COMMENT ON COLUMN "policy"."min_admission_time" IS 'Minimum duration of issue state ''admission''; Minimum time an issue stays open; Note: should be considerably smaller than "max_admission_time"';
|
jbe@532
|
434 COMMENT ON COLUMN "policy"."issue_quorum" IS 'Absolute number of supporters needed by an initiative to be "accepted", i.e. pass from ''admission'' to ''discussion'' state';
|
jbe@532
|
435 COMMENT ON COLUMN "policy"."issue_quorum_num" IS 'Numerator of supporter quorum to be reached by an initiative to be "accepted", i.e. pass from ''admission'' to ''discussion'' state (Note: further requirements apply, see quorum columns of "area" table)';
|
jbe@532
|
436 COMMENT ON COLUMN "policy"."issue_quorum_den" IS 'Denominator of supporter quorum to be reached by an initiative to be "accepted", i.e. pass from ''admission'' to ''discussion'' state (Note: further requirements apply, see quorum columns of "area" table)';
|
jbe@532
|
437 COMMENT ON COLUMN "policy"."initiative_quorum" IS 'Absolute number of satisfied supporters to be reached by an initiative to be "admitted" for voting';
|
jbe@532
|
438 COMMENT ON COLUMN "policy"."initiative_quorum_num" IS 'Numerator of satisfied supporter quorum to be reached by an initiative to be "admitted" for voting';
|
jbe@532
|
439 COMMENT ON COLUMN "policy"."initiative_quorum_den" IS 'Denominator of satisfied supporter quorum to be reached by an initiative to be "admitted" for voting';
|
jbe@532
|
440
|
jbe@532
|
441
|
jbe@532
|
442 ALTER TABLE "unit" ADD COLUMN "region" JSONB;
|
jbe@532
|
443
|
jbe@532
|
444 CREATE INDEX "unit_region_idx" ON "unit" USING gist ((GeoJSON_to_ecluster("region")));
|
jbe@532
|
445
|
jbe@532
|
446 COMMENT ON COLUMN "unit"."member_count" IS 'Count of members as determined by column "voting_right" in table "privilege" (only active members counted)';
|
jbe@532
|
447 COMMENT ON COLUMN "unit"."region" IS 'Scattered (or hollow) polygon represented as an array of polygons indicating valid coordinates for initiatives of issues with this policy';
|
jbe@532
|
448
|
jbe@532
|
449
|
jbe@532
|
450 DROP INDEX "area_unit_id_idx";
|
jbe@532
|
451 ALTER TABLE "area" ADD UNIQUE ("unit_id", "id");
|
jbe@532
|
452
|
jbe@532
|
453 ALTER TABLE "area" ADD COLUMN "quorum_standard" NUMERIC NOT NULL DEFAULT 2 CHECK ("quorum_standard" >= 0);
|
jbe@532
|
454 ALTER TABLE "area" ADD COLUMN "quorum_issues" NUMERIC NOT NULL DEFAULT 1 CHECK ("quorum_issues" > 0);
|
jbe@532
|
455 ALTER TABLE "area" ADD COLUMN "quorum_time" INTERVAL NOT NULL DEFAULT '1 day' CHECK ("quorum_time" > '0'::INTERVAL);
|
jbe@532
|
456 ALTER TABLE "area" ADD COLUMN "quorum_exponent" NUMERIC NOT NULL DEFAULT 0.5 CHECK ("quorum_exponent" BETWEEN 0 AND 1);
|
jbe@532
|
457 ALTER TABLE "area" ADD COLUMN "quorum_factor" NUMERIC NOT NULL DEFAULT 2 CHECK ("quorum_factor" >= 1);
|
jbe@532
|
458 ALTER TABLE "area" ADD COLUMN "quorum_den" INT4 CHECK ("quorum_den" > 0);
|
jbe@532
|
459 ALTER TABLE "area" ADD COLUMN "issue_quorum" INT4;
|
jbe@532
|
460 ALTER TABLE "area" ADD COLUMN "region" JSONB;
|
jbe@532
|
461
|
jbe@532
|
462 ALTER TABLE "area" DROP COLUMN "direct_member_count";
|
jbe@532
|
463 ALTER TABLE "area" DROP COLUMN "member_weight";
|
jbe@532
|
464
|
jbe@532
|
465 CREATE INDEX "area_region_idx" ON "area" USING gist ((GeoJSON_to_ecluster("region")));
|
jbe@532
|
466
|
jbe@532
|
467 COMMENT ON COLUMN "area"."quorum_standard" IS 'Parameter for dynamic issue quorum: default quorum';
|
jbe@532
|
468 COMMENT ON COLUMN "area"."quorum_issues" IS 'Parameter for dynamic issue quorum: number of open issues for default quorum';
|
jbe@532
|
469 COMMENT ON COLUMN "area"."quorum_time" IS 'Parameter for dynamic issue quorum: discussion, verification, and voting time of open issues to result in the given default quorum (open issues with shorter time will increase quorum and open issues with longer time will reduce quorum if "quorum_exponent" is greater than zero)';
|
jbe@532
|
470 COMMENT ON COLUMN "area"."quorum_exponent" IS 'Parameter for dynamic issue quorum: set to zero to ignore duration of open issues, set to one to fully take duration of open issues into account; defaults to 0.5';
|
jbe@532
|
471 COMMENT ON COLUMN "area"."quorum_factor" IS 'Parameter for dynamic issue quorum: factor to increase dynamic quorum when a number of "quorum_issues" issues with "quorum_time" duration of discussion, verification, and voting phase are added to the number of open admitted issues';
|
jbe@532
|
472 COMMENT ON COLUMN "area"."quorum_den" IS 'Parameter for dynamic issue quorum: when set, dynamic quorum is multiplied with "issue"."population" and divided by "quorum_den" (and then rounded up)';
|
jbe@532
|
473 COMMENT ON COLUMN "area"."issue_quorum" IS 'Additional dynamic issue quorum based on the number of open accepted issues; automatically calculated by function "issue_admission"';
|
jbe@532
|
474 COMMENT ON COLUMN "area"."external_reference" IS 'Opaque data field to store an external reference';
|
jbe@532
|
475 COMMENT ON COLUMN "area"."region" IS 'Scattered (or hollow) polygon represented as an array of polygons indicating valid coordinates for initiatives of issues with this policy';
|
jbe@532
|
476
|
jbe@532
|
477
|
jbe@532
|
478 CREATE TABLE "snapshot" (
|
jbe@532
|
479 UNIQUE ("issue_id", "id"), -- index needed for foreign-key on table "issue"
|
jbe@532
|
480 "id" SERIAL8 PRIMARY KEY,
|
jbe@532
|
481 "calculated" TIMESTAMPTZ NOT NULL DEFAULT now(),
|
jbe@532
|
482 "population" INT4,
|
jbe@532
|
483 "area_id" INT4 NOT NULL REFERENCES "area" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
484 "issue_id" INT4 ); -- NOTE: following (cyclic) reference is added later through ALTER command: REFERENCES "issue" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
jbe@532
|
485
|
jbe@532
|
486 COMMENT ON TABLE "snapshot" IS 'Point in time when a snapshot of one or more issues (see table "snapshot_issue") and their supporter situation is taken';
|
jbe@532
|
487
|
jbe@532
|
488
|
jbe@532
|
489 CREATE TABLE "snapshot_population" (
|
jbe@532
|
490 PRIMARY KEY ("snapshot_id", "member_id"),
|
jbe@532
|
491 "snapshot_id" INT8 REFERENCES "snapshot" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
492 "member_id" INT4 REFERENCES "member" ("id") ON DELETE RESTRICT ON UPDATE CASCADE );
|
jbe@532
|
493
|
jbe@532
|
494 COMMENT ON TABLE "snapshot_population" IS 'Members with voting right relevant for a snapshot';
|
jbe@532
|
495
|
jbe@532
|
496
|
jbe@532
|
497 ALTER TABLE "issue" ADD UNIQUE ("area_id", "id");
|
jbe@532
|
498 DROP INDEX "issue_area_id_idx";
|
jbe@536
|
499 ALTER TABLE "issue" ADD UNIQUE ("policy_id", "id");
|
jbe@536
|
500 DROP INDEX "issue_policy_id_idx";
|
jbe@532
|
501
|
jbe@532
|
502 ALTER TABLE "issue" RENAME COLUMN "snapshot" TO "calculated";
|
jbe@532
|
503
|
jbe@532
|
504 ALTER TABLE "issue" ADD COLUMN "latest_snapshot_id" INT8 REFERENCES "snapshot" ("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
jbe@532
|
505 ALTER TABLE "issue" ADD COLUMN "admission_snapshot_id" INT8 REFERENCES "snapshot" ("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
jbe@532
|
506 ALTER TABLE "issue" ADD COLUMN "half_freeze_snapshot_id" INT8;
|
jbe@532
|
507 ALTER TABLE "issue" ADD COLUMN "full_freeze_snapshot_id" INT8;
|
jbe@532
|
508
|
jbe@532
|
509 ALTER TABLE "issue" ADD FOREIGN KEY ("id", "half_freeze_snapshot_id")
|
jbe@532
|
510 REFERENCES "snapshot" ("issue_id", "id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
jbe@532
|
511 ALTER TABLE "issue" ADD FOREIGN KEY ("id", "full_freeze_snapshot_id")
|
jbe@532
|
512 REFERENCES "snapshot" ("issue_id", "id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
jbe@532
|
513
|
jbe@532
|
514 ALTER TABLE "issue" DROP CONSTRAINT "last_snapshot_on_full_freeze";
|
jbe@532
|
515 ALTER TABLE "issue" DROP CONSTRAINT "freeze_requires_snapshot";
|
jbe@532
|
516 ALTER TABLE "issue" DROP CONSTRAINT "set_both_or_none_of_snapshot_and_latest_snapshot_event";
|
jbe@532
|
517
|
jbe@532
|
518 CREATE INDEX "issue_state_idx" ON "issue" ("state");
|
jbe@532
|
519 CREATE INDEX "issue_latest_snapshot_id" ON "issue" ("latest_snapshot_id");
|
jbe@532
|
520 CREATE INDEX "issue_admission_snapshot_id" ON "issue" ("admission_snapshot_id");
|
jbe@532
|
521 CREATE INDEX "issue_half_freeze_snapshot_id" ON "issue" ("half_freeze_snapshot_id");
|
jbe@532
|
522 CREATE INDEX "issue_full_freeze_snapshot_id" ON "issue" ("full_freeze_snapshot_id");
|
jbe@532
|
523
|
jbe@532
|
524 COMMENT ON COLUMN "issue"."accepted" IS 'Point in time, when the issue was accepted for further discussion (see columns "issue_quorum_num" and "issue_quorum_den" of table "policy" and quorum columns of table "area")';
|
jbe@532
|
525 COMMENT ON COLUMN "issue"."calculated" IS 'Point in time, when most recent snapshot and "population" and *_count values were calculated (NOTE: value is equal to "snapshot"."calculated" of snapshot with "id"="issue"."latest_snapshot_id")';
|
jbe@532
|
526 COMMENT ON COLUMN "issue"."latest_snapshot_id" IS 'Snapshot id of most recent snapshot';
|
jbe@532
|
527 COMMENT ON COLUMN "issue"."admission_snapshot_id" IS 'Snapshot id when issue as accepted or canceled in admission phase';
|
jbe@532
|
528 COMMENT ON COLUMN "issue"."half_freeze_snapshot_id" IS 'Snapshot id at end of discussion phase';
|
jbe@532
|
529 COMMENT ON COLUMN "issue"."full_freeze_snapshot_id" IS 'Snapshot id at end of verification phase';
|
jbe@532
|
530 COMMENT ON COLUMN "issue"."population" IS 'Count of members in "snapshot_population" table with "snapshot_id" equal to "issue"."latest_snapshot_id"';
|
jbe@532
|
531
|
jbe@532
|
532
|
jbe@532
|
533 ALTER TABLE "snapshot" ADD FOREIGN KEY ("issue_id") REFERENCES "issue" ("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
jbe@532
|
534
|
jbe@532
|
535
|
jbe@532
|
536 ALTER TABLE "initiative" DROP CONSTRAINT "initiative_suggested_initiative_id_fkey";
|
jbe@532
|
537 ALTER TABLE "initiative" ADD FOREIGN KEY ("suggested_initiative_id") REFERENCES "initiative" ("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
jbe@532
|
538
|
jbe@532
|
539 ALTER TABLE "initiative" ADD COLUMN "location" JSONB;
|
jbe@532
|
540 ALTER TABLE "initiative" ADD COLUMN "draft_text_search_data" TSVECTOR;
|
jbe@532
|
541
|
jbe@532
|
542 CREATE INDEX "initiative_location_idx" ON "initiative" USING gist ((GeoJSON_to_ecluster("location")));
|
jbe@532
|
543 CREATE INDEX "initiative_draft_text_search_data_idx" ON "initiative" USING gin ("draft_text_search_data");
|
jbe@532
|
544
|
jbe@532
|
545 COMMENT ON COLUMN "initiative"."location" IS 'Geographic location of initiative as GeoJSON object (automatically copied from most recent draft)';
|
jbe@532
|
546
|
jbe@532
|
547
|
jbe@532
|
548 ALTER TABLE "draft" ADD COLUMN "location" JSONB;
|
jbe@532
|
549
|
jbe@532
|
550 CREATE INDEX "draft_location_idx" ON "draft" USING gist ((GeoJSON_to_ecluster("location")));
|
jbe@532
|
551
|
jbe@532
|
552 COMMENT ON COLUMN "draft"."location" IS 'Geographic location of initiative as GeoJSON object (automatically copied to "initiative" table if draft is most recent)';
|
jbe@532
|
553
|
jbe@532
|
554
|
jbe@532
|
555 ALTER TABLE "suggestion" ADD COLUMN "location" JSONB;
|
jbe@532
|
556
|
jbe@532
|
557 CREATE INDEX "suggestion_location_idx" ON "suggestion" USING gist ((GeoJSON_to_ecluster("location")));
|
jbe@532
|
558
|
jbe@532
|
559 COMMENT ON COLUMN "suggestion"."location" IS 'Geographic location of suggestion as GeoJSON object';
|
jbe@532
|
560
|
jbe@532
|
561
|
jbe@532
|
562 CREATE TABLE "temporary_suggestion_counts" (
|
jbe@532
|
563 "id" INT8 PRIMARY KEY, -- NOTE: no referential integrity due to performance/locking issues; REFERENCES "suggestion" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
564 "minus2_unfulfilled_count" INT4 NOT NULL,
|
jbe@532
|
565 "minus2_fulfilled_count" INT4 NOT NULL,
|
jbe@532
|
566 "minus1_unfulfilled_count" INT4 NOT NULL,
|
jbe@532
|
567 "minus1_fulfilled_count" INT4 NOT NULL,
|
jbe@532
|
568 "plus1_unfulfilled_count" INT4 NOT NULL,
|
jbe@532
|
569 "plus1_fulfilled_count" INT4 NOT NULL,
|
jbe@532
|
570 "plus2_unfulfilled_count" INT4 NOT NULL,
|
jbe@532
|
571 "plus2_fulfilled_count" INT4 NOT NULL );
|
jbe@532
|
572
|
jbe@532
|
573 COMMENT ON TABLE "temporary_suggestion_counts" IS 'Holds certain calculated values (suggestion counts) temporarily until they can be copied into table "suggestion"';
|
jbe@532
|
574
|
jbe@532
|
575 COMMENT ON COLUMN "temporary_suggestion_counts"."id" IS 'References "suggestion" ("id") but has no referential integrity trigger associated, due to performance/locking issues';
|
jbe@532
|
576
|
jbe@532
|
577
|
jbe@532
|
578 ALTER TABLE "interest" DROP CONSTRAINT "interest_member_id_fkey";
|
jbe@532
|
579 ALTER TABLE "interest" ADD FOREIGN KEY ("member_id") REFERENCES "member" ("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
jbe@532
|
580
|
jbe@532
|
581
|
jbe@532
|
582 ALTER TABLE "initiator" DROP CONSTRAINT "initiator_member_id_fkey";
|
jbe@532
|
583 ALTER TABLE "initiator" ADD FOREIGN KEY ("member_id") REFERENCES "member" ("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
jbe@532
|
584
|
jbe@532
|
585
|
jbe@532
|
586 ALTER TABLE "delegation" DROP CONSTRAINT "delegation_trustee_id_fkey";
|
jbe@532
|
587 ALTER TABLE "delegation" ADD FOREIGN KEY ("trustee_id") REFERENCES "member" ("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
jbe@532
|
588
|
jbe@532
|
589
|
jbe@532
|
590 CREATE TABLE "snapshot_issue" (
|
jbe@532
|
591 PRIMARY KEY ("snapshot_id", "issue_id"),
|
jbe@532
|
592 "snapshot_id" INT8 REFERENCES "snapshot" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
593 "issue_id" INT4 REFERENCES "issue" ("id") ON DELETE CASCADE ON UPDATE CASCADE );
|
jbe@532
|
594 CREATE INDEX "snapshot_issue_issue_id_idx" ON "snapshot_issue" ("issue_id");
|
jbe@532
|
595
|
jbe@532
|
596 COMMENT ON TABLE "snapshot_issue" IS 'List of issues included in a snapshot';
|
jbe@532
|
597
|
jbe@532
|
598 COMMENT ON COLUMN "snapshot_issue"."issue_id" IS 'Issue being part of the snapshot; Trigger "delete_snapshot_on_partial_delete" on "snapshot_issue" table will delete snapshot if an issue of the snapshot is deleted.';
|
jbe@532
|
599
|
jbe@532
|
600
|
jbe@532
|
601 ALTER TABLE "direct_interest_snapshot" RENAME TO "direct_interest_snapshot_old"; -- TODO!
|
jbe@532
|
602 ALTER INDEX "direct_interest_snapshot_pkey" RENAME TO "direct_interest_snapshot_old_pkey";
|
jbe@532
|
603 ALTER INDEX "direct_interest_snapshot_member_id_idx" RENAME TO "direct_interest_snapshot_old_member_id_idx";
|
jbe@532
|
604
|
jbe@532
|
605 ALTER TABLE "delegating_interest_snapshot" RENAME TO "delegating_interest_snapshot_old"; -- TODO!
|
jbe@532
|
606 ALTER INDEX "delegating_interest_snapshot_pkey" RENAME TO "delegating_interest_snapshot_old_pkey";
|
jbe@532
|
607 ALTER INDEX "delegating_interest_snapshot_member_id_idx" RENAME TO "delegating_interest_snapshot_old_member_id_idx";
|
jbe@532
|
608
|
jbe@532
|
609 ALTER TABLE "direct_supporter_snapshot" RENAME TO "direct_supporter_snapshot_old"; -- TODO!
|
jbe@532
|
610 ALTER INDEX "direct_supporter_snapshot_pkey" RENAME TO "direct_supporter_snapshot_old_pkey";
|
jbe@532
|
611 ALTER INDEX "direct_supporter_snapshot_member_id_idx" RENAME TO "direct_supporter_snapshot_old_member_id_idx";
|
jbe@532
|
612
|
jbe@532
|
613
|
jbe@532
|
614 CREATE TABLE "direct_interest_snapshot" (
|
jbe@532
|
615 PRIMARY KEY ("snapshot_id", "issue_id", "member_id"),
|
jbe@532
|
616 "snapshot_id" INT8,
|
jbe@532
|
617 "issue_id" INT4,
|
jbe@532
|
618 FOREIGN KEY ("snapshot_id", "issue_id")
|
jbe@532
|
619 REFERENCES "snapshot_issue" ("snapshot_id", "issue_id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
620 "member_id" INT4 REFERENCES "member" ("id") ON DELETE RESTRICT ON UPDATE RESTRICT,
|
jbe@532
|
621 "weight" INT4 );
|
jbe@532
|
622 CREATE INDEX "direct_interest_snapshot_member_id_idx" ON "direct_interest_snapshot" ("member_id");
|
jbe@532
|
623
|
jbe@532
|
624 COMMENT ON TABLE "direct_interest_snapshot" IS 'Snapshot of active members having an "interest" in the "issue"; for corrections refer to column "issue_notice" of "issue" table';
|
jbe@532
|
625
|
jbe@532
|
626 COMMENT ON COLUMN "direct_interest_snapshot"."weight" IS 'Weight of member (1 or higher) according to "delegating_interest_snapshot"';
|
jbe@532
|
627
|
jbe@532
|
628
|
jbe@532
|
629 CREATE TABLE "delegating_interest_snapshot" (
|
jbe@532
|
630 PRIMARY KEY ("snapshot_id", "issue_id", "member_id"),
|
jbe@532
|
631 "snapshot_id" INT8,
|
jbe@532
|
632 "issue_id" INT4,
|
jbe@532
|
633 FOREIGN KEY ("snapshot_id", "issue_id")
|
jbe@532
|
634 REFERENCES "snapshot_issue" ("snapshot_id", "issue_id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
635 "member_id" INT4 REFERENCES "member" ("id") ON DELETE RESTRICT ON UPDATE RESTRICT,
|
jbe@532
|
636 "weight" INT4,
|
jbe@532
|
637 "scope" "delegation_scope" NOT NULL,
|
jbe@532
|
638 "delegate_member_ids" INT4[] NOT NULL );
|
jbe@532
|
639 CREATE INDEX "delegating_interest_snapshot_member_id_idx" ON "delegating_interest_snapshot" ("member_id");
|
jbe@532
|
640
|
jbe@532
|
641 COMMENT ON TABLE "delegating_interest_snapshot" IS 'Delegations increasing the weight of entries in the "direct_interest_snapshot" table; for corrections refer to column "issue_notice" of "issue" table';
|
jbe@532
|
642
|
jbe@532
|
643 COMMENT ON COLUMN "delegating_interest_snapshot"."member_id" IS 'Delegating member';
|
jbe@532
|
644 COMMENT ON COLUMN "delegating_interest_snapshot"."weight" IS 'Intermediate weight';
|
jbe@532
|
645 COMMENT ON COLUMN "delegating_interest_snapshot"."delegate_member_ids" IS 'Chain of members who act as delegates; last entry referes to "member_id" column of table "direct_interest_snapshot"';
|
jbe@532
|
646
|
jbe@532
|
647
|
jbe@532
|
648 CREATE TABLE "direct_supporter_snapshot" (
|
jbe@532
|
649 PRIMARY KEY ("snapshot_id", "initiative_id", "member_id"),
|
jbe@532
|
650 "snapshot_id" INT8,
|
jbe@532
|
651 "issue_id" INT4 NOT NULL,
|
jbe@532
|
652 FOREIGN KEY ("snapshot_id", "issue_id")
|
jbe@532
|
653 REFERENCES "snapshot_issue" ("snapshot_id", "issue_id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
654 "initiative_id" INT4,
|
jbe@532
|
655 "member_id" INT4 REFERENCES "member" ("id") ON DELETE RESTRICT ON UPDATE RESTRICT,
|
jbe@532
|
656 "draft_id" INT8 NOT NULL,
|
jbe@532
|
657 "informed" BOOLEAN NOT NULL,
|
jbe@532
|
658 "satisfied" BOOLEAN NOT NULL,
|
jbe@532
|
659 FOREIGN KEY ("issue_id", "initiative_id") REFERENCES "initiative" ("issue_id", "id") ON DELETE CASCADE ON UPDATE CASCADE,
|
jbe@532
|
660 FOREIGN KEY ("initiative_id", "draft_id") REFERENCES "draft" ("initiative_id", "id") ON DELETE NO ACTION ON UPDATE CASCADE,
|
jbe@532
|
661 FOREIGN KEY ("snapshot_id", "issue_id", "member_id") REFERENCES "direct_interest_snapshot" ("snapshot_id", "issue_id", "member_id") ON DELETE CASCADE ON UPDATE CASCADE );
|
jbe@532
|
662 CREATE INDEX "direct_supporter_snapshot_member_id_idx" ON "direct_supporter_snapshot" ("member_id");
|
jbe@532
|
663
|
jbe@532
|
664 COMMENT ON TABLE "direct_supporter_snapshot" IS 'Snapshot of supporters of initiatives (weight is stored in "direct_interest_snapshot"); for corrections refer to column "issue_notice" of "issue" table';
|
jbe@532
|
665
|
jbe@532
|
666 COMMENT ON COLUMN "direct_supporter_snapshot"."issue_id" IS 'WARNING: No index: For selections use column "initiative_id" and join via table "initiative" where neccessary';
|
jbe@532
|
667 COMMENT ON COLUMN "direct_supporter_snapshot"."informed" IS 'Supporter has seen the latest draft of the initiative';
|
jbe@532
|
668 COMMENT ON COLUMN "direct_supporter_snapshot"."satisfied" IS 'Supporter has no "critical_opinion"s';
|
jbe@532
|
669
|
jbe@532
|
670
|
jbe@532
|
671 ALTER TABLE "non_voter" DROP CONSTRAINT "non_voter_pkey";
|
jbe@532
|
672 DROP INDEX "non_voter_member_id_idx";
|
jbe@532
|
673
|
jbe@532
|
674 ALTER TABLE "non_voter" ADD PRIMARY KEY ("member_id", "issue_id");
|
jbe@532
|
675 CREATE INDEX "non_voter_issue_id_idx" ON "non_voter" ("issue_id");
|
jbe@532
|
676
|
jbe@532
|
677
|
jbe@545
|
678 INSERT INTO "member_useterms" ("member_id", "accepted", "contract_identifier")
|
jbe@545
|
679 SELECT
|
jbe@545
|
680 "member_id",
|
jbe@545
|
681 regexp_replace("value", '^accepted at ', '')::TIMESTAMPTZ AS "accepted",
|
jbe@545
|
682 regexp_replace("key", '^use_terms_checkbox_', '') AS "contract_identifier"
|
jbe@545
|
683 FROM "setting" WHERE "key" LIKE 'use_terms_checkbox_%';
|
jbe@545
|
684
|
jbe@545
|
685
|
jbe@542
|
686 DROP TABLE "setting";
|
jbe@542
|
687 DROP TABLE "setting_map";
|
jbe@542
|
688 DROP TABLE "member_relation_setting";
|
jbe@542
|
689 DROP TABLE "unit_setting";
|
jbe@542
|
690 DROP TABLE "area_setting";
|
jbe@542
|
691 DROP TABLE "initiative_setting";
|
jbe@542
|
692 DROP TABLE "suggestion_setting";
|
jbe@542
|
693
|
jbe@542
|
694
|
jbe@532
|
695 ALTER TABLE "event" ADD COLUMN "other_member_id" INT4 REFERENCES "member" ("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
jbe@532
|
696 ALTER TABLE "event" ADD COLUMN "scope" "delegation_scope";
|
jbe@532
|
697 ALTER TABLE "event" ADD COLUMN "unit_id" INT4 REFERENCES "unit" ("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
jbe@532
|
698 ALTER TABLE "event" ADD COLUMN "area_id" INT4;
|
jbe@536
|
699 ALTER TABLE "event" ADD COLUMN "policy_id" INT4 REFERENCES "policy" ("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
jbe@532
|
700 ALTER TABLE "event" ADD COLUMN "boolean_value" BOOLEAN;
|
jbe@532
|
701 ALTER TABLE "event" ADD COLUMN "numeric_value" INT4;
|
jbe@532
|
702 ALTER TABLE "event" ADD COLUMN "text_value" TEXT;
|
jbe@532
|
703 ALTER TABLE "event" ADD COLUMN "old_text_value" TEXT;
|
jbe@532
|
704
|
jbe@532
|
705 ALTER TABLE "event" ADD FOREIGN KEY ("unit_id", "area_id") REFERENCES "area" ("unit_id", "id") ON DELETE CASCADE ON UPDATE CASCADE;
|
jbe@532
|
706 ALTER TABLE "event" ADD FOREIGN KEY ("area_id", "issue_id") REFERENCES "issue" ("area_id", "id") ON DELETE CASCADE ON UPDATE CASCADE;
|
jbe@536
|
707 ALTER TABLE "event" ADD FOREIGN KEY ("policy_id", "issue_id") REFERENCES "issue" ("policy_id", "id") ON DELETE CASCADE ON UPDATE CASCADE;
|
jbe@532
|
708
|
jbe@532
|
709 ALTER TABLE "event" DROP CONSTRAINT "event_initiative_id_fkey1";
|
jbe@532
|
710 ALTER TABLE "event" DROP CONSTRAINT "null_constr_for_issue_state_changed";
|
jbe@532
|
711 ALTER TABLE "event" DROP CONSTRAINT "null_constr_for_initiative_creation_or_revocation_or_new_draft";
|
jbe@532
|
712 ALTER TABLE "event" DROP CONSTRAINT "null_constr_for_suggestion_creation";
|
jbe@532
|
713
|
jbe@532
|
714 UPDATE "event" SET "unit_id" = "area"."unit_id", "area_id" = "issue"."area_id"
|
jbe@532
|
715 FROM "issue", "area"
|
jbe@532
|
716 WHERE "issue"."id" = "event"."issue_id" AND "area"."id" = "issue"."area_id";
|
jbe@532
|
717
|
jbe@532
|
718 ALTER TABLE "event" ADD CONSTRAINT "constr_for_issue_state_changed" CHECK (
|
jbe@532
|
719 "event" != 'issue_state_changed' OR (
|
jbe@532
|
720 "member_id" ISNULL AND
|
jbe@532
|
721 "other_member_id" ISNULL AND
|
jbe@532
|
722 "scope" ISNULL AND
|
jbe@532
|
723 "unit_id" NOTNULL AND
|
jbe@532
|
724 "area_id" NOTNULL AND
|
jbe@536
|
725 "policy_id" NOTNULL AND
|
jbe@532
|
726 "issue_id" NOTNULL AND
|
jbe@532
|
727 "state" NOTNULL AND
|
jbe@532
|
728 "initiative_id" ISNULL AND
|
jbe@532
|
729 "draft_id" ISNULL AND
|
jbe@532
|
730 "suggestion_id" ISNULL AND
|
jbe@532
|
731 "boolean_value" ISNULL AND
|
jbe@532
|
732 "numeric_value" ISNULL AND
|
jbe@532
|
733 "text_value" ISNULL AND
|
jbe@532
|
734 "old_text_value" ISNULL ));
|
jbe@532
|
735 ALTER TABLE "event" ADD CONSTRAINT "constr_for_initiative_creation_or_revocation_or_new_draft" CHECK (
|
jbe@532
|
736 "event" NOT IN (
|
jbe@532
|
737 'initiative_created_in_new_issue',
|
jbe@532
|
738 'initiative_created_in_existing_issue',
|
jbe@532
|
739 'initiative_revoked',
|
jbe@532
|
740 'new_draft_created'
|
jbe@532
|
741 ) OR (
|
jbe@532
|
742 "member_id" NOTNULL AND
|
jbe@532
|
743 "other_member_id" ISNULL AND
|
jbe@532
|
744 "scope" ISNULL AND
|
jbe@532
|
745 "unit_id" NOTNULL AND
|
jbe@532
|
746 "area_id" NOTNULL AND
|
jbe@536
|
747 "policy_id" NOTNULL AND
|
jbe@532
|
748 "issue_id" NOTNULL AND
|
jbe@532
|
749 "state" NOTNULL AND
|
jbe@532
|
750 "initiative_id" NOTNULL AND
|
jbe@532
|
751 "draft_id" NOTNULL AND
|
jbe@532
|
752 "suggestion_id" ISNULL AND
|
jbe@532
|
753 "boolean_value" ISNULL AND
|
jbe@532
|
754 "numeric_value" ISNULL AND
|
jbe@532
|
755 "text_value" ISNULL AND
|
jbe@532
|
756 "old_text_value" ISNULL ));
|
jbe@532
|
757 ALTER TABLE "event" ADD CONSTRAINT "constr_for_suggestion_creation" CHECK (
|
jbe@532
|
758 "event" != 'suggestion_created' OR (
|
jbe@532
|
759 "member_id" NOTNULL AND
|
jbe@532
|
760 "other_member_id" ISNULL AND
|
jbe@532
|
761 "scope" ISNULL AND
|
jbe@532
|
762 "unit_id" NOTNULL AND
|
jbe@532
|
763 "area_id" NOTNULL AND
|
jbe@536
|
764 "policy_id" NOTNULL AND
|
jbe@532
|
765 "issue_id" NOTNULL AND
|
jbe@532
|
766 "state" NOTNULL AND
|
jbe@532
|
767 "initiative_id" NOTNULL AND
|
jbe@532
|
768 "draft_id" ISNULL AND
|
jbe@532
|
769 "suggestion_id" NOTNULL AND
|
jbe@532
|
770 "boolean_value" ISNULL AND
|
jbe@532
|
771 "numeric_value" ISNULL AND
|
jbe@532
|
772 "text_value" ISNULL AND
|
jbe@532
|
773 "old_text_value" ISNULL ));
|
jbe@532
|
774 ALTER TABLE "event" ADD CONSTRAINT "constr_for_suggestion_removal" CHECK (
|
jbe@532
|
775 "event" != 'suggestion_removed' OR (
|
jbe@532
|
776 "member_id" ISNULL AND
|
jbe@532
|
777 "other_member_id" ISNULL AND
|
jbe@532
|
778 "scope" ISNULL AND
|
jbe@532
|
779 "unit_id" NOTNULL AND
|
jbe@532
|
780 "area_id" NOTNULL AND
|
jbe@536
|
781 "policy_id" NOTNULL AND
|
jbe@532
|
782 "issue_id" NOTNULL AND
|
jbe@532
|
783 "state" NOTNULL AND
|
jbe@532
|
784 "initiative_id" NOTNULL AND
|
jbe@532
|
785 "draft_id" ISNULL AND
|
jbe@532
|
786 "suggestion_id" NOTNULL AND
|
jbe@532
|
787 "boolean_value" ISNULL AND
|
jbe@532
|
788 "numeric_value" ISNULL AND
|
jbe@532
|
789 "text_value" ISNULL AND
|
jbe@532
|
790 "old_text_value" ISNULL ));
|
jbe@532
|
791 ALTER TABLE "event" ADD CONSTRAINT "constr_for_value_less_member_event" CHECK (
|
jbe@532
|
792 "event" NOT IN (
|
jbe@532
|
793 'member_activated',
|
jbe@532
|
794 'member_removed',
|
jbe@532
|
795 'member_profile_updated',
|
jbe@532
|
796 'member_image_updated'
|
jbe@532
|
797 ) OR (
|
jbe@532
|
798 "member_id" NOTNULL AND
|
jbe@532
|
799 "other_member_id" ISNULL AND
|
jbe@532
|
800 "scope" ISNULL AND
|
jbe@532
|
801 "unit_id" ISNULL AND
|
jbe@532
|
802 "area_id" ISNULL AND
|
jbe@536
|
803 "policy_id" ISNULL AND
|
jbe@532
|
804 "issue_id" ISNULL AND
|
jbe@532
|
805 "state" ISNULL AND
|
jbe@532
|
806 "initiative_id" ISNULL AND
|
jbe@532
|
807 "draft_id" ISNULL AND
|
jbe@532
|
808 "suggestion_id" ISNULL AND
|
jbe@532
|
809 "boolean_value" ISNULL AND
|
jbe@532
|
810 "numeric_value" ISNULL AND
|
jbe@532
|
811 "text_value" ISNULL AND
|
jbe@532
|
812 "old_text_value" ISNULL ));
|
jbe@532
|
813 ALTER TABLE "event" ADD CONSTRAINT "constr_for_member_active" CHECK (
|
jbe@532
|
814 "event" != 'member_active' OR (
|
jbe@532
|
815 "member_id" NOTNULL AND
|
jbe@532
|
816 "other_member_id" ISNULL AND
|
jbe@532
|
817 "scope" ISNULL AND
|
jbe@532
|
818 "unit_id" ISNULL AND
|
jbe@532
|
819 "area_id" ISNULL AND
|
jbe@536
|
820 "policy_id" ISNULL AND
|
jbe@532
|
821 "issue_id" ISNULL AND
|
jbe@532
|
822 "state" ISNULL AND
|
jbe@532
|
823 "initiative_id" ISNULL AND
|
jbe@532
|
824 "draft_id" ISNULL AND
|
jbe@532
|
825 "suggestion_id" ISNULL AND
|
jbe@532
|
826 "boolean_value" NOTNULL AND
|
jbe@532
|
827 "numeric_value" ISNULL AND
|
jbe@532
|
828 "text_value" ISNULL AND
|
jbe@532
|
829 "old_text_value" ISNULL ));
|
jbe@532
|
830 ALTER TABLE "event" ADD CONSTRAINT "constr_for_member_name_updated" CHECK (
|
jbe@532
|
831 "event" != 'member_name_updated' OR (
|
jbe@532
|
832 "member_id" NOTNULL AND
|
jbe@532
|
833 "other_member_id" ISNULL AND
|
jbe@532
|
834 "scope" ISNULL AND
|
jbe@532
|
835 "unit_id" ISNULL AND
|
jbe@532
|
836 "area_id" ISNULL AND
|
jbe@536
|
837 "policy_id" ISNULL AND
|
jbe@532
|
838 "issue_id" ISNULL AND
|
jbe@532
|
839 "state" ISNULL AND
|
jbe@532
|
840 "initiative_id" ISNULL AND
|
jbe@532
|
841 "draft_id" ISNULL AND
|
jbe@532
|
842 "suggestion_id" ISNULL AND
|
jbe@532
|
843 "boolean_value" ISNULL AND
|
jbe@532
|
844 "numeric_value" ISNULL AND
|
jbe@532
|
845 "text_value" NOTNULL AND
|
jbe@532
|
846 "old_text_value" NOTNULL ));
|
jbe@532
|
847 ALTER TABLE "event" ADD CONSTRAINT "constr_for_interest" CHECK (
|
jbe@532
|
848 "event" != 'interest' OR (
|
jbe@532
|
849 "member_id" NOTNULL AND
|
jbe@532
|
850 "other_member_id" ISNULL AND
|
jbe@532
|
851 "scope" ISNULL AND
|
jbe@532
|
852 "unit_id" NOTNULL AND
|
jbe@532
|
853 "area_id" NOTNULL AND
|
jbe@536
|
854 "policy_id" NOTNULL AND
|
jbe@532
|
855 "issue_id" NOTNULL AND
|
jbe@532
|
856 "state" NOTNULL AND
|
jbe@532
|
857 "initiative_id" ISNULL AND
|
jbe@532
|
858 "draft_id" ISNULL AND
|
jbe@532
|
859 "suggestion_id" ISNULL AND
|
jbe@532
|
860 "boolean_value" NOTNULL AND
|
jbe@532
|
861 "numeric_value" ISNULL AND
|
jbe@532
|
862 "text_value" ISNULL AND
|
jbe@532
|
863 "old_text_value" ISNULL ));
|
jbe@532
|
864 ALTER TABLE "event" ADD CONSTRAINT "constr_for_initiator" CHECK (
|
jbe@532
|
865 "event" != 'initiator' OR (
|
jbe@532
|
866 "member_id" NOTNULL AND
|
jbe@532
|
867 "other_member_id" ISNULL AND
|
jbe@532
|
868 "scope" ISNULL AND
|
jbe@532
|
869 "unit_id" NOTNULL AND
|
jbe@532
|
870 "area_id" NOTNULL AND
|
jbe@536
|
871 "policy_id" NOTNULL AND
|
jbe@532
|
872 "issue_id" NOTNULL AND
|
jbe@532
|
873 "state" NOTNULL AND
|
jbe@532
|
874 "initiative_id" NOTNULL AND
|
jbe@532
|
875 "draft_id" ISNULL AND
|
jbe@532
|
876 "suggestion_id" ISNULL AND
|
jbe@532
|
877 "boolean_value" NOTNULL AND
|
jbe@532
|
878 "numeric_value" ISNULL AND
|
jbe@532
|
879 "text_value" ISNULL AND
|
jbe@532
|
880 "old_text_value" ISNULL ));
|
jbe@532
|
881 ALTER TABLE "event" ADD CONSTRAINT "constr_for_support" CHECK (
|
jbe@532
|
882 "event" != 'support' OR (
|
jbe@532
|
883 "member_id" NOTNULL AND
|
jbe@532
|
884 "other_member_id" ISNULL AND
|
jbe@532
|
885 "scope" ISNULL AND
|
jbe@532
|
886 "unit_id" NOTNULL AND
|
jbe@532
|
887 "area_id" NOTNULL AND
|
jbe@536
|
888 "policy_id" NOTNULL AND
|
jbe@532
|
889 "issue_id" NOTNULL AND
|
jbe@532
|
890 "state" NOTNULL AND
|
jbe@532
|
891 "initiative_id" NOTNULL AND
|
jbe@532
|
892 ("draft_id" NOTNULL) = ("boolean_value" = TRUE) AND
|
jbe@532
|
893 "suggestion_id" ISNULL AND
|
jbe@532
|
894 "boolean_value" NOTNULL AND
|
jbe@532
|
895 "numeric_value" ISNULL AND
|
jbe@532
|
896 "text_value" ISNULL AND
|
jbe@532
|
897 "old_text_value" ISNULL ));
|
jbe@532
|
898 ALTER TABLE "event" ADD CONSTRAINT "constr_for_support_updated" CHECK (
|
jbe@532
|
899 "event" != 'support_updated' OR (
|
jbe@532
|
900 "member_id" NOTNULL AND
|
jbe@532
|
901 "other_member_id" ISNULL AND
|
jbe@532
|
902 "scope" ISNULL AND
|
jbe@532
|
903 "unit_id" NOTNULL AND
|
jbe@532
|
904 "area_id" NOTNULL AND
|
jbe@536
|
905 "policy_id" NOTNULL AND
|
jbe@532
|
906 "issue_id" NOTNULL AND
|
jbe@532
|
907 "state" NOTNULL AND
|
jbe@532
|
908 "initiative_id" NOTNULL AND
|
jbe@532
|
909 "draft_id" NOTNULL AND
|
jbe@532
|
910 "suggestion_id" ISNULL AND
|
jbe@532
|
911 "boolean_value" ISNULL AND
|
jbe@532
|
912 "numeric_value" ISNULL AND
|
jbe@532
|
913 "text_value" ISNULL AND
|
jbe@532
|
914 "old_text_value" ISNULL ));
|
jbe@532
|
915 ALTER TABLE "event" ADD CONSTRAINT "constr_for_suggestion_rated" CHECK (
|
jbe@532
|
916 "event" != 'suggestion_rated' OR (
|
jbe@532
|
917 "member_id" NOTNULL AND
|
jbe@532
|
918 "other_member_id" ISNULL AND
|
jbe@532
|
919 "scope" ISNULL AND
|
jbe@532
|
920 "unit_id" NOTNULL AND
|
jbe@532
|
921 "area_id" NOTNULL AND
|
jbe@536
|
922 "policy_id" NOTNULL AND
|
jbe@532
|
923 "issue_id" NOTNULL AND
|
jbe@532
|
924 "state" NOTNULL AND
|
jbe@532
|
925 "initiative_id" NOTNULL AND
|
jbe@532
|
926 "draft_id" ISNULL AND
|
jbe@532
|
927 "suggestion_id" NOTNULL AND
|
jbe@532
|
928 ("boolean_value" NOTNULL) = ("numeric_value" != 0) AND
|
jbe@532
|
929 "numeric_value" NOTNULL AND
|
jbe@532
|
930 "numeric_value" IN (-2, -1, 0, 1, 2) AND
|
jbe@532
|
931 "text_value" ISNULL AND
|
jbe@532
|
932 "old_text_value" ISNULL ));
|
jbe@532
|
933 ALTER TABLE "event" ADD CONSTRAINT "constr_for_delegation" CHECK (
|
jbe@532
|
934 "event" != 'delegation' OR (
|
jbe@532
|
935 "member_id" NOTNULL AND
|
jbe@532
|
936 ("other_member_id" NOTNULL) OR ("boolean_value" = FALSE) AND
|
jbe@532
|
937 "scope" NOTNULL AND
|
jbe@532
|
938 "unit_id" NOTNULL AND
|
jbe@532
|
939 ("area_id" NOTNULL) = ("scope" != 'unit'::"delegation_scope") AND
|
jbe@536
|
940 "policy_id" ISNULL AND
|
jbe@532
|
941 ("issue_id" NOTNULL) = ("scope" = 'issue'::"delegation_scope") AND
|
jbe@532
|
942 ("state" NOTNULL) = ("scope" = 'issue'::"delegation_scope") AND
|
jbe@532
|
943 "initiative_id" ISNULL AND
|
jbe@532
|
944 "draft_id" ISNULL AND
|
jbe@532
|
945 "suggestion_id" ISNULL AND
|
jbe@532
|
946 "boolean_value" NOTNULL AND
|
jbe@532
|
947 "numeric_value" ISNULL AND
|
jbe@532
|
948 "text_value" ISNULL AND
|
jbe@532
|
949 "old_text_value" ISNULL ));
|
jbe@532
|
950 ALTER TABLE "event" ADD CONSTRAINT "constr_for_contact" CHECK (
|
jbe@532
|
951 "event" != 'contact' OR (
|
jbe@532
|
952 "member_id" NOTNULL AND
|
jbe@532
|
953 "other_member_id" NOTNULL AND
|
jbe@532
|
954 "scope" ISNULL AND
|
jbe@532
|
955 "unit_id" ISNULL AND
|
jbe@532
|
956 "area_id" ISNULL AND
|
jbe@536
|
957 "policy_id" ISNULL AND
|
jbe@532
|
958 "issue_id" ISNULL AND
|
jbe@532
|
959 "state" ISNULL AND
|
jbe@532
|
960 "initiative_id" ISNULL AND
|
jbe@532
|
961 "draft_id" ISNULL AND
|
jbe@532
|
962 "suggestion_id" ISNULL AND
|
jbe@532
|
963 "boolean_value" NOTNULL AND
|
jbe@532
|
964 "numeric_value" ISNULL AND
|
jbe@532
|
965 "text_value" ISNULL AND
|
jbe@532
|
966 "old_text_value" ISNULL ));
|
jbe@532
|
967
|
jbe@532
|
968
|
jbe@534
|
969 ALTER TABLE "notification_event_sent" RENAME TO "event_processed";
|
jbe@534
|
970 ALTER INDEX "notification_event_sent_singleton_idx" RENAME TO "event_processed_singleton_idx";
|
jbe@534
|
971
|
jbe@534
|
972 COMMENT ON TABLE "event_processed" IS 'This table stores one row with the last event_id, for which event handlers have been executed (e.g. notifications having been sent out)';
|
jbe@534
|
973 COMMENT ON INDEX "event_processed_singleton_idx" IS 'This index ensures that "event_processed" only contains one row maximum.';
|
jbe@534
|
974
|
jbe@534
|
975
|
jbe@537
|
976 CREATE FUNCTION "write_event_unit_trigger"()
|
jbe@537
|
977 RETURNS TRIGGER
|
jbe@537
|
978 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@538
|
979 DECLARE
|
jbe@538
|
980 "event_v" "event_type";
|
jbe@537
|
981 BEGIN
|
jbe@538
|
982 IF TG_OP = 'UPDATE' THEN
|
jbe@538
|
983 IF OLD."active" = FALSE AND NEW."active" = FALSE THEN
|
jbe@538
|
984 RETURN NULL;
|
jbe@547
|
985 --ELSIF OLD."active" = FALSE AND NEW."active" = TRUE THEN
|
jbe@547
|
986 -- "event_v" := 'unit_created';
|
jbe@547
|
987 --ELSIF OLD."active" = TRUE AND NEW."active" = FALSE THEN
|
jbe@547
|
988 -- "event_v" := 'unit_removed';
|
jbe@546
|
989 ELSIF OLD != NEW THEN
|
jbe@546
|
990 "event_v" := 'unit_updated';
|
jbe@538
|
991 ELSE
|
jbe@546
|
992 RETURN NULL;
|
jbe@538
|
993 END IF;
|
jbe@538
|
994 ELSE
|
jbe@538
|
995 "event_v" := 'unit_created';
|
jbe@538
|
996 END IF;
|
jbe@538
|
997 INSERT INTO "event" ("event", "unit_id") VALUES ("event_v", NEW."id");
|
jbe@537
|
998 RETURN NULL;
|
jbe@537
|
999 END;
|
jbe@537
|
1000 $$;
|
jbe@537
|
1001
|
jbe@537
|
1002 CREATE TRIGGER "write_event_unit" AFTER INSERT OR UPDATE ON "unit"
|
jbe@537
|
1003 FOR EACH ROW EXECUTE PROCEDURE "write_event_unit_trigger"();
|
jbe@537
|
1004
|
jbe@537
|
1005 COMMENT ON FUNCTION "write_event_unit_trigger"() IS 'Implementation of trigger "write_event_unit" on table "unit"';
|
jbe@537
|
1006 COMMENT ON TRIGGER "write_event_unit" ON "unit" IS 'Create entry in "event" table on new or changed/disabled units';
|
jbe@537
|
1007
|
jbe@537
|
1008
|
jbe@537
|
1009 CREATE FUNCTION "write_event_area_trigger"()
|
jbe@537
|
1010 RETURNS TRIGGER
|
jbe@537
|
1011 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@538
|
1012 DECLARE
|
jbe@538
|
1013 "event_v" "event_type";
|
jbe@537
|
1014 BEGIN
|
jbe@538
|
1015 IF TG_OP = 'UPDATE' THEN
|
jbe@538
|
1016 IF OLD."active" = FALSE AND NEW."active" = FALSE THEN
|
jbe@538
|
1017 RETURN NULL;
|
jbe@547
|
1018 --ELSIF OLD."active" = FALSE AND NEW."active" = TRUE THEN
|
jbe@547
|
1019 -- "event_v" := 'area_created';
|
jbe@547
|
1020 --ELSIF OLD."active" = TRUE AND NEW."active" = FALSE THEN
|
jbe@547
|
1021 -- "event_v" := 'area_removed';
|
jbe@546
|
1022 ELSIF OLD != NEW THEN
|
jbe@546
|
1023 "event_v" := 'area_updated';
|
jbe@538
|
1024 ELSE
|
jbe@546
|
1025 RETURN NULL;
|
jbe@538
|
1026 END IF;
|
jbe@538
|
1027 ELSE
|
jbe@538
|
1028 "event_v" := 'area_created';
|
jbe@538
|
1029 END IF;
|
jbe@538
|
1030 INSERT INTO "event" ("event", "area_id") VALUES ("event_v", NEW."id");
|
jbe@537
|
1031 RETURN NULL;
|
jbe@537
|
1032 END;
|
jbe@537
|
1033 $$;
|
jbe@537
|
1034
|
jbe@537
|
1035 CREATE TRIGGER "write_event_area" AFTER INSERT OR UPDATE ON "area"
|
jbe@537
|
1036 FOR EACH ROW EXECUTE PROCEDURE "write_event_area_trigger"();
|
jbe@537
|
1037
|
jbe@537
|
1038 COMMENT ON FUNCTION "write_event_area_trigger"() IS 'Implementation of trigger "write_event_area" on table "area"';
|
jbe@537
|
1039 COMMENT ON TRIGGER "write_event_area" ON "area" IS 'Create entry in "event" table on new or changed/disabled areas';
|
jbe@537
|
1040
|
jbe@537
|
1041
|
jbe@537
|
1042 CREATE FUNCTION "write_event_policy_trigger"()
|
jbe@537
|
1043 RETURNS TRIGGER
|
jbe@537
|
1044 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@538
|
1045 DECLARE
|
jbe@538
|
1046 "event_v" "event_type";
|
jbe@537
|
1047 BEGIN
|
jbe@538
|
1048 IF TG_OP = 'UPDATE' THEN
|
jbe@538
|
1049 IF OLD."active" = FALSE AND NEW."active" = FALSE THEN
|
jbe@538
|
1050 RETURN NULL;
|
jbe@547
|
1051 --ELSIF OLD."active" = FALSE AND NEW."active" = TRUE THEN
|
jbe@547
|
1052 -- "event_v" := 'policy_created';
|
jbe@547
|
1053 --ELSIF OLD."active" = TRUE AND NEW."active" = FALSE THEN
|
jbe@547
|
1054 -- "event_v" := 'policy_removed';
|
jbe@546
|
1055 ELSIF OLD != NEW THEN
|
jbe@546
|
1056 "event_v" := 'policy_updated';
|
jbe@538
|
1057 ELSE
|
jbe@546
|
1058 RETURN NULL;
|
jbe@538
|
1059 END IF;
|
jbe@538
|
1060 ELSE
|
jbe@538
|
1061 "event_v" := 'policy_created';
|
jbe@538
|
1062 END IF;
|
jbe@538
|
1063 INSERT INTO "event" ("event", "policy_id") VALUES ("event_v", NEW."id");
|
jbe@537
|
1064 RETURN NULL;
|
jbe@537
|
1065 END;
|
jbe@537
|
1066 $$;
|
jbe@537
|
1067
|
jbe@537
|
1068 CREATE TRIGGER "write_event_policy" AFTER INSERT OR UPDATE ON "policy"
|
jbe@537
|
1069 FOR EACH ROW EXECUTE PROCEDURE "write_event_policy_trigger"();
|
jbe@537
|
1070
|
jbe@537
|
1071 COMMENT ON FUNCTION "write_event_policy_trigger"() IS 'Implementation of trigger "write_event_policy" on table "policy"';
|
jbe@537
|
1072 COMMENT ON TRIGGER "write_event_policy" ON "policy" IS 'Create entry in "event" table on new or changed/disabled policies';
|
jbe@537
|
1073
|
jbe@537
|
1074
|
jbe@532
|
1075 CREATE OR REPLACE FUNCTION "write_event_issue_state_changed_trigger"()
|
jbe@532
|
1076 RETURNS TRIGGER
|
jbe@532
|
1077 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1078 DECLARE
|
jbe@532
|
1079 "area_row" "area"%ROWTYPE;
|
jbe@532
|
1080 BEGIN
|
jbe@532
|
1081 IF NEW."state" != OLD."state" THEN
|
jbe@532
|
1082 SELECT * INTO "area_row" FROM "area" WHERE "id" = NEW."area_id"
|
jbe@532
|
1083 FOR SHARE;
|
jbe@532
|
1084 INSERT INTO "event" (
|
jbe@532
|
1085 "event",
|
jbe@536
|
1086 "unit_id", "area_id", "policy_id", "issue_id", "state"
|
jbe@532
|
1087 ) VALUES (
|
jbe@532
|
1088 'issue_state_changed',
|
jbe@536
|
1089 "area_row"."unit_id", NEW."area_id", NEW."policy_id",
|
jbe@536
|
1090 NEW."id", NEW."state"
|
jbe@532
|
1091 );
|
jbe@532
|
1092 END IF;
|
jbe@532
|
1093 RETURN NULL;
|
jbe@532
|
1094 END;
|
jbe@532
|
1095 $$;
|
jbe@532
|
1096
|
jbe@532
|
1097
|
jbe@532
|
1098 CREATE OR REPLACE FUNCTION "write_event_initiative_or_draft_created_trigger"()
|
jbe@532
|
1099 RETURNS TRIGGER
|
jbe@532
|
1100 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1101 DECLARE
|
jbe@532
|
1102 "initiative_row" "initiative"%ROWTYPE;
|
jbe@532
|
1103 "issue_row" "issue"%ROWTYPE;
|
jbe@532
|
1104 "area_row" "area"%ROWTYPE;
|
jbe@532
|
1105 "event_v" "event_type";
|
jbe@532
|
1106 BEGIN
|
jbe@532
|
1107 SELECT * INTO "initiative_row" FROM "initiative"
|
jbe@532
|
1108 WHERE "id" = NEW."initiative_id" FOR SHARE;
|
jbe@532
|
1109 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1110 WHERE "id" = "initiative_row"."issue_id" FOR SHARE;
|
jbe@532
|
1111 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1112 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1113 IF EXISTS (
|
jbe@532
|
1114 SELECT NULL FROM "draft"
|
jbe@532
|
1115 WHERE "initiative_id" = NEW."initiative_id" AND "id" != NEW."id"
|
jbe@532
|
1116 FOR SHARE
|
jbe@532
|
1117 ) THEN
|
jbe@532
|
1118 "event_v" := 'new_draft_created';
|
jbe@532
|
1119 ELSE
|
jbe@532
|
1120 IF EXISTS (
|
jbe@532
|
1121 SELECT NULL FROM "initiative"
|
jbe@532
|
1122 WHERE "issue_id" = "initiative_row"."issue_id"
|
jbe@532
|
1123 AND "id" != "initiative_row"."id"
|
jbe@532
|
1124 FOR SHARE
|
jbe@532
|
1125 ) THEN
|
jbe@532
|
1126 "event_v" := 'initiative_created_in_existing_issue';
|
jbe@532
|
1127 ELSE
|
jbe@532
|
1128 "event_v" := 'initiative_created_in_new_issue';
|
jbe@532
|
1129 END IF;
|
jbe@532
|
1130 END IF;
|
jbe@532
|
1131 INSERT INTO "event" (
|
jbe@532
|
1132 "event", "member_id",
|
jbe@536
|
1133 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@532
|
1134 "initiative_id", "draft_id"
|
jbe@532
|
1135 ) VALUES (
|
jbe@532
|
1136 "event_v", NEW."author_id",
|
jbe@536
|
1137 "area_row"."unit_id", "issue_row"."area_id", "issue_row"."policy_id",
|
jbe@532
|
1138 "initiative_row"."issue_id", "issue_row"."state",
|
jbe@532
|
1139 NEW."initiative_id", NEW."id"
|
jbe@532
|
1140 );
|
jbe@532
|
1141 RETURN NULL;
|
jbe@532
|
1142 END;
|
jbe@532
|
1143 $$;
|
jbe@532
|
1144
|
jbe@532
|
1145
|
jbe@532
|
1146 CREATE OR REPLACE FUNCTION "write_event_initiative_revoked_trigger"()
|
jbe@532
|
1147 RETURNS TRIGGER
|
jbe@532
|
1148 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1149 DECLARE
|
jbe@532
|
1150 "issue_row" "issue"%ROWTYPE;
|
jbe@532
|
1151 "area_row" "area"%ROWTYPE;
|
jbe@532
|
1152 "draft_id_v" "draft"."id"%TYPE;
|
jbe@532
|
1153 BEGIN
|
jbe@532
|
1154 IF OLD."revoked" ISNULL AND NEW."revoked" NOTNULL THEN
|
jbe@532
|
1155 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1156 WHERE "id" = NEW."issue_id" FOR SHARE;
|
jbe@532
|
1157 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1158 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1159 SELECT "id" INTO "draft_id_v" FROM "current_draft"
|
jbe@532
|
1160 WHERE "initiative_id" = NEW."id" FOR SHARE;
|
jbe@532
|
1161 INSERT INTO "event" (
|
jbe@532
|
1162 "event", "member_id",
|
jbe@536
|
1163 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@532
|
1164 "initiative_id", "draft_id"
|
jbe@532
|
1165 ) VALUES (
|
jbe@532
|
1166 'initiative_revoked', NEW."revoked_by_member_id",
|
jbe@532
|
1167 "area_row"."unit_id", "issue_row"."area_id",
|
jbe@536
|
1168 "issue_row"."policy_id",
|
jbe@532
|
1169 NEW."issue_id", "issue_row"."state",
|
jbe@532
|
1170 NEW."id", "draft_id_v"
|
jbe@532
|
1171 );
|
jbe@532
|
1172 END IF;
|
jbe@532
|
1173 RETURN NULL;
|
jbe@532
|
1174 END;
|
jbe@532
|
1175 $$;
|
jbe@532
|
1176
|
jbe@532
|
1177
|
jbe@532
|
1178 CREATE OR REPLACE FUNCTION "write_event_suggestion_created_trigger"()
|
jbe@532
|
1179 RETURNS TRIGGER
|
jbe@532
|
1180 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1181 DECLARE
|
jbe@532
|
1182 "initiative_row" "initiative"%ROWTYPE;
|
jbe@532
|
1183 "issue_row" "issue"%ROWTYPE;
|
jbe@532
|
1184 "area_row" "area"%ROWTYPE;
|
jbe@532
|
1185 BEGIN
|
jbe@532
|
1186 SELECT * INTO "initiative_row" FROM "initiative"
|
jbe@532
|
1187 WHERE "id" = NEW."initiative_id" FOR SHARE;
|
jbe@532
|
1188 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1189 WHERE "id" = "initiative_row"."issue_id" FOR SHARE;
|
jbe@532
|
1190 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1191 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1192 INSERT INTO "event" (
|
jbe@532
|
1193 "event", "member_id",
|
jbe@536
|
1194 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@532
|
1195 "initiative_id", "suggestion_id"
|
jbe@532
|
1196 ) VALUES (
|
jbe@532
|
1197 'suggestion_created', NEW."author_id",
|
jbe@536
|
1198 "area_row"."unit_id", "issue_row"."area_id", "issue_row"."policy_id",
|
jbe@532
|
1199 "initiative_row"."issue_id", "issue_row"."state",
|
jbe@532
|
1200 NEW."initiative_id", NEW."id"
|
jbe@532
|
1201 );
|
jbe@532
|
1202 RETURN NULL;
|
jbe@532
|
1203 END;
|
jbe@532
|
1204 $$;
|
jbe@532
|
1205
|
jbe@532
|
1206
|
jbe@532
|
1207 CREATE FUNCTION "write_event_suggestion_removed_trigger"()
|
jbe@532
|
1208 RETURNS TRIGGER
|
jbe@532
|
1209 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1210 DECLARE
|
jbe@532
|
1211 "initiative_row" "initiative"%ROWTYPE;
|
jbe@532
|
1212 "issue_row" "issue"%ROWTYPE;
|
jbe@532
|
1213 "area_row" "area"%ROWTYPE;
|
jbe@532
|
1214 BEGIN
|
jbe@532
|
1215 SELECT * INTO "initiative_row" FROM "initiative"
|
jbe@532
|
1216 WHERE "id" = OLD."initiative_id" FOR SHARE;
|
jbe@532
|
1217 IF "initiative_row"."id" NOTNULL THEN
|
jbe@532
|
1218 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1219 WHERE "id" = "initiative_row"."issue_id" FOR SHARE;
|
jbe@532
|
1220 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1221 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1222 INSERT INTO "event" (
|
jbe@532
|
1223 "event",
|
jbe@536
|
1224 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@532
|
1225 "initiative_id", "suggestion_id"
|
jbe@532
|
1226 ) VALUES (
|
jbe@532
|
1227 'suggestion_removed',
|
jbe@532
|
1228 "area_row"."unit_id", "issue_row"."area_id",
|
jbe@536
|
1229 "issue_row"."policy_id",
|
jbe@532
|
1230 "initiative_row"."issue_id", "issue_row"."state",
|
jbe@532
|
1231 OLD."initiative_id", OLD."id"
|
jbe@532
|
1232 );
|
jbe@532
|
1233 END IF;
|
jbe@532
|
1234 RETURN NULL;
|
jbe@532
|
1235 END;
|
jbe@532
|
1236 $$;
|
jbe@532
|
1237
|
jbe@532
|
1238 CREATE TRIGGER "write_event_suggestion_removed"
|
jbe@532
|
1239 AFTER DELETE ON "suggestion" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1240 "write_event_suggestion_removed_trigger"();
|
jbe@532
|
1241
|
jbe@532
|
1242 COMMENT ON FUNCTION "write_event_suggestion_removed_trigger"() IS 'Implementation of trigger "write_event_suggestion_removed" on table "issue"';
|
jbe@532
|
1243 COMMENT ON TRIGGER "write_event_suggestion_removed" ON "suggestion" IS 'Create entry in "event" table on suggestion creation';
|
jbe@532
|
1244
|
jbe@532
|
1245
|
jbe@532
|
1246 CREATE FUNCTION "write_event_member_trigger"()
|
jbe@532
|
1247 RETURNS TRIGGER
|
jbe@532
|
1248 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1249 BEGIN
|
jbe@532
|
1250 IF TG_OP = 'INSERT' THEN
|
jbe@532
|
1251 IF NEW."activated" NOTNULL THEN
|
jbe@532
|
1252 INSERT INTO "event" ("event", "member_id")
|
jbe@532
|
1253 VALUES ('member_activated', NEW."id");
|
jbe@532
|
1254 END IF;
|
jbe@532
|
1255 IF NEW."active" THEN
|
jbe@532
|
1256 INSERT INTO "event" ("event", "member_id", "boolean_value")
|
jbe@532
|
1257 VALUES ('member_active', NEW."id", TRUE);
|
jbe@532
|
1258 END IF;
|
jbe@532
|
1259 ELSIF TG_OP = 'UPDATE' THEN
|
jbe@532
|
1260 IF OLD."id" != NEW."id" THEN
|
jbe@532
|
1261 RAISE EXCEPTION 'Cannot change member ID';
|
jbe@532
|
1262 END IF;
|
jbe@532
|
1263 IF OLD."name" != NEW."name" THEN
|
jbe@532
|
1264 INSERT INTO "event" (
|
jbe@532
|
1265 "event", "member_id", "text_value", "old_text_value"
|
jbe@532
|
1266 ) VALUES (
|
jbe@532
|
1267 'member_name_updated', NEW."id", NEW."name", OLD."name"
|
jbe@532
|
1268 );
|
jbe@532
|
1269 END IF;
|
jbe@532
|
1270 IF OLD."active" != NEW."active" THEN
|
jbe@532
|
1271 INSERT INTO "event" ("event", "member_id", "boolean_value") VALUES (
|
jbe@532
|
1272 'member_active', NEW."id", NEW."active"
|
jbe@532
|
1273 );
|
jbe@532
|
1274 END IF;
|
jbe@532
|
1275 IF
|
jbe@532
|
1276 OLD."activated" NOTNULL AND
|
jbe@540
|
1277 (OLD."login" NOTNULL OR OLD."authority_login" NOTNULL) AND
|
jbe@532
|
1278 NEW."login" ISNULL AND
|
jbe@532
|
1279 NEW."authority_login" ISNULL AND
|
jbe@532
|
1280 NEW."locked" = TRUE
|
jbe@532
|
1281 THEN
|
jbe@532
|
1282 INSERT INTO "event" ("event", "member_id")
|
jbe@532
|
1283 VALUES ('member_removed', NEW."id");
|
jbe@532
|
1284 END IF;
|
jbe@532
|
1285 END IF;
|
jbe@532
|
1286 RETURN NULL;
|
jbe@532
|
1287 END;
|
jbe@532
|
1288 $$;
|
jbe@532
|
1289
|
jbe@532
|
1290 CREATE TRIGGER "write_event_member"
|
jbe@532
|
1291 AFTER INSERT OR UPDATE ON "member" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1292 "write_event_member_trigger"();
|
jbe@532
|
1293
|
jbe@532
|
1294 COMMENT ON FUNCTION "write_event_member_trigger"() IS 'Implementation of trigger "write_event_member" on table "member"';
|
jbe@532
|
1295 COMMENT ON TRIGGER "write_event_member" ON "member" IS 'Create entries in "event" table on insertion to member table';
|
jbe@532
|
1296
|
jbe@532
|
1297
|
jbe@532
|
1298 CREATE FUNCTION "write_event_member_profile_updated_trigger"()
|
jbe@532
|
1299 RETURNS TRIGGER
|
jbe@532
|
1300 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1301 BEGIN
|
jbe@532
|
1302 IF TG_OP = 'DELETE' OR TG_OP = 'UPDATE' THEN
|
jbe@532
|
1303 IF EXISTS (SELECT NULL FROM "member" WHERE "id" = OLD."member_id") THEN
|
jbe@532
|
1304 INSERT INTO "event" ("event", "member_id") VALUES (
|
jbe@532
|
1305 'member_profile_updated', OLD."member_id"
|
jbe@532
|
1306 );
|
jbe@532
|
1307 END IF;
|
jbe@532
|
1308 END IF;
|
jbe@532
|
1309 IF TG_OP = 'UPDATE' THEN
|
jbe@532
|
1310 IF OLD."member_id" = NEW."member_id" THEN
|
jbe@532
|
1311 RETURN NULL;
|
jbe@532
|
1312 END IF;
|
jbe@532
|
1313 END IF;
|
jbe@532
|
1314 IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
|
jbe@532
|
1315 INSERT INTO "event" ("event", "member_id") VALUES (
|
jbe@532
|
1316 'member_profile_updated', NEW."member_id"
|
jbe@532
|
1317 );
|
jbe@532
|
1318 END IF;
|
jbe@532
|
1319 RETURN NULL;
|
jbe@532
|
1320 END;
|
jbe@532
|
1321 $$;
|
jbe@532
|
1322
|
jbe@532
|
1323 CREATE TRIGGER "write_event_member_profile_updated"
|
jbe@532
|
1324 AFTER INSERT OR UPDATE OR DELETE ON "member_profile"
|
jbe@532
|
1325 FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1326 "write_event_member_profile_updated_trigger"();
|
jbe@532
|
1327
|
jbe@532
|
1328 COMMENT ON FUNCTION "write_event_member_profile_updated_trigger"() IS 'Implementation of trigger "write_event_member_profile_updated" on table "member_profile"';
|
jbe@532
|
1329 COMMENT ON TRIGGER "write_event_member_profile_updated" ON "member_profile" IS 'Creates entries in "event" table on member profile update';
|
jbe@532
|
1330
|
jbe@532
|
1331
|
jbe@532
|
1332 CREATE FUNCTION "write_event_member_image_updated_trigger"()
|
jbe@532
|
1333 RETURNS TRIGGER
|
jbe@532
|
1334 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1335 BEGIN
|
jbe@532
|
1336 IF TG_OP = 'DELETE' OR TG_OP = 'UPDATE' THEN
|
jbe@532
|
1337 IF NOT OLD."scaled" THEN
|
jbe@532
|
1338 IF EXISTS (SELECT NULL FROM "member" WHERE "id" = OLD."member_id") THEN
|
jbe@532
|
1339 INSERT INTO "event" ("event", "member_id") VALUES (
|
jbe@532
|
1340 'member_image_updated', OLD."member_id"
|
jbe@532
|
1341 );
|
jbe@532
|
1342 END IF;
|
jbe@532
|
1343 END IF;
|
jbe@532
|
1344 END IF;
|
jbe@532
|
1345 IF TG_OP = 'UPDATE' THEN
|
jbe@532
|
1346 IF
|
jbe@532
|
1347 OLD."member_id" = NEW."member_id" AND
|
jbe@532
|
1348 OLD."scaled" = NEW."scaled"
|
jbe@532
|
1349 THEN
|
jbe@532
|
1350 RETURN NULL;
|
jbe@532
|
1351 END IF;
|
jbe@532
|
1352 END IF;
|
jbe@532
|
1353 IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
|
jbe@532
|
1354 IF NOT NEW."scaled" THEN
|
jbe@532
|
1355 INSERT INTO "event" ("event", "member_id") VALUES (
|
jbe@532
|
1356 'member_image_updated', NEW."member_id"
|
jbe@532
|
1357 );
|
jbe@532
|
1358 END IF;
|
jbe@532
|
1359 END IF;
|
jbe@532
|
1360 RETURN NULL;
|
jbe@532
|
1361 END;
|
jbe@532
|
1362 $$;
|
jbe@532
|
1363
|
jbe@532
|
1364 CREATE TRIGGER "write_event_member_image_updated"
|
jbe@532
|
1365 AFTER INSERT OR UPDATE OR DELETE ON "member_image"
|
jbe@532
|
1366 FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1367 "write_event_member_image_updated_trigger"();
|
jbe@532
|
1368
|
jbe@532
|
1369 COMMENT ON FUNCTION "write_event_member_image_updated_trigger"() IS 'Implementation of trigger "write_event_member_image_updated" on table "member_image"';
|
jbe@532
|
1370 COMMENT ON TRIGGER "write_event_member_image_updated" ON "member_image" IS 'Creates entries in "event" table on member image update';
|
jbe@532
|
1371
|
jbe@532
|
1372
|
jbe@532
|
1373 CREATE FUNCTION "write_event_interest_trigger"()
|
jbe@532
|
1374 RETURNS TRIGGER
|
jbe@532
|
1375 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1376 DECLARE
|
jbe@532
|
1377 "issue_row" "issue"%ROWTYPE;
|
jbe@532
|
1378 "area_row" "area"%ROWTYPE;
|
jbe@532
|
1379 BEGIN
|
jbe@532
|
1380 IF TG_OP = 'UPDATE' THEN
|
jbe@532
|
1381 IF OLD = NEW THEN
|
jbe@532
|
1382 RETURN NULL;
|
jbe@532
|
1383 END IF;
|
jbe@532
|
1384 END IF;
|
jbe@532
|
1385 IF TG_OP = 'DELETE' OR TG_OP = 'UPDATE' THEN
|
jbe@532
|
1386 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1387 WHERE "id" = OLD."issue_id" FOR SHARE;
|
jbe@532
|
1388 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1389 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1390 IF "issue_row"."id" NOTNULL THEN
|
jbe@532
|
1391 INSERT INTO "event" (
|
jbe@532
|
1392 "event", "member_id",
|
jbe@536
|
1393 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@532
|
1394 "boolean_value"
|
jbe@532
|
1395 ) VALUES (
|
jbe@532
|
1396 'interest', OLD."member_id",
|
jbe@532
|
1397 "area_row"."unit_id", "issue_row"."area_id",
|
jbe@536
|
1398 "issue_row"."policy_id",
|
jbe@532
|
1399 OLD."issue_id", "issue_row"."state",
|
jbe@532
|
1400 FALSE
|
jbe@532
|
1401 );
|
jbe@532
|
1402 END IF;
|
jbe@532
|
1403 END IF;
|
jbe@532
|
1404 IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
|
jbe@532
|
1405 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1406 WHERE "id" = NEW."issue_id" FOR SHARE;
|
jbe@532
|
1407 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1408 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1409 INSERT INTO "event" (
|
jbe@532
|
1410 "event", "member_id",
|
jbe@536
|
1411 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@532
|
1412 "boolean_value"
|
jbe@532
|
1413 ) VALUES (
|
jbe@532
|
1414 'interest', NEW."member_id",
|
jbe@532
|
1415 "area_row"."unit_id", "issue_row"."area_id",
|
jbe@536
|
1416 "issue_row"."policy_id",
|
jbe@532
|
1417 NEW."issue_id", "issue_row"."state",
|
jbe@532
|
1418 TRUE
|
jbe@532
|
1419 );
|
jbe@532
|
1420 END IF;
|
jbe@532
|
1421 RETURN NULL;
|
jbe@532
|
1422 END;
|
jbe@532
|
1423 $$;
|
jbe@532
|
1424
|
jbe@532
|
1425 CREATE TRIGGER "write_event_interest"
|
jbe@532
|
1426 AFTER INSERT OR UPDATE OR DELETE ON "interest" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1427 "write_event_interest_trigger"();
|
jbe@532
|
1428
|
jbe@532
|
1429 COMMENT ON FUNCTION "write_event_interest_trigger"() IS 'Implementation of trigger "write_event_interest_inserted" on table "interest"';
|
jbe@532
|
1430 COMMENT ON TRIGGER "write_event_interest" ON "interest" IS 'Create entry in "event" table on adding or removing interest';
|
jbe@532
|
1431
|
jbe@532
|
1432
|
jbe@532
|
1433 CREATE FUNCTION "write_event_initiator_trigger"()
|
jbe@532
|
1434 RETURNS TRIGGER
|
jbe@532
|
1435 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1436 DECLARE
|
jbe@532
|
1437 "initiative_row" "initiative"%ROWTYPE;
|
jbe@532
|
1438 "issue_row" "issue"%ROWTYPE;
|
jbe@532
|
1439 "area_row" "area"%ROWTYPE;
|
jbe@532
|
1440 BEGIN
|
jbe@532
|
1441 IF TG_OP = 'UPDATE' THEN
|
jbe@532
|
1442 IF
|
jbe@532
|
1443 OLD."initiative_id" = NEW."initiative_id" AND
|
jbe@532
|
1444 OLD."member_id" = NEW."member_id" AND
|
jbe@532
|
1445 coalesce(OLD."accepted", FALSE) = coalesce(NEW."accepted", FALSE)
|
jbe@532
|
1446 THEN
|
jbe@532
|
1447 RETURN NULL;
|
jbe@532
|
1448 END IF;
|
jbe@532
|
1449 END IF;
|
jbe@532
|
1450 IF (TG_OP = 'DELETE' OR TG_OP = 'UPDATE') AND NOT "accepted_v" THEN
|
jbe@532
|
1451 IF coalesce(OLD."accepted", FALSE) = TRUE THEN
|
jbe@532
|
1452 SELECT * INTO "initiative_row" FROM "initiative"
|
jbe@532
|
1453 WHERE "id" = OLD."initiative_id" FOR SHARE;
|
jbe@532
|
1454 IF "initiative_row"."id" NOTNULL THEN
|
jbe@532
|
1455 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1456 WHERE "id" = "initiative_row"."issue_id" FOR SHARE;
|
jbe@532
|
1457 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1458 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1459 INSERT INTO "event" (
|
jbe@532
|
1460 "event", "member_id",
|
jbe@536
|
1461 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@532
|
1462 "initiative_id", "boolean_value"
|
jbe@532
|
1463 ) VALUES (
|
jbe@532
|
1464 'initiator', OLD."member_id",
|
jbe@532
|
1465 "area_row"."unit_id", "issue_row"."area_id",
|
jbe@536
|
1466 "issue_row"."policy_id",
|
jbe@532
|
1467 "issue_row"."id", "issue_row"."state",
|
jbe@532
|
1468 OLD."initiative_id", FALSE
|
jbe@532
|
1469 );
|
jbe@532
|
1470 END IF;
|
jbe@532
|
1471 END IF;
|
jbe@532
|
1472 END IF;
|
jbe@532
|
1473 IF TG_OP = 'UPDATE' AND NOT "rejected_v" THEN
|
jbe@532
|
1474 IF coalesce(NEW."accepted", FALSE) = TRUE THEN
|
jbe@532
|
1475 SELECT * INTO "initiative_row" FROM "initiative"
|
jbe@532
|
1476 WHERE "id" = NEW."initiative_id" FOR SHARE;
|
jbe@532
|
1477 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1478 WHERE "id" = "initiative_row"."issue_id" FOR SHARE;
|
jbe@532
|
1479 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1480 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1481 INSERT INTO "event" (
|
jbe@532
|
1482 "event", "member_id",
|
jbe@536
|
1483 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@532
|
1484 "initiative_id", "boolean_value"
|
jbe@532
|
1485 ) VALUES (
|
jbe@532
|
1486 'initiator', NEW."member_id",
|
jbe@532
|
1487 "area_row"."unit_id", "issue_row"."area_id",
|
jbe@536
|
1488 "issue_row"."policy_id",
|
jbe@532
|
1489 "issue_row"."id", "issue_row"."state",
|
jbe@532
|
1490 NEW."initiative_id", TRUE
|
jbe@532
|
1491 );
|
jbe@532
|
1492 END IF;
|
jbe@532
|
1493 END IF;
|
jbe@532
|
1494 RETURN NULL;
|
jbe@532
|
1495 END;
|
jbe@532
|
1496 $$;
|
jbe@532
|
1497
|
jbe@532
|
1498 CREATE TRIGGER "write_event_initiator"
|
jbe@532
|
1499 AFTER UPDATE OR DELETE ON "initiator" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1500 "write_event_initiator_trigger"();
|
jbe@532
|
1501
|
jbe@532
|
1502 COMMENT ON FUNCTION "write_event_initiator_trigger"() IS 'Implementation of trigger "write_event_initiator" on table "initiator"';
|
jbe@532
|
1503 COMMENT ON TRIGGER "write_event_initiator" ON "initiator" IS 'Create entry in "event" table when accepting or removing initiatorship (NOTE: trigger does not fire on INSERT to avoid events on initiative creation)';
|
jbe@532
|
1504
|
jbe@532
|
1505
|
jbe@532
|
1506 CREATE FUNCTION "write_event_support_trigger"()
|
jbe@532
|
1507 RETURNS TRIGGER
|
jbe@532
|
1508 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1509 DECLARE
|
jbe@532
|
1510 "issue_row" "issue"%ROWTYPE;
|
jbe@532
|
1511 "area_row" "area"%ROWTYPE;
|
jbe@532
|
1512 BEGIN
|
jbe@532
|
1513 IF TG_OP = 'UPDATE' THEN
|
jbe@532
|
1514 IF
|
jbe@532
|
1515 OLD."initiative_id" = NEW."initiative_id" AND
|
jbe@532
|
1516 OLD."member_id" = NEW."member_id"
|
jbe@532
|
1517 THEN
|
jbe@532
|
1518 IF OLD."draft_id" != NEW."draft_id" THEN
|
jbe@532
|
1519 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1520 WHERE "id" = NEW."issue_id" FOR SHARE;
|
jbe@532
|
1521 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1522 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1523 INSERT INTO "event" (
|
jbe@532
|
1524 "event", "member_id",
|
jbe@536
|
1525 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@532
|
1526 "initiative_id", "draft_id"
|
jbe@532
|
1527 ) VALUES (
|
jbe@532
|
1528 'support_updated', NEW."member_id",
|
jbe@532
|
1529 "area_row"."unit_id", "issue_row"."area_id",
|
jbe@536
|
1530 "issue_row"."policy_id",
|
jbe@532
|
1531 "issue_row"."id", "issue_row"."state",
|
jbe@532
|
1532 NEW."initiative_id", NEW."draft_id"
|
jbe@532
|
1533 );
|
jbe@532
|
1534 END IF;
|
jbe@532
|
1535 RETURN NULL;
|
jbe@532
|
1536 END IF;
|
jbe@532
|
1537 END IF;
|
jbe@532
|
1538 IF TG_OP = 'DELETE' OR TG_OP = 'UPDATE' THEN
|
jbe@532
|
1539 IF EXISTS (
|
jbe@532
|
1540 SELECT NULL FROM "initiative" WHERE "id" = OLD."initiative_id"
|
jbe@532
|
1541 FOR SHARE
|
jbe@532
|
1542 ) THEN
|
jbe@532
|
1543 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1544 WHERE "id" = OLD."issue_id" FOR SHARE;
|
jbe@532
|
1545 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1546 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1547 INSERT INTO "event" (
|
jbe@532
|
1548 "event", "member_id",
|
jbe@536
|
1549 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@535
|
1550 "initiative_id", "boolean_value"
|
jbe@532
|
1551 ) VALUES (
|
jbe@532
|
1552 'support', OLD."member_id",
|
jbe@532
|
1553 "area_row"."unit_id", "issue_row"."area_id",
|
jbe@536
|
1554 "issue_row"."policy_id",
|
jbe@532
|
1555 "issue_row"."id", "issue_row"."state",
|
jbe@535
|
1556 OLD."initiative_id", FALSE
|
jbe@532
|
1557 );
|
jbe@532
|
1558 END IF;
|
jbe@532
|
1559 END IF;
|
jbe@532
|
1560 IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
|
jbe@532
|
1561 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1562 WHERE "id" = NEW."issue_id" FOR SHARE;
|
jbe@532
|
1563 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1564 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1565 INSERT INTO "event" (
|
jbe@532
|
1566 "event", "member_id",
|
jbe@536
|
1567 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@532
|
1568 "initiative_id", "draft_id", "boolean_value"
|
jbe@532
|
1569 ) VALUES (
|
jbe@532
|
1570 'support', NEW."member_id",
|
jbe@532
|
1571 "area_row"."unit_id", "issue_row"."area_id",
|
jbe@536
|
1572 "issue_row"."policy_id",
|
jbe@532
|
1573 "issue_row"."id", "issue_row"."state",
|
jbe@532
|
1574 NEW."initiative_id", NEW."draft_id", TRUE
|
jbe@532
|
1575 );
|
jbe@532
|
1576 END IF;
|
jbe@532
|
1577 RETURN NULL;
|
jbe@532
|
1578 END;
|
jbe@532
|
1579 $$;
|
jbe@532
|
1580
|
jbe@532
|
1581 CREATE TRIGGER "write_event_support"
|
jbe@532
|
1582 AFTER INSERT OR UPDATE OR DELETE ON "supporter" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1583 "write_event_support_trigger"();
|
jbe@532
|
1584
|
jbe@532
|
1585 COMMENT ON FUNCTION "write_event_support_trigger"() IS 'Implementation of trigger "write_event_support" on table "supporter"';
|
jbe@532
|
1586 COMMENT ON TRIGGER "write_event_support" ON "supporter" IS 'Create entry in "event" table when adding, updating, or removing support';
|
jbe@532
|
1587
|
jbe@532
|
1588
|
jbe@532
|
1589 CREATE FUNCTION "write_event_suggestion_rated_trigger"()
|
jbe@532
|
1590 RETURNS TRIGGER
|
jbe@532
|
1591 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1592 DECLARE
|
jbe@532
|
1593 "same_pkey_v" BOOLEAN = FALSE;
|
jbe@532
|
1594 "initiative_row" "initiative"%ROWTYPE;
|
jbe@532
|
1595 "issue_row" "issue"%ROWTYPE;
|
jbe@532
|
1596 "area_row" "area"%ROWTYPE;
|
jbe@532
|
1597 BEGIN
|
jbe@532
|
1598 IF TG_OP = 'UPDATE' THEN
|
jbe@532
|
1599 IF
|
jbe@532
|
1600 OLD."suggestion_id" = NEW."suggestion_id" AND
|
jbe@532
|
1601 OLD."member_id" = NEW."member_id"
|
jbe@532
|
1602 THEN
|
jbe@532
|
1603 IF
|
jbe@532
|
1604 OLD."degree" = NEW."degree" AND
|
jbe@532
|
1605 OLD."fulfilled" = NEW."fulfilled"
|
jbe@532
|
1606 THEN
|
jbe@532
|
1607 RETURN NULL;
|
jbe@532
|
1608 END IF;
|
jbe@532
|
1609 "same_pkey_v" := TRUE;
|
jbe@532
|
1610 END IF;
|
jbe@532
|
1611 END IF;
|
jbe@532
|
1612 IF (TG_OP = 'DELETE' OR TG_OP = 'UPDATE') AND NOT "same_pkey_v" THEN
|
jbe@532
|
1613 IF EXISTS (
|
jbe@532
|
1614 SELECT NULL FROM "suggestion" WHERE "id" = OLD."suggestion_id"
|
jbe@532
|
1615 FOR SHARE
|
jbe@532
|
1616 ) THEN
|
jbe@532
|
1617 SELECT * INTO "initiative_row" FROM "initiative"
|
jbe@532
|
1618 WHERE "id" = OLD."initiative_id" FOR SHARE;
|
jbe@532
|
1619 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1620 WHERE "id" = "initiative_row"."issue_id" FOR SHARE;
|
jbe@532
|
1621 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1622 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1623 INSERT INTO "event" (
|
jbe@532
|
1624 "event", "member_id",
|
jbe@536
|
1625 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@532
|
1626 "initiative_id", "suggestion_id",
|
jbe@532
|
1627 "boolean_value", "numeric_value"
|
jbe@532
|
1628 ) VALUES (
|
jbe@532
|
1629 'suggestion_rated', OLD."member_id",
|
jbe@532
|
1630 "area_row"."unit_id", "issue_row"."area_id",
|
jbe@536
|
1631 "issue_row"."policy_id",
|
jbe@532
|
1632 "initiative_row"."issue_id", "issue_row"."state",
|
jbe@532
|
1633 OLD."initiative_id", OLD."suggestion_id",
|
jbe@532
|
1634 NULL, 0
|
jbe@532
|
1635 );
|
jbe@532
|
1636 END IF;
|
jbe@532
|
1637 END IF;
|
jbe@532
|
1638 IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
|
jbe@532
|
1639 SELECT * INTO "initiative_row" FROM "initiative"
|
jbe@532
|
1640 WHERE "id" = NEW."initiative_id" FOR SHARE;
|
jbe@532
|
1641 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1642 WHERE "id" = "initiative_row"."issue_id" FOR SHARE;
|
jbe@532
|
1643 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1644 WHERE "id" = "issue_row"."area_id" FOR SHARE;
|
jbe@532
|
1645 INSERT INTO "event" (
|
jbe@532
|
1646 "event", "member_id",
|
jbe@536
|
1647 "unit_id", "area_id", "policy_id", "issue_id", "state",
|
jbe@532
|
1648 "initiative_id", "suggestion_id",
|
jbe@532
|
1649 "boolean_value", "numeric_value"
|
jbe@532
|
1650 ) VALUES (
|
jbe@532
|
1651 'suggestion_rated', NEW."member_id",
|
jbe@532
|
1652 "area_row"."unit_id", "issue_row"."area_id",
|
jbe@536
|
1653 "issue_row"."policy_id",
|
jbe@532
|
1654 "initiative_row"."issue_id", "issue_row"."state",
|
jbe@532
|
1655 NEW."initiative_id", NEW."suggestion_id",
|
jbe@532
|
1656 NEW."fulfilled", NEW."degree"
|
jbe@532
|
1657 );
|
jbe@532
|
1658 END IF;
|
jbe@532
|
1659 RETURN NULL;
|
jbe@532
|
1660 END;
|
jbe@532
|
1661 $$;
|
jbe@532
|
1662
|
jbe@532
|
1663 CREATE TRIGGER "write_event_suggestion_rated"
|
jbe@532
|
1664 AFTER INSERT OR UPDATE OR DELETE ON "opinion" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1665 "write_event_suggestion_rated_trigger"();
|
jbe@532
|
1666
|
jbe@532
|
1667 COMMENT ON FUNCTION "write_event_suggestion_rated_trigger"() IS 'Implementation of trigger "write_event_suggestion_rated" on table "opinion"';
|
jbe@532
|
1668 COMMENT ON TRIGGER "write_event_suggestion_rated" ON "opinion" IS 'Create entry in "event" table when adding, updating, or removing support';
|
jbe@532
|
1669
|
jbe@532
|
1670
|
jbe@532
|
1671 CREATE FUNCTION "write_event_delegation_trigger"()
|
jbe@532
|
1672 RETURNS TRIGGER
|
jbe@532
|
1673 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1674 DECLARE
|
jbe@532
|
1675 "issue_row" "issue"%ROWTYPE;
|
jbe@532
|
1676 "area_row" "area"%ROWTYPE;
|
jbe@532
|
1677 BEGIN
|
jbe@532
|
1678 IF TG_OP = 'DELETE' THEN
|
jbe@532
|
1679 IF EXISTS (
|
jbe@532
|
1680 SELECT NULL FROM "member" WHERE "id" = OLD."truster_id"
|
jbe@532
|
1681 ) AND (CASE OLD."scope"
|
jbe@532
|
1682 WHEN 'unit'::"delegation_scope" THEN EXISTS (
|
jbe@532
|
1683 SELECT NULL FROM "unit" WHERE "id" = OLD."unit_id"
|
jbe@532
|
1684 )
|
jbe@532
|
1685 WHEN 'area'::"delegation_scope" THEN EXISTS (
|
jbe@532
|
1686 SELECT NULL FROM "area" WHERE "id" = OLD."area_id"
|
jbe@532
|
1687 )
|
jbe@532
|
1688 WHEN 'issue'::"delegation_scope" THEN EXISTS (
|
jbe@532
|
1689 SELECT NULL FROM "issue" WHERE "id" = OLD."issue_id"
|
jbe@532
|
1690 )
|
jbe@532
|
1691 END) THEN
|
jbe@532
|
1692 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1693 WHERE "id" = OLD."issue_id" FOR SHARE;
|
jbe@532
|
1694 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1695 WHERE "id" = COALESCE(OLD."area_id", "issue_row"."area_id")
|
jbe@532
|
1696 FOR SHARE;
|
jbe@532
|
1697 INSERT INTO "event" (
|
jbe@532
|
1698 "event", "member_id", "scope",
|
jbe@532
|
1699 "unit_id", "area_id", "issue_id", "state",
|
jbe@532
|
1700 "boolean_value"
|
jbe@532
|
1701 ) VALUES (
|
jbe@532
|
1702 'delegation', OLD."truster_id", OLD."scope",
|
jbe@532
|
1703 COALESCE(OLD."unit_id", "area_row"."unit_id"), "area_row"."id",
|
jbe@532
|
1704 OLD."issue_id", "issue_row"."state",
|
jbe@532
|
1705 FALSE
|
jbe@532
|
1706 );
|
jbe@532
|
1707 END IF;
|
jbe@532
|
1708 ELSE
|
jbe@532
|
1709 SELECT * INTO "issue_row" FROM "issue"
|
jbe@532
|
1710 WHERE "id" = NEW."issue_id" FOR SHARE;
|
jbe@532
|
1711 SELECT * INTO "area_row" FROM "area"
|
jbe@532
|
1712 WHERE "id" = COALESCE(NEW."area_id", "issue_row"."area_id")
|
jbe@532
|
1713 FOR SHARE;
|
jbe@532
|
1714 INSERT INTO "event" (
|
jbe@532
|
1715 "event", "member_id", "other_member_id", "scope",
|
jbe@532
|
1716 "unit_id", "area_id", "issue_id", "state",
|
jbe@532
|
1717 "boolean_value"
|
jbe@532
|
1718 ) VALUES (
|
jbe@532
|
1719 'delegation', NEW."truster_id", NEW."trustee_id", NEW."scope",
|
jbe@532
|
1720 COALESCE(NEW."unit_id", "area_row"."unit_id"), "area_row"."id",
|
jbe@532
|
1721 NEW."issue_id", "issue_row"."state",
|
jbe@532
|
1722 TRUE
|
jbe@532
|
1723 );
|
jbe@532
|
1724 END IF;
|
jbe@532
|
1725 RETURN NULL;
|
jbe@532
|
1726 END;
|
jbe@532
|
1727 $$;
|
jbe@532
|
1728
|
jbe@532
|
1729 CREATE TRIGGER "write_event_delegation"
|
jbe@532
|
1730 AFTER INSERT OR UPDATE OR DELETE ON "delegation" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1731 "write_event_delegation_trigger"();
|
jbe@532
|
1732
|
jbe@532
|
1733 COMMENT ON FUNCTION "write_event_delegation_trigger"() IS 'Implementation of trigger "write_event_delegation" on table "delegation"';
|
jbe@532
|
1734 COMMENT ON TRIGGER "write_event_delegation" ON "delegation" IS 'Create entry in "event" table when adding, updating, or removing a delegation';
|
jbe@532
|
1735
|
jbe@532
|
1736
|
jbe@532
|
1737 CREATE FUNCTION "write_event_contact_trigger"()
|
jbe@532
|
1738 RETURNS TRIGGER
|
jbe@532
|
1739 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1740 BEGIN
|
jbe@532
|
1741 IF TG_OP = 'UPDATE' THEN
|
jbe@532
|
1742 IF
|
jbe@532
|
1743 OLD."member_id" = NEW."member_id" AND
|
jbe@532
|
1744 OLD."other_member_id" = NEW."other_member_id" AND
|
jbe@532
|
1745 OLD."public" = NEW."public"
|
jbe@532
|
1746 THEN
|
jbe@532
|
1747 RETURN NULL;
|
jbe@532
|
1748 END IF;
|
jbe@532
|
1749 END IF;
|
jbe@532
|
1750 IF TG_OP = 'DELETE' OR TG_OP = 'UPDATE' THEN
|
jbe@532
|
1751 IF OLD."public" THEN
|
jbe@532
|
1752 IF EXISTS (
|
jbe@532
|
1753 SELECT NULL FROM "member" WHERE "id" = OLD."member_id"
|
jbe@532
|
1754 FOR SHARE
|
jbe@532
|
1755 ) AND EXISTS (
|
jbe@532
|
1756 SELECT NULL FROM "member" WHERE "id" = OLD."other_member_id"
|
jbe@532
|
1757 FOR SHARE
|
jbe@532
|
1758 ) THEN
|
jbe@532
|
1759 INSERT INTO "event" (
|
jbe@532
|
1760 "event", "member_id", "other_member_id", "boolean_value"
|
jbe@532
|
1761 ) VALUES (
|
jbe@532
|
1762 'contact', OLD."member_id", OLD."other_member_id", FALSE
|
jbe@532
|
1763 );
|
jbe@532
|
1764 END IF;
|
jbe@532
|
1765 END IF;
|
jbe@532
|
1766 END IF;
|
jbe@532
|
1767 IF TG_OP = 'INSERT' OR TG_OP = 'UPDATE' THEN
|
jbe@532
|
1768 IF NEW."public" THEN
|
jbe@532
|
1769 INSERT INTO "event" (
|
jbe@532
|
1770 "event", "member_id", "other_member_id", "boolean_value"
|
jbe@532
|
1771 ) VALUES (
|
jbe@532
|
1772 'contact', NEW."member_id", NEW."other_member_id", TRUE
|
jbe@532
|
1773 );
|
jbe@532
|
1774 END IF;
|
jbe@532
|
1775 END IF;
|
jbe@532
|
1776 RETURN NULL;
|
jbe@532
|
1777 END;
|
jbe@532
|
1778 $$;
|
jbe@532
|
1779
|
jbe@532
|
1780 CREATE TRIGGER "write_event_contact"
|
jbe@532
|
1781 AFTER INSERT OR UPDATE OR DELETE ON "contact" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1782 "write_event_contact_trigger"();
|
jbe@532
|
1783
|
jbe@532
|
1784 COMMENT ON FUNCTION "write_event_contact_trigger"() IS 'Implementation of trigger "write_event_contact" on table "contact"';
|
jbe@532
|
1785 COMMENT ON TRIGGER "write_event_contact" ON "contact" IS 'Create entry in "event" table when adding or removing public contacts';
|
jbe@532
|
1786
|
jbe@532
|
1787
|
jbe@532
|
1788 CREATE FUNCTION "send_event_notify_trigger"()
|
jbe@532
|
1789 RETURNS TRIGGER
|
jbe@532
|
1790 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1791 BEGIN
|
jbe@532
|
1792 EXECUTE 'NOTIFY "event", ''' || NEW."event" || '''';
|
jbe@532
|
1793 RETURN NULL;
|
jbe@532
|
1794 END;
|
jbe@532
|
1795 $$;
|
jbe@532
|
1796
|
jbe@532
|
1797 CREATE TRIGGER "send_notify"
|
jbe@532
|
1798 AFTER INSERT OR UPDATE ON "event" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1799 "send_event_notify_trigger"();
|
jbe@532
|
1800
|
jbe@532
|
1801
|
jbe@532
|
1802 CREATE FUNCTION "delete_extended_scope_tokens_trigger"()
|
jbe@532
|
1803 RETURNS TRIGGER
|
jbe@532
|
1804 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1805 DECLARE
|
jbe@532
|
1806 "system_application_row" "system_application"%ROWTYPE;
|
jbe@532
|
1807 BEGIN
|
jbe@532
|
1808 IF OLD."system_application_id" NOTNULL THEN
|
jbe@532
|
1809 SELECT * FROM "system_application" INTO "system_application_row"
|
jbe@532
|
1810 WHERE "id" = OLD."system_application_id";
|
jbe@532
|
1811 DELETE FROM "token"
|
jbe@532
|
1812 WHERE "member_id" = OLD."member_id"
|
jbe@532
|
1813 AND "system_application_id" = OLD."system_application_id"
|
jbe@532
|
1814 AND NOT COALESCE(
|
jbe@532
|
1815 regexp_split_to_array("scope", E'\\s+') <@
|
jbe@532
|
1816 regexp_split_to_array(
|
jbe@532
|
1817 "system_application_row"."automatic_scope", E'\\s+'
|
jbe@532
|
1818 ),
|
jbe@532
|
1819 FALSE
|
jbe@532
|
1820 );
|
jbe@532
|
1821 END IF;
|
jbe@532
|
1822 RETURN OLD;
|
jbe@532
|
1823 END;
|
jbe@532
|
1824 $$;
|
jbe@532
|
1825
|
jbe@532
|
1826 CREATE TRIGGER "delete_extended_scope_tokens"
|
jbe@532
|
1827 BEFORE DELETE ON "member_application" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1828 "delete_extended_scope_tokens_trigger"();
|
jbe@532
|
1829
|
jbe@532
|
1830
|
jbe@532
|
1831 CREATE FUNCTION "detach_token_from_session_trigger"()
|
jbe@532
|
1832 RETURNS TRIGGER
|
jbe@532
|
1833 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1834 BEGIN
|
jbe@532
|
1835 UPDATE "token" SET "session_id" = NULL
|
jbe@532
|
1836 WHERE "session_id" = OLD."id";
|
jbe@532
|
1837 RETURN OLD;
|
jbe@532
|
1838 END;
|
jbe@532
|
1839 $$;
|
jbe@532
|
1840
|
jbe@532
|
1841 CREATE TRIGGER "detach_token_from_session"
|
jbe@532
|
1842 BEFORE DELETE ON "session" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1843 "detach_token_from_session_trigger"();
|
jbe@532
|
1844
|
jbe@532
|
1845
|
jbe@532
|
1846 CREATE FUNCTION "delete_non_detached_scope_with_session_trigger"()
|
jbe@532
|
1847 RETURNS TRIGGER
|
jbe@532
|
1848 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1849 BEGIN
|
jbe@532
|
1850 IF NEW."session_id" ISNULL THEN
|
jbe@532
|
1851 SELECT coalesce(string_agg("element", ' '), '') INTO NEW."scope"
|
jbe@532
|
1852 FROM unnest(regexp_split_to_array(NEW."scope", E'\\s+')) AS "element"
|
jbe@532
|
1853 WHERE "element" LIKE '%_detached';
|
jbe@532
|
1854 END IF;
|
jbe@532
|
1855 RETURN NEW;
|
jbe@532
|
1856 END;
|
jbe@532
|
1857 $$;
|
jbe@532
|
1858
|
jbe@532
|
1859 CREATE TRIGGER "delete_non_detached_scope_with_session"
|
jbe@532
|
1860 BEFORE INSERT OR UPDATE ON "token" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1861 "delete_non_detached_scope_with_session_trigger"();
|
jbe@532
|
1862
|
jbe@532
|
1863
|
jbe@532
|
1864 CREATE FUNCTION "delete_token_with_empty_scope_trigger"()
|
jbe@532
|
1865 RETURNS TRIGGER
|
jbe@532
|
1866 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1867 BEGIN
|
jbe@532
|
1868 IF NEW."scope" = '' THEN
|
jbe@532
|
1869 DELETE FROM "token" WHERE "id" = NEW."id";
|
jbe@532
|
1870 END IF;
|
jbe@532
|
1871 RETURN NULL;
|
jbe@532
|
1872 END;
|
jbe@532
|
1873 $$;
|
jbe@532
|
1874
|
jbe@532
|
1875 CREATE TRIGGER "delete_token_with_empty_scope"
|
jbe@532
|
1876 AFTER INSERT OR UPDATE ON "token" FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1877 "delete_token_with_empty_scope_trigger"();
|
jbe@532
|
1878
|
jbe@532
|
1879
|
jbe@532
|
1880 CREATE FUNCTION "delete_snapshot_on_partial_delete_trigger"()
|
jbe@532
|
1881 RETURNS TRIGGER
|
jbe@532
|
1882 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1883 BEGIN
|
jbe@532
|
1884 IF TG_OP = 'UPDATE' THEN
|
jbe@532
|
1885 IF
|
jbe@532
|
1886 OLD."snapshot_id" = NEW."snapshot_id" AND
|
jbe@532
|
1887 OLD."issue_id" = NEW."issue_id"
|
jbe@532
|
1888 THEN
|
jbe@532
|
1889 RETURN NULL;
|
jbe@532
|
1890 END IF;
|
jbe@532
|
1891 END IF;
|
jbe@532
|
1892 DELETE FROM "snapshot" WHERE "id" = OLD."snapshot_id";
|
jbe@532
|
1893 RETURN NULL;
|
jbe@532
|
1894 END;
|
jbe@532
|
1895 $$;
|
jbe@532
|
1896
|
jbe@532
|
1897 CREATE TRIGGER "delete_snapshot_on_partial_delete"
|
jbe@532
|
1898 AFTER UPDATE OR DELETE ON "snapshot_issue"
|
jbe@532
|
1899 FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1900 "delete_snapshot_on_partial_delete_trigger"();
|
jbe@532
|
1901
|
jbe@532
|
1902 COMMENT ON FUNCTION "delete_snapshot_on_partial_delete_trigger"() IS 'Implementation of trigger "delete_snapshot_on_partial_delete" on table "snapshot_issue"';
|
jbe@532
|
1903 COMMENT ON TRIGGER "delete_snapshot_on_partial_delete" ON "snapshot_issue" IS 'Deletes whole snapshot if one issue is deleted from the snapshot';
|
jbe@532
|
1904
|
jbe@532
|
1905
|
jbe@532
|
1906 CREATE FUNCTION "copy_current_draft_data"
|
jbe@532
|
1907 ("initiative_id_p" "initiative"."id"%TYPE )
|
jbe@532
|
1908 RETURNS VOID
|
jbe@532
|
1909 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1910 BEGIN
|
jbe@532
|
1911 PERFORM NULL FROM "initiative" WHERE "id" = "initiative_id_p"
|
jbe@532
|
1912 FOR UPDATE;
|
jbe@532
|
1913 UPDATE "initiative" SET
|
jbe@532
|
1914 "location" = "draft"."location",
|
jbe@532
|
1915 "draft_text_search_data" = "draft"."text_search_data"
|
jbe@532
|
1916 FROM "current_draft" AS "draft"
|
jbe@532
|
1917 WHERE "initiative"."id" = "initiative_id_p"
|
jbe@532
|
1918 AND "draft"."initiative_id" = "initiative_id_p";
|
jbe@532
|
1919 END;
|
jbe@532
|
1920 $$;
|
jbe@532
|
1921
|
jbe@532
|
1922 COMMENT ON FUNCTION "copy_current_draft_data"
|
jbe@532
|
1923 ( "initiative"."id"%TYPE )
|
jbe@532
|
1924 IS 'Helper function for function "copy_current_draft_data_trigger"';
|
jbe@532
|
1925
|
jbe@532
|
1926
|
jbe@532
|
1927 CREATE FUNCTION "copy_current_draft_data_trigger"()
|
jbe@532
|
1928 RETURNS TRIGGER
|
jbe@532
|
1929 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
1930 BEGIN
|
jbe@532
|
1931 IF TG_OP='DELETE' THEN
|
jbe@532
|
1932 PERFORM "copy_current_draft_data"(OLD."initiative_id");
|
jbe@532
|
1933 ELSE
|
jbe@532
|
1934 IF TG_OP='UPDATE' THEN
|
jbe@532
|
1935 IF COALESCE(OLD."inititiave_id" != NEW."initiative_id", TRUE) THEN
|
jbe@532
|
1936 PERFORM "copy_current_draft_data"(OLD."initiative_id");
|
jbe@532
|
1937 END IF;
|
jbe@532
|
1938 END IF;
|
jbe@532
|
1939 PERFORM "copy_current_draft_data"(NEW."initiative_id");
|
jbe@532
|
1940 END IF;
|
jbe@532
|
1941 RETURN NULL;
|
jbe@532
|
1942 END;
|
jbe@532
|
1943 $$;
|
jbe@532
|
1944
|
jbe@532
|
1945 CREATE TRIGGER "copy_current_draft_data"
|
jbe@532
|
1946 AFTER INSERT OR UPDATE OR DELETE ON "draft"
|
jbe@532
|
1947 FOR EACH ROW EXECUTE PROCEDURE
|
jbe@532
|
1948 "copy_current_draft_data_trigger"();
|
jbe@532
|
1949
|
jbe@532
|
1950 COMMENT ON FUNCTION "copy_current_draft_data_trigger"() IS 'Implementation of trigger "copy_current_draft_data" on table "draft"';
|
jbe@532
|
1951 COMMENT ON TRIGGER "copy_current_draft_data" ON "draft" IS 'Copy certain fields from most recent "draft" to "initiative"';
|
jbe@532
|
1952
|
jbe@532
|
1953
|
jbe@532
|
1954 CREATE VIEW "area_quorum" AS
|
jbe@532
|
1955 SELECT
|
jbe@532
|
1956 "area"."id" AS "area_id",
|
jbe@532
|
1957 ceil(
|
jbe@532
|
1958 "area"."quorum_standard"::FLOAT8 * "quorum_factor"::FLOAT8 ^ (
|
jbe@532
|
1959 coalesce(
|
jbe@532
|
1960 ( SELECT sum(
|
jbe@532
|
1961 ( extract(epoch from "area"."quorum_time")::FLOAT8 /
|
jbe@532
|
1962 extract(epoch from
|
jbe@532
|
1963 ("issue"."accepted"-"issue"."created") +
|
jbe@532
|
1964 "issue"."discussion_time" +
|
jbe@532
|
1965 "issue"."verification_time" +
|
jbe@532
|
1966 "issue"."voting_time"
|
jbe@532
|
1967 )::FLOAT8
|
jbe@532
|
1968 ) ^ "area"."quorum_exponent"::FLOAT8
|
jbe@532
|
1969 )
|
jbe@532
|
1970 FROM "issue" JOIN "policy"
|
jbe@532
|
1971 ON "issue"."policy_id" = "policy"."id"
|
jbe@532
|
1972 WHERE "issue"."area_id" = "area"."id"
|
jbe@532
|
1973 AND "issue"."accepted" NOTNULL
|
jbe@532
|
1974 AND "issue"."closed" ISNULL
|
jbe@532
|
1975 AND "policy"."polling" = FALSE
|
jbe@532
|
1976 )::FLOAT8, 0::FLOAT8
|
jbe@532
|
1977 ) / "area"."quorum_issues"::FLOAT8 - 1::FLOAT8
|
jbe@532
|
1978 ) * CASE WHEN "area"."quorum_den" ISNULL THEN 1 ELSE (
|
jbe@532
|
1979 SELECT "snapshot"."population"
|
jbe@532
|
1980 FROM "snapshot"
|
jbe@532
|
1981 WHERE "snapshot"."area_id" = "area"."id"
|
jbe@532
|
1982 AND "snapshot"."issue_id" ISNULL
|
jbe@532
|
1983 ORDER BY "snapshot"."id" DESC
|
jbe@532
|
1984 LIMIT 1
|
jbe@532
|
1985 ) END / coalesce("area"."quorum_den", 1)
|
jbe@532
|
1986
|
jbe@532
|
1987 )::INT4 AS "issue_quorum"
|
jbe@532
|
1988 FROM "area";
|
jbe@532
|
1989
|
jbe@532
|
1990 COMMENT ON VIEW "area_quorum" IS 'Area-based quorum considering number of open (accepted) issues';
|
jbe@532
|
1991
|
jbe@532
|
1992
|
jbe@532
|
1993 CREATE VIEW "area_with_unaccepted_issues" AS
|
jbe@532
|
1994 SELECT DISTINCT ON ("area"."id") "area".*
|
jbe@532
|
1995 FROM "area" JOIN "issue" ON "area"."id" = "issue"."area_id"
|
jbe@532
|
1996 WHERE "issue"."state" = 'admission';
|
jbe@532
|
1997
|
jbe@532
|
1998 COMMENT ON VIEW "area_with_unaccepted_issues" IS 'All areas with unaccepted open issues (needed for issue admission system)';
|
jbe@532
|
1999
|
jbe@532
|
2000
|
jbe@532
|
2001 DROP VIEW "area_member_count";
|
jbe@532
|
2002
|
jbe@532
|
2003
|
jbe@532
|
2004 DROP TABLE "membership";
|
jbe@532
|
2005
|
jbe@532
|
2006
|
jbe@532
|
2007 DROP FUNCTION "membership_weight"
|
jbe@532
|
2008 ( "area_id_p" "area"."id"%TYPE,
|
jbe@532
|
2009 "member_id_p" "member"."id"%TYPE );
|
jbe@532
|
2010
|
jbe@532
|
2011
|
jbe@532
|
2012 DROP FUNCTION "membership_weight_with_skipping"
|
jbe@532
|
2013 ( "area_id_p" "area"."id"%TYPE,
|
jbe@532
|
2014 "member_id_p" "member"."id"%TYPE,
|
jbe@532
|
2015 "skip_member_ids_p" INT4[] ); -- TODO: ordering/cascade
|
jbe@532
|
2016
|
jbe@532
|
2017
|
jbe@532
|
2018 CREATE OR REPLACE VIEW "issue_delegation" AS
|
jbe@532
|
2019 SELECT DISTINCT ON ("issue"."id", "delegation"."truster_id")
|
jbe@532
|
2020 "issue"."id" AS "issue_id",
|
jbe@532
|
2021 "delegation"."id",
|
jbe@532
|
2022 "delegation"."truster_id",
|
jbe@532
|
2023 "delegation"."trustee_id",
|
jbe@532
|
2024 "delegation"."scope"
|
jbe@532
|
2025 FROM "issue"
|
jbe@532
|
2026 JOIN "area"
|
jbe@532
|
2027 ON "area"."id" = "issue"."area_id"
|
jbe@532
|
2028 JOIN "delegation"
|
jbe@532
|
2029 ON "delegation"."unit_id" = "area"."unit_id"
|
jbe@532
|
2030 OR "delegation"."area_id" = "area"."id"
|
jbe@532
|
2031 OR "delegation"."issue_id" = "issue"."id"
|
jbe@532
|
2032 JOIN "member"
|
jbe@532
|
2033 ON "delegation"."truster_id" = "member"."id"
|
jbe@532
|
2034 JOIN "privilege"
|
jbe@532
|
2035 ON "area"."unit_id" = "privilege"."unit_id"
|
jbe@532
|
2036 AND "delegation"."truster_id" = "privilege"."member_id"
|
jbe@532
|
2037 WHERE "member"."active" AND "privilege"."voting_right"
|
jbe@532
|
2038 ORDER BY
|
jbe@532
|
2039 "issue"."id",
|
jbe@532
|
2040 "delegation"."truster_id",
|
jbe@532
|
2041 "delegation"."scope" DESC;
|
jbe@532
|
2042
|
jbe@532
|
2043
|
jbe@532
|
2044 CREATE VIEW "unit_member" AS
|
jbe@532
|
2045 SELECT
|
jbe@532
|
2046 "unit"."id" AS "unit_id",
|
jbe@532
|
2047 "member"."id" AS "member_id"
|
jbe@532
|
2048 FROM "privilege"
|
jbe@532
|
2049 JOIN "unit" ON "unit_id" = "privilege"."unit_id"
|
jbe@532
|
2050 JOIN "member" ON "member"."id" = "privilege"."member_id"
|
jbe@532
|
2051 WHERE "privilege"."voting_right" AND "member"."active";
|
jbe@532
|
2052
|
jbe@532
|
2053 COMMENT ON VIEW "unit_member" IS 'Active members with voting right in a unit';
|
jbe@532
|
2054
|
jbe@532
|
2055
|
jbe@532
|
2056 CREATE OR REPLACE VIEW "unit_member_count" AS
|
jbe@532
|
2057 SELECT
|
jbe@532
|
2058 "unit"."id" AS "unit_id",
|
jbe@532
|
2059 count("unit_member"."member_id") AS "member_count"
|
jbe@532
|
2060 FROM "unit" LEFT JOIN "unit_member"
|
jbe@532
|
2061 ON "unit"."id" = "unit_member"."unit_id"
|
jbe@532
|
2062 GROUP BY "unit"."id";
|
jbe@532
|
2063
|
jbe@532
|
2064 COMMENT ON VIEW "unit_member_count" IS 'View used to update "member_count" column of "unit" table';
|
jbe@532
|
2065
|
jbe@532
|
2066
|
jbe@532
|
2067 CREATE OR REPLACE VIEW "opening_draft" AS
|
jbe@532
|
2068 SELECT DISTINCT ON ("initiative_id") * FROM "draft"
|
jbe@532
|
2069 ORDER BY "initiative_id", "id";
|
jbe@532
|
2070
|
jbe@532
|
2071
|
jbe@532
|
2072 CREATE OR REPLACE VIEW "current_draft" AS
|
jbe@532
|
2073 SELECT DISTINCT ON ("initiative_id") * FROM "draft"
|
jbe@532
|
2074 ORDER BY "initiative_id", "id" DESC;
|
jbe@532
|
2075
|
jbe@532
|
2076
|
jbe@532
|
2077 CREATE OR REPLACE VIEW "issue_supporter_in_admission_state" AS
|
jbe@532
|
2078 SELECT
|
jbe@532
|
2079 "area"."unit_id",
|
jbe@532
|
2080 "issue"."area_id",
|
jbe@532
|
2081 "issue"."id" AS "issue_id",
|
jbe@532
|
2082 "supporter"."member_id",
|
jbe@532
|
2083 "direct_interest_snapshot"."weight"
|
jbe@532
|
2084 FROM "issue"
|
jbe@532
|
2085 JOIN "area" ON "area"."id" = "issue"."area_id"
|
jbe@532
|
2086 JOIN "supporter" ON "supporter"."issue_id" = "issue"."id"
|
jbe@532
|
2087 JOIN "direct_interest_snapshot"
|
jbe@532
|
2088 ON "direct_interest_snapshot"."snapshot_id" = "issue"."latest_snapshot_id"
|
jbe@532
|
2089 AND "direct_interest_snapshot"."issue_id" = "issue"."id"
|
jbe@532
|
2090 AND "direct_interest_snapshot"."member_id" = "supporter"."member_id"
|
jbe@532
|
2091 WHERE "issue"."state" = 'admission'::"issue_state";
|
jbe@532
|
2092
|
jbe@532
|
2093
|
jbe@532
|
2094 CREATE OR REPLACE VIEW "individual_suggestion_ranking" AS
|
jbe@532
|
2095 SELECT
|
jbe@532
|
2096 "opinion"."initiative_id",
|
jbe@532
|
2097 "opinion"."member_id",
|
jbe@532
|
2098 "direct_interest_snapshot"."weight",
|
jbe@532
|
2099 CASE WHEN
|
jbe@532
|
2100 ("opinion"."degree" = 2 AND "opinion"."fulfilled" = FALSE) OR
|
jbe@532
|
2101 ("opinion"."degree" = -2 AND "opinion"."fulfilled" = TRUE)
|
jbe@532
|
2102 THEN 1 ELSE
|
jbe@532
|
2103 CASE WHEN
|
jbe@532
|
2104 ("opinion"."degree" = 1 AND "opinion"."fulfilled" = FALSE) OR
|
jbe@532
|
2105 ("opinion"."degree" = -1 AND "opinion"."fulfilled" = TRUE)
|
jbe@532
|
2106 THEN 2 ELSE
|
jbe@532
|
2107 CASE WHEN
|
jbe@532
|
2108 ("opinion"."degree" = 2 AND "opinion"."fulfilled" = TRUE) OR
|
jbe@532
|
2109 ("opinion"."degree" = -2 AND "opinion"."fulfilled" = FALSE)
|
jbe@532
|
2110 THEN 3 ELSE 4 END
|
jbe@532
|
2111 END
|
jbe@532
|
2112 END AS "preference",
|
jbe@532
|
2113 "opinion"."suggestion_id"
|
jbe@532
|
2114 FROM "opinion"
|
jbe@532
|
2115 JOIN "initiative" ON "initiative"."id" = "opinion"."initiative_id"
|
jbe@532
|
2116 JOIN "issue" ON "issue"."id" = "initiative"."issue_id"
|
jbe@532
|
2117 JOIN "direct_interest_snapshot"
|
jbe@532
|
2118 ON "direct_interest_snapshot"."snapshot_id" = "issue"."latest_snapshot_id"
|
jbe@532
|
2119 AND "direct_interest_snapshot"."issue_id" = "issue"."id"
|
jbe@532
|
2120 AND "direct_interest_snapshot"."member_id" = "opinion"."member_id";
|
jbe@532
|
2121
|
jbe@532
|
2122
|
jbe@532
|
2123 CREATE VIEW "expired_session" AS
|
jbe@532
|
2124 SELECT * FROM "session" WHERE now() > "expiry";
|
jbe@532
|
2125
|
jbe@532
|
2126 CREATE RULE "delete" AS ON DELETE TO "expired_session" DO INSTEAD
|
jbe@532
|
2127 DELETE FROM "session" WHERE "id" = OLD."id";
|
jbe@532
|
2128
|
jbe@532
|
2129 COMMENT ON VIEW "expired_session" IS 'View containing all expired sessions where DELETE is possible';
|
jbe@532
|
2130 COMMENT ON RULE "delete" ON "expired_session" IS 'Rule allowing DELETE on rows in "expired_session" view, i.e. DELETE FROM "expired_session"';
|
jbe@532
|
2131
|
jbe@532
|
2132
|
jbe@532
|
2133 CREATE VIEW "expired_token" AS
|
jbe@532
|
2134 SELECT * FROM "token" WHERE now() > "expiry" AND NOT (
|
jbe@532
|
2135 "token_type" = 'authorization' AND "used" AND EXISTS (
|
jbe@532
|
2136 SELECT NULL FROM "token" AS "other"
|
jbe@532
|
2137 WHERE "other"."authorization_token_id" = "id" ) );
|
jbe@532
|
2138
|
jbe@532
|
2139 CREATE RULE "delete" AS ON DELETE TO "expired_token" DO INSTEAD
|
jbe@532
|
2140 DELETE FROM "token" WHERE "id" = OLD."id";
|
jbe@532
|
2141
|
jbe@532
|
2142 COMMENT ON VIEW "expired_token" IS 'View containing all expired tokens where DELETE is possible; Note that used authorization codes must not be deleted if still referred to by other tokens';
|
jbe@532
|
2143
|
jbe@532
|
2144
|
jbe@532
|
2145 CREATE VIEW "unused_snapshot" AS
|
jbe@532
|
2146 SELECT "snapshot".* FROM "snapshot"
|
jbe@532
|
2147 LEFT JOIN "issue"
|
jbe@532
|
2148 ON "snapshot"."id" = "issue"."latest_snapshot_id"
|
jbe@532
|
2149 OR "snapshot"."id" = "issue"."admission_snapshot_id"
|
jbe@532
|
2150 OR "snapshot"."id" = "issue"."half_freeze_snapshot_id"
|
jbe@532
|
2151 OR "snapshot"."id" = "issue"."full_freeze_snapshot_id"
|
jbe@532
|
2152 WHERE "issue"."id" ISNULL;
|
jbe@532
|
2153
|
jbe@532
|
2154 CREATE RULE "delete" AS ON DELETE TO "unused_snapshot" DO INSTEAD
|
jbe@532
|
2155 DELETE FROM "snapshot" WHERE "id" = OLD."id";
|
jbe@532
|
2156
|
jbe@532
|
2157 COMMENT ON VIEW "unused_snapshot" IS 'Snapshots that are not referenced by any issue (either as latest snapshot or as snapshot at phase/state change)';
|
jbe@532
|
2158
|
jbe@532
|
2159
|
jbe@532
|
2160 CREATE VIEW "expired_snapshot" AS
|
jbe@532
|
2161 SELECT "unused_snapshot".* FROM "unused_snapshot" CROSS JOIN "system_setting"
|
jbe@532
|
2162 WHERE "unused_snapshot"."calculated" <
|
jbe@532
|
2163 now() - "system_setting"."snapshot_retention";
|
jbe@532
|
2164
|
jbe@532
|
2165 CREATE RULE "delete" AS ON DELETE TO "expired_snapshot" DO INSTEAD
|
jbe@532
|
2166 DELETE FROM "snapshot" WHERE "id" = OLD."id";
|
jbe@532
|
2167
|
jbe@532
|
2168 COMMENT ON VIEW "expired_snapshot" IS 'Contains "unused_snapshot"s that are older than "system_setting"."snapshot_retention" (for deletion)';
|
jbe@532
|
2169
|
jbe@532
|
2170
|
jbe@532
|
2171 COMMENT ON COLUMN "delegation_chain_row"."participation" IS 'In case of delegation chains for issues: interest; for area and global delegation chains: always null';
|
jbe@532
|
2172
|
jbe@532
|
2173
|
jbe@532
|
2174 CREATE OR REPLACE FUNCTION "delegation_chain"
|
jbe@532
|
2175 ( "member_id_p" "member"."id"%TYPE,
|
jbe@532
|
2176 "unit_id_p" "unit"."id"%TYPE,
|
jbe@532
|
2177 "area_id_p" "area"."id"%TYPE,
|
jbe@532
|
2178 "issue_id_p" "issue"."id"%TYPE,
|
jbe@532
|
2179 "simulate_trustee_id_p" "member"."id"%TYPE DEFAULT NULL,
|
jbe@532
|
2180 "simulate_default_p" BOOLEAN DEFAULT FALSE )
|
jbe@532
|
2181 RETURNS SETOF "delegation_chain_row"
|
jbe@532
|
2182 LANGUAGE 'plpgsql' STABLE AS $$
|
jbe@532
|
2183 DECLARE
|
jbe@532
|
2184 "scope_v" "delegation_scope";
|
jbe@532
|
2185 "unit_id_v" "unit"."id"%TYPE;
|
jbe@532
|
2186 "area_id_v" "area"."id"%TYPE;
|
jbe@532
|
2187 "issue_row" "issue"%ROWTYPE;
|
jbe@532
|
2188 "visited_member_ids" INT4[]; -- "member"."id"%TYPE[]
|
jbe@532
|
2189 "loop_member_id_v" "member"."id"%TYPE;
|
jbe@532
|
2190 "output_row" "delegation_chain_row";
|
jbe@532
|
2191 "output_rows" "delegation_chain_row"[];
|
jbe@532
|
2192 "simulate_v" BOOLEAN;
|
jbe@532
|
2193 "simulate_here_v" BOOLEAN;
|
jbe@532
|
2194 "delegation_row" "delegation"%ROWTYPE;
|
jbe@532
|
2195 "row_count" INT4;
|
jbe@532
|
2196 "i" INT4;
|
jbe@532
|
2197 "loop_v" BOOLEAN;
|
jbe@532
|
2198 BEGIN
|
jbe@532
|
2199 IF "simulate_trustee_id_p" NOTNULL AND "simulate_default_p" THEN
|
jbe@532
|
2200 RAISE EXCEPTION 'Both "simulate_trustee_id_p" is set, and "simulate_default_p" is true';
|
jbe@532
|
2201 END IF;
|
jbe@532
|
2202 IF "simulate_trustee_id_p" NOTNULL OR "simulate_default_p" THEN
|
jbe@532
|
2203 "simulate_v" := TRUE;
|
jbe@532
|
2204 ELSE
|
jbe@532
|
2205 "simulate_v" := FALSE;
|
jbe@532
|
2206 END IF;
|
jbe@532
|
2207 IF
|
jbe@532
|
2208 "unit_id_p" NOTNULL AND
|
jbe@532
|
2209 "area_id_p" ISNULL AND
|
jbe@532
|
2210 "issue_id_p" ISNULL
|
jbe@532
|
2211 THEN
|
jbe@532
|
2212 "scope_v" := 'unit';
|
jbe@532
|
2213 "unit_id_v" := "unit_id_p";
|
jbe@532
|
2214 ELSIF
|
jbe@532
|
2215 "unit_id_p" ISNULL AND
|
jbe@532
|
2216 "area_id_p" NOTNULL AND
|
jbe@532
|
2217 "issue_id_p" ISNULL
|
jbe@532
|
2218 THEN
|
jbe@532
|
2219 "scope_v" := 'area';
|
jbe@532
|
2220 "area_id_v" := "area_id_p";
|
jbe@532
|
2221 SELECT "unit_id" INTO "unit_id_v"
|
jbe@532
|
2222 FROM "area" WHERE "id" = "area_id_v";
|
jbe@532
|
2223 ELSIF
|
jbe@532
|
2224 "unit_id_p" ISNULL AND
|
jbe@532
|
2225 "area_id_p" ISNULL AND
|
jbe@532
|
2226 "issue_id_p" NOTNULL
|
jbe@532
|
2227 THEN
|
jbe@532
|
2228 SELECT INTO "issue_row" * FROM "issue" WHERE "id" = "issue_id_p";
|
jbe@532
|
2229 IF "issue_row"."id" ISNULL THEN
|
jbe@532
|
2230 RETURN;
|
jbe@532
|
2231 END IF;
|
jbe@532
|
2232 IF "issue_row"."closed" NOTNULL THEN
|
jbe@532
|
2233 IF "simulate_v" THEN
|
jbe@532
|
2234 RAISE EXCEPTION 'Tried to simulate delegation chain for closed issue.';
|
jbe@532
|
2235 END IF;
|
jbe@532
|
2236 FOR "output_row" IN
|
jbe@532
|
2237 SELECT * FROM
|
jbe@532
|
2238 "delegation_chain_for_closed_issue"("member_id_p", "issue_id_p")
|
jbe@532
|
2239 LOOP
|
jbe@532
|
2240 RETURN NEXT "output_row";
|
jbe@532
|
2241 END LOOP;
|
jbe@532
|
2242 RETURN;
|
jbe@532
|
2243 END IF;
|
jbe@532
|
2244 "scope_v" := 'issue';
|
jbe@532
|
2245 SELECT "area_id" INTO "area_id_v"
|
jbe@532
|
2246 FROM "issue" WHERE "id" = "issue_id_p";
|
jbe@532
|
2247 SELECT "unit_id" INTO "unit_id_v"
|
jbe@532
|
2248 FROM "area" WHERE "id" = "area_id_v";
|
jbe@532
|
2249 ELSE
|
jbe@532
|
2250 RAISE EXCEPTION 'Exactly one of unit_id_p, area_id_p, or issue_id_p must be NOTNULL.';
|
jbe@532
|
2251 END IF;
|
jbe@532
|
2252 "visited_member_ids" := '{}';
|
jbe@532
|
2253 "loop_member_id_v" := NULL;
|
jbe@532
|
2254 "output_rows" := '{}';
|
jbe@532
|
2255 "output_row"."index" := 0;
|
jbe@532
|
2256 "output_row"."member_id" := "member_id_p";
|
jbe@532
|
2257 "output_row"."member_valid" := TRUE;
|
jbe@532
|
2258 "output_row"."participation" := FALSE;
|
jbe@532
|
2259 "output_row"."overridden" := FALSE;
|
jbe@532
|
2260 "output_row"."disabled_out" := FALSE;
|
jbe@532
|
2261 "output_row"."scope_out" := NULL;
|
jbe@532
|
2262 LOOP
|
jbe@532
|
2263 IF "visited_member_ids" @> ARRAY["output_row"."member_id"] THEN
|
jbe@532
|
2264 "loop_member_id_v" := "output_row"."member_id";
|
jbe@532
|
2265 ELSE
|
jbe@532
|
2266 "visited_member_ids" :=
|
jbe@532
|
2267 "visited_member_ids" || "output_row"."member_id";
|
jbe@532
|
2268 END IF;
|
jbe@532
|
2269 IF "output_row"."participation" ISNULL THEN
|
jbe@532
|
2270 "output_row"."overridden" := NULL;
|
jbe@532
|
2271 ELSIF "output_row"."participation" THEN
|
jbe@532
|
2272 "output_row"."overridden" := TRUE;
|
jbe@532
|
2273 END IF;
|
jbe@532
|
2274 "output_row"."scope_in" := "output_row"."scope_out";
|
jbe@532
|
2275 "output_row"."member_valid" := EXISTS (
|
jbe@532
|
2276 SELECT NULL FROM "member" JOIN "privilege"
|
jbe@532
|
2277 ON "privilege"."member_id" = "member"."id"
|
jbe@532
|
2278 AND "privilege"."unit_id" = "unit_id_v"
|
jbe@532
|
2279 WHERE "id" = "output_row"."member_id"
|
jbe@532
|
2280 AND "member"."active" AND "privilege"."voting_right"
|
jbe@532
|
2281 );
|
jbe@532
|
2282 "simulate_here_v" := (
|
jbe@532
|
2283 "simulate_v" AND
|
jbe@532
|
2284 "output_row"."member_id" = "member_id_p"
|
jbe@532
|
2285 );
|
jbe@532
|
2286 "delegation_row" := ROW(NULL);
|
jbe@532
|
2287 IF "output_row"."member_valid" OR "simulate_here_v" THEN
|
jbe@532
|
2288 IF "scope_v" = 'unit' THEN
|
jbe@532
|
2289 IF NOT "simulate_here_v" THEN
|
jbe@532
|
2290 SELECT * INTO "delegation_row" FROM "delegation"
|
jbe@532
|
2291 WHERE "truster_id" = "output_row"."member_id"
|
jbe@532
|
2292 AND "unit_id" = "unit_id_v";
|
jbe@532
|
2293 END IF;
|
jbe@532
|
2294 ELSIF "scope_v" = 'area' THEN
|
jbe@532
|
2295 IF "simulate_here_v" THEN
|
jbe@532
|
2296 IF "simulate_trustee_id_p" ISNULL THEN
|
jbe@532
|
2297 SELECT * INTO "delegation_row" FROM "delegation"
|
jbe@532
|
2298 WHERE "truster_id" = "output_row"."member_id"
|
jbe@532
|
2299 AND "unit_id" = "unit_id_v";
|
jbe@532
|
2300 END IF;
|
jbe@532
|
2301 ELSE
|
jbe@532
|
2302 SELECT * INTO "delegation_row" FROM "delegation"
|
jbe@532
|
2303 WHERE "truster_id" = "output_row"."member_id"
|
jbe@532
|
2304 AND (
|
jbe@532
|
2305 "unit_id" = "unit_id_v" OR
|
jbe@532
|
2306 "area_id" = "area_id_v"
|
jbe@532
|
2307 )
|
jbe@532
|
2308 ORDER BY "scope" DESC;
|
jbe@532
|
2309 END IF;
|
jbe@532
|
2310 ELSIF "scope_v" = 'issue' THEN
|
jbe@532
|
2311 IF "issue_row"."fully_frozen" ISNULL THEN
|
jbe@532
|
2312 "output_row"."participation" := EXISTS (
|
jbe@532
|
2313 SELECT NULL FROM "interest"
|
jbe@532
|
2314 WHERE "issue_id" = "issue_id_p"
|
jbe@532
|
2315 AND "member_id" = "output_row"."member_id"
|
jbe@532
|
2316 );
|
jbe@532
|
2317 ELSE
|
jbe@532
|
2318 IF "output_row"."member_id" = "member_id_p" THEN
|
jbe@532
|
2319 "output_row"."participation" := EXISTS (
|
jbe@532
|
2320 SELECT NULL FROM "direct_voter"
|
jbe@532
|
2321 WHERE "issue_id" = "issue_id_p"
|
jbe@532
|
2322 AND "member_id" = "output_row"."member_id"
|
jbe@532
|
2323 );
|
jbe@532
|
2324 ELSE
|
jbe@532
|
2325 "output_row"."participation" := NULL;
|
jbe@532
|
2326 END IF;
|
jbe@532
|
2327 END IF;
|
jbe@532
|
2328 IF "simulate_here_v" THEN
|
jbe@532
|
2329 IF "simulate_trustee_id_p" ISNULL THEN
|
jbe@532
|
2330 SELECT * INTO "delegation_row" FROM "delegation"
|
jbe@532
|
2331 WHERE "truster_id" = "output_row"."member_id"
|
jbe@532
|
2332 AND (
|
jbe@532
|
2333 "unit_id" = "unit_id_v" OR
|
jbe@532
|
2334 "area_id" = "area_id_v"
|
jbe@532
|
2335 )
|
jbe@532
|
2336 ORDER BY "scope" DESC;
|
jbe@532
|
2337 END IF;
|
jbe@532
|
2338 ELSE
|
jbe@532
|
2339 SELECT * INTO "delegation_row" FROM "delegation"
|
jbe@532
|
2340 WHERE "truster_id" = "output_row"."member_id"
|
jbe@532
|
2341 AND (
|
jbe@532
|
2342 "unit_id" = "unit_id_v" OR
|
jbe@532
|
2343 "area_id" = "area_id_v" OR
|
jbe@532
|
2344 "issue_id" = "issue_id_p"
|
jbe@532
|
2345 )
|
jbe@532
|
2346 ORDER BY "scope" DESC;
|
jbe@532
|
2347 END IF;
|
jbe@532
|
2348 END IF;
|
jbe@532
|
2349 ELSE
|
jbe@532
|
2350 "output_row"."participation" := FALSE;
|
jbe@532
|
2351 END IF;
|
jbe@532
|
2352 IF "simulate_here_v" AND "simulate_trustee_id_p" NOTNULL THEN
|
jbe@532
|
2353 "output_row"."scope_out" := "scope_v";
|
jbe@532
|
2354 "output_rows" := "output_rows" || "output_row";
|
jbe@532
|
2355 "output_row"."member_id" := "simulate_trustee_id_p";
|
jbe@532
|
2356 ELSIF "delegation_row"."trustee_id" NOTNULL THEN
|
jbe@532
|
2357 "output_row"."scope_out" := "delegation_row"."scope";
|
jbe@532
|
2358 "output_rows" := "output_rows" || "output_row";
|
jbe@532
|
2359 "output_row"."member_id" := "delegation_row"."trustee_id";
|
jbe@532
|
2360 ELSIF "delegation_row"."scope" NOTNULL THEN
|
jbe@532
|
2361 "output_row"."scope_out" := "delegation_row"."scope";
|
jbe@532
|
2362 "output_row"."disabled_out" := TRUE;
|
jbe@532
|
2363 "output_rows" := "output_rows" || "output_row";
|
jbe@532
|
2364 EXIT;
|
jbe@532
|
2365 ELSE
|
jbe@532
|
2366 "output_row"."scope_out" := NULL;
|
jbe@532
|
2367 "output_rows" := "output_rows" || "output_row";
|
jbe@532
|
2368 EXIT;
|
jbe@532
|
2369 END IF;
|
jbe@532
|
2370 EXIT WHEN "loop_member_id_v" NOTNULL;
|
jbe@532
|
2371 "output_row"."index" := "output_row"."index" + 1;
|
jbe@532
|
2372 END LOOP;
|
jbe@532
|
2373 "row_count" := array_upper("output_rows", 1);
|
jbe@532
|
2374 "i" := 1;
|
jbe@532
|
2375 "loop_v" := FALSE;
|
jbe@532
|
2376 LOOP
|
jbe@532
|
2377 "output_row" := "output_rows"["i"];
|
jbe@532
|
2378 EXIT WHEN "output_row" ISNULL; -- NOTE: ISNULL and NOT ... NOTNULL produce different results!
|
jbe@532
|
2379 IF "loop_v" THEN
|
jbe@532
|
2380 IF "i" + 1 = "row_count" THEN
|
jbe@532
|
2381 "output_row"."loop" := 'last';
|
jbe@532
|
2382 ELSIF "i" = "row_count" THEN
|
jbe@532
|
2383 "output_row"."loop" := 'repetition';
|
jbe@532
|
2384 ELSE
|
jbe@532
|
2385 "output_row"."loop" := 'intermediate';
|
jbe@532
|
2386 END IF;
|
jbe@532
|
2387 ELSIF "output_row"."member_id" = "loop_member_id_v" THEN
|
jbe@532
|
2388 "output_row"."loop" := 'first';
|
jbe@532
|
2389 "loop_v" := TRUE;
|
jbe@532
|
2390 END IF;
|
jbe@532
|
2391 IF "scope_v" = 'unit' THEN
|
jbe@532
|
2392 "output_row"."participation" := NULL;
|
jbe@532
|
2393 END IF;
|
jbe@532
|
2394 RETURN NEXT "output_row";
|
jbe@532
|
2395 "i" := "i" + 1;
|
jbe@532
|
2396 END LOOP;
|
jbe@532
|
2397 RETURN;
|
jbe@532
|
2398 END;
|
jbe@532
|
2399 $$;
|
jbe@532
|
2400
|
jbe@532
|
2401
|
jbe@532
|
2402 CREATE OR REPLACE FUNCTION "get_initiatives_for_notification"
|
jbe@532
|
2403 ( "recipient_id_p" "member"."id"%TYPE )
|
jbe@532
|
2404 RETURNS SETOF "initiative_for_notification"
|
jbe@532
|
2405 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
2406 DECLARE
|
jbe@532
|
2407 "result_row" "initiative_for_notification"%ROWTYPE;
|
jbe@532
|
2408 "last_draft_id_v" "draft"."id"%TYPE;
|
jbe@532
|
2409 "last_suggestion_id_v" "suggestion"."id"%TYPE;
|
jbe@532
|
2410 BEGIN
|
jbe@532
|
2411 PERFORM "require_transaction_isolation"();
|
jbe@532
|
2412 PERFORM NULL FROM "member" WHERE "id" = "recipient_id_p" FOR UPDATE;
|
jbe@532
|
2413 FOR "result_row" IN
|
jbe@532
|
2414 SELECT * FROM "initiative_for_notification"
|
jbe@532
|
2415 WHERE "recipient_id" = "recipient_id_p"
|
jbe@532
|
2416 LOOP
|
jbe@532
|
2417 SELECT "id" INTO "last_draft_id_v" FROM "draft"
|
jbe@532
|
2418 WHERE "draft"."initiative_id" = "result_row"."initiative_id"
|
jbe@532
|
2419 ORDER BY "id" DESC LIMIT 1;
|
jbe@532
|
2420 SELECT "id" INTO "last_suggestion_id_v" FROM "suggestion"
|
jbe@532
|
2421 WHERE "suggestion"."initiative_id" = "result_row"."initiative_id"
|
jbe@532
|
2422 ORDER BY "id" DESC LIMIT 1;
|
jbe@532
|
2423 INSERT INTO "notification_initiative_sent"
|
jbe@532
|
2424 ("member_id", "initiative_id", "last_draft_id", "last_suggestion_id")
|
jbe@532
|
2425 VALUES (
|
jbe@532
|
2426 "recipient_id_p",
|
jbe@532
|
2427 "result_row"."initiative_id",
|
jbe@532
|
2428 "last_draft_id_v",
|
jbe@532
|
2429 "last_suggestion_id_v" )
|
jbe@532
|
2430 ON CONFLICT ("member_id", "initiative_id") DO UPDATE SET
|
jbe@532
|
2431 "last_draft_id" = "last_draft_id_v",
|
jbe@532
|
2432 "last_suggestion_id" = "last_suggestion_id_v";
|
jbe@532
|
2433 RETURN NEXT "result_row";
|
jbe@532
|
2434 END LOOP;
|
jbe@532
|
2435 DELETE FROM "notification_initiative_sent"
|
jbe@532
|
2436 USING "initiative", "issue"
|
jbe@532
|
2437 WHERE "notification_initiative_sent"."member_id" = "recipient_id_p"
|
jbe@532
|
2438 AND "initiative"."id" = "notification_initiative_sent"."initiative_id"
|
jbe@532
|
2439 AND "issue"."id" = "initiative"."issue_id"
|
jbe@532
|
2440 AND ( "issue"."closed" NOTNULL OR "issue"."fully_frozen" NOTNULL );
|
jbe@532
|
2441 UPDATE "member" SET
|
jbe@532
|
2442 "notification_counter" = "notification_counter" + 1,
|
jbe@532
|
2443 "notification_sent" = now()
|
jbe@532
|
2444 WHERE "id" = "recipient_id_p";
|
jbe@532
|
2445 RETURN;
|
jbe@532
|
2446 END;
|
jbe@532
|
2447 $$;
|
jbe@532
|
2448
|
jbe@532
|
2449
|
jbe@532
|
2450 CREATE OR REPLACE FUNCTION "calculate_member_counts"()
|
jbe@532
|
2451 RETURNS VOID
|
jbe@532
|
2452 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
2453 BEGIN
|
jbe@532
|
2454 PERFORM "require_transaction_isolation"();
|
jbe@532
|
2455 DELETE FROM "member_count";
|
jbe@532
|
2456 INSERT INTO "member_count" ("total_count")
|
jbe@532
|
2457 SELECT "total_count" FROM "member_count_view";
|
jbe@532
|
2458 UPDATE "unit" SET "member_count" = "view"."member_count"
|
jbe@532
|
2459 FROM "unit_member_count" AS "view"
|
jbe@532
|
2460 WHERE "view"."unit_id" = "unit"."id";
|
jbe@532
|
2461 RETURN;
|
jbe@532
|
2462 END;
|
jbe@532
|
2463 $$;
|
jbe@532
|
2464
|
jbe@532
|
2465 COMMENT ON FUNCTION "calculate_member_counts"() IS 'Updates "member_count" table and "member_count" column of table "area" by materializing data from views "member_count_view" and "unit_member_count"';
|
jbe@532
|
2466
|
jbe@532
|
2467
|
jbe@532
|
2468 CREATE FUNCTION "calculate_area_quorum"()
|
jbe@532
|
2469 RETURNS VOID
|
jbe@532
|
2470 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
2471 BEGIN
|
jbe@532
|
2472 PERFORM "dont_require_transaction_isolation"();
|
jbe@532
|
2473 UPDATE "area" SET "issue_quorum" = "view"."issue_quorum"
|
jbe@532
|
2474 FROM "area_quorum" AS "view"
|
jbe@532
|
2475 WHERE "view"."area_id" = "area"."id";
|
jbe@532
|
2476 RETURN;
|
jbe@532
|
2477 END;
|
jbe@532
|
2478 $$;
|
jbe@532
|
2479
|
jbe@532
|
2480 COMMENT ON FUNCTION "calculate_area_quorum"() IS 'Calculate column "issue_quorum" in table "area" from view "area_quorum"';
|
jbe@532
|
2481
|
jbe@532
|
2482
|
jbe@532
|
2483 DROP VIEW "remaining_harmonic_initiative_weight_summands";
|
jbe@532
|
2484 DROP VIEW "remaining_harmonic_supporter_weight";
|
jbe@532
|
2485
|
jbe@532
|
2486
|
jbe@532
|
2487 CREATE VIEW "remaining_harmonic_supporter_weight" AS
|
jbe@532
|
2488 SELECT
|
jbe@532
|
2489 "direct_interest_snapshot"."snapshot_id",
|
jbe@532
|
2490 "direct_interest_snapshot"."issue_id",
|
jbe@532
|
2491 "direct_interest_snapshot"."member_id",
|
jbe@532
|
2492 "direct_interest_snapshot"."weight" AS "weight_num",
|
jbe@532
|
2493 count("initiative"."id") AS "weight_den"
|
jbe@532
|
2494 FROM "issue"
|
jbe@532
|
2495 JOIN "direct_interest_snapshot"
|
jbe@532
|
2496 ON "issue"."latest_snapshot_id" = "direct_interest_snapshot"."snapshot_id"
|
jbe@532
|
2497 AND "issue"."id" = "direct_interest_snapshot"."issue_id"
|
jbe@532
|
2498 JOIN "initiative"
|
jbe@532
|
2499 ON "issue"."id" = "initiative"."issue_id"
|
jbe@532
|
2500 AND "initiative"."harmonic_weight" ISNULL
|
jbe@532
|
2501 JOIN "direct_supporter_snapshot"
|
jbe@532
|
2502 ON "issue"."latest_snapshot_id" = "direct_supporter_snapshot"."snapshot_id"
|
jbe@532
|
2503 AND "initiative"."id" = "direct_supporter_snapshot"."initiative_id"
|
jbe@532
|
2504 AND "direct_interest_snapshot"."member_id" = "direct_supporter_snapshot"."member_id"
|
jbe@532
|
2505 AND (
|
jbe@532
|
2506 "direct_supporter_snapshot"."satisfied" = TRUE OR
|
jbe@532
|
2507 coalesce("initiative"."admitted", FALSE) = FALSE
|
jbe@532
|
2508 )
|
jbe@532
|
2509 GROUP BY
|
jbe@532
|
2510 "direct_interest_snapshot"."snapshot_id",
|
jbe@532
|
2511 "direct_interest_snapshot"."issue_id",
|
jbe@532
|
2512 "direct_interest_snapshot"."member_id",
|
jbe@532
|
2513 "direct_interest_snapshot"."weight";
|
jbe@532
|
2514
|
jbe@532
|
2515
|
jbe@532
|
2516 CREATE VIEW "remaining_harmonic_initiative_weight_summands" AS
|
jbe@532
|
2517 SELECT
|
jbe@532
|
2518 "initiative"."issue_id",
|
jbe@532
|
2519 "initiative"."id" AS "initiative_id",
|
jbe@532
|
2520 "initiative"."admitted",
|
jbe@532
|
2521 sum("remaining_harmonic_supporter_weight"."weight_num") AS "weight_num",
|
jbe@532
|
2522 "remaining_harmonic_supporter_weight"."weight_den"
|
jbe@532
|
2523 FROM "remaining_harmonic_supporter_weight"
|
jbe@532
|
2524 JOIN "initiative"
|
jbe@532
|
2525 ON "remaining_harmonic_supporter_weight"."issue_id" = "initiative"."issue_id"
|
jbe@532
|
2526 AND "initiative"."harmonic_weight" ISNULL
|
jbe@532
|
2527 JOIN "direct_supporter_snapshot"
|
jbe@532
|
2528 ON "remaining_harmonic_supporter_weight"."snapshot_id" = "direct_supporter_snapshot"."snapshot_id"
|
jbe@532
|
2529 AND "initiative"."id" = "direct_supporter_snapshot"."initiative_id"
|
jbe@532
|
2530 AND "remaining_harmonic_supporter_weight"."member_id" = "direct_supporter_snapshot"."member_id"
|
jbe@532
|
2531 AND (
|
jbe@532
|
2532 "direct_supporter_snapshot"."satisfied" = TRUE OR
|
jbe@532
|
2533 coalesce("initiative"."admitted", FALSE) = FALSE
|
jbe@532
|
2534 )
|
jbe@532
|
2535 GROUP BY
|
jbe@532
|
2536 "initiative"."issue_id",
|
jbe@532
|
2537 "initiative"."id",
|
jbe@532
|
2538 "initiative"."admitted",
|
jbe@532
|
2539 "remaining_harmonic_supporter_weight"."weight_den";
|
jbe@532
|
2540
|
jbe@532
|
2541
|
jbe@532
|
2542 DROP FUNCTION "create_population_snapshot"
|
jbe@532
|
2543 ( "issue_id_p" "issue"."id"%TYPE );
|
jbe@532
|
2544
|
jbe@532
|
2545
|
jbe@532
|
2546 DROP FUNCTION "weight_of_added_delegations_for_population_snapshot"
|
jbe@532
|
2547 ( "issue_id_p" "issue"."id"%TYPE,
|
jbe@532
|
2548 "member_id_p" "member"."id"%TYPE,
|
jbe@532
|
2549 "delegate_member_ids_p" "delegating_population_snapshot"."delegate_member_ids"%TYPE );
|
jbe@532
|
2550
|
jbe@532
|
2551
|
jbe@532
|
2552 DROP FUNCTION "weight_of_added_delegations_for_interest_snapshot"
|
jbe@532
|
2553 ( "issue_id_p" "issue"."id"%TYPE,
|
jbe@532
|
2554 "member_id_p" "member"."id"%TYPE,
|
jbe@532
|
2555 "delegate_member_ids_p" "delegating_interest_snapshot"."delegate_member_ids"%TYPE );
|
jbe@532
|
2556
|
jbe@532
|
2557
|
jbe@532
|
2558 CREATE FUNCTION "weight_of_added_delegations_for_snapshot"
|
jbe@532
|
2559 ( "snapshot_id_p" "snapshot"."id"%TYPE,
|
jbe@532
|
2560 "issue_id_p" "issue"."id"%TYPE,
|
jbe@532
|
2561 "member_id_p" "member"."id"%TYPE,
|
jbe@532
|
2562 "delegate_member_ids_p" "delegating_interest_snapshot"."delegate_member_ids"%TYPE )
|
jbe@532
|
2563 RETURNS "direct_interest_snapshot"."weight"%TYPE
|
jbe@532
|
2564 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
2565 DECLARE
|
jbe@532
|
2566 "issue_delegation_row" "issue_delegation"%ROWTYPE;
|
jbe@532
|
2567 "delegate_member_ids_v" "delegating_interest_snapshot"."delegate_member_ids"%TYPE;
|
jbe@532
|
2568 "weight_v" INT4;
|
jbe@532
|
2569 "sub_weight_v" INT4;
|
jbe@532
|
2570 BEGIN
|
jbe@532
|
2571 PERFORM "require_transaction_isolation"();
|
jbe@532
|
2572 "weight_v" := 0;
|
jbe@532
|
2573 FOR "issue_delegation_row" IN
|
jbe@532
|
2574 SELECT * FROM "issue_delegation"
|
jbe@532
|
2575 WHERE "trustee_id" = "member_id_p"
|
jbe@532
|
2576 AND "issue_id" = "issue_id_p"
|
jbe@532
|
2577 LOOP
|
jbe@532
|
2578 IF NOT EXISTS (
|
jbe@532
|
2579 SELECT NULL FROM "direct_interest_snapshot"
|
jbe@532
|
2580 WHERE "snapshot_id" = "snapshot_id_p"
|
jbe@532
|
2581 AND "issue_id" = "issue_id_p"
|
jbe@532
|
2582 AND "member_id" = "issue_delegation_row"."truster_id"
|
jbe@532
|
2583 ) AND NOT EXISTS (
|
jbe@532
|
2584 SELECT NULL FROM "delegating_interest_snapshot"
|
jbe@532
|
2585 WHERE "snapshot_id" = "snapshot_id_p"
|
jbe@532
|
2586 AND "issue_id" = "issue_id_p"
|
jbe@532
|
2587 AND "member_id" = "issue_delegation_row"."truster_id"
|
jbe@532
|
2588 ) THEN
|
jbe@532
|
2589 "delegate_member_ids_v" :=
|
jbe@532
|
2590 "member_id_p" || "delegate_member_ids_p";
|
jbe@532
|
2591 INSERT INTO "delegating_interest_snapshot" (
|
jbe@532
|
2592 "snapshot_id",
|
jbe@532
|
2593 "issue_id",
|
jbe@532
|
2594 "member_id",
|
jbe@532
|
2595 "scope",
|
jbe@532
|
2596 "delegate_member_ids"
|
jbe@532
|
2597 ) VALUES (
|
jbe@532
|
2598 "snapshot_id_p",
|
jbe@532
|
2599 "issue_id_p",
|
jbe@532
|
2600 "issue_delegation_row"."truster_id",
|
jbe@532
|
2601 "issue_delegation_row"."scope",
|
jbe@532
|
2602 "delegate_member_ids_v"
|
jbe@532
|
2603 );
|
jbe@532
|
2604 "sub_weight_v" := 1 +
|
jbe@532
|
2605 "weight_of_added_delegations_for_snapshot"(
|
jbe@532
|
2606 "snapshot_id_p",
|
jbe@532
|
2607 "issue_id_p",
|
jbe@532
|
2608 "issue_delegation_row"."truster_id",
|
jbe@532
|
2609 "delegate_member_ids_v"
|
jbe@532
|
2610 );
|
jbe@532
|
2611 UPDATE "delegating_interest_snapshot"
|
jbe@532
|
2612 SET "weight" = "sub_weight_v"
|
jbe@532
|
2613 WHERE "snapshot_id" = "snapshot_id_p"
|
jbe@532
|
2614 AND "issue_id" = "issue_id_p"
|
jbe@532
|
2615 AND "member_id" = "issue_delegation_row"."truster_id";
|
jbe@532
|
2616 "weight_v" := "weight_v" + "sub_weight_v";
|
jbe@532
|
2617 END IF;
|
jbe@532
|
2618 END LOOP;
|
jbe@532
|
2619 RETURN "weight_v";
|
jbe@532
|
2620 END;
|
jbe@532
|
2621 $$;
|
jbe@532
|
2622
|
jbe@532
|
2623 COMMENT ON FUNCTION "weight_of_added_delegations_for_snapshot"
|
jbe@532
|
2624 ( "snapshot"."id"%TYPE,
|
jbe@532
|
2625 "issue"."id"%TYPE,
|
jbe@532
|
2626 "member"."id"%TYPE,
|
jbe@532
|
2627 "delegating_interest_snapshot"."delegate_member_ids"%TYPE )
|
jbe@532
|
2628 IS 'Helper function for "fill_snapshot" function';
|
jbe@532
|
2629
|
jbe@532
|
2630
|
jbe@532
|
2631 DROP FUNCTION "create_interest_snapshot"
|
jbe@532
|
2632 ( "issue_id_p" "issue"."id"%TYPE );
|
jbe@532
|
2633
|
jbe@532
|
2634
|
jbe@532
|
2635 DROP FUNCTION "create_snapshot"
|
jbe@532
|
2636 ( "issue_id_p" "issue"."id"%TYPE );
|
jbe@532
|
2637
|
jbe@532
|
2638
|
jbe@532
|
2639 CREATE FUNCTION "take_snapshot"
|
jbe@532
|
2640 ( "issue_id_p" "issue"."id"%TYPE,
|
jbe@532
|
2641 "area_id_p" "area"."id"%TYPE = NULL )
|
jbe@532
|
2642 RETURNS "snapshot"."id"%TYPE
|
jbe@532
|
2643 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
2644 DECLARE
|
jbe@532
|
2645 "area_id_v" "area"."id"%TYPE;
|
jbe@532
|
2646 "unit_id_v" "unit"."id"%TYPE;
|
jbe@532
|
2647 "snapshot_id_v" "snapshot"."id"%TYPE;
|
jbe@532
|
2648 "issue_id_v" "issue"."id"%TYPE;
|
jbe@532
|
2649 "member_id_v" "member"."id"%TYPE;
|
jbe@532
|
2650 BEGIN
|
jbe@532
|
2651 IF "issue_id_p" NOTNULL AND "area_id_p" NOTNULL THEN
|
jbe@532
|
2652 RAISE EXCEPTION 'One of "issue_id_p" and "area_id_p" must be NULL';
|
jbe@532
|
2653 END IF;
|
jbe@532
|
2654 PERFORM "require_transaction_isolation"();
|
jbe@532
|
2655 IF "issue_id_p" ISNULL THEN
|
jbe@532
|
2656 "area_id_v" := "area_id_p";
|
jbe@532
|
2657 ELSE
|
jbe@532
|
2658 SELECT "area_id" INTO "area_id_v"
|
jbe@532
|
2659 FROM "issue" WHERE "id" = "issue_id_p";
|
jbe@532
|
2660 END IF;
|
jbe@532
|
2661 SELECT "unit_id" INTO "unit_id_v" FROM "area" WHERE "id" = "area_id_p";
|
jbe@532
|
2662 INSERT INTO "snapshot" ("area_id", "issue_id")
|
jbe@532
|
2663 VALUES ("area_id_v", "issue_id_p")
|
jbe@532
|
2664 RETURNING "id" INTO "snapshot_id_v";
|
jbe@532
|
2665 INSERT INTO "snapshot_population" ("snapshot_id", "member_id")
|
jbe@532
|
2666 SELECT "snapshot_id_v", "member_id"
|
jbe@532
|
2667 FROM "unit_member" WHERE "unit_id" = "unit_id_v";
|
jbe@532
|
2668 UPDATE "snapshot" SET
|
jbe@532
|
2669 "population" = (
|
jbe@532
|
2670 SELECT count(1) FROM "snapshot_population"
|
jbe@532
|
2671 WHERE "snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2672 ) WHERE "id" = "snapshot_id_v";
|
jbe@532
|
2673 FOR "issue_id_v" IN
|
jbe@532
|
2674 SELECT "id" FROM "issue"
|
jbe@532
|
2675 WHERE CASE WHEN "issue_id_p" ISNULL THEN
|
jbe@532
|
2676 "area_id" = "area_id_p" AND
|
jbe@532
|
2677 "state" = 'admission'
|
jbe@532
|
2678 ELSE
|
jbe@532
|
2679 "id" = "issue_id_p"
|
jbe@532
|
2680 END
|
jbe@532
|
2681 LOOP
|
jbe@532
|
2682 INSERT INTO "snapshot_issue" ("snapshot_id", "issue_id")
|
jbe@532
|
2683 VALUES ("snapshot_id_v", "issue_id_v");
|
jbe@532
|
2684 INSERT INTO "direct_interest_snapshot"
|
jbe@532
|
2685 ("snapshot_id", "issue_id", "member_id")
|
jbe@532
|
2686 SELECT
|
jbe@532
|
2687 "snapshot_id_v" AS "snapshot_id",
|
jbe@532
|
2688 "issue_id_v" AS "issue_id",
|
jbe@532
|
2689 "member"."id" AS "member_id"
|
jbe@532
|
2690 FROM "issue"
|
jbe@532
|
2691 JOIN "area" ON "issue"."area_id" = "area"."id"
|
jbe@532
|
2692 JOIN "interest" ON "issue"."id" = "interest"."issue_id"
|
jbe@532
|
2693 JOIN "member" ON "interest"."member_id" = "member"."id"
|
jbe@532
|
2694 JOIN "privilege"
|
jbe@532
|
2695 ON "privilege"."unit_id" = "area"."unit_id"
|
jbe@532
|
2696 AND "privilege"."member_id" = "member"."id"
|
jbe@532
|
2697 WHERE "issue"."id" = "issue_id_v"
|
jbe@532
|
2698 AND "member"."active" AND "privilege"."voting_right";
|
jbe@532
|
2699 FOR "member_id_v" IN
|
jbe@532
|
2700 SELECT "member_id" FROM "direct_interest_snapshot"
|
jbe@532
|
2701 WHERE "snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2702 AND "issue_id" = "issue_id_v"
|
jbe@532
|
2703 LOOP
|
jbe@532
|
2704 UPDATE "direct_interest_snapshot" SET
|
jbe@532
|
2705 "weight" = 1 +
|
jbe@532
|
2706 "weight_of_added_delegations_for_snapshot"(
|
jbe@532
|
2707 "snapshot_id_v",
|
jbe@532
|
2708 "issue_id_v",
|
jbe@532
|
2709 "member_id_v",
|
jbe@532
|
2710 '{}'
|
jbe@532
|
2711 )
|
jbe@532
|
2712 WHERE "snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2713 AND "issue_id" = "issue_id_v"
|
jbe@532
|
2714 AND "member_id" = "member_id_v";
|
jbe@532
|
2715 END LOOP;
|
jbe@532
|
2716 INSERT INTO "direct_supporter_snapshot"
|
jbe@532
|
2717 ( "snapshot_id", "issue_id", "initiative_id", "member_id",
|
jbe@532
|
2718 "draft_id", "informed", "satisfied" )
|
jbe@532
|
2719 SELECT
|
jbe@532
|
2720 "snapshot_id_v" AS "snapshot_id",
|
jbe@532
|
2721 "issue_id_v" AS "issue_id",
|
jbe@532
|
2722 "initiative"."id" AS "initiative_id",
|
jbe@532
|
2723 "supporter"."member_id" AS "member_id",
|
jbe@532
|
2724 "supporter"."draft_id" AS "draft_id",
|
jbe@532
|
2725 "supporter"."draft_id" = "current_draft"."id" AS "informed",
|
jbe@532
|
2726 NOT EXISTS (
|
jbe@532
|
2727 SELECT NULL FROM "critical_opinion"
|
jbe@532
|
2728 WHERE "initiative_id" = "initiative"."id"
|
jbe@532
|
2729 AND "member_id" = "supporter"."member_id"
|
jbe@532
|
2730 ) AS "satisfied"
|
jbe@532
|
2731 FROM "initiative"
|
jbe@532
|
2732 JOIN "supporter"
|
jbe@532
|
2733 ON "supporter"."initiative_id" = "initiative"."id"
|
jbe@532
|
2734 JOIN "current_draft"
|
jbe@532
|
2735 ON "initiative"."id" = "current_draft"."initiative_id"
|
jbe@532
|
2736 JOIN "direct_interest_snapshot"
|
jbe@532
|
2737 ON "snapshot_id_v" = "direct_interest_snapshot"."snapshot_id"
|
jbe@532
|
2738 AND "supporter"."member_id" = "direct_interest_snapshot"."member_id"
|
jbe@532
|
2739 AND "initiative"."issue_id" = "direct_interest_snapshot"."issue_id"
|
jbe@532
|
2740 WHERE "initiative"."issue_id" = "issue_id_v";
|
jbe@532
|
2741 DELETE FROM "temporary_suggestion_counts";
|
jbe@532
|
2742 INSERT INTO "temporary_suggestion_counts"
|
jbe@532
|
2743 ( "id",
|
jbe@532
|
2744 "minus2_unfulfilled_count", "minus2_fulfilled_count",
|
jbe@532
|
2745 "minus1_unfulfilled_count", "minus1_fulfilled_count",
|
jbe@532
|
2746 "plus1_unfulfilled_count", "plus1_fulfilled_count",
|
jbe@532
|
2747 "plus2_unfulfilled_count", "plus2_fulfilled_count" )
|
jbe@532
|
2748 SELECT
|
jbe@532
|
2749 "suggestion"."id",
|
jbe@532
|
2750 ( SELECT coalesce(sum("di"."weight"), 0)
|
jbe@532
|
2751 FROM "opinion" JOIN "direct_interest_snapshot" AS "di"
|
jbe@532
|
2752 ON "di"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2753 AND "di"."issue_id" = "issue_id_v"
|
jbe@532
|
2754 AND "di"."member_id" = "opinion"."member_id"
|
jbe@532
|
2755 WHERE "opinion"."suggestion_id" = "suggestion"."id"
|
jbe@532
|
2756 AND "opinion"."degree" = -2
|
jbe@532
|
2757 AND "opinion"."fulfilled" = FALSE
|
jbe@532
|
2758 ) AS "minus2_unfulfilled_count",
|
jbe@532
|
2759 ( SELECT coalesce(sum("di"."weight"), 0)
|
jbe@532
|
2760 FROM "opinion" JOIN "direct_interest_snapshot" AS "di"
|
jbe@532
|
2761 ON "di"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2762 AND "di"."issue_id" = "issue_id_v"
|
jbe@532
|
2763 AND "di"."member_id" = "opinion"."member_id"
|
jbe@532
|
2764 WHERE "opinion"."suggestion_id" = "suggestion"."id"
|
jbe@532
|
2765 AND "opinion"."degree" = -2
|
jbe@532
|
2766 AND "opinion"."fulfilled" = TRUE
|
jbe@532
|
2767 ) AS "minus2_fulfilled_count",
|
jbe@532
|
2768 ( SELECT coalesce(sum("di"."weight"), 0)
|
jbe@532
|
2769 FROM "opinion" JOIN "direct_interest_snapshot" AS "di"
|
jbe@532
|
2770 ON "di"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2771 AND "di"."issue_id" = "issue_id_v"
|
jbe@532
|
2772 AND "di"."member_id" = "opinion"."member_id"
|
jbe@532
|
2773 WHERE "opinion"."suggestion_id" = "suggestion"."id"
|
jbe@532
|
2774 AND "opinion"."degree" = -1
|
jbe@532
|
2775 AND "opinion"."fulfilled" = FALSE
|
jbe@532
|
2776 ) AS "minus1_unfulfilled_count",
|
jbe@532
|
2777 ( SELECT coalesce(sum("di"."weight"), 0)
|
jbe@532
|
2778 FROM "opinion" JOIN "direct_interest_snapshot" AS "di"
|
jbe@532
|
2779 ON "di"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2780 AND "di"."issue_id" = "issue_id_v"
|
jbe@532
|
2781 AND "di"."member_id" = "opinion"."member_id"
|
jbe@532
|
2782 WHERE "opinion"."suggestion_id" = "suggestion"."id"
|
jbe@532
|
2783 AND "opinion"."degree" = -1
|
jbe@532
|
2784 AND "opinion"."fulfilled" = TRUE
|
jbe@532
|
2785 ) AS "minus1_fulfilled_count",
|
jbe@532
|
2786 ( SELECT coalesce(sum("di"."weight"), 0)
|
jbe@532
|
2787 FROM "opinion" JOIN "direct_interest_snapshot" AS "di"
|
jbe@532
|
2788 ON "di"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2789 AND "di"."issue_id" = "issue_id_v"
|
jbe@532
|
2790 AND "di"."member_id" = "opinion"."member_id"
|
jbe@532
|
2791 WHERE "opinion"."suggestion_id" = "suggestion"."id"
|
jbe@532
|
2792 AND "opinion"."degree" = 1
|
jbe@532
|
2793 AND "opinion"."fulfilled" = FALSE
|
jbe@532
|
2794 ) AS "plus1_unfulfilled_count",
|
jbe@532
|
2795 ( SELECT coalesce(sum("di"."weight"), 0)
|
jbe@532
|
2796 FROM "opinion" JOIN "direct_interest_snapshot" AS "di"
|
jbe@532
|
2797 ON "di"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2798 AND "di"."issue_id" = "issue_id_v"
|
jbe@532
|
2799 AND "di"."member_id" = "opinion"."member_id"
|
jbe@532
|
2800 WHERE "opinion"."suggestion_id" = "suggestion"."id"
|
jbe@532
|
2801 AND "opinion"."degree" = 1
|
jbe@532
|
2802 AND "opinion"."fulfilled" = TRUE
|
jbe@532
|
2803 ) AS "plus1_fulfilled_count",
|
jbe@532
|
2804 ( SELECT coalesce(sum("di"."weight"), 0)
|
jbe@532
|
2805 FROM "opinion" JOIN "direct_interest_snapshot" AS "di"
|
jbe@532
|
2806 ON "di"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2807 AND "di"."issue_id" = "issue_id_v"
|
jbe@532
|
2808 AND "di"."member_id" = "opinion"."member_id"
|
jbe@532
|
2809 WHERE "opinion"."suggestion_id" = "suggestion"."id"
|
jbe@532
|
2810 AND "opinion"."degree" = 2
|
jbe@532
|
2811 AND "opinion"."fulfilled" = FALSE
|
jbe@532
|
2812 ) AS "plus2_unfulfilled_count",
|
jbe@532
|
2813 ( SELECT coalesce(sum("di"."weight"), 0)
|
jbe@532
|
2814 FROM "opinion" JOIN "direct_interest_snapshot" AS "di"
|
jbe@532
|
2815 ON "di"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2816 AND "di"."issue_id" = "issue_id_v"
|
jbe@532
|
2817 AND "di"."member_id" = "opinion"."member_id"
|
jbe@532
|
2818 WHERE "opinion"."suggestion_id" = "suggestion"."id"
|
jbe@532
|
2819 AND "opinion"."degree" = 2
|
jbe@532
|
2820 AND "opinion"."fulfilled" = TRUE
|
jbe@532
|
2821 ) AS "plus2_fulfilled_count"
|
jbe@532
|
2822 FROM "suggestion" JOIN "initiative"
|
jbe@532
|
2823 ON "suggestion"."initiative_id" = "initiative"."id"
|
jbe@532
|
2824 WHERE "initiative"."issue_id" = "issue_id_v";
|
jbe@532
|
2825 END LOOP;
|
jbe@532
|
2826 RETURN "snapshot_id_v";
|
jbe@532
|
2827 END;
|
jbe@532
|
2828 $$;
|
jbe@532
|
2829
|
jbe@532
|
2830 COMMENT ON FUNCTION "take_snapshot"
|
jbe@532
|
2831 ( "issue"."id"%TYPE,
|
jbe@532
|
2832 "area"."id"%TYPE )
|
jbe@532
|
2833 IS 'This function creates a new interest/supporter snapshot of a particular issue, or, if the first argument is NULL, for all issues in ''admission'' phase of the area given as second argument. It must be executed with TRANSACTION ISOLATION LEVEL REPEATABLE READ. The snapshot must later be finished by calling "finish_snapshot" for every issue.';
|
jbe@532
|
2834
|
jbe@532
|
2835
|
jbe@532
|
2836 DROP FUNCTION "set_snapshot_event"
|
jbe@532
|
2837 ( "issue_id_p" "issue"."id"%TYPE,
|
jbe@532
|
2838 "event_p" "snapshot_event" );
|
jbe@532
|
2839
|
jbe@532
|
2840
|
jbe@532
|
2841 CREATE FUNCTION "finish_snapshot"
|
jbe@532
|
2842 ( "issue_id_p" "issue"."id"%TYPE )
|
jbe@532
|
2843 RETURNS VOID
|
jbe@532
|
2844 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
2845 DECLARE
|
jbe@532
|
2846 "snapshot_id_v" "snapshot"."id"%TYPE;
|
jbe@532
|
2847 BEGIN
|
jbe@532
|
2848 -- NOTE: function does not require snapshot isolation but we don't call
|
jbe@532
|
2849 -- "dont_require_snapshot_isolation" here because this function is
|
jbe@532
|
2850 -- also invoked by "check_issue"
|
jbe@532
|
2851 LOCK TABLE "snapshot" IN EXCLUSIVE MODE;
|
jbe@532
|
2852 SELECT "id" INTO "snapshot_id_v" FROM "snapshot"
|
jbe@532
|
2853 ORDER BY "id" DESC LIMIT 1;
|
jbe@532
|
2854 UPDATE "issue" SET
|
jbe@532
|
2855 "calculated" = "snapshot"."calculated",
|
jbe@532
|
2856 "latest_snapshot_id" = "snapshot_id_v",
|
jbe@532
|
2857 "population" = "snapshot"."population"
|
jbe@532
|
2858 FROM "snapshot"
|
jbe@532
|
2859 WHERE "issue"."id" = "issue_id_p"
|
jbe@532
|
2860 AND "snapshot"."id" = "snapshot_id_v";
|
jbe@532
|
2861 UPDATE "initiative" SET
|
jbe@532
|
2862 "supporter_count" = (
|
jbe@532
|
2863 SELECT coalesce(sum("di"."weight"), 0)
|
jbe@532
|
2864 FROM "direct_interest_snapshot" AS "di"
|
jbe@532
|
2865 JOIN "direct_supporter_snapshot" AS "ds"
|
jbe@532
|
2866 ON "di"."member_id" = "ds"."member_id"
|
jbe@532
|
2867 WHERE "di"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2868 AND "di"."issue_id" = "issue_id_p"
|
jbe@532
|
2869 AND "ds"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2870 AND "ds"."initiative_id" = "initiative"."id"
|
jbe@532
|
2871 ),
|
jbe@532
|
2872 "informed_supporter_count" = (
|
jbe@532
|
2873 SELECT coalesce(sum("di"."weight"), 0)
|
jbe@532
|
2874 FROM "direct_interest_snapshot" AS "di"
|
jbe@532
|
2875 JOIN "direct_supporter_snapshot" AS "ds"
|
jbe@532
|
2876 ON "di"."member_id" = "ds"."member_id"
|
jbe@532
|
2877 WHERE "di"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2878 AND "di"."issue_id" = "issue_id_p"
|
jbe@532
|
2879 AND "ds"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2880 AND "ds"."initiative_id" = "initiative"."id"
|
jbe@532
|
2881 AND "ds"."informed"
|
jbe@532
|
2882 ),
|
jbe@532
|
2883 "satisfied_supporter_count" = (
|
jbe@532
|
2884 SELECT coalesce(sum("di"."weight"), 0)
|
jbe@532
|
2885 FROM "direct_interest_snapshot" AS "di"
|
jbe@532
|
2886 JOIN "direct_supporter_snapshot" AS "ds"
|
jbe@532
|
2887 ON "di"."member_id" = "ds"."member_id"
|
jbe@532
|
2888 WHERE "di"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2889 AND "di"."issue_id" = "issue_id_p"
|
jbe@532
|
2890 AND "ds"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2891 AND "ds"."initiative_id" = "initiative"."id"
|
jbe@532
|
2892 AND "ds"."satisfied"
|
jbe@532
|
2893 ),
|
jbe@532
|
2894 "satisfied_informed_supporter_count" = (
|
jbe@532
|
2895 SELECT coalesce(sum("di"."weight"), 0)
|
jbe@532
|
2896 FROM "direct_interest_snapshot" AS "di"
|
jbe@532
|
2897 JOIN "direct_supporter_snapshot" AS "ds"
|
jbe@532
|
2898 ON "di"."member_id" = "ds"."member_id"
|
jbe@532
|
2899 WHERE "di"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2900 AND "di"."issue_id" = "issue_id_p"
|
jbe@532
|
2901 AND "ds"."snapshot_id" = "snapshot_id_v"
|
jbe@532
|
2902 AND "ds"."initiative_id" = "initiative"."id"
|
jbe@532
|
2903 AND "ds"."informed"
|
jbe@532
|
2904 AND "ds"."satisfied"
|
jbe@532
|
2905 )
|
jbe@532
|
2906 WHERE "issue_id" = "issue_id_p";
|
jbe@532
|
2907 UPDATE "suggestion" SET
|
jbe@532
|
2908 "minus2_unfulfilled_count" = "temp"."minus2_unfulfilled_count",
|
jbe@532
|
2909 "minus2_fulfilled_count" = "temp"."minus2_fulfilled_count",
|
jbe@532
|
2910 "minus1_unfulfilled_count" = "temp"."minus1_unfulfilled_count",
|
jbe@532
|
2911 "minus1_fulfilled_count" = "temp"."minus1_fulfilled_count",
|
jbe@532
|
2912 "plus1_unfulfilled_count" = "temp"."plus1_unfulfilled_count",
|
jbe@532
|
2913 "plus1_fulfilled_count" = "temp"."plus1_fulfilled_count",
|
jbe@532
|
2914 "plus2_unfulfilled_count" = "temp"."plus2_unfulfilled_count",
|
jbe@532
|
2915 "plus2_fulfilled_count" = "temp"."plus2_fulfilled_count"
|
jbe@532
|
2916 FROM "temporary_suggestion_counts" AS "temp", "initiative"
|
jbe@532
|
2917 WHERE "temp"."id" = "suggestion"."id"
|
jbe@532
|
2918 AND "initiative"."issue_id" = "issue_id_p"
|
jbe@532
|
2919 AND "suggestion"."initiative_id" = "initiative"."id";
|
jbe@532
|
2920 DELETE FROM "temporary_suggestion_counts";
|
jbe@532
|
2921 RETURN;
|
jbe@532
|
2922 END;
|
jbe@532
|
2923 $$;
|
jbe@532
|
2924
|
jbe@532
|
2925 COMMENT ON FUNCTION "finish_snapshot"
|
jbe@532
|
2926 ( "issue"."id"%TYPE )
|
jbe@532
|
2927 IS 'After calling "take_snapshot", this function "finish_snapshot" needs to be called for every issue in the snapshot (separate function calls keep locking time minimal)';
|
jbe@532
|
2928
|
jbe@532
|
2929
|
jbe@532
|
2930 CREATE FUNCTION "issue_admission"
|
jbe@532
|
2931 ( "area_id_p" "area"."id"%TYPE )
|
jbe@532
|
2932 RETURNS BOOLEAN
|
jbe@532
|
2933 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
2934 DECLARE
|
jbe@532
|
2935 "issue_id_v" "issue"."id"%TYPE;
|
jbe@532
|
2936 BEGIN
|
jbe@532
|
2937 PERFORM "dont_require_transaction_isolation"();
|
jbe@532
|
2938 LOCK TABLE "snapshot" IN EXCLUSIVE MODE;
|
jbe@532
|
2939 UPDATE "area" SET "issue_quorum" = "view"."issue_quorum"
|
jbe@532
|
2940 FROM "area_quorum" AS "view"
|
jbe@532
|
2941 WHERE "area"."id" = "view"."area_id"
|
jbe@532
|
2942 AND "area"."id" = "area_id_p";
|
jbe@532
|
2943 SELECT "id" INTO "issue_id_v" FROM "issue_for_admission"
|
jbe@532
|
2944 WHERE "area_id" = "area_id_p";
|
jbe@532
|
2945 IF "issue_id_v" ISNULL THEN RETURN FALSE; END IF;
|
jbe@532
|
2946 UPDATE "issue" SET
|
jbe@532
|
2947 "admission_snapshot_id" = "latest_snapshot_id",
|
jbe@532
|
2948 "state" = 'discussion',
|
jbe@532
|
2949 "accepted" = now(),
|
jbe@532
|
2950 "phase_finished" = NULL
|
jbe@532
|
2951 WHERE "id" = "issue_id_v";
|
jbe@532
|
2952 RETURN TRUE;
|
jbe@532
|
2953 END;
|
jbe@532
|
2954 $$;
|
jbe@532
|
2955
|
jbe@532
|
2956 COMMENT ON FUNCTION "issue_admission"
|
jbe@532
|
2957 ( "area"."id"%TYPE )
|
jbe@532
|
2958 IS 'Checks if an issue in the area can be admitted for further discussion; returns TRUE on success in which case the function must be called again until it returns FALSE';
|
jbe@532
|
2959
|
jbe@532
|
2960
|
jbe@532
|
2961 CREATE OR REPLACE FUNCTION "check_issue"
|
jbe@532
|
2962 ( "issue_id_p" "issue"."id"%TYPE,
|
jbe@532
|
2963 "persist" "check_issue_persistence" )
|
jbe@532
|
2964 RETURNS "check_issue_persistence"
|
jbe@532
|
2965 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
2966 DECLARE
|
jbe@532
|
2967 "issue_row" "issue"%ROWTYPE;
|
jbe@532
|
2968 "last_calculated_v" "snapshot"."calculated"%TYPE;
|
jbe@532
|
2969 "policy_row" "policy"%ROWTYPE;
|
jbe@532
|
2970 "initiative_row" "initiative"%ROWTYPE;
|
jbe@532
|
2971 "state_v" "issue_state";
|
jbe@532
|
2972 BEGIN
|
jbe@532
|
2973 PERFORM "require_transaction_isolation"();
|
jbe@532
|
2974 IF "persist" ISNULL THEN
|
jbe@532
|
2975 SELECT * INTO "issue_row" FROM "issue" WHERE "id" = "issue_id_p"
|
jbe@532
|
2976 FOR UPDATE;
|
jbe@532
|
2977 SELECT "calculated" INTO "last_calculated_v"
|
jbe@532
|
2978 FROM "snapshot" JOIN "snapshot_issue"
|
jbe@532
|
2979 ON "snapshot"."id" = "snapshot_issue"."snapshot_id"
|
jbe@532
|
2980 WHERE "snapshot_issue"."issue_id" = "issue_id_p";
|
jbe@532
|
2981 IF "issue_row"."closed" NOTNULL THEN
|
jbe@532
|
2982 RETURN NULL;
|
jbe@532
|
2983 END IF;
|
jbe@532
|
2984 "persist"."state" := "issue_row"."state";
|
jbe@532
|
2985 IF
|
jbe@532
|
2986 ( "issue_row"."state" = 'admission' AND "last_calculated_v" >=
|
jbe@532
|
2987 "issue_row"."created" + "issue_row"."max_admission_time" ) OR
|
jbe@532
|
2988 ( "issue_row"."state" = 'discussion' AND now() >=
|
jbe@532
|
2989 "issue_row"."accepted" + "issue_row"."discussion_time" ) OR
|
jbe@532
|
2990 ( "issue_row"."state" = 'verification' AND now() >=
|
jbe@532
|
2991 "issue_row"."half_frozen" + "issue_row"."verification_time" ) OR
|
jbe@532
|
2992 ( "issue_row"."state" = 'voting' AND now() >=
|
jbe@532
|
2993 "issue_row"."fully_frozen" + "issue_row"."voting_time" )
|
jbe@532
|
2994 THEN
|
jbe@532
|
2995 "persist"."phase_finished" := TRUE;
|
jbe@532
|
2996 ELSE
|
jbe@532
|
2997 "persist"."phase_finished" := FALSE;
|
jbe@532
|
2998 END IF;
|
jbe@532
|
2999 IF
|
jbe@532
|
3000 NOT EXISTS (
|
jbe@532
|
3001 -- all initiatives are revoked
|
jbe@532
|
3002 SELECT NULL FROM "initiative"
|
jbe@532
|
3003 WHERE "issue_id" = "issue_id_p" AND "revoked" ISNULL
|
jbe@532
|
3004 ) AND (
|
jbe@532
|
3005 -- and issue has not been accepted yet
|
jbe@532
|
3006 "persist"."state" = 'admission' OR
|
jbe@532
|
3007 -- or verification time has elapsed
|
jbe@532
|
3008 ( "persist"."state" = 'verification' AND
|
jbe@532
|
3009 "persist"."phase_finished" ) OR
|
jbe@532
|
3010 -- or no initiatives have been revoked lately
|
jbe@532
|
3011 NOT EXISTS (
|
jbe@532
|
3012 SELECT NULL FROM "initiative"
|
jbe@532
|
3013 WHERE "issue_id" = "issue_id_p"
|
jbe@532
|
3014 AND now() < "revoked" + "issue_row"."verification_time"
|
jbe@532
|
3015 )
|
jbe@532
|
3016 )
|
jbe@532
|
3017 THEN
|
jbe@532
|
3018 "persist"."issue_revoked" := TRUE;
|
jbe@532
|
3019 ELSE
|
jbe@532
|
3020 "persist"."issue_revoked" := FALSE;
|
jbe@532
|
3021 END IF;
|
jbe@532
|
3022 IF "persist"."phase_finished" OR "persist"."issue_revoked" THEN
|
jbe@532
|
3023 UPDATE "issue" SET "phase_finished" = now()
|
jbe@532
|
3024 WHERE "id" = "issue_row"."id";
|
jbe@532
|
3025 RETURN "persist";
|
jbe@532
|
3026 ELSIF
|
jbe@532
|
3027 "persist"."state" IN ('admission', 'discussion', 'verification')
|
jbe@532
|
3028 THEN
|
jbe@532
|
3029 RETURN "persist";
|
jbe@532
|
3030 ELSE
|
jbe@532
|
3031 RETURN NULL;
|
jbe@532
|
3032 END IF;
|
jbe@532
|
3033 END IF;
|
jbe@532
|
3034 IF
|
jbe@532
|
3035 "persist"."state" IN ('admission', 'discussion', 'verification') AND
|
jbe@532
|
3036 coalesce("persist"."snapshot_created", FALSE) = FALSE
|
jbe@532
|
3037 THEN
|
jbe@532
|
3038 IF "persist"."state" != 'admission' THEN
|
jbe@532
|
3039 PERFORM "take_snapshot"("issue_id_p");
|
jbe@532
|
3040 PERFORM "finish_snapshot"("issue_id_p");
|
jbe@532
|
3041 END IF;
|
jbe@532
|
3042 "persist"."snapshot_created" = TRUE;
|
jbe@532
|
3043 IF "persist"."phase_finished" THEN
|
jbe@532
|
3044 IF "persist"."state" = 'admission' THEN
|
jbe@532
|
3045 UPDATE "issue" SET "admission_snapshot_id" = "latest_snapshot_id";
|
jbe@532
|
3046 ELSIF "persist"."state" = 'discussion' THEN
|
jbe@532
|
3047 UPDATE "issue" SET "half_freeze_snapshot_id" = "latest_snapshot_id";
|
jbe@532
|
3048 ELSIF "persist"."state" = 'verification' THEN
|
jbe@532
|
3049 UPDATE "issue" SET "full_freeze_snapshot_id" = "latest_snapshot_id";
|
jbe@532
|
3050 SELECT * INTO "issue_row" FROM "issue" WHERE "id" = "issue_id_p";
|
jbe@532
|
3051 SELECT * INTO "policy_row" FROM "policy"
|
jbe@532
|
3052 WHERE "id" = "issue_row"."policy_id";
|
jbe@532
|
3053 FOR "initiative_row" IN
|
jbe@532
|
3054 SELECT * FROM "initiative"
|
jbe@532
|
3055 WHERE "issue_id" = "issue_id_p" AND "revoked" ISNULL
|
jbe@532
|
3056 FOR UPDATE
|
jbe@532
|
3057 LOOP
|
jbe@532
|
3058 IF
|
jbe@532
|
3059 "initiative_row"."polling" OR (
|
jbe@532
|
3060 "initiative_row"."satisfied_supporter_count" >
|
jbe@532
|
3061 "policy_row"."initiative_quorum" AND
|
jbe@532
|
3062 "initiative_row"."satisfied_supporter_count" *
|
jbe@532
|
3063 "policy_row"."initiative_quorum_den" >=
|
jbe@532
|
3064 "issue_row"."population" * "policy_row"."initiative_quorum_num"
|
jbe@532
|
3065 )
|
jbe@532
|
3066 THEN
|
jbe@532
|
3067 UPDATE "initiative" SET "admitted" = TRUE
|
jbe@532
|
3068 WHERE "id" = "initiative_row"."id";
|
jbe@532
|
3069 ELSE
|
jbe@532
|
3070 UPDATE "initiative" SET "admitted" = FALSE
|
jbe@532
|
3071 WHERE "id" = "initiative_row"."id";
|
jbe@532
|
3072 END IF;
|
jbe@532
|
3073 END LOOP;
|
jbe@532
|
3074 END IF;
|
jbe@532
|
3075 END IF;
|
jbe@532
|
3076 RETURN "persist";
|
jbe@532
|
3077 END IF;
|
jbe@532
|
3078 IF
|
jbe@532
|
3079 "persist"."state" IN ('admission', 'discussion', 'verification') AND
|
jbe@532
|
3080 coalesce("persist"."harmonic_weights_set", FALSE) = FALSE
|
jbe@532
|
3081 THEN
|
jbe@532
|
3082 PERFORM "set_harmonic_initiative_weights"("issue_id_p");
|
jbe@532
|
3083 "persist"."harmonic_weights_set" = TRUE;
|
jbe@532
|
3084 IF
|
jbe@532
|
3085 "persist"."phase_finished" OR
|
jbe@532
|
3086 "persist"."issue_revoked" OR
|
jbe@532
|
3087 "persist"."state" = 'admission'
|
jbe@532
|
3088 THEN
|
jbe@532
|
3089 RETURN "persist";
|
jbe@532
|
3090 ELSE
|
jbe@532
|
3091 RETURN NULL;
|
jbe@532
|
3092 END IF;
|
jbe@532
|
3093 END IF;
|
jbe@532
|
3094 IF "persist"."issue_revoked" THEN
|
jbe@532
|
3095 IF "persist"."state" = 'admission' THEN
|
jbe@532
|
3096 "state_v" := 'canceled_revoked_before_accepted';
|
jbe@532
|
3097 ELSIF "persist"."state" = 'discussion' THEN
|
jbe@532
|
3098 "state_v" := 'canceled_after_revocation_during_discussion';
|
jbe@532
|
3099 ELSIF "persist"."state" = 'verification' THEN
|
jbe@532
|
3100 "state_v" := 'canceled_after_revocation_during_verification';
|
jbe@532
|
3101 END IF;
|
jbe@532
|
3102 UPDATE "issue" SET
|
jbe@532
|
3103 "state" = "state_v",
|
jbe@532
|
3104 "closed" = "phase_finished",
|
jbe@532
|
3105 "phase_finished" = NULL
|
jbe@532
|
3106 WHERE "id" = "issue_id_p";
|
jbe@532
|
3107 RETURN NULL;
|
jbe@532
|
3108 END IF;
|
jbe@532
|
3109 IF "persist"."state" = 'admission' THEN
|
jbe@532
|
3110 SELECT * INTO "issue_row" FROM "issue" WHERE "id" = "issue_id_p"
|
jbe@532
|
3111 FOR UPDATE;
|
jbe@532
|
3112 IF "issue_row"."phase_finished" NOTNULL THEN
|
jbe@532
|
3113 UPDATE "issue" SET
|
jbe@532
|
3114 "state" = 'canceled_issue_not_accepted',
|
jbe@532
|
3115 "closed" = "phase_finished",
|
jbe@532
|
3116 "phase_finished" = NULL
|
jbe@532
|
3117 WHERE "id" = "issue_id_p";
|
jbe@532
|
3118 END IF;
|
jbe@532
|
3119 RETURN NULL;
|
jbe@532
|
3120 END IF;
|
jbe@532
|
3121 IF "persist"."phase_finished" THEN
|
jbe@532
|
3122 IF "persist"."state" = 'discussion' THEN
|
jbe@532
|
3123 UPDATE "issue" SET
|
jbe@532
|
3124 "state" = 'verification',
|
jbe@532
|
3125 "half_frozen" = "phase_finished",
|
jbe@532
|
3126 "phase_finished" = NULL
|
jbe@532
|
3127 WHERE "id" = "issue_id_p";
|
jbe@532
|
3128 RETURN NULL;
|
jbe@532
|
3129 END IF;
|
jbe@532
|
3130 IF "persist"."state" = 'verification' THEN
|
jbe@532
|
3131 SELECT * INTO "issue_row" FROM "issue" WHERE "id" = "issue_id_p"
|
jbe@532
|
3132 FOR UPDATE;
|
jbe@532
|
3133 SELECT * INTO "policy_row" FROM "policy"
|
jbe@532
|
3134 WHERE "id" = "issue_row"."policy_id";
|
jbe@532
|
3135 IF EXISTS (
|
jbe@532
|
3136 SELECT NULL FROM "initiative"
|
jbe@532
|
3137 WHERE "issue_id" = "issue_id_p" AND "admitted" = TRUE
|
jbe@532
|
3138 ) THEN
|
jbe@532
|
3139 UPDATE "issue" SET
|
jbe@532
|
3140 "state" = 'voting',
|
jbe@532
|
3141 "fully_frozen" = "phase_finished",
|
jbe@532
|
3142 "phase_finished" = NULL
|
jbe@532
|
3143 WHERE "id" = "issue_id_p";
|
jbe@532
|
3144 ELSE
|
jbe@532
|
3145 UPDATE "issue" SET
|
jbe@532
|
3146 "state" = 'canceled_no_initiative_admitted',
|
jbe@532
|
3147 "fully_frozen" = "phase_finished",
|
jbe@532
|
3148 "closed" = "phase_finished",
|
jbe@532
|
3149 "phase_finished" = NULL
|
jbe@532
|
3150 WHERE "id" = "issue_id_p";
|
jbe@532
|
3151 -- NOTE: The following DELETE statements have effect only when
|
jbe@532
|
3152 -- issue state has been manipulated
|
jbe@532
|
3153 DELETE FROM "direct_voter" WHERE "issue_id" = "issue_id_p";
|
jbe@532
|
3154 DELETE FROM "delegating_voter" WHERE "issue_id" = "issue_id_p";
|
jbe@532
|
3155 DELETE FROM "battle" WHERE "issue_id" = "issue_id_p";
|
jbe@532
|
3156 END IF;
|
jbe@532
|
3157 RETURN NULL;
|
jbe@532
|
3158 END IF;
|
jbe@532
|
3159 IF "persist"."state" = 'voting' THEN
|
jbe@532
|
3160 IF coalesce("persist"."closed_voting", FALSE) = FALSE THEN
|
jbe@532
|
3161 PERFORM "close_voting"("issue_id_p");
|
jbe@532
|
3162 "persist"."closed_voting" = TRUE;
|
jbe@532
|
3163 RETURN "persist";
|
jbe@532
|
3164 END IF;
|
jbe@532
|
3165 PERFORM "calculate_ranks"("issue_id_p");
|
jbe@532
|
3166 RETURN NULL;
|
jbe@532
|
3167 END IF;
|
jbe@532
|
3168 END IF;
|
jbe@532
|
3169 RAISE WARNING 'should not happen';
|
jbe@532
|
3170 RETURN NULL;
|
jbe@532
|
3171 END;
|
jbe@532
|
3172 $$;
|
jbe@532
|
3173
|
jbe@532
|
3174
|
jbe@532
|
3175 CREATE OR REPLACE FUNCTION "check_everything"()
|
jbe@532
|
3176 RETURNS VOID
|
jbe@532
|
3177 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
3178 DECLARE
|
jbe@532
|
3179 "area_id_v" "area"."id"%TYPE;
|
jbe@532
|
3180 "snapshot_id_v" "snapshot"."id"%TYPE;
|
jbe@532
|
3181 "issue_id_v" "issue"."id"%TYPE;
|
jbe@532
|
3182 "persist_v" "check_issue_persistence";
|
jbe@532
|
3183 BEGIN
|
jbe@532
|
3184 RAISE WARNING 'Function "check_everything" should only be used for development and debugging purposes';
|
jbe@532
|
3185 DELETE FROM "expired_session";
|
jbe@532
|
3186 DELETE FROM "expired_token";
|
jbe@532
|
3187 DELETE FROM "expired_snapshot";
|
jbe@532
|
3188 PERFORM "check_activity"();
|
jbe@532
|
3189 PERFORM "calculate_member_counts"();
|
jbe@532
|
3190 FOR "area_id_v" IN SELECT "id" FROM "area_with_unaccepted_issues" LOOP
|
jbe@532
|
3191 SELECT "take_snapshot"(NULL, "area_id_v") INTO "snapshot_id_v";
|
jbe@532
|
3192 PERFORM "finish_snapshot"("issue_id") FROM "snapshot_issue"
|
jbe@532
|
3193 WHERE "snapshot_id" = "snapshot_id_v";
|
jbe@532
|
3194 LOOP
|
jbe@532
|
3195 EXIT WHEN "issue_admission"("area_id_v") = FALSE;
|
jbe@532
|
3196 END LOOP;
|
jbe@532
|
3197 END LOOP;
|
jbe@532
|
3198 FOR "issue_id_v" IN SELECT "id" FROM "open_issue" LOOP
|
jbe@532
|
3199 "persist_v" := NULL;
|
jbe@532
|
3200 LOOP
|
jbe@532
|
3201 "persist_v" := "check_issue"("issue_id_v", "persist_v");
|
jbe@532
|
3202 EXIT WHEN "persist_v" ISNULL;
|
jbe@532
|
3203 END LOOP;
|
jbe@532
|
3204 END LOOP;
|
jbe@532
|
3205 RETURN;
|
jbe@532
|
3206 END;
|
jbe@532
|
3207 $$;
|
jbe@532
|
3208
|
jbe@532
|
3209 COMMENT ON FUNCTION "check_everything"() IS 'Amongst other regular tasks, this function performs "check_issue" for every open issue. Use this function only for development and debugging purposes, as you may run into locking and/or serialization problems in productive environments. For production, use lf_update binary instead';
|
jbe@532
|
3210
|
jbe@532
|
3211
|
jbe@532
|
3212 CREATE OR REPLACE FUNCTION "clean_issue"("issue_id_p" "issue"."id"%TYPE)
|
jbe@532
|
3213 RETURNS VOID
|
jbe@532
|
3214 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
3215 BEGIN
|
jbe@532
|
3216 IF EXISTS (
|
jbe@532
|
3217 SELECT NULL FROM "issue" WHERE "id" = "issue_id_p" AND "cleaned" ISNULL
|
jbe@532
|
3218 ) THEN
|
jbe@532
|
3219 -- override protection triggers:
|
jbe@532
|
3220 INSERT INTO "temporary_transaction_data" ("key", "value")
|
jbe@532
|
3221 VALUES ('override_protection_triggers', TRUE::TEXT);
|
jbe@532
|
3222 -- clean data:
|
jbe@532
|
3223 DELETE FROM "delegating_voter"
|
jbe@532
|
3224 WHERE "issue_id" = "issue_id_p";
|
jbe@532
|
3225 DELETE FROM "direct_voter"
|
jbe@532
|
3226 WHERE "issue_id" = "issue_id_p";
|
jbe@532
|
3227 DELETE FROM "delegating_interest_snapshot"
|
jbe@532
|
3228 WHERE "issue_id" = "issue_id_p";
|
jbe@532
|
3229 DELETE FROM "direct_interest_snapshot"
|
jbe@532
|
3230 WHERE "issue_id" = "issue_id_p";
|
jbe@532
|
3231 DELETE FROM "non_voter"
|
jbe@532
|
3232 WHERE "issue_id" = "issue_id_p";
|
jbe@532
|
3233 DELETE FROM "delegation"
|
jbe@532
|
3234 WHERE "issue_id" = "issue_id_p";
|
jbe@532
|
3235 DELETE FROM "supporter"
|
jbe@532
|
3236 USING "initiative" -- NOTE: due to missing index on issue_id
|
jbe@532
|
3237 WHERE "initiative"."issue_id" = "issue_id_p"
|
jbe@532
|
3238 AND "supporter"."initiative_id" = "initiative_id";
|
jbe@532
|
3239 -- mark issue as cleaned:
|
jbe@532
|
3240 UPDATE "issue" SET "cleaned" = now() WHERE "id" = "issue_id_p";
|
jbe@532
|
3241 -- finish overriding protection triggers (avoids garbage):
|
jbe@532
|
3242 DELETE FROM "temporary_transaction_data"
|
jbe@532
|
3243 WHERE "key" = 'override_protection_triggers';
|
jbe@532
|
3244 END IF;
|
jbe@532
|
3245 RETURN;
|
jbe@532
|
3246 END;
|
jbe@532
|
3247 $$;
|
jbe@532
|
3248
|
jbe@532
|
3249
|
jbe@532
|
3250 CREATE OR REPLACE FUNCTION "delete_member"("member_id_p" "member"."id"%TYPE)
|
jbe@532
|
3251 RETURNS VOID
|
jbe@532
|
3252 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
3253 BEGIN
|
jbe@532
|
3254 UPDATE "member" SET
|
jbe@532
|
3255 "last_login" = NULL,
|
jbe@532
|
3256 "last_delegation_check" = NULL,
|
jbe@532
|
3257 "login" = NULL,
|
jbe@532
|
3258 "password" = NULL,
|
jbe@532
|
3259 "authority" = NULL,
|
jbe@532
|
3260 "authority_uid" = NULL,
|
jbe@532
|
3261 "authority_login" = NULL,
|
jbe@532
|
3262 "locked" = TRUE,
|
jbe@532
|
3263 "active" = FALSE,
|
jbe@532
|
3264 "notify_email" = NULL,
|
jbe@532
|
3265 "notify_email_unconfirmed" = NULL,
|
jbe@532
|
3266 "notify_email_secret" = NULL,
|
jbe@532
|
3267 "notify_email_secret_expiry" = NULL,
|
jbe@532
|
3268 "notify_email_lock_expiry" = NULL,
|
jbe@532
|
3269 "disable_notifications" = TRUE,
|
jbe@532
|
3270 "notification_counter" = DEFAULT,
|
jbe@532
|
3271 "notification_sample_size" = 0,
|
jbe@532
|
3272 "notification_dow" = NULL,
|
jbe@532
|
3273 "notification_hour" = NULL,
|
jbe@543
|
3274 "notification_sent" = NULL,
|
jbe@532
|
3275 "login_recovery_expiry" = NULL,
|
jbe@532
|
3276 "password_reset_secret" = NULL,
|
jbe@532
|
3277 "password_reset_secret_expiry" = NULL,
|
jbe@532
|
3278 "location" = NULL
|
jbe@532
|
3279 WHERE "id" = "member_id_p";
|
jbe@532
|
3280 -- "text_search_data" is updated by triggers
|
jbe@544
|
3281 DELETE FROM "member_settings" WHERE "member_id" = "member_id_p";
|
jbe@543
|
3282 DELETE FROM "member_profile" WHERE "member_id" = "member_id_p";
|
jbe@543
|
3283 DELETE FROM "rendered_member_statement" WHERE "member_id" = "member_id_p";
|
jbe@532
|
3284 DELETE FROM "member_image" WHERE "member_id" = "member_id_p";
|
jbe@532
|
3285 DELETE FROM "contact" WHERE "member_id" = "member_id_p";
|
jbe@532
|
3286 DELETE FROM "ignored_member" WHERE "member_id" = "member_id_p";
|
jbe@532
|
3287 DELETE FROM "session" WHERE "member_id" = "member_id_p";
|
jbe@543
|
3288 DELETE FROM "member_application" WHERE "member_id" = "member_id_p";
|
jbe@543
|
3289 DELETE FROM "token" WHERE "member_id" = "member_id_p";
|
jbe@543
|
3290 DELETE FROM "subscription" WHERE "member_id" = "member_id_p";
|
jbe@543
|
3291 DELETE FROM "ignored_area" WHERE "member_id" = "member_id_p";
|
jbe@532
|
3292 DELETE FROM "ignored_initiative" WHERE "member_id" = "member_id_p";
|
jbe@532
|
3293 DELETE FROM "delegation" WHERE "truster_id" = "member_id_p";
|
jbe@532
|
3294 DELETE FROM "non_voter" WHERE "member_id" = "member_id_p";
|
jbe@532
|
3295 DELETE FROM "direct_voter" USING "issue"
|
jbe@532
|
3296 WHERE "direct_voter"."issue_id" = "issue"."id"
|
jbe@532
|
3297 AND "issue"."closed" ISNULL
|
jbe@532
|
3298 AND "member_id" = "member_id_p";
|
jbe@543
|
3299 DELETE FROM "notification_initiative_sent" WHERE "member_id" = "member_id_p";
|
jbe@532
|
3300 RETURN;
|
jbe@532
|
3301 END;
|
jbe@532
|
3302 $$;
|
jbe@532
|
3303
|
jbe@532
|
3304
|
jbe@532
|
3305 CREATE OR REPLACE FUNCTION "delete_private_data"()
|
jbe@532
|
3306 RETURNS VOID
|
jbe@532
|
3307 LANGUAGE 'plpgsql' VOLATILE AS $$
|
jbe@532
|
3308 BEGIN
|
jbe@532
|
3309 DELETE FROM "temporary_transaction_data";
|
jbe@543
|
3310 DELETE FROM "temporary_suggestion_counts";
|
jbe@532
|
3311 DELETE FROM "member" WHERE "activated" ISNULL;
|
jbe@532
|
3312 UPDATE "member" SET
|
jbe@532
|
3313 "invite_code" = NULL,
|
jbe@532
|
3314 "invite_code_expiry" = NULL,
|
jbe@532
|
3315 "admin_comment" = NULL,
|
jbe@532
|
3316 "last_login" = NULL,
|
jbe@532
|
3317 "last_delegation_check" = NULL,
|
jbe@532
|
3318 "login" = NULL,
|
jbe@532
|
3319 "password" = NULL,
|
jbe@532
|
3320 "authority" = NULL,
|
jbe@532
|
3321 "authority_uid" = NULL,
|
jbe@532
|
3322 "authority_login" = NULL,
|
jbe@532
|
3323 "lang" = NULL,
|
jbe@532
|
3324 "notify_email" = NULL,
|
jbe@532
|
3325 "notify_email_unconfirmed" = NULL,
|
jbe@532
|
3326 "notify_email_secret" = NULL,
|
jbe@532
|
3327 "notify_email_secret_expiry" = NULL,
|
jbe@532
|
3328 "notify_email_lock_expiry" = NULL,
|
jbe@532
|
3329 "disable_notifications" = TRUE,
|
jbe@532
|
3330 "notification_counter" = DEFAULT,
|
jbe@532
|
3331 "notification_sample_size" = 0,
|
jbe@532
|
3332 "notification_dow" = NULL,
|
jbe@532
|
3333 "notification_hour" = NULL,
|
jbe@543
|
3334 "notification_sent" = NULL,
|
jbe@532
|
3335 "login_recovery_expiry" = NULL,
|
jbe@532
|
3336 "password_reset_secret" = NULL,
|
jbe@532
|
3337 "password_reset_secret_expiry" = NULL,
|
jbe@532
|
3338 "location" = NULL;
|
jbe@532
|
3339 -- "text_search_data" is updated by triggers
|
jbe@544
|
3340 DELETE FROM "member_settings";
|
jbe@544
|
3341 DELETE FROM "member_useterms";
|
jbe@543
|
3342 DELETE FROM "member_profile";
|
jbe@543
|
3343 DELETE FROM "rendered_member_statement";
|
jbe@532
|
3344 DELETE FROM "member_image";
|
jbe@532
|
3345 DELETE FROM "contact";
|
jbe@532
|
3346 DELETE FROM "ignored_member";
|
jbe@532
|
3347 DELETE FROM "session";
|
jbe@543
|
3348 DELETE FROM "system_application";
|
jbe@543
|
3349 DELETE FROM "system_application_redirect_uri";
|
jbe@543
|
3350 DELETE FROM "dynamic_application_scope";
|
jbe@543
|
3351 DELETE FROM "member_application";
|
jbe@543
|
3352 DELETE FROM "token";
|
jbe@543
|
3353 DELETE FROM "subscription";
|
jbe@543
|
3354 DELETE FROM "ignored_area";
|
jbe@532
|
3355 DELETE FROM "ignored_initiative";
|
jbe@532
|
3356 DELETE FROM "non_voter";
|
jbe@532
|
3357 DELETE FROM "direct_voter" USING "issue"
|
jbe@532
|
3358 WHERE "direct_voter"."issue_id" = "issue"."id"
|
jbe@532
|
3359 AND "issue"."closed" ISNULL;
|
jbe@543
|
3360 DELETE FROM "event_processed";
|
jbe@543
|
3361 DELETE FROM "notification_initiative_sent";
|
jbe@543
|
3362 DELETE FROM "newsletter";
|
jbe@532
|
3363 RETURN;
|
jbe@532
|
3364 END;
|
jbe@532
|
3365 $$;
|
jbe@532
|
3366
|
jbe@532
|
3367
|
jbe@532
|
3368 CREATE TEMPORARY TABLE "old_snapshot" AS
|
jbe@532
|
3369 SELECT "ordered".*, row_number() OVER () AS "snapshot_id"
|
jbe@532
|
3370 FROM (
|
jbe@532
|
3371 SELECT * FROM (
|
jbe@532
|
3372 SELECT
|
jbe@532
|
3373 "id" AS "issue_id",
|
jbe@532
|
3374 'end_of_admission'::"snapshot_event" AS "event",
|
jbe@532
|
3375 "accepted" AS "calculated"
|
jbe@532
|
3376 FROM "issue" WHERE "accepted" NOTNULL
|
jbe@532
|
3377 UNION ALL
|
jbe@532
|
3378 SELECT
|
jbe@532
|
3379 "id" AS "issue_id",
|
jbe@532
|
3380 'half_freeze'::"snapshot_event" AS "event",
|
jbe@532
|
3381 "half_frozen" AS "calculated"
|
jbe@532
|
3382 FROM "issue" WHERE "half_frozen" NOTNULL
|
jbe@532
|
3383 UNION ALL
|
jbe@532
|
3384 SELECT
|
jbe@532
|
3385 "id" AS "issue_id",
|
jbe@532
|
3386 'full_freeze'::"snapshot_event" AS "event",
|
jbe@532
|
3387 "fully_frozen" AS "calculated"
|
jbe@532
|
3388 FROM "issue" WHERE "fully_frozen" NOTNULL
|
jbe@532
|
3389 ) AS "unordered"
|
jbe@532
|
3390 ORDER BY "calculated", "issue_id", "event"
|
jbe@532
|
3391 ) AS "ordered";
|
jbe@532
|
3392
|
jbe@532
|
3393
|
jbe@532
|
3394 INSERT INTO "snapshot" ("id", "calculated", "population", "area_id", "issue_id")
|
jbe@532
|
3395 SELECT
|
jbe@532
|
3396 "old_snapshot"."snapshot_id" AS "id",
|
jbe@532
|
3397 "old_snapshot"."calculated",
|
jbe@532
|
3398 ( SELECT COALESCE(sum("weight"), 0)
|
jbe@532
|
3399 FROM "direct_population_snapshot" "dps"
|
jbe@532
|
3400 WHERE "dps"."issue_id" = "old_snapshot"."issue_id"
|
jbe@532
|
3401 AND "dps"."event" = "old_snapshot"."event"
|
jbe@532
|
3402 ) AS "population",
|
jbe@532
|
3403 "issue"."area_id" AS "area_id",
|
jbe@532
|
3404 "issue"."id" AS "issue_id"
|
jbe@532
|
3405 FROM "old_snapshot" JOIN "issue"
|
jbe@532
|
3406 ON "old_snapshot"."issue_id" = "issue"."id";
|
jbe@532
|
3407
|
jbe@532
|
3408
|
jbe@532
|
3409 INSERT INTO "snapshot_issue" ("snapshot_id", "issue_id")
|
jbe@532
|
3410 SELECT "id" AS "snapshot_id", "issue_id" FROM "snapshot";
|
jbe@532
|
3411
|
jbe@532
|
3412
|
jbe@532
|
3413 INSERT INTO "snapshot_population" ("snapshot_id", "member_id")
|
jbe@532
|
3414 SELECT
|
jbe@532
|
3415 "old_snapshot"."snapshot_id",
|
jbe@532
|
3416 "direct_population_snapshot"."member_id"
|
jbe@532
|
3417 FROM "old_snapshot" JOIN "direct_population_snapshot"
|
jbe@532
|
3418 ON "old_snapshot"."issue_id" = "direct_population_snapshot"."issue_id"
|
jbe@532
|
3419 AND "old_snapshot"."event" = "direct_population_snapshot"."event";
|
jbe@532
|
3420
|
jbe@532
|
3421 INSERT INTO "snapshot_population" ("snapshot_id", "member_id")
|
jbe@532
|
3422 SELECT
|
jbe@532
|
3423 "old_snapshot"."snapshot_id",
|
jbe@532
|
3424 "delegating_population_snapshot"."member_id"
|
jbe@532
|
3425 FROM "old_snapshot" JOIN "delegating_population_snapshot"
|
jbe@532
|
3426 ON "old_snapshot"."issue_id" = "delegating_population_snapshot"."issue_id"
|
jbe@532
|
3427 AND "old_snapshot"."event" = "delegating_population_snapshot"."event";
|
jbe@532
|
3428
|
jbe@532
|
3429
|
jbe@532
|
3430 INSERT INTO "direct_interest_snapshot"
|
jbe@532
|
3431 ("snapshot_id", "issue_id", "member_id", "weight")
|
jbe@532
|
3432 SELECT
|
jbe@532
|
3433 "old_snapshot"."snapshot_id",
|
jbe@532
|
3434 "old_snapshot"."issue_id",
|
jbe@532
|
3435 "direct_interest_snapshot_old"."member_id",
|
jbe@532
|
3436 "direct_interest_snapshot_old"."weight"
|
jbe@532
|
3437 FROM "old_snapshot" JOIN "direct_interest_snapshot_old"
|
jbe@532
|
3438 ON "old_snapshot"."issue_id" = "direct_interest_snapshot_old"."issue_id"
|
jbe@532
|
3439 AND "old_snapshot"."event" = "direct_interest_snapshot_old"."event";
|
jbe@532
|
3440
|
jbe@532
|
3441 INSERT INTO "delegating_interest_snapshot"
|
jbe@532
|
3442 ( "snapshot_id", "issue_id",
|
jbe@532
|
3443 "member_id", "weight", "scope", "delegate_member_ids" )
|
jbe@532
|
3444 SELECT
|
jbe@532
|
3445 "old_snapshot"."snapshot_id",
|
jbe@532
|
3446 "old_snapshot"."issue_id",
|
jbe@532
|
3447 "delegating_interest_snapshot_old"."member_id",
|
jbe@532
|
3448 "delegating_interest_snapshot_old"."weight",
|
jbe@532
|
3449 "delegating_interest_snapshot_old"."scope",
|
jbe@532
|
3450 "delegating_interest_snapshot_old"."delegate_member_ids"
|
jbe@532
|
3451 FROM "old_snapshot" JOIN "delegating_interest_snapshot_old"
|
jbe@532
|
3452 ON "old_snapshot"."issue_id" = "delegating_interest_snapshot_old"."issue_id"
|
jbe@532
|
3453 AND "old_snapshot"."event" = "delegating_interest_snapshot_old"."event";
|
jbe@532
|
3454
|
jbe@532
|
3455 INSERT INTO "direct_supporter_snapshot"
|
jbe@532
|
3456 ( "snapshot_id", "issue_id",
|
jbe@532
|
3457 "initiative_id", "member_id", "draft_id", "informed", "satisfied" )
|
jbe@532
|
3458 SELECT
|
jbe@532
|
3459 "old_snapshot"."snapshot_id",
|
jbe@532
|
3460 "old_snapshot"."issue_id",
|
jbe@532
|
3461 "direct_supporter_snapshot_old"."initiative_id",
|
jbe@532
|
3462 "direct_supporter_snapshot_old"."member_id",
|
jbe@532
|
3463 "direct_supporter_snapshot_old"."draft_id",
|
jbe@532
|
3464 "direct_supporter_snapshot_old"."informed",
|
jbe@532
|
3465 "direct_supporter_snapshot_old"."satisfied"
|
jbe@532
|
3466 FROM "old_snapshot" JOIN "direct_supporter_snapshot_old"
|
jbe@532
|
3467 ON "old_snapshot"."issue_id" = "direct_supporter_snapshot_old"."issue_id"
|
jbe@532
|
3468 AND "old_snapshot"."event" = "direct_supporter_snapshot_old"."event";
|
jbe@532
|
3469
|
jbe@532
|
3470
|
jbe@532
|
3471 ALTER TABLE "issue" DISABLE TRIGGER USER; -- NOTE: required to modify table later
|
jbe@532
|
3472
|
jbe@532
|
3473 UPDATE "issue" SET "latest_snapshot_id" = "snapshot"."id"
|
jbe@532
|
3474 FROM (
|
jbe@532
|
3475 SELECT DISTINCT ON ("issue_id") "issue_id", "id"
|
jbe@532
|
3476 FROM "snapshot" ORDER BY "issue_id", "id" DESC
|
jbe@532
|
3477 ) AS "snapshot"
|
jbe@532
|
3478 WHERE "snapshot"."issue_id" = "issue"."id";
|
jbe@532
|
3479
|
jbe@532
|
3480 UPDATE "issue" SET "admission_snapshot_id" = "old_snapshot"."snapshot_id"
|
jbe@532
|
3481 FROM "old_snapshot"
|
jbe@532
|
3482 WHERE "old_snapshot"."issue_id" = "issue"."id"
|
jbe@532
|
3483 AND "old_snapshot"."event" = 'end_of_admission';
|
jbe@532
|
3484
|
jbe@532
|
3485 UPDATE "issue" SET "half_freeze_snapshot_id" = "old_snapshot"."snapshot_id"
|
jbe@532
|
3486 FROM "old_snapshot"
|
jbe@532
|
3487 WHERE "old_snapshot"."issue_id" = "issue"."id"
|
jbe@532
|
3488 AND "old_snapshot"."event" = 'half_freeze';
|
jbe@532
|
3489
|
jbe@532
|
3490 UPDATE "issue" SET "full_freeze_snapshot_id" = "old_snapshot"."snapshot_id"
|
jbe@532
|
3491 FROM "old_snapshot"
|
jbe@532
|
3492 WHERE "old_snapshot"."issue_id" = "issue"."id"
|
jbe@532
|
3493 AND "old_snapshot"."event" = 'full_freeze';
|
jbe@532
|
3494
|
jbe@532
|
3495 ALTER TABLE "issue" ENABLE TRIGGER USER;
|
jbe@532
|
3496
|
jbe@532
|
3497
|
jbe@532
|
3498 DROP TABLE "old_snapshot";
|
jbe@532
|
3499
|
jbe@532
|
3500 DROP TABLE "direct_supporter_snapshot_old";
|
jbe@532
|
3501 DROP TABLE "delegating_interest_snapshot_old";
|
jbe@532
|
3502 DROP TABLE "direct_interest_snapshot_old";
|
jbe@532
|
3503 DROP TABLE "delegating_population_snapshot";
|
jbe@532
|
3504 DROP TABLE "direct_population_snapshot";
|
jbe@532
|
3505
|
jbe@532
|
3506
|
jbe@532
|
3507 DROP VIEW "open_issue";
|
jbe@532
|
3508
|
jbe@532
|
3509
|
jbe@532
|
3510 ALTER TABLE "issue" DROP COLUMN "latest_snapshot_event";
|
jbe@532
|
3511
|
jbe@532
|
3512
|
jbe@532
|
3513 CREATE VIEW "open_issue" AS
|
jbe@532
|
3514 SELECT * FROM "issue" WHERE "closed" ISNULL;
|
jbe@532
|
3515
|
jbe@532
|
3516 COMMENT ON VIEW "open_issue" IS 'All open issues';
|
jbe@532
|
3517
|
jbe@532
|
3518
|
jbe@532
|
3519 -- NOTE: create "issue_for_admission" view after altering table "issue"
|
jbe@532
|
3520 CREATE VIEW "issue_for_admission" AS
|
jbe@532
|
3521 SELECT DISTINCT ON ("issue"."area_id")
|
jbe@532
|
3522 "issue".*,
|
jbe@532
|
3523 max("initiative"."supporter_count") AS "max_supporter_count"
|
jbe@532
|
3524 FROM "issue"
|
jbe@532
|
3525 JOIN "policy" ON "issue"."policy_id" = "policy"."id"
|
jbe@532
|
3526 JOIN "initiative" ON "issue"."id" = "initiative"."issue_id"
|
jbe@532
|
3527 JOIN "area" ON "issue"."area_id" = "area"."id"
|
jbe@532
|
3528 WHERE "issue"."state" = 'admission'::"issue_state"
|
jbe@532
|
3529 AND now() >= "issue"."created" + "issue"."min_admission_time"
|
jbe@532
|
3530 AND "initiative"."supporter_count" >= "policy"."issue_quorum"
|
jbe@532
|
3531 AND "initiative"."supporter_count" * "policy"."issue_quorum_den" >=
|
jbe@532
|
3532 "issue"."population" * "policy"."issue_quorum_num"
|
jbe@532
|
3533 AND "initiative"."supporter_count" >= "area"."issue_quorum"
|
jbe@532
|
3534 AND "initiative"."revoked" ISNULL
|
jbe@532
|
3535 GROUP BY "issue"."id"
|
jbe@532
|
3536 ORDER BY "issue"."area_id", "max_supporter_count" DESC, "issue"."id";
|
jbe@532
|
3537
|
jbe@532
|
3538 COMMENT ON VIEW "issue_for_admission" IS 'Contains up to 1 issue per area eligible to pass from ''admission'' to ''discussion'' state; needs to be recalculated after admitting the issue in this view';
|
jbe@532
|
3539
|
jbe@532
|
3540
|
jbe@532
|
3541 DROP TYPE "snapshot_event";
|
jbe@532
|
3542
|
jbe@532
|
3543
|
jbe@532
|
3544 ALTER TABLE "issue" ADD CONSTRAINT "snapshot_required" CHECK (
|
jbe@532
|
3545 ("half_frozen" ISNULL OR "half_freeze_snapshot_id" NOTNULL) AND
|
jbe@532
|
3546 ("fully_frozen" ISNULL OR "full_freeze_snapshot_id" NOTNULL) );
|
jbe@532
|
3547
|
jbe@532
|
3548
|
jbe@532
|
3549 COMMIT;
|