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