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

Commit a9a5eb3

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 b217459 commit a9a5eb3

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
@@ -1318,6 +1318,8 @@ SetFunctionReturnType(Oid funcOid, Oid newRetType)
13181318
Relation pg_proc_rel;
13191319
HeapTuple tup;
13201320
Form_pg_proc procForm;
1321+
ObjectAddress func_address;
1322+
ObjectAddress type_address;
13211323

13221324
pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
13231325

@@ -1338,6 +1340,14 @@ SetFunctionReturnType(Oid funcOid, Oid newRetType)
13381340
CatalogUpdateIndexes(pg_proc_rel, tup);
13391341

13401342
heap_close(pg_proc_rel, RowExclusiveLock);
1343+
1344+
/*
1345+
* Also update the dependency to the new type. Opaque is a pinned type, so
1346+
* there is no old dependency record for it that we would need to remove.
1347+
*/
1348+
ObjectAddressSet(type_address, TypeRelationId, newRetType);
1349+
ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
1350+
recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
13411351
}
13421352

13431353

@@ -1352,6 +1362,8 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
13521362
Relation pg_proc_rel;
13531363
HeapTuple tup;
13541364
Form_pg_proc procForm;
1365+
ObjectAddress func_address;
1366+
ObjectAddress type_address;
13551367

13561368
pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
13571369

@@ -1373,6 +1385,14 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
13731385
CatalogUpdateIndexes(pg_proc_rel, tup);
13741386

13751387
heap_close(pg_proc_rel, RowExclusiveLock);
1388+
1389+
/*
1390+
* Also update the dependency to the new type. Opaque is a pinned type, so
1391+
* there is no old dependency record for it that we would need to remove.
1392+
*/
1393+
ObjectAddressSet(type_address, TypeRelationId, newArgType);
1394+
ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
1395+
recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
13761396
}
13771397

13781398

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)