mirror of
https://github.com/postgres/postgres.git
synced 2025-06-04 12:42:24 +03:00
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
This commit is contained in:
parent
99090e977d
commit
b47e2f7a94
@ -1189,6 +1189,8 @@ SetFunctionReturnType(Oid funcOid, Oid newRetType)
|
|||||||
Relation pg_proc_rel;
|
Relation pg_proc_rel;
|
||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
Form_pg_proc procForm;
|
Form_pg_proc procForm;
|
||||||
|
ObjectAddress func_address;
|
||||||
|
ObjectAddress type_address;
|
||||||
|
|
||||||
pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
|
pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
@ -1209,6 +1211,20 @@ SetFunctionReturnType(Oid funcOid, Oid newRetType)
|
|||||||
CatalogUpdateIndexes(pg_proc_rel, tup);
|
CatalogUpdateIndexes(pg_proc_rel, tup);
|
||||||
|
|
||||||
heap_close(pg_proc_rel, RowExclusiveLock);
|
heap_close(pg_proc_rel, RowExclusiveLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Also update the dependency to the new type. Opaque is a pinned type, so
|
||||||
|
* there is no old dependency record for it that we would need to remove.
|
||||||
|
*/
|
||||||
|
type_address.classId = TypeRelationId;
|
||||||
|
type_address.objectId = newRetType;
|
||||||
|
type_address.objectSubId = 0;
|
||||||
|
|
||||||
|
func_address.classId = ProcedureRelationId;
|
||||||
|
func_address.objectId = funcOid;
|
||||||
|
func_address.objectSubId = 0;
|
||||||
|
|
||||||
|
recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1223,6 +1239,8 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
|
|||||||
Relation pg_proc_rel;
|
Relation pg_proc_rel;
|
||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
Form_pg_proc procForm;
|
Form_pg_proc procForm;
|
||||||
|
ObjectAddress func_address;
|
||||||
|
ObjectAddress type_address;
|
||||||
|
|
||||||
pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
|
pg_proc_rel = heap_open(ProcedureRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
@ -1244,6 +1262,20 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
|
|||||||
CatalogUpdateIndexes(pg_proc_rel, tup);
|
CatalogUpdateIndexes(pg_proc_rel, tup);
|
||||||
|
|
||||||
heap_close(pg_proc_rel, RowExclusiveLock);
|
heap_close(pg_proc_rel, RowExclusiveLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Also update the dependency to the new type. Opaque is a pinned type, so
|
||||||
|
* there is no old dependency record for it that we would need to remove.
|
||||||
|
*/
|
||||||
|
type_address.classId = TypeRelationId;
|
||||||
|
type_address.objectId = newArgType;
|
||||||
|
type_address.objectSubId = 0;
|
||||||
|
|
||||||
|
func_address.classId = ProcedureRelationId;
|
||||||
|
func_address.objectId = funcOid;
|
||||||
|
func_address.objectSubId = 0;
|
||||||
|
|
||||||
|
recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,6 +109,37 @@ ERROR: type "text_w_default" already exists
|
|||||||
DROP TYPE default_test_row CASCADE;
|
DROP TYPE default_test_row CASCADE;
|
||||||
NOTICE: drop cascades to function get_default_test()
|
NOTICE: drop cascades to function get_default_test()
|
||||||
DROP TABLE default_test;
|
DROP TABLE default_test;
|
||||||
|
-- Check type create with input/output incompatibility
|
||||||
|
CREATE TYPE not_existing_type (INPUT = array_in,
|
||||||
|
OUTPUT = array_out,
|
||||||
|
ELEMENT = int,
|
||||||
|
INTERNALLENGTH = 32);
|
||||||
|
ERROR: function array_out(not_existing_type) does not exist
|
||||||
|
-- Check dependency transfer of opaque functions when creating a new type
|
||||||
|
CREATE FUNCTION base_fn_in(cstring) RETURNS opaque AS 'boolin'
|
||||||
|
LANGUAGE internal IMMUTABLE STRICT;
|
||||||
|
CREATE FUNCTION base_fn_out(opaque) RETURNS opaque AS 'boolout'
|
||||||
|
LANGUAGE internal IMMUTABLE STRICT;
|
||||||
|
CREATE TYPE base_type(INPUT = base_fn_in, OUTPUT = base_fn_out);
|
||||||
|
WARNING: changing argument type of function base_fn_out from "opaque" to base_type
|
||||||
|
WARNING: changing return type of function base_fn_in from "opaque" to base_type
|
||||||
|
WARNING: changing return type of function base_fn_out from "opaque" to "cstring"
|
||||||
|
DROP FUNCTION base_fn_in(cstring); -- error
|
||||||
|
ERROR: cannot drop function base_fn_in(cstring) because other objects depend on it
|
||||||
|
DETAIL: type base_type depends on function base_fn_in(cstring)
|
||||||
|
function base_fn_out(base_type) depends on type base_type
|
||||||
|
HINT: Use DROP ... CASCADE to drop the dependent objects too.
|
||||||
|
DROP FUNCTION base_fn_out(opaque); -- error
|
||||||
|
ERROR: function base_fn_out(opaque) does not exist
|
||||||
|
DROP TYPE base_type; -- error
|
||||||
|
ERROR: cannot drop type base_type because other objects depend on it
|
||||||
|
DETAIL: function base_fn_out(base_type) depends on type base_type
|
||||||
|
function base_fn_in(cstring) depends on type base_type
|
||||||
|
HINT: Use DROP ... CASCADE to drop the dependent objects too.
|
||||||
|
DROP TYPE base_type CASCADE;
|
||||||
|
NOTICE: drop cascades to 2 other objects
|
||||||
|
DETAIL: drop cascades to function base_fn_out(base_type)
|
||||||
|
drop cascades to function base_fn_in(cstring)
|
||||||
-- Check usage of typmod with a user-defined type
|
-- Check usage of typmod with a user-defined type
|
||||||
-- (we have borrowed numeric's typmod functions)
|
-- (we have borrowed numeric's typmod functions)
|
||||||
CREATE TEMP TABLE mytab (foo widget(42,13,7)); -- should fail
|
CREATE TEMP TABLE mytab (foo widget(42,13,7)); -- should fail
|
||||||
|
@ -109,6 +109,23 @@ DROP TYPE default_test_row CASCADE;
|
|||||||
|
|
||||||
DROP TABLE default_test;
|
DROP TABLE default_test;
|
||||||
|
|
||||||
|
-- Check type create with input/output incompatibility
|
||||||
|
CREATE TYPE not_existing_type (INPUT = array_in,
|
||||||
|
OUTPUT = array_out,
|
||||||
|
ELEMENT = int,
|
||||||
|
INTERNALLENGTH = 32);
|
||||||
|
|
||||||
|
-- Check dependency transfer of opaque functions when creating a new type
|
||||||
|
CREATE FUNCTION base_fn_in(cstring) RETURNS opaque AS 'boolin'
|
||||||
|
LANGUAGE internal IMMUTABLE STRICT;
|
||||||
|
CREATE FUNCTION base_fn_out(opaque) RETURNS opaque AS 'boolout'
|
||||||
|
LANGUAGE internal IMMUTABLE STRICT;
|
||||||
|
CREATE TYPE base_type(INPUT = base_fn_in, OUTPUT = base_fn_out);
|
||||||
|
DROP FUNCTION base_fn_in(cstring); -- error
|
||||||
|
DROP FUNCTION base_fn_out(opaque); -- error
|
||||||
|
DROP TYPE base_type; -- error
|
||||||
|
DROP TYPE base_type CASCADE;
|
||||||
|
|
||||||
-- Check usage of typmod with a user-defined type
|
-- Check usage of typmod with a user-defined type
|
||||||
-- (we have borrowed numeric's typmod functions)
|
-- (we have borrowed numeric's typmod functions)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user