-- 035-events-hash-partitions.sql
-- Создание hash-партиций и дочерних индексов для core.events

DO $$
    DECLARE
        n int := 16;  -- число партиций по модулю
        i int;
        part_name text;
        idx1_name text; -- (event_type)
        idx2_name text; -- (event_type, msg_index)
    BEGIN
        -- 1) создать недостающие партиции: events_h00 .. events_h15
        FOR i IN 0..n-1 LOOP
                part_name := 'events_h' || to_char(i, 'FM00');  -- строго без пробелов и с ведущим нулём

                -- если партиции с таким именем нет — создаём
                IF NOT EXISTS (
                    SELECT 1
                    FROM pg_class c
                             JOIN pg_namespace ns ON ns.oid = c.relnamespace
                    WHERE ns.nspname = 'core' AND c.relname = part_name
                ) THEN
                    EXECUTE format(
                            'CREATE TABLE core.%I PARTITION OF core.events FOR VALUES WITH (MODULUS %s, REMAINDER %s);',
                            part_name, n, i
                            );
                END IF;
            END LOOP;

        -- 2) для каждой партиции: создать дочерние индексы и прикрепить к родителям
        FOR i IN 0..n-1 LOOP
                part_name := 'events_h' || to_char(i, 'FM00');

                idx1_name := part_name || '_event_type_idx';
                idx2_name := part_name || '_event_type_msg_index_idx';

                -- создать дочерний индекс (event_type), если нет
                EXECUTE format('CREATE INDEX IF NOT EXISTS %I ON core.%I (event_type);', idx1_name, part_name);

                -- прикрепить его к partitioned-index core.idx_events_type, если ещё не прикреплён
                IF NOT EXISTS (
                    SELECT 1
                    FROM pg_inherits inh
                             JOIN pg_class    c  ON c.oid  = inh.inhrelid
                             JOIN pg_class    p  ON p.oid  = inh.inhparent
                             JOIN pg_namespace nc ON nc.oid = c.relnamespace
                             JOIN pg_namespace np ON np.oid = p.relnamespace
                    WHERE np.nspname='core' AND p.relname='idx_events_type'
                      AND nc.nspname='core' AND c.relname=idx1_name
                ) THEN
                    BEGIN
                        EXECUTE format('ALTER INDEX core.idx_events_type ATTACH PARTITION core.%I;', idx1_name);
                    EXCEPTION WHEN others THEN
                        -- например: "Another index is already attached for partition …" — безопасно игнорируем
                        NULL;
                    END;
                END IF;

                -- создать дочерний индекс (event_type, msg_index), если нет
                EXECUTE format('CREATE INDEX IF NOT EXISTS %I ON core.%I (event_type, msg_index);', idx2_name, part_name);

                -- прикрепить его к partitioned-index core.idx_events_type_msg, если ещё не прикреплён
                IF NOT EXISTS (
                    SELECT 1
                    FROM pg_inherits inh
                             JOIN pg_class    c  ON c.oid  = inh.inhrelid
                             JOIN pg_class    p  ON p.oid  = inh.inhparent
                             JOIN pg_namespace nc ON nc.oid = c.relnamespace
                             JOIN pg_namespace np ON np.oid = p.relnamespace
                    WHERE np.nspname='core' AND p.relname='idx_events_type_msg'
                      AND nc.nspname='core' AND c.relname=idx2_name
                ) THEN
                    BEGIN
                        EXECUTE format('ALTER INDEX core.idx_events_type_msg ATTACH PARTITION core.%I;', idx2_name);
                    EXCEPTION WHEN others THEN
                        NULL;
                    END;
                END IF;

            END LOOP;
    END$$;