type-func-deps.patch

application/octet-stream

Filename: type-func-deps.patch
Type: application/octet-stream
Part: 0
Message: Re: BUG #14706: Dependencies not recorded properly for base types

Patch

Format: unified
File+
src/backend/commands/typecmds.c 23 0
src/test/regress/expected/create_type.out 25 0
src/test/regress/sql/create_type.sql 11 0
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index e7ecc4ed7e..758a9c1520 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -165,6 +165,8 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 	Oid			resulttype;
 	ListCell   *pl;
 	ObjectAddress address;
+	bool		updated_input = false,
+				updated_output = false;
 
 	/*
 	 * As of Postgres 8.4, we require superuser privilege to create a base
@@ -457,6 +459,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 				 (errmsg("changing return type of function %s from %s to %s",
 						 NameListToString(inputName), "opaque", typeName)));
 			SetFunctionReturnType(inputOid, typoid);
+			updated_input = true;
 		}
 		else
 			ereport(ERROR,
@@ -474,6 +477,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 				 (errmsg("changing return type of function %s from %s to %s",
 						 NameListToString(outputName), "opaque", "cstring")));
 			SetFunctionReturnType(outputOid, CSTRINGOID);
+			updated_output = true;
 		}
 		else
 			ereport(ERROR,
@@ -679,6 +683,25 @@ DefineType(ParseState *pstate, List *names, List *parameters)
 
 	pfree(array_type);
 
+	/*
+	 * If type of an OPAQUE function has been changed, add cross-dependencies
+	 * with the new type created.
+	 */
+	if (updated_input)
+	{
+		ObjectAddress input_address;
+
+		ObjectAddressSet(input_address, ProcedureRelationId, inputOid);
+		recordDependencyOn(&input_address, &address, DEPENDENCY_NORMAL);
+	}
+	if (updated_output)
+	{
+		ObjectAddress output_address;
+
+		ObjectAddressSet(output_address, ProcedureRelationId, outputOid);
+		recordDependencyOn(&output_address, &address, DEPENDENCY_NORMAL);
+	}
+
 	return address;
 }
 
diff --git a/src/test/regress/expected/create_type.out b/src/test/regress/expected/create_type.out
index 7bdad4e9bb..b2fa8061f3 100644
--- a/src/test/regress/expected/create_type.out
+++ b/src/test/regress/expected/create_type.out
@@ -115,6 +115,31 @@ CREATE TYPE not_existing_type (INPUT = array_in,
     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_in(cstring) depends on type base_type
+function base_fn_out(base_type) 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_in(cstring)
+drop cascades to function base_fn_out(base_type)
 -- Check usage of typmod with a user-defined type
 -- (we have borrowed numeric's typmod functions)
 CREATE TEMP TABLE mytab (foo widget(42,13,7));     -- should fail
diff --git a/src/test/regress/sql/create_type.sql b/src/test/regress/sql/create_type.sql
index a1839ef9e7..a28303aa6a 100644
--- a/src/test/regress/sql/create_type.sql
+++ b/src/test/regress/sql/create_type.sql
@@ -115,6 +115,17 @@ CREATE TYPE not_existing_type (INPUT = array_in,
     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
 -- (we have borrowed numeric's typmod functions)