Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
max-norin committed Nov 11, 2024
1 parent 944f213 commit 73d4f1d
Show file tree
Hide file tree
Showing 12 changed files with 322 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Install the extension.
```sql
CREATE EXTENSION "pg_full_inherit"
SCHEMA "abstract"
VERSION '1.0';
VERSION '1.1';
```

[Learn more about an extension and control file](https://postgrespro.ru/docs/postgresql/current/extend-extensions)
Expand Down
2 changes: 1 addition & 1 deletion README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ ALTER ROLE "postgres" SET search_path TO "public", "abstract";
```sql
CREATE EXTENSION "pg_full_inherit"
SCHEMA "abstract"
VERSION '1.0';
VERSION '1.1';
```

[Подробнее про расширение и файл control](https://postgrespro.ru/docs/postgresql/current/extend-extensions)
Expand Down
294 changes: 294 additions & 0 deletions dist/pg_full_inherit--1.0--1.1.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
/*
-- =================== GET_TABLE_NAME ===================
*/
CREATE FUNCTION @extschema@.get_table_name ("relid" REGCLASS, "is_full" BOOLEAN = TRUE)
RETURNS TEXT
AS $$
BEGIN
RETURN (
SELECT CASE WHEN "is_full" THEN format('%I.%I', n.nspname, c.relname)
ELSE format('%I', c.relname)
END
FROM pg_class c JOIN pg_namespace n on c.relnamespace = n.oid
WHERE c.oid = "relid");
END
$$
LANGUAGE plpgsql
RETURNS NULL ON NULL INPUT;
/*
=================== NAME ===================
*/
DROP FUNCTION @extschema@.get_child_constraint_name ("name" TEXT, "parent" TEXT, "child" TEXT);

CREATE FUNCTION @extschema@.get_child_constraint_name ("name" TEXT, "parent" REGCLASS, "child" REGCLASS)
RETURNS TEXT
AS $$
BEGIN
RETURN regexp_replace("name", '^' || @extschema@.get_table_name("parent", FALSE), @extschema@.get_table_name("child", FALSE));
END
$$
LANGUAGE plpgsql
IMMUTABLE
RETURNS NULL ON NULL INPUT;

DROP FUNCTION @extschema@.get_child_trigger_name ("name" TEXT, "parent" TEXT, "child" TEXT);

CREATE FUNCTION @extschema@.get_child_trigger_name ("name" TEXT, "parent" REGCLASS, "child" REGCLASS)
RETURNS TEXT
AS $$
BEGIN
RETURN "name";
END
$$
LANGUAGE plpgsql
IMMUTABLE
RETURNS NULL ON NULL INPUT;
/*
=================== DEF ===================
*/
DROP FUNCTION @extschema@.get_child_trigger_def ("parentdef" TEXT, "parentname" TEXT, "parent" TEXT, "child" TEXT);

CREATE FUNCTION @extschema@.get_child_trigger_def ("parentdef" TEXT, "parentname" TEXT, "parent" REGCLASS, "child" REGCLASS)
RETURNS TEXT
AS $$
BEGIN
RETURN regexp_replace (
replace ("parentdef", @extschema@.get_table_name("parent", TRUE), @extschema@.get_table_name("child", TRUE)),
'(CREATE (CONSTRAINT )?TRIGGER) ' || quote_ident ("parentname"),
'\1 ' || quote_ident (@extschema@.get_child_trigger_name("parentname", "parent", "child")));
END
$$
LANGUAGE plpgsql
IMMUTABLE
RETURNS NULL ON NULL INPUT;
/*
=================== GET_INHERIT_TRIGGERS ===================
*/
CREATE OR REPLACE FUNCTION @extschema@.get_inherit_triggers ()
RETURNS TABLE
(
"parentid" OID,
"parentrelid" OID,
"parentname" TEXT,
"parentdef" TEXT,
"childid" OID,
"childrelid" OID,
"childname" TEXT,
"childdef" TEXT,
"is_inherited" BOOL
)
AS $$
BEGIN
RETURN QUERY
WITH "triggers" AS (
SELECT "t"."oid", "t"."tgrelid", "t"."tgname", pg_get_triggerdef("t"."oid") AS "tgdef"
FROM "pg_trigger" "t"
WHERE "t"."tgisinternal" = FALSE)
SELECT "pc"."oid" AS "parentid",
"i"."inhparent" AS "parentrelid",
"pc"."tgname"::TEXT AS "parentname",
"pc"."tgdef" AS "parentdef",
"cc"."oid" AS "childid",
"i"."inhrelid" AS "childrelid",
"cc"."tgname"::TEXT AS "childname",
"cc"."tgdef" AS "childdef",
"cc"."tgdef" IS NOT NULL AS "is_inherited"
FROM "pg_inherits" "i"
LEFT JOIN "triggers" "pc" ON "i"."inhparent" = "pc"."tgrelid"
LEFT JOIN "triggers" "cc" ON "i"."inhrelid" = "cc"."tgrelid"
AND @extschema@.get_child_trigger_def("pc"."tgdef", "pc"."tgname":: TEXT, "i"."inhparent"::REGCLASS, "i"."inhrelid"::REGCLASS) = "cc"."tgdef"
WHERE "pc"."oid" IS NOT NULL OR "cc"."oid" IS NOT NULL;
END
$$
LANGUAGE plpgsql
STABLE
RETURNS NULL ON NULL INPUT;
/*
=================== EVENT_TRIGGER_ADD_INHERIT_CONSTRAINTS ===================
*/
CREATE OR REPLACE FUNCTION @extschema@.event_trigger_add_inherit_constraints ()
RETURNS EVENT_TRIGGER
AS $$
DECLARE
"command" RECORD;
"parent" OID;
"child" OID;
"constraint" RECORD;
"name" TEXT;
"query" TEXT;
"constraints" REFCURSOR;
BEGIN
FOR "command" IN
SELECT * FROM pg_event_trigger_ddl_commands ()
LOOP
IF "command".in_extension = TRUE THEN
CONTINUE;
END IF;

IF "command".command_tag = 'CREATE TABLE' THEN
"child" = "command".objid;
OPEN "constraints" FOR
SELECT * FROM @extschema@.get_inherit_constraints() "c"
WHERE "c"."childrelid" = "child" AND "c"."is_inherited" = FALSE
LIMIT 1;
ELSEIF "command".command_tag = 'ALTER TABLE' THEN
"parent" = "command".objid;
"child" = "command".objid;
OPEN "constraints" FOR
SELECT * FROM @extschema@.get_inherit_constraints() "c"
WHERE ("c"."parentrelid" = "parent" OR "c"."childrelid" = "child")
AND "c"."is_inherited" = FALSE
LIMIT 1;
ELSE
CONTINUE;
END IF;

LOOP
FETCH NEXT FROM "constraints" INTO "constraint";
EXIT WHEN "constraint" IS NULL;

"name" = @extschema@.get_child_constraint_name("constraint"."parentname", "constraint"."parentrelid"::REGCLASS, "constraint"."childrelid"::REGCLASS);
"query" = format('ALTER TABLE %1s ADD CONSTRAINT %2I %3s;', "constraint"."childrelid"::REGCLASS, "name", "constraint"."parentdef");
RAISE NOTICE USING MESSAGE = format('-- ADD CONSTRAINT %1I TO %2s TABLE FROM %3s TABLE', "name", "constraint"."childrelid"::REGCLASS, "constraint"."parentrelid"::REGCLASS);
RAISE NOTICE USING MESSAGE = "query";
EXECUTE "query";
END LOOP;
CLOSE "constraints";
END LOOP;
END;
$$
LANGUAGE plpgsql
VOLATILE;
/*
=================== EVENT_TRIGGER_ADD_INHERIT_TRIGGERS ===================
*/
CREATE OR REPLACE FUNCTION @extschema@.event_trigger_add_inherit_triggers ()
RETURNS EVENT_TRIGGER
AS $$
DECLARE
"command" RECORD;
"triggerid" OID;
"child" OID;
"trigger" RECORD;
"name" TEXT;
"query" TEXT;
"triggers" REFCURSOR;
BEGIN
FOR "command" IN
SELECT * FROM pg_event_trigger_ddl_commands ()
LOOP
IF "command".in_extension = TRUE THEN
CONTINUE;
END IF;

IF "command".command_tag = 'CREATE TABLE' THEN
"child" = "command".objid;
OPEN "triggers" FOR
SELECT * FROM @extschema@.get_inherit_triggers() "t"
WHERE "t"."childrelid" = "child" AND "t"."is_inherited" = FALSE;
ELSEIF "command".command_tag = 'ALTER TABLE' THEN
"child" = "command".objid;
OPEN "triggers" FOR
SELECT * FROM @extschema@.get_inherit_triggers() "t"
WHERE "t"."childrelid" = "child" AND "t"."is_inherited" = FALSE;
ELSEIF "command".command_tag = 'CREATE TRIGGER' THEN
"triggerid" = "command".objid;
OPEN "triggers" FOR
SELECT * FROM @extschema@.get_inherit_triggers() "t"
WHERE "t"."parentid" = "triggerid" AND "t"."is_inherited" = FALSE;
ELSE
CONTINUE;
END IF;

LOOP
FETCH NEXT FROM "triggers" INTO "trigger";
EXIT WHEN "trigger" IS NULL;

"name" = @extschema@.get_child_trigger_name("trigger"."parentname", "trigger"."parentrelid"::REGCLASS, "trigger"."childrelid"::REGCLASS);
"query" = @extschema@.get_child_trigger_def("trigger"."parentdef", "trigger"."parentname", "trigger"."parentrelid"::REGCLASS, "trigger"."childrelid"::REGCLASS);
RAISE NOTICE USING MESSAGE = format('-- ADD TRIGGER %1I TO %2s TABLE FROM %3s TABLE', "name", "trigger"."childrelid"::REGCLASS, "trigger"."parentrelid"::REGCLASS);
RAISE NOTICE USING MESSAGE = "query";
EXECUTE "query";
END LOOP;
CLOSE "triggers";
END LOOP;
END;
$$
LANGUAGE plpgsql
VOLATILE;
/*
=================== EVENT_TRIGGER_DROP_INHERIT_CONSTRAINTS ===================
*/
CREATE OR REPLACE FUNCTION @extschema@.event_trigger_drop_inherit_constraints ()
RETURNS EVENT_TRIGGER
AS $$
DECLARE
"object" RECORD;
"parent" OID;
"child" OID;
"name" TEXT;
"query" TEXT;
"schema" TEXT;
"table" TEXT;
BEGIN
FOR "object" IN
SELECT * FROM pg_event_trigger_dropped_objects()
LOOP
IF "object".object_type = 'table constraint' THEN
"schema" = "object".address_names[1];
"table" = "object".address_names[2];
"parent" = format('%1I.%2I', "schema", "table")::REGCLASS::OID;
"name" = "object".address_names[3];
FOR "child" IN
SELECT inhrelid FROM pg_inherits WHERE inhparent = "parent"
LOOP
"name" = @extschema@.get_child_constraint_name("name", "parent"::REGCLASS, "child"::REGCLASS);
"query" = format('ALTER TABLE %1s DROP CONSTRAINT IF EXISTS %2I;', "child"::REGCLASS, "name");
RAISE NOTICE USING MESSAGE = format('-- DROP CONSTRAINT %1I FROM %2s TABLE BASED ON DEPENDENCY ON %3s TABLE', "name", "child"::REGCLASS, "parent"::REGCLASS);
RAISE NOTICE USING MESSAGE = "query";
EXECUTE "query";
END LOOP;
END IF;
END LOOP;
END;
$$
LANGUAGE plpgsql
VOLATILE;
/*
=================== EVENT_TRIGGER_DROP_INHERIT_TRIGGERS ===================
*/
CREATE OR REPLACE FUNCTION @extschema@.event_trigger_drop_inherit_triggers ()
RETURNS EVENT_TRIGGER
AS $$
DECLARE
"object" RECORD;
"parent" OID;
"child" OID;
"name" TEXT;
"query" TEXT;
"schema" TEXT;
"table" TEXT;
BEGIN
FOR "object" IN
SELECT * FROM pg_event_trigger_dropped_objects()
LOOP
IF "object".object_type = 'trigger' THEN
"schema" = "object".address_names[1];
"table" = "object".address_names[2];
"parent" = format('%1I.%2I', "schema", "table")::REGCLASS::OID;
"name" = "object".address_names[3];
FOR "child" IN
SELECT inhrelid FROM pg_inherits WHERE inhparent = "parent"
LOOP
"name" = @extschema@.get_child_trigger_name("name", "parent"::REGCLASS, "child"::REGCLASS);
"query" = format('DROP TRIGGER IF EXISTS %1I ON %2s;', "name", "child"::REGCLASS);
RAISE NOTICE USING MESSAGE = format('-- DROP TRIGGER %1I FROM %2s TABLE BASED ON DEPENDENCY ON %3s TABLE', "name", "child"::REGCLASS, "parent"::REGCLASS);
RAISE NOTICE USING MESSAGE = "query";
EXECUTE "query";
END LOOP;
END IF;
END LOOP;
END;
$$
LANGUAGE plpgsql
VOLATILE;
2 changes: 1 addition & 1 deletion dist/pg_full_inherit.control
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
comment = 'full inherit'
default_version = '1.0'
default_version = '1.1'
module_pathname = '$libdir/pg_full_inherit'
relocatable = false
2 changes: 1 addition & 1 deletion event-triggers/add_inherit_constraints.sql
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ BEGIN
-- завершить цикл если constraint пустой
EXIT WHEN "constraint" IS NULL;
-- имя для ограничения дочерней таблицы
"name" = public.get_child_constraint_name("constraint"."parentname", "constraint"."parentrelid"::REGCLASS::TEXT, "constraint"."childrelid"::REGCLASS::TEXT);
"name" = public.get_child_constraint_name("constraint"."parentname", "constraint"."parentrelid"::REGCLASS, "constraint"."childrelid"::REGCLASS);
-- запрос на добавление ограничения name в таблицу childrelid
"query" = format('ALTER TABLE %1s ADD CONSTRAINT %2I %3s;', "constraint"."childrelid", "name", "constraint"."parentdef");
RAISE NOTICE USING MESSAGE = format('-- ADD CONSTRAINT %1I TO %2s TABLE FROM %3s TABLE', "name", "constraint"."childrelid", "constraint"."parentrelid");
Expand Down
4 changes: 2 additions & 2 deletions event-triggers/add_inherit_triggers.sql
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ BEGIN
-- завершить цикл если trigger пустой
EXIT WHEN "trigger" IS NULL;
-- имя для триггера дочерней таблицы
"name" = public.get_child_trigger_name("trigger"."parentname", "trigger"."parentrelid"::REGCLASS::TEXT, "trigger"."childrelid"::REGCLASS::TEXT);
"name" = public.get_child_trigger_name("trigger"."parentname", "trigger"."parentrelid"::REGCLASS, "trigger"."childrelid"::REGCLASS);
-- запрос на добавление триггера в таблицу childrelid
"query" = public.get_child_trigger_def("trigger"."parentdef", "trigger"."parentname", "trigger"."parentrelid"::REGCLASS::TEXT, "trigger"."childrelid"::REGCLASS::TEXT);
"query" = public.get_child_trigger_def("trigger"."parentdef", "trigger"."parentname", "trigger"."parentrelid"::REGCLASS, "trigger"."childrelid"::REGCLASS);
RAISE NOTICE USING MESSAGE = format('-- ADD TRIGGER %1I TO %2s TABLE FROM %3s TABLE', "name", "trigger"."childrelid"::REGCLASS, "trigger"."parentrelid"::REGCLASS);
RAISE NOTICE USING MESSAGE = "query";
EXECUTE "query";
Expand Down
2 changes: 1 addition & 1 deletion event-triggers/drop_inherit_constraints.sql
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ BEGIN
SELECT inhrelid FROM pg_inherits WHERE inhparent = "parent"
LOOP
-- имя ограничения дочерней таблице
"name" = public.get_child_constraint_name("name", "parent"::REGCLASS::TEXT, "child"::REGCLASS::TEXT);
"name" = public.get_child_constraint_name("name", "parent"::REGCLASS, "child"::REGCLASS);
-- удаление ограничения name из дочерней таблицы
"query" = format('ALTER TABLE %1s DROP CONSTRAINT IF EXISTS %2I;', "child"::REGCLASS, "name");
RAISE NOTICE USING MESSAGE = format('-- DROP CONSTRAINT %1I FROM %2s TABLE BASED ON DEPENDENCY ON %3s TABLE', "name", "child"::REGCLASS, "parent"::REGCLASS);
Expand Down
2 changes: 1 addition & 1 deletion event-triggers/drop_inherit_triggers.sql
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ BEGIN
SELECT inhrelid FROM pg_inherits WHERE inhparent = "parent"
LOOP
-- имя триггера дочерней таблице
"name" = public.get_child_trigger_name("name", "parent"::REGCLASS::TEXT, "child"::REGCLASS::TEXT);
"name" = public.get_child_trigger_name("name", "parent"::REGCLASS, "child"::REGCLASS);
-- удаление триггер name из дочерней таблицы
"query" = format('DROP TRIGGER IF EXISTS %1I ON %2s;', "name", "child"::REGCLASS);
RAISE NOTICE USING MESSAGE = format('-- DROP TRIGGER %1I FROM %2s TABLE BASED ON DEPENDENCY ON %3s TABLE', "name", "child"::REGCLASS, "parent"::REGCLASS);
Expand Down
4 changes: 2 additions & 2 deletions helpers/def.sql
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
CREATE FUNCTION public.get_child_trigger_def ("parentdef" TEXT, "parentname" TEXT, "parent" TEXT, "child" TEXT)
CREATE FUNCTION public.get_child_trigger_def ("parentdef" TEXT, "parentname" TEXT, "parent" REGCLASS, "child" REGCLASS)
RETURNS TEXT
AS $$
BEGIN
RETURN regexp_replace (
replace ("parentdef", "parent", "child"),
replace ("parentdef", public.get_table_name("parent", TRUE), public.get_table_name("child", TRUE)),
'(CREATE (CONSTRAINT )?TRIGGER) ' || quote_ident ("parentname"),
'\1 ' || quote_ident (public.get_child_trigger_name("parentname", "parent", "child")));
END
Expand Down
2 changes: 1 addition & 1 deletion helpers/get_inherit_triggers.sql
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ BEGIN
FROM "pg_inherits" "i"
LEFT JOIN "triggers" "pc" ON "i"."inhparent" = "pc"."tgrelid"
LEFT JOIN "triggers" "cc" ON "i"."inhrelid" = "cc"."tgrelid"
AND public.get_child_trigger_def("pc"."tgdef", "pc"."tgname":: TEXT, "i"."inhparent"::REGCLASS::TEXT, "i"."inhrelid"::REGCLASS::TEXT) = "cc"."tgdef"
AND public.get_child_trigger_def("pc"."tgdef", "pc"."tgname":: TEXT, "i"."inhparent"::REGCLASS, "i"."inhrelid"::REGCLASS) = "cc"."tgdef"
WHERE "pc"."oid" IS NOT NULL OR "cc"."oid" IS NOT NULL;
END
$$
Expand Down
14 changes: 14 additions & 0 deletions helpers/get_table_name.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CREATE FUNCTION public.get_table_name ("relid" REGCLASS, "is_full" BOOLEAN = TRUE)
RETURNS TEXT
AS $$
BEGIN
RETURN (
SELECT CASE WHEN "is_full" THEN format('%I.%I', n.nspname, c.relname)
ELSE format('%I', c.relname)
END
FROM pg_class c JOIN pg_namespace n on c.relnamespace = n.oid
WHERE c.oid = "relid");
END
$$
LANGUAGE plpgsql
RETURNS NULL ON NULL INPUT;
Loading

0 comments on commit 73d4f1d

Please sign in to comment.