pg_ivm/pg_ivm--1.0.sql
Jason Petersen fe6a09e5f7 WIP: Allow partitioned tables in IMMVs
This isn't feature-complete yet, but opening as a place to start a con-
versation around how to fully implement this feature.

At the moment, the prohibition on partitioned tables is removed, and
hooks are added to handle ATTACH PARTITION and DETACH PARTITION.

To do:

  * Add check to prohibit multiple partitioned tables (causes crash)
  * Change ATTACH/DETACH to be incremental (presently does a REFRESH)
  * Figure out issue with multiple tables and correct it
2024-09-26 10:22:45 -06:00

110 lines
2.6 KiB
PL/PgSQL

-- catalog
CREATE SCHEMA __pg_ivm__;
CREATE TABLE __pg_ivm__.pg_ivm_immv(
immvrelid regclass NOT NULL,
viewdef text NOT NULL,
CONSTRAINT pg_ivm_immv_pkey PRIMARY KEY (immvrelid)
);
ALTER TABLE __pg_ivm__.pg_ivm_immv SET SCHEMA pg_catalog;
--CREATE UNIQUE INDEX ON pg_catalog.pg_ivm_immv USING btree (immvrelid);
SELECT pg_catalog.pg_extension_config_dump('pg_catalog.pg_ivm_immv', '');
-- functions
CREATE FUNCTION changes_partitions(pg_ddl_command)
RETURNS boolean
IMMUTABLE
STRICT
AS 'MODULE_PATHNAME', 'changes_partitions'
LANGUAGE C;
-- CREATE FUNCTION get_command_type(text, text, pg_ddl_command, text)
-- RETURNS void
-- IMMUTABLE
-- STRICT
-- AS 'MODULE_PATHNAME', 'get_command_type'
-- LANGUAGE C;
CREATE FUNCTION create_immv(text, text)
RETURNS bigint
STRICT
AS 'MODULE_PATHNAME', 'create_immv'
LANGUAGE C;
-- trigger functions
CREATE FUNCTION "IVM_immediate_before"()
RETURNS trigger
AS 'MODULE_PATHNAME', 'IVM_immediate_before'
LANGUAGE C;
CREATE FUNCTION "IVM_immediate_maintenance"()
RETURNS trigger
AS 'MODULE_PATHNAME', 'IVM_immediate_maintenance'
LANGUAGE C;
CREATE FUNCTION "IVM_prevent_immv_change"()
RETURNS trigger
AS 'MODULE_PATHNAME', 'IVM_prevent_immv_change'
LANGUAGE C;
/*
* DDL trigger that removes entry from pg_ivm_immv
*/
CREATE FUNCTION pg_ivm_sql_drop_trigger_func()
RETURNS event_trigger AS $$
DECLARE
pg_class_oid OID;
relids REGCLASS[];
BEGIN
pg_class_oid = 'pg_catalog.pg_class'::regclass;
/* Find relids to remove */
DELETE FROM pg_catalog.pg_ivm_immv
USING pg_catalog.pg_event_trigger_dropped_objects() AS events
WHERE immvrelid = events.objid AND
events.classid = pg_class_oid AND events.objsubid = 0;
END
$$ LANGUAGE plpgsql;
CREATE EVENT TRIGGER pg_ivm_sql_drop_trigger
ON sql_drop
EXECUTE PROCEDURE pg_catalog.pg_ivm_sql_drop_trigger_func();
-- Process ALTER TABLE, specifically ATTACH/DETACH PARTITION
-- TODO: Get incremental update working
CREATE OR REPLACE FUNCTION ivm_immediate_event()
RETURNS event_trigger
LANGUAGE plpgsql
AS $function$
DECLARE
r record;
BEGIN
FOR r IN SELECT * FROM pg_event_trigger_ddl_commands()
LOOP
IF changes_partitions(r.command) THEN
PERFORM refresh_immv(
convert_from(
substring(tgargs FOR (position('\x00'::bytea in tgargs)-1)),
'SQL_ASCII'
)::oid::regclass::text,
true)
FROM pg_trigger
WHERE tgfoid='"IVM_immediate_maintenance"'::regproc AND tgtype=4;
END IF;
END LOOP;
END;
$function$;
-- Run on any ALTER TABLE
CREATE EVENT TRIGGER IVM_trigger_event
ON ddl_command_end WHEN TAG IN ('ALTER TABLE')
EXECUTE PROCEDURE ivm_immediate_event();