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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy