Skip to content

Commit 46968f2

Browse files
committed
Finish pgxntool update
Switch to keeping versioned extension files. As part of that, bump to 1.0.0 Also, mark as "testing" (instead of unstable) in PGXN.
1 parent 368f833 commit 46968f2

4 files changed

Lines changed: 333 additions & 7 deletions

File tree

META.in.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"name": "extension_drop",
1717

1818
"X_comment": "REQUIRED. Version of the distribution. http://pgxn.org/spec/#version",
19-
"version": "0.1.1",
19+
"version": "1.0.0",
2020

2121
"X_comment": "REQUIRED. Short description of distribution.",
2222
"abstract": "Run custom commands when an extension is dropped.",
@@ -41,7 +41,7 @@
4141
"file": "sql/extension_drop.sql",
4242

4343
"X_comment": "REQUIRED. Version the extension is at.",
44-
"version": "0.1.1",
44+
"version": "1.0.0",
4545

4646
"X_comment": "Optional: \"abstract\": Description of the extension.",
4747
"abstract": "Run custom commands when an extension is dropped.",
@@ -73,7 +73,7 @@
7373
"X_comment": "Valid keys for 'prereqs' are configure, build, runtime, or test.",
7474
"X_comment": "Valid keys for 'requires' are requires, recommends, suggests, or conflicts.",
7575
"X_comment": "Requires event_triggers, introduced in 9.3",
76-
"X_comment": "cat_tools: requires extension suppport, added in 0.2.1",
76+
"X_comment": "cat_tools: requires extension support, added in 0.2.1",
7777
"prereqs": {
7878

7979
"build": {

META.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"name": "extension_drop",
1717

1818
"X_comment": "REQUIRED. Version of the distribution. http://pgxn.org/spec/#version",
19-
"version": "0.1.1",
19+
"version": "1.0.0",
2020

2121
"X_comment": "REQUIRED. Short description of distribution.",
2222
"abstract": "Run custom commands when an extension is dropped.",
@@ -41,7 +41,7 @@
4141
"file": "sql/extension_drop.sql",
4242

4343
"X_comment": "REQUIRED. Version the extension is at.",
44-
"version": "0.1.1",
44+
"version": "1.0.0",
4545

4646
"X_comment": "Optional: \"abstract\": Description of the extension.",
4747
"abstract": "Run custom commands when an extension is dropped.",
@@ -72,7 +72,7 @@
7272
"X_comment": "Valid keys for 'prereqs' are configure, build, runtime, or test.",
7373
"X_comment": "Valid keys for 'requires' are requires, recommends, suggests, or conflicts.",
7474
"X_comment": "Requires event_triggers, introduced in 9.3",
75-
"X_comment": "cat_tools: requires extension suppport, added in 0.2.1",
75+
"X_comment": "cat_tools: requires extension support, added in 0.2.1",
7676
"prereqs": {
7777

7878
"build": {

extension_drop.control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
comment = 'Allows specifying commands to run when dropping an extension.'
2-
default_version = '0.1.1'
2+
default_version = '1.0.0'
33
relocatable = false
44
requires = 'cat_tools'

sql/extension_drop--1.0.0.sql

Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
/* DO NOT EDIT - AUTO-GENERATED FILE */
2+
/*
3+
* NOTE: All pg_temp objects must be dropped at the end of the script!
4+
* Otherwise the eventual DROP CASCADE of pg_temp when the session ends will
5+
* also drop the extension! Instead of risking problems, create our own
6+
* "temporary" schema instead.
7+
*/
8+
CREATE SCHEMA __extension_drop;
9+
10+
CREATE TABLE __extension_drop.messages AS SELECT pg_catalog.current_setting('client_min_messages');
11+
SET client_min_messages = WARNING;
12+
13+
CREATE FUNCTION __extension_drop.exec(
14+
sql text
15+
) RETURNS void LANGUAGE plpgsql AS $body$
16+
BEGIN
17+
RAISE DEBUG 'sql = %', sql;
18+
EXECUTE sql;
19+
END
20+
$body$;
21+
22+
CREATE FUNCTION __extension_drop.safe_dump(
23+
relation regclass
24+
, filter text DEFAULT ''
25+
) RETURNS void LANGUAGE plpgsql AS $body$
26+
BEGIN
27+
PERFORM pg_catalog.pg_extension_config_dump(relation, filter);
28+
EXCEPTION WHEN feature_not_supported THEN
29+
NULL;
30+
END
31+
$body$;
32+
33+
CREATE FUNCTION __extension_drop.create_function(
34+
function_name text
35+
, args text
36+
, options text
37+
, body text
38+
, comment text
39+
, grants text DEFAULT NULL
40+
) RETURNS void LANGUAGE plpgsql AS $body$
41+
DECLARE
42+
c_clean_args text := cat_tools.routine__parse_arg_types_text(args);
43+
44+
create_template CONSTANT text := $template$
45+
CREATE OR REPLACE FUNCTION %s(
46+
%s
47+
) RETURNS %s SET search_path FROM CURRENT AS
48+
%L
49+
$template$
50+
;
51+
52+
revoke_template CONSTANT text := $template$
53+
REVOKE ALL ON FUNCTION %s(
54+
%s
55+
) FROM public;
56+
$template$
57+
;
58+
59+
grant_template CONSTANT text := $template$
60+
GRANT EXECUTE ON FUNCTION %s(
61+
%s
62+
) TO %s;
63+
$template$
64+
;
65+
66+
comment_template CONSTANT text := $template$
67+
COMMENT ON FUNCTION %s(
68+
%s
69+
) IS %L;
70+
$template$
71+
;
72+
73+
BEGIN
74+
PERFORM __extension_drop.exec( format(
75+
create_template
76+
, function_name
77+
, args
78+
, options -- TODO: Force search_path if options ~* 'definer'
79+
, body
80+
) )
81+
;
82+
83+
IF grants IS NOT NULL THEN
84+
PERFORM __extension_drop.exec( format(
85+
revoke_template
86+
, function_name
87+
, c_clean_args
88+
) )
89+
;
90+
IF grants <> '' THEN
91+
PERFORM __extension_drop.exec( format(
92+
grant_template
93+
, function_name
94+
, c_clean_args
95+
, grants
96+
) )
97+
;
98+
END IF;
99+
END IF;
100+
101+
IF comment IS NOT NULL THEN
102+
PERFORM __extension_drop.exec( format(
103+
comment_template
104+
, function_name
105+
, c_clean_args
106+
, comment
107+
) )
108+
;
109+
END IF;
110+
END
111+
$body$;
112+
113+
CREATE TABLE extension_drop__commands(
114+
extension_name name PRIMARY KEY
115+
, sql text NOT NULL
116+
);
117+
SELECT __extension_drop.safe_dump('extension_drop__commands', '');
118+
119+
SELECT __extension_drop.create_function(
120+
'extension_drop__sanity_check'
121+
, 'ignore name DEFAULT NULL'
122+
, 'name[] LANGUAGE sql STABLE'
123+
, $body$
124+
SELECT array(
125+
SELECT extension_name
126+
FROM extension_drop__commands c
127+
WHERE NOT EXISTS(SELECT 1 FROM pg_catalog.pg_extension e WHERE e.extname = c.extension_name)
128+
AND extension_name IS DISTINCT FROM ignore
129+
)
130+
$body$
131+
, $$Returns an array of extensions that have drop commands but do not exist. This array should always be empty!$$
132+
);
133+
134+
SELECT __extension_drop.create_function(
135+
'extension_drop__sanity_assert'
136+
, 'ignore name DEFAULT NULL'
137+
, 'void LANGUAGE plpgsql STABLE'
138+
, $body$
139+
DECLARE
140+
bad name[] := extension_drop__sanity_check(ignore);
141+
BEGIN
142+
IF bad != '{}'::name[] THEN
143+
RAISE 'unexpected drop commands'
144+
USING ERRCODE = 'XD001'
145+
, HINT = $$This should not happen unless someone manually inserted into "extension_drop__commands" or messed with the "extension_drop" event trigger.
146+
Use SELECT extension_drop__repair() to fix this.$$
147+
, DETAIL = format(
148+
'%s not exist: %s'
149+
, CASE WHEN array_length(bad, 1) = 1 THEN 'This extension does' ELSE 'These extensions do' END
150+
, array_to_string(bad, ', ')
151+
)
152+
;
153+
END IF;
154+
END
155+
$body$
156+
, $$Throws an error if the "extension_drop__commands" table is not in a sane state.$$
157+
);
158+
159+
/*
160+
* REPAIR
161+
*/
162+
SELECT __extension_drop.create_function(
163+
'extension_drop__repair'
164+
, ''
165+
, 'void LANGUAGE sql'
166+
, $body$
167+
DELETE FROM extension_drop__commands WHERE extension_name = ANY( extension_drop__sanity_check() )
168+
$body$
169+
, 'Repairs the "extension_drop__commands" table. THIS FUNCTION SHOULD NEVER BE NEEDED.'
170+
, '' -- Just revoke all access
171+
);
172+
173+
/*
174+
* GET
175+
*/
176+
SELECT __extension_drop.create_function(
177+
'extension_drop__get'
178+
, $$
179+
extension_name extension_drop__commands.extension_name%TYPE
180+
$$
181+
, 'extension_drop__commands STABLE LANGUAGE plpgsql'
182+
, $body$
183+
DECLARE
184+
ret extension_drop__commands;
185+
BEGIN
186+
PERFORM extension_drop__sanity_assert();
187+
SELECT INTO STRICT ret
188+
*
189+
FROM extension_drop__commands d
190+
WHERE d.extension_name = extension_drop__get.extension_name
191+
;
192+
193+
RETURN ret;
194+
195+
EXCEPTION WHEN no_data_found THEN
196+
RAISE 'no drop commands for extension "%"', extension_name
197+
USING errcode = 'no_data_found'
198+
;
199+
END
200+
$body$
201+
, $$Get info about a set of commands to be run when an extension is dropped.$$
202+
);
203+
204+
/*
205+
* ADD
206+
*/
207+
SELECT __extension_drop.create_function(
208+
'extension_drop__add'
209+
, $$
210+
extension_name extension_drop__commands.extension_name%TYPE
211+
, sql extension_drop__commands.sql%TYPE
212+
$$
213+
, 'void LANGUAGE plpgsql'
214+
, $body$
215+
BEGIN
216+
INSERT INTO extension_drop__commands VALUES(extension_name, sql);
217+
PERFORM extension_drop__sanity_assert();
218+
END
219+
$body$
220+
, $$Adds a set of commands to be run when an extension is dropped.$$
221+
, '' -- Just revoke all access
222+
);
223+
224+
/*
225+
* REMOVE
226+
*/
227+
SELECT __extension_drop.create_function(
228+
'extension_drop__remove'
229+
, $$
230+
extension_name extension_drop__commands.extension_name%TYPE
231+
$$
232+
, 'void LANGUAGE sql'
233+
, $body$
234+
DELETE FROM extension_drop__commands d
235+
-- extension_drop__get() runs sanity checks for us
236+
WHERE d.extension_name = (extension_drop__get(extension_name)).extension_name
237+
$body$
238+
, $$Remove a set of commands to be run when an extension is dropped.$$
239+
, '' -- Just revoke all access
240+
);
241+
242+
/*
243+
* UPDATE
244+
*/
245+
SELECT __extension_drop.create_function(
246+
'extension_drop__update'
247+
, $$
248+
extension_name extension_drop__commands.extension_name%TYPE
249+
, sql extension_drop__commands.sql%TYPE
250+
$$
251+
, 'void LANGUAGE sql'
252+
, $body$
253+
UPDATE extension_drop__commands d
254+
SET sql = extension_drop__update.sql
255+
-- extension_drop__get() runs sanity checks for us
256+
WHERE d.extension_name = (extension_drop__get(extension_name)).extension_name
257+
$body$
258+
, $$Update the set of commands to be run when an extension is dropped.$$
259+
, '' -- Just revoke all access
260+
);
261+
262+
/*
263+
* TRIGGER FUNCTION
264+
*/
265+
SELECT __extension_drop.create_function(
266+
'extension_drop__event_trigger'
267+
, ''
268+
, 'event_trigger LANGUAGE plpgsql'
269+
, $body$
270+
DECLARE
271+
r extension_drop__commands;
272+
BEGIN
273+
RAISE DEBUG 'extension_drop event trigger entry: tg_event %, tg_tag %', tg_event, tg_tag;
274+
FOR r IN
275+
SELECT c.*
276+
FROM extension_drop__commands c
277+
JOIN pg_event_trigger_dropped_objects() d
278+
ON c.extension_name = d.object_name
279+
AND d.object_type = 'extension'
280+
LOOP
281+
RAISE DEBUG E'extension "%" is being dropped; executing SQL:\n%', r.extension_name, r.sql;
282+
EXECUTE r.sql;
283+
DELETE FROM extension_drop__commands WHERE extension_name = r.extension_name;
284+
END LOOP;
285+
286+
/*
287+
* Need to do this after the fact since the extensions being dropped have
288+
* already been removed from the catalog by the time this function is called.
289+
*/
290+
PERFORM extension_drop__sanity_assert();
291+
END
292+
$body$
293+
, 'Event trigger function that does the actual work for extension_drop.'
294+
);
295+
296+
CREATE EVENT TRIGGER extension_drop
297+
ON sql_drop
298+
WHEN tag IN( 'DROP EXTENSION' ) -- NOTE! This MUST be IN
299+
EXECUTE PROCEDURE extension_drop__event_trigger()
300+
;
301+
302+
/*
303+
* Drop "temporary" objects
304+
*/
305+
SELECT __extension_drop.exec('SET client_min_messages = ' || current_setting)
306+
FROM __extension_drop.messages
307+
;
308+
DROP TABLE __extension_drop.messages;
309+
DROP FUNCTION __extension_drop.create_function(
310+
function_name text
311+
, args text
312+
, options text
313+
, body text
314+
, comment text
315+
, grants text
316+
);
317+
DROP FUNCTION __extension_drop.safe_dump(
318+
relation regclass
319+
, text
320+
);
321+
DROP FUNCTION __extension_drop.exec(
322+
sql text
323+
);
324+
DROP SCHEMA __extension_drop;
325+
326+
-- vim: sw=2 ts=2 expandtab

0 commit comments

Comments
 (0)