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