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