/** 
 * <feature scope="SanteDB.Persistence.Data.ADO" id="20171030-01" name="Update:20171030-01" applyRange="0.2.0.7-1.1.0.0"  invariantName="npgsql">
 *	<summary>Update: Adds the SQUASH_DB() command to database</summary>
 *	<remarks></remarks>
 *	<isInstalled>select ck_patch('20171030-01')</isInstalled>
 * </feature>
 */
BEGIN TRANSACTION;

CREATE OR REPLACE FUNCTION squash_db() RETURNS VOID AS $$
DECLARE 
	DBS NUMERIC;
BEGIN

	RAISE INFO '  O O   \ /';
	RAISE INFO '   X     X ';
	RAISE INFO '  / \   O O';
	RAISE INFO 'PRUNING DATABASE STARTED - THIS WILL REMOVE ALL OBSOLETE DATA FROM DATABASE';
	RAISE INFO 'DEPENDING ON THE SIZE OF YOUR DATASET THIS MAY TAKE UP TO 30 MINUTES';
	select pg_database_size(current_database()) INTO DBS;
	RAISE INFO 'CURRENT DB SIZE: %', pg_size_pretty(DBS);

	RAISE INFO 'PRUNING % ADDRESSES', (SELECT COUNT(*) FROM ENT_ADDR_TBL WHERE OBSLT_VRSN_SEQ_ID IS NOT NULL);
	DELETE FROM ENT_ADDR_CMP_TBL WHERE ADDR_ID IN (SELECT ADDR_ID FROM ENT_ADDR_TBL WHERE OBSLT_VRSN_SEQ_ID IS NOT NULL);
	DELETE FROM ENT_ADDR_TBL WHERE OBSLT_VRSN_SEQ_ID IS NOT NULL;

	-- NO CURRENT VERSIONS EXIST?
	DELETE FROM ENT_ADDR_CMP_TBL WHERE ADDR_ID IN (SELECT ADDR_ID FROM ENT_ADDR_TBL WHERE NOT EXISTS(SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_ADDR_TBL.ENT_ID) AND OBSLT_VRSN_SEQ_ID IS NULL);
	DELETE FROM ENT_ADDR_TBL WHERE NOT EXISTS(SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_ADDR_TBL.ENT_ID) AND OBSLT_VRSN_SEQ_ID IS NULL;
	RAISE INFO 'REDIRECTING ADDRESSES';
	UPDATE ENT_ADDR_TBL SET EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_ADDR_TBL.ENT_ID LIMIT 1) WHERE EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);

	RAISE INFO 'PRUNING % NAMES', (SELECT COUNT(*) FROM ENT_NAME_TBL WHERE OBSLT_VRSN_SEQ_ID  IS NOT NULL);
	DELETE FROM ENT_NAME_CMP_TBL WHERE NAME_ID IN (SELECT NAME_ID FROM ENT_NAME_TBL WHERE OBSLT_VRSN_SEQ_ID  IS NOT NULL);
	DELETE FROM ENT_NAME_TBL WHERE OBSLT_VRSN_SEQ_ID  IS NOT NULL;
	-- NO CURRENT VERSIONS EXIST?
	DELETE FROM ENT_NAME_CMP_TBL WHERE NAME_ID IN (SELECT NAME_ID FROM ENT_NAME_TBL WHERE NOT EXISTS(SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_NAME_TBL.ENT_ID) AND OBSLT_VRSN_SEQ_ID IS NULL);
	DELETE FROM ENT_NAME_TBL WHERE NOT EXISTS(SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_NAME_TBL.ENT_ID) AND OBSLT_VRSN_SEQ_ID IS NULL;
	RAISE INFO 'REDIRECTING NAMES';
	UPDATE ENT_NAME_TBL SET EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_NAME_TBL.ENT_ID LIMIT 1) WHERE EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);

	RAISE INFO 'PRUNING % IDENTIFIERS', (SELECT COUNT(*) FROM ENT_ID_TBL WHERE OBSLT_VRSN_SEQ_ID  IS NOT NULL) +
	 (SELECT COUNT(*) FROM ENT_ID_TBL WHERE NOT EXISTS(SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_ID_TBL.ENT_ID) AND OBSLT_VRSN_SEQ_ID IS NULL) + 
	 (SELECT COUNT(*) FROM ENT_ID_TBL WHERE EXISTS (SELECT * FROM ENT_ID_TBL B WHERE ENT_ID_TBL.EFFT_VRSN_SEQ_ID <> B.EFFT_VRSN_SEQ_ID AND ENT_ID_TBL.ENT_ID = B.ENT_ID AND B.EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = B.ENT_ID LIMIT 1) AND B.AUT_ID = ENT_ID_TBL.AUT_ID AND B.ID_VAL = ENT_ID_TBL.ID_VAL));
	DELETE FROM ENT_ID_TBL WHERE OBSLT_VRSN_SEQ_ID  IS NOT NULL;
	DELETE FROM ENT_ID_TBL WHERE NOT EXISTS(SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_ID_TBL.ENT_ID) AND OBSLT_VRSN_SEQ_ID IS NULL;
	DELETE FROM ENT_ID_TBL WHERE EXISTS (SELECT * FROM ENT_ID_TBL B WHERE ENT_ID_TBL.EFFT_VRSN_SEQ_ID <> B.EFFT_VRSN_SEQ_ID AND ENT_ID_TBL.ENT_ID = B.ENT_ID AND B.EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = B.ENT_ID LIMIT 1) AND B.AUT_ID = ENT_ID_TBL.AUT_ID AND B.ID_VAL = ENT_ID_TBL.ID_VAL);
	RAISE INFO 'REDIRECTING IDENTIFIERS';
	UPDATE ENT_ID_TBL SET EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_ID_TBL.ENT_ID LIMIT 1) WHERE EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);

	RAISE INFO 'PRUNING % TELECOM ADDRESSES', (SELECT COUNT(*) FROM ENT_TEL_TBL WHERE OBSLT_VRSN_SEQ_ID  IS NOT NULL);
	DELETE FROM ENT_TEL_TBL WHERE OBSLT_VRSN_SEQ_ID  IS NOT NULL;
	RAISE INFO 'REDIRECTING TELECOM ADDRESSES';
	UPDATE ENT_TEL_TBL  SET EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_TEL_TBL.ENT_ID LIMIT 1) WHERE EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);

	RAISE INFO 'PRUNING % EXTENSIONS', (SELECT COUNT(*) FROM ENT_EXT_TBL WHERE OBSLT_VRSN_SEQ_ID IS NOT NULL) +
		(SELECT COUNT (*) FROM ENT_EXT_TBL WHERE NOT EXISTS(SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_EXT_TBL.ENT_ID) AND OBSLT_VRSN_SEQ_ID IS NULL)
	;
	DELETE FROM ENT_EXT_TBL WHERE OBSLT_VRSN_SEQ_ID IS NOT NULL;
	DELETE FROM ENT_EXT_TBL WHERE NOT EXISTS(SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_EXT_TBL.ENT_ID) AND OBSLT_VRSN_SEQ_ID IS NULL;
	RAISE INFO 'REDIRECTING EXTENSIONS';
	UPDATE ENT_EXT_TBL SET EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_EXT_TBL.ENT_ID LIMIT 1) WHERE EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);

	RAISE INFO 'PRUNING PATIENTS';
	DELETE FROM PAT_TBL WHERE ENT_VRSN_ID IN (SELECT ENT_VRSN_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC  IS NOT NULL);

	RAISE INFO 'PRUNING PROVIDERS';
	DELETE FROM PVDR_TBL WHERE ENT_VRSN_ID IN (SELECT ENT_VRSN_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC  IS NOT NULL);

	RAISE INFO 'PRUNING USERS';
	DELETE FROM USR_ENT_TBL WHERE ENT_VRSN_ID IN (SELECT ENT_VRSN_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC  IS NOT NULL);

	RAISE INFO 'PRUNING PERSONS';
	DELETE FROM PSN_LNG_TBL WHERE OBSLT_VRSN_SEQ_ID  IS NOT NULL;
	UPDATE PSN_LNG_TBL  SET EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = PSN_LNG_TBL.ENT_ID LIMIT 1) WHERE EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);
	DELETE FROM PSN_TBL WHERE ENT_VRSN_ID IN (SELECT ENT_VRSN_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC  IS NOT NULL);

	RAISE INFO 'PRUNING PLACES';
	DELETE FROM PLC_TBL WHERE ENT_VRSN_ID IN (SELECT ENT_VRSN_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC  IS NOT NULL);

	RAISE INFO 'PRUNING ORGANIZATIONS';
	DELETE FROM ORG_TBL WHERE ENT_VRSN_ID IN (SELECT ENT_VRSN_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC  IS NOT NULL);

	RAISE INFO 'PRUNING MATERIALS';
	DELETE FROM MMAT_TBL WHERE ENT_VRSN_ID IN (SELECT ENT_VRSN_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC  IS NOT NULL);
	DELETE FROM MAT_TBL WHERE ENT_VRSN_ID IN (SELECT ENT_VRSN_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC  IS NOT NULL);

	RAISE INFO 'PRUNING ENTITY RELATIONSHIPS';
	DELETE FROM ENT_REL_TBL WHERE OBSLT_VRSN_SEQ_ID IS NOT NULL;
	RAISE INFO 'REDIRECTING % ENTITY RELATIONSHIPS', (SELECT COUNT(*) FROM ENT_REL_TBL WHERE EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL));
	UPDATE ENT_REL_TBL SET EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ENT_ID = ENT_REL_TBL.SRC_ENT_ID LIMIT 1) WHERE EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);

	RAISE INFO 'DISABLING TRIGGERS';
	ALTER TABLE ENT_ADDR_TBL DISABLE TRIGGER ALL;
	ALTER TABLE ENT_NAME_TBL DISABLE TRIGGER ALL;
	ALTER TABLE ENT_ID_TBL DISABLE TRIGGER ALL;
	ALTER TABLE ENT_TEL_TBL DISABLE TRIGGER ALL;
	ALTER TABLE ENT_EXT_TBL DISABLE TRIGGER ALL;
	ALTER TABLE ENT_REL_TBL DISABLE TRIGGER ALL;
	ALTER TABLE ENT_VRSN_TBL DISABLE TRIGGER ALL;

	-- DELETE FROM ENT VRSN TBL 
	RAISE INFO 'REWRITING ENTITY VERSION TREE';
	UPDATE ENT_VRSN_TBL SET RPLC_VRSN_ID = NULL WHERE OBSLT_UTC IS NULL AND RPLC_VRSN_ID IS NULL;
	RAISE INFO 'PRUNING % ENTITY VERSION TREE ENTRIES', (SELECT COUNT(*) FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);
	DELETE FROM ENT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL ;

	RAISE INFO 'ENABLING TRIGGERS';
	ALTER TABLE ENT_VRSN_TBL ENABLE TRIGGER ALL;
	ALTER TABLE ENT_ADDR_TBL ENABLE TRIGGER ALL;
	ALTER TABLE ENT_NAME_TBL ENABLE TRIGGER ALL;
	ALTER TABLE ENT_ID_TBL ENABLE TRIGGER ALL;
	ALTER TABLE ENT_TEL_TBL ENABLE TRIGGER ALL;
	ALTER TABLE ENT_REL_TBL ENABLE TRIGGER ALL;
	ALTER TABLE ENT_EXT_TBL ENABLE TRIGGER ALL;

	RAISE INFO 'PRUNING ACT IDENTIFIERS';
	DELETE FROM ACT_ID_TBL WHERE OBSLT_VRSN_SEQ_ID IS NOT NULL;
	RAISE INFO 'REDIRECTING ACT IDENTIFIERS';
	UPDATE ACT_ID_TBL SET EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ACT_ID = ACT_ID_TBL.ACT_ID LIMIT 1) WHERE OBSLT_VRSN_SEQ_ID IS NULL AND EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);

	RAISE INFO 'PRUNING ACT EXTENSIONS';
	DELETE FROM ACT_EXT_TBL WHERE OBSLT_VRSN_SEQ_ID IS NOT NULL;
	RAISE INFO 'REDIRECTING ACT EXTENSIONS';
	UPDATE ACT_EXT_TBL SET EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ACT_ID = ACT_EXT_TBL.ACT_ID LIMIT 1) WHERE OBSLT_VRSN_SEQ_ID IS NULL AND EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);

	RAISE INFO 'PRUNING OBSERVATIONS';
	DELETE FROM QTY_OBS_TBL WHERE ACT_VRSN_ID IN (SELECT ACT_VRSN_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);
	DELETE FROM TXT_OBS_TBL WHERE ACT_VRSN_ID IN (SELECT ACT_VRSN_ID FROM ACT_VRSN_TBL WHERE  OBSLT_UTC IS NOT NULL );
	DELETE FROM CD_OBS_TBL WHERE ACT_VRSN_ID IN (SELECT ACT_VRSN_ID FROM ACT_VRSN_TBL WHERE  OBSLT_UTC IS NOT NULL );
	DELETE FROM OBS_TBL WHERE ACT_VRSN_ID IN (SELECT ACT_VRSN_ID FROM ACT_VRSN_TBL WHERE  OBSLT_UTC IS NOT NULL );

	RAISE INFO 'PRUNING SUBSTANCE ADMINISTRATIONS';
	DELETE FROM SUB_ADM_TBL WHERE ACT_VRSN_ID IN (SELECT ACT_VRSN_ID FROM ACT_VRSN_TBL WHERE  OBSLT_UTC IS NOT NULL );

	RAISE INFO 'PRUNING ENCOUNTERS';
	DELETE FROM PAT_ENC_TBL WHERE ACT_VRSN_ID IN (SELECT ACT_VRSN_ID FROM ACT_VRSN_TBL WHERE  OBSLT_UTC IS NOT NULL);

	RAISE INFO 'PRUNING PROCEDURES';
	DELETE FROM PROC_TBL WHERE ACT_VRSN_ID IN (SELECT ACT_VRSN_ID FROM ACT_VRSN_TBL WHERE  OBSLT_UTC IS NOT NULL );

	ALTER TABLE ACT_REL_TBL DISABLE TRIGGER ALL;
	ALTER TABLE ACT_PTCPT_TBL DISABLE TRIGGER ALL;
	ALTER TABLE ACT_VRSN_TBL DISABLE TRIGGER ALL;

	RAISE INFO 'PRUNING ACT RELATIONSHIPS';
	DELETE FROM ACT_REL_TBL WHERE OBSLT_VRSN_SEQ_ID IS NOT NULL;
	RAISE INFO 'REDIRECTING % ACT RELATIONSHIPS', (SELECT COUNT(*) FROM ACT_REL_TBL WHERE EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL));
	UPDATE ACT_REL_TBL SET EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ACT_ID = ACT_REL_TBL.SRC_ACT_ID LIMIT 1) WHERE EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);

	RAISE INFO 'PRUNING ACT PARTICIPATIONS';
	DELETE FROM ACT_PTCPT_TBL WHERE OBSLT_VRSN_SEQ_ID IS NOT NULL;
	RAISE INFO 'REDIRECTING % ACT PARTICIPATIONS', (SELECT COUNT(*) FROM ACT_PTCPT_TBL WHERE EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL));
	UPDATE ACT_PTCPT_TBL SET EFFT_VRSN_SEQ_ID = (SELECT VRSN_SEQ_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NULL AND ACT_ID = ACT_PTCPT_TBL.ACT_ID LIMIT 1) WHERE EFFT_VRSN_SEQ_ID IN (SELECT VRSN_SEQ_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL);

	RAISE INFO 'REWRITING ACT VERSION TREE';
	UPDATE ACT_VRSN_TBL SET RPLC_VRSN_ID = NULL WHERE OBSLT_UTC IS NULL AND RPLC_VRSN_ID IS NULL;
	RAISE INFO 'PRUNING % ACT VERSION TREE ENTRIES', (SELECT COUNT(*) FROM ACT_VRSN_TBL WHERE ACT_VRSN_ID IN (SELECT ACT_VRSN_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL ));
	DELETE FROM ACT_VRSN_TBL WHERE ACT_VRSN_ID IN (SELECT ACT_VRSN_ID FROM ACT_VRSN_TBL WHERE OBSLT_UTC IS NOT NULL );

	ALTER TABLE ACT_REL_TBL ENABLE TRIGGER ALL;
	ALTER TABLE ACT_PTCPT_TBL ENABLE TRIGGER ALL;
	ALTER TABLE ACT_VRSN_TBL ENABLE TRIGGER ALL;

	RAISE INFO 'PRUNING COMPLETED';
	select pg_database_size(current_database()) INTO DBS;
	RAISE INFO 'DB SIZE: % (RUNNING VACUUM FULL IS RECOMMENDED)', pg_size_pretty(DBS);

END;
$$ LANGUAGE plpgsql;

 -- GET THE SCHEMA VERSION
CREATE OR REPLACE FUNCTION GET_SCH_VRSN() RETURNS VARCHAR(10) AS
$$
BEGIN
	RETURN '1.1.0.0';
END;
$$ LANGUAGE plpgsql;

SELECT REG_PATCH('20171030-01');

COMMIT;