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