liquid_feedback_core

annotate update/core-update.v3.2.2-v4.0.0.sql @ 546:f46ebb677898

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

Impressum / About Us