From 37a795a60b4f4b1def11c615525ec5e0e9449e05 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 26 Oct 2017 13:47:45 -0400 Subject: 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 " 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 --- doc/src/sgml/datatype.sgml | 3 +-- doc/src/sgml/rowtypes.sgml | 5 +++-- doc/src/sgml/xfunc.sgml | 37 +++++++++++++++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 6 deletions(-) (limited to 'doc/src') diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index b397e188583..3d46098263d 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -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. diff --git a/doc/src/sgml/rowtypes.sgml b/doc/src/sgml/rowtypes.sgml index 7e436a46065..f80d44bc75c 100644 --- a/doc/src/sgml/rowtypes.sgml +++ b/doc/src/sgml/rowtypes.sgml @@ -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 do not apply 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 CHECK + constraints of the domain.) diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index d9fccaa17c6..9bdb72cd989 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -351,6 +351,31 @@ CREATE FUNCTION tf1 (accountno integer, debit numeric) RETURNS numeric AS $$ WHERE accountno = tf1.accountno RETURNING balance; $$ LANGUAGE SQL; + + + + + A SQL function must return exactly its declared + result type. This may require inserting an explicit cast. + For example, suppose we wanted the + previous add_em function to return + type float8 instead. This won't work: + + +CREATE FUNCTION add_em(integer, integer) RETURNS float8 AS $$ + SELECT $1 + $2; +$$ LANGUAGE SQL; + + + even though in other contexts PostgreSQL + would be willing to insert an implicit cast to + convert integer to float8. + We need to write it as + + +CREATE FUNCTION add_em(integer, integer) RETURNS float8 AS $$ + SELECT ($1 + $2)::float8; +$$ LANGUAGE SQL; @@ -452,13 +477,16 @@ $$ LANGUAGE SQL; - 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: ERROR: function declared to return emp returns varchar instead of text at column 1 + As with the base-type case, the function will not insert any casts + automatically. @@ -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. -- cgit v1.2.3