pgmq-migration-0.1.1.0: database/v1.11.0/05_queue_management.sql
------------------------------------------------------------
-- Queue management functions
------------------------------------------------------------
CREATE FUNCTION pgmq.create_non_partitioned(queue_name TEXT)
RETURNS void AS $$
DECLARE
qtable TEXT := pgmq.format_table_name(queue_name, 'q');
qtable_seq TEXT := qtable || '_msg_id_seq';
atable TEXT := pgmq.format_table_name(queue_name, 'a');
BEGIN
PERFORM pgmq.validate_queue_name(queue_name);
PERFORM pgmq.acquire_queue_lock(queue_name);
EXECUTE FORMAT(
$QUERY$
CREATE TABLE IF NOT EXISTS pgmq.%I (
msg_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
read_ct INT DEFAULT 0 NOT NULL,
enqueued_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
last_read_at TIMESTAMP WITH TIME ZONE,
vt TIMESTAMP WITH TIME ZONE NOT NULL,
message JSONB,
headers JSONB
)
$QUERY$,
qtable
);
EXECUTE FORMAT(
$QUERY$
CREATE TABLE IF NOT EXISTS pgmq.%I (
msg_id BIGINT PRIMARY KEY,
read_ct INT DEFAULT 0 NOT NULL,
enqueued_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
last_read_at TIMESTAMP WITH TIME ZONE,
archived_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
vt TIMESTAMP WITH TIME ZONE NOT NULL,
message JSONB,
headers JSONB
);
$QUERY$,
atable
);
EXECUTE FORMAT(
$QUERY$
CREATE INDEX IF NOT EXISTS %I ON pgmq.%I (vt ASC);
$QUERY$,
qtable || '_vt_idx', qtable
);
EXECUTE FORMAT(
$QUERY$
CREATE INDEX IF NOT EXISTS %I ON pgmq.%I (archived_at);
$QUERY$,
'archived_at_idx_' || queue_name, atable
);
EXECUTE FORMAT(
$QUERY$
INSERT INTO pgmq.meta (queue_name, is_partitioned, is_unlogged)
VALUES (%L, false, false)
ON CONFLICT
DO NOTHING;
$QUERY$,
queue_name
);
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION pgmq.create_unlogged(queue_name TEXT)
RETURNS void AS $$
DECLARE
qtable TEXT := pgmq.format_table_name(queue_name, 'q');
qtable_seq TEXT := qtable || '_msg_id_seq';
atable TEXT := pgmq.format_table_name(queue_name, 'a');
BEGIN
PERFORM pgmq.validate_queue_name(queue_name);
PERFORM pgmq.acquire_queue_lock(queue_name);
EXECUTE FORMAT(
$QUERY$
CREATE UNLOGGED TABLE IF NOT EXISTS pgmq.%I (
msg_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
read_ct INT DEFAULT 0 NOT NULL,
enqueued_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
last_read_at TIMESTAMP WITH TIME ZONE,
vt TIMESTAMP WITH TIME ZONE NOT NULL,
message JSONB,
headers JSONB
)
$QUERY$,
qtable
);
EXECUTE FORMAT(
$QUERY$
CREATE TABLE IF NOT EXISTS pgmq.%I (
msg_id BIGINT PRIMARY KEY,
read_ct INT DEFAULT 0 NOT NULL,
enqueued_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
last_read_at TIMESTAMP WITH TIME ZONE,
archived_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL,
vt TIMESTAMP WITH TIME ZONE NOT NULL,
message JSONB,
headers JSONB
);
$QUERY$,
atable
);
EXECUTE FORMAT(
$QUERY$
CREATE INDEX IF NOT EXISTS %I ON pgmq.%I (vt ASC);
$QUERY$,
qtable || '_vt_idx', qtable
);
EXECUTE FORMAT(
$QUERY$
CREATE INDEX IF NOT EXISTS %I ON pgmq.%I (archived_at);
$QUERY$,
'archived_at_idx_' || queue_name, atable
);
EXECUTE FORMAT(
$QUERY$
INSERT INTO pgmq.meta (queue_name, is_partitioned, is_unlogged)
VALUES (%L, false, true)
ON CONFLICT
DO NOTHING;
$QUERY$,
queue_name
);
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION pgmq.create(queue_name TEXT)
RETURNS void AS $$
BEGIN
PERFORM pgmq.create_non_partitioned(queue_name);
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION pgmq.drop_queue(queue_name TEXT, partitioned BOOLEAN)
RETURNS BOOLEAN AS $$
DECLARE
qtable TEXT := pgmq.format_table_name(queue_name, 'q');
fq_qtable TEXT := 'pgmq.' || qtable;
atable TEXT := pgmq.format_table_name(queue_name, 'a');
fq_atable TEXT := 'pgmq.' || atable;
BEGIN
RAISE WARNING 'drop_queue(queue_name, partitioned) is deprecated and will be removed in PGMQ v2.0. Use drop_queue(queue_name) instead';
PERFORM pgmq.drop_queue(queue_name);
RETURN TRUE;
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION pgmq.drop_queue(queue_name TEXT)
RETURNS BOOLEAN AS $$
DECLARE
qtable TEXT := pgmq.format_table_name(queue_name, 'q');
qtable_seq TEXT := qtable || '_msg_id_seq';
fq_qtable TEXT := 'pgmq.' || qtable;
atable TEXT := pgmq.format_table_name(queue_name, 'a');
fq_atable TEXT := 'pgmq.' || atable;
partitioned BOOLEAN;
BEGIN
PERFORM pgmq.acquire_queue_lock(queue_name);
EXECUTE FORMAT(
$QUERY$
SELECT is_partitioned FROM pgmq.meta WHERE queue_name = %L
$QUERY$,
queue_name
) INTO partitioned;
-- check if the queue exists
IF NOT EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_name = qtable and table_schema = 'pgmq'
) THEN
RAISE NOTICE 'pgmq queue `%` does not exist', queue_name;
RETURN FALSE;
END IF;
EXECUTE FORMAT(
$QUERY$
DROP TABLE IF EXISTS pgmq.%I
$QUERY$,
qtable
);
EXECUTE FORMAT(
$QUERY$
DROP TABLE IF EXISTS pgmq.%I
$QUERY$,
atable
);
IF EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_name = 'meta' and table_schema = 'pgmq'
) THEN
EXECUTE FORMAT(
$QUERY$
DELETE FROM pgmq.meta WHERE queue_name = %L
$QUERY$,
queue_name
);
END IF;
IF partitioned THEN
EXECUTE FORMAT(
$QUERY$
DELETE FROM %I.part_config where parent_table in (%L, %L)
$QUERY$,
pgmq._get_pg_partman_schema(), fq_qtable, fq_atable
);
END IF;
RETURN TRUE;
END;
$$ LANGUAGE plpgsql;
-- list queues
CREATE FUNCTION pgmq."list_queues"()
RETURNS SETOF pgmq.queue_record AS $$
BEGIN
RETURN QUERY SELECT * FROM pgmq.meta;
END
$$ LANGUAGE plpgsql;
-- purge queue, deleting all entries in it.
CREATE OR REPLACE FUNCTION pgmq."purge_queue"(queue_name TEXT)
RETURNS BIGINT AS $$
DECLARE
deleted_count INTEGER;
qtable TEXT := pgmq.format_table_name(queue_name, 'q');
BEGIN
-- Get the row count before truncating
EXECUTE format('SELECT count(*) FROM pgmq.%I', qtable) INTO deleted_count;
-- Use TRUNCATE for better performance on large tables
EXECUTE format('TRUNCATE TABLE pgmq.%I', qtable);
-- Return the number of purged rows
RETURN deleted_count;
END
$$ LANGUAGE plpgsql;
-- unassign archive, so it can be kept when a queue is deleted
CREATE FUNCTION pgmq."detach_archive"(queue_name TEXT)
RETURNS VOID AS $$
DECLARE
atable TEXT := pgmq.format_table_name(queue_name, 'a');
BEGIN
RAISE WARNING 'detach_archive(queue_name) is deprecated and is a no-op. It will be removed in PGMQ v2.0. Archive tables are no longer member objects.';
END
$$ LANGUAGE plpgsql;