diff --git a/.gitignore b/.gitignore index 1873c2c..20c7e6a 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,12 @@ control.mk .deps/ # built targets -# Note: Version-specific files (sql/*--*.sql) are now tracked in git and should be committed +# Note: Version-specific files (sql/*--*.sql) are tracked in git and should be +# committed once a version is really released (immutable from then on) -- +# except sql/extension_drop--stable.sql, which is just a mechanical copy of +# sql/extension_drop.sql for as long as default_version is the stable +# pseudo-version, so committing it would just duplicate that file. +sql/extension_drop--stable.sql # Test artifacts results/ diff --git a/HISTORY.asc b/HISTORY.asc index f483708..c92f145 100644 --- a/HISTORY.asc +++ b/HISTORY.asc @@ -1,5 +1,5 @@ -1.0.0 ------ +STABLE +------ == Remove redundant client_min_messages handling from install script `CREATE EXTENSION` already raises `client_min_messages` to `WARNING` for the install script (only-raising, so a stricter caller is respected) and diff --git a/META.in.json b/META.in.json index d7c8cdb..5556eb1 100644 --- a/META.in.json +++ b/META.in.json @@ -16,7 +16,7 @@ "name": "extension_drop", "X_comment": "REQUIRED. Version of the distribution. http://pgxn.org/spec/#version", - "version": "1.0.0", + "version": "stable", "X_comment": "REQUIRED. Short description of distribution.", "abstract": "Run custom commands when an extension is dropped.", @@ -41,7 +41,7 @@ "file": "sql/extension_drop.sql", "X_comment": "REQUIRED. Version the extension is at.", - "version": "1.0.0", + "version": "stable", "X_comment": "Optional: \"abstract\": Description of the extension.", "abstract": "Run custom commands when an extension is dropped.", diff --git a/META.json b/META.json index 70608a2..a31bbb6 100644 --- a/META.json +++ b/META.json @@ -16,7 +16,7 @@ "name": "extension_drop", "X_comment": "REQUIRED. Version of the distribution. http://pgxn.org/spec/#version", - "version": "1.0.0", + "version": "stable", "X_comment": "REQUIRED. Short description of distribution.", "abstract": "Run custom commands when an extension is dropped.", @@ -41,7 +41,7 @@ "file": "sql/extension_drop.sql", "X_comment": "REQUIRED. Version the extension is at.", - "version": "1.0.0", + "version": "stable", "X_comment": "Optional: \"abstract\": Description of the extension.", "abstract": "Run custom commands when an extension is dropped.", diff --git a/extension_drop.control b/extension_drop.control index 64aba38..f129e48 100644 --- a/extension_drop.control +++ b/extension_drop.control @@ -1,4 +1,4 @@ comment = 'Allows specifying commands to run when dropping an extension.' -default_version = '1.0.0' +default_version = 'stable' relocatable = false requires = 'cat_tools' diff --git a/sql/extension_drop--1.0.0.sql b/sql/extension_drop--1.0.0.sql deleted file mode 100644 index 3fe71e8..0000000 --- a/sql/extension_drop--1.0.0.sql +++ /dev/null @@ -1,319 +0,0 @@ -/* DO NOT EDIT - AUTO-GENERATED FILE */ -/* - * NOTE: All pg_temp objects must be dropped at the end of the script! - * Otherwise the eventual DROP CASCADE of pg_temp when the session ends will - * also drop the extension! Instead of risking problems, create our own - * "temporary" schema instead. - */ -CREATE SCHEMA __extension_drop; - -CREATE FUNCTION __extension_drop.exec( - sql text -) RETURNS void LANGUAGE plpgsql AS $body$ -BEGIN - RAISE DEBUG 'sql = %', sql; - EXECUTE sql; -END -$body$; - -CREATE FUNCTION __extension_drop.safe_dump( - relation regclass - , filter text DEFAULT '' -) RETURNS void LANGUAGE plpgsql AS $body$ -BEGIN - PERFORM pg_catalog.pg_extension_config_dump(relation, filter); -EXCEPTION WHEN feature_not_supported THEN - NULL; -END -$body$; - -CREATE FUNCTION __extension_drop.create_function( - function_name text - , args text - , options text - , body text - , comment text - , grants text DEFAULT NULL -) RETURNS void LANGUAGE plpgsql AS $body$ -DECLARE - c_clean_args text := cat_tools.routine__parse_arg_types_text(args); - - create_template CONSTANT text := $template$ -CREATE OR REPLACE FUNCTION %s( -%s -) RETURNS %s SET search_path FROM CURRENT AS -%L -$template$ - ; - - revoke_template CONSTANT text := $template$ -REVOKE ALL ON FUNCTION %s( -%s -) FROM public; -$template$ - ; - - grant_template CONSTANT text := $template$ -GRANT EXECUTE ON FUNCTION %s( -%s -) TO %s; -$template$ - ; - - comment_template CONSTANT text := $template$ -COMMENT ON FUNCTION %s( -%s -) IS %L; -$template$ - ; - -BEGIN - PERFORM __extension_drop.exec( format( - create_template - , function_name - , args - , options -- TODO: Force search_path if options ~* 'definer' - , body - ) ) - ; - - IF grants IS NOT NULL THEN - PERFORM __extension_drop.exec( format( - revoke_template - , function_name - , c_clean_args - ) ) - ; - IF grants <> '' THEN - PERFORM __extension_drop.exec( format( - grant_template - , function_name - , c_clean_args - , grants - ) ) - ; - END IF; - END IF; - - IF comment IS NOT NULL THEN - PERFORM __extension_drop.exec( format( - comment_template - , function_name - , c_clean_args - , comment - ) ) - ; - END IF; -END -$body$; - -CREATE TABLE extension_drop__commands( - extension_name name PRIMARY KEY - , sql text NOT NULL -); -SELECT __extension_drop.safe_dump('extension_drop__commands', ''); - -SELECT __extension_drop.create_function( - 'extension_drop__sanity_check' - , 'ignore name DEFAULT NULL' - , 'name[] LANGUAGE sql STABLE' - , $body$ -SELECT array( - SELECT extension_name - FROM extension_drop__commands c - WHERE NOT EXISTS(SELECT 1 FROM pg_catalog.pg_extension e WHERE e.extname = c.extension_name) - AND extension_name IS DISTINCT FROM ignore - ) -$body$ - , $$Returns an array of extensions that have drop commands but do not exist. This array should always be empty!$$ -); - -SELECT __extension_drop.create_function( - 'extension_drop__sanity_assert' - , 'ignore name DEFAULT NULL' - , 'void LANGUAGE plpgsql STABLE' - , $body$ -DECLARE - bad name[] := extension_drop__sanity_check(ignore); -BEGIN - IF bad != '{}'::name[] THEN - RAISE 'unexpected drop commands' - USING ERRCODE = 'XD001' - , HINT = $$This should not happen unless someone manually inserted into "extension_drop__commands" or messed with the "extension_drop" event trigger. - Use SELECT extension_drop__repair() to fix this.$$ - , DETAIL = format( - '%s not exist: %s' - , CASE WHEN array_length(bad, 1) = 1 THEN 'This extension does' ELSE 'These extensions do' END - , array_to_string(bad, ', ') - ) - ; - END IF; -END -$body$ - , $$Throws an error if the "extension_drop__commands" table is not in a sane state.$$ -); - -/* - * REPAIR - */ -SELECT __extension_drop.create_function( - 'extension_drop__repair' - , '' - , 'void LANGUAGE sql' - , $body$ -DELETE FROM extension_drop__commands WHERE extension_name = ANY( extension_drop__sanity_check() ) -$body$ - , 'Repairs the "extension_drop__commands" table. THIS FUNCTION SHOULD NEVER BE NEEDED.' - , '' -- Just revoke all access -); - -/* - * GET - */ -SELECT __extension_drop.create_function( - 'extension_drop__get' - , $$ - extension_name extension_drop__commands.extension_name%TYPE -$$ - , 'extension_drop__commands STABLE LANGUAGE plpgsql' - , $body$ -DECLARE - ret extension_drop__commands; -BEGIN - PERFORM extension_drop__sanity_assert(); - SELECT INTO STRICT ret - * - FROM extension_drop__commands d - WHERE d.extension_name = extension_drop__get.extension_name - ; - - RETURN ret; - -EXCEPTION WHEN no_data_found THEN - RAISE 'no drop commands for extension "%"', extension_name - USING errcode = 'no_data_found' - ; -END -$body$ - , $$Get info about a set of commands to be run when an extension is dropped.$$ -); - -/* - * ADD - */ -SELECT __extension_drop.create_function( - 'extension_drop__add' - , $$ - extension_name extension_drop__commands.extension_name%TYPE - , sql extension_drop__commands.sql%TYPE -$$ - , 'void LANGUAGE plpgsql' - , $body$ -BEGIN - INSERT INTO extension_drop__commands VALUES(extension_name, sql); - PERFORM extension_drop__sanity_assert(); -END -$body$ - , $$Adds a set of commands to be run when an extension is dropped.$$ - , '' -- Just revoke all access -); - -/* - * REMOVE - */ -SELECT __extension_drop.create_function( - 'extension_drop__remove' - , $$ - extension_name extension_drop__commands.extension_name%TYPE -$$ - , 'void LANGUAGE sql' - , $body$ -DELETE FROM extension_drop__commands d - -- extension_drop__get() runs sanity checks for us - WHERE d.extension_name = (extension_drop__get(extension_name)).extension_name -$body$ - , $$Remove a set of commands to be run when an extension is dropped.$$ - , '' -- Just revoke all access -); - -/* - * UPDATE - */ -SELECT __extension_drop.create_function( - 'extension_drop__update' - , $$ - extension_name extension_drop__commands.extension_name%TYPE - , sql extension_drop__commands.sql%TYPE -$$ - , 'void LANGUAGE sql' - , $body$ -UPDATE extension_drop__commands d - SET sql = extension_drop__update.sql - -- extension_drop__get() runs sanity checks for us - WHERE d.extension_name = (extension_drop__get(extension_name)).extension_name -$body$ - , $$Update the set of commands to be run when an extension is dropped.$$ - , '' -- Just revoke all access -); - -/* - * TRIGGER FUNCTION - */ -SELECT __extension_drop.create_function( - 'extension_drop__event_trigger' - , '' - , 'event_trigger LANGUAGE plpgsql' - , $body$ -DECLARE - r extension_drop__commands; -BEGIN - RAISE DEBUG 'extension_drop event trigger entry: tg_event %, tg_tag %', tg_event, tg_tag; - FOR r IN - SELECT c.* - FROM extension_drop__commands c - JOIN pg_event_trigger_dropped_objects() d - ON c.extension_name = d.object_name - AND d.object_type = 'extension' - LOOP - RAISE DEBUG E'extension "%" is being dropped; executing SQL:\n%', r.extension_name, r.sql; - EXECUTE r.sql; - DELETE FROM extension_drop__commands WHERE extension_name = r.extension_name; - END LOOP; - - /* - * Need to do this after the fact since the extensions being dropped have - * already been removed from the catalog by the time this function is called. - */ - PERFORM extension_drop__sanity_assert(); -END -$body$ - , 'Event trigger function that does the actual work for extension_drop.' -); - -CREATE EVENT TRIGGER extension_drop - ON sql_drop - WHEN tag IN( 'DROP EXTENSION' ) -- NOTE! This MUST be IN - EXECUTE PROCEDURE extension_drop__event_trigger() -; - -/* - * Drop "temporary" objects - */ -DROP FUNCTION __extension_drop.create_function( - function_name text - , args text - , options text - , body text - , comment text - , grants text -); -DROP FUNCTION __extension_drop.safe_dump( - relation regclass - , text -); -DROP FUNCTION __extension_drop.exec( - sql text -); -DROP SCHEMA __extension_drop; - --- vim: sw=2 ts=2 expandtab