Files
2013-04-15 12:37:45 -04:00

550 lines
22 KiB
PL/PgSQL

-------------------------------------------------------------------------------
-- million trillion trillion
-- | trillion trillion
-- | | trillion
-- | | | billion
-- | | | | million
-- | | | | | thousand
-- | | | | | |
-- numeric(35,2) maxes out at $999,999,999,999,999,999,999,999,999,999,999.00.
-------------------------------------------------------------------------------
-- Create the initial structure.
CREATE EXTENSION hstore;
CREATE TABLE participants
( id text PRIMARY KEY
, statement text DEFAULT ''
, stripe_customer_id text DEFAULT NULL
, last_bill_result text DEFAULT NULL
, session_token text UNIQUE DEFAULT NULL
, session_expires timestamp with time zone DEFAULT CURRENT_TIMESTAMP
, ctime timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
, claimed_time timestamp with time zone DEFAULT NULL
, is_admin boolean NOT NULL DEFAULT FALSE
, shares_giving boolean NOT NULL DEFAULT TRUE
-- If this isn't NULL then it means one participant was folded into another
-- and all requests for this participant should be redirected to the other.
, redirect text DEFAULT NULL REFERENCES participants
-- The participants balance is expected to be receipts - disbursements. It is
-- stored here as an optimization and sanity check.
, balance numeric(35,2) DEFAULT 0.0
, pending numeric(35,2) DEFAULT NULL
);
CREATE TABLE social_network_users
( id serial PRIMARY KEY
, network text NOT NULL
, user_id text NOT NULL
, user_info hstore
, is_locked boolean NOT NULL DEFAULT FALSE
, participant_id text DEFAULT NULL REFERENCES participants ON DELETE RESTRICT
, UNIQUE(network, user_id)
);
-- tips -- all times a participant elects to tip another
CREATE TABLE tips
( id serial PRIMARY KEY
, ctime timestamp with time zone NOT NULL
, mtime timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
, tipper text NOT NULL REFERENCES participants ON DELETE RESTRICT
, tippee text NOT NULL REFERENCES participants ON DELETE RESTRICT
, amount numeric(35,2) NOT NULL
);
-- transfers -- balance transfers from one user to another
CREATE TABLE transfers
( id serial PRIMARY KEY
, timestamp timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
, tipper text NOT NULL REFERENCES participants ON DELETE RESTRICT
, tippee text NOT NULL REFERENCES participants ON DELETE RESTRICT
, amount numeric(35,2) NOT NULL
);
-- paydays -- payday events, stats about them
CREATE TABLE paydays
( id serial PRIMARY KEY
, ts_start timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
, ts_end timestamp with time zone UNIQUE NOT NULL DEFAULT '1970-01-01T00:00:00+00'::timestamptz
, nparticipants bigint DEFAULT 0
, ntippers bigint DEFAULT 0
, ntips bigint DEFAULT 0
, ntransfers bigint DEFAULT 0
, transfer_volume numeric(35,2) DEFAULT 0.00
, ncc_failing bigint DEFAULT 0
, ncc_missing bigint DEFAULT 0
, nexchanges bigint DEFAULT 0
, exchange_volume numeric(35,2) DEFAULT 0.00
, exchange_fees_volume numeric(35,2) DEFAULT 0.00
);
-- exchanges -- when a participant moves cash between Gittip and their bank
CREATE TABLE exchanges
( id serial PRIMARY KEY
, timestamp timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
, amount numeric(35,2) NOT NULL
, fee numeric(35,2) NOT NULL
, participant_id text NOT NULL REFERENCES participants ON DELETE RESTRICT
);
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/128
ALTER TABLE participants ADD COLUMN anonymous bool NOT NULL DEFAULT FALSE;
ALTER TABLE participants DROP COLUMN shares_giving;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/110
ALTER TABLE participants ADD COLUMN goal numeric(35,2) DEFAULT NULL;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/78
ALTER TABLE participants ADD COLUMN balanced_account_uri text DEFAULT NULL;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/161
ALTER TABLE participants ADD CONSTRAINT min_balance CHECK(balance >= 0);
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/35
ALTER TABLE participants ALTER COLUMN statement SET NOT NULL;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/22
ALTER TABLE participants ADD COLUMN last_ach_result text DEFAULT NULL;
ALTER TABLE paydays RENAME COLUMN nexchanges TO ncharges;
ALTER TABLE paydays RENAME COLUMN exchange_volume TO charge_volume;
ALTER TABLE paydays RENAME COLUMN exchange_fees_volume TO charge_fees_volume;
ALTER TABLE paydays ADD COLUMN nachs bigint DEFAULT 0;
ALTER TABLE paydays ADD COLUMN ach_volume numeric(35,2) DEFAULT 0.00;
ALTER TABLE paydays ADD COLUMN ach_fees_volume numeric(35,2) DEFAULT 0.00;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/80
-- The redirect column ended up being YAGNI. I'm dropping it here because
-- it's implicated in constraints that we'd otherwise have to alter below.
ALTER TABLE participants DROP redirect;
BEGIN;
-- We need to be able to change participant_id and have that cascade out to
-- other tables. Let's do this in a transaction, just for kicks. Kinda
-- gives me the willies to be changing constraints like this. I think it's
-- because I never created the constraints so explicitly in the first
-- place. The below is copied / pasted / edited from `\d participants`.
-- I *think* I'm doing this right. :^O
ALTER TABLE "exchanges" DROP CONSTRAINT "exchanges_participant_id_fkey";
ALTER TABLE "exchanges" ADD CONSTRAINT "exchanges_participant_id_fkey"
FOREIGN KEY (participant_id) REFERENCES participants(id)
ON UPDATE CASCADE ON DELETE RESTRICT;
ALTER TABLE "social_network_users" DROP CONSTRAINT "social_network_users_participant_id_fkey";
ALTER TABLE "social_network_users" ADD CONSTRAINT "social_network_users_participant_id_fkey"
FOREIGN KEY (participant_id) REFERENCES participants(id)
ON UPDATE CASCADE ON DELETE RESTRICT;
ALTER TABLE "tips" DROP CONSTRAINT "tips_tippee_fkey";
ALTER TABLE "tips" ADD CONSTRAINT "tips_tippee_fkey"
FOREIGN KEY (tippee) REFERENCES participants(id)
ON UPDATE CASCADE ON DELETE RESTRICT;
ALTER TABLE "tips" DROP CONSTRAINT "tips_tipper_fkey";
ALTER TABLE "tips" ADD CONSTRAINT "tips_tipper_fkey"
FOREIGN KEY (tipper) REFERENCES participants(id)
ON UPDATE CASCADE ON DELETE RESTRICT;
ALTER TABLE "transfers" DROP CONSTRAINT "transfers_tippee_fkey";
ALTER TABLE "transfers" ADD CONSTRAINT "transfers_tippee_fkey"
FOREIGN KEY (tippee) REFERENCES participants(id)
ON UPDATE CASCADE ON DELETE RESTRICT;
ALTER TABLE "transfers" DROP CONSTRAINT "transfers_tipper_fkey";
ALTER TABLE "transfers" ADD CONSTRAINT "transfers_tipper_fkey"
FOREIGN KEY (tipper) REFERENCES participants(id)
ON UPDATE CASCADE ON DELETE RESTRICT;
END;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/35
-- https://github.com/gittip/www.gittip.com/issues/170
ALTER TABLE participants ALTER COLUMN balance SET NOT NULL;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/350
ALTER TABLE participants ADD COLUMN payin_suspended bool NOT NULL DEFAULT FALSE;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/354
ALTER TABLE participants ADD COLUMN is_suspicious bool DEFAULT NULL;
UPDATE participants SET is_suspicious=true WHERE payin_suspended;
ALTER TABLE participants DROP COLUMN payin_suspended;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/406
ALTER TABLE social_network_users RENAME TO elsewhere;
ALTER TABLE elsewhere RENAME COLUMN network TO platform;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/406
CREATE TABLE absorptions
( id serial PRIMARY KEY
, timestamp timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
, absorbed_by text NOT NULL REFERENCES participants ON DELETE RESTRICT
, absorbed text NOT NULL REFERENCES participants ON DELETE RESTRICT
);
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/406
-- Decided to change this. Easier to drop and recreate at this point.
DROP TABLE absorptions;
CREATE TABLE absorptions
( id serial PRIMARY KEY
, timestamp timestamp with time zone NOT NULL
DEFAULT CURRENT_TIMESTAMP
, absorbed_was text NOT NULL
-- Not a foreign key!
, absorbed_by text NOT NULL
REFERENCES participants ON DELETE RESTRICT ON UPDATE CASCADE
, archived_as text NOT NULL
REFERENCES participants ON DELETE RESTRICT ON UPDATE RESTRICT
-- For absorbed we actually want ON UPDATE RESTRICT as a sanity check:
-- noone should be changing participant_ids of absorbed accounts.
);
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/406
-- Let's clean up the naming of the constraints on the elsewhere table.
BEGIN;
ALTER TABLE elsewhere DROP CONSTRAINT "social_network_users_pkey";
ALTER TABLE elsewhere ADD CONSTRAINT "elsewhere_pkey"
PRIMARY KEY (id);
ALTER TABLE elsewhere DROP constraint "social_network_users_network_user_id_key";
ALTER TABLE elsewhere ADD constraint "elsewhere_platform_user_id_key"
UNIQUE (platform, user_id);
ALTER TABLE elsewhere DROP constraint "social_network_users_participant_id_fkey";
ALTER TABLE elsewhere ADD constraint "elsewhere_participant_id_fkey"
FOREIGN KEY (participant_id) REFERENCES participants(id)
ON UPDATE CASCADE ON DELETE RESTRICT;
END;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/419
ALTER TABLE paydays ADD COLUMN nach_failures bigint DEFAULT 0;
ALTER TABLE paydays RENAME COLUMN nach_failures TO nach_failing; -- double oops
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/35
-- https://github.com/gittip/www.gittip.com/issues/406
ALTER TABLE elsewhere ALTER COLUMN participant_id SET NOT NULL;
-- Every account elsewhere must have at least a stub participant account in
-- Gittip. However, not every participant must have an account elsewhere. A
-- participant without a connected account elsewhere will have no way to login
-- to Gittip. It will be considered "archived."
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/406
-- Gittip participants can only connect one account per platform at a time.
ALTER TABLE elsewhere ADD CONSTRAINT "elsewhere_platform_participant_id_key"
UNIQUE (platform, participant_id);
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/53
ALTER TABLE exchanges ADD COLUMN recorder text DEFAULT NULL
REFERENCES participants(id)
ON UPDATE CASCADE ON DELETE RESTRICT;
ALTER TABLE exchanges ADD COLUMN note text DEFAULT NULL;
-------------------------------------------------------------------------------
--- https://github.com/gittip/www.gittip.com/issues/545
create view goal_summary as SELECT tippee as id, goal, (amount/goal) * 100 as percentage, statement, sum(amount) as amount
FROM ( SELECT DISTINCT ON (tipper, tippee) tippee, amount
FROM tips
JOIN participants p ON p.id = tipper
JOIN participants p2 ON p2.id = tippee
WHERE p.last_bill_result = ''
AND p2.claimed_time IS NOT NULL
ORDER BY tipper, tippee, mtime DESC
) AS tips_agg
join participants p3 on p3.id = tips_agg.tippee
GROUP BY tippee, goal, percentage, statement
;
-------------------------------------------------------------------------------
--- https://github.com/gittip/www.gittip.com/issues/778
DROP VIEW goal_summary;
CREATE VIEW goal_summary AS
SELECT tippee as id
, goal
, CASE goal WHEN 0 THEN 0 ELSE (amount / goal) * 100 END AS percentage
, statement
, sum(amount) as amount
FROM ( SELECT DISTINCT ON (tipper, tippee) tippee, amount
FROM tips
JOIN participants p ON p.id = tipper
JOIN participants p2 ON p2.id = tippee
WHERE p.last_bill_result = ''
AND p2.claimed_time IS NOT NULL
ORDER BY tipper, tippee, mtime DESC
) AS tips_agg
JOIN participants p3 ON p3.id = tips_agg.tippee
WHERE goal > 0
GROUP BY tippee, goal, percentage, statement;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/141
-- Create a goals table to track all goals a participant has stated over time.
CREATE TABLE goals
( id serial PRIMARY KEY
, ctime timestamp with time zone NOT NULL
, mtime timestamp with time zone NOT NULL
DEFAULT CURRENT_TIMESTAMP
, participant text NOT NULL
REFERENCES participants
ON UPDATE CASCADE
ON DELETE RESTRICT
, goal numeric(35,2) DEFAULT NULL
);
BEGIN;
-- Migrate data from goal column of participants over to new goals table.
INSERT INTO goals (ctime, mtime, participant, goal)
SELECT CURRENT_TIMESTAMP
, CURRENT_TIMESTAMP
, id
, goal
FROM participants
WHERE goal IS NOT NULL;
-- Create a rule to log changes to participant.goal into goals.
CREATE RULE log_goal_changes
AS ON UPDATE TO participants
WHERE (OLD.goal IS NULL AND NOT NEW.goal IS NULL)
OR (NEW.goal IS NULL AND NOT OLD.goal IS NULL)
OR NEW.goal <> OLD.goal
DO
INSERT INTO goals
(ctime, participant, goal)
VALUES ( COALESCE (( SELECT ctime
FROM goals
WHERE participant=OLD.id
LIMIT 1
), CURRENT_TIMESTAMP)
, OLD.id
, NEW.goal
);
END;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/406
ALTER SEQUENCE social_network_users_id_seq RENAME TO elsewhere_id_seq;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/287
-- participants
ALTER TABLE participants RENAME COLUMN id TO username;
-- elsewhere
ALTER TABLE elsewhere RENAME COLUMN participant_id TO participant;
ALTER TABLE "elsewhere" DROP CONSTRAINT "elsewhere_participant_id_fkey";
ALTER TABLE "elsewhere" ADD CONSTRAINT "elsewhere_participant_fkey"
FOREIGN KEY (participant) REFERENCES participants(username)
ON UPDATE CASCADE ON DELETE RESTRICT;
ALTER TABLE "elsewhere" DROP CONSTRAINT
"elsewhere_platform_participant_id_key";
ALTER TABLE "elsewhere" ADD CONSTRAINT "elsewhere_platform_participant_key"
UNIQUE (platform, participant);
-- exchanges
ALTER TABLE exchanges RENAME COLUMN participant_id TO participant;
ALTER TABLE "exchanges" DROP CONSTRAINT "exchanges_participant_id_fkey";
ALTER TABLE "exchanges" ADD CONSTRAINT "exchanges_participant_fkey"
FOREIGN KEY (participant) REFERENCES participants(username)
ON UPDATE CASCADE ON DELETE RESTRICT;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/680
ALTER TABLE participants ADD COLUMN id bigserial NOT NULL UNIQUE;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/503
BEGIN;
ALTER TABLE participants ADD COLUMN username_lower text
NOT NULL DEFAULT '';
UPDATE participants SET username_lower = lower(username);
END;
ALTER TABLE participants ADD UNIQUE (username_lower);
ALTER TABLE participants ALTER COLUMN username_lower DROP DEFAULT;
-------------------------------------------------------------------------------
-- https://github.com/gittip/www.gittip.com/issues/449
BEGIN;
-------------------
-- participant type
CREATE TYPE participant_type AS ENUM ( 'individual'
, 'group'
, 'open group'
);
CREATE TABLE log_participant_type
( id serial PRIMARY KEY
, ctime timestamp with time zone NOT NULL
, mtime timestamp with time zone NOT NULL
DEFAULT CURRENT_TIMESTAMP
, participant text NOT NULL REFERENCES participants
ON UPDATE CASCADE ON DELETE RESTRICT
, type participant_type NOT NULL
);
ALTER TABLE participants ADD COLUMN type participant_type
NOT NULL DEFAULT 'individual';
CREATE RULE log_participant_type
AS ON UPDATE TO participants
WHERE NEW.type <> OLD.type
DO
INSERT INTO log_participant_type
(ctime, participant, type)
VALUES ( COALESCE (( SELECT ctime
FROM log_participant_type
WHERE participant=OLD.username
LIMIT 1
), CURRENT_TIMESTAMP)
, OLD.username
, NEW.type
);
------------------
-- identifications
CREATE TABLE identifications
( id bigserial PRIMARY KEY
, ctime timestamp with time zone NOT NULL
, mtime timestamp with time zone NOT NULL
DEFAULT CURRENT_TIMESTAMP
, member text NOT NULL REFERENCES participants
ON DELETE RESTRICT ON UPDATE CASCADE
, "group" text NOT NULL REFERENCES participants
ON DELETE RESTRICT ON UPDATE CASCADE
, weight int NOT NULL DEFAULT 0
, identified_by text NOT NULL REFERENCES participants
ON DELETE RESTRICT ON UPDATE CASCADE
, CONSTRAINT no_member_of_self CHECK (member != "group")
, CONSTRAINT no_self_nomination CHECK (member != "identified_by")
, CONSTRAINT no_stacking_the_deck CHECK ("group" != "identified_by")
);
CREATE VIEW current_identifications AS
SELECT DISTINCT ON (member, "group", identified_by) i.*
FROM identifications i
JOIN participants p ON p.username = identified_by
WHERE p.is_suspicious IS FALSE
ORDER BY member
, "group"
, identified_by
, mtime DESC;
END;
-------------------------------------------------------------------------------
CREATE VIEW backed_tips AS
SELECT DISTINCT ON (tipper, tippee) t.*
FROM tips t
JOIN participants p ON p.username = tipper
WHERE p.is_suspicious IS NOT TRUE
AND p.last_bill_result=''
ORDER BY tipper
, tippee
, mtime DESC;