jbe@385: BEGIN; jbe@385: jbe@385: CREATE OR REPLACE VIEW "liquid_feedback_version" AS jbe@385: SELECT * FROM (VALUES ('2.2.3', 2, 2, 3)) jbe@385: AS "subquery"("string", "major", "minor", "revision"); jbe@385: jbe@385: DROP TABLE "internal_session_store"; jbe@385: jbe@385: CREATE TABLE "temporary_transaction_data" ( jbe@385: PRIMARY KEY ("txid", "key"), jbe@385: "txid" INT8 DEFAULT txid_current(), jbe@385: "key" TEXT, jbe@385: "value" TEXT NOT NULL ); jbe@385: jbe@385: COMMENT ON TABLE "temporary_transaction_data" IS 'Table to store temporary transaction data; shall be emptied before a transaction is committed'; jbe@385: jbe@385: COMMENT ON COLUMN "temporary_transaction_data"."txid" IS 'Value returned by function txid_current(); should be added to WHERE clause, when doing SELECT on this table, but ignored when doing DELETE on this table'; jbe@385: jbe@385: CREATE OR REPLACE FUNCTION "forbid_changes_on_closed_issue_trigger"() jbe@385: RETURNS TRIGGER jbe@385: LANGUAGE 'plpgsql' VOLATILE AS $$ jbe@385: DECLARE jbe@385: "issue_id_v" "issue"."id"%TYPE; jbe@385: "issue_row" "issue"%ROWTYPE; jbe@385: BEGIN jbe@385: IF EXISTS ( jbe@385: SELECT NULL FROM "temporary_transaction_data" jbe@385: WHERE "txid" = txid_current() jbe@385: AND "key" = 'override_protection_triggers' jbe@385: AND "value" = TRUE::TEXT jbe@385: ) THEN jbe@385: RETURN NULL; jbe@385: END IF; jbe@385: IF TG_OP = 'DELETE' THEN jbe@385: "issue_id_v" := OLD."issue_id"; jbe@385: ELSE jbe@385: "issue_id_v" := NEW."issue_id"; jbe@385: END IF; jbe@385: SELECT INTO "issue_row" * FROM "issue" jbe@385: WHERE "id" = "issue_id_v" FOR SHARE; jbe@385: IF ( jbe@385: "issue_row"."closed" NOTNULL OR ( jbe@385: "issue_row"."state" = 'voting' AND jbe@385: "issue_row"."phase_finished" NOTNULL jbe@385: ) jbe@385: ) THEN jbe@385: IF jbe@385: TG_RELID = 'direct_voter'::regclass AND jbe@385: TG_OP = 'UPDATE' jbe@385: THEN jbe@385: IF jbe@385: OLD."issue_id" = NEW."issue_id" AND jbe@385: OLD."member_id" = NEW."member_id" AND jbe@385: OLD."weight" = NEW."weight" jbe@385: THEN jbe@385: RETURN NULL; -- allows changing of voter comment jbe@385: END IF; jbe@385: END IF; jbe@385: RAISE EXCEPTION 'Tried to modify data after voting has been closed.'; jbe@385: END IF; jbe@385: RETURN NULL; jbe@385: END; jbe@385: $$; jbe@385: jbe@385: CREATE OR REPLACE FUNCTION "close_voting"("issue_id_p" "issue"."id"%TYPE) jbe@385: RETURNS VOID jbe@385: LANGUAGE 'plpgsql' VOLATILE AS $$ jbe@385: DECLARE jbe@385: "area_id_v" "area"."id"%TYPE; jbe@385: "unit_id_v" "unit"."id"%TYPE; jbe@385: "member_id_v" "member"."id"%TYPE; jbe@385: BEGIN jbe@385: PERFORM "require_transaction_isolation"(); jbe@385: SELECT "area_id" INTO "area_id_v" FROM "issue" WHERE "id" = "issue_id_p"; jbe@385: SELECT "unit_id" INTO "unit_id_v" FROM "area" WHERE "id" = "area_id_v"; jbe@385: -- override protection triggers: jbe@385: INSERT INTO "temporary_transaction_data" ("key", "value") jbe@385: VALUES ('override_protection_triggers', TRUE::TEXT); jbe@385: -- delete timestamp of voting comment: jbe@385: UPDATE "direct_voter" SET "comment_changed" = NULL jbe@385: WHERE "issue_id" = "issue_id_p"; jbe@385: -- delete delegating votes (in cases of manual reset of issue state): jbe@385: DELETE FROM "delegating_voter" jbe@385: WHERE "issue_id" = "issue_id_p"; jbe@385: -- delete votes from non-privileged voters: jbe@385: DELETE FROM "direct_voter" jbe@385: USING ( jbe@385: SELECT jbe@385: "direct_voter"."member_id" jbe@385: FROM "direct_voter" jbe@385: JOIN "member" ON "direct_voter"."member_id" = "member"."id" jbe@385: LEFT JOIN "privilege" jbe@385: ON "privilege"."unit_id" = "unit_id_v" jbe@385: AND "privilege"."member_id" = "direct_voter"."member_id" jbe@385: WHERE "direct_voter"."issue_id" = "issue_id_p" AND ( jbe@385: "member"."active" = FALSE OR jbe@385: "privilege"."voting_right" ISNULL OR jbe@385: "privilege"."voting_right" = FALSE jbe@385: ) jbe@385: ) AS "subquery" jbe@385: WHERE "direct_voter"."issue_id" = "issue_id_p" jbe@385: AND "direct_voter"."member_id" = "subquery"."member_id"; jbe@385: -- consider delegations: jbe@385: UPDATE "direct_voter" SET "weight" = 1 jbe@385: WHERE "issue_id" = "issue_id_p"; jbe@385: PERFORM "add_vote_delegations"("issue_id_p"); jbe@385: -- finish overriding protection triggers (avoids garbage): jbe@385: DELETE FROM "temporary_transaction_data" jbe@385: WHERE "key" = 'override_protection_triggers'; jbe@385: -- materialize battle_view: jbe@385: -- NOTE: "closed" column of issue must be set at this point jbe@385: DELETE FROM "battle" WHERE "issue_id" = "issue_id_p"; jbe@385: INSERT INTO "battle" ( jbe@385: "issue_id", jbe@385: "winning_initiative_id", "losing_initiative_id", jbe@385: "count" jbe@385: ) SELECT jbe@385: "issue_id", jbe@385: "winning_initiative_id", "losing_initiative_id", jbe@385: "count" jbe@385: FROM "battle_view" WHERE "issue_id" = "issue_id_p"; jbe@385: -- set voter count: jbe@385: UPDATE "issue" SET jbe@385: "voter_count" = ( jbe@385: SELECT coalesce(sum("weight"), 0) jbe@385: FROM "direct_voter" WHERE "issue_id" = "issue_id_p" jbe@385: ) jbe@385: WHERE "id" = "issue_id_p"; jbe@385: -- copy "positive_votes" and "negative_votes" from "battle" table: jbe@385: UPDATE "initiative" SET jbe@385: "positive_votes" = "battle_win"."count", jbe@385: "negative_votes" = "battle_lose"."count" jbe@385: FROM "battle" AS "battle_win", "battle" AS "battle_lose" jbe@385: WHERE jbe@385: "battle_win"."issue_id" = "issue_id_p" AND jbe@385: "battle_win"."winning_initiative_id" = "initiative"."id" AND jbe@385: "battle_win"."losing_initiative_id" ISNULL AND jbe@385: "battle_lose"."issue_id" = "issue_id_p" AND jbe@385: "battle_lose"."losing_initiative_id" = "initiative"."id" AND jbe@385: "battle_lose"."winning_initiative_id" ISNULL; jbe@385: END; jbe@385: $$; jbe@385: jbe@385: CREATE OR REPLACE FUNCTION "clean_issue"("issue_id_p" "issue"."id"%TYPE) jbe@385: RETURNS VOID jbe@385: LANGUAGE 'plpgsql' VOLATILE AS $$ jbe@385: BEGIN jbe@385: IF EXISTS ( jbe@385: SELECT NULL FROM "issue" WHERE "id" = "issue_id_p" AND "cleaned" ISNULL jbe@385: ) THEN jbe@385: -- override protection triggers: jbe@385: INSERT INTO "temporary_transaction_data" ("key", "value") jbe@385: VALUES ('override_protection_triggers', TRUE::TEXT); jbe@385: -- clean data: jbe@385: DELETE FROM "delegating_voter" jbe@385: WHERE "issue_id" = "issue_id_p"; jbe@385: DELETE FROM "direct_voter" jbe@385: WHERE "issue_id" = "issue_id_p"; jbe@385: DELETE FROM "delegating_interest_snapshot" jbe@385: WHERE "issue_id" = "issue_id_p"; jbe@385: DELETE FROM "direct_interest_snapshot" jbe@385: WHERE "issue_id" = "issue_id_p"; jbe@385: DELETE FROM "delegating_population_snapshot" jbe@385: WHERE "issue_id" = "issue_id_p"; jbe@385: DELETE FROM "direct_population_snapshot" jbe@385: WHERE "issue_id" = "issue_id_p"; jbe@385: DELETE FROM "non_voter" jbe@385: WHERE "issue_id" = "issue_id_p"; jbe@385: DELETE FROM "delegation" jbe@385: WHERE "issue_id" = "issue_id_p"; jbe@385: DELETE FROM "supporter" jbe@385: USING "initiative" -- NOTE: due to missing index on issue_id jbe@385: WHERE "initiative"."issue_id" = "issue_id_p" jbe@385: AND "supporter"."initiative_id" = "initiative_id"; jbe@385: -- mark issue as cleaned: jbe@385: UPDATE "issue" SET "cleaned" = now() WHERE "id" = "issue_id_p"; jbe@385: -- finish overriding protection triggers (avoids garbage): jbe@385: DELETE FROM "temporary_transaction_data" jbe@385: WHERE "key" = 'override_protection_triggers'; jbe@385: END IF; jbe@385: RETURN; jbe@385: END; jbe@385: $$; jbe@385: jbe@385: CREATE OR REPLACE FUNCTION "delete_private_data"() jbe@385: RETURNS VOID jbe@385: LANGUAGE 'plpgsql' VOLATILE AS $$ jbe@385: BEGIN jbe@385: DELETE FROM "temporary_transaction_data"; jbe@385: DELETE FROM "member" WHERE "activated" ISNULL; jbe@385: UPDATE "member" SET jbe@385: "invite_code" = NULL, jbe@385: "invite_code_expiry" = NULL, jbe@385: "admin_comment" = NULL, jbe@385: "last_login" = NULL, jbe@385: "login" = NULL, jbe@385: "password" = NULL, jbe@385: "lang" = NULL, jbe@385: "notify_email" = NULL, jbe@385: "notify_email_unconfirmed" = NULL, jbe@385: "notify_email_secret" = NULL, jbe@385: "notify_email_secret_expiry" = NULL, jbe@385: "notify_email_lock_expiry" = NULL, jbe@385: "notify_level" = NULL, jbe@385: "password_reset_secret" = NULL, jbe@385: "password_reset_secret_expiry" = NULL, jbe@385: "organizational_unit" = NULL, jbe@385: "internal_posts" = NULL, jbe@385: "realname" = NULL, jbe@385: "birthday" = NULL, jbe@385: "address" = NULL, jbe@385: "email" = NULL, jbe@385: "xmpp_address" = NULL, jbe@385: "website" = NULL, jbe@385: "phone" = NULL, jbe@385: "mobile_phone" = NULL, jbe@385: "profession" = NULL, jbe@385: "external_memberships" = NULL, jbe@385: "external_posts" = NULL, jbe@385: "formatting_engine" = NULL, jbe@385: "statement" = NULL; jbe@385: -- "text_search_data" is updated by triggers jbe@385: DELETE FROM "setting"; jbe@385: DELETE FROM "setting_map"; jbe@385: DELETE FROM "member_relation_setting"; jbe@385: DELETE FROM "member_image"; jbe@385: DELETE FROM "contact"; jbe@385: DELETE FROM "ignored_member"; jbe@385: DELETE FROM "session"; jbe@385: DELETE FROM "area_setting"; jbe@385: DELETE FROM "issue_setting"; jbe@385: DELETE FROM "ignored_initiative"; jbe@385: DELETE FROM "initiative_setting"; jbe@385: DELETE FROM "suggestion_setting"; jbe@385: DELETE FROM "non_voter"; jbe@385: DELETE FROM "direct_voter" USING "issue" jbe@385: WHERE "direct_voter"."issue_id" = "issue"."id" jbe@385: AND "issue"."closed" ISNULL; jbe@385: RETURN; jbe@385: END; jbe@385: $$; jbe@385: jbe@385: COMMIT;