Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b47e2f7

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/[email protected]
1 parent 99090e9 commit b47e2f7

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

src/backend/commands/functioncmds.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,8 @@ SetFunctionReturnType(Oid funcOid, Oid newRetType)
11891189
Relation pg_proc_rel;
11901190
HeapTuple tup;
11911191
Form_pg_proc procForm;
1192+
ObjectAddress func_address;
1193+
ObjectAddress type_address;
11921194

11931195
pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
11941196

@@ -1209,6 +1211,20 @@ SetFunctionReturnType(Oid funcOid, Oid newRetType)
12091211
CatalogUpdateIndexes(pg_proc_rel, tup);
12101212

12111213
heap_close(pg_proc_rel, RowExclusiveLock);
1214+
1215+
/*
1216+
* Also update the dependency to the new type. Opaque is a pinned type, so
1217+
* there is no old dependency record for it that we would need to remove.
1218+
*/
1219+
type_address.classId = TypeRelationId;
1220+
type_address.objectId = newRetType;
1221+
type_address.objectSubId = 0;
1222+
1223+
func_address.classId = ProcedureRelationId;
1224+
func_address.objectId = funcOid;
1225+
func_address.objectSubId = 0;
1226+
1227+
recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
12121228
}
12131229

12141230

@@ -1223,6 +1239,8 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
12231239
Relation pg_proc_rel;
12241240
HeapTuple tup;
12251241
Form_pg_proc procForm;
1242+
ObjectAddress func_address;
1243+
ObjectAddress type_address;
12261244

12271245
pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
12281246

@@ -1244,6 +1262,20 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
12441262
CatalogUpdateIndexes(pg_proc_rel, tup);
12451263

12461264
heap_close(pg_proc_rel, RowExclusiveLock);
1265+
1266+
/*
1267+
* Also update the dependency to the new type. Opaque is a pinned type, so
1268+
* there is no old dependency record for it that we would need to remove.
1269+
*/
1270+
type_address.classId = TypeRelationId;
1271+
type_address.objectId = newArgType;
1272+
type_address.objectSubId = 0;
1273+
1274+
func_address.classId = ProcedureRelationId;
1275+
func_address.objectId = funcOid;
1276+
func_address.objectSubId = 0;
1277+
1278+
recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
12471279
}
12481280

12491281

src/test/regress/expected/create_type.out

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,37 @@ ERROR: type "text_w_default" already exists
109109
DROP TYPE default_test_row CASCADE;
110110
NOTICE: drop cascades to function get_default_test()
111111
DROP TABLE default_test;
112+
-- Check type create with input/output incompatibility
113+
CREATE TYPE not_existing_type (INPUT = array_in,
114+
OUTPUT = array_out,
115+
ELEMENT = int,
116+
INTERNALLENGTH = 32);
117+
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)
112143
-- Check usage of typmod with a user-defined type
113144
-- (we have borrowed numeric's typmod functions)
114145
CREATE TEMP TABLE mytab (foo widget(42,13,7)); -- should fail

src/test/regress/sql/create_type.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,23 @@ DROP TYPE default_test_row CASCADE;
109109

110110
DROP TABLE default_test;
111111

112+
-- Check type create with input/output incompatibility
113+
CREATE TYPE not_existing_type (INPUT = array_in,
114+
OUTPUT = array_out,
115+
ELEMENT = int,
116+
INTERNALLENGTH = 32);
117+
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+
112129
-- Check usage of typmod with a user-defined type
113130
-- (we have borrowed numeric's typmod functions)
114131

0 commit comments

Comments
 (0)