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:
@ -4379,8 +4379,7 @@ SET xmloption TO { DOCUMENT | CONTENT };
|
||||
underlying type — 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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
— 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>
|
||||
|
Reference in New Issue
Block a user