| rev | 
   line source | 
| 
jbe@453
 | 
     1 BEGIN;
 | 
| 
jbe@453
 | 
     2 
 | 
| 
jbe@453
 | 
     3 CREATE OR REPLACE VIEW "liquid_feedback_version" AS
 | 
| 
jbe@453
 | 
     4   SELECT * FROM (VALUES ('3.1.0', 3, 1, 0))
 | 
| 
jbe@453
 | 
     5   AS "subquery"("string", "major", "minor", "revision");
 | 
| 
jbe@453
 | 
     6 
 | 
| 
jbe@453
 | 
     7 ALTER TABLE "member" DROP CONSTRAINT "authority_requires_uid_and_vice_versa";
 | 
| 
jbe@453
 | 
     8 ALTER TABLE "member" ADD CONSTRAINT "authority_requires_uid_and_vice_versa" CHECK (
 | 
| 
jbe@453
 | 
     9   ("authority" NOTNULL) = ("authority_uid" NOTNULL) );
 | 
| 
jbe@453
 | 
    10 
 | 
| 
jbe@453
 | 
    11 DROP TABLE "member_application";
 | 
| 
jbe@453
 | 
    12 DROP TYPE "application_access_level";
 | 
| 
jbe@453
 | 
    13 
 | 
| 
jbe@456
 | 
    14 ALTER TABLE "policy" ADD COLUMN "min_admission_time" INTERVAL;
 | 
| 
jbe@453
 | 
    15 ALTER TABLE "policy" RENAME COLUMN "admission_time" TO "max_admission_time";
 | 
| 
jbe@453
 | 
    16 
 | 
| 
jbe@456
 | 
    17 ALTER TABLE "policy" DROP CONSTRAINT "timing";  -- re-added after UPDATE
 | 
| 
jbe@453
 | 
    18 
 | 
| 
jbe@453
 | 
    19 ALTER TABLE "policy" DROP CONSTRAINT "issue_quorum_if_and_only_if_not_polling";
 | 
| 
jbe@453
 | 
    20 ALTER TABLE "policy" ADD CONSTRAINT "issue_quorum_if_and_only_if_not_polling" CHECK (
 | 
| 
jbe@453
 | 
    21   "polling" = ("issue_quorum_num" ISNULL) AND
 | 
| 
jbe@453
 | 
    22   "polling" = ("issue_quorum_den" ISNULL) );
 | 
| 
jbe@453
 | 
    23 
 | 
| 
jbe@453
 | 
    24 COMMENT ON COLUMN "policy"."polling" IS 'TRUE = special policy for non-user-generated issues without issue quorum, where certain initiatives (those having the "polling" flag set) do not need to pass the initiative quorum; "min_admission_time" and "max_admission_time" MUST be set to NULL, the other timings may be set to NULL altogether, allowing individual timing for those issues';
 | 
| 
jbe@453
 | 
    25 COMMENT ON COLUMN "policy"."min_admission_time" IS 'Minimum duration of issue state ''admission''; Minimum time an issue stays open';
 | 
| 
jbe@453
 | 
    26 
 | 
| 
jbe@456
 | 
    27 ALTER TABLE "issue" ADD COLUMN "min_admission_time" INTERVAL;
 | 
| 
jbe@453
 | 
    28 ALTER TABLE "issue" RENAME COLUMN "admission_time" TO "max_admission_time";
 | 
| 
jbe@453
 | 
    29 
 | 
| 
jbe@456
 | 
    30 ALTER TABLE "issue" DROP CONSTRAINT "admission_time_not_null_unless_instantly_accepted";  -- re-added after UPDATE
 | 
| 
jbe@453
 | 
    31 
 | 
| 
jbe@453
 | 
    32 ALTER TABLE "issue" DROP CONSTRAINT "set_both_or_none_of_snapshot_and_latest_snapshot_event";
 | 
| 
jbe@453
 | 
    33 ALTER TABLE "issue" ADD CONSTRAINT "set_both_or_none_of_snapshot_and_latest_snapshot_event" CHECK (
 | 
| 
jbe@453
 | 
    34   (("snapshot" NOTNULL) = ("latest_snapshot_event" NOTNULL)) );
 | 
| 
jbe@453
 | 
    35 
 | 
| 
jbe@453
 | 
    36 COMMENT ON COLUMN "issue"."closed" IS 'Point in time, when "max_admission_time" or "voting_time" have elapsed, and issue is no longer active; Frontends must ensure that for closed issues additionally to the restrictions for half_frozen and fully_frozen issues a) no voter is added or removed to/from the direct_voter table, b) no votes are added, modified or removed.';
 | 
| 
jbe@453
 | 
    37 COMMENT ON COLUMN "issue"."min_admission_time" IS 'Copied from "policy" table at creation of issue';
 | 
| 
jbe@453
 | 
    38 
 | 
| 
jbe@453
 | 
    39 DROP TRIGGER "update_text_search_data" ON "initiative";
 | 
| 
jbe@453
 | 
    40 ALTER TABLE "initiative" DROP COLUMN "discussion_url";
 | 
| 
jbe@453
 | 
    41 
 | 
| 
jbe@453
 | 
    42 ALTER TABLE "initiative" DROP CONSTRAINT "all_or_none_of_revoked_and_revoked_by_member_id_must_be_null";
 | 
| 
jbe@453
 | 
    43 ALTER TABLE "initiative" ADD CONSTRAINT "all_or_none_of_revoked_and_revoked_by_member_id_must_be_null" CHECK (
 | 
| 
jbe@453
 | 
    44   ("revoked" NOTNULL) = ("revoked_by_member_id" NOTNULL) );
 | 
| 
jbe@453
 | 
    45 
 | 
| 
jbe@453
 | 
    46  CREATE TRIGGER "update_text_search_data"
 | 
| 
jbe@453
 | 
    47    BEFORE INSERT OR UPDATE ON "initiative"
 | 
| 
jbe@453
 | 
    48    FOR EACH ROW EXECUTE PROCEDURE
 | 
| 
jbe@453
 | 
    49    tsvector_update_trigger('text_search_data', 'pg_catalog.simple', "name");
 | 
| 
jbe@453
 | 
    50 
 | 
| 
jbe@453
 | 
    51 ALTER TABLE "event" DROP CONSTRAINT "null_constraints_for_issue_state_changed";
 | 
| 
jbe@453
 | 
    52 ALTER TABLE "event" DROP CONSTRAINT "null_constraints_for_initiative_creation_or_revocation_or_new_draft";
 | 
| 
jbe@453
 | 
    53 ALTER TABLE "event" DROP CONSTRAINT "null_constraints_for_suggestion_creation";
 | 
| 
jbe@453
 | 
    54 
 | 
| 
jbe@453
 | 
    55 ALTER TABLE "event" ADD CONSTRAINT "null_constr_for_issue_state_changed" CHECK (
 | 
| 
jbe@453
 | 
    56   "event" != 'issue_state_changed' OR (
 | 
| 
jbe@453
 | 
    57     "member_id"     ISNULL  AND
 | 
| 
jbe@453
 | 
    58     "issue_id"      NOTNULL AND
 | 
| 
jbe@453
 | 
    59     "state"         NOTNULL AND
 | 
| 
jbe@453
 | 
    60     "initiative_id" ISNULL  AND
 | 
| 
jbe@453
 | 
    61     "draft_id"      ISNULL  AND
 | 
| 
jbe@453
 | 
    62     "suggestion_id" ISNULL  ) );
 | 
| 
jbe@453
 | 
    63 ALTER TABLE "event" ADD CONSTRAINT "null_constr_for_initiative_creation_or_revocation_or_new_draft" CHECK (
 | 
| 
jbe@453
 | 
    64   "event" NOT IN (
 | 
| 
jbe@453
 | 
    65     'initiative_created_in_new_issue',
 | 
| 
jbe@453
 | 
    66     'initiative_created_in_existing_issue',
 | 
| 
jbe@453
 | 
    67     'initiative_revoked',
 | 
| 
jbe@453
 | 
    68     'new_draft_created'
 | 
| 
jbe@453
 | 
    69   ) OR (
 | 
| 
jbe@453
 | 
    70     "member_id"     NOTNULL AND
 | 
| 
jbe@453
 | 
    71     "issue_id"      NOTNULL AND
 | 
| 
jbe@453
 | 
    72     "state"         NOTNULL AND
 | 
| 
jbe@453
 | 
    73     "initiative_id" NOTNULL AND
 | 
| 
jbe@453
 | 
    74     "draft_id"      NOTNULL AND
 | 
| 
jbe@453
 | 
    75     "suggestion_id" ISNULL  ) );
 | 
| 
jbe@453
 | 
    76 ALTER TABLE "event" ADD CONSTRAINT "null_constr_for_suggestion_creation" CHECK (
 | 
| 
jbe@453
 | 
    77   "event" != 'suggestion_created' OR (
 | 
| 
jbe@453
 | 
    78     "member_id"     NOTNULL AND
 | 
| 
jbe@453
 | 
    79     "issue_id"      NOTNULL AND
 | 
| 
jbe@453
 | 
    80     "state"         NOTNULL AND
 | 
| 
jbe@453
 | 
    81     "initiative_id" NOTNULL AND
 | 
| 
jbe@453
 | 
    82     "draft_id"      ISNULL  AND
 | 
| 
jbe@453
 | 
    83     "suggestion_id" NOTNULL ) );
 | 
| 
jbe@453
 | 
    84 
 | 
| 
jbe@453
 | 
    85 CREATE OR REPLACE FUNCTION "copy_timings_trigger"()
 | 
| 
jbe@453
 | 
    86   RETURNS TRIGGER
 | 
| 
jbe@453
 | 
    87   LANGUAGE 'plpgsql' VOLATILE AS $$
 | 
| 
jbe@453
 | 
    88     DECLARE
 | 
| 
jbe@453
 | 
    89       "policy_row" "policy"%ROWTYPE;
 | 
| 
jbe@453
 | 
    90     BEGIN
 | 
| 
jbe@453
 | 
    91       SELECT * INTO "policy_row" FROM "policy"
 | 
| 
jbe@453
 | 
    92         WHERE "id" = NEW."policy_id";
 | 
| 
jbe@453
 | 
    93       IF NEW."min_admission_time" ISNULL THEN
 | 
| 
jbe@453
 | 
    94         NEW."min_admission_time" := "policy_row"."min_admission_time";
 | 
| 
jbe@453
 | 
    95       END IF;
 | 
| 
jbe@453
 | 
    96       IF NEW."max_admission_time" ISNULL THEN
 | 
| 
jbe@453
 | 
    97         NEW."max_admission_time" := "policy_row"."max_admission_time";
 | 
| 
jbe@453
 | 
    98       END IF;
 | 
| 
jbe@453
 | 
    99       IF NEW."discussion_time" ISNULL THEN
 | 
| 
jbe@453
 | 
   100         NEW."discussion_time" := "policy_row"."discussion_time";
 | 
| 
jbe@453
 | 
   101       END IF;
 | 
| 
jbe@453
 | 
   102       IF NEW."verification_time" ISNULL THEN
 | 
| 
jbe@453
 | 
   103         NEW."verification_time" := "policy_row"."verification_time";
 | 
| 
jbe@453
 | 
   104       END IF;
 | 
| 
jbe@453
 | 
   105       IF NEW."voting_time" ISNULL THEN
 | 
| 
jbe@453
 | 
   106         NEW."voting_time" := "policy_row"."voting_time";
 | 
| 
jbe@453
 | 
   107       END IF;
 | 
| 
jbe@453
 | 
   108       RETURN NEW;
 | 
| 
jbe@453
 | 
   109     END;
 | 
| 
jbe@453
 | 
   110   $$;
 | 
| 
jbe@453
 | 
   111 
 | 
| 
jbe@453
 | 
   112 CREATE OR REPLACE FUNCTION "check_issue"
 | 
| 
jbe@453
 | 
   113   ( "issue_id_p" "issue"."id"%TYPE,
 | 
| 
jbe@453
 | 
   114     "persist"    "check_issue_persistence" )
 | 
| 
jbe@453
 | 
   115   RETURNS "check_issue_persistence"
 | 
| 
jbe@453
 | 
   116   LANGUAGE 'plpgsql' VOLATILE AS $$
 | 
| 
jbe@453
 | 
   117     DECLARE
 | 
| 
jbe@453
 | 
   118       "issue_row"      "issue"%ROWTYPE;
 | 
| 
jbe@453
 | 
   119       "policy_row"     "policy"%ROWTYPE;
 | 
| 
jbe@453
 | 
   120       "initiative_row" "initiative"%ROWTYPE;
 | 
| 
jbe@453
 | 
   121       "state_v"        "issue_state";
 | 
| 
jbe@453
 | 
   122     BEGIN
 | 
| 
jbe@453
 | 
   123       PERFORM "require_transaction_isolation"();
 | 
| 
jbe@453
 | 
   124       IF "persist" ISNULL THEN
 | 
| 
jbe@453
 | 
   125         SELECT * INTO "issue_row" FROM "issue" WHERE "id" = "issue_id_p"
 | 
| 
jbe@453
 | 
   126           FOR UPDATE;
 | 
| 
jbe@453
 | 
   127         IF "issue_row"."closed" NOTNULL THEN
 | 
| 
jbe@453
 | 
   128           RETURN NULL;
 | 
| 
jbe@453
 | 
   129         END IF;
 | 
| 
jbe@453
 | 
   130         "persist"."state" := "issue_row"."state";
 | 
| 
jbe@453
 | 
   131         IF
 | 
| 
jbe@453
 | 
   132           ( "issue_row"."state" = 'admission' AND now() >=
 | 
| 
jbe@453
 | 
   133             "issue_row"."created" + "issue_row"."max_admission_time" ) OR
 | 
| 
jbe@453
 | 
   134           ( "issue_row"."state" = 'discussion' AND now() >=
 | 
| 
jbe@453
 | 
   135             "issue_row"."accepted" + "issue_row"."discussion_time" ) OR
 | 
| 
jbe@453
 | 
   136           ( "issue_row"."state" = 'verification' AND now() >=
 | 
| 
jbe@453
 | 
   137             "issue_row"."half_frozen" + "issue_row"."verification_time" ) OR
 | 
| 
jbe@453
 | 
   138           ( "issue_row"."state" = 'voting' AND now() >=
 | 
| 
jbe@453
 | 
   139             "issue_row"."fully_frozen" + "issue_row"."voting_time" )
 | 
| 
jbe@453
 | 
   140         THEN
 | 
| 
jbe@453
 | 
   141           "persist"."phase_finished" := TRUE;
 | 
| 
jbe@453
 | 
   142         ELSE
 | 
| 
jbe@453
 | 
   143           "persist"."phase_finished" := FALSE;
 | 
| 
jbe@453
 | 
   144         END IF;
 | 
| 
jbe@453
 | 
   145         IF
 | 
| 
jbe@453
 | 
   146           NOT EXISTS (
 | 
| 
jbe@453
 | 
   147             -- all initiatives are revoked
 | 
| 
jbe@453
 | 
   148             SELECT NULL FROM "initiative"
 | 
| 
jbe@453
 | 
   149             WHERE "issue_id" = "issue_id_p" AND "revoked" ISNULL
 | 
| 
jbe@453
 | 
   150           ) AND (
 | 
| 
jbe@453
 | 
   151             -- and issue has not been accepted yet
 | 
| 
jbe@453
 | 
   152             "persist"."state" = 'admission' OR
 | 
| 
jbe@453
 | 
   153             -- or verification time has elapsed
 | 
| 
jbe@453
 | 
   154             ( "persist"."state" = 'verification' AND
 | 
| 
jbe@453
 | 
   155               "persist"."phase_finished" ) OR
 | 
| 
jbe@453
 | 
   156             -- or no initiatives have been revoked lately
 | 
| 
jbe@453
 | 
   157             NOT EXISTS (
 | 
| 
jbe@453
 | 
   158               SELECT NULL FROM "initiative"
 | 
| 
jbe@453
 | 
   159               WHERE "issue_id" = "issue_id_p"
 | 
| 
jbe@453
 | 
   160               AND now() < "revoked" + "issue_row"."verification_time"
 | 
| 
jbe@453
 | 
   161             )
 | 
| 
jbe@453
 | 
   162           )
 | 
| 
jbe@453
 | 
   163         THEN
 | 
| 
jbe@453
 | 
   164           "persist"."issue_revoked" := TRUE;
 | 
| 
jbe@453
 | 
   165         ELSE
 | 
| 
jbe@453
 | 
   166           "persist"."issue_revoked" := FALSE;
 | 
| 
jbe@453
 | 
   167         END IF;
 | 
| 
jbe@453
 | 
   168         IF "persist"."phase_finished" OR "persist"."issue_revoked" THEN
 | 
| 
jbe@453
 | 
   169           UPDATE "issue" SET "phase_finished" = now()
 | 
| 
jbe@453
 | 
   170             WHERE "id" = "issue_row"."id";
 | 
| 
jbe@453
 | 
   171           RETURN "persist";
 | 
| 
jbe@453
 | 
   172         ELSIF
 | 
| 
jbe@453
 | 
   173           "persist"."state" IN ('admission', 'discussion', 'verification')
 | 
| 
jbe@453
 | 
   174         THEN
 | 
| 
jbe@453
 | 
   175           RETURN "persist";
 | 
| 
jbe@453
 | 
   176         ELSE
 | 
| 
jbe@453
 | 
   177           RETURN NULL;
 | 
| 
jbe@453
 | 
   178         END IF;
 | 
| 
jbe@453
 | 
   179       END IF;
 | 
| 
jbe@453
 | 
   180       IF
 | 
| 
jbe@453
 | 
   181         "persist"."state" IN ('admission', 'discussion', 'verification') AND
 | 
| 
jbe@453
 | 
   182         coalesce("persist"."snapshot_created", FALSE) = FALSE
 | 
| 
jbe@453
 | 
   183       THEN
 | 
| 
jbe@453
 | 
   184         PERFORM "create_snapshot"("issue_id_p");
 | 
| 
jbe@453
 | 
   185         "persist"."snapshot_created" = TRUE;
 | 
| 
jbe@453
 | 
   186         IF "persist"."phase_finished" THEN
 | 
| 
jbe@453
 | 
   187           IF "persist"."state" = 'admission' THEN
 | 
| 
jbe@453
 | 
   188             PERFORM "set_snapshot_event"("issue_id_p", 'end_of_admission');
 | 
| 
jbe@453
 | 
   189           ELSIF "persist"."state" = 'discussion' THEN
 | 
| 
jbe@453
 | 
   190             PERFORM "set_snapshot_event"("issue_id_p", 'half_freeze');
 | 
| 
jbe@453
 | 
   191           ELSIF "persist"."state" = 'verification' THEN
 | 
| 
jbe@453
 | 
   192             PERFORM "set_snapshot_event"("issue_id_p", 'full_freeze');
 | 
| 
jbe@453
 | 
   193             SELECT * INTO "issue_row" FROM "issue" WHERE "id" = "issue_id_p";
 | 
| 
jbe@453
 | 
   194             SELECT * INTO "policy_row" FROM "policy"
 | 
| 
jbe@453
 | 
   195               WHERE "id" = "issue_row"."policy_id";
 | 
| 
jbe@453
 | 
   196             FOR "initiative_row" IN
 | 
| 
jbe@453
 | 
   197               SELECT * FROM "initiative"
 | 
| 
jbe@453
 | 
   198               WHERE "issue_id" = "issue_id_p" AND "revoked" ISNULL
 | 
| 
jbe@453
 | 
   199               FOR UPDATE
 | 
| 
jbe@453
 | 
   200             LOOP
 | 
| 
jbe@453
 | 
   201               IF
 | 
| 
jbe@453
 | 
   202                 "initiative_row"."polling" OR (
 | 
| 
jbe@453
 | 
   203                   "initiative_row"."satisfied_supporter_count" > 0 AND
 | 
| 
jbe@453
 | 
   204                   "initiative_row"."satisfied_supporter_count" *
 | 
| 
jbe@453
 | 
   205                   "policy_row"."initiative_quorum_den" >=
 | 
| 
jbe@453
 | 
   206                   "issue_row"."population" * "policy_row"."initiative_quorum_num"
 | 
| 
jbe@453
 | 
   207                 )
 | 
| 
jbe@453
 | 
   208               THEN
 | 
| 
jbe@453
 | 
   209                 UPDATE "initiative" SET "admitted" = TRUE
 | 
| 
jbe@453
 | 
   210                   WHERE "id" = "initiative_row"."id";
 | 
| 
jbe@453
 | 
   211               ELSE
 | 
| 
jbe@453
 | 
   212                 UPDATE "initiative" SET "admitted" = FALSE
 | 
| 
jbe@453
 | 
   213                   WHERE "id" = "initiative_row"."id";
 | 
| 
jbe@453
 | 
   214               END IF;
 | 
| 
jbe@453
 | 
   215             END LOOP;
 | 
| 
jbe@453
 | 
   216           END IF;
 | 
| 
jbe@453
 | 
   217         END IF;
 | 
| 
jbe@453
 | 
   218         RETURN "persist";
 | 
| 
jbe@453
 | 
   219       END IF;
 | 
| 
jbe@453
 | 
   220       IF
 | 
| 
jbe@453
 | 
   221         "persist"."state" IN ('admission', 'discussion', 'verification') AND
 | 
| 
jbe@453
 | 
   222         coalesce("persist"."harmonic_weights_set", FALSE) = FALSE
 | 
| 
jbe@453
 | 
   223       THEN
 | 
| 
jbe@453
 | 
   224         PERFORM "set_harmonic_initiative_weights"("issue_id_p");
 | 
| 
jbe@453
 | 
   225         "persist"."harmonic_weights_set" = TRUE;
 | 
| 
jbe@453
 | 
   226         IF
 | 
| 
jbe@453
 | 
   227           "persist"."phase_finished" OR
 | 
| 
jbe@453
 | 
   228           "persist"."issue_revoked" OR
 | 
| 
jbe@453
 | 
   229           "persist"."state" = 'admission'
 | 
| 
jbe@453
 | 
   230         THEN
 | 
| 
jbe@453
 | 
   231           RETURN "persist";
 | 
| 
jbe@453
 | 
   232         ELSE
 | 
| 
jbe@453
 | 
   233           RETURN NULL;
 | 
| 
jbe@453
 | 
   234         END IF;
 | 
| 
jbe@453
 | 
   235       END IF;
 | 
| 
jbe@453
 | 
   236       IF "persist"."issue_revoked" THEN
 | 
| 
jbe@453
 | 
   237         IF "persist"."state" = 'admission' THEN
 | 
| 
jbe@453
 | 
   238           "state_v" := 'canceled_revoked_before_accepted';
 | 
| 
jbe@453
 | 
   239         ELSIF "persist"."state" = 'discussion' THEN
 | 
| 
jbe@453
 | 
   240           "state_v" := 'canceled_after_revocation_during_discussion';
 | 
| 
jbe@453
 | 
   241         ELSIF "persist"."state" = 'verification' THEN
 | 
| 
jbe@453
 | 
   242           "state_v" := 'canceled_after_revocation_during_verification';
 | 
| 
jbe@453
 | 
   243         END IF;
 | 
| 
jbe@453
 | 
   244         UPDATE "issue" SET
 | 
| 
jbe@453
 | 
   245           "state"          = "state_v",
 | 
| 
jbe@453
 | 
   246           "closed"         = "phase_finished",
 | 
| 
jbe@453
 | 
   247           "phase_finished" = NULL
 | 
| 
jbe@453
 | 
   248           WHERE "id" = "issue_id_p";
 | 
| 
jbe@453
 | 
   249         RETURN NULL;
 | 
| 
jbe@453
 | 
   250       END IF;
 | 
| 
jbe@453
 | 
   251       IF "persist"."state" = 'admission' THEN
 | 
| 
jbe@453
 | 
   252         SELECT * INTO "issue_row" FROM "issue" WHERE "id" = "issue_id_p"
 | 
| 
jbe@453
 | 
   253           FOR UPDATE;
 | 
| 
jbe@453
 | 
   254         SELECT * INTO "policy_row"
 | 
| 
jbe@453
 | 
   255           FROM "policy" WHERE "id" = "issue_row"."policy_id";
 | 
| 
jbe@453
 | 
   256         IF 
 | 
| 
jbe@453
 | 
   257           ( now() >=
 | 
| 
jbe@453
 | 
   258             "issue_row"."created" + "issue_row"."min_admission_time" ) AND
 | 
| 
jbe@453
 | 
   259           EXISTS (
 | 
| 
jbe@453
 | 
   260             SELECT NULL FROM "initiative"
 | 
| 
jbe@453
 | 
   261             WHERE "issue_id" = "issue_id_p"
 | 
| 
jbe@453
 | 
   262             AND "supporter_count" > 0
 | 
| 
jbe@453
 | 
   263             AND "supporter_count" * "policy_row"."issue_quorum_den"
 | 
| 
jbe@453
 | 
   264             >= "issue_row"."population" * "policy_row"."issue_quorum_num"
 | 
| 
jbe@453
 | 
   265           )
 | 
| 
jbe@453
 | 
   266         THEN
 | 
| 
jbe@453
 | 
   267           UPDATE "issue" SET
 | 
| 
jbe@453
 | 
   268             "state"          = 'discussion',
 | 
| 
jbe@453
 | 
   269             "accepted"       = coalesce("phase_finished", now()),
 | 
| 
jbe@453
 | 
   270             "phase_finished" = NULL
 | 
| 
jbe@453
 | 
   271             WHERE "id" = "issue_id_p";
 | 
| 
jbe@453
 | 
   272         ELSIF "issue_row"."phase_finished" NOTNULL THEN
 | 
| 
jbe@453
 | 
   273           UPDATE "issue" SET
 | 
| 
jbe@453
 | 
   274             "state"          = 'canceled_issue_not_accepted',
 | 
| 
jbe@453
 | 
   275             "closed"         = "phase_finished",
 | 
| 
jbe@453
 | 
   276             "phase_finished" = NULL
 | 
| 
jbe@453
 | 
   277             WHERE "id" = "issue_id_p";
 | 
| 
jbe@453
 | 
   278         END IF;
 | 
| 
jbe@453
 | 
   279         RETURN NULL;
 | 
| 
jbe@453
 | 
   280       END IF;
 | 
| 
jbe@453
 | 
   281       IF "persist"."phase_finished" THEN
 | 
| 
jbe@453
 | 
   282         IF "persist"."state" = 'discussion' THEN
 | 
| 
jbe@453
 | 
   283           UPDATE "issue" SET
 | 
| 
jbe@453
 | 
   284             "state"          = 'verification',
 | 
| 
jbe@453
 | 
   285             "half_frozen"    = "phase_finished",
 | 
| 
jbe@453
 | 
   286             "phase_finished" = NULL
 | 
| 
jbe@453
 | 
   287             WHERE "id" = "issue_id_p";
 | 
| 
jbe@453
 | 
   288           RETURN NULL;
 | 
| 
jbe@453
 | 
   289         END IF;
 | 
| 
jbe@453
 | 
   290         IF "persist"."state" = 'verification' THEN
 | 
| 
jbe@453
 | 
   291           SELECT * INTO "issue_row" FROM "issue" WHERE "id" = "issue_id_p"
 | 
| 
jbe@453
 | 
   292             FOR UPDATE;
 | 
| 
jbe@453
 | 
   293           SELECT * INTO "policy_row" FROM "policy"
 | 
| 
jbe@453
 | 
   294             WHERE "id" = "issue_row"."policy_id";
 | 
| 
jbe@453
 | 
   295           IF EXISTS (
 | 
| 
jbe@453
 | 
   296             SELECT NULL FROM "initiative"
 | 
| 
jbe@453
 | 
   297             WHERE "issue_id" = "issue_id_p" AND "admitted" = TRUE
 | 
| 
jbe@453
 | 
   298           ) THEN
 | 
| 
jbe@453
 | 
   299             UPDATE "issue" SET
 | 
| 
jbe@453
 | 
   300               "state"          = 'voting',
 | 
| 
jbe@453
 | 
   301               "fully_frozen"   = "phase_finished",
 | 
| 
jbe@453
 | 
   302               "phase_finished" = NULL
 | 
| 
jbe@453
 | 
   303               WHERE "id" = "issue_id_p";
 | 
| 
jbe@453
 | 
   304           ELSE
 | 
| 
jbe@453
 | 
   305             UPDATE "issue" SET
 | 
| 
jbe@453
 | 
   306               "state"          = 'canceled_no_initiative_admitted',
 | 
| 
jbe@453
 | 
   307               "fully_frozen"   = "phase_finished",
 | 
| 
jbe@453
 | 
   308               "closed"         = "phase_finished",
 | 
| 
jbe@453
 | 
   309               "phase_finished" = NULL
 | 
| 
jbe@453
 | 
   310               WHERE "id" = "issue_id_p";
 | 
| 
jbe@453
 | 
   311             -- NOTE: The following DELETE statements have effect only when
 | 
| 
jbe@453
 | 
   312             --       issue state has been manipulated
 | 
| 
jbe@453
 | 
   313             DELETE FROM "direct_voter"     WHERE "issue_id" = "issue_id_p";
 | 
| 
jbe@453
 | 
   314             DELETE FROM "delegating_voter" WHERE "issue_id" = "issue_id_p";
 | 
| 
jbe@453
 | 
   315             DELETE FROM "battle"           WHERE "issue_id" = "issue_id_p";
 | 
| 
jbe@453
 | 
   316           END IF;
 | 
| 
jbe@453
 | 
   317           RETURN NULL;
 | 
| 
jbe@453
 | 
   318         END IF;
 | 
| 
jbe@453
 | 
   319         IF "persist"."state" = 'voting' THEN
 | 
| 
jbe@453
 | 
   320           IF coalesce("persist"."closed_voting", FALSE) = FALSE THEN
 | 
| 
jbe@453
 | 
   321             PERFORM "close_voting"("issue_id_p");
 | 
| 
jbe@453
 | 
   322             "persist"."closed_voting" = TRUE;
 | 
| 
jbe@453
 | 
   323             RETURN "persist";
 | 
| 
jbe@453
 | 
   324           END IF;
 | 
| 
jbe@453
 | 
   325           PERFORM "calculate_ranks"("issue_id_p");
 | 
| 
jbe@453
 | 
   326           RETURN NULL;
 | 
| 
jbe@453
 | 
   327         END IF;
 | 
| 
jbe@453
 | 
   328       END IF;
 | 
| 
jbe@453
 | 
   329       RAISE WARNING 'should not happen';
 | 
| 
jbe@453
 | 
   330       RETURN NULL;
 | 
| 
jbe@453
 | 
   331     END;
 | 
| 
jbe@453
 | 
   332   $$;
 | 
| 
jbe@453
 | 
   333 
 | 
| 
jbe@456
 | 
   334 -- temporarily drop deferred trigger to allow UPDATE with subsequent ALTER TABLE:
 | 
| 
jbe@456
 | 
   335 DROP TRIGGER "issue_requires_first_initiative" ON "issue";
 | 
| 
jbe@456
 | 
   336 
 | 
| 
jbe@456
 | 
   337 -- set "min_admission_time" values where appropriate:
 | 
| 
jbe@456
 | 
   338 UPDATE "policy" SET "min_admission_time" = '0' WHERE "max_admission_time" NOTNULL;
 | 
| 
jbe@456
 | 
   339 UPDATE "issue" SET "min_admission_time" = '0' WHERE "max_admission_time" NOTNULL;
 | 
| 
jbe@456
 | 
   340 
 | 
| 
jbe@456
 | 
   341 -- add constraints related to "min_admission_time" after UPDATE:
 | 
| 
jbe@456
 | 
   342 ALTER TABLE "policy" ADD CONSTRAINT "timing" CHECK (
 | 
| 
jbe@456
 | 
   343   ( "polling" = FALSE AND
 | 
| 
jbe@456
 | 
   344     "min_admission_time" NOTNULL AND "max_admission_time" NOTNULL AND
 | 
| 
jbe@456
 | 
   345     "min_admission_time" <= "max_admission_time" AND
 | 
| 
jbe@456
 | 
   346     "discussion_time" NOTNULL AND
 | 
| 
jbe@456
 | 
   347     "verification_time" NOTNULL AND
 | 
| 
jbe@456
 | 
   348     "voting_time" NOTNULL ) OR
 | 
| 
jbe@456
 | 
   349   ( "polling" = TRUE AND
 | 
| 
jbe@456
 | 
   350     "min_admission_time" ISNULL AND "max_admission_time" ISNULL AND
 | 
| 
jbe@456
 | 
   351     "discussion_time" NOTNULL AND
 | 
| 
jbe@456
 | 
   352     "verification_time" NOTNULL AND
 | 
| 
jbe@456
 | 
   353     "voting_time" NOTNULL ) OR
 | 
| 
jbe@456
 | 
   354   ( "polling" = TRUE AND
 | 
| 
jbe@456
 | 
   355     "min_admission_time" ISNULL AND "max_admission_time" ISNULL AND
 | 
| 
jbe@456
 | 
   356     "discussion_time" ISNULL AND
 | 
| 
jbe@456
 | 
   357     "verification_time" ISNULL AND
 | 
| 
jbe@456
 | 
   358     "voting_time" ISNULL ) );
 | 
| 
jbe@456
 | 
   359 
 | 
| 
jbe@456
 | 
   360 ALTER TABLE "issue" ADD CONSTRAINT "admission_time_not_null_unless_instantly_accepted" CHECK (
 | 
| 
jbe@456
 | 
   361   ("min_admission_time" NOTNULL) = ("max_admission_time" NOTNULL) AND
 | 
| 
jbe@456
 | 
   362   ("min_admission_time" NOTNULL OR ("accepted" NOTNULL AND "accepted" = "created")) );
 | 
| 
jbe@456
 | 
   363 
 | 
| 
jbe@456
 | 
   364 -- re-add temporarily dropped trigger:
 | 
| 
jbe@456
 | 
   365 CREATE CONSTRAINT TRIGGER "issue_requires_first_initiative"
 | 
| 
jbe@456
 | 
   366   AFTER INSERT OR UPDATE ON "issue" DEFERRABLE INITIALLY DEFERRED
 | 
| 
jbe@456
 | 
   367   FOR EACH ROW EXECUTE PROCEDURE
 | 
| 
jbe@456
 | 
   368   "issue_requires_first_initiative_trigger"();
 | 
| 
jbe@456
 | 
   369 COMMENT ON TRIGGER "issue_requires_first_initiative" ON "issue" IS 'Ensure that new issues have at least one initiative';
 | 
| 
jbe@456
 | 
   370 
 | 
| 
jbe@453
 | 
   371 COMMIT;
 |