1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Support domains over composite types.

This is the last major omission in our domains feature: you can now
make a domain over anything that's not a pseudotype.

The major complication from an implementation standpoint is that places
that might be creating tuples of a domain type now need to be prepared
to apply domain_check().  It seems better that unprepared code fail
with an error like "<type> is not composite" than that it silently fail
to apply domain constraints.  Therefore, relevant infrastructure like
get_func_result_type() and lookup_rowtype_tupdesc() has been adjusted
to treat domain-over-composite as a distinct case that unprepared code
won't recognize, rather than just transparently treating it the same
as plain composite.  This isn't a 100% solution to the possibility of
overlooked domain checks, but it catches most places.

In passing, improve typcache.c's support for domains (it can now cache
the identity of a domain's base type), and rewrite the argument handling
logic in jsonfuncs.c's populate_record[set]_worker to reduce duplicative
per-call lookups.

I believe this is code-complete so far as the core and contrib code go.
The PLs need varying amounts of work, which will be tackled in followup
patches.

Discussion: https://postgr.es/m/4206.1499798337@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2017-10-26 13:47:45 -04:00
parent 08f1e1f0a4
commit 37a795a60b
37 changed files with 1085 additions and 293 deletions

View File

@ -4379,8 +4379,7 @@ SET xmloption TO { DOCUMENT | CONTENT };
underlying type &mdash; for example, any operator or function that
can be applied to the underlying type will work on the domain type.
The underlying type can be any built-in or user-defined base type,
enum type, array or range type, or another domain. (Currently, domains
over composite types are not implemented.)
enum type, array type, composite type, range type, or another domain.
</para>
<para>

View File

@ -84,8 +84,9 @@ CREATE TABLE inventory_item (
restriction of the current implementation: since no constraints are
associated with a composite type, the constraints shown in the table
definition <emphasis>do not apply</emphasis> to values of the composite type
outside the table. (A partial workaround is to use domain
types as members of composite types.)
outside the table. (To work around this, create a domain over the composite
type, and apply the desired constraints as <literal>CHECK</literal>
constraints of the domain.)
</para>
</sect2>

View File

@ -351,6 +351,31 @@ CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$
WHERE accountno = tf1.accountno
RETURNING balance;
$$ LANGUAGE SQL;
</programlisting>
</para>
<para>
A <acronym>SQL</acronym> function must return exactly its declared
result type. This may require inserting an explicit cast.
For example, suppose we wanted the
previous <function>add_em</function> function to return
type <type>float8</type> instead. This won't work:
<programlisting>
CREATE FUNCTION add_em(integer, integer) RETURNS float8 AS $$
SELECT $1 + $2;
$$ LANGUAGE SQL;
</programlisting>
even though in other contexts <productname>PostgreSQL</productname>
would be willing to insert an implicit cast to
convert <type>integer</type> to <type>float8</type>.
We need to write it as
<programlisting>
CREATE FUNCTION add_em(integer, integer) RETURNS float8 AS $$
SELECT ($1 + $2)::float8;
$$ LANGUAGE SQL;
</programlisting>
</para>
</sect2>
@ -452,13 +477,16 @@ $$ LANGUAGE SQL;
</listitem>
<listitem>
<para>
You must typecast the expressions to match the
definition of the composite type, or you will get errors like this:
We must ensure each expression's type matches the corresponding
column of the composite type, inserting a cast if necessary.
Otherwise we'll get errors like this:
<screen>
<computeroutput>
ERROR: function declared to return emp returns varchar instead of text at column 1
</computeroutput>
</screen>
As with the base-type case, the function will not insert any casts
automatically.
</para>
</listitem>
</itemizedlist>
@ -478,6 +506,11 @@ $$ LANGUAGE SQL;
in this situation, but it is a handy alternative in some cases
&mdash; for example, if we need to compute the result by calling
another function that returns the desired composite value.
Another example is that if we are trying to write a function that
returns a domain over composite, rather than a plain composite type,
it is always necessary to write it as returning a single column,
since there is no other way to produce a value that is exactly of
the domain type.
</para>
<para>