CREATE TABLE person (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    gender TEXT CHECK (gender IN ('male', 'female', 'other')),
    birth DATE,
    death DATE
);

CREATE TABLE holds (
    id INTEGER REFERENCES person(id),
    position TEXT NOT NULL,
    country CHAR(2) NOT NULL,
    start DATE NOT NULL,
    until DATE,
    PRIMARY KEY(id,position,start)
);

CREATE TABLE party (
    id INTEGER,
    party TEXT NOT NULL,
    PRIMARY KEY(id,party)
);

\copy person FROM 'FR_person.csv' WITH CSV HEADER;
\copy holds FROM 'FR_position.csv' WITH CSV HEADER;
\copy party FROM 'FR_party.csv' WITH CSV HEADER;
\copy person FROM 'SG_person.csv' WITH CSV HEADER;
\copy holds FROM 'SG_position.csv' WITH CSV HEADER;
\copy party FROM 'SG_party.csv' WITH CSV HEADER;

ALTER TABLE person ADD COLUMN validity tstzmultirange;
ALTER TABLE holds ADD COLUMN validity tstzmultirange;

UPDATE person SET validity=tstzmultirange(tstzrange(birth,death));
UPDATE holds SET validity=tstzmultirange(tstzrange(start,until));

ALTER TABLE holds DROP COLUMN start;
ALTER TABLE holds DROP COLUMN until;

CREATE EXTENSION provsql CASCADE;
SET provsql.update_provenance = on;

SELECT provsql.add_provenance('person');
SELECT provsql.add_provenance('holds');

SELECT provsql.create_provenance_mapping_view('person_validity','person','validity');
SELECT provsql.create_provenance_mapping_view('holds_validity','holds','validity');

ALTER VIEW provsql.time_validity_view RENAME TO time_validity_view_update;
CREATE VIEW provsql.time_validity_view AS
  SELECT * FROM provsql.time_validity_view_update
UNION ALL
  SELECT * FROM person_validity
UNION ALL
  SELECT * FROM holds_validity;

SET SEARCH_PATH TO public, provsql;

CREATE VIEW person_position AS
SELECT DISTINCT name, position FROM person JOIN holds ON person.id=holds.id
AND country='FR';

--- EXAMPLE QUERIES ---

-- What were the positions of François Bayrou over time?
SELECT position, union_tstzintervals(provenance(),'time_validity_view') valid
FROM person JOIN holds ON person.id=holds.id
WHERE name='François Bayrou' order by valid;

-- What were the ministers during Emmanuel Macron's presidential terms?
SELECT name, validity FROM
  timeslice('person_position', '2017-05-16', NOW())
  AS (name TEXT, position TEXT, validity tstzmultirange, provsql uuid)
  ORDER BY validity;

-- Who were the Ministers of Justice over time?
SELECT name, validity FROM
  history('person_position', ARRAY['position'], ARRAY['Minister of Justice'])
  AS (name TEXT, position TEXT, validity tstzmultirange, provsql uuid)
  ORDER BY validity;

-- What was the government like on 19 June 1981?
SELECT name, position FROM timetravel('person_position', '1981-06-19')
  AS tt(name TEXT, position TEXT, validity tstzmultirange, provsql uuid)
ORDER BY position;

-- Fire François Bayrou and replace him with Pierre Senellart
DELETE FROM holds WHERE position='Prime Minister of France' AND id IN
  (SELECT id FROM person WHERE name='François Bayrou');
INSERT INTO person(id, name, gender) VALUES(100000, 'Pierre Senellart', 'male');
INSERT INTO holds(id, position, country) VALUES(100000, 'Prime Minister of France', 'FR');

-- What were the positions of François Bayrou over time, now he has been
-- fired?
SELECT position, union_tstzintervals(provenance(),'time_validity_view') valid
FROM person JOIN holds ON person.id=holds.id
WHERE name='François Bayrou' order by valid;

-- What is the current government composition?
SELECT name, position FROM timetravel('person_position', NOW())
  AS tt(name TEXT, position TEXT, validity tstzmultirange, provsql uuid)
ORDER BY position;

-- Undo the changes: Pierre Senellart is out, François Bayrou is in
SELECT undo(provenance()) FROM update_provenance;

-- What were the positions of François Bayrou over time, now he has been
-- fired and then reinstated?
SELECT position, union_tstzintervals(provenance(),'time_validity_view') valid
FROM person JOIN holds ON person.id=holds.id
WHERE name='François Bayrou' order by valid;

-- What is the current government composition?
SELECT name, position FROM timetravel('person_position', NOW())
  AS tt(name TEXT, position TEXT, validity tstzmultirange, provsql uuid)
ORDER BY position;
