liquid_feedback_core

annotate update/core-update.v1.4.0-v1.5.0.sql @ 182:4c03ef70dd92

Removed trigger "set_activated_timestamp"; Updated update script
author jbe
date Fri Jul 29 15:23:42 2011 +0200 (2011-07-29)
parents 1024224df943
children ed2f94a397cd
rev   line source
jbe@178 1 SELECT "calculate_ranks"("id") FROM "issue_with_ranks_missing";
jbe@178 2
jbe@177 3 BEGIN;
jbe@177 4
jbe@177 5 CREATE OR REPLACE VIEW "liquid_feedback_version" AS
jbe@177 6 SELECT * FROM (VALUES ('1.5.0_devel', 1, 5, -1))
jbe@177 7 AS "subquery"("string", "major", "minor", "revision");
jbe@177 8
jbe@182 9 ALTER TABLE "member" ADD COLUMN "invite_code" TEXT UNIQUE;
jbe@182 10 ALTER TABLE "member" ADD COLUMN "admin_comment" TEXT;
jbe@182 11 ALTER TABLE "member" ADD COLUMN "activated" TIMESTAMPTZ;
jbe@182 12 ALTER TABLE "member" ALTER COLUMN "active" SET DEFAULT FALSE;
jbe@177 13 ALTER TABLE "member" ADD COLUMN "formatting_engine" TEXT;
jbe@182 14
jbe@182 15 COMMENT ON COLUMN "member"."created" IS 'Creation of member record and/or invite code';
jbe@182 16 COMMENT ON COLUMN "member"."invite_code" IS 'Optional invite code, to allow a member to initialize his/her account the first time';
jbe@182 17 COMMENT ON COLUMN "member"."activated" IS 'Timestamp of activation of account (i.e. usage of "invite_code"); needs to be set for "active" members';
jbe@182 18 COMMENT ON COLUMN "member"."active" IS 'Memberships, support and votes are taken into account when corresponding members are marked as active. When the user does not log in for an extended period of time, this flag may be set to FALSE. If the user is not locked, he/she may reset the active flag by logging in (has to be set to TRUE by frontend on every login).';
jbe@177 19 COMMENT ON COLUMN "member"."formatting_engine" IS 'Allows different formatting engines (i.e. wiki formats) to be used for "member"."statement"';
jbe@177 20
jbe@177 21 CREATE TABLE "rendered_member_statement" (
jbe@177 22 PRIMARY KEY ("member_id", "format"),
jbe@177 23 "member_id" INT8 REFERENCES "member" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
jbe@177 24 "format" TEXT,
jbe@177 25 "content" TEXT NOT NULL );
jbe@177 26
jbe@177 27 COMMENT ON TABLE "rendered_member_statement" IS 'This table may be used by frontends to cache "rendered" member statements (e.g. HTML output generated from wiki text)';
jbe@177 28
jbe@177 29 ALTER TABLE "policy" ADD COLUMN "direct_majority_num" INT4 NOT NULL DEFAULT 1;
jbe@177 30 ALTER TABLE "policy" ADD COLUMN "direct_majority_den" INT4 NOT NULL DEFAULT 2;
jbe@177 31 ALTER TABLE "policy" ADD COLUMN "direct_majority_strict" BOOLEAN NOT NULL DEFAULT TRUE;
jbe@177 32 ALTER TABLE "policy" ADD COLUMN "direct_majority_positive" INT4 NOT NULL DEFAULT 0;
jbe@177 33 ALTER TABLE "policy" ADD COLUMN "direct_majority_non_negative" INT4 NOT NULL DEFAULT 0;
jbe@177 34 ALTER TABLE "policy" ADD COLUMN "indirect_majority_num" INT4 NOT NULL DEFAULT 1;
jbe@177 35 ALTER TABLE "policy" ADD COLUMN "indirect_majority_den" INT4 NOT NULL DEFAULT 2;
jbe@177 36 ALTER TABLE "policy" ADD COLUMN "indirect_majority_strict" BOOLEAN NOT NULL DEFAULT TRUE;
jbe@177 37 ALTER TABLE "policy" ADD COLUMN "indirect_majority_positive" INT4 NOT NULL DEFAULT 0;
jbe@177 38 ALTER TABLE "policy" ADD COLUMN "indirect_majority_non_negative" INT4 NOT NULL DEFAULT 0;
jbe@177 39 ALTER TABLE "policy" ADD COLUMN "no_reverse_beat_path" BOOLEAN NOT NULL DEFAULT TRUE;
jbe@177 40 ALTER TABLE "policy" ADD COLUMN "no_multistage_majority" BOOLEAN NOT NULL DEFAULT FALSE;
jbe@177 41
jbe@177 42 UPDATE "policy" SET
jbe@177 43 "direct_majority_num" = "majority_num",
jbe@177 44 "direct_majority_den" = "majority_den",
jbe@177 45 "direct_majority_strict" = "majority_strict",
jbe@177 46 "indirect_majority_num" = "majority_num",
jbe@177 47 "indirect_majority_den" = "majority_den",
jbe@177 48 "indirect_majority_strict" = "majority_strict";
jbe@177 49
jbe@177 50 ALTER TABLE "policy" DROP COLUMN "majority_num";
jbe@177 51 ALTER TABLE "policy" DROP COLUMN "majority_den";
jbe@177 52 ALTER TABLE "policy" DROP COLUMN "majority_strict";
jbe@177 53
jbe@177 54 COMMENT ON COLUMN "policy"."direct_majority_num" IS 'Numerator of fraction of neccessary direct majority for initiatives to be attainable as winner';
jbe@177 55 COMMENT ON COLUMN "policy"."direct_majority_den" IS 'Denominator of fraction of neccessary direct majority for initaitives to be attainable as winner';
jbe@177 56 COMMENT ON COLUMN "policy"."direct_majority_strict" IS 'If TRUE, then the direct majority must be strictly greater than "direct_majority_num"/"direct_majority_den", otherwise it may also be equal.';
jbe@177 57 COMMENT ON COLUMN "policy"."direct_majority_positive" IS 'Absolute number of "positive_votes" neccessary for an initiative to be attainable as winner';
jbe@177 58 COMMENT ON COLUMN "policy"."direct_majority_non_negative" IS 'Absolute number of sum of "positive_votes" and abstentions neccessary for an initiative to be attainable as winner';
jbe@177 59 COMMENT ON COLUMN "policy"."indirect_majority_num" IS 'Numerator of fraction of neccessary indirect majority (through beat path) for initiatives to be attainable as winner';
jbe@177 60 COMMENT ON COLUMN "policy"."indirect_majority_den" IS 'Denominator of fraction of neccessary indirect majority (through beat path) for initiatives to be attainable as winner';
jbe@177 61 COMMENT ON COLUMN "policy"."indirect_majority_strict" IS 'If TRUE, then the indirect majority must be strictly greater than "indirect_majority_num"/"indirect_majority_den", otherwise it may also be equal.';
jbe@177 62 COMMENT ON COLUMN "policy"."indirect_majority_positive" IS 'Absolute number of votes in favor of the winner neccessary in a beat path to the status quo for an initaitive to be attainable as winner';
jbe@177 63 COMMENT ON COLUMN "policy"."indirect_majority_non_negative" IS 'Absolute number of sum of votes in favor and abstentions in a beat path to the status quo for an initiative to be attainable as winner';
jbe@177 64 COMMENT ON COLUMN "policy"."no_reverse_beat_path" IS 'Causes initiatives with "reverse_beat_path" flag to not be "eligible", thus disallowing them to be winner. See comment on column "initiative"."reverse_beat_path". This option ensures both that a winning initiative is never tied in a (weak) condorcet paradox with the status quo and a winning initiative always beats the status quo directly with a simple majority.';
jbe@177 65 COMMENT ON COLUMN "policy"."no_multistage_majority" IS 'Causes initiatives with "multistage_majority" flag to not be "eligible", thus disallowing them to be winner. See comment on column "initiative"."multistage_majority". This disqualifies initiatives which could cause an instable result. An instable result in this meaning is a result such that repeating the ballot with same preferences but with the winner of the first ballot as status quo would lead to a different winner in the second ballot. If there are no direct majorities required for the winner, or if in direct comparison only simple majorities are required and "no_reverse_beat_path" is true, then results are always stable and this flag does not have any effect on the winner (but still affects the "eligible" flag of an "initiative").';
jbe@177 66
jbe@177 67 ALTER TABLE "area" DROP COLUMN "autoreject_weight";
jbe@177 68
jbe@177 69 DROP VIEW "open_issue";
jbe@177 70 DROP VIEW "issue_with_ranks_missing";
jbe@177 71
jbe@177 72 ALTER TABLE "issue" DROP COLUMN "vote_now";
jbe@177 73 ALTER TABLE "issue" DROP COLUMN "vote_later";
jbe@177 74 ALTER TABLE "issue" ADD COLUMN "status_quo_schulze_rank" INT4;
jbe@177 75
jbe@177 76 CREATE VIEW "open_issue" AS
jbe@177 77 SELECT * FROM "issue" WHERE "closed" ISNULL;
jbe@177 78
jbe@177 79 COMMENT ON VIEW "open_issue" IS 'All open issues';
jbe@177 80
jbe@177 81 CREATE VIEW "issue_with_ranks_missing" AS
jbe@177 82 SELECT * FROM "issue"
jbe@177 83 WHERE "fully_frozen" NOTNULL
jbe@177 84 AND "closed" NOTNULL
jbe@177 85 AND "ranks_available" = FALSE;
jbe@177 86
jbe@177 87 COMMENT ON VIEW "issue_with_ranks_missing" IS 'Issues where voting was finished, but no ranks have been calculated yet';
jbe@177 88
jbe@177 89 COMMENT ON COLUMN "issue"."half_frozen" IS 'Point in time, when "discussion_time" has elapsed; Frontends must ensure that for half_frozen issues a) initiatives are not revoked, b) no new drafts are created, c) no initiators are added or removed.';
jbe@177 90 COMMENT ON COLUMN "issue"."snapshot" IS 'Point in time, when snapshot tables have been updated and "population" and *_count values were precalculated';
jbe@177 91 COMMENT ON COLUMN "issue"."status_quo_schulze_rank" IS 'Schulze rank of status quo, as calculated by "calculate_ranks" function';
jbe@177 92
jbe@179 93 DROP VIEW "battle_view";
jbe@179 94
jbe@180 95 ALTER TABLE "initiative" DROP CONSTRAINT "non_admitted_initiatives_cant_contain_voting_results";
jbe@180 96 ALTER TABLE "initiative" DROP CONSTRAINT "all_or_none_of_positive_votes_negative_votes_and_agreed_must_be_null";
jbe@180 97 ALTER TABLE "initiative" DROP CONSTRAINT "non_agreed_initiatives_cant_get_a_rank";
jbe@180 98
jbe@178 99 ALTER TABLE "initiative" DROP COLUMN "agreed";
jbe@177 100 ALTER TABLE "initiative" ADD COLUMN "direct_majority" BOOLEAN;
jbe@177 101 ALTER TABLE "initiative" ADD COLUMN "indirect_majority" BOOLEAN;
jbe@177 102 ALTER TABLE "initiative" ADD COLUMN "schulze_rank" INT4;
jbe@177 103 ALTER TABLE "initiative" ADD COLUMN "better_than_status_quo" BOOLEAN;
jbe@177 104 ALTER TABLE "initiative" ADD COLUMN "worse_than_status_quo" BOOLEAN;
jbe@177 105 ALTER TABLE "initiative" ADD COLUMN "reverse_beat_path" BOOLEAN;
jbe@177 106 ALTER TABLE "initiative" ADD COLUMN "multistage_majority" BOOLEAN;
jbe@177 107 ALTER TABLE "initiative" ADD COLUMN "eligible" BOOLEAN;
jbe@177 108 ALTER TABLE "initiative" ADD COLUMN "winner" BOOLEAN;
jbe@177 109
jbe@177 110 ALTER TABLE "initiative" ADD CONSTRAINT "non_admitted_initiatives_cant_contain_voting_results" CHECK (
jbe@177 111 ( "admitted" NOTNULL AND "admitted" = TRUE ) OR
jbe@177 112 ( "positive_votes" ISNULL AND "negative_votes" ISNULL AND
jbe@177 113 "direct_majority" ISNULL AND "indirect_majority" ISNULL AND
jbe@177 114 "schulze_rank" ISNULL AND
jbe@177 115 "better_than_status_quo" ISNULL AND "worse_than_status_quo" ISNULL AND
jbe@177 116 "reverse_beat_path" ISNULL AND "multistage_majority" ISNULL AND
jbe@177 117 "eligible" ISNULL AND "winner" ISNULL AND "rank" ISNULL ) );
jbe@177 118 ALTER TABLE "initiative" ADD CONSTRAINT "better_excludes_worse" CHECK (NOT ("better_than_status_quo" AND "worse_than_status_quo"));
jbe@177 119 ALTER TABLE "initiative" ADD CONSTRAINT "minimum_requirement_to_be_eligible" CHECK (
jbe@177 120 "eligible" = FALSE OR
jbe@177 121 ("direct_majority" AND "indirect_majority" AND "better_than_status_quo") );
jbe@177 122 ALTER TABLE "initiative" ADD CONSTRAINT "winner_must_be_eligible" CHECK ("winner"=FALSE OR "eligible"=TRUE);
jbe@177 123 ALTER TABLE "initiative" ADD CONSTRAINT "winner_must_have_first_rank" CHECK ("winner"=FALSE OR "rank"=1);
jbe@177 124 ALTER TABLE "initiative" ADD CONSTRAINT "eligible_at_first_rank_is_winner" CHECK ("eligible"=FALSE OR "rank"!=1 OR "winner"=TRUE);
jbe@177 125 ALTER TABLE "initiative" ADD CONSTRAINT "unique_rank_per_issue" UNIQUE ("issue_id", "rank");
jbe@177 126
jbe@177 127 COMMENT ON COLUMN "initiative"."direct_majority" IS 'TRUE, if "positive_votes"/("positive_votes"+"negative_votes") is strictly greater or greater-equal than "direct_majority_num"/"direct_majority_den", and "positive_votes" is greater-equal than "direct_majority_positive", and ("positive_votes"+abstentions) is greater-equal than "direct_majority_non_negative"';
jbe@177 128 COMMENT ON COLUMN "initiative"."indirect_majority" IS 'Same as "direct_majority", but also considering indirect beat paths';
jbe@177 129 COMMENT ON COLUMN "initiative"."schulze_rank" IS 'Schulze-Ranking without tie-breaking';
jbe@177 130 COMMENT ON COLUMN "initiative"."better_than_status_quo" IS 'TRUE, if initiative has a schulze-ranking better than the status quo (without tie-breaking)';
jbe@177 131 COMMENT ON COLUMN "initiative"."worse_than_status_quo" IS 'TRUE, if initiative has a schulze-ranking worse than the status quo (without tie-breaking)';
jbe@177 132 COMMENT ON COLUMN "initiative"."reverse_beat_path" IS 'TRUE, if there is a beat path (may include ties), from this initiative to the status quo';
jbe@177 133 COMMENT ON COLUMN "initiative"."multistage_majority" IS 'TRUE, if either (a) this initiative has no better rank than the status quo, or (b) there exists a better ranked initiative X, which directly beats this initiative, and either more voters prefer X to this initiative than voters preferring X to the status quo or less voters prefer this initiative to X than voters preferring the status quo to X';
jbe@177 134 COMMENT ON COLUMN "initiative"."eligible" IS 'Initiative is "attainable" and depending on selected policy has no "reverse_beat_path" or "multistage_majority"';
jbe@177 135 COMMENT ON COLUMN "initiative"."winner" IS 'Winner is the "eligible" initiative with best "schulze_rank" and in case of ties with lowest "id"';
jbe@177 136 COMMENT ON COLUMN "initiative"."rank" IS 'Unique ranking for all "admitted" initiatives per issue; lower rank is better; a winner always has rank 1, but rank 1 does not imply that an initiative is winner; initiatives with "direct_majority" AND "indirect_majority" always have a better (lower) rank than other initiatives';
jbe@177 137
jbe@177 138 ALTER TABLE "battle" DROP CONSTRAINT "battle_pkey";
jbe@177 139 ALTER TABLE "battle" ALTER COLUMN "issue_id" SET NOT NULL;
jbe@177 140 ALTER TABLE "battle" ADD CONSTRAINT "initiative_ids_not_equal" CHECK (
jbe@177 141 "winning_initiative_id" != "losing_initiative_id" OR
jbe@177 142 ( ("winning_initiative_id" NOTNULL AND "losing_initiative_id" ISNULL) OR
jbe@177 143 ("winning_initiative_id" ISNULL AND "losing_initiative_id" NOTNULL) ) );
jbe@177 144
jbe@177 145 CREATE UNIQUE INDEX "battle_winning_losing_idx" ON "battle" ("issue_id", "winning_initiative_id", "losing_initiative_id");
jbe@177 146 CREATE UNIQUE INDEX "battle_winning_null_idx" ON "battle" ("issue_id", "winning_initiative_id") WHERE "losing_initiative_id" ISNULL;
jbe@177 147 CREATE UNIQUE INDEX "battle_null_losing_idx" ON "battle" ("issue_id", "losing_initiative_id") WHERE "winning_initiative_id" ISNULL;
jbe@177 148
jbe@177 149 ALTER TABLE "suggestion" ADD COLUMN "draft_id" INT8;
jbe@177 150 -- more later
jbe@177 151
jbe@177 152 ALTER TABLE "suggestion" ADD FOREIGN KEY ("initiative_id", "draft_id") REFERENCES "draft" ("initiative_id", "id") ON DELETE NO ACTION ON UPDATE CASCADE;
jbe@177 153 ALTER TABLE "suggestion" ADD COLUMN "formatting_engine" TEXT;
jbe@177 154 ALTER TABLE "suggestion" RENAME COLUMN "description" TO "content";
jbe@177 155
jbe@177 156 DROP TRIGGER "update_text_search_data" ON "suggestion";
jbe@177 157
jbe@177 158 CREATE TRIGGER "update_text_search_data"
jbe@177 159 BEFORE INSERT OR UPDATE ON "suggestion"
jbe@177 160 FOR EACH ROW EXECUTE PROCEDURE
jbe@177 161 tsvector_update_trigger('text_search_data', 'pg_catalog.simple',
jbe@177 162 "name", "content");
jbe@177 163
jbe@177 164 COMMENT ON COLUMN "suggestion"."draft_id" IS 'Draft, which the author has seen when composing the suggestion; should always be set by a frontend, but defaults to current draft of the initiative (implemented by trigger "default_for_draft_id")';
jbe@177 165
jbe@177 166 CREATE TABLE "rendered_suggestion" (
jbe@177 167 PRIMARY KEY ("suggestion_id", "format"),
jbe@177 168 "suggestion_id" INT8 REFERENCES "suggestion" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
jbe@177 169 "format" TEXT,
jbe@177 170 "content" TEXT NOT NULL );
jbe@177 171
jbe@177 172 COMMENT ON TABLE "rendered_suggestion" IS 'This table may be used by frontends to cache "rendered" drafts (e.g. HTML output generated from wiki text)';
jbe@177 173
jbe@177 174 DROP VIEW "area_member_count";
jbe@177 175
jbe@177 176 ALTER TABLE "membership" DROP COLUMN "autoreject";
jbe@177 177
jbe@177 178 ALTER TABLE "interest" DROP COLUMN "autoreject";
jbe@177 179 ALTER TABLE "interest" DROP COLUMN "voting_requested";
jbe@177 180
jbe@177 181 ALTER TABLE "supporter" DROP CONSTRAINT "supporter_initiative_id_fkey";
jbe@177 182 ALTER TABLE "supporter" ADD FOREIGN KEY ("initiative_id", "draft_id") REFERENCES "draft" ("initiative_id", "id") ON DELETE NO ACTION ON UPDATE CASCADE;
jbe@177 183
jbe@177 184 COMMENT ON COLUMN "supporter"."draft_id" IS 'Latest seen draft; should always be set by a frontend, but defaults to current draft of the initiative (implemented by trigger "default_for_draft_id")';
jbe@177 185
jbe@177 186 ALTER TABLE "direct_interest_snapshot" DROP COLUMN "voting_requested";
jbe@177 187 ALTER TABLE "direct_voter" DROP COLUMN "autoreject";
jbe@177 188
jbe@177 189 DROP TRIGGER "default_for_draft_id" ON "supporter";
jbe@177 190 DROP FUNCTION "supporter_default_for_draft_id_trigger"();
jbe@177 191
jbe@177 192 CREATE FUNCTION "default_for_draft_id_trigger"()
jbe@177 193 RETURNS TRIGGER
jbe@177 194 LANGUAGE 'plpgsql' VOLATILE AS $$
jbe@177 195 BEGIN
jbe@177 196 IF NEW."draft_id" ISNULL THEN
jbe@177 197 SELECT "id" INTO NEW."draft_id" FROM "current_draft"
jbe@177 198 WHERE "initiative_id" = NEW."initiative_id";
jbe@177 199 END IF;
jbe@177 200 RETURN NEW;
jbe@177 201 END;
jbe@177 202 $$;
jbe@177 203
jbe@177 204 CREATE TRIGGER "default_for_draft_id" BEFORE INSERT OR UPDATE ON "suggestion"
jbe@177 205 FOR EACH ROW EXECUTE PROCEDURE "default_for_draft_id_trigger"();
jbe@177 206 CREATE TRIGGER "default_for_draft_id" BEFORE INSERT OR UPDATE ON "supporter"
jbe@177 207 FOR EACH ROW EXECUTE PROCEDURE "default_for_draft_id_trigger"();
jbe@177 208
jbe@177 209 COMMENT ON FUNCTION "default_for_draft_id_trigger"() IS 'Implementation of trigger "default_for_draft" on tables "supporter" and "suggestion"';
jbe@177 210 COMMENT ON TRIGGER "default_for_draft_id" ON "suggestion" IS 'If "draft_id" is NULL, then use the current draft of the initiative as default';
jbe@177 211 COMMENT ON TRIGGER "default_for_draft_id" ON "supporter" IS 'If "draft_id" is NULL, then use the current draft of the initiative as default';
jbe@177 212
jbe@177 213 CREATE VIEW "area_member_count" AS
jbe@177 214 SELECT
jbe@177 215 "area"."id" AS "area_id",
jbe@177 216 count("member"."id") AS "direct_member_count",
jbe@177 217 coalesce(
jbe@177 218 sum(
jbe@177 219 CASE WHEN "member"."id" NOTNULL THEN
jbe@177 220 "membership_weight"("area"."id", "member"."id")
jbe@177 221 ELSE 0 END
jbe@177 222 )
jbe@177 223 ) AS "member_weight"
jbe@177 224 FROM "area"
jbe@177 225 LEFT JOIN "membership"
jbe@177 226 ON "area"."id" = "membership"."area_id"
jbe@177 227 LEFT JOIN "privilege"
jbe@177 228 ON "privilege"."unit_id" = "area"."unit_id"
jbe@177 229 AND "privilege"."member_id" = "membership"."member_id"
jbe@177 230 AND "privilege"."voting_right"
jbe@177 231 LEFT JOIN "member"
jbe@177 232 ON "member"."id" = "privilege"."member_id" -- NOTE: no membership here!
jbe@177 233 AND "member"."active"
jbe@177 234 GROUP BY "area"."id";
jbe@177 235
jbe@177 236 COMMENT ON VIEW "area_member_count" IS 'View used to update "direct_member_count" and "member_weight" columns of table "area"';
jbe@177 237
jbe@177 238 CREATE VIEW "battle_participant" AS
jbe@177 239 SELECT "initiative"."id", "initiative"."issue_id"
jbe@177 240 FROM "issue" JOIN "initiative"
jbe@177 241 ON "issue"."id" = "initiative"."issue_id"
jbe@177 242 WHERE "initiative"."admitted"
jbe@177 243 UNION ALL
jbe@177 244 SELECT NULL, "id" AS "issue_id"
jbe@177 245 FROM "issue";
jbe@177 246
jbe@177 247 COMMENT ON VIEW "battle_participant" IS 'Helper view for "battle_view" containing admitted initiatives plus virtual "status-quo" initiative denoted by NULL reference';
jbe@177 248
jbe@179 249 CREATE VIEW "battle_view" AS
jbe@177 250 SELECT
jbe@177 251 "issue"."id" AS "issue_id",
jbe@177 252 "winning_initiative"."id" AS "winning_initiative_id",
jbe@177 253 "losing_initiative"."id" AS "losing_initiative_id",
jbe@177 254 sum(
jbe@177 255 CASE WHEN
jbe@177 256 coalesce("better_vote"."grade", 0) >
jbe@177 257 coalesce("worse_vote"."grade", 0)
jbe@177 258 THEN "direct_voter"."weight" ELSE 0 END
jbe@177 259 ) AS "count"
jbe@177 260 FROM "issue"
jbe@177 261 LEFT JOIN "direct_voter"
jbe@177 262 ON "issue"."id" = "direct_voter"."issue_id"
jbe@177 263 JOIN "battle_participant" AS "winning_initiative"
jbe@177 264 ON "issue"."id" = "winning_initiative"."issue_id"
jbe@177 265 JOIN "battle_participant" AS "losing_initiative"
jbe@177 266 ON "issue"."id" = "losing_initiative"."issue_id"
jbe@177 267 LEFT JOIN "vote" AS "better_vote"
jbe@177 268 ON "direct_voter"."member_id" = "better_vote"."member_id"
jbe@177 269 AND "winning_initiative"."id" = "better_vote"."initiative_id"
jbe@177 270 LEFT JOIN "vote" AS "worse_vote"
jbe@177 271 ON "direct_voter"."member_id" = "worse_vote"."member_id"
jbe@177 272 AND "losing_initiative"."id" = "worse_vote"."initiative_id"
jbe@177 273 WHERE "issue"."closed" NOTNULL
jbe@177 274 AND "issue"."cleaned" ISNULL
jbe@177 275 AND (
jbe@177 276 "winning_initiative"."id" != "losing_initiative"."id" OR
jbe@177 277 ( ("winning_initiative"."id" NOTNULL AND "losing_initiative"."id" ISNULL) OR
jbe@177 278 ("winning_initiative"."id" ISNULL AND "losing_initiative"."id" NOTNULL) ) )
jbe@177 279 GROUP BY
jbe@177 280 "issue"."id",
jbe@177 281 "winning_initiative"."id",
jbe@177 282 "losing_initiative"."id";
jbe@177 283
jbe@177 284 COMMENT ON VIEW "battle_view" IS 'Number of members preferring one initiative (or status-quo) to another initiative (or status-quo); Used to fill "battle" table';
jbe@177 285
jbe@177 286 CREATE OR REPLACE FUNCTION "create_interest_snapshot"
jbe@177 287 ( "issue_id_p" "issue"."id"%TYPE )
jbe@177 288 RETURNS VOID
jbe@177 289 LANGUAGE 'plpgsql' VOLATILE AS $$
jbe@177 290 DECLARE
jbe@177 291 "member_id_v" "member"."id"%TYPE;
jbe@177 292 BEGIN
jbe@177 293 DELETE FROM "direct_interest_snapshot"
jbe@177 294 WHERE "issue_id" = "issue_id_p"
jbe@177 295 AND "event" = 'periodic';
jbe@177 296 DELETE FROM "delegating_interest_snapshot"
jbe@177 297 WHERE "issue_id" = "issue_id_p"
jbe@177 298 AND "event" = 'periodic';
jbe@177 299 DELETE FROM "direct_supporter_snapshot"
jbe@177 300 WHERE "issue_id" = "issue_id_p"
jbe@177 301 AND "event" = 'periodic';
jbe@177 302 INSERT INTO "direct_interest_snapshot"
jbe@177 303 ("issue_id", "event", "member_id")
jbe@177 304 SELECT
jbe@177 305 "issue_id_p" AS "issue_id",
jbe@177 306 'periodic' AS "event",
jbe@177 307 "member"."id" AS "member_id"
jbe@177 308 FROM "issue"
jbe@177 309 JOIN "area" ON "issue"."area_id" = "area"."id"
jbe@177 310 JOIN "interest" ON "issue"."id" = "interest"."issue_id"
jbe@177 311 JOIN "member" ON "interest"."member_id" = "member"."id"
jbe@177 312 JOIN "privilege"
jbe@177 313 ON "privilege"."unit_id" = "area"."unit_id"
jbe@177 314 AND "privilege"."member_id" = "member"."id"
jbe@177 315 WHERE "issue"."id" = "issue_id_p"
jbe@177 316 AND "member"."active" AND "privilege"."voting_right";
jbe@177 317 FOR "member_id_v" IN
jbe@177 318 SELECT "member_id" FROM "direct_interest_snapshot"
jbe@177 319 WHERE "issue_id" = "issue_id_p"
jbe@177 320 AND "event" = 'periodic'
jbe@177 321 LOOP
jbe@177 322 UPDATE "direct_interest_snapshot" SET
jbe@177 323 "weight" = 1 +
jbe@177 324 "weight_of_added_delegations_for_interest_snapshot"(
jbe@177 325 "issue_id_p",
jbe@177 326 "member_id_v",
jbe@177 327 '{}'
jbe@177 328 )
jbe@177 329 WHERE "issue_id" = "issue_id_p"
jbe@177 330 AND "event" = 'periodic'
jbe@177 331 AND "member_id" = "member_id_v";
jbe@177 332 END LOOP;
jbe@177 333 INSERT INTO "direct_supporter_snapshot"
jbe@177 334 ( "issue_id", "initiative_id", "event", "member_id",
jbe@177 335 "informed", "satisfied" )
jbe@177 336 SELECT
jbe@177 337 "issue_id_p" AS "issue_id",
jbe@177 338 "initiative"."id" AS "initiative_id",
jbe@177 339 'periodic' AS "event",
jbe@177 340 "supporter"."member_id" AS "member_id",
jbe@177 341 "supporter"."draft_id" = "current_draft"."id" AS "informed",
jbe@177 342 NOT EXISTS (
jbe@177 343 SELECT NULL FROM "critical_opinion"
jbe@177 344 WHERE "initiative_id" = "initiative"."id"
jbe@177 345 AND "member_id" = "supporter"."member_id"
jbe@177 346 ) AS "satisfied"
jbe@177 347 FROM "initiative"
jbe@177 348 JOIN "supporter"
jbe@177 349 ON "supporter"."initiative_id" = "initiative"."id"
jbe@177 350 JOIN "current_draft"
jbe@177 351 ON "initiative"."id" = "current_draft"."initiative_id"
jbe@177 352 JOIN "direct_interest_snapshot"
jbe@177 353 ON "supporter"."member_id" = "direct_interest_snapshot"."member_id"
jbe@177 354 AND "initiative"."issue_id" = "direct_interest_snapshot"."issue_id"
jbe@177 355 AND "event" = 'periodic'
jbe@177 356 WHERE "initiative"."issue_id" = "issue_id_p";
jbe@177 357 RETURN;
jbe@177 358 END;
jbe@177 359 $$;
jbe@177 360
jbe@177 361 CREATE OR REPLACE FUNCTION "create_snapshot"
jbe@177 362 ( "issue_id_p" "issue"."id"%TYPE )
jbe@177 363 RETURNS VOID
jbe@177 364 LANGUAGE 'plpgsql' VOLATILE AS $$
jbe@177 365 DECLARE
jbe@177 366 "initiative_id_v" "initiative"."id"%TYPE;
jbe@177 367 "suggestion_id_v" "suggestion"."id"%TYPE;
jbe@177 368 BEGIN
jbe@177 369 PERFORM "lock_issue"("issue_id_p");
jbe@177 370 PERFORM "create_population_snapshot"("issue_id_p");
jbe@177 371 PERFORM "create_interest_snapshot"("issue_id_p");
jbe@177 372 UPDATE "issue" SET
jbe@177 373 "snapshot" = now(),
jbe@177 374 "latest_snapshot_event" = 'periodic',
jbe@177 375 "population" = (
jbe@177 376 SELECT coalesce(sum("weight"), 0)
jbe@177 377 FROM "direct_population_snapshot"
jbe@177 378 WHERE "issue_id" = "issue_id_p"
jbe@177 379 AND "event" = 'periodic'
jbe@177 380 )
jbe@177 381 WHERE "id" = "issue_id_p";
jbe@177 382 FOR "initiative_id_v" IN
jbe@177 383 SELECT "id" FROM "initiative" WHERE "issue_id" = "issue_id_p"
jbe@177 384 LOOP
jbe@177 385 UPDATE "initiative" SET
jbe@177 386 "supporter_count" = (
jbe@177 387 SELECT coalesce(sum("di"."weight"), 0)
jbe@177 388 FROM "direct_interest_snapshot" AS "di"
jbe@177 389 JOIN "direct_supporter_snapshot" AS "ds"
jbe@177 390 ON "di"."member_id" = "ds"."member_id"
jbe@177 391 WHERE "di"."issue_id" = "issue_id_p"
jbe@177 392 AND "di"."event" = 'periodic'
jbe@177 393 AND "ds"."initiative_id" = "initiative_id_v"
jbe@177 394 AND "ds"."event" = 'periodic'
jbe@177 395 ),
jbe@177 396 "informed_supporter_count" = (
jbe@177 397 SELECT coalesce(sum("di"."weight"), 0)
jbe@177 398 FROM "direct_interest_snapshot" AS "di"
jbe@177 399 JOIN "direct_supporter_snapshot" AS "ds"
jbe@177 400 ON "di"."member_id" = "ds"."member_id"
jbe@177 401 WHERE "di"."issue_id" = "issue_id_p"
jbe@177 402 AND "di"."event" = 'periodic'
jbe@177 403 AND "ds"."initiative_id" = "initiative_id_v"
jbe@177 404 AND "ds"."event" = 'periodic'
jbe@177 405 AND "ds"."informed"
jbe@177 406 ),
jbe@177 407 "satisfied_supporter_count" = (
jbe@177 408 SELECT coalesce(sum("di"."weight"), 0)
jbe@177 409 FROM "direct_interest_snapshot" AS "di"
jbe@177 410 JOIN "direct_supporter_snapshot" AS "ds"
jbe@177 411 ON "di"."member_id" = "ds"."member_id"
jbe@177 412 WHERE "di"."issue_id" = "issue_id_p"
jbe@177 413 AND "di"."event" = 'periodic'
jbe@177 414 AND "ds"."initiative_id" = "initiative_id_v"
jbe@177 415 AND "ds"."event" = 'periodic'
jbe@177 416 AND "ds"."satisfied"
jbe@177 417 ),
jbe@177 418 "satisfied_informed_supporter_count" = (
jbe@177 419 SELECT coalesce(sum("di"."weight"), 0)
jbe@177 420 FROM "direct_interest_snapshot" AS "di"
jbe@177 421 JOIN "direct_supporter_snapshot" AS "ds"
jbe@177 422 ON "di"."member_id" = "ds"."member_id"
jbe@177 423 WHERE "di"."issue_id" = "issue_id_p"
jbe@177 424 AND "di"."event" = 'periodic'
jbe@177 425 AND "ds"."initiative_id" = "initiative_id_v"
jbe@177 426 AND "ds"."event" = 'periodic'
jbe@177 427 AND "ds"."informed"
jbe@177 428 AND "ds"."satisfied"
jbe@177 429 )
jbe@177 430 WHERE "id" = "initiative_id_v";
jbe@177 431 FOR "suggestion_id_v" IN
jbe@177 432 SELECT "id" FROM "suggestion"
jbe@177 433 WHERE "initiative_id" = "initiative_id_v"
jbe@177 434 LOOP
jbe@177 435 UPDATE "suggestion" SET
jbe@177 436 "minus2_unfulfilled_count" = (
jbe@177 437 SELECT coalesce(sum("snapshot"."weight"), 0)
jbe@177 438 FROM "issue" CROSS JOIN "opinion"
jbe@177 439 JOIN "direct_interest_snapshot" AS "snapshot"
jbe@177 440 ON "snapshot"."issue_id" = "issue"."id"
jbe@177 441 AND "snapshot"."event" = "issue"."latest_snapshot_event"
jbe@177 442 AND "snapshot"."member_id" = "opinion"."member_id"
jbe@177 443 WHERE "issue"."id" = "issue_id_p"
jbe@177 444 AND "opinion"."suggestion_id" = "suggestion_id_v"
jbe@177 445 AND "opinion"."degree" = -2
jbe@177 446 AND "opinion"."fulfilled" = FALSE
jbe@177 447 ),
jbe@177 448 "minus2_fulfilled_count" = (
jbe@177 449 SELECT coalesce(sum("snapshot"."weight"), 0)
jbe@177 450 FROM "issue" CROSS JOIN "opinion"
jbe@177 451 JOIN "direct_interest_snapshot" AS "snapshot"
jbe@177 452 ON "snapshot"."issue_id" = "issue"."id"
jbe@177 453 AND "snapshot"."event" = "issue"."latest_snapshot_event"
jbe@177 454 AND "snapshot"."member_id" = "opinion"."member_id"
jbe@177 455 WHERE "issue"."id" = "issue_id_p"
jbe@177 456 AND "opinion"."suggestion_id" = "suggestion_id_v"
jbe@177 457 AND "opinion"."degree" = -2
jbe@177 458 AND "opinion"."fulfilled" = TRUE
jbe@177 459 ),
jbe@177 460 "minus1_unfulfilled_count" = (
jbe@177 461 SELECT coalesce(sum("snapshot"."weight"), 0)
jbe@177 462 FROM "issue" CROSS JOIN "opinion"
jbe@177 463 JOIN "direct_interest_snapshot" AS "snapshot"
jbe@177 464 ON "snapshot"."issue_id" = "issue"."id"
jbe@177 465 AND "snapshot"."event" = "issue"."latest_snapshot_event"
jbe@177 466 AND "snapshot"."member_id" = "opinion"."member_id"
jbe@177 467 WHERE "issue"."id" = "issue_id_p"
jbe@177 468 AND "opinion"."suggestion_id" = "suggestion_id_v"
jbe@177 469 AND "opinion"."degree" = -1
jbe@177 470 AND "opinion"."fulfilled" = FALSE
jbe@177 471 ),
jbe@177 472 "minus1_fulfilled_count" = (
jbe@177 473 SELECT coalesce(sum("snapshot"."weight"), 0)
jbe@177 474 FROM "issue" CROSS JOIN "opinion"
jbe@177 475 JOIN "direct_interest_snapshot" AS "snapshot"
jbe@177 476 ON "snapshot"."issue_id" = "issue"."id"
jbe@177 477 AND "snapshot"."event" = "issue"."latest_snapshot_event"
jbe@177 478 AND "snapshot"."member_id" = "opinion"."member_id"
jbe@177 479 WHERE "issue"."id" = "issue_id_p"
jbe@177 480 AND "opinion"."suggestion_id" = "suggestion_id_v"
jbe@177 481 AND "opinion"."degree" = -1
jbe@177 482 AND "opinion"."fulfilled" = TRUE
jbe@177 483 ),
jbe@177 484 "plus1_unfulfilled_count" = (
jbe@177 485 SELECT coalesce(sum("snapshot"."weight"), 0)
jbe@177 486 FROM "issue" CROSS JOIN "opinion"
jbe@177 487 JOIN "direct_interest_snapshot" AS "snapshot"
jbe@177 488 ON "snapshot"."issue_id" = "issue"."id"
jbe@177 489 AND "snapshot"."event" = "issue"."latest_snapshot_event"
jbe@177 490 AND "snapshot"."member_id" = "opinion"."member_id"
jbe@177 491 WHERE "issue"."id" = "issue_id_p"
jbe@177 492 AND "opinion"."suggestion_id" = "suggestion_id_v"
jbe@177 493 AND "opinion"."degree" = 1
jbe@177 494 AND "opinion"."fulfilled" = FALSE
jbe@177 495 ),
jbe@177 496 "plus1_fulfilled_count" = (
jbe@177 497 SELECT coalesce(sum("snapshot"."weight"), 0)
jbe@177 498 FROM "issue" CROSS JOIN "opinion"
jbe@177 499 JOIN "direct_interest_snapshot" AS "snapshot"
jbe@177 500 ON "snapshot"."issue_id" = "issue"."id"
jbe@177 501 AND "snapshot"."event" = "issue"."latest_snapshot_event"
jbe@177 502 AND "snapshot"."member_id" = "opinion"."member_id"
jbe@177 503 WHERE "issue"."id" = "issue_id_p"
jbe@177 504 AND "opinion"."suggestion_id" = "suggestion_id_v"
jbe@177 505 AND "opinion"."degree" = 1
jbe@177 506 AND "opinion"."fulfilled" = TRUE
jbe@177 507 ),
jbe@177 508 "plus2_unfulfilled_count" = (
jbe@177 509 SELECT coalesce(sum("snapshot"."weight"), 0)
jbe@177 510 FROM "issue" CROSS JOIN "opinion"
jbe@177 511 JOIN "direct_interest_snapshot" AS "snapshot"
jbe@177 512 ON "snapshot"."issue_id" = "issue"."id"
jbe@177 513 AND "snapshot"."event" = "issue"."latest_snapshot_event"
jbe@177 514 AND "snapshot"."member_id" = "opinion"."member_id"
jbe@177 515 WHERE "issue"."id" = "issue_id_p"
jbe@177 516 AND "opinion"."suggestion_id" = "suggestion_id_v"
jbe@177 517 AND "opinion"."degree" = 2
jbe@177 518 AND "opinion"."fulfilled" = FALSE
jbe@177 519 ),
jbe@177 520 "plus2_fulfilled_count" = (
jbe@177 521 SELECT coalesce(sum("snapshot"."weight"), 0)
jbe@177 522 FROM "issue" CROSS JOIN "opinion"
jbe@177 523 JOIN "direct_interest_snapshot" AS "snapshot"
jbe@177 524 ON "snapshot"."issue_id" = "issue"."id"
jbe@177 525 AND "snapshot"."event" = "issue"."latest_snapshot_event"
jbe@177 526 AND "snapshot"."member_id" = "opinion"."member_id"
jbe@177 527 WHERE "issue"."id" = "issue_id_p"
jbe@177 528 AND "opinion"."suggestion_id" = "suggestion_id_v"
jbe@177 529 AND "opinion"."degree" = 2
jbe@177 530 AND "opinion"."fulfilled" = TRUE
jbe@177 531 )
jbe@177 532 WHERE "suggestion"."id" = "suggestion_id_v";
jbe@177 533 END LOOP;
jbe@177 534 END LOOP;
jbe@177 535 RETURN;
jbe@177 536 END;
jbe@177 537 $$;
jbe@177 538
jbe@177 539 CREATE OR REPLACE FUNCTION "close_voting"("issue_id_p" "issue"."id"%TYPE)
jbe@177 540 RETURNS VOID
jbe@177 541 LANGUAGE 'plpgsql' VOLATILE AS $$
jbe@177 542 DECLARE
jbe@177 543 "area_id_v" "area"."id"%TYPE;
jbe@177 544 "unit_id_v" "unit"."id"%TYPE;
jbe@177 545 "member_id_v" "member"."id"%TYPE;
jbe@177 546 BEGIN
jbe@177 547 PERFORM "lock_issue"("issue_id_p");
jbe@177 548 SELECT "area_id" INTO "area_id_v" FROM "issue" WHERE "id" = "issue_id_p";
jbe@177 549 SELECT "unit_id" INTO "unit_id_v" FROM "area" WHERE "id" = "area_id_v";
jbe@177 550 -- delete delegating votes (in cases of manual reset of issue state):
jbe@177 551 DELETE FROM "delegating_voter"
jbe@177 552 WHERE "issue_id" = "issue_id_p";
jbe@177 553 -- delete votes from non-privileged voters:
jbe@177 554 DELETE FROM "direct_voter"
jbe@177 555 USING (
jbe@177 556 SELECT
jbe@177 557 "direct_voter"."member_id"
jbe@177 558 FROM "direct_voter"
jbe@177 559 JOIN "member" ON "direct_voter"."member_id" = "member"."id"
jbe@177 560 LEFT JOIN "privilege"
jbe@177 561 ON "privilege"."unit_id" = "unit_id_v"
jbe@177 562 AND "privilege"."member_id" = "direct_voter"."member_id"
jbe@177 563 WHERE "direct_voter"."issue_id" = "issue_id_p" AND (
jbe@177 564 "member"."active" = FALSE OR
jbe@177 565 "privilege"."voting_right" ISNULL OR
jbe@177 566 "privilege"."voting_right" = FALSE
jbe@177 567 )
jbe@177 568 ) AS "subquery"
jbe@177 569 WHERE "direct_voter"."issue_id" = "issue_id_p"
jbe@177 570 AND "direct_voter"."member_id" = "subquery"."member_id";
jbe@177 571 -- consider delegations:
jbe@177 572 UPDATE "direct_voter" SET "weight" = 1
jbe@177 573 WHERE "issue_id" = "issue_id_p";
jbe@177 574 PERFORM "add_vote_delegations"("issue_id_p");
jbe@177 575 -- set voter count and mark issue as being calculated:
jbe@177 576 UPDATE "issue" SET
jbe@177 577 "state" = 'calculation',
jbe@177 578 "closed" = now(),
jbe@177 579 "voter_count" = (
jbe@177 580 SELECT coalesce(sum("weight"), 0)
jbe@177 581 FROM "direct_voter" WHERE "issue_id" = "issue_id_p"
jbe@177 582 )
jbe@177 583 WHERE "id" = "issue_id_p";
jbe@177 584 -- materialize battle_view:
jbe@177 585 -- NOTE: "closed" column of issue must be set at this point
jbe@177 586 DELETE FROM "battle" WHERE "issue_id" = "issue_id_p";
jbe@177 587 INSERT INTO "battle" (
jbe@177 588 "issue_id",
jbe@177 589 "winning_initiative_id", "losing_initiative_id",
jbe@177 590 "count"
jbe@177 591 ) SELECT
jbe@177 592 "issue_id",
jbe@177 593 "winning_initiative_id", "losing_initiative_id",
jbe@177 594 "count"
jbe@177 595 FROM "battle_view" WHERE "issue_id" = "issue_id_p";
jbe@177 596 -- copy "positive_votes" and "negative_votes" from "battle" table:
jbe@177 597 UPDATE "initiative" SET
jbe@177 598 "positive_votes" = "battle_win"."count",
jbe@177 599 "negative_votes" = "battle_lose"."count"
jbe@177 600 FROM "battle" AS "battle_win", "battle" AS "battle_lose"
jbe@177 601 WHERE
jbe@177 602 "battle_win"."issue_id" = "issue_id_p" AND
jbe@177 603 "battle_win"."winning_initiative_id" = "initiative"."id" AND
jbe@177 604 "battle_win"."losing_initiative_id" ISNULL AND
jbe@177 605 "battle_lose"."issue_id" = "issue_id_p" AND
jbe@177 606 "battle_lose"."losing_initiative_id" = "initiative"."id" AND
jbe@177 607 "battle_lose"."winning_initiative_id" ISNULL;
jbe@177 608 END;
jbe@177 609 $$;
jbe@177 610
jbe@177 611 DROP FUNCTION "array_init_string"(INTEGER);
jbe@177 612 DROP FUNCTION "square_matrix_init_string"(INTEGER);
jbe@177 613
jbe@177 614 CREATE OR REPLACE FUNCTION "calculate_ranks"("issue_id_p" "issue"."id"%TYPE)
jbe@177 615 RETURNS VOID
jbe@177 616 LANGUAGE 'plpgsql' VOLATILE AS $$
jbe@177 617 DECLARE
jbe@177 618 "issue_row" "issue"%ROWTYPE;
jbe@177 619 "policy_row" "policy"%ROWTYPE;
jbe@177 620 "dimension_v" INTEGER;
jbe@177 621 "vote_matrix" INT4[][]; -- absolute votes
jbe@177 622 "matrix" INT8[][]; -- defeat strength / best paths
jbe@177 623 "i" INTEGER;
jbe@177 624 "j" INTEGER;
jbe@177 625 "k" INTEGER;
jbe@177 626 "battle_row" "battle"%ROWTYPE;
jbe@177 627 "rank_ary" INT4[];
jbe@177 628 "rank_v" INT4;
jbe@177 629 "done_v" INTEGER;
jbe@177 630 "winners_ary" INTEGER[];
jbe@177 631 "initiative_id_v" "initiative"."id"%TYPE;
jbe@177 632 BEGIN
jbe@177 633 SELECT * INTO "issue_row"
jbe@177 634 FROM "issue" WHERE "id" = "issue_id_p"
jbe@177 635 FOR UPDATE;
jbe@177 636 SELECT * INTO "policy_row"
jbe@177 637 FROM "policy" WHERE "id" = "issue_row"."policy_id";
jbe@177 638 SELECT count(1) INTO "dimension_v"
jbe@177 639 FROM "battle_participant" WHERE "issue_id" = "issue_id_p";
jbe@177 640 -- Create "vote_matrix" with absolute number of votes in pairwise
jbe@177 641 -- comparison:
jbe@177 642 "vote_matrix" := array_fill(NULL::INT4, ARRAY["dimension_v", "dimension_v"]);
jbe@177 643 "i" := 1;
jbe@177 644 "j" := 2;
jbe@177 645 FOR "battle_row" IN
jbe@177 646 SELECT * FROM "battle" WHERE "issue_id" = "issue_id_p"
jbe@177 647 ORDER BY
jbe@177 648 "winning_initiative_id" NULLS LAST,
jbe@177 649 "losing_initiative_id" NULLS LAST
jbe@177 650 LOOP
jbe@177 651 "vote_matrix"["i"]["j"] := "battle_row"."count";
jbe@177 652 IF "j" = "dimension_v" THEN
jbe@177 653 "i" := "i" + 1;
jbe@177 654 "j" := 1;
jbe@177 655 ELSE
jbe@177 656 "j" := "j" + 1;
jbe@177 657 IF "j" = "i" THEN
jbe@177 658 "j" := "j" + 1;
jbe@177 659 END IF;
jbe@177 660 END IF;
jbe@177 661 END LOOP;
jbe@177 662 IF "i" != "dimension_v" OR "j" != "dimension_v" + 1 THEN
jbe@177 663 RAISE EXCEPTION 'Wrong battle count (should not happen)';
jbe@177 664 END IF;
jbe@177 665 -- Store defeat strengths in "matrix" using "defeat_strength"
jbe@177 666 -- function:
jbe@177 667 "matrix" := array_fill(NULL::INT8, ARRAY["dimension_v", "dimension_v"]);
jbe@177 668 "i" := 1;
jbe@177 669 LOOP
jbe@177 670 "j" := 1;
jbe@177 671 LOOP
jbe@177 672 IF "i" != "j" THEN
jbe@177 673 "matrix"["i"]["j"] := "defeat_strength"(
jbe@177 674 "vote_matrix"["i"]["j"],
jbe@177 675 "vote_matrix"["j"]["i"]
jbe@177 676 );
jbe@177 677 END IF;
jbe@177 678 EXIT WHEN "j" = "dimension_v";
jbe@177 679 "j" := "j" + 1;
jbe@177 680 END LOOP;
jbe@177 681 EXIT WHEN "i" = "dimension_v";
jbe@177 682 "i" := "i" + 1;
jbe@177 683 END LOOP;
jbe@177 684 -- Find best paths:
jbe@177 685 "i" := 1;
jbe@177 686 LOOP
jbe@177 687 "j" := 1;
jbe@177 688 LOOP
jbe@177 689 IF "i" != "j" THEN
jbe@177 690 "k" := 1;
jbe@177 691 LOOP
jbe@177 692 IF "i" != "k" AND "j" != "k" THEN
jbe@177 693 IF "matrix"["j"]["i"] < "matrix"["i"]["k"] THEN
jbe@177 694 IF "matrix"["j"]["i"] > "matrix"["j"]["k"] THEN
jbe@177 695 "matrix"["j"]["k"] := "matrix"["j"]["i"];
jbe@177 696 END IF;
jbe@177 697 ELSE
jbe@177 698 IF "matrix"["i"]["k"] > "matrix"["j"]["k"] THEN
jbe@177 699 "matrix"["j"]["k"] := "matrix"["i"]["k"];
jbe@177 700 END IF;
jbe@177 701 END IF;
jbe@177 702 END IF;
jbe@177 703 EXIT WHEN "k" = "dimension_v";
jbe@177 704 "k" := "k" + 1;
jbe@177 705 END LOOP;
jbe@177 706 END IF;
jbe@177 707 EXIT WHEN "j" = "dimension_v";
jbe@177 708 "j" := "j" + 1;
jbe@177 709 END LOOP;
jbe@177 710 EXIT WHEN "i" = "dimension_v";
jbe@177 711 "i" := "i" + 1;
jbe@177 712 END LOOP;
jbe@177 713 -- Determine order of winners:
jbe@177 714 "rank_ary" := array_fill(NULL::INT4, ARRAY["dimension_v"]);
jbe@177 715 "rank_v" := 1;
jbe@177 716 "done_v" := 0;
jbe@177 717 LOOP
jbe@177 718 "winners_ary" := '{}';
jbe@177 719 "i" := 1;
jbe@177 720 LOOP
jbe@177 721 IF "rank_ary"["i"] ISNULL THEN
jbe@177 722 "j" := 1;
jbe@177 723 LOOP
jbe@177 724 IF
jbe@177 725 "i" != "j" AND
jbe@177 726 "rank_ary"["j"] ISNULL AND
jbe@177 727 "matrix"["j"]["i"] > "matrix"["i"]["j"]
jbe@177 728 THEN
jbe@177 729 -- someone else is better
jbe@177 730 EXIT;
jbe@177 731 END IF;
jbe@177 732 IF "j" = "dimension_v" THEN
jbe@177 733 -- noone is better
jbe@177 734 "winners_ary" := "winners_ary" || "i";
jbe@177 735 EXIT;
jbe@177 736 END IF;
jbe@177 737 "j" := "j" + 1;
jbe@177 738 END LOOP;
jbe@177 739 END IF;
jbe@177 740 EXIT WHEN "i" = "dimension_v";
jbe@177 741 "i" := "i" + 1;
jbe@177 742 END LOOP;
jbe@177 743 "i" := 1;
jbe@177 744 LOOP
jbe@177 745 "rank_ary"["winners_ary"["i"]] := "rank_v";
jbe@177 746 "done_v" := "done_v" + 1;
jbe@177 747 EXIT WHEN "i" = array_upper("winners_ary", 1);
jbe@177 748 "i" := "i" + 1;
jbe@177 749 END LOOP;
jbe@177 750 EXIT WHEN "done_v" = "dimension_v";
jbe@177 751 "rank_v" := "rank_v" + 1;
jbe@177 752 END LOOP;
jbe@177 753 -- write preliminary results:
jbe@177 754 "i" := 1;
jbe@177 755 FOR "initiative_id_v" IN
jbe@177 756 SELECT "id" FROM "initiative"
jbe@177 757 WHERE "issue_id" = "issue_id_p" AND "admitted"
jbe@177 758 ORDER BY "id"
jbe@177 759 LOOP
jbe@177 760 UPDATE "initiative" SET
jbe@177 761 "direct_majority" =
jbe@177 762 CASE WHEN "policy_row"."direct_majority_strict" THEN
jbe@177 763 "positive_votes" * "policy_row"."direct_majority_den" >
jbe@177 764 "policy_row"."direct_majority_num" * ("positive_votes"+"negative_votes")
jbe@177 765 ELSE
jbe@177 766 "positive_votes" * "policy_row"."direct_majority_den" >=
jbe@177 767 "policy_row"."direct_majority_num" * ("positive_votes"+"negative_votes")
jbe@177 768 END
jbe@177 769 AND "positive_votes" >= "policy_row"."direct_majority_positive"
jbe@177 770 AND "issue_row"."voter_count"-"negative_votes" >=
jbe@177 771 "policy_row"."direct_majority_non_negative",
jbe@177 772 "indirect_majority" =
jbe@177 773 CASE WHEN "policy_row"."indirect_majority_strict" THEN
jbe@177 774 "positive_votes" * "policy_row"."indirect_majority_den" >
jbe@177 775 "policy_row"."indirect_majority_num" * ("positive_votes"+"negative_votes")
jbe@177 776 ELSE
jbe@177 777 "positive_votes" * "policy_row"."indirect_majority_den" >=
jbe@177 778 "policy_row"."indirect_majority_num" * ("positive_votes"+"negative_votes")
jbe@177 779 END
jbe@177 780 AND "positive_votes" >= "policy_row"."indirect_majority_positive"
jbe@177 781 AND "issue_row"."voter_count"-"negative_votes" >=
jbe@177 782 "policy_row"."indirect_majority_non_negative",
jbe@177 783 "schulze_rank" = "rank_ary"["i"],
jbe@177 784 "better_than_status_quo" = "rank_ary"["i"] < "rank_ary"["dimension_v"],
jbe@177 785 "worse_than_status_quo" = "rank_ary"["i"] > "rank_ary"["dimension_v"],
jbe@177 786 "multistage_majority" = "rank_ary"["i"] >= "rank_ary"["dimension_v"],
jbe@177 787 "reverse_beat_path" = "matrix"["dimension_v"]["i"] >= 0,
jbe@177 788 "winner" = FALSE
jbe@177 789 WHERE "id" = "initiative_id_v";
jbe@177 790 "i" := "i" + 1;
jbe@177 791 END LOOP;
jbe@177 792 IF "i" != "dimension_v" THEN
jbe@177 793 RAISE EXCEPTION 'Wrong winner count (should not happen)';
jbe@177 794 END IF;
jbe@177 795 -- take indirect majorities into account:
jbe@177 796 LOOP
jbe@177 797 UPDATE "initiative" SET "indirect_majority" = TRUE
jbe@177 798 FROM (
jbe@177 799 SELECT "new_initiative"."id" AS "initiative_id"
jbe@177 800 FROM "initiative" "old_initiative"
jbe@177 801 JOIN "initiative" "new_initiative"
jbe@177 802 ON "new_initiative"."issue_id" = "issue_id_p"
jbe@177 803 AND "new_initiative"."indirect_majority" = FALSE
jbe@177 804 JOIN "battle" "battle_win"
jbe@177 805 ON "battle_win"."issue_id" = "issue_id_p"
jbe@177 806 AND "battle_win"."winning_initiative_id" = "new_initiative"."id"
jbe@177 807 AND "battle_win"."losing_initiative_id" = "old_initiative"."id"
jbe@177 808 JOIN "battle" "battle_lose"
jbe@177 809 ON "battle_lose"."issue_id" = "issue_id_p"
jbe@177 810 AND "battle_lose"."losing_initiative_id" = "new_initiative"."id"
jbe@177 811 AND "battle_lose"."winning_initiative_id" = "old_initiative"."id"
jbe@177 812 WHERE "old_initiative"."issue_id" = "issue_id_p"
jbe@177 813 AND "old_initiative"."indirect_majority" = TRUE
jbe@177 814 AND CASE WHEN "policy_row"."indirect_majority_strict" THEN
jbe@177 815 "battle_win"."count" * "policy_row"."indirect_majority_den" >
jbe@177 816 "policy_row"."indirect_majority_num" *
jbe@177 817 ("battle_win"."count"+"battle_lose"."count")
jbe@177 818 ELSE
jbe@177 819 "battle_win"."count" * "policy_row"."indirect_majority_den" >=
jbe@177 820 "policy_row"."indirect_majority_num" *
jbe@177 821 ("battle_win"."count"+"battle_lose"."count")
jbe@177 822 END
jbe@177 823 AND "battle_win"."count" >= "policy_row"."indirect_majority_positive"
jbe@177 824 AND "issue_row"."voter_count"-"battle_lose"."count" >=
jbe@177 825 "policy_row"."indirect_majority_non_negative"
jbe@177 826 ) AS "subquery"
jbe@177 827 WHERE "id" = "subquery"."initiative_id";
jbe@177 828 EXIT WHEN NOT FOUND;
jbe@177 829 END LOOP;
jbe@177 830 -- set "multistage_majority" for remaining matching initiatives:
jbe@177 831 UPDATE "initiative" SET "multistage_majority" = TRUE
jbe@177 832 FROM (
jbe@177 833 SELECT "losing_initiative"."id" AS "initiative_id"
jbe@177 834 FROM "initiative" "losing_initiative"
jbe@177 835 JOIN "initiative" "winning_initiative"
jbe@177 836 ON "winning_initiative"."issue_id" = "issue_id_p"
jbe@177 837 AND "winning_initiative"."admitted"
jbe@177 838 JOIN "battle" "battle_win"
jbe@177 839 ON "battle_win"."issue_id" = "issue_id_p"
jbe@177 840 AND "battle_win"."winning_initiative_id" = "winning_initiative"."id"
jbe@177 841 AND "battle_win"."losing_initiative_id" = "losing_initiative"."id"
jbe@177 842 JOIN "battle" "battle_lose"
jbe@177 843 ON "battle_lose"."issue_id" = "issue_id_p"
jbe@177 844 AND "battle_lose"."losing_initiative_id" = "winning_initiative"."id"
jbe@177 845 AND "battle_lose"."winning_initiative_id" = "losing_initiative"."id"
jbe@177 846 WHERE "losing_initiative"."issue_id" = "issue_id_p"
jbe@177 847 AND "losing_initiative"."admitted"
jbe@177 848 AND "winning_initiative"."schulze_rank" <
jbe@177 849 "losing_initiative"."schulze_rank"
jbe@177 850 AND "battle_win"."count" > "battle_lose"."count"
jbe@177 851 AND (
jbe@177 852 "battle_win"."count" > "winning_initiative"."positive_votes" OR
jbe@177 853 "battle_lose"."count" < "losing_initiative"."negative_votes" )
jbe@177 854 ) AS "subquery"
jbe@177 855 WHERE "id" = "subquery"."initiative_id";
jbe@177 856 -- mark eligible initiatives:
jbe@177 857 UPDATE "initiative" SET "eligible" = TRUE
jbe@177 858 WHERE "issue_id" = "issue_id_p"
jbe@177 859 AND "initiative"."direct_majority"
jbe@177 860 AND "initiative"."indirect_majority"
jbe@177 861 AND "initiative"."better_than_status_quo"
jbe@177 862 AND (
jbe@177 863 "policy_row"."no_multistage_majority" = FALSE OR
jbe@177 864 "initiative"."multistage_majority" = FALSE )
jbe@177 865 AND (
jbe@177 866 "policy_row"."no_reverse_beat_path" = FALSE OR
jbe@177 867 "initiative"."reverse_beat_path" = FALSE );
jbe@177 868 -- mark final winner:
jbe@177 869 UPDATE "initiative" SET "winner" = TRUE
jbe@177 870 FROM (
jbe@177 871 SELECT "id" AS "initiative_id"
jbe@177 872 FROM "initiative"
jbe@177 873 WHERE "issue_id" = "issue_id_p" AND "eligible"
jbe@177 874 ORDER BY "schulze_rank", "id"
jbe@177 875 LIMIT 1
jbe@177 876 ) AS "subquery"
jbe@177 877 WHERE "id" = "subquery"."initiative_id";
jbe@177 878 -- write (final) ranks:
jbe@177 879 "rank_v" := 1;
jbe@177 880 FOR "initiative_id_v" IN
jbe@177 881 SELECT "id"
jbe@177 882 FROM "initiative"
jbe@177 883 WHERE "issue_id" = "issue_id_p" AND "admitted"
jbe@177 884 ORDER BY
jbe@177 885 "winner" DESC,
jbe@177 886 ("direct_majority" AND "indirect_majority") DESC,
jbe@177 887 "schulze_rank",
jbe@177 888 "id"
jbe@177 889 LOOP
jbe@177 890 UPDATE "initiative" SET "rank" = "rank_v"
jbe@177 891 WHERE "id" = "initiative_id_v";
jbe@177 892 "rank_v" := "rank_v" + 1;
jbe@177 893 END LOOP;
jbe@177 894 -- set schulze rank of status quo and mark issue as finished:
jbe@177 895 UPDATE "issue" SET
jbe@177 896 "status_quo_schulze_rank" = "rank_ary"["dimension_v"],
jbe@177 897 "state" =
jbe@177 898 CASE WHEN EXISTS (
jbe@177 899 SELECT NULL FROM "initiative"
jbe@177 900 WHERE "issue_id" = "issue_id_p" AND "winner"
jbe@177 901 ) THEN
jbe@177 902 'finished_with_winner'::"issue_state"
jbe@177 903 ELSE
jbe@177 904 'finished_without_winner'::"issue_state"
jbe@177 905 END,
jbe@177 906 "ranks_available" = TRUE
jbe@177 907 WHERE "id" = "issue_id_p";
jbe@177 908 RETURN;
jbe@177 909 END;
jbe@177 910 $$;
jbe@177 911
jbe@177 912 CREATE OR REPLACE FUNCTION "check_issue"
jbe@177 913 ( "issue_id_p" "issue"."id"%TYPE )
jbe@177 914 RETURNS VOID
jbe@177 915 LANGUAGE 'plpgsql' VOLATILE AS $$
jbe@177 916 DECLARE
jbe@177 917 "issue_row" "issue"%ROWTYPE;
jbe@177 918 "policy_row" "policy"%ROWTYPE;
jbe@177 919 BEGIN
jbe@177 920 PERFORM "lock_issue"("issue_id_p");
jbe@177 921 SELECT * INTO "issue_row" FROM "issue" WHERE "id" = "issue_id_p";
jbe@177 922 -- only process open issues:
jbe@177 923 IF "issue_row"."closed" ISNULL THEN
jbe@177 924 SELECT * INTO "policy_row" FROM "policy"
jbe@177 925 WHERE "id" = "issue_row"."policy_id";
jbe@177 926 -- create a snapshot, unless issue is already fully frozen:
jbe@177 927 IF "issue_row"."fully_frozen" ISNULL THEN
jbe@177 928 PERFORM "create_snapshot"("issue_id_p");
jbe@177 929 SELECT * INTO "issue_row" FROM "issue" WHERE "id" = "issue_id_p";
jbe@177 930 END IF;
jbe@177 931 -- eventually close or accept issues, which have not been accepted:
jbe@177 932 IF "issue_row"."accepted" ISNULL THEN
jbe@177 933 IF EXISTS (
jbe@177 934 SELECT NULL FROM "initiative"
jbe@177 935 WHERE "issue_id" = "issue_id_p"
jbe@177 936 AND "supporter_count" > 0
jbe@177 937 AND "supporter_count" * "policy_row"."issue_quorum_den"
jbe@177 938 >= "issue_row"."population" * "policy_row"."issue_quorum_num"
jbe@177 939 ) THEN
jbe@177 940 -- accept issues, if supporter count is high enough
jbe@177 941 PERFORM "set_snapshot_event"("issue_id_p", 'end_of_admission');
jbe@177 942 -- NOTE: "issue_row" used later
jbe@177 943 "issue_row"."state" := 'discussion';
jbe@177 944 "issue_row"."accepted" := now();
jbe@177 945 UPDATE "issue" SET
jbe@177 946 "state" = "issue_row"."state",
jbe@177 947 "accepted" = "issue_row"."accepted"
jbe@177 948 WHERE "id" = "issue_row"."id";
jbe@177 949 ELSIF
jbe@177 950 now() >= "issue_row"."created" + "issue_row"."admission_time"
jbe@177 951 THEN
jbe@177 952 -- close issues, if admission time has expired
jbe@177 953 PERFORM "set_snapshot_event"("issue_id_p", 'end_of_admission');
jbe@177 954 UPDATE "issue" SET
jbe@177 955 "state" = 'canceled_issue_not_accepted',
jbe@177 956 "closed" = now()
jbe@177 957 WHERE "id" = "issue_row"."id";
jbe@177 958 END IF;
jbe@177 959 END IF;
jbe@177 960 -- eventually half freeze issues:
jbe@177 961 IF
jbe@177 962 -- NOTE: issue can't be closed at this point, if it has been accepted
jbe@177 963 "issue_row"."accepted" NOTNULL AND
jbe@177 964 "issue_row"."half_frozen" ISNULL
jbe@177 965 THEN
jbe@177 966 IF
jbe@177 967 now() >= "issue_row"."accepted" + "issue_row"."discussion_time"
jbe@177 968 THEN
jbe@177 969 PERFORM "set_snapshot_event"("issue_id_p", 'half_freeze');
jbe@177 970 -- NOTE: "issue_row" used later
jbe@177 971 "issue_row"."state" := 'verification';
jbe@177 972 "issue_row"."half_frozen" := now();
jbe@177 973 UPDATE "issue" SET
jbe@177 974 "state" = "issue_row"."state",
jbe@177 975 "half_frozen" = "issue_row"."half_frozen"
jbe@177 976 WHERE "id" = "issue_row"."id";
jbe@177 977 END IF;
jbe@177 978 END IF;
jbe@177 979 -- close issues after some time, if all initiatives have been revoked:
jbe@177 980 IF
jbe@177 981 "issue_row"."closed" ISNULL AND
jbe@177 982 NOT EXISTS (
jbe@177 983 -- all initiatives are revoked
jbe@177 984 SELECT NULL FROM "initiative"
jbe@177 985 WHERE "issue_id" = "issue_id_p" AND "revoked" ISNULL
jbe@177 986 ) AND (
jbe@177 987 -- and issue has not been accepted yet
jbe@177 988 "issue_row"."accepted" ISNULL OR
jbe@177 989 NOT EXISTS (
jbe@177 990 -- or no initiatives have been revoked lately
jbe@177 991 SELECT NULL FROM "initiative"
jbe@177 992 WHERE "issue_id" = "issue_id_p"
jbe@177 993 AND now() < "revoked" + "issue_row"."verification_time"
jbe@177 994 ) OR (
jbe@177 995 -- or verification time has elapsed
jbe@177 996 "issue_row"."half_frozen" NOTNULL AND
jbe@177 997 "issue_row"."fully_frozen" ISNULL AND
jbe@177 998 now() >= "issue_row"."half_frozen" + "issue_row"."verification_time"
jbe@177 999 )
jbe@177 1000 )
jbe@177 1001 THEN
jbe@177 1002 -- NOTE: "issue_row" used later
jbe@177 1003 IF "issue_row"."accepted" ISNULL THEN
jbe@177 1004 "issue_row"."state" := 'canceled_revoked_before_accepted';
jbe@177 1005 ELSIF "issue_row"."half_frozen" ISNULL THEN
jbe@177 1006 "issue_row"."state" := 'canceled_after_revocation_during_discussion';
jbe@177 1007 ELSE
jbe@177 1008 "issue_row"."state" := 'canceled_after_revocation_during_verification';
jbe@177 1009 END IF;
jbe@177 1010 "issue_row"."closed" := now();
jbe@177 1011 UPDATE "issue" SET
jbe@177 1012 "state" = "issue_row"."state",
jbe@177 1013 "closed" = "issue_row"."closed"
jbe@177 1014 WHERE "id" = "issue_row"."id";
jbe@177 1015 END IF;
jbe@177 1016 -- fully freeze issue after verification time:
jbe@177 1017 IF
jbe@177 1018 "issue_row"."half_frozen" NOTNULL AND
jbe@177 1019 "issue_row"."fully_frozen" ISNULL AND
jbe@177 1020 "issue_row"."closed" ISNULL AND
jbe@177 1021 now() >= "issue_row"."half_frozen" + "issue_row"."verification_time"
jbe@177 1022 THEN
jbe@177 1023 PERFORM "freeze_after_snapshot"("issue_id_p");
jbe@177 1024 -- NOTE: "issue" might change, thus "issue_row" has to be updated below
jbe@177 1025 END IF;
jbe@177 1026 SELECT * INTO "issue_row" FROM "issue" WHERE "id" = "issue_id_p";
jbe@177 1027 -- close issue by calling close_voting(...) after voting time:
jbe@177 1028 IF
jbe@177 1029 "issue_row"."closed" ISNULL AND
jbe@177 1030 "issue_row"."fully_frozen" NOTNULL AND
jbe@177 1031 now() >= "issue_row"."fully_frozen" + "issue_row"."voting_time"
jbe@177 1032 THEN
jbe@177 1033 PERFORM "close_voting"("issue_id_p");
jbe@177 1034 -- calculate ranks will not consume much time and can be done now
jbe@177 1035 PERFORM "calculate_ranks"("issue_id_p");
jbe@177 1036 END IF;
jbe@177 1037 END IF;
jbe@177 1038 RETURN;
jbe@177 1039 END;
jbe@177 1040 $$;
jbe@177 1041
jbe@178 1042 COMMIT;
jbe@178 1043
jbe@178 1044 BEGIN;
jbe@178 1045
jbe@182 1046 UPDATE "member" SET "activated" = "created";
jbe@182 1047
jbe@182 1048 UPDATE "member" SET
jbe@182 1049 "created" = "invite_code"."created",
jbe@182 1050 "invite_code" = "invite_code"."code",
jbe@182 1051 "admin_comment" = "invite_code"."comment"
jbe@182 1052 FROM "invite_code"
jbe@182 1053 WHERE "member"."id" = "invite_code"."member_id";
jbe@182 1054
jbe@182 1055 DROP TABLE "invite_code_unit";
jbe@182 1056 DROP TABLE "invite_code";
jbe@182 1057
jbe@178 1058 UPDATE "initiative" SET
jbe@178 1059 "direct_majority" = "rank" NOTNULL,
jbe@178 1060 "indirect_majority" = "rank" NOTNULL,
jbe@178 1061 "schulze_rank" = "rank",
jbe@178 1062 "better_than_status_quo" = "rank" NOTNULL,
jbe@178 1063 "worse_than_status_quo" = "rank" ISNULL,
jbe@178 1064 "reverse_beat_path" = "rank" ISNULL,
jbe@178 1065 "multistage_majority" = "rank" ISNULL,
jbe@178 1066 "eligible" = "rank" NOTNULL,
jbe@178 1067 "winner" = ("rank" = 1)
jbe@178 1068 FROM "issue"
jbe@178 1069 WHERE "issue"."id" = "initiative"."issue_id"
jbe@178 1070 AND "issue"."state" IN ('finished_without_winner', 'finished_with_winner')
jbe@178 1071 AND "initiative"."admitted";
jbe@177 1072
jbe@178 1073 UPDATE "issue" SET "status_quo_schulze_rank" = "subquery"."rank"
jbe@178 1074 FROM (
jbe@178 1075 SELECT
jbe@178 1076 "issue"."id" AS "issue_id",
jbe@178 1077 COALESCE(max("initiative"."rank") + 1) AS "rank"
jbe@178 1078 FROM "issue" JOIN "initiative"
jbe@178 1079 ON "issue"."id" = "initiative"."issue_id"
jbe@178 1080 WHERE "issue"."state" IN ('finished_without_winner', 'finished_with_winner')
jbe@178 1081 AND "initiative"."admitted"
jbe@178 1082 GROUP BY "issue"."id"
jbe@178 1083 ) AS "subquery"
jbe@178 1084 WHERE "issue"."id" = "subquery"."issue_id";
jbe@178 1085
jbe@178 1086 CREATE FUNCTION "update__set_remaining_ranks"("issue_id_p" "issue"."id"%TYPE)
jbe@178 1087 RETURNS VOID
jbe@178 1088 LANGUAGE 'plpgsql' AS $$
jbe@178 1089 DECLARE
jbe@178 1090 "rank_v" INT4;
jbe@178 1091 "initiative_id_v" INT4;
jbe@178 1092 BEGIN
jbe@178 1093 SELECT "status_quo_schulze_rank" INTO "rank_v"
jbe@178 1094 FROM "issue" WHERE "id" = "issue_id_p";
jbe@178 1095 FOR "initiative_id_v" IN
jbe@178 1096 SELECT "id" FROM "initiative"
jbe@178 1097 WHERE "issue_id" = "issue_id_p" AND "admitted" AND "rank" ISNULL
jbe@178 1098 ORDER BY "vote_ratio"("positive_votes", "negative_votes") DESC
jbe@178 1099 LOOP
jbe@178 1100 UPDATE "initiative" SET
jbe@178 1101 "schulze_rank" = "rank_v" + 1,
jbe@178 1102 "rank" = "rank_v"
jbe@178 1103 WHERE "id" = "initiative_id_v";
jbe@178 1104 "rank_v" := "rank_v" + 1;
jbe@178 1105 END LOOP;
jbe@178 1106 RETURN;
jbe@178 1107 END;
jbe@178 1108 $$;
jbe@178 1109
jbe@178 1110 SELECT "update__set_remaining_ranks"("id") FROM "issue"
jbe@178 1111 WHERE "state" IN ('finished_without_winner', 'finished_with_winner');
jbe@178 1112
jbe@178 1113 DROP FUNCTION "update__set_remaining_ranks"("issue"."id"%TYPE);
jbe@177 1114
jbe@177 1115 UPDATE "suggestion" SET "draft_id" = "subquery"."draft_id"
jbe@177 1116 FROM (
jbe@177 1117 SELECT DISTINCT ON ("suggestion"."id")
jbe@177 1118 "suggestion"."id" AS "suggestion_id",
jbe@177 1119 "draft"."id" AS "draft_id"
jbe@177 1120 FROM "suggestion" JOIN "draft"
jbe@177 1121 ON "suggestion"."initiative_id" = "draft"."initiative_id"
jbe@177 1122 WHERE "draft"."created" <= "suggestion"."created"
jbe@177 1123 ORDER BY "suggestion"."id", "draft"."created" DESC
jbe@177 1124 ) AS "subquery"
jbe@177 1125 WHERE "suggestion"."id" = "subquery"."suggestion_id";
jbe@177 1126
jbe@178 1127 COMMIT;
jbe@178 1128
jbe@182 1129 ALTER TABLE "member" ADD CONSTRAINT "not_active_without_activated"
jbe@182 1130 CHECK ("activated" NOTNULL OR "active" = FALSE);
jbe@177 1131 ALTER TABLE "suggestion" ALTER COLUMN "draft_id" SET NOT NULL;

Impressum / About Us