jbe@383: BEGIN; jbe@383: jbe@383: CREATE OR REPLACE VIEW "liquid_feedback_version" AS jbe@383: SELECT * FROM (VALUES ('2.2.2', 2, 2, 2)) jbe@383: AS "subquery"("string", "major", "minor", "revision"); jbe@383: jbe@383: CREATE TABLE "internal_session_store" ( jbe@383: PRIMARY KEY ("backend_pid", "key"), jbe@383: "backend_pid" INT4, jbe@383: "key" TEXT, jbe@383: "value" TEXT NOT NULL ); jbe@383: jbe@383: COMMENT ON TABLE "internal_session_store" IS 'Table to store session variables; shall be emptied before a transaction is committed'; jbe@383: jbe@383: COMMENT ON COLUMN "internal_session_store"."backend_pid" IS 'Value returned by function pg_backend_pid()'; jbe@383: jbe@383: CREATE OR REPLACE FUNCTION "forbid_changes_on_closed_issue_trigger"() jbe@383: RETURNS TRIGGER jbe@383: LANGUAGE 'plpgsql' VOLATILE AS $$ jbe@383: DECLARE jbe@383: "issue_id_v" "issue"."id"%TYPE; jbe@383: "issue_row" "issue"%ROWTYPE; jbe@383: BEGIN jbe@383: IF EXISTS ( jbe@383: SELECT NULL FROM "internal_session_store" jbe@383: WHERE "backend_pid" = pg_backend_pid() jbe@383: AND "key" = 'override_protection_triggers' jbe@383: AND "value" = TRUE::TEXT jbe@383: ) THEN jbe@383: RETURN NULL; jbe@383: END IF; jbe@383: IF TG_OP = 'DELETE' THEN jbe@383: "issue_id_v" := OLD."issue_id"; jbe@383: ELSE jbe@383: "issue_id_v" := NEW."issue_id"; jbe@383: END IF; jbe@383: SELECT INTO "issue_row" * FROM "issue" jbe@383: WHERE "id" = "issue_id_v" FOR SHARE; jbe@383: IF ( jbe@383: "issue_row"."closed" NOTNULL OR ( jbe@383: "issue_row"."state" = 'voting' AND jbe@383: "issue_row"."phase_finished" NOTNULL jbe@383: ) jbe@383: ) THEN jbe@383: IF jbe@383: TG_RELID = 'direct_voter'::regclass AND jbe@383: TG_OP = 'UPDATE' jbe@383: THEN jbe@383: IF jbe@383: OLD."issue_id" = NEW."issue_id" AND jbe@383: OLD."member_id" = NEW."member_id" AND jbe@383: OLD."weight" = NEW."weight" jbe@383: THEN jbe@383: RETURN NULL; -- allows changing of voter comment jbe@383: END IF; jbe@383: END IF; jbe@383: RAISE EXCEPTION 'Tried to modify data after voting has been closed.'; jbe@383: END IF; jbe@383: RETURN NULL; jbe@383: END; jbe@383: $$; jbe@383: jbe@383: CREATE OR REPLACE FUNCTION "close_voting"("issue_id_p" "issue"."id"%TYPE) jbe@383: RETURNS VOID jbe@383: LANGUAGE 'plpgsql' VOLATILE AS $$ jbe@383: DECLARE jbe@383: "area_id_v" "area"."id"%TYPE; jbe@383: "unit_id_v" "unit"."id"%TYPE; jbe@383: "member_id_v" "member"."id"%TYPE; jbe@383: BEGIN jbe@383: PERFORM "require_transaction_isolation"(); jbe@383: SELECT "area_id" INTO "area_id_v" FROM "issue" WHERE "id" = "issue_id_p"; jbe@383: SELECT "unit_id" INTO "unit_id_v" FROM "area" WHERE "id" = "area_id_v"; jbe@383: -- override protection triggers: jbe@383: DELETE FROM "internal_session_store"; jbe@383: INSERT INTO "internal_session_store" ("backend_pid", "key", "value") jbe@383: VALUES (pg_backend_pid(), 'override_protection_triggers', TRUE::TEXT); jbe@383: -- delete timestamp of voting comment: jbe@383: UPDATE "direct_voter" SET "comment_changed" = NULL jbe@383: WHERE "issue_id" = "issue_id_p"; jbe@383: -- delete delegating votes (in cases of manual reset of issue state): jbe@383: DELETE FROM "delegating_voter" jbe@383: WHERE "issue_id" = "issue_id_p"; jbe@383: -- delete votes from non-privileged voters: jbe@383: DELETE FROM "direct_voter" jbe@383: USING ( jbe@383: SELECT jbe@383: "direct_voter"."member_id" jbe@383: FROM "direct_voter" jbe@383: JOIN "member" ON "direct_voter"."member_id" = "member"."id" jbe@383: LEFT JOIN "privilege" jbe@383: ON "privilege"."unit_id" = "unit_id_v" jbe@383: AND "privilege"."member_id" = "direct_voter"."member_id" jbe@383: WHERE "direct_voter"."issue_id" = "issue_id_p" AND ( jbe@383: "member"."active" = FALSE OR jbe@383: "privilege"."voting_right" ISNULL OR jbe@383: "privilege"."voting_right" = FALSE jbe@383: ) jbe@383: ) AS "subquery" jbe@383: WHERE "direct_voter"."issue_id" = "issue_id_p" jbe@383: AND "direct_voter"."member_id" = "subquery"."member_id"; jbe@383: -- consider delegations: jbe@383: UPDATE "direct_voter" SET "weight" = 1 jbe@383: WHERE "issue_id" = "issue_id_p"; jbe@383: PERFORM "add_vote_delegations"("issue_id_p"); jbe@383: -- finish overriding protection triggers (mandatory, as pids may be reused): jbe@383: DELETE FROM "internal_session_store"; jbe@383: -- materialize battle_view: jbe@383: -- NOTE: "closed" column of issue must be set at this point jbe@383: DELETE FROM "battle" WHERE "issue_id" = "issue_id_p"; jbe@383: INSERT INTO "battle" ( jbe@383: "issue_id", jbe@383: "winning_initiative_id", "losing_initiative_id", jbe@383: "count" jbe@383: ) SELECT jbe@383: "issue_id", jbe@383: "winning_initiative_id", "losing_initiative_id", jbe@383: "count" jbe@383: FROM "battle_view" WHERE "issue_id" = "issue_id_p"; jbe@383: -- set voter count: jbe@383: UPDATE "issue" SET jbe@383: "voter_count" = ( jbe@383: SELECT coalesce(sum("weight"), 0) jbe@383: FROM "direct_voter" WHERE "issue_id" = "issue_id_p" jbe@383: ) jbe@383: WHERE "id" = "issue_id_p"; jbe@383: -- copy "positive_votes" and "negative_votes" from "battle" table: jbe@383: UPDATE "initiative" SET jbe@383: "positive_votes" = "battle_win"."count", jbe@383: "negative_votes" = "battle_lose"."count" jbe@383: FROM "battle" AS "battle_win", "battle" AS "battle_lose" jbe@383: WHERE jbe@383: "battle_win"."issue_id" = "issue_id_p" AND jbe@383: "battle_win"."winning_initiative_id" = "initiative"."id" AND jbe@383: "battle_win"."losing_initiative_id" ISNULL AND jbe@383: "battle_lose"."issue_id" = "issue_id_p" AND jbe@383: "battle_lose"."losing_initiative_id" = "initiative"."id" AND jbe@383: "battle_lose"."winning_initiative_id" ISNULL; jbe@383: END; jbe@383: $$; jbe@383: jbe@383: COMMIT;