test: migrate tests to master and exclude from releases
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
-- Create additional user for partitioning tasks
|
||||
CREATE USER zbx_part WITH PASSWORD 'zbx_part';
|
||||
GRANT CONNECT ON DATABASE zabbix TO zbx_part;
|
||||
-- Grant usage on public schema (standard for PG 15+)
|
||||
GRANT USAGE ON SCHEMA public TO zbx_part;
|
||||
3359
postgresql/tests/docker/init_scripts/01_00_schema.sql
Normal file
3359
postgresql/tests/docker/init_scripts/01_00_schema.sql
Normal file
File diff suppressed because it is too large
Load Diff
54
postgresql/tests/docker/init_scripts/01_10_schema_create.sql
Normal file
54
postgresql/tests/docker/init_scripts/01_10_schema_create.sql
Normal file
@@ -0,0 +1,54 @@
|
||||
-- ============================================================================
|
||||
-- Creates the 'partitions' schema and configuration table.
|
||||
-- Defines the structure for managing Zabbix partitioning.
|
||||
-- ============================================================================
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS partitions;
|
||||
|
||||
-- Configuration table to store partitioning settings per table
|
||||
CREATE TABLE IF NOT EXISTS partitions.config (
|
||||
table_name text NOT NULL,
|
||||
period text NOT NULL,
|
||||
keep_history interval NOT NULL,
|
||||
future_partitions integer NOT NULL DEFAULT 5,
|
||||
last_updated timestamp WITH TIME ZONE DEFAULT (now() AT TIME ZONE 'UTC'),
|
||||
PRIMARY KEY (table_name)
|
||||
);
|
||||
|
||||
-- Table to track installed version of the partitioning solution
|
||||
CREATE TABLE IF NOT EXISTS partitions.version (
|
||||
version text PRIMARY KEY,
|
||||
installed_at timestamp with time zone DEFAULT (now() AT TIME ZONE 'UTC'),
|
||||
description text
|
||||
);
|
||||
|
||||
INSERT INTO partitions.version (version, description) VALUES ('7-2', 'Added housekeeper task interceptor trigger to drop tasks for partitioned tables')
|
||||
ON CONFLICT (version) DO NOTHING;
|
||||
|
||||
-- Default configuration for Zabbix tables (adjust as needed)
|
||||
-- History tables: Daily partitions, keep 30 days
|
||||
INSERT INTO partitions.config (table_name, period, keep_history) VALUES
|
||||
('history', 'day', '30 days'),
|
||||
('history_uint', 'day', '30 days'),
|
||||
('history_str', 'day', '30 days'),
|
||||
('history_log', 'day', '30 days'),
|
||||
('history_text', 'day', '30 days'),
|
||||
('history_bin', 'day', '30 days')
|
||||
ON CONFLICT (table_name) DO NOTHING;
|
||||
|
||||
-- Zabbix 8.0+ only: Uncomment the following lines if running Zabbix 8.0 or later
|
||||
-- INSERT INTO partitions.config (table_name, period, keep_history) VALUES
|
||||
-- ('history_json', 'day', '30 days')
|
||||
-- ON CONFLICT (table_name) DO NOTHING;
|
||||
|
||||
|
||||
-- Trends tables: Monthly partitions, keep 12 months
|
||||
INSERT INTO partitions.config (table_name, period, keep_history) VALUES
|
||||
('trends', 'month', '12 months'),
|
||||
('trends_uint', 'month', '12 months')
|
||||
ON CONFLICT (table_name) DO NOTHING;
|
||||
|
||||
-- Auditlog: Monthly partitions, keep 12 months
|
||||
INSERT INTO partitions.config (table_name, period, keep_history) VALUES
|
||||
('auditlog', 'month', '12 months')
|
||||
ON CONFLICT (table_name) DO NOTHING;
|
||||
244
postgresql/tests/docker/init_scripts/01_30_maintenance.sql
Normal file
244
postgresql/tests/docker/init_scripts/01_30_maintenance.sql
Normal file
@@ -0,0 +1,244 @@
|
||||
-- ============================================================================
|
||||
-- Core functions for Zabbix partitioning (Create, Drop, Maintain).
|
||||
-- ============================================================================
|
||||
|
||||
-- Function to check if a partition exists in a specific schema
|
||||
CREATE OR REPLACE FUNCTION partitions.partition_exists(p_partition_name text, p_schema text)
|
||||
RETURNS boolean AS $$
|
||||
BEGIN
|
||||
RETURN EXISTS (
|
||||
SELECT 1 FROM pg_class c
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relname = p_partition_name
|
||||
AND n.nspname = p_schema
|
||||
);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- Function to create a partition
|
||||
CREATE OR REPLACE PROCEDURE partitions.create_partition(
|
||||
p_parent_table text,
|
||||
p_start_time timestamp with time zone,
|
||||
p_end_time timestamp with time zone,
|
||||
p_period text
|
||||
) LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
v_partition_name text;
|
||||
v_start_ts bigint;
|
||||
v_end_ts bigint;
|
||||
v_suffix text;
|
||||
v_parent_schema text;
|
||||
BEGIN
|
||||
-- Determine the schema of the parent table
|
||||
SELECT n.nspname INTO v_parent_schema
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relname = p_parent_table AND pg_table_is_visible(c.oid);
|
||||
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION 'Parent table % not found', p_parent_table;
|
||||
END IF;
|
||||
-- (No changes needed for time here as passed params are already UTC-adjusted in caller)
|
||||
v_start_ts := extract(epoch from p_start_time)::bigint;
|
||||
v_end_ts := extract(epoch from p_end_time)::bigint;
|
||||
|
||||
IF p_period = 'month' THEN
|
||||
v_suffix := to_char(p_start_time, 'YYYYMM');
|
||||
ELSIF p_period LIKE '%hour%' THEN
|
||||
v_suffix := to_char(p_start_time, 'YYYYMMDDHH24');
|
||||
ELSE
|
||||
v_suffix := to_char(p_start_time, 'YYYYMMDD');
|
||||
END IF;
|
||||
|
||||
v_partition_name := p_parent_table || '_p' || v_suffix;
|
||||
|
||||
IF NOT partitions.partition_exists(v_partition_name, v_parent_schema) THEN
|
||||
BEGIN
|
||||
EXECUTE format(
|
||||
'CREATE TABLE %I.%I PARTITION OF %I.%I FOR VALUES FROM (%s) TO (%s)',
|
||||
v_parent_schema, v_partition_name, v_parent_schema, p_parent_table, v_start_ts, v_end_ts
|
||||
);
|
||||
EXCEPTION
|
||||
WHEN invalid_object_definition THEN
|
||||
-- Ignore overlap errors (e.g., when transitioning from daily to hourly partitioning)
|
||||
RAISE NOTICE 'Partition % overlaps with an existing partition. Skipping.', v_partition_name;
|
||||
WHEN duplicate_table THEN
|
||||
-- Ignore race condition: another process created the partition concurrently
|
||||
RAISE NOTICE 'Partition % already exists (concurrent creation). Skipping.', v_partition_name;
|
||||
END;
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- Function to drop old partitions
|
||||
CREATE OR REPLACE PROCEDURE partitions.drop_old_partitions(
|
||||
p_parent_table text,
|
||||
p_retention interval,
|
||||
p_period text
|
||||
) LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
v_cutoff_ts bigint;
|
||||
v_partition record;
|
||||
v_partition_date timestamp with time zone;
|
||||
v_suffix text;
|
||||
v_partition_schema text;
|
||||
BEGIN
|
||||
-- Calculate cutoff timestamp
|
||||
v_cutoff_ts := extract(epoch from (now() - p_retention))::bigint;
|
||||
|
||||
FOR v_partition IN
|
||||
SELECT
|
||||
child.relname AS partition_name,
|
||||
n.nspname AS partition_schema
|
||||
FROM pg_inherits
|
||||
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
|
||||
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
|
||||
JOIN pg_namespace n ON child.relnamespace = n.oid
|
||||
WHERE parent.relname = p_parent_table AND pg_table_is_visible(parent.oid)
|
||||
LOOP
|
||||
-- Parse partition suffix to determine age
|
||||
-- Format: parent_pYYYYMM or parent_pYYYYMMDD
|
||||
v_suffix := substring(v_partition.partition_name from length(p_parent_table) + 3);
|
||||
|
||||
BEGIN
|
||||
IF length(v_suffix) = 6 THEN -- YYYYMM
|
||||
v_partition_date := timezone('UTC', to_timestamp(v_suffix || '01', 'YYYYMMDD')::timestamp without time zone);
|
||||
ELSIF length(v_suffix) = 8 THEN -- YYYYMMDD
|
||||
v_partition_date := timezone('UTC', to_timestamp(v_suffix, 'YYYYMMDD')::timestamp without time zone);
|
||||
ELSIF length(v_suffix) = 10 THEN -- YYYYMMDDHH
|
||||
v_partition_date := timezone('UTC', to_timestamp(v_suffix, 'YYYYMMDDHH24')::timestamp without time zone);
|
||||
ELSE
|
||||
CONTINUE; -- Ignore non-matching suffix lengths
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
-- Safely ignore parsing errors for oddly named partitions
|
||||
CONTINUE;
|
||||
END;
|
||||
|
||||
-- Now check retention and execute DROP TABLE (so dropping errors are correctly raised!)
|
||||
IF length(v_suffix) = 6 THEN -- YYYYMM
|
||||
IF extract(epoch from (v_partition_date + '1 month'::interval)) < v_cutoff_ts THEN
|
||||
RAISE NOTICE 'Dropping old partition %', v_partition.partition_name;
|
||||
EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name);
|
||||
COMMIT; -- Release lock immediately
|
||||
END IF;
|
||||
ELSIF length(v_suffix) = 8 THEN -- YYYYMMDD
|
||||
-- If period is weekly, the partition spans an entire week. Otherwise, it spans one day.
|
||||
IF p_period = 'week' THEN
|
||||
IF extract(epoch from (v_partition_date + '1 week'::interval)) < v_cutoff_ts THEN
|
||||
RAISE NOTICE 'Dropping old partition %', v_partition.partition_name;
|
||||
EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name);
|
||||
COMMIT; -- Release lock immediately
|
||||
END IF;
|
||||
ELSE
|
||||
IF extract(epoch from (v_partition_date + '1 day'::interval)) < v_cutoff_ts THEN
|
||||
RAISE NOTICE 'Dropping old partition %', v_partition.partition_name;
|
||||
EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name);
|
||||
COMMIT; -- Release lock immediately
|
||||
END IF;
|
||||
END IF;
|
||||
ELSIF length(v_suffix) = 10 THEN -- YYYYMMDDHH
|
||||
IF extract(epoch from (v_partition_date + p_period::interval)) < v_cutoff_ts THEN
|
||||
RAISE NOTICE 'Dropping old partition %', v_partition.partition_name;
|
||||
EXECUTE format('DROP TABLE %I.%I', v_partition.partition_schema, v_partition.partition_name);
|
||||
COMMIT; -- Release lock immediately
|
||||
END IF;
|
||||
END IF;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- MAIN Procedure to maintain a single table
|
||||
CREATE OR REPLACE PROCEDURE partitions.maintain_table(
|
||||
p_table_name text,
|
||||
p_period text,
|
||||
p_keep_history interval,
|
||||
p_future_partitions integer DEFAULT 5
|
||||
) LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
v_start_time timestamp with time zone;
|
||||
v_period_interval interval;
|
||||
i integer;
|
||||
v_past_iterations integer;
|
||||
BEGIN
|
||||
IF p_period = 'day' THEN
|
||||
v_period_interval := '1 day'::interval;
|
||||
v_start_time := date_trunc('day', now(), 'UTC');
|
||||
-- Calculate how many past days cover the retention period (86400 seconds = 1 day)
|
||||
v_past_iterations := ceil(extract(epoch from p_keep_history) / 86400)::integer;
|
||||
|
||||
ELSIF p_period = 'week' THEN
|
||||
v_period_interval := '1 week'::interval;
|
||||
v_start_time := date_trunc('week', now(), 'UTC');
|
||||
-- 604800 seconds = 1 week
|
||||
v_past_iterations := ceil(extract(epoch from p_keep_history) / 604800)::integer;
|
||||
|
||||
ELSIF p_period = 'month' THEN
|
||||
v_period_interval := '1 month'::interval;
|
||||
v_start_time := date_trunc('month', now(), 'UTC');
|
||||
-- Approximate 30 days per month (2592000 seconds)
|
||||
v_past_iterations := ceil(extract(epoch from p_keep_history) / 2592000)::integer;
|
||||
|
||||
ELSIF p_period LIKE '%hour%' THEN
|
||||
v_period_interval := p_period::interval;
|
||||
v_start_time := to_timestamp(floor(extract(epoch from now()) / extract(epoch from v_period_interval)) * extract(epoch from v_period_interval));
|
||||
v_past_iterations := ceil(extract(epoch from p_keep_history) / extract(epoch from v_period_interval))::integer;
|
||||
|
||||
ELSE
|
||||
RAISE EXCEPTION 'Unsupported partitioning period: %', p_period;
|
||||
END IF;
|
||||
|
||||
-- 1. Create Future Partitions (Current + Buffer)
|
||||
FOR i IN 0..p_future_partitions LOOP
|
||||
CALL partitions.create_partition(
|
||||
p_table_name,
|
||||
v_start_time + (i * v_period_interval),
|
||||
v_start_time + ((i + 1) * v_period_interval),
|
||||
p_period
|
||||
);
|
||||
COMMIT; -- Release lock immediately
|
||||
END LOOP;
|
||||
|
||||
-- 2. Create Past Partitions (Covering retention period)
|
||||
IF v_past_iterations > 0 THEN
|
||||
FOR i IN 1..v_past_iterations LOOP
|
||||
CALL partitions.create_partition(
|
||||
p_table_name,
|
||||
v_start_time - (i * v_period_interval),
|
||||
v_start_time - ((i - 1) * v_period_interval),
|
||||
p_period
|
||||
);
|
||||
COMMIT; -- Release lock immediately
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
-- 3. Drop Old Partitions
|
||||
CALL partitions.drop_old_partitions(p_table_name, p_keep_history, p_period);
|
||||
|
||||
-- 4. Update Metadata
|
||||
UPDATE partitions.config SET last_updated = now() WHERE table_name = p_table_name;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- Global Maintenance Procedure
|
||||
CREATE OR REPLACE PROCEDURE partitions.run_maintenance()
|
||||
LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
v_row record;
|
||||
BEGIN
|
||||
FOR v_row IN SELECT * FROM partitions.config LOOP
|
||||
CALL partitions.maintain_table(v_row.table_name, v_row.period, v_row.keep_history, v_row.future_partitions);
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- Trigger function to silently discard housekeeper tasks for partitioned tables
|
||||
CREATE OR REPLACE FUNCTION partitions.housekeeper_insert_trigger()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM partitions.config WHERE table_name = NEW.tablename) THEN
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
84
postgresql/tests/docker/init_scripts/01_40_enable.sql
Normal file
84
postgresql/tests/docker/init_scripts/01_40_enable.sql
Normal file
@@ -0,0 +1,84 @@
|
||||
-- ============================================================================
|
||||
-- Converts standard Zabbix tables to Partitioned tables.
|
||||
-- WARNING: This renames existing tables to *_old.
|
||||
-- ============================================================================
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
v_row record;
|
||||
v_table text;
|
||||
v_old_table text;
|
||||
v_pk_sql text;
|
||||
v_schema text;
|
||||
BEGIN
|
||||
FOR v_row IN SELECT * FROM partitions.config LOOP
|
||||
v_table := v_row.table_name;
|
||||
v_old_table := v_table || '_old';
|
||||
|
||||
-- Determine schema
|
||||
SELECT n.nspname INTO v_schema
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relname = v_table AND pg_table_is_visible(c.oid);
|
||||
|
||||
|
||||
IF EXISTS (SELECT 1 FROM pg_class WHERE relname = v_table AND relkind = 'r' AND pg_table_is_visible(oid)) THEN
|
||||
RAISE NOTICE 'Converting table % to partitioned table...', v_table;
|
||||
|
||||
-- 1. Rename existing table
|
||||
EXECUTE format('ALTER TABLE %I.%I RENAME TO %I', v_schema, v_table, v_old_table);
|
||||
|
||||
-- 2. Create new partitioned table (handling auditlog PK uniquely)
|
||||
IF v_table = 'auditlog' THEN
|
||||
EXECUTE format('CREATE TABLE %I.%I (LIKE %I.%I INCLUDING DEFAULTS INCLUDING COMMENTS) PARTITION BY RANGE (clock)', v_schema, v_table, v_schema, v_old_table);
|
||||
EXECUTE format('ALTER TABLE %I.%I ADD PRIMARY KEY (auditid, clock)', v_schema, v_table);
|
||||
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_p_1 ON %I.%I (userid, clock)', v_schema, v_table);
|
||||
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_p_2 ON %I.%I (clock)', v_schema, v_table);
|
||||
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_p_3 ON %I.%I (resourcetype, resourceid)', v_schema, v_table);
|
||||
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_p_4 ON %I.%I (recordsetid)', v_schema, v_table);
|
||||
EXECUTE format('CREATE INDEX IF NOT EXISTS auditlog_p_5 ON %I.%I (ip)', v_schema, v_table);
|
||||
ELSE
|
||||
EXECUTE format('CREATE TABLE %I.%I (LIKE %I.%I INCLUDING ALL) PARTITION BY RANGE (clock)', v_schema, v_table, v_schema, v_old_table);
|
||||
END IF;
|
||||
|
||||
-- 3. Create initial partitions
|
||||
RAISE NOTICE 'Creating initial partitions for %...', v_table;
|
||||
CALL partitions.maintain_table(v_table, v_row.period, v_row.keep_history, v_row.future_partitions);
|
||||
|
||||
-- Optional: Migrate existing data
|
||||
-- EXECUTE format('INSERT INTO %I.%I SELECT * FROM %I.%I', v_schema, v_table, v_schema, v_old_table);
|
||||
|
||||
ELSIF EXISTS (SELECT 1 FROM pg_class WHERE relname = v_table AND relkind = 'p' AND pg_table_is_visible(oid)) THEN
|
||||
RAISE NOTICE 'Table % is already partitioned. Skipping conversion.', v_table;
|
||||
-- Just run maintenance for this specific table to ensure partitions exist
|
||||
CALL partitions.maintain_table(v_table, v_row.period, v_row.keep_history, v_row.future_partitions);
|
||||
ELSE
|
||||
RAISE WARNING 'Table % not found!', v_table;
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
-- Attach trigger to housekeeper table to silently discard tasks for partitioned tables.
|
||||
-- Dynamically determine the schema of the housekeeper table to support custom schemas.
|
||||
SELECT n.nspname INTO v_schema
|
||||
FROM pg_class c
|
||||
JOIN pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relname = 'housekeeper' AND pg_table_is_visible(c.oid);
|
||||
|
||||
IF v_schema IS NOT NULL THEN
|
||||
EXECUTE format('DROP TRIGGER IF EXISTS housekeeper_filter ON %I.housekeeper', v_schema);
|
||||
EXECUTE format('CREATE TRIGGER housekeeper_filter BEFORE INSERT ON %I.housekeeper FOR EACH ROW EXECUTE FUNCTION partitions.housekeeper_insert_trigger()', v_schema);
|
||||
RAISE NOTICE 'Housekeeper intercept trigger installed on %.housekeeper', v_schema;
|
||||
ELSE
|
||||
RAISE WARNING 'housekeeper table not found — trigger NOT installed!';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- ==========================================================================
|
||||
-- IMPORTANT: If the Zabbix Server connects with a non-superuser (e.g., 'zabbix'),
|
||||
-- that user MUST have access to the partitions schema for the housekeeper trigger
|
||||
-- to work. Without these GRANTs, every INSERT into housekeeper will FAIL.
|
||||
-- Uncomment and adjust the username below:
|
||||
-- ==========================================================================
|
||||
-- GRANT USAGE ON SCHEMA partitions TO zabbix;
|
||||
-- GRANT SELECT ON partitions.config TO zabbix;
|
||||
|
||||
33
postgresql/tests/docker/init_scripts/01_50_monitoring.sql
Normal file
33
postgresql/tests/docker/init_scripts/01_50_monitoring.sql
Normal file
@@ -0,0 +1,33 @@
|
||||
-- ============================================================================
|
||||
-- Creates a view to monitor partition status and sizes.
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE VIEW partitions.monitoring AS
|
||||
SELECT
|
||||
parent.relname AS parent_table,
|
||||
c.table_name,
|
||||
c.period,
|
||||
c.keep_history,
|
||||
c.future_partitions AS configured_future_partitions,
|
||||
count(child.relname) AS partition_count,
|
||||
count(child.relname) FILTER (
|
||||
WHERE
|
||||
(c.period = 'day' AND child.relname > (parent.relname || '_p' || to_char(now() AT TIME ZONE 'UTC', 'YYYYMMDD')))
|
||||
OR
|
||||
(c.period = 'month' AND child.relname > (parent.relname || '_p' || to_char(now() AT TIME ZONE 'UTC', 'YYYYMM')))
|
||||
OR
|
||||
(c.period = 'week' AND child.relname > (parent.relname || '_p' || to_char(date_trunc('week', now() AT TIME ZONE 'UTC'), 'YYYYMMDD')))
|
||||
OR
|
||||
(c.period LIKE '%hour%' AND child.relname > (parent.relname || '_p' || to_char(now() AT TIME ZONE 'UTC', 'YYYYMMDDHH24')))
|
||||
) AS actual_future_partitions,
|
||||
sum(pg_total_relation_size(child.oid)) AS total_size_bytes,
|
||||
pg_size_pretty(sum(pg_total_relation_size(child.oid))) AS total_size,
|
||||
min(child.relname) AS oldest_partition,
|
||||
max(child.relname) AS newest_partition,
|
||||
c.last_updated
|
||||
FROM partitions.config c
|
||||
JOIN pg_class parent ON parent.relname = c.table_name AND pg_table_is_visible(parent.oid)
|
||||
LEFT JOIN pg_inherits ON pg_inherits.inhparent = parent.oid
|
||||
LEFT JOIN pg_class child ON pg_inherits.inhrelid = child.oid
|
||||
WHERE parent.relkind = 'p' -- Only partitioned tables
|
||||
GROUP BY parent.relname, c.table_name, c.period, c.keep_history, c.future_partitions, c.last_updated;
|
||||
187
postgresql/tests/docker/init_scripts/02_images.sql
Normal file
187
postgresql/tests/docker/init_scripts/02_images.sql
Normal file
File diff suppressed because one or more lines are too long
287733
postgresql/tests/docker/init_scripts/03_data.sql
Normal file
287733
postgresql/tests/docker/init_scripts/03_data.sql
Normal file
File diff suppressed because it is too large
Load Diff
91
postgresql/tests/docker/init_scripts/04_gen_data.sql
Normal file
91
postgresql/tests/docker/init_scripts/04_gen_data.sql
Normal file
@@ -0,0 +1,91 @@
|
||||
-- ============================================================================
|
||||
-- SCRIPT: z_gen_history_data.sql
|
||||
-- DESCRIPTION: Generates mock data for Zabbix history and trends tables.
|
||||
-- Creates a dummy host and items if they don't exist.
|
||||
-- ============================================================================
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
v_hostid bigint := 900001;
|
||||
v_groupid bigint := 900001;
|
||||
v_interfaceid bigint := 900001;
|
||||
v_itemid_start bigint := 900001;
|
||||
v_start_time integer := extract(epoch from (now() - interval '7 days'))::integer;
|
||||
v_end_time integer := extract(epoch from now())::integer;
|
||||
i integer;
|
||||
BEGIN
|
||||
-- 1. CREATE DUMMY STRUCTURES
|
||||
-- Host Group
|
||||
INSERT INTO hstgrp (groupid, name, uuid, type)
|
||||
VALUES (v_groupid, 'Partition Test Group', 'df77189c49034553999973d8e0500001', 0)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Host
|
||||
INSERT INTO hosts (hostid, host, name, status, uuid)
|
||||
VALUES (v_hostid, 'partition-test-host', 'Partition Test Host', 0, 'df77189c49034553999973d8e0500002')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- Interface
|
||||
INSERT INTO interface (interfaceid, hostid, main, type, useip, ip, dns, port)
|
||||
VALUES (v_interfaceid, v_hostid, 1, 1, 1, '127.0.0.1', '', '10050')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- 2. CREATE DUMMY ITEMS AND GENERATE HISTORY
|
||||
|
||||
-- Item 1: Numeric Float (HISTORY)
|
||||
INSERT INTO items (itemid, hostid, interfaceid, name, key_, type, value_type, delay, uuid)
|
||||
VALUES (v_itemid_start + 1, v_hostid, v_interfaceid, 'Test Float Item', 'test.float', 0, 0, '1m', 'df77189c49034553999973d8e0500003');
|
||||
|
||||
INSERT INTO history (itemid, clock, value, ns)
|
||||
SELECT
|
||||
v_itemid_start + 1,
|
||||
ts,
|
||||
random() * 100,
|
||||
0
|
||||
FROM generate_series(v_start_time, v_end_time, 60) AS ts;
|
||||
|
||||
INSERT INTO trends (itemid, clock, num, value_min, value_avg, value_max)
|
||||
SELECT
|
||||
v_itemid_start + 1,
|
||||
(ts / 3600) * 3600, -- Hourly truncation
|
||||
60,
|
||||
0,
|
||||
50,
|
||||
100
|
||||
FROM generate_series(v_start_time, v_end_time, 3600) AS ts;
|
||||
|
||||
-- Item 2: Numeric Unsigned (HISTORY_UINT)
|
||||
INSERT INTO items (itemid, hostid, interfaceid, name, key_, type, value_type, delay, uuid)
|
||||
VALUES (v_itemid_start + 2, v_hostid, v_interfaceid, 'Test Uint Item', 'test.uint', 0, 3, '1m', 'df77189c49034553999973d8e0500004');
|
||||
|
||||
INSERT INTO history_uint (itemid, clock, value, ns)
|
||||
SELECT
|
||||
v_itemid_start + 2,
|
||||
ts,
|
||||
(random() * 1000)::integer,
|
||||
0
|
||||
FROM generate_series(v_start_time, v_end_time, 60) AS ts;
|
||||
|
||||
INSERT INTO trends_uint (itemid, clock, num, value_min, value_avg, value_max)
|
||||
SELECT
|
||||
v_itemid_start + 2,
|
||||
(ts / 3600) * 3600,
|
||||
60,
|
||||
0,
|
||||
500,
|
||||
1000
|
||||
FROM generate_series(v_start_time, v_end_time, 3600) AS ts;
|
||||
|
||||
-- Item 3: Character (HISTORY_STR)
|
||||
INSERT INTO items (itemid, hostid, interfaceid, name, key_, type, value_type, delay, uuid)
|
||||
VALUES (v_itemid_start + 3, v_hostid, v_interfaceid, 'Test Str Item', 'test.str', 0, 1, '1m', 'df77189c49034553999973d8e0500005');
|
||||
|
||||
INSERT INTO history_str (itemid, clock, value, ns)
|
||||
SELECT
|
||||
v_itemid_start + 3,
|
||||
ts,
|
||||
'test_value_' || ts,
|
||||
0
|
||||
FROM generate_series(v_start_time, v_end_time, 300) AS ts; -- Every 5 mins
|
||||
|
||||
END $$;
|
||||
Reference in New Issue
Block a user