-- This file contains triggers that act on the main 'hypertable' table as
-- well as triggers for newly created hypertables.

-- Trigger to prevent unsupported operations on the main table.
-- Our C code should rewrite a DELETE or UPDATE to apply to the replica and not main table.
-- The only exception is if we use ONLY, which should be an error.
CREATE OR REPLACE FUNCTION _iobeamdb_internal.on_unsupported_main_table()
    RETURNS TRIGGER LANGUAGE PLPGSQL AS
$BODY$
BEGIN
    IF TG_OP = 'UPDATE' THEN
        RAISE EXCEPTION 'UPDATE ONLY not supported on hypertables'
        USING ERRCODE = 'IO101';
    ELSIF TG_OP = 'DELETE' AND current_setting('io.ignore_delete_in_trigger', true) IS DISTINCT FROM 'true' THEN
        RAISE EXCEPTION 'DELETE ONLY not currently supported on hypertables'
        USING ERRCODE = 'IO101';
    END IF;
    RETURN NEW;
END
$BODY$;

--Trigger for when stuff is inserted into main table (error because everything should go through a temp table)
CREATE OR REPLACE FUNCTION _iobeamdb_internal.on_modify_main_table()
    RETURNS TRIGGER LANGUAGE PLPGSQL AS
$BODY$
BEGIN 
    RAISE EXCEPTION 'Should never be inserting data directly into main table'
    USING ERRCODE = 'IO501';
END
$BODY$;

-- Trigger for handling the addition of new hypertables.
CREATE OR REPLACE FUNCTION _iobeamdb_internal.on_change_hypertable()
    RETURNS TRIGGER LANGUAGE PLPGSQL AS
$BODY$
DECLARE
    remote_node _iobeamdb_catalog.node;
BEGIN

    IF TG_OP = 'INSERT' THEN

        EXECUTE format(
            $$
                CREATE SCHEMA IF NOT EXISTS %I
            $$, NEW.associated_schema_name);

        PERFORM _iobeamdb_internal.create_table(NEW.root_schema_name, NEW.root_table_name);

        IF NEW.created_on <> current_database() THEN
           PERFORM _iobeamdb_internal.create_schema(NEW.schema_name);
           PERFORM _iobeamdb_internal.create_table(NEW.schema_name, NEW.table_name);
        END IF;

        -- UPDATE not supported, so do them before action
        EXECUTE format(
            $$
                CREATE TRIGGER modify_trigger BEFORE UPDATE OR DELETE ON %I.%I
                FOR EACH STATEMENT EXECUTE PROCEDURE _iobeamdb_internal.on_unsupported_main_table();
            $$, NEW.schema_name, NEW.table_name);
        EXECUTE format(
            $$
                CREATE TRIGGER insert_trigger AFTER INSERT ON %I.%I
                FOR EACH STATEMENT EXECUTE PROCEDURE _iobeamdb_internal.on_modify_main_table();
            $$, NEW.schema_name, NEW.table_name);
        RETURN NEW;
    END IF;

    PERFORM _iobeamdb_internal.on_trigger_error(TG_OP, TG_TABLE_SCHEMA, TG_TABLE_NAME);
END
$BODY$
SET client_min_messages = WARNING; --suppress NOTICE on IF EXISTS schema


/*
    Drops public hypertable when hypertable rows deleted (row created in deleted_hypertable table).
*/
CREATE OR REPLACE FUNCTION _iobeamdb_internal.on_change_deleted_hypertable()
    RETURNS TRIGGER LANGUAGE PLPGSQL AS
$BODY$
DECLARE
    hypertable_row _iobeamdb_catalog.hypertable;
BEGIN
    IF TG_OP <> 'INSERT' THEN
        PERFORM _iobeamdb_internal.on_trigger_error(TG_OP, TG_TABLE_SCHEMA, TG_TABLE_NAME);
    END IF;
    --drop index on all chunks

    PERFORM _iobeamdb_internal.drop_root_table(NEW.root_schema_name, NEW.root_table_name);

    IF new.deleted_on <> current_database() THEN
      PERFORM set_config('io.ignore_ddl_in_trigger', 'true', true);
      EXECUTE format('DROP TABLE %I.%I', NEW.schema_name, NEW.table_name);
    END IF;

    RETURN NEW;
END
$BODY$
;
