BEGIN;

-- This script upgrades a pre PiAnoS 4.0 rc15 instance to 4.0-rc16+
-- You will need to run `dbadmin.py resolve` to indicate that the schema is in sync
-- ** DO NOT TRY TO `sync` SINCE IT IS BROKEN AND IS LIKELY TO SCREW THE DB. USE THIS SCRIPT AND RUN `resolve` AFTERWARDS **

-- microdb schema
ALTER TABLE microdb_schema ADD COLUMN json text;

-- Personal Folders
ALTER TABLE folder ADD COLUMN personalof int;
ALTER TABLE folder ADD FOREIGN KEY (personalof) REFERENCES person(id);
DROP VIEW resultvex;
CREATE VIEW resultvex AS (SELECT result.assignment, 
	result.type AS typeid, 
	resulttype.name AS type, 
	result.step AS stepid, 
	resultstep.name AS step, 
	result.updatedon,
	obs_concl.value AS conclusion,
	obs_mark.value AS mark_value,
	obs_decision.value AS decision,
	obs_decision_ex.value AS decision_ex
FROM resulttype,resultstep,result 
	LEFT OUTER JOIN observation AS obs_concl ON obs_concl.assignment = result.assignment 
		AND obs_concl.restype = result.type 
		AND obs_concl.resstep = result.step 
		AND obs_concl.type = (SELECT id FROM observationtype WHERE name = 'conclusion') 
	LEFT OUTER JOIN observation AS obs_mark ON obs_mark.assignment = result.assignment 
		AND obs_mark.restype = result.type 
		AND obs_mark.resstep = result.step 
		AND obs_mark.type = (SELECT id FROM observationtype WHERE name = 'mark-value') 
	LEFT OUTER JOIN observation AS obs_decision ON obs_decision.assignment = result.assignment 
		AND obs_decision.restype = result.type 
		AND obs_decision.resstep = result.step 
		AND obs_decision.type = (SELECT id FROM observationtype WHERE name = 'comparison-decision') 
	LEFT OUTER JOIN observation AS obs_decision_ex ON obs_decision_ex.assignment = result.assignment 
		AND obs_decision_ex.restype = result.type 
		AND obs_decision_ex.resstep = result.step 
		AND obs_decision_ex.type = (SELECT id FROM observationtype WHERE name = 'comparison-decision-ex') 
WHERE result.type = resulttype.id 
	AND result.step = resultstep.id
);

-- Full-text search
-- First we need to add the relevant columns to all indexed tables
-- then add the function and trigger
-- then (no-op) update the table to trigger the population of the column
-- then set not null
-- Finally we'll be able to build the master search view

-- Folder
ALTER TABLE folder ADD COLUMN fts tsvector;
CREATE OR REPLACE FUNCTION folder_tsvector_update_func() RETURNS trigger AS $$
BEGIN
	NEW.fts := setweight(to_tsvector(coalesce(NEW.name,'')), 'B');
	RETURN NEW;
END
$$ LANGUAGE plpgsql;					
CREATE TRIGGER folder_tsvector_update_trigger
	BEFORE INSERT OR UPDATE ON folder
	FOR EACH ROW EXECUTE PROCEDURE folder_tsvector_update_func();
UPDATE folder SET name=name;
ALTER TABLE folder ALTER COLUMN fts SET NOT NULL;

-- Exercise
ALTER TABLE exercise ADD COLUMN fts tsvector;
CREATE OR REPLACE FUNCTION exercise_tsvector_update_func() RETURNS trigger AS $$
BEGIN
	NEW.fts := setweight(to_tsvector(coalesce(NEW.name,'')), 'B') || setweight(to_tsvector(coalesce(NEW.description,'')), 'C');
	RETURN NEW;
END
$$ LANGUAGE plpgsql;					
CREATE TRIGGER exercise_tsvector_update_trigger
	BEFORE INSERT OR UPDATE ON exercise
	FOR EACH ROW EXECUTE PROCEDURE exercise_tsvector_update_func();
UPDATE exercise SET name=name;
ALTER TABLE exercise ALTER COLUMN fts SET NOT NULL;

-- Person
ALTER TABLE person ADD COLUMN fts tsvector;
CREATE OR REPLACE FUNCTION person_tsvector_update_func() RETURNS trigger AS $$
BEGIN
	NEW.fts := setweight(to_tsvector(coalesce(NEW.name,'')), 'A') || setweight(to_tsvector(coalesce(NEW.username,'')), 'B') || setweight(to_tsvector(coalesce(NEW.email,'')), 'B');
	RETURN NEW;
END
$$ LANGUAGE plpgsql;					
CREATE TRIGGER person_tsvector_update_trigger
	BEFORE INSERT OR UPDATE ON person
	FOR EACH ROW EXECUTE PROCEDURE person_tsvector_update_func();
UPDATE person SET name=name;
ALTER TABLE person ALTER COLUMN fts SET NOT NULL;

-- pgroup
ALTER TABLE pgroup ADD COLUMN fts tsvector;
CREATE OR REPLACE FUNCTION pgroup_tsvector_update_func() RETURNS trigger AS $$
BEGIN
	NEW.fts := setweight(to_tsvector(coalesce(NEW.name,'')), 'B');
	RETURN NEW;
END
$$ LANGUAGE plpgsql;					
CREATE TRIGGER pgroup_tsvector_update_trigger
	BEFORE INSERT OR UPDATE ON pgroup
	FOR EACH ROW EXECUTE PROCEDURE pgroup_tsvector_update_func();
UPDATE pgroup SET name=name;
ALTER TABLE pgroup ALTER COLUMN fts SET NOT NULL;

-- Image
ALTER TABLE image ADD COLUMN fts tsvector;
CREATE OR REPLACE FUNCTION image_tsvector_update_func() RETURNS trigger AS $$
BEGIN
	NEW.fts := setweight(to_tsvector(coalesce(NEW.name,'')), 'B') || setweight(to_tsvector(coalesce(NEW.info,'')), 'B');
	RETURN NEW;
END
$$ LANGUAGE plpgsql;					
CREATE TRIGGER image_tsvector_update_trigger
	BEFORE INSERT OR UPDATE ON image
	FOR EACH ROW EXECUTE PROCEDURE image_tsvector_update_func();
UPDATE image SET name=name;
ALTER TABLE image ALTER COLUMN fts SET NOT NULL;

-- ftsv master view
CREATE VIEW ftsv AS (
SELECT 'person' AS type, person.id, person.name, CASE person.active WHEN true THEN 'Active' WHEN false THEN 'Inactive' END || ', In group(s): '||array_to_string(array_agg(pgroup.name), ',') AS desc, person.fts 
FROM person,membership,pgroup 
WHERE person.id = membership.person 
	AND membership.pgroup = pgroup.id 
GROUP BY person.id, person.name, person.fts, person.active
UNION 
SELECT 'pgroup' AS type, pgroup.id, pgroup.name, '' AS desc, pgroup.fts
FROM pgroup 
UNION
SELECT 'image' AS type, image.id, image.name, image.info AS desc, image.fts
FROM image
UNION
SELECT 'folder' AS type, folder.id, folder.name, count(exercise.id)::text || ' exercise(s)' AS desc, folder.fts
FROM folder LEFT OUTER JOIN exercise ON exercise.folder = folder.id
GROUP BY folder.id, folder.name, folder.fts
UNION
SELECT 'exercise' AS type, exercise.id, exercise.name, exercise.description AS desc, exercise.fts
FROM exercise
);





