mirror of
https://github.com/postgres/postgres.git
synced 2025-07-12 21:01:52 +03:00
Allow casting a table's row type to the table's supertype if it's a typed table
This is analogous to the existing facility that allows casting a row type to a supertable's row type.
This commit is contained in:
@ -15,6 +15,7 @@
|
|||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include "catalog/pg_cast.h"
|
#include "catalog/pg_cast.h"
|
||||||
|
#include "catalog/pg_class.h"
|
||||||
#include "catalog/pg_inherits_fn.h"
|
#include "catalog/pg_inherits_fn.h"
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
@ -48,6 +49,7 @@ static Node *coerce_record_to_complex(ParseState *pstate, Node *node,
|
|||||||
CoercionForm cformat,
|
CoercionForm cformat,
|
||||||
int location);
|
int location);
|
||||||
static bool is_complex_array(Oid typid);
|
static bool is_complex_array(Oid typid);
|
||||||
|
static bool typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -371,7 +373,8 @@ coerce_type(ParseState *pstate, Node *node,
|
|||||||
/* NB: we do NOT want a RelabelType here */
|
/* NB: we do NOT want a RelabelType here */
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (typeInheritsFrom(inputTypeId, targetTypeId))
|
if (typeInheritsFrom(inputTypeId, targetTypeId)
|
||||||
|
|| typeIsOfTypedTable(inputTypeId, targetTypeId))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Input class type is a subclass of target, so generate an
|
* Input class type is a subclass of target, so generate an
|
||||||
@ -482,7 +485,8 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
|
|||||||
/*
|
/*
|
||||||
* If input is a class type that inherits from target, accept
|
* If input is a class type that inherits from target, accept
|
||||||
*/
|
*/
|
||||||
if (typeInheritsFrom(inputTypeId, targetTypeId))
|
if (typeInheritsFrom(inputTypeId, targetTypeId)
|
||||||
|
|| typeIsOfTypedTable(inputTypeId, targetTypeId))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2046,3 +2050,34 @@ is_complex_array(Oid typid)
|
|||||||
|
|
||||||
return (OidIsValid(elemtype) && ISCOMPLEX(elemtype));
|
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;
|
||||||
|
}
|
||||||
|
@ -92,3 +92,18 @@ drop cascades to function get_all_persons()
|
|||||||
drop cascades to table persons2
|
drop cascades to table persons2
|
||||||
drop cascades to table persons3
|
drop cascades to table persons3
|
||||||
DROP TABLE stuff;
|
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)
|
||||||
|
@ -47,3 +47,15 @@ DROP TYPE person_type RESTRICT;
|
|||||||
DROP TYPE person_type CASCADE;
|
DROP TYPE person_type CASCADE;
|
||||||
|
|
||||||
DROP TABLE stuff;
|
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;
|
||||||
|
Reference in New Issue
Block a user