Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6a208aa

Browse files
committed
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.
1 parent 92a73d2 commit 6a208aa

File tree

3 files changed

+64
-2
lines changed

3 files changed

+64
-2
lines changed

src/backend/parser/parse_coerce.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "postgres.h"
1616

1717
#include "catalog/pg_cast.h"
18+
#include "catalog/pg_class.h"
1819
#include "catalog/pg_inherits_fn.h"
1920
#include "catalog/pg_proc.h"
2021
#include "catalog/pg_type.h"
@@ -48,6 +49,7 @@ static Node *coerce_record_to_complex(ParseState *pstate, Node *node,
4849
CoercionForm cformat,
4950
int location);
5051
static bool is_complex_array(Oid typid);
52+
static bool typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId);
5153

5254

5355
/*
@@ -371,7 +373,8 @@ coerce_type(ParseState *pstate, Node *node,
371373
/* NB: we do NOT want a RelabelType here */
372374
return node;
373375
}
374-
if (typeInheritsFrom(inputTypeId, targetTypeId))
376+
if (typeInheritsFrom(inputTypeId, targetTypeId)
377+
|| typeIsOfTypedTable(inputTypeId, targetTypeId))
375378
{
376379
/*
377380
* 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,
482485
/*
483486
* If input is a class type that inherits from target, accept
484487
*/
485-
if (typeInheritsFrom(inputTypeId, targetTypeId))
488+
if (typeInheritsFrom(inputTypeId, targetTypeId)
489+
|| typeIsOfTypedTable(inputTypeId, targetTypeId))
486490
continue;
487491

488492
/*
@@ -2046,3 +2050,34 @@ is_complex_array(Oid typid)
20462050

20472051
return (OidIsValid(elemtype) && ISCOMPLEX(elemtype));
20482052
}
2053+
2054+
2055+
/*
2056+
* Check whether reltypeId is the row type of a typed table of type
2057+
* reloftypeId. (This is conceptually similar to the subtype
2058+
* relationship checked by typeInheritsFrom().)
2059+
*/
2060+
static bool
2061+
typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId)
2062+
{
2063+
Oid relid = typeidTypeRelid(reltypeId);
2064+
bool result = false;
2065+
2066+
if (relid)
2067+
{
2068+
HeapTuple tp;
2069+
Form_pg_class reltup;
2070+
2071+
tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
2072+
if (!HeapTupleIsValid(tp))
2073+
elog(ERROR, "cache lookup failed for relation %u", relid);
2074+
2075+
reltup = (Form_pg_class) GETSTRUCT(tp);
2076+
if (reltup->reloftype == reloftypeId)
2077+
result = true;
2078+
2079+
ReleaseSysCache(tp);
2080+
}
2081+
2082+
return result;
2083+
}

src/test/regress/expected/typed_table.out

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,18 @@ drop cascades to function get_all_persons()
9292
drop cascades to table persons2
9393
drop cascades to table persons3
9494
DROP TABLE stuff;
95+
-- implicit casting
96+
CREATE TYPE person_type AS (id int, name text);
97+
CREATE TABLE persons OF person_type;
98+
INSERT INTO persons VALUES (1, 'test');
99+
CREATE FUNCTION namelen(person_type) RETURNS int LANGUAGE SQL AS $$ SELECT length($1.name) $$;
100+
SELECT id, namelen(persons) FROM persons;
101+
id | namelen
102+
----+---------
103+
1 | 4
104+
(1 row)
105+
106+
DROP TYPE person_type CASCADE;
107+
NOTICE: drop cascades to 2 other objects
108+
DETAIL: drop cascades to table persons
109+
drop cascades to function namelen(person_type)

src/test/regress/sql/typed_table.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,15 @@ DROP TYPE person_type RESTRICT;
4747
DROP TYPE person_type CASCADE;
4848

4949
DROP TABLE stuff;
50+
51+
52+
-- implicit casting
53+
54+
CREATE TYPE person_type AS (id int, name text);
55+
CREATE TABLE persons OF person_type;
56+
INSERT INTO persons VALUES (1, 'test');
57+
58+
CREATE FUNCTION namelen(person_type) RETURNS int LANGUAGE SQL AS $$ SELECT length($1.name) $$;
59+
SELECT id, namelen(persons) FROM persons;
60+
61+
DROP TYPE person_type CASCADE;

0 commit comments

Comments
 (0)