#include "postgres.h"
#include "catalog/pg_cast.h"
+#include "catalog/pg_class.h"
#include "catalog/pg_inherits_fn.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
CoercionForm cformat,
int location);
static bool is_complex_array(Oid typid);
+static bool typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId);
/*
/* NB: we do NOT want a RelabelType here */
return node;
}
- if (typeInheritsFrom(inputTypeId, targetTypeId))
+ if (typeInheritsFrom(inputTypeId, targetTypeId)
+ || typeIsOfTypedTable(inputTypeId, targetTypeId))
{
/*
* Input class type is a subclass of target, so generate an
/*
* If input is a class type that inherits from target, accept
*/
- if (typeInheritsFrom(inputTypeId, targetTypeId))
+ if (typeInheritsFrom(inputTypeId, targetTypeId)
+ || typeIsOfTypedTable(inputTypeId, targetTypeId))
continue;
/*
return (OidIsValid(elemtype) && ISCOMPLEX(elemtype));
}
+
+
+/*
+ * Check whether reltypeId is the row type of a typed table of type
+ * reloftypeId. (This is conceptually similar to the subtype
+ * relationship checked by typeInheritsFrom().)
+ */
+static bool
+typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId)
+{
+ Oid relid = typeidTypeRelid(reltypeId);
+ bool result = false;
+
+ if (relid)
+ {
+ HeapTuple tp;
+ Form_pg_class reltup;
+
+ tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tp))
+ elog(ERROR, "cache lookup failed for relation %u", relid);
+
+ reltup = (Form_pg_class) GETSTRUCT(tp);
+ if (reltup->reloftype == reloftypeId)
+ result = true;
+
+ ReleaseSysCache(tp);
+ }
+
+ return result;
+}
drop cascades to table persons2
drop cascades to table persons3
DROP TABLE stuff;
+-- implicit casting
+CREATE TYPE person_type AS (id int, name text);
+CREATE TABLE persons OF person_type;
+INSERT INTO persons VALUES (1, 'test');
+CREATE FUNCTION namelen(person_type) RETURNS int LANGUAGE SQL AS $$ SELECT length($1.name) $$;
+SELECT id, namelen(persons) FROM persons;
+ id | namelen
+----+---------
+ 1 | 4
+(1 row)
+
+DROP TYPE person_type CASCADE;
+NOTICE: drop cascades to 2 other objects
+DETAIL: drop cascades to table persons
+drop cascades to function namelen(person_type)
DROP TYPE person_type CASCADE;
DROP TABLE stuff;
+
+
+-- implicit casting
+
+CREATE TYPE person_type AS (id int, name text);
+CREATE TABLE persons OF person_type;
+INSERT INTO persons VALUES (1, 'test');
+
+CREATE FUNCTION namelen(person_type) RETURNS int LANGUAGE SQL AS $$ SELECT length($1.name) $$;
+SELECT id, namelen(persons) FROM persons;
+
+DROP TYPE person_type CASCADE;