Hi all,

I just bumped into the following problem in HEAD (1c41e2a):
=# create type my_array_float (INPUT = array_in, OUTPUT = array_out,
ELEMENT = float4, INTERNALLENGTH = 32);
ERROR:  XX000: cache lookup failed for type 0
LOCATION:  format_type_internal, format_type.c:135

First note that in ~9.4 the error message is correct:
=# create type my_array_float (INPUT = array_in, OUTPUT = array_out,
ELEMENT = float4, INTERNALLENGTH = 32);
ERROR:  42883: function array_out(my_array_float) does not exist
LOCATION:  findTypeOutputFunction, typecmds.c:1709

Now, the problem is caused by findTypeOutputFunction() in DefineType()
because process passes InvalidOid as type OID when creating a type
shell, root cause being a2e35b5 because of this:
+               address = TypeShellMake(typeName, typeNamespace, GetUserId());

The fix consists in being sure that typoid uses the OID of the type
shell created, aka the OID stored in adress.ObjectID. Attached is a
patch with a regression test checking for shell creation with
incompatible input/output functions (failure caused by output function
here though) able to check this code path.
Regards,
-- 
Michael
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 67e2ae2..37bcd53 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -217,6 +217,7 @@ DefineType(List *names, List *parameters)
 		address = TypeShellMake(typeName, typeNamespace, GetUserId());
 		/* Make new shell type visible for modification below */
 		CommandCounterIncrement();
+		typoid = address.objectId;
 
 		/*
 		 * If the command was a parameterless CREATE TYPE, we're done ---
@@ -1720,6 +1721,8 @@ findTypeOutputFunction(List *procname, Oid typeOid)
 	if (OidIsValid(procOid))
 		return procOid;
 
+	Assert(OidIsValid(typeOid));
+
 	/* No luck, try it with OPAQUE */
 	argList[0] = OPAQUEOID;
 
diff --git a/src/test/regress/expected/create_type.out b/src/test/regress/expected/create_type.out
index 35e8f5d..3646c2b 100644
--- a/src/test/regress/expected/create_type.out
+++ b/src/test/regress/expected/create_type.out
@@ -107,6 +107,12 @@ ERROR:  type "text_w_default" already exists
 DROP TYPE default_test_row CASCADE;
 NOTICE:  drop cascades to function get_default_test()
 DROP TABLE default_test;
+-- Check shell 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 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 96a075b..0c79050 100644
--- a/src/test/regress/sql/create_type.sql
+++ b/src/test/regress/sql/create_type.sql
@@ -106,6 +106,12 @@ DROP TYPE default_test_row CASCADE;
 
 DROP TABLE default_test;
 
+-- Check shell type create with input/output incompatibility
+CREATE TYPE not_existing_type (INPUT = array_in,
+    OUTPUT = array_out,
+    ELEMENT = int,
+    INTERNALLENGTH = 32);
+
 -- Check usage of typmod with a user-defined type
 -- (we have borrowed numeric's typmod functions)
 
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to