Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 30681c8

Browse files
committed
Fix dependency, when changing a function's argument/return type.
When a new base type is created using the old-style procedure of first creating the input/output functions with "opaque" in place of the base type, the "opaque" argument/return type is changed to the final base type, on CREATE TYPE. However, we did not create a pg_depend record when doing that, so the functions were left not depending on the type. Fixes bug #14706, reported by Karen Huddleston. Discussion: https://www.postgresql.org/message-id/20170614232259.1424.82774@wrigleys.postgresql.org
1 parent 39ac559 commit 30681c8

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

src/backend/commands/functioncmds.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,8 @@ SetFunctionReturnType(Oid funcOid, Oid newRetType)
13161316
Relation pg_proc_rel;
13171317
HeapTuple tup;
13181318
Form_pg_proc procForm;
1319+
ObjectAddress func_address;
1320+
ObjectAddress type_address;
13191321

13201322
pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
13211323

@@ -1334,6 +1336,14 @@ SetFunctionReturnType(Oid funcOid, Oid newRetType)
13341336
CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
13351337

13361338
heap_close(pg_proc_rel, RowExclusiveLock);
1339+
1340+
/*
1341+
* Also update the dependency to the new type. Opaque is a pinned type, so
1342+
* there is no old dependency record for it that we would need to remove.
1343+
*/
1344+
ObjectAddressSet(type_address, TypeRelationId, newRetType);
1345+
ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
1346+
recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
13371347
}
13381348

13391349

@@ -1348,6 +1358,8 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
13481358
Relation pg_proc_rel;
13491359
HeapTuple tup;
13501360
Form_pg_proc procForm;
1361+
ObjectAddress func_address;
1362+
ObjectAddress type_address;
13511363

13521364
pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
13531365

@@ -1367,6 +1379,14 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
13671379
CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
13681380

13691381
heap_close(pg_proc_rel, RowExclusiveLock);
1382+
1383+
/*
1384+
* Also update the dependency to the new type. Opaque is a pinned type, so
1385+
* there is no old dependency record for it that we would need to remove.
1386+
*/
1387+
ObjectAddressSet(type_address, TypeRelationId, newArgType);
1388+
ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
1389+
recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
13701390
}
13711391

13721392

src/test/regress/expected/create_type.out

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,31 @@ CREATE TYPE not_existing_type (INPUT = array_in,
115115
ELEMENT = int,
116116
INTERNALLENGTH = 32);
117117
ERROR: function array_out(not_existing_type) does not exist
118+
-- Check dependency transfer of opaque functions when creating a new type
119+
CREATE FUNCTION base_fn_in(cstring) RETURNS opaque AS 'boolin'
120+
LANGUAGE internal IMMUTABLE STRICT;
121+
CREATE FUNCTION base_fn_out(opaque) RETURNS opaque AS 'boolout'
122+
LANGUAGE internal IMMUTABLE STRICT;
123+
CREATE TYPE base_type(INPUT = base_fn_in, OUTPUT = base_fn_out);
124+
WARNING: changing argument type of function base_fn_out from "opaque" to base_type
125+
WARNING: changing return type of function base_fn_in from opaque to base_type
126+
WARNING: changing return type of function base_fn_out from opaque to cstring
127+
DROP FUNCTION base_fn_in(cstring); -- error
128+
ERROR: cannot drop function base_fn_in(cstring) because other objects depend on it
129+
DETAIL: type base_type depends on function base_fn_in(cstring)
130+
function base_fn_out(base_type) depends on type base_type
131+
HINT: Use DROP ... CASCADE to drop the dependent objects too.
132+
DROP FUNCTION base_fn_out(opaque); -- error
133+
ERROR: function base_fn_out(opaque) does not exist
134+
DROP TYPE base_type; -- error
135+
ERROR: cannot drop type base_type because other objects depend on it
136+
DETAIL: function base_fn_out(base_type) depends on type base_type
137+
function base_fn_in(cstring) depends on type base_type
138+
HINT: Use DROP ... CASCADE to drop the dependent objects too.
139+
DROP TYPE base_type CASCADE;
140+
NOTICE: drop cascades to 2 other objects
141+
DETAIL: drop cascades to function base_fn_out(base_type)
142+
drop cascades to function base_fn_in(cstring)
118143
-- Check usage of typmod with a user-defined type
119144
-- (we have borrowed numeric's typmod functions)
120145
CREATE TEMP TABLE mytab (foo widget(42,13,7)); -- should fail

src/test/regress/sql/create_type.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,17 @@ CREATE TYPE not_existing_type (INPUT = array_in,
115115
ELEMENT = int,
116116
INTERNALLENGTH = 32);
117117

118+
-- Check dependency transfer of opaque functions when creating a new type
119+
CREATE FUNCTION base_fn_in(cstring) RETURNS opaque AS 'boolin'
120+
LANGUAGE internal IMMUTABLE STRICT;
121+
CREATE FUNCTION base_fn_out(opaque) RETURNS opaque AS 'boolout'
122+
LANGUAGE internal IMMUTABLE STRICT;
123+
CREATE TYPE base_type(INPUT = base_fn_in, OUTPUT = base_fn_out);
124+
DROP FUNCTION base_fn_in(cstring); -- error
125+
DROP FUNCTION base_fn_out(opaque); -- error
126+
DROP TYPE base_type; -- error
127+
DROP TYPE base_type CASCADE;
128+
118129
-- Check usage of typmod with a user-defined type
119130
-- (we have borrowed numeric's typmod functions)
120131

0 commit comments

Comments
 (0)