1998-05-09 19:31:34 -04:00
/*-------------------------------------------------------------------------
*
* parse_coerce . c
2000-02-20 16:32:16 -05:00
* handle type coercions / conversions for parser
1998-05-09 19:31:34 -04:00
*
2021-01-02 13:06:25 -05:00
* Portions Copyright ( c ) 1996 - 2021 , PostgreSQL Global Development Group
2000-01-26 00:58:53 -05:00
* Portions Copyright ( c ) 1994 , Regents of the University of California
1998-05-09 19:31:34 -04:00
*
*
* IDENTIFICATION
2010-09-20 16:08:53 -04:00
* src / backend / parser / parse_coerce . c
1998-05-09 19:31:34 -04:00
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
# include "postgres.h"
2002-07-18 19:11:32 -04:00
# include "catalog/pg_cast.h"
2011-01-01 15:44:32 -05:00
# include "catalog/pg_class.h"
2018-04-08 14:35:29 -04:00
# include "catalog/pg_inherits.h"
2000-03-18 19:15:39 -05:00
# include "catalog/pg_proc.h"
2006-07-13 12:49:20 -04:00
# include "catalog/pg_type.h"
2002-03-20 14:45:13 -05:00
# include "nodes/makefuncs.h"
2008-08-25 18:42:34 -04:00
# include "nodes/nodeFuncs.h"
1999-07-16 01:00:38 -04:00
# include "parser/parse_coerce.h"
2004-05-10 18:44:49 -04:00
# include "parser/parse_relation.h"
2000-06-14 23:33:12 -04:00
# include "parser/parse_type.h"
1999-07-16 01:00:38 -04:00
# include "utils/builtins.h"
2020-04-08 00:10:16 -04:00
# include "utils/datum.h" /* needed for datumIsEqual() */
Support subscripting of arbitrary types, not only arrays.
This patch generalizes the subscripting infrastructure so that any
data type can be subscripted, if it provides a handler function to
define what that means. Traditional variable-length (varlena) arrays
all use array_subscript_handler(), while the existing fixed-length
types that support subscripting use raw_array_subscript_handler().
It's expected that other types that want to use subscripting notation
will define their own handlers. (This patch provides no such new
features, though; it only lays the foundation for them.)
To do this, move the parser's semantic processing of subscripts
(including coercion to whatever data type is required) into a
method callback supplied by the handler. On the execution side,
replace the ExecEvalSubscriptingRef* layer of functions with direct
calls to callback-supplied execution routines. (Thus, essentially
no new run-time overhead should be caused by this patch. Indeed,
there is room to remove some overhead by supplying specialized
execution routines. This patch does a little bit in that line,
but more could be done.)
Additional work is required here and there to remove formerly
hard-wired assumptions about the result type, collation, etc
of a SubscriptingRef expression node; and to remove assumptions
that the subscript values must be integers.
One useful side-effect of this is that we now have a less squishy
mechanism for identifying whether a data type is a "true" array:
instead of wiring in weird rules about typlen, we can look to see
if pg_type.typsubscript == F_ARRAY_SUBSCRIPT_HANDLER. For this
to be bulletproof, we have to forbid user-defined types from using
that handler directly; but there seems no good reason for them to
do so.
This patch also removes assumptions that the number of subscripts
is limited to MAXDIM (6), or indeed has any hard-wired limit.
That limit still applies to types handled by array_subscript_handler
or raw_array_subscript_handler, but to discourage other dependencies
on this constant, I've moved it from c.h to utils/array.h.
Dmitry Dolgov, reviewed at various times by Tom Lane, Arthur Zakirov,
Peter Eisentraut, Pavel Stehule
Discussion: https://postgr.es/m/CA+q6zcVDuGBv=M0FqBYX8DPebS3F_0KQ6OVFobGJPM507_SZ_w@mail.gmail.com
Discussion: https://postgr.es/m/CA+q6zcVovR+XY4mfk-7oNk-rF91gH0PebnNfuUjuuDsyHjOcVA@mail.gmail.com
2020-12-09 12:40:37 -05:00
# include "utils/fmgroids.h"
2002-03-20 14:45:13 -05:00
# include "utils/lsyscache.h"
1998-05-09 19:31:34 -04:00
# include "utils/syscache.h"
2004-05-10 18:44:49 -04:00
# include "utils/typcache.h"
1998-05-09 19:31:34 -04:00
2002-03-20 14:45:13 -05:00
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
static Node * coerce_type_typmod ( Node * node ,
2004-06-15 21:27:00 -04:00
Oid targetTypeId , int32 targetTypMod ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
CoercionContext ccontext , CoercionForm cformat ,
int location ,
bool hideInputCoercion ) ;
2004-06-15 21:27:00 -04:00
static void hide_coercion_node ( Node * node ) ;
2007-03-27 19:21:12 -04:00
static Node * build_coercion_expression ( Node * node ,
2007-06-05 17:31:09 -04:00
CoercionPathType pathtype ,
Oid funcId ,
Oid targetTypeId , int32 targetTypMod ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
CoercionContext ccontext , CoercionForm cformat ,
int location ) ;
2004-05-10 18:44:49 -04:00
static Node * coerce_record_to_complex ( ParseState * pstate , Node * node ,
Oid targetTypeId ,
CoercionContext ccontext ,
2008-08-28 19:09:48 -04:00
CoercionForm cformat ,
int location ) ;
2008-10-13 12:25:20 -04:00
static bool is_complex_array ( Oid typid ) ;
2011-01-01 15:44:32 -05:00
static bool typeIsOfTypedTable ( Oid reltypeId , Oid reloftypeId ) ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
/*
* coerce_to_target_type ( )
* Convert an expression to a target type and typmod .
*
* This is the general - purpose entry point for arbitrary type coercion
* operations . Direct use of the component operations can_coerce_type ,
* coerce_type , and coerce_type_typmod should be restricted to special
* cases ( eg , when the conversion is expected to succeed ) .
*
* Returns the possibly - transformed expression tree , or NULL if the type
2003-07-19 16:20:53 -04:00
* conversion is not possible . ( We do this , rather than ereport ' ing directly ,
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
* so that callers can generate custom error messages indicating context . )
*
2003-04-29 18:13:11 -04:00
* pstate - parse state ( can be NULL , see coerce_type )
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
* expr - input expression tree ( already transformed by transformExpr )
* exprtype - result type of expr
* targettype - desired result type
* targettypmod - desired result typmod
* ccontext , cformat - context indicators to control coercions
2008-08-28 19:09:48 -04:00
* location - parse location of the coercion request , or - 1 if unknown / implicit
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
*/
Node *
2003-04-29 18:13:11 -04:00
coerce_to_target_type ( ParseState * pstate , Node * expr , Oid exprtype ,
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
Oid targettype , int32 targettypmod ,
CoercionContext ccontext ,
2008-08-28 19:09:48 -04:00
CoercionForm cformat ,
int location )
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
{
2004-06-15 21:27:00 -04:00
Node * result ;
2012-01-02 14:43:45 -05:00
Node * origexpr ;
2004-06-15 21:27:00 -04:00
if ( ! can_coerce_type ( 1 , & exprtype , & targettype , ccontext ) )
return NULL ;
2012-01-02 14:43:45 -05:00
/*
* If the input has a CollateExpr at the top , strip it off , perform the
* coercion , and put a new one back on . This is annoying since it
* duplicates logic in coerce_type , but if we don ' t do this then it ' s too
* hard to tell whether coerce_type actually changed anything , and we
* * must * know that to avoid possibly calling hide_coercion_node on
* something that wasn ' t generated by coerce_type . Note that if there are
* multiple stacked CollateExprs , we just discard all but the topmost .
2021-04-12 14:37:22 -04:00
* Also , if the target type isn ' t collatable , we discard the CollateExpr .
2012-01-02 14:43:45 -05:00
*/
origexpr = expr ;
while ( expr & & IsA ( expr , CollateExpr ) )
expr = ( Node * ) ( ( CollateExpr * ) expr ) - > arg ;
2004-06-15 21:27:00 -04:00
result = coerce_type ( pstate , expr , exprtype ,
targettype , targettypmod ,
2008-08-28 19:09:48 -04:00
ccontext , cformat , location ) ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
/*
* If the target is a fixed - length type , it may need a length coercion as
2004-06-15 21:27:00 -04:00
* well as a type coercion . If we find ourselves adding both , force the
* inner coercion node to implicit display form .
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
*/
2004-06-15 21:27:00 -04:00
result = coerce_type_typmod ( result ,
targettype , targettypmod ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
ccontext , cformat , location ,
2004-06-15 21:27:00 -04:00
( result ! = expr & & ! IsA ( result , Const ) ) ) ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
2021-04-12 14:37:22 -04:00
if ( expr ! = origexpr & & type_is_collatable ( targettype ) )
2012-01-02 14:43:45 -05:00
{
/* Reinstall top CollateExpr */
CollateExpr * coll = ( CollateExpr * ) origexpr ;
CollateExpr * newcoll = makeNode ( CollateExpr ) ;
newcoll - > arg = ( Expr * ) result ;
newcoll - > collOid = coll - > collOid ;
newcoll - > location = coll - > location ;
result = ( Node * ) newcoll ;
}
2004-06-15 21:27:00 -04:00
return result ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
}
2002-08-31 18:10:48 -04:00
1998-05-09 19:31:34 -04:00
2002-08-31 22:27:32 -04:00
/*
* coerce_type ( )
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
* Convert an expression to a different type .
2002-08-31 22:27:32 -04:00
*
* The caller should already have determined that the coercion is possible ;
* see can_coerce_type .
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
*
2004-06-15 21:27:00 -04:00
* Normally , no coercion to a typmod ( length ) is performed here . The caller
* must call coerce_type_typmod as well , if a typmod constraint is wanted .
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
* ( But if the target type is a domain , it may internally contain a
2003-02-03 16:15:45 -05:00
* typmod constraint , which will be applied inside coerce_to_domain . )
2004-06-15 21:27:00 -04:00
* In some cases pg_cast specifies a type coercion function that also
* applies length conversion , and in those cases only , the result will
* already be properly coerced to the specified typmod .
2003-04-29 18:13:11 -04:00
*
* pstate is only used in the case that we are able to resolve the type of
* a previously UNKNOWN Param . It is okay to pass pstate = NULL if the
* caller does not want type information updated for Params .
2011-03-19 20:29:08 -04:00
*
* Note : this function must not modify the given expression tree , only add
* decoration on top of it . See transformSetOperationTree , for example .
1998-05-09 19:31:34 -04:00
*/
Node *
2003-04-29 18:13:11 -04:00
coerce_type ( ParseState * pstate , Node * node ,
2004-06-15 21:27:00 -04:00
Oid inputTypeId , Oid targetTypeId , int32 targetTypeMod ,
2008-08-28 19:09:48 -04:00
CoercionContext ccontext , CoercionForm cformat , int location )
1998-05-09 19:31:34 -04:00
{
2000-02-20 16:32:16 -05:00
Node * result ;
2007-06-05 17:31:09 -04:00
CoercionPathType pathtype ;
2002-08-31 22:27:32 -04:00
Oid funcId ;
1998-05-09 19:31:34 -04:00
2000-03-23 02:36:03 -05:00
if ( targetTypeId = = inputTypeId | |
node = = NULL )
1999-08-04 22:33:54 -04:00
{
2002-08-31 18:10:48 -04:00
/* no conversion needed */
2003-04-29 18:13:11 -04:00
return node ;
1999-08-04 22:33:54 -04:00
}
2003-12-17 14:49:39 -05:00
if ( targetTypeId = = ANYOID | |
2006-10-11 16:21:04 -04:00
targetTypeId = = ANYELEMENTOID | |
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
targetTypeId = = ANYNONARRAYOID | |
targetTypeId = = ANYCOMPATIBLEOID | |
targetTypeId = = ANYCOMPATIBLENONARRAYOID )
2003-12-17 14:49:39 -05:00
{
2006-10-11 16:21:04 -04:00
/*
* Assume can_coerce_type verified that implicit coercion is okay .
*
* Note : by returning the unmodified node here , we are saying that
* it ' s OK to treat an UNKNOWN constant as a valid input for a
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
* function accepting one of these pseudotypes . This should be all
* right , since an UNKNOWN value is still a perfectly valid Datum .
2006-10-11 16:21:04 -04:00
*
2011-06-08 12:52:12 -04:00
* NB : we do NOT want a RelabelType here : the exposed type of the
* function argument must be its actual type , not the polymorphic
* pseudotype .
2006-10-11 16:21:04 -04:00
*/
2003-12-17 14:49:39 -05:00
return node ;
}
2011-06-08 12:52:12 -04:00
if ( targetTypeId = = ANYARRAYOID | |
2011-11-03 07:16:28 -04:00
targetTypeId = = ANYENUMOID | |
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
targetTypeId = = ANYRANGEOID | |
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
targetTypeId = = ANYMULTIRANGEOID | |
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
targetTypeId = = ANYCOMPATIBLEARRAYOID | |
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
targetTypeId = = ANYCOMPATIBLERANGEOID | |
targetTypeId = = ANYCOMPATIBLEMULTIRANGEOID )
2011-06-08 12:52:12 -04:00
{
/*
* Assume can_coerce_type verified that implicit coercion is okay .
*
* These cases are unlike the ones above because the exposed type of
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
* the argument must be an actual array , enum , range , or multirange
* type . In particular the argument must * not * be an UNKNOWN
* constant . If it is , we just fall through ; below , we ' ll call the
* pseudotype ' s input function , which will produce an error . Also , if
* what we have is a domain over array , enum , range , or multirange , we
* have to relabel it to its base type .
2011-06-08 12:52:12 -04:00
*
* Note : currently , we can ' t actually see a domain - over - enum here ,
* since the other functions in this file will not match such a
* parameter to ANYENUM . But that should get changed eventually .
*/
if ( inputTypeId ! = UNKNOWNOID )
{
Oid baseTypeId = getBaseType ( inputTypeId ) ;
if ( baseTypeId ! = inputTypeId )
{
RelabelType * r = makeRelabelType ( ( Expr * ) node ,
baseTypeId , - 1 ,
InvalidOid ,
cformat ) ;
r - > location = location ;
return ( Node * ) r ;
}
/* Not a domain type, so return it as-is */
return node ;
}
}
2003-04-29 18:13:11 -04:00
if ( inputTypeId = = UNKNOWNOID & & IsA ( node , Const ) )
1999-08-04 22:33:54 -04:00
{
1999-10-02 19:29:19 -04:00
/*
* Input is a string constant with previously undetermined type . Apply
1999-08-04 22:33:54 -04:00
* the target type ' s typinput function to it to produce a constant of
* the target type .
*
* NOTE : this case cannot be folded together with the other
* constant - input case , since the typinput function does not
* necessarily behave the same as a type conversion function . For
* example , int4 ' s typinput function will reject " 1.2 " , whereas
* float - to - int type conversion will round to integer .
1999-10-02 19:29:19 -04:00
*
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
* XXX if the typinput function is not immutable , we really ought to
1999-10-02 19:29:19 -04:00
* postpone evaluation of the function call until runtime . But there
* is no way to represent a typinput function call as an expression
* tree , because C - string values are not Datums . ( XXX This * is *
2002-08-31 18:10:48 -04:00
* possible as of 7.3 , do we want to do it ? )
1998-05-09 19:31:34 -04:00
*/
1999-08-04 22:33:54 -04:00
Const * con = ( Const * ) node ;
1999-08-23 20:09:56 -04:00
Const * newcon = makeNode ( Const ) ;
2006-04-05 18:11:58 -04:00
Oid baseTypeId ;
int32 baseTypeMod ;
2008-09-10 14:29:41 -04:00
int32 inputTypeMod ;
2015-05-02 16:46:23 -04:00
Type baseType ;
2008-09-01 16:42:46 -04:00
ParseCallbackState pcbstate ;
1999-08-04 22:33:54 -04:00
2006-04-05 18:11:58 -04:00
/*
* If the target type is a domain , we want to call its base type ' s
* input routine , not domain_in ( ) . This is to avoid premature failure
* when the domain applies a typmod : existing input routines follow
* implicit - coercion semantics for length checks , which is not always
* what we want here . The needed check will be applied properly
* inside coerce_to_domain ( ) .
*/
2008-09-10 14:29:41 -04:00
baseTypeMod = targetTypeMod ;
2006-04-05 18:11:58 -04:00
baseTypeId = getBaseTypeAndTypmod ( targetTypeId , & baseTypeMod ) ;
2008-09-10 14:29:41 -04:00
/*
* For most types we pass typmod - 1 to the input routine , because
* existing input routines follow implicit - coercion semantics for
* length checks , which is not always what we want here . Any length
* constraint will be applied later by our caller . An exception
* however is the INTERVAL type , for which we * must * pass the typmod
* or it won ' t be able to obey the bizarre SQL - spec input rules . ( Ugly
* as sin , but so is this part of the spec . . . )
*/
if ( baseTypeId = = INTERVALOID )
inputTypeMod = baseTypeMod ;
else
inputTypeMod = - 1 ;
2015-05-02 16:46:23 -04:00
baseType = typeidType ( baseTypeId ) ;
2006-04-05 18:11:58 -04:00
newcon - > consttype = baseTypeId ;
2008-09-10 14:29:41 -04:00
newcon - > consttypmod = inputTypeMod ;
2015-05-02 16:46:23 -04:00
newcon - > constcollid = typeTypeCollation ( baseType ) ;
newcon - > constlen = typeLen ( baseType ) ;
newcon - > constbyval = typeByVal ( baseType ) ;
1999-08-23 20:09:56 -04:00
newcon - > constisnull = con - > constisnull ;
2012-03-27 15:17:00 -04:00
/*
* We use the original literal ' s location regardless of the position
* of the coercion . This is a change from pre - 9.2 behavior , meant to
* simplify life for pg_stat_statements .
*/
newcon - > location = con - > location ;
1999-08-04 22:33:54 -04:00
2008-09-01 16:42:46 -04:00
/*
* Set up to point at the constant ' s text if the input routine throws
* an error .
*/
setup_parser_errposition_callback ( & pcbstate , pstate , con - > location ) ;
2006-04-04 15:35:37 -04:00
/*
* We assume here that UNKNOWN ' s internal representation is the same
* as CSTRING .
*/
1999-08-23 20:09:56 -04:00
if ( ! con - > constisnull )
2015-05-02 16:46:23 -04:00
newcon - > constvalue = stringTypeDatum ( baseType ,
2006-04-04 15:35:37 -04:00
DatumGetCString ( con - > constvalue ) ,
2008-09-10 14:29:41 -04:00
inputTypeMod ) ;
2006-04-04 15:35:37 -04:00
else
2015-05-02 16:46:23 -04:00
newcon - > constvalue = stringTypeDatum ( baseType ,
2008-09-10 14:29:41 -04:00
NULL ,
inputTypeMod ) ;
1998-05-09 19:31:34 -04:00
Add defenses against putting expanded objects into Const nodes.
Putting a reference to an expanded-format value into a Const node would be
a bad idea for a couple of reasons. It'd be possible for the supposedly
immutable Const to change value, if something modified the referenced
variable ... in fact, if the Const's reference were R/W, any function that
has the Const as argument might itself change it at runtime. Also, because
datumIsEqual() is pretty simplistic, the Const might fail to compare equal
to other Consts that it should compare equal to, notably including copies
of itself. This could lead to unexpected planner behavior, such as "could
not find pathkey item to sort" errors or inferior plans.
I have not been able to find any way to get an expanded value into a Const
within the existing core code; but Paul Ramsey was able to trigger the
problem by writing a datatype input function that returns an expanded
value.
The best fix seems to be to establish a rule that varlena values being
placed into Const nodes should be passed through pg_detoast_datum().
That will do nothing (and cost little) in normal cases, but it will flatten
expanded values and thereby avoid the above problems. Also, it will
convert short-header or compressed values into canonical format, which will
avoid possible unexpected lack-of-equality issues for those cases too.
And it provides a last-ditch defense against putting a toasted value into
a Const, which we already knew was dangerous, cf commit 2b0c86b66563cf2f.
(In the light of this discussion, I'm no longer sure that that commit
provided 100% protection against such cases, but this fix should do it.)
The test added in commit 65c3d05e18e7c530 to catch datatype input functions
with unstable results would fail for functions that returned expanded
values; but it seems a bit uncharitable to deem a result unstable just
because it's expressed in expanded form, so revise the coding so that we
check for bitwise equality only after applying pg_detoast_datum(). That's
a sufficient condition anyway given the new rule about detoasting when
forming a Const.
Back-patch to 9.5 where the expanded-object facility was added. It's
possible that this should go back further; but in the absence of clear
evidence that there's any live bug in older branches, I'll refrain for now.
2016-01-21 12:55:59 -05:00
/*
* If it ' s a varlena value , force it to be in non - expanded
* ( non - toasted ) format ; this avoids any possible dependency on
* external values and improves consistency of representation .
*/
if ( ! con - > constisnull & & newcon - > constlen = = - 1 )
newcon - > constvalue =
PointerGetDatum ( PG_DETOAST_DATUM ( newcon - > constvalue ) ) ;
# ifdef RANDOMIZE_ALLOCATED_MEMORY
/*
* For pass - by - reference data types , repeat the conversion to see if
* the input function leaves any uninitialized bytes in the result . We
* can only detect that reliably if RANDOMIZE_ALLOCATED_MEMORY is
* enabled , so we don ' t bother testing otherwise . The reason we don ' t
* want any instability in the input function is that comparison of
* Const nodes relies on bytewise comparison of the datums , so if the
* input function leaves garbage then subexpressions that should be
* identical may not get recognized as such . See pgsql - hackers
* discussion of 2008 - 04 - 04.
*/
if ( ! con - > constisnull & & ! newcon - > constbyval )
{
Datum val2 ;
val2 = stringTypeDatum ( baseType ,
DatumGetCString ( con - > constvalue ) ,
inputTypeMod ) ;
if ( newcon - > constlen = = - 1 )
val2 = PointerGetDatum ( PG_DETOAST_DATUM ( val2 ) ) ;
if ( ! datumIsEqual ( newcon - > constvalue , val2 , false , newcon - > constlen ) )
elog ( WARNING , " type %s has unstable input conversion for \" %s \" " ,
typeTypeName ( baseType ) , DatumGetCString ( con - > constvalue ) ) ;
}
# endif
2008-09-01 16:42:46 -04:00
cancel_parser_errposition_callback ( & pcbstate ) ;
1999-08-23 20:09:56 -04:00
result = ( Node * ) newcon ;
2002-08-31 18:10:48 -04:00
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
/* If target is a domain, apply constraints. */
2006-04-05 18:11:58 -04:00
if ( baseTypeId ! = targetTypeId )
result = coerce_to_domain ( result ,
baseTypeId , baseTypeMod ,
targetTypeId ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
ccontext , cformat , location ,
false ) ;
2002-08-31 18:10:48 -04:00
2015-05-02 16:46:23 -04:00
ReleaseSysCache ( baseType ) ;
2003-04-29 18:13:11 -04:00
return result ;
}
2009-10-30 21:41:31 -04:00
if ( IsA ( node , Param ) & &
pstate ! = NULL & & pstate - > p_coerce_param_hook ! = NULL )
2003-04-29 18:13:11 -04:00
{
/*
2009-10-30 21:41:31 -04:00
* Allow the CoerceParamHook to decide what happens . It can return a
* transformed node ( very possibly the same Param node ) , or return
* NULL to indicate we should proceed with normal coercion .
2003-04-29 18:13:11 -04:00
*/
2017-09-07 12:06:23 -04:00
result = pstate - > p_coerce_param_hook ( pstate ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
( Param * ) node ,
targetTypeId ,
targetTypeMod ,
location ) ;
2009-10-30 21:41:31 -04:00
if ( result )
return result ;
1999-08-04 22:33:54 -04:00
}
2011-03-11 16:27:51 -05:00
if ( IsA ( node , CollateExpr ) )
2011-02-08 16:04:18 -05:00
{
2011-03-11 16:27:51 -05:00
/*
2011-03-19 20:29:08 -04:00
* If we have a COLLATE clause , we have to push the coercion
2021-04-12 14:37:22 -04:00
* underneath the COLLATE ; or discard the COLLATE if the target type
* isn ' t collatable . This is really ugly , but there is little choice
* because the above hacks on Consts and Params wouldn ' t happen
2012-01-02 14:43:45 -05:00
* otherwise . This kluge has consequences in coerce_to_target_type .
2011-03-11 16:27:51 -05:00
*/
2011-03-19 20:29:08 -04:00
CollateExpr * coll = ( CollateExpr * ) node ;
2021-04-12 14:37:22 -04:00
result = coerce_type ( pstate , ( Node * ) coll - > arg ,
inputTypeId , targetTypeId , targetTypeMod ,
ccontext , cformat , location ) ;
if ( type_is_collatable ( targetTypeId ) )
{
CollateExpr * newcoll = makeNode ( CollateExpr ) ;
newcoll - > arg = ( Expr * ) result ;
newcoll - > collOid = coll - > collOid ;
newcoll - > location = coll - > location ;
result = ( Node * ) newcoll ;
}
return result ;
2011-02-08 16:04:18 -05:00
}
2007-06-05 17:31:09 -04:00
pathtype = find_coercion_pathway ( targetTypeId , inputTypeId , ccontext ,
& funcId ) ;
if ( pathtype ! = COERCION_PATH_NONE )
2000-02-20 16:32:16 -05:00
{
2007-06-05 17:31:09 -04:00
if ( pathtype ! = COERCION_PATH_RELABELTYPE )
2002-08-31 22:27:32 -04:00
{
/*
* Generate an expression tree representing run - time application
* of the conversion function . If we are dealing with a domain
* target type , the conversion function will yield the base type ,
2004-11-06 12:46:38 -05:00
* and we need to extract the correct typmod to use from the
* domain ' s typtypmod .
2002-08-31 22:27:32 -04:00
*/
2006-04-05 18:11:58 -04:00
Oid baseTypeId ;
2004-11-06 12:46:38 -05:00
int32 baseTypeMod ;
2006-04-05 18:11:58 -04:00
baseTypeMod = targetTypeMod ;
baseTypeId = getBaseTypeAndTypmod ( targetTypeId , & baseTypeMod ) ;
2002-08-31 22:27:32 -04:00
2007-06-05 17:31:09 -04:00
result = build_coercion_expression ( node , pathtype , funcId ,
2004-11-06 12:46:38 -05:00
baseTypeId , baseTypeMod ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
ccontext , cformat , location ) ;
2002-08-31 22:27:32 -04:00
/*
2003-02-03 16:15:45 -05:00
* If domain , coerce to the domain type and relabel with domain
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
* type ID , hiding the previous coercion node .
2002-08-31 22:27:32 -04:00
*/
if ( targetTypeId ! = baseTypeId )
2006-04-05 18:11:58 -04:00
result = coerce_to_domain ( result , baseTypeId , baseTypeMod ,
targetTypeId ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
ccontext , cformat , location ,
true ) ;
2002-08-31 22:27:32 -04:00
}
else
{
/*
* We don ' t need to do a physical conversion , but we do need to
* attach a RelabelType node so that the expression will be seen
* to have the intended type when inspected by higher - level code .
*
* Also , domains may have value restrictions beyond the base type
2003-02-03 16:15:45 -05:00
* that must be accounted for . If the destination is a domain
* then we won ' t need a RelabelType node .
2002-08-31 22:27:32 -04:00
*/
2006-04-05 18:11:58 -04:00
result = coerce_to_domain ( node , InvalidOid , - 1 , targetTypeId ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
ccontext , cformat , location ,
false ) ;
2003-02-03 16:15:45 -05:00
if ( result = = node )
{
/*
* XXX could we label result with exprTypmod ( node ) instead of
* default - 1 typmod , to save a possible length - coercion
* later ? Would work if both types have same interpretation of
* typmod , which is likely but not certain .
*/
2008-08-28 19:09:48 -04:00
RelabelType * r = makeRelabelType ( ( Expr * ) result ,
targetTypeId , - 1 ,
2011-03-19 20:29:08 -04:00
InvalidOid ,
2008-08-28 19:09:48 -04:00
cformat ) ;
r - > location = location ;
result = ( Node * ) r ;
2003-02-03 16:15:45 -05:00
}
2002-08-31 22:27:32 -04:00
}
2003-04-29 18:13:11 -04:00
return result ;
2000-02-20 16:32:16 -05:00
}
2004-05-10 18:44:49 -04:00
if ( inputTypeId = = RECORDOID & &
ISCOMPLEX ( targetTypeId ) )
{
/* Coerce a RECORD to a specific complex type */
return coerce_record_to_complex ( pstate , node , targetTypeId ,
2008-08-28 19:09:48 -04:00
ccontext , cformat , location ) ;
2004-05-10 18:44:49 -04:00
}
2005-05-04 20:19:47 -04:00
if ( targetTypeId = = RECORDOID & &
ISCOMPLEX ( inputTypeId ) )
{
/* Coerce a specific complex type to RECORD */
/* NB: we do NOT want a RelabelType here */
return node ;
}
2008-10-13 12:25:20 -04:00
# ifdef NOT_USED
if ( inputTypeId = = RECORDARRAYOID & &
is_complex_array ( targetTypeId ) )
{
/* Coerce record[] to a specific complex array type */
/* not implemented yet ... */
}
# endif
if ( targetTypeId = = RECORDARRAYOID & &
is_complex_array ( inputTypeId ) )
{
/* Coerce a specific complex array type to record[] */
/* NB: we do NOT want a RelabelType here */
return node ;
}
2011-01-01 15:44:32 -05:00
if ( typeInheritsFrom ( inputTypeId , targetTypeId )
| | typeIsOfTypedTable ( inputTypeId , targetTypeId ) )
2000-03-16 01:35:07 -05:00
{
2002-03-20 14:45:13 -05:00
/*
2004-12-11 18:26:51 -05:00
* Input class type is a subclass of target , so generate an
* appropriate runtime conversion ( removing unneeded columns and
* possibly rearranging the ones that are wanted ) .
2017-10-26 13:47:45 -04:00
*
* We will also get here when the input is a domain over a subclass of
* the target type . To keep life simple for the executor , we define
* ConvertRowtypeExpr as only working between regular composite types ;
* therefore , in such cases insert a RelabelType to smash the input
* expression down to its base type .
2002-03-20 14:45:13 -05:00
*/
2017-10-26 13:47:45 -04:00
Oid baseTypeId = getBaseType ( inputTypeId ) ;
2004-12-11 18:26:51 -05:00
ConvertRowtypeExpr * r = makeNode ( ConvertRowtypeExpr ) ;
2017-10-26 13:47:45 -04:00
if ( baseTypeId ! = inputTypeId )
{
RelabelType * rt = makeRelabelType ( ( Expr * ) node ,
baseTypeId , - 1 ,
InvalidOid ,
COERCE_IMPLICIT_CAST ) ;
rt - > location = location ;
node = ( Node * ) rt ;
}
2004-12-11 18:26:51 -05:00
r - > arg = ( Expr * ) node ;
r - > resulttype = targetTypeId ;
r - > convertformat = cformat ;
2008-08-28 19:09:48 -04:00
r - > location = location ;
2004-12-11 18:26:51 -05:00
return ( Node * ) r ;
2000-03-16 01:35:07 -05:00
}
2003-04-29 18:13:11 -04:00
/* If we get here, caller blew it */
2003-07-19 16:20:53 -04:00
elog ( ERROR , " failed to find conversion function from %s to %s " ,
2003-04-29 18:13:11 -04:00
format_type_be ( inputTypeId ) , format_type_be ( targetTypeId ) ) ;
return NULL ; /* keep compiler quiet */
1999-05-22 00:12:29 -04:00
}
1998-05-09 19:31:34 -04:00
2002-08-31 22:27:32 -04:00
/*
* can_coerce_type ( )
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
* Can input_typeids be coerced to target_typeids ?
2002-04-11 16:00:18 -04:00
*
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
* We must be told the context ( CAST construct , assignment , implicit coercion )
* as this determines the set of available casts .
1998-05-09 19:31:34 -04:00
*/
bool
2018-10-23 06:17:16 -04:00
can_coerce_type ( int nargs , const Oid * input_typeids , const Oid * target_typeids ,
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
CoercionContext ccontext )
1998-05-09 19:31:34 -04:00
{
2003-04-08 19:20:04 -04:00
bool have_generics = false ;
1998-05-09 19:31:34 -04:00
int i ;
/* run through argument list... */
for ( i = 0 ; i < nargs ; i + + )
{
2000-03-16 01:35:07 -05:00
Oid inputTypeId = input_typeids [ i ] ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
Oid targetTypeId = target_typeids [ i ] ;
2007-06-05 17:31:09 -04:00
CoercionPathType pathtype ;
2002-03-20 14:45:13 -05:00
Oid funcId ;
1998-09-01 00:40:42 -04:00
2000-03-16 01:35:07 -05:00
/* no problem if same type */
if ( inputTypeId = = targetTypeId )
continue ;
1998-05-09 19:31:34 -04:00
2002-08-21 20:01:51 -04:00
/* accept if target is ANY */
if ( targetTypeId = = ANYOID )
continue ;
2007-04-01 23:49:42 -04:00
/* accept if target is polymorphic, for now */
if ( IsPolymorphicType ( targetTypeId ) )
2002-08-21 20:01:51 -04:00
{
2003-04-08 19:20:04 -04:00
have_generics = true ; /* do more checking later */
continue ;
2002-08-21 20:01:51 -04:00
}
2003-12-17 14:49:39 -05:00
/*
* If input is an untyped string constant , assume we can convert it to
2004-06-05 20:41:28 -04:00
* anything .
2003-12-17 14:49:39 -05:00
*/
if ( inputTypeId = = UNKNOWNOID )
continue ;
2002-08-21 20:01:51 -04:00
/*
2002-08-31 22:27:32 -04:00
* If pg_cast shows that we can coerce , accept . This test now covers
* both binary - compatible and coercion - function cases .
2002-08-21 20:01:51 -04:00
*/
2007-06-05 17:31:09 -04:00
pathtype = find_coercion_pathway ( targetTypeId , inputTypeId , ccontext ,
& funcId ) ;
if ( pathtype ! = COERCION_PATH_NONE )
2002-08-21 20:01:51 -04:00
continue ;
2004-05-10 18:44:49 -04:00
/*
* If input is RECORD and target is a composite type , assume we can
* coerce ( may need tighter checking here )
*/
if ( inputTypeId = = RECORDOID & &
ISCOMPLEX ( targetTypeId ) )
continue ;
2005-05-04 20:19:47 -04:00
/*
* If input is a composite type and target is RECORD , accept
*/
if ( targetTypeId = = RECORDOID & &
ISCOMPLEX ( inputTypeId ) )
continue ;
2008-10-13 12:25:20 -04:00
# ifdef NOT_USED /* not implemented yet */
2009-06-11 10:49:15 -04:00
2008-10-13 12:25:20 -04:00
/*
* If input is record [ ] and target is a composite array type , assume
* we can coerce ( may need tighter checking here )
*/
if ( inputTypeId = = RECORDARRAYOID & &
is_complex_array ( targetTypeId ) )
continue ;
# endif
/*
* If input is a composite array type and target is record [ ] , accept
*/
if ( targetTypeId = = RECORDARRAYOID & &
is_complex_array ( inputTypeId ) )
continue ;
2000-03-16 01:35:07 -05:00
/*
2002-08-31 22:27:32 -04:00
* If input is a class type that inherits from target , accept
2000-03-16 01:35:07 -05:00
*/
2011-01-01 15:44:32 -05:00
if ( typeInheritsFrom ( inputTypeId , targetTypeId )
| | typeIsOfTypedTable ( inputTypeId , targetTypeId ) )
2000-03-16 01:35:07 -05:00
continue ;
/*
2002-08-31 22:27:32 -04:00
* Else , cannot coerce at this argument position
2000-03-16 01:35:07 -05:00
*/
2002-08-31 22:27:32 -04:00
return false ;
1998-05-09 19:31:34 -04:00
}
2003-04-08 19:20:04 -04:00
/* If we found any generic argument types, cross-check them */
if ( have_generics )
{
if ( ! check_generic_type_consistency ( input_typeids , target_typeids ,
nargs ) )
return false ;
}
1998-05-09 19:31:34 -04:00
return true ;
1999-05-22 00:12:29 -04:00
}
1998-05-09 19:31:34 -04:00
2002-08-31 22:27:32 -04:00
/*
2003-02-03 16:15:45 -05:00
* Create an expression tree to represent coercion to a domain type .
*
* ' arg ' : input expression
* ' baseTypeId ' : base type of domain , if known ( pass InvalidOid if caller
* has not bothered to look this up )
2006-04-05 18:11:58 -04:00
* ' baseTypeMod ' : base type typmod of domain , if known ( pass - 1 if caller
* has not bothered to look this up )
2003-02-03 16:15:45 -05:00
* ' typeId ' : target type to coerce to
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
* ' ccontext ' : context indicator to control coercions
* ' cformat ' : coercion display format
2008-08-28 19:09:48 -04:00
* ' location ' : coercion request location
2004-06-15 21:27:00 -04:00
* ' hideInputCoercion ' : if true , hide the input coercion under this one .
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
*
2003-02-03 16:15:45 -05:00
* If the target type isn ' t a domain , the given ' arg ' is returned as - is .
2002-08-31 22:27:32 -04:00
*/
Node *
2006-04-05 18:11:58 -04:00
coerce_to_domain ( Node * arg , Oid baseTypeId , int32 baseTypeMod , Oid typeId ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
CoercionContext ccontext , CoercionForm cformat , int location ,
bool hideInputCoercion )
2002-08-31 22:27:32 -04:00
{
2003-02-03 16:15:45 -05:00
CoerceToDomain * result ;
2002-08-31 22:27:32 -04:00
2003-02-03 16:15:45 -05:00
/* Get the base type if it hasn't been supplied */
if ( baseTypeId = = InvalidOid )
2006-04-05 18:11:58 -04:00
baseTypeId = getBaseTypeAndTypmod ( typeId , & baseTypeMod ) ;
2002-08-31 22:27:32 -04:00
2003-02-03 16:15:45 -05:00
/* If it isn't a domain, return the node as it was passed in */
if ( baseTypeId = = typeId )
return arg ;
2002-08-31 22:27:32 -04:00
2004-06-15 21:27:00 -04:00
/* Suppress display of nested coercion steps */
if ( hideInputCoercion )
hide_coercion_node ( arg ) ;
2002-08-31 22:27:32 -04:00
/*
2003-02-03 16:15:45 -05:00
* If the domain applies a typmod to its base type , build the appropriate
* coercion step . Mark it implicit for display purposes , because we don ' t
* want it shown separately by ruleutils . c ; but the isExplicit flag passed
* to the conversion function depends on the manner in which the domain
* coercion is invoked , so that the semantics of implicit and explicit
* coercion differ . ( Is that really the behavior we want ? )
*
* NOTE : because we apply this as part of the fixed expression structure ,
* ALTER DOMAIN cannot alter the typtypmod . But it ' s unclear that that
* would be safe to do anyway , without lots of knowledge about what the
* base type thinks the typmod means .
2002-08-31 22:27:32 -04:00
*/
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
arg = coerce_type_typmod ( arg , baseTypeId , baseTypeMod ,
ccontext , COERCE_IMPLICIT_CAST , location ,
false ) ;
2002-08-31 22:27:32 -04:00
/*
2003-02-03 16:15:45 -05:00
* Now build the domain coercion node . This represents run - time checking
* of any constraints currently attached to the domain . This also ensures
* that the expression is properly labeled as to result type .
2002-08-31 22:27:32 -04:00
*/
2003-02-03 16:15:45 -05:00
result = makeNode ( CoerceToDomain ) ;
result - > arg = ( Expr * ) arg ;
result - > resulttype = typeId ;
result - > resulttypmod = - 1 ; /* currently, always -1 for domains */
2011-03-19 20:29:08 -04:00
/* resultcollid will be set by parse_collate.c */
2003-02-03 16:15:45 -05:00
result - > coercionformat = cformat ;
2008-08-28 19:09:48 -04:00
result - > location = location ;
2002-08-31 22:27:32 -04:00
2003-02-03 16:15:45 -05:00
return ( Node * ) result ;
2002-08-31 22:27:32 -04:00
}
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
/*
* coerce_type_typmod ( )
* Force a value to a particular typmod , if meaningful and possible .
2000-01-16 19:14:49 -05:00
*
* This is applied to values that are going to be stored in a relation
* ( where we have an atttypmod for the column ) as well as values being
* explicitly CASTed ( where the typmod comes from the target type spec ) .
*
* The caller must have already ensured that the value is of the correct
* type , typically by applying coerce_type .
*
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
* ccontext may affect semantics , depending on whether the length coercion
* function pays attention to the isExplicit flag it ' s passed .
*
* cformat determines the display properties of the generated node ( if any ) .
*
* If hideInputCoercion is true * and * we generate a node , the input node is
* forced to IMPLICIT display form , so that only the typmod coercion node will
* be visible when displaying the expression .
2004-06-15 21:27:00 -04:00
*
2002-08-31 18:10:48 -04:00
* NOTE : this does not need to work on domain types , because any typmod
* coercion for a domain is considered to be part of the type coercion
2002-08-31 22:27:32 -04:00
* needed to produce the domain value in the first place . So , no getBaseType .
2000-01-16 19:14:49 -05:00
*/
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
static Node *
coerce_type_typmod ( Node * node , Oid targetTypeId , int32 targetTypMod ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
CoercionContext ccontext , CoercionForm cformat ,
int location ,
bool hideInputCoercion )
2000-01-16 19:14:49 -05:00
{
2007-06-05 17:31:09 -04:00
CoercionPathType pathtype ;
2002-03-20 14:45:13 -05:00
Oid funcId ;
2000-01-16 19:14:49 -05:00
Don't elide casting to typmod -1.
Casting a value that's already of a type with a specific typmod
to an unspecified typmod doesn't do anything so far as run-time
behavior is concerned. However, it really ought to change the
exposed type of the expression to match. Up to now,
coerce_type_typmod hasn't bothered with that, which creates gotchas
in contexts such as recursive unions. If for example one side of
the union is numeric(18,3), but it needs to be plain numeric to
match the other side, there's no direct way to express that.
This is easy enough to fix, by inserting a RelabelType to update the
exposed type of the expression. However, it's a bit nervous-making
to change this behavior, because it's stood for a really long time.
(I strongly suspect that it's like this in part because the logic
pre-dates the introduction of RelabelType in 7.0. The commit log
message for 57b30e8e2 is interesting reading here.) As a compromise,
we'll sneak the change into 14beta3, and consider back-patching to
stable branches if no complaints emerge in the next three months.
Discussion: https://postgr.es/m/CABNQVagu3bZGqiTjb31a8D5Od3fUMs7Oh3gmZMQZVHZ=uWWWfQ@mail.gmail.com
2021-08-06 17:32:54 -04:00
/* Skip coercion if already done */
if ( targetTypMod = = exprTypmod ( node ) )
2000-01-16 19:14:49 -05:00
return node ;
Don't elide casting to typmod -1.
Casting a value that's already of a type with a specific typmod
to an unspecified typmod doesn't do anything so far as run-time
behavior is concerned. However, it really ought to change the
exposed type of the expression to match. Up to now,
coerce_type_typmod hasn't bothered with that, which creates gotchas
in contexts such as recursive unions. If for example one side of
the union is numeric(18,3), but it needs to be plain numeric to
match the other side, there's no direct way to express that.
This is easy enough to fix, by inserting a RelabelType to update the
exposed type of the expression. However, it's a bit nervous-making
to change this behavior, because it's stood for a really long time.
(I strongly suspect that it's like this in part because the logic
pre-dates the introduction of RelabelType in 7.0. The commit log
message for 57b30e8e2 is interesting reading here.) As a compromise,
we'll sneak the change into 14beta3, and consider back-patching to
stable branches if no complaints emerge in the next three months.
Discussion: https://postgr.es/m/CABNQVagu3bZGqiTjb31a8D5Od3fUMs7Oh3gmZMQZVHZ=uWWWfQ@mail.gmail.com
2021-08-06 17:32:54 -04:00
/* Suppress display of nested coercion steps */
if ( hideInputCoercion )
hide_coercion_node ( node ) ;
2021-12-16 15:36:02 -05:00
/*
* A negative typmod means that no actual coercion is needed , but we still
* want a RelabelType to ensure that the expression exposes the intended
* typmod .
*/
if ( targetTypMod < 0 )
pathtype = COERCION_PATH_NONE ;
else
pathtype = find_typmod_coercion_function ( targetTypeId , & funcId ) ;
2007-06-05 17:31:09 -04:00
if ( pathtype ! = COERCION_PATH_NONE )
2000-01-16 19:14:49 -05:00
{
2007-06-05 17:31:09 -04:00
node = build_coercion_expression ( node , pathtype , funcId ,
2004-06-15 21:27:00 -04:00
targetTypeId , targetTypMod ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
ccontext , cformat , location ) ;
2004-06-15 21:27:00 -04:00
}
Don't elide casting to typmod -1.
Casting a value that's already of a type with a specific typmod
to an unspecified typmod doesn't do anything so far as run-time
behavior is concerned. However, it really ought to change the
exposed type of the expression to match. Up to now,
coerce_type_typmod hasn't bothered with that, which creates gotchas
in contexts such as recursive unions. If for example one side of
the union is numeric(18,3), but it needs to be plain numeric to
match the other side, there's no direct way to express that.
This is easy enough to fix, by inserting a RelabelType to update the
exposed type of the expression. However, it's a bit nervous-making
to change this behavior, because it's stood for a really long time.
(I strongly suspect that it's like this in part because the logic
pre-dates the introduction of RelabelType in 7.0. The commit log
message for 57b30e8e2 is interesting reading here.) As a compromise,
we'll sneak the change into 14beta3, and consider back-patching to
stable branches if no complaints emerge in the next three months.
Discussion: https://postgr.es/m/CABNQVagu3bZGqiTjb31a8D5Od3fUMs7Oh3gmZMQZVHZ=uWWWfQ@mail.gmail.com
2021-08-06 17:32:54 -04:00
else
{
/*
* We don ' t need to perform any actual coercion step , but we should
* apply a RelabelType to ensure that the expression exposes the
* intended typmod .
*/
node = applyRelabelType ( node , targetTypeId , targetTypMod ,
exprCollation ( node ) ,
cformat , location , false ) ;
}
2000-01-16 19:14:49 -05:00
2004-06-15 21:27:00 -04:00
return node ;
}
/*
* Mark a coercion node as IMPLICIT so it will never be displayed by
* ruleutils . c . We use this when we generate a nest of coercion nodes
* to implement what is logically one conversion ; the inner nodes are
* forced to IMPLICIT_CAST format . This does not change their semantics ,
* only display behavior .
*
* It is caller error to call this on something that doesn ' t have a
* CoercionForm field .
*/
static void
hide_coercion_node ( Node * node )
{
if ( IsA ( node , FuncExpr ) )
( ( FuncExpr * ) node ) - > funcformat = COERCE_IMPLICIT_CAST ;
else if ( IsA ( node , RelabelType ) )
( ( RelabelType * ) node ) - > relabelformat = COERCE_IMPLICIT_CAST ;
2007-06-05 17:31:09 -04:00
else if ( IsA ( node , CoerceViaIO ) )
( ( CoerceViaIO * ) node ) - > coerceformat = COERCE_IMPLICIT_CAST ;
2007-03-27 19:21:12 -04:00
else if ( IsA ( node , ArrayCoerceExpr ) )
( ( ArrayCoerceExpr * ) node ) - > coerceformat = COERCE_IMPLICIT_CAST ;
2004-12-11 18:26:51 -05:00
else if ( IsA ( node , ConvertRowtypeExpr ) )
( ( ConvertRowtypeExpr * ) node ) - > convertformat = COERCE_IMPLICIT_CAST ;
2004-06-15 21:27:00 -04:00
else if ( IsA ( node , RowExpr ) )
( ( RowExpr * ) node ) - > row_format = COERCE_IMPLICIT_CAST ;
else if ( IsA ( node , CoerceToDomain ) )
( ( CoerceToDomain * ) node ) - > coercionformat = COERCE_IMPLICIT_CAST ;
else
elog ( ERROR , " unsupported node type: %d " , ( int ) nodeTag ( node ) ) ;
}
/*
* build_coercion_expression ( )
2007-03-27 19:21:12 -04:00
* Construct an expression tree for applying a pg_cast entry .
2004-06-15 21:27:00 -04:00
*
2007-03-27 19:21:12 -04:00
* This is used for both type - coercion and length - coercion operations ,
2004-06-15 21:27:00 -04:00
* since there is no difference in terms of the calling convention .
*/
static Node *
2007-03-27 19:21:12 -04:00
build_coercion_expression ( Node * node ,
2007-06-05 17:31:09 -04:00
CoercionPathType pathtype ,
Oid funcId ,
2004-06-15 21:27:00 -04:00
Oid targetTypeId , int32 targetTypMod ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
CoercionContext ccontext , CoercionForm cformat ,
int location )
2004-06-15 21:27:00 -04:00
{
2007-03-27 19:21:12 -04:00
int nargs = 0 ;
2004-06-15 21:27:00 -04:00
2007-03-27 19:21:12 -04:00
if ( OidIsValid ( funcId ) )
{
HeapTuple tp ;
Form_pg_proc procstruct ;
2004-06-15 21:27:00 -04:00
2010-02-14 13:42:19 -05:00
tp = SearchSysCache1 ( PROCOID , ObjectIdGetDatum ( funcId ) ) ;
2007-03-27 19:21:12 -04:00
if ( ! HeapTupleIsValid ( tp ) )
elog ( ERROR , " cache lookup failed for function %u " , funcId ) ;
procstruct = ( Form_pg_proc ) GETSTRUCT ( tp ) ;
2004-06-15 21:27:00 -04:00
2007-03-27 19:21:12 -04:00
/*
* These Asserts essentially check that function is a legal coercion
* function . We can ' t make the seemingly obvious tests on prorettype
2007-06-05 17:31:09 -04:00
* and proargtypes [ 0 ] , even in the COERCION_PATH_FUNC case , because of
2007-03-27 19:21:12 -04:00
* various binary - compatibility cases .
*/
/* Assert(targetTypeId == procstruct->prorettype); */
Assert ( ! procstruct - > proretset ) ;
2018-03-02 08:57:38 -05:00
Assert ( procstruct - > prokind = = PROKIND_FUNCTION ) ;
2007-03-27 19:21:12 -04:00
nargs = procstruct - > pronargs ;
Assert ( nargs > = 1 & & nargs < = 3 ) ;
/* Assert(procstruct->proargtypes.values[0] == exprType(node)); */
Assert ( nargs < 2 | | procstruct - > proargtypes . values [ 1 ] = = INT4OID ) ;
Assert ( nargs < 3 | | procstruct - > proargtypes . values [ 2 ] = = BOOLOID ) ;
ReleaseSysCache ( tp ) ;
2004-06-15 21:27:00 -04:00
}
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
2007-06-05 17:31:09 -04:00
if ( pathtype = = COERCION_PATH_FUNC )
2007-03-27 19:21:12 -04:00
{
/* We build an ordinary FuncExpr with special arguments */
2008-08-28 19:09:48 -04:00
FuncExpr * fexpr ;
2007-03-27 19:21:12 -04:00
List * args ;
Const * cons ;
Assert ( OidIsValid ( funcId ) ) ;
args = list_make1 ( node ) ;
2000-01-16 19:14:49 -05:00
2007-03-27 19:21:12 -04:00
if ( nargs > = 2 )
{
/* Pass target typmod as an int4 constant */
cons = makeConst ( INT4OID ,
- 1 ,
2011-03-25 20:10:42 -04:00
InvalidOid ,
2007-03-27 19:21:12 -04:00
sizeof ( int32 ) ,
Int32GetDatum ( targetTypMod ) ,
false ,
true ) ;
args = lappend ( args , cons ) ;
}
if ( nargs = = 3 )
{
/* Pass it a boolean isExplicit parameter, too */
cons = makeConst ( BOOLOID ,
- 1 ,
2011-03-25 20:10:42 -04:00
InvalidOid ,
2007-03-27 19:21:12 -04:00
sizeof ( bool ) ,
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
BoolGetDatum ( ccontext = = COERCION_EXPLICIT ) ,
2007-03-27 19:21:12 -04:00
false ,
true ) ;
args = lappend ( args , cons ) ;
}
2011-03-19 20:29:08 -04:00
fexpr = makeFuncExpr ( funcId , targetTypeId , args ,
InvalidOid , InvalidOid , cformat ) ;
2008-08-28 19:09:48 -04:00
fexpr - > location = location ;
return ( Node * ) fexpr ;
2007-03-27 19:21:12 -04:00
}
2007-06-05 17:31:09 -04:00
else if ( pathtype = = COERCION_PATH_ARRAYCOERCE )
{
/* We need to build an ArrayCoerceExpr */
ArrayCoerceExpr * acoerce = makeNode ( ArrayCoerceExpr ) ;
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
CaseTestExpr * ctest = makeNode ( CaseTestExpr ) ;
Oid sourceBaseTypeId ;
int32 sourceBaseTypeMod ;
Oid targetElementType ;
Node * elemexpr ;
/*
* Look through any domain over the source array type . Note we don ' t
* expect that the target type is a domain ; it must be a plain array .
* ( To get to a domain target type , we ' ll do coerce_to_domain later . )
*/
sourceBaseTypeMod = exprTypmod ( node ) ;
sourceBaseTypeId = getBaseTypeAndTypmod ( exprType ( node ) ,
& sourceBaseTypeMod ) ;
2018-10-30 15:26:11 -04:00
/*
* Set up a CaseTestExpr representing one element of the source array .
* This is an abuse of CaseTestExpr , but it ' s OK as long as there
* can ' t be any CaseExpr or ArrayCoerceExpr within the completed
* elemexpr .
*/
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
ctest - > typeId = get_element_type ( sourceBaseTypeId ) ;
Assert ( OidIsValid ( ctest - > typeId ) ) ;
ctest - > typeMod = sourceBaseTypeMod ;
ctest - > collation = InvalidOid ; /* Assume coercions don't care */
/* And coerce it to the target element type */
targetElementType = get_element_type ( targetTypeId ) ;
Assert ( OidIsValid ( targetElementType ) ) ;
elemexpr = coerce_to_target_type ( NULL ,
( Node * ) ctest ,
ctest - > typeId ,
targetElementType ,
targetTypMod ,
ccontext ,
cformat ,
location ) ;
if ( elemexpr = = NULL ) /* shouldn't happen */
elog ( ERROR , " failed to coerce array element type as expected " ) ;
2007-06-05 17:31:09 -04:00
acoerce - > arg = ( Expr * ) node ;
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
acoerce - > elemexpr = ( Expr * ) elemexpr ;
2007-06-05 17:31:09 -04:00
acoerce - > resulttype = targetTypeId ;
2007-11-15 16:14:46 -05:00
2007-06-05 17:31:09 -04:00
/*
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
* Label the output as having a particular element typmod only if we
* ended up with a per - element expression that is labeled that way .
2007-06-05 17:31:09 -04:00
*/
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
acoerce - > resulttypmod = exprTypmod ( elemexpr ) ;
2011-03-26 14:25:48 -04:00
/* resultcollid will be set by parse_collate.c */
2007-06-05 17:31:09 -04:00
acoerce - > coerceformat = cformat ;
2008-08-28 19:09:48 -04:00
acoerce - > location = location ;
2007-06-05 17:31:09 -04:00
return ( Node * ) acoerce ;
}
else if ( pathtype = = COERCION_PATH_COERCEVIAIO )
{
/* We need to build a CoerceViaIO node */
CoerceViaIO * iocoerce = makeNode ( CoerceViaIO ) ;
Assert ( ! OidIsValid ( funcId ) ) ;
iocoerce - > arg = ( Expr * ) node ;
iocoerce - > resulttype = targetTypeId ;
2011-03-26 14:25:48 -04:00
/* resultcollid will be set by parse_collate.c */
2007-06-05 17:31:09 -04:00
iocoerce - > coerceformat = cformat ;
2008-08-28 19:09:48 -04:00
iocoerce - > location = location ;
2007-06-05 17:31:09 -04:00
return ( Node * ) iocoerce ;
}
else
{
elog ( ERROR , " unsupported pathtype %d in build_coercion_expression " ,
( int ) pathtype ) ;
return NULL ; /* keep compiler quiet */
}
2000-01-16 19:14:49 -05:00
}
2004-06-15 21:27:00 -04:00
2004-05-10 18:44:49 -04:00
/*
* coerce_record_to_complex
* Coerce a RECORD to a specific composite type .
*
* Currently we only support this for inputs that are RowExprs or whole - row
* Vars .
*/
static Node *
coerce_record_to_complex ( ParseState * pstate , Node * node ,
Oid targetTypeId ,
CoercionContext ccontext ,
2008-08-28 19:09:48 -04:00
CoercionForm cformat ,
int location )
2004-05-10 18:44:49 -04:00
{
RowExpr * rowexpr ;
2017-10-26 13:47:45 -04:00
Oid baseTypeId ;
int32 baseTypeMod = - 1 ;
2004-05-10 18:44:49 -04:00
TupleDesc tupdesc ;
List * args = NIL ;
List * newargs ;
int i ;
2004-08-17 14:47:09 -04:00
int ucolno ;
2004-05-26 00:41:50 -04:00
ListCell * arg ;
2004-05-10 18:44:49 -04:00
if ( node & & IsA ( node , RowExpr ) )
{
2004-08-17 14:47:09 -04:00
/*
* Since the RowExpr must be of type RECORD , we needn ' t worry about it
* containing any dropped columns .
*/
2004-05-10 18:44:49 -04:00
args = ( ( RowExpr * ) node ) - > args ;
}
else if ( node & & IsA ( node , Var ) & &
( ( Var * ) node ) - > varattno = = InvalidAttrNumber )
{
2004-08-19 16:57:41 -04:00
int rtindex = ( ( Var * ) node ) - > varno ;
int sublevels_up = ( ( Var * ) node ) - > varlevelsup ;
2008-09-01 16:42:46 -04:00
int vlocation = ( ( Var * ) node ) - > location ;
Make parser rely more heavily on the ParseNamespaceItem data structure.
When I added the ParseNamespaceItem data structure (in commit 5ebaaa494),
it wasn't very tightly integrated into the parser's APIs. In the wake of
adding p_rtindex to that struct (commit b541e9acc), there is a good reason
to make more use of it: by passing around ParseNamespaceItem pointers
instead of bare RTE pointers, we can get rid of various messy methods for
passing back or deducing the rangetable index of an RTE during parsing.
Hence, refactor the addRangeTableEntryXXX functions to build and return
a ParseNamespaceItem struct, not just the RTE proper; and replace
addRTEtoQuery with addNSItemToQuery, which is passed a ParseNamespaceItem
rather than building one internally.
Also, add per-column data (a ParseNamespaceColumn array) to each
ParseNamespaceItem. These arrays are built during addRangeTableEntryXXX,
where we have column type data at hand so that it's nearly free to fill
the data structure. Later, when we need to build Vars referencing RTEs,
we can use the ParseNamespaceColumn info to avoid the rather expensive
operations done in get_rte_attribute_type() or expandRTE().
get_rte_attribute_type() is indeed dead code now, so I've removed it.
This makes for a useful improvement in parse analysis speed, around 20%
in one moderately-complex test query.
The ParseNamespaceColumn structs also include Var identity information
(varno/varattno). That info isn't actually being used in this patch,
except that p_varno == 0 is a handy test for a dropped column.
A follow-on patch will make more use of it.
Discussion: https://postgr.es/m/2461.1577764221@sss.pgh.pa.us
2020-01-02 11:29:01 -05:00
ParseNamespaceItem * nsitem ;
2004-08-19 16:57:41 -04:00
Make parser rely more heavily on the ParseNamespaceItem data structure.
When I added the ParseNamespaceItem data structure (in commit 5ebaaa494),
it wasn't very tightly integrated into the parser's APIs. In the wake of
adding p_rtindex to that struct (commit b541e9acc), there is a good reason
to make more use of it: by passing around ParseNamespaceItem pointers
instead of bare RTE pointers, we can get rid of various messy methods for
passing back or deducing the rangetable index of an RTE during parsing.
Hence, refactor the addRangeTableEntryXXX functions to build and return
a ParseNamespaceItem struct, not just the RTE proper; and replace
addRTEtoQuery with addNSItemToQuery, which is passed a ParseNamespaceItem
rather than building one internally.
Also, add per-column data (a ParseNamespaceColumn array) to each
ParseNamespaceItem. These arrays are built during addRangeTableEntryXXX,
where we have column type data at hand so that it's nearly free to fill
the data structure. Later, when we need to build Vars referencing RTEs,
we can use the ParseNamespaceColumn info to avoid the rather expensive
operations done in get_rte_attribute_type() or expandRTE().
get_rte_attribute_type() is indeed dead code now, so I've removed it.
This makes for a useful improvement in parse analysis speed, around 20%
in one moderately-complex test query.
The ParseNamespaceColumn structs also include Var identity information
(varno/varattno). That info isn't actually being used in this patch,
except that p_varno == 0 is a handy test for a dropped column.
A follow-on patch will make more use of it.
Discussion: https://postgr.es/m/2461.1577764221@sss.pgh.pa.us
2020-01-02 11:29:01 -05:00
nsitem = GetNSItemByRangeTablePosn ( pstate , rtindex , sublevels_up ) ;
args = expandNSItemVars ( nsitem , sublevels_up , vlocation , NULL ) ;
2004-05-10 18:44:49 -04:00
}
else
ereport ( ERROR ,
( errcode ( ERRCODE_CANNOT_COERCE ) ,
errmsg ( " cannot cast type %s to %s " ,
format_type_be ( RECORDOID ) ,
2008-08-28 19:09:48 -04:00
format_type_be ( targetTypeId ) ) ,
parser_coercion_errposition ( pstate , location , node ) ) ) ;
2004-05-10 18:44:49 -04:00
2017-10-26 13:47:45 -04:00
/*
* Look up the composite type , accounting for possibility that what we are
* given is a domain over composite .
*/
baseTypeId = getBaseTypeAndTypmod ( targetTypeId , & baseTypeMod ) ;
tupdesc = lookup_rowtype_tupdesc ( baseTypeId , baseTypeMod ) ;
/* Process the fields */
2004-05-10 18:44:49 -04:00
newargs = NIL ;
2004-08-17 14:47:09 -04:00
ucolno = 1 ;
arg = list_head ( args ) ;
for ( i = 0 ; i < tupdesc - > natts ; i + + )
2004-05-10 18:44:49 -04:00
{
2004-08-17 14:47:09 -04:00
Node * expr ;
2008-08-28 19:09:48 -04:00
Node * cexpr ;
2004-08-17 14:47:09 -04:00
Oid exprtype ;
2017-08-20 14:19:07 -04:00
Form_pg_attribute attr = TupleDescAttr ( tupdesc , i ) ;
2004-08-17 14:47:09 -04:00
/* Fill in NULLs for dropped columns in rowtype */
2017-08-20 14:19:07 -04:00
if ( attr - > attisdropped )
2004-08-17 14:47:09 -04:00
{
/*
* can ' t use atttypid here , but it doesn ' t really matter what type
* the Const claims to be .
*/
2011-03-25 20:10:42 -04:00
newargs = lappend ( newargs ,
makeNullConst ( INT4OID , - 1 , InvalidOid ) ) ;
2004-08-17 14:47:09 -04:00
continue ;
}
if ( arg = = NULL )
ereport ( ERROR ,
( errcode ( ERRCODE_CANNOT_COERCE ) ,
errmsg ( " cannot cast type %s to %s " ,
format_type_be ( RECORDOID ) ,
format_type_be ( targetTypeId ) ) ,
2008-08-28 19:09:48 -04:00
errdetail ( " Input has too few columns. " ) ,
parser_coercion_errposition ( pstate , location , node ) ) ) ;
2004-08-17 14:47:09 -04:00
expr = ( Node * ) lfirst ( arg ) ;
exprtype = exprType ( expr ) ;
2004-05-10 18:44:49 -04:00
2008-08-28 19:09:48 -04:00
cexpr = coerce_to_target_type ( pstate ,
expr , exprtype ,
2017-08-20 14:19:07 -04:00
attr - > atttypid ,
attr - > atttypmod ,
2008-08-28 19:09:48 -04:00
ccontext ,
COERCE_IMPLICIT_CAST ,
- 1 ) ;
if ( cexpr = = NULL )
2004-05-10 18:44:49 -04:00
ereport ( ERROR ,
( errcode ( ERRCODE_CANNOT_COERCE ) ,
errmsg ( " cannot cast type %s to %s " ,
format_type_be ( RECORDOID ) ,
format_type_be ( targetTypeId ) ) ,
errdetail ( " Cannot cast type %s to %s in column %d. " ,
format_type_be ( exprtype ) ,
2017-08-20 14:19:07 -04:00
format_type_be ( attr - > atttypid ) ,
2008-08-28 19:09:48 -04:00
ucolno ) ,
parser_coercion_errposition ( pstate , location , expr ) ) ) ;
newargs = lappend ( newargs , cexpr ) ;
2004-08-17 14:47:09 -04:00
ucolno + + ;
Represent Lists as expansible arrays, not chains of cons-cells.
Originally, Postgres Lists were a more or less exact reimplementation of
Lisp lists, which consist of chains of separately-allocated cons cells,
each having a value and a next-cell link. We'd hacked that once before
(commit d0b4399d8) to add a separate List header, but the data was still
in cons cells. That makes some operations -- notably list_nth() -- O(N),
and it's bulky because of the next-cell pointers and per-cell palloc
overhead, and it's very cache-unfriendly if the cons cells end up
scattered around rather than being adjacent.
In this rewrite, we still have List headers, but the data is in a
resizable array of values, with no next-cell links. Now we need at
most two palloc's per List, and often only one, since we can allocate
some values in the same palloc call as the List header. (Of course,
extending an existing List may require repalloc's to enlarge the array.
But this involves just O(log N) allocations not O(N).)
Of course this is not without downsides. The key difficulty is that
addition or deletion of a list entry may now cause other entries to
move, which it did not before.
For example, that breaks foreach() and sister macros, which historically
used a pointer to the current cons-cell as loop state. We can repair
those macros transparently by making their actual loop state be an
integer list index; the exposed "ListCell *" pointer is no longer state
carried across loop iterations, but is just a derived value. (In
practice, modern compilers can optimize things back to having just one
loop state value, at least for simple cases with inline loop bodies.)
In principle, this is a semantics change for cases where the loop body
inserts or deletes list entries ahead of the current loop index; but
I found no such cases in the Postgres code.
The change is not at all transparent for code that doesn't use foreach()
but chases lists "by hand" using lnext(). The largest share of such
code in the backend is in loops that were maintaining "prev" and "next"
variables in addition to the current-cell pointer, in order to delete
list cells efficiently using list_delete_cell(). However, we no longer
need a previous-cell pointer to delete a list cell efficiently. Keeping
a next-cell pointer doesn't work, as explained above, but we can improve
matters by changing such code to use a regular foreach() loop and then
using the new macro foreach_delete_current() to delete the current cell.
(This macro knows how to update the associated foreach loop's state so
that no cells will be missed in the traversal.)
There remains a nontrivial risk of code assuming that a ListCell *
pointer will remain good over an operation that could now move the list
contents. To help catch such errors, list.c can be compiled with a new
define symbol DEBUG_LIST_MEMORY_USAGE that forcibly moves list contents
whenever that could possibly happen. This makes list operations
significantly more expensive so it's not normally turned on (though it
is on by default if USE_VALGRIND is on).
There are two notable API differences from the previous code:
* lnext() now requires the List's header pointer in addition to the
current cell's address.
* list_delete_cell() no longer requires a previous-cell argument.
These changes are somewhat unfortunate, but on the other hand code using
either function needs inspection to see if it is assuming anything
it shouldn't, so it's not all bad.
Programmers should be aware of these significant performance changes:
* list_nth() and related functions are now O(1); so there's no
major access-speed difference between a list and an array.
* Inserting or deleting a list element now takes time proportional to
the distance to the end of the list, due to moving the array elements.
(However, it typically *doesn't* require palloc or pfree, so except in
long lists it's probably still faster than before.) Notably, lcons()
used to be about the same cost as lappend(), but that's no longer true
if the list is long. Code that uses lcons() and list_delete_first()
to maintain a stack might usefully be rewritten to push and pop at the
end of the list rather than the beginning.
* There are now list_insert_nth...() and list_delete_nth...() functions
that add or remove a list cell identified by index. These have the
data-movement penalty explained above, but there's no search penalty.
* list_concat() and variants now copy the second list's data into
storage belonging to the first list, so there is no longer any
sharing of cells between the input lists. The second argument is
now declared "const List *" to reflect that it isn't changed.
This patch just does the minimum needed to get the new implementation
in place and fix bugs exposed by the regression tests. As suggested
by the foregoing, there's a fair amount of followup work remaining to
do.
Also, the ENABLE_LIST_COMPAT macros are finally removed in this
commit. Code using those should have been gone a dozen years ago.
Patch by me; thanks to David Rowley, Jesper Pedersen, and others
for review.
Discussion: https://postgr.es/m/11587.1550975080@sss.pgh.pa.us
2019-07-15 13:41:58 -04:00
arg = lnext ( args , arg ) ;
2004-05-10 18:44:49 -04:00
}
2004-08-17 14:47:09 -04:00
if ( arg ! = NULL )
ereport ( ERROR ,
( errcode ( ERRCODE_CANNOT_COERCE ) ,
errmsg ( " cannot cast type %s to %s " ,
format_type_be ( RECORDOID ) ,
format_type_be ( targetTypeId ) ) ,
2008-08-28 19:09:48 -04:00
errdetail ( " Input has too many columns. " ) ,
parser_coercion_errposition ( pstate , location , node ) ) ) ;
2004-05-10 18:44:49 -04:00
2006-06-16 14:42:24 -04:00
ReleaseTupleDesc ( tupdesc ) ;
2004-05-10 18:44:49 -04:00
rowexpr = makeNode ( RowExpr ) ;
rowexpr - > args = newargs ;
2017-10-26 13:47:45 -04:00
rowexpr - > row_typeid = baseTypeId ;
2004-05-10 18:44:49 -04:00
rowexpr - > row_format = cformat ;
2008-10-06 13:39:26 -04:00
rowexpr - > colnames = NIL ; /* not needed for named target type */
2008-08-28 19:09:48 -04:00
rowexpr - > location = location ;
2017-10-26 13:47:45 -04:00
/* If target is a domain, apply constraints */
if ( baseTypeId ! = targetTypeId )
{
rowexpr - > row_format = COERCE_IMPLICIT_CAST ;
return coerce_to_domain ( ( Node * ) rowexpr ,
baseTypeId , baseTypeMod ,
targetTypeId ,
ccontext , cformat , location ,
false ) ;
}
2004-05-10 18:44:49 -04:00
return ( Node * ) rowexpr ;
}
1998-05-09 19:31:34 -04:00
2006-07-26 15:31:51 -04:00
/*
* coerce_to_boolean ( )
2001-06-19 18:39:12 -04:00
* Coerce an argument of a construct that requires boolean input
2002-05-12 19:43:04 -04:00
* ( AND , OR , NOT , etc ) . Also check that input is not a set .
2001-06-19 18:39:12 -04:00
*
2002-05-12 19:43:04 -04:00
* Returns the possibly - transformed node tree .
2003-04-29 18:13:11 -04:00
*
* As with coerce_type , pstate may be NULL if no special unknown - Param
* processing is wanted .
2001-06-19 18:39:12 -04:00
*/
2002-05-12 19:43:04 -04:00
Node *
2003-04-29 18:13:11 -04:00
coerce_to_boolean ( ParseState * pstate , Node * node ,
const char * constructName )
2001-06-19 18:39:12 -04:00
{
2002-05-12 19:43:04 -04:00
Oid inputTypeId = exprType ( node ) ;
2001-06-19 18:39:12 -04:00
2002-05-12 19:43:04 -04:00
if ( inputTypeId ! = BOOLOID )
{
2008-08-28 19:09:48 -04:00
Node * newnode ;
newnode = coerce_to_target_type ( pstate , node , inputTypeId ,
BOOLOID , - 1 ,
COERCION_ASSIGNMENT ,
COERCE_IMPLICIT_CAST ,
- 1 ) ;
if ( newnode = = NULL )
2003-07-19 16:20:53 -04:00
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
/* translator: first %s is name of a SQL construct, eg WHERE */
2017-01-18 14:08:20 -05:00
errmsg ( " argument of %s must be type %s, not type %s " ,
constructName , " boolean " ,
format_type_be ( inputTypeId ) ) ,
2008-08-28 19:09:48 -04:00
parser_errposition ( pstate , exprLocation ( node ) ) ) ) ;
node = newnode ;
2002-05-12 19:43:04 -04:00
}
if ( expression_returns_set ( node ) )
2003-07-19 16:20:53 -04:00
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
/* translator: %s is name of a SQL construct, eg WHERE */
errmsg ( " argument of %s must not return a set " ,
2008-08-28 19:09:48 -04:00
constructName ) ,
parser_errposition ( pstate , exprLocation ( node ) ) ) ) ;
2003-07-03 15:07:54 -04:00
return node ;
}
2006-07-26 15:31:51 -04:00
/*
2017-03-08 10:39:37 -05:00
* coerce_to_specific_type_typmod ( )
* Coerce an argument of a construct that requires a specific data type ,
* with a specific typmod . Also check that input is not a set .
2003-07-03 15:07:54 -04:00
*
* Returns the possibly - transformed node tree .
*
* As with coerce_type , pstate may be NULL if no special unknown - Param
* processing is wanted .
*/
Node *
2017-03-08 10:39:37 -05:00
coerce_to_specific_type_typmod ( ParseState * pstate , Node * node ,
Oid targetTypeId , int32 targetTypmod ,
const char * constructName )
2006-12-21 11:05:16 -05:00
{
Oid inputTypeId = exprType ( node ) ;
2006-12-23 19:29:20 -05:00
if ( inputTypeId ! = targetTypeId )
2006-12-21 11:05:16 -05:00
{
2008-08-28 19:09:48 -04:00
Node * newnode ;
newnode = coerce_to_target_type ( pstate , node , inputTypeId ,
2017-03-08 10:39:37 -05:00
targetTypeId , targetTypmod ,
2008-08-28 19:09:48 -04:00
COERCION_ASSIGNMENT ,
COERCE_IMPLICIT_CAST ,
- 1 ) ;
if ( newnode = = NULL )
2006-12-21 11:05:16 -05:00
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
/* translator: first %s is name of a SQL construct, eg LIMIT */
2006-12-23 19:29:20 -05:00
errmsg ( " argument of %s must be type %s, not type %s " ,
constructName ,
format_type_be ( targetTypeId ) ,
2008-08-28 19:09:48 -04:00
format_type_be ( inputTypeId ) ) ,
parser_errposition ( pstate , exprLocation ( node ) ) ) ) ;
node = newnode ;
2006-12-21 11:05:16 -05:00
}
if ( expression_returns_set ( node ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
/* translator: %s is name of a SQL construct, eg LIMIT */
errmsg ( " argument of %s must not return a set " ,
2008-08-28 19:09:48 -04:00
constructName ) ,
parser_errposition ( pstate , exprLocation ( node ) ) ) ) ;
2006-12-21 11:05:16 -05:00
return node ;
}
2017-03-08 10:39:37 -05:00
/*
* coerce_to_specific_type ( )
* Coerce an argument of a construct that requires a specific data type .
* Also check that input is not a set .
*
* Returns the possibly - transformed node tree .
*
* As with coerce_type , pstate may be NULL if no special unknown - Param
* processing is wanted .
*/
Node *
coerce_to_specific_type ( ParseState * pstate , Node * node ,
Oid targetTypeId ,
const char * constructName )
{
return coerce_to_specific_type_typmod ( pstate , node ,
targetTypeId , - 1 ,
constructName ) ;
}
2001-06-19 18:39:12 -04:00
2008-08-28 19:09:48 -04:00
/*
* parser_coercion_errposition - report coercion error location , if possible
*
* We prefer to point at the coercion request ( CAST , : : , etc ) if possible ;
* but there may be no such location in the case of an implicit coercion .
* In that case point at the input expression .
*
* XXX possibly this is more generally useful than coercion errors ;
* if so , should rename and place with parser_errposition .
*/
2020-03-25 11:57:36 -04:00
int
2008-08-28 19:09:48 -04:00
parser_coercion_errposition ( ParseState * pstate ,
int coerce_location ,
Node * input_expr )
{
if ( coerce_location > = 0 )
2020-03-25 11:57:36 -04:00
return parser_errposition ( pstate , coerce_location ) ;
2008-08-28 19:09:48 -04:00
else
2020-03-25 11:57:36 -04:00
return parser_errposition ( pstate , exprLocation ( input_expr ) ) ;
2008-08-28 19:09:48 -04:00
}
/*
* select_common_type ( )
* Determine the common supertype of a list of input expressions .
2008-10-25 13:19:09 -04:00
* This is used for determining the output type of CASE , UNION ,
* and similar constructs .
2000-10-05 15:11:39 -04:00
*
2008-08-28 19:09:48 -04:00
* ' exprs ' is a * nonempty * list of expressions . Note that earlier items
2000-10-05 15:11:39 -04:00
* in the list will be preferred if there is doubt .
* ' context ' is a phrase to use in the error message if we fail to select
2008-10-25 13:19:09 -04:00
* a usable type . Pass NULL to have the routine return InvalidOid
* rather than throwing an error on failure .
2008-08-28 19:09:48 -04:00
* ' which_expr ' : if not NULL , receives a pointer to the particular input
* expression from which the result type was taken .
Fix failure to validate the result of select_common_type().
Although select_common_type() has a failure-return convention, an
apparent successful return just provides a type OID that *might* work
as a common supertype; we've not validated that the required casts
actually exist. In the mainstream use-cases that doesn't matter,
because we'll proceed to invoke coerce_to_common_type() on each input,
which will fail appropriately if the proposed common type doesn't
actually work. However, a few callers didn't read the (nonexistent)
fine print, and thought that if they got back a nonzero OID then the
coercions were sure to work.
This affects in particular the recently-added "anycompatible"
polymorphic types; we might think that a function/operator using
such types matches cases it really doesn't. A likely end result
of that is unexpected "ambiguous operator" errors, as for example
in bug #17387 from James Inform. Another, much older, case is that
the parser might try to transform an "x IN (list)" construct to
a ScalarArrayOpExpr even when the list elements don't actually have
a common supertype.
It doesn't seem desirable to add more checking to select_common_type
itself, as that'd just slow down the mainstream use-cases. Instead,
write a separate function verify_common_type that performs the
missing checks, and add a call to that where necessary. Likewise add
verify_common_type_from_oids to go with select_common_type_from_oids.
Back-patch to v13 where the "anycompatible" types came in. (The
symptom complained of in bug #17387 doesn't appear till v14, but
that's just because we didn't get around to converting || to use
anycompatible till then.) In principle the "x IN (list)" fix could
go back all the way, but I'm not currently convinced that it makes
much difference in real-world cases, so I won't bother for now.
Discussion: https://postgr.es/m/17387-5dfe54b988444963@postgresql.org
2022-01-29 11:41:12 -05:00
*
* Caution : " failure " just means that there were inputs of different type
* categories . It is not guaranteed that all the inputs are coercible to the
* selected type ; caller must check that ( see verify_common_type ) .
2000-10-05 15:11:39 -04:00
*/
Oid
2008-08-28 19:09:48 -04:00
select_common_type ( ParseState * pstate , List * exprs , const char * context ,
Node * * which_expr )
2000-10-05 15:11:39 -04:00
{
2008-08-28 19:09:48 -04:00
Node * pexpr ;
2000-10-05 15:11:39 -04:00
Oid ptype ;
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
TYPCATEGORY pcategory ;
bool pispreferred ;
2008-08-28 19:09:48 -04:00
ListCell * lc ;
2000-10-05 15:11:39 -04:00
2008-08-28 19:09:48 -04:00
Assert ( exprs ! = NIL ) ;
pexpr = ( Node * ) linitial ( exprs ) ;
Represent Lists as expansible arrays, not chains of cons-cells.
Originally, Postgres Lists were a more or less exact reimplementation of
Lisp lists, which consist of chains of separately-allocated cons cells,
each having a value and a next-cell link. We'd hacked that once before
(commit d0b4399d8) to add a separate List header, but the data was still
in cons cells. That makes some operations -- notably list_nth() -- O(N),
and it's bulky because of the next-cell pointers and per-cell palloc
overhead, and it's very cache-unfriendly if the cons cells end up
scattered around rather than being adjacent.
In this rewrite, we still have List headers, but the data is in a
resizable array of values, with no next-cell links. Now we need at
most two palloc's per List, and often only one, since we can allocate
some values in the same palloc call as the List header. (Of course,
extending an existing List may require repalloc's to enlarge the array.
But this involves just O(log N) allocations not O(N).)
Of course this is not without downsides. The key difficulty is that
addition or deletion of a list entry may now cause other entries to
move, which it did not before.
For example, that breaks foreach() and sister macros, which historically
used a pointer to the current cons-cell as loop state. We can repair
those macros transparently by making their actual loop state be an
integer list index; the exposed "ListCell *" pointer is no longer state
carried across loop iterations, but is just a derived value. (In
practice, modern compilers can optimize things back to having just one
loop state value, at least for simple cases with inline loop bodies.)
In principle, this is a semantics change for cases where the loop body
inserts or deletes list entries ahead of the current loop index; but
I found no such cases in the Postgres code.
The change is not at all transparent for code that doesn't use foreach()
but chases lists "by hand" using lnext(). The largest share of such
code in the backend is in loops that were maintaining "prev" and "next"
variables in addition to the current-cell pointer, in order to delete
list cells efficiently using list_delete_cell(). However, we no longer
need a previous-cell pointer to delete a list cell efficiently. Keeping
a next-cell pointer doesn't work, as explained above, but we can improve
matters by changing such code to use a regular foreach() loop and then
using the new macro foreach_delete_current() to delete the current cell.
(This macro knows how to update the associated foreach loop's state so
that no cells will be missed in the traversal.)
There remains a nontrivial risk of code assuming that a ListCell *
pointer will remain good over an operation that could now move the list
contents. To help catch such errors, list.c can be compiled with a new
define symbol DEBUG_LIST_MEMORY_USAGE that forcibly moves list contents
whenever that could possibly happen. This makes list operations
significantly more expensive so it's not normally turned on (though it
is on by default if USE_VALGRIND is on).
There are two notable API differences from the previous code:
* lnext() now requires the List's header pointer in addition to the
current cell's address.
* list_delete_cell() no longer requires a previous-cell argument.
These changes are somewhat unfortunate, but on the other hand code using
either function needs inspection to see if it is assuming anything
it shouldn't, so it's not all bad.
Programmers should be aware of these significant performance changes:
* list_nth() and related functions are now O(1); so there's no
major access-speed difference between a list and an array.
* Inserting or deleting a list element now takes time proportional to
the distance to the end of the list, due to moving the array elements.
(However, it typically *doesn't* require palloc or pfree, so except in
long lists it's probably still faster than before.) Notably, lcons()
used to be about the same cost as lappend(), but that's no longer true
if the list is long. Code that uses lcons() and list_delete_first()
to maintain a stack might usefully be rewritten to push and pop at the
end of the list rather than the beginning.
* There are now list_insert_nth...() and list_delete_nth...() functions
that add or remove a list cell identified by index. These have the
data-movement penalty explained above, but there's no search penalty.
* list_concat() and variants now copy the second list's data into
storage belonging to the first list, so there is no longer any
sharing of cells between the input lists. The second argument is
now declared "const List *" to reflect that it isn't changed.
This patch just does the minimum needed to get the new implementation
in place and fix bugs exposed by the regression tests. As suggested
by the foregoing, there's a fair amount of followup work remaining to
do.
Also, the ENABLE_LIST_COMPAT macros are finally removed in this
commit. Code using those should have been gone a dozen years ago.
Patch by me; thanks to David Rowley, Jesper Pedersen, and others
for review.
Discussion: https://postgr.es/m/11587.1550975080@sss.pgh.pa.us
2019-07-15 13:41:58 -04:00
lc = list_second_cell ( exprs ) ;
2008-08-28 19:09:48 -04:00
ptype = exprType ( pexpr ) ;
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 11:46:51 -05:00
/*
* If all input types are valid and exactly the same , just pick that type .
* This is the only way that we will resolve the result as being a domain
* type ; otherwise domains are smashed to their base types for comparison .
*/
if ( ptype ! = UNKNOWNOID )
{
Represent Lists as expansible arrays, not chains of cons-cells.
Originally, Postgres Lists were a more or less exact reimplementation of
Lisp lists, which consist of chains of separately-allocated cons cells,
each having a value and a next-cell link. We'd hacked that once before
(commit d0b4399d8) to add a separate List header, but the data was still
in cons cells. That makes some operations -- notably list_nth() -- O(N),
and it's bulky because of the next-cell pointers and per-cell palloc
overhead, and it's very cache-unfriendly if the cons cells end up
scattered around rather than being adjacent.
In this rewrite, we still have List headers, but the data is in a
resizable array of values, with no next-cell links. Now we need at
most two palloc's per List, and often only one, since we can allocate
some values in the same palloc call as the List header. (Of course,
extending an existing List may require repalloc's to enlarge the array.
But this involves just O(log N) allocations not O(N).)
Of course this is not without downsides. The key difficulty is that
addition or deletion of a list entry may now cause other entries to
move, which it did not before.
For example, that breaks foreach() and sister macros, which historically
used a pointer to the current cons-cell as loop state. We can repair
those macros transparently by making their actual loop state be an
integer list index; the exposed "ListCell *" pointer is no longer state
carried across loop iterations, but is just a derived value. (In
practice, modern compilers can optimize things back to having just one
loop state value, at least for simple cases with inline loop bodies.)
In principle, this is a semantics change for cases where the loop body
inserts or deletes list entries ahead of the current loop index; but
I found no such cases in the Postgres code.
The change is not at all transparent for code that doesn't use foreach()
but chases lists "by hand" using lnext(). The largest share of such
code in the backend is in loops that were maintaining "prev" and "next"
variables in addition to the current-cell pointer, in order to delete
list cells efficiently using list_delete_cell(). However, we no longer
need a previous-cell pointer to delete a list cell efficiently. Keeping
a next-cell pointer doesn't work, as explained above, but we can improve
matters by changing such code to use a regular foreach() loop and then
using the new macro foreach_delete_current() to delete the current cell.
(This macro knows how to update the associated foreach loop's state so
that no cells will be missed in the traversal.)
There remains a nontrivial risk of code assuming that a ListCell *
pointer will remain good over an operation that could now move the list
contents. To help catch such errors, list.c can be compiled with a new
define symbol DEBUG_LIST_MEMORY_USAGE that forcibly moves list contents
whenever that could possibly happen. This makes list operations
significantly more expensive so it's not normally turned on (though it
is on by default if USE_VALGRIND is on).
There are two notable API differences from the previous code:
* lnext() now requires the List's header pointer in addition to the
current cell's address.
* list_delete_cell() no longer requires a previous-cell argument.
These changes are somewhat unfortunate, but on the other hand code using
either function needs inspection to see if it is assuming anything
it shouldn't, so it's not all bad.
Programmers should be aware of these significant performance changes:
* list_nth() and related functions are now O(1); so there's no
major access-speed difference between a list and an array.
* Inserting or deleting a list element now takes time proportional to
the distance to the end of the list, due to moving the array elements.
(However, it typically *doesn't* require palloc or pfree, so except in
long lists it's probably still faster than before.) Notably, lcons()
used to be about the same cost as lappend(), but that's no longer true
if the list is long. Code that uses lcons() and list_delete_first()
to maintain a stack might usefully be rewritten to push and pop at the
end of the list rather than the beginning.
* There are now list_insert_nth...() and list_delete_nth...() functions
that add or remove a list cell identified by index. These have the
data-movement penalty explained above, but there's no search penalty.
* list_concat() and variants now copy the second list's data into
storage belonging to the first list, so there is no longer any
sharing of cells between the input lists. The second argument is
now declared "const List *" to reflect that it isn't changed.
This patch just does the minimum needed to get the new implementation
in place and fix bugs exposed by the regression tests. As suggested
by the foregoing, there's a fair amount of followup work remaining to
do.
Also, the ENABLE_LIST_COMPAT macros are finally removed in this
commit. Code using those should have been gone a dozen years ago.
Patch by me; thanks to David Rowley, Jesper Pedersen, and others
for review.
Discussion: https://postgr.es/m/11587.1550975080@sss.pgh.pa.us
2019-07-15 13:41:58 -04:00
for_each_cell ( lc , exprs , lc )
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 11:46:51 -05:00
{
2008-08-28 19:09:48 -04:00
Node * nexpr = ( Node * ) lfirst ( lc ) ;
Oid ntype = exprType ( nexpr ) ;
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 11:46:51 -05:00
if ( ntype ! = ptype )
break ;
}
2008-08-28 19:09:48 -04:00
if ( lc = = NULL ) /* got to the end of the list? */
{
if ( which_expr )
* which_expr = pexpr ;
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 11:46:51 -05:00
return ptype ;
2008-08-28 19:09:48 -04:00
}
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 11:46:51 -05:00
}
2008-08-28 19:09:48 -04:00
/*
* Nope , so set up for the full algorithm . Note that at this point , lc
* points to the first list item with type different from pexpr ' s ; we need
* not re - examine any items the previous loop advanced over .
*/
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 11:46:51 -05:00
ptype = getBaseType ( ptype ) ;
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
get_type_category_preferred ( ptype , & pcategory , & pispreferred ) ;
2004-05-26 00:41:50 -04:00
Represent Lists as expansible arrays, not chains of cons-cells.
Originally, Postgres Lists were a more or less exact reimplementation of
Lisp lists, which consist of chains of separately-allocated cons cells,
each having a value and a next-cell link. We'd hacked that once before
(commit d0b4399d8) to add a separate List header, but the data was still
in cons cells. That makes some operations -- notably list_nth() -- O(N),
and it's bulky because of the next-cell pointers and per-cell palloc
overhead, and it's very cache-unfriendly if the cons cells end up
scattered around rather than being adjacent.
In this rewrite, we still have List headers, but the data is in a
resizable array of values, with no next-cell links. Now we need at
most two palloc's per List, and often only one, since we can allocate
some values in the same palloc call as the List header. (Of course,
extending an existing List may require repalloc's to enlarge the array.
But this involves just O(log N) allocations not O(N).)
Of course this is not without downsides. The key difficulty is that
addition or deletion of a list entry may now cause other entries to
move, which it did not before.
For example, that breaks foreach() and sister macros, which historically
used a pointer to the current cons-cell as loop state. We can repair
those macros transparently by making their actual loop state be an
integer list index; the exposed "ListCell *" pointer is no longer state
carried across loop iterations, but is just a derived value. (In
practice, modern compilers can optimize things back to having just one
loop state value, at least for simple cases with inline loop bodies.)
In principle, this is a semantics change for cases where the loop body
inserts or deletes list entries ahead of the current loop index; but
I found no such cases in the Postgres code.
The change is not at all transparent for code that doesn't use foreach()
but chases lists "by hand" using lnext(). The largest share of such
code in the backend is in loops that were maintaining "prev" and "next"
variables in addition to the current-cell pointer, in order to delete
list cells efficiently using list_delete_cell(). However, we no longer
need a previous-cell pointer to delete a list cell efficiently. Keeping
a next-cell pointer doesn't work, as explained above, but we can improve
matters by changing such code to use a regular foreach() loop and then
using the new macro foreach_delete_current() to delete the current cell.
(This macro knows how to update the associated foreach loop's state so
that no cells will be missed in the traversal.)
There remains a nontrivial risk of code assuming that a ListCell *
pointer will remain good over an operation that could now move the list
contents. To help catch such errors, list.c can be compiled with a new
define symbol DEBUG_LIST_MEMORY_USAGE that forcibly moves list contents
whenever that could possibly happen. This makes list operations
significantly more expensive so it's not normally turned on (though it
is on by default if USE_VALGRIND is on).
There are two notable API differences from the previous code:
* lnext() now requires the List's header pointer in addition to the
current cell's address.
* list_delete_cell() no longer requires a previous-cell argument.
These changes are somewhat unfortunate, but on the other hand code using
either function needs inspection to see if it is assuming anything
it shouldn't, so it's not all bad.
Programmers should be aware of these significant performance changes:
* list_nth() and related functions are now O(1); so there's no
major access-speed difference between a list and an array.
* Inserting or deleting a list element now takes time proportional to
the distance to the end of the list, due to moving the array elements.
(However, it typically *doesn't* require palloc or pfree, so except in
long lists it's probably still faster than before.) Notably, lcons()
used to be about the same cost as lappend(), but that's no longer true
if the list is long. Code that uses lcons() and list_delete_first()
to maintain a stack might usefully be rewritten to push and pop at the
end of the list rather than the beginning.
* There are now list_insert_nth...() and list_delete_nth...() functions
that add or remove a list cell identified by index. These have the
data-movement penalty explained above, but there's no search penalty.
* list_concat() and variants now copy the second list's data into
storage belonging to the first list, so there is no longer any
sharing of cells between the input lists. The second argument is
now declared "const List *" to reflect that it isn't changed.
This patch just does the minimum needed to get the new implementation
in place and fix bugs exposed by the regression tests. As suggested
by the foregoing, there's a fair amount of followup work remaining to
do.
Also, the ENABLE_LIST_COMPAT macros are finally removed in this
commit. Code using those should have been gone a dozen years ago.
Patch by me; thanks to David Rowley, Jesper Pedersen, and others
for review.
Discussion: https://postgr.es/m/11587.1550975080@sss.pgh.pa.us
2019-07-15 13:41:58 -04:00
for_each_cell ( lc , exprs , lc )
2000-10-05 15:11:39 -04:00
{
2008-08-28 19:09:48 -04:00
Node * nexpr = ( Node * ) lfirst ( lc ) ;
Oid ntype = getBaseType ( exprType ( nexpr ) ) ;
2000-10-05 15:11:39 -04:00
/* move on to next one if no new information... */
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 11:46:51 -05:00
if ( ntype ! = UNKNOWNOID & & ntype ! = ptype )
2000-10-05 15:11:39 -04:00
{
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
TYPCATEGORY ncategory ;
bool nispreferred ;
get_type_category_preferred ( ntype , & ncategory , & nispreferred ) ;
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 11:46:51 -05:00
if ( ptype = = UNKNOWNOID )
2000-10-05 15:11:39 -04:00
{
Fix select_common_type() so that it can select a domain type, if all inputs
to a UNION, CASE, or related construct are of the same domain type. The
main part of this routine smashes domains to their base types, which seems
necessary because the logic involves TypeCategory() and IsPreferredType(),
neither of which work usefully on domains. However, we can add a first
pass that just detects whether all the inputs are exactly the same type,
and if so accept that without question (so long as it's not UNKNOWN).
Per recent gripe from Dean Rasheed.
In passing, remove some tests for InvalidOid, which have clearly been dead
code for quite some time now, because getBaseType() would fail on that input.
Also, clarify the manual's not-very-precise description of the existing
algorithm's behavior.
2007-11-26 11:46:51 -05:00
/* so far, only unknowns so take anything... */
2008-08-28 19:09:48 -04:00
pexpr = nexpr ;
2000-10-05 15:11:39 -04:00
ptype = ntype ;
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
pcategory = ncategory ;
pispreferred = nispreferred ;
2000-10-05 15:11:39 -04:00
}
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
else if ( ncategory ! = pcategory )
2000-10-05 15:11:39 -04:00
{
/*
* both types in different categories ? then not much hope . . .
*/
2008-10-25 13:19:09 -04:00
if ( context = = NULL )
return InvalidOid ;
2003-07-19 16:20:53 -04:00
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
2006-11-28 07:54:42 -05:00
/*------
translator : first % s is name of a SQL construct , eg CASE */
2003-07-19 16:20:53 -04:00
errmsg ( " %s types %s and %s cannot be matched " ,
context ,
format_type_be ( ptype ) ,
2008-08-28 19:09:48 -04:00
format_type_be ( ntype ) ) ,
parser_errposition ( pstate , exprLocation ( nexpr ) ) ) ) ;
2000-10-05 15:11:39 -04:00
}
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
else if ( ! pispreferred & &
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
can_coerce_type ( 1 , & ptype , & ntype , COERCION_IMPLICIT ) & &
! can_coerce_type ( 1 , & ntype , & ptype , COERCION_IMPLICIT ) )
2000-10-05 15:11:39 -04:00
{
/*
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
* take new type if can coerce to it implicitly but not the
* other way ; but if we have a preferred type , stay on it .
2000-10-05 15:11:39 -04:00
*/
2008-08-28 19:09:48 -04:00
pexpr = nexpr ;
2000-10-05 15:11:39 -04:00
ptype = ntype ;
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
pcategory = ncategory ;
pispreferred = nispreferred ;
2000-10-05 15:11:39 -04:00
}
}
}
2000-11-08 23:14:32 -05:00
/*
* If all the inputs were UNKNOWN type - - - ie , unknown - type literals - - -
* then resolve as type TEXT . This situation comes up with constructs
* like SELECT ( CASE WHEN foo THEN ' bar ' ELSE ' baz ' END ) ; SELECT ' foo '
* UNION SELECT ' bar ' ; It might seem desirable to leave the construct ' s
* output type as UNKNOWN , but that really doesn ' t work , because we ' d
* probably end up needing a runtime coercion from UNKNOWN to something
* else , and we usually won ' t have it . We need to coerce the unknown
* literals while they are still literals , so a decision has to be made
* now .
*/
if ( ptype = = UNKNOWNOID )
ptype = TEXTOID ;
2008-08-28 19:09:48 -04:00
if ( which_expr )
* which_expr = pexpr ;
2000-10-05 15:11:39 -04:00
return ptype ;
}
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/*
* select_common_type_from_oids ( )
* Determine the common supertype of an array of type OIDs .
*
* This is the same logic as select_common_type ( ) , but working from
* an array of type OIDs not a list of expressions . As in that function ,
* earlier entries in the array have some preference over later ones .
* On failure , return InvalidOid if noerror is true , else throw an error .
*
Fix failure to validate the result of select_common_type().
Although select_common_type() has a failure-return convention, an
apparent successful return just provides a type OID that *might* work
as a common supertype; we've not validated that the required casts
actually exist. In the mainstream use-cases that doesn't matter,
because we'll proceed to invoke coerce_to_common_type() on each input,
which will fail appropriately if the proposed common type doesn't
actually work. However, a few callers didn't read the (nonexistent)
fine print, and thought that if they got back a nonzero OID then the
coercions were sure to work.
This affects in particular the recently-added "anycompatible"
polymorphic types; we might think that a function/operator using
such types matches cases it really doesn't. A likely end result
of that is unexpected "ambiguous operator" errors, as for example
in bug #17387 from James Inform. Another, much older, case is that
the parser might try to transform an "x IN (list)" construct to
a ScalarArrayOpExpr even when the list elements don't actually have
a common supertype.
It doesn't seem desirable to add more checking to select_common_type
itself, as that'd just slow down the mainstream use-cases. Instead,
write a separate function verify_common_type that performs the
missing checks, and add a call to that where necessary. Likewise add
verify_common_type_from_oids to go with select_common_type_from_oids.
Back-patch to v13 where the "anycompatible" types came in. (The
symptom complained of in bug #17387 doesn't appear till v14, but
that's just because we didn't get around to converting || to use
anycompatible till then.) In principle the "x IN (list)" fix could
go back all the way, but I'm not currently convinced that it makes
much difference in real-world cases, so I won't bother for now.
Discussion: https://postgr.es/m/17387-5dfe54b988444963@postgresql.org
2022-01-29 11:41:12 -05:00
* Caution : " failure " just means that there were inputs of different type
* categories . It is not guaranteed that all the inputs are coercible to the
* selected type ; caller must check that ( see verify_common_type_from_oids ) .
*
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
* Note : neither caller will pass any UNKNOWNOID entries , so the tests
* for that in this function are dead code . However , they don ' t cost much ,
* and it seems better to keep this logic as close to select_common_type ( )
* as possible .
*/
static Oid
select_common_type_from_oids ( int nargs , const Oid * typeids , bool noerror )
{
Oid ptype ;
TYPCATEGORY pcategory ;
bool pispreferred ;
int i = 1 ;
Assert ( nargs > 0 ) ;
ptype = typeids [ 0 ] ;
/* If all input types are valid and exactly the same, pick that type. */
if ( ptype ! = UNKNOWNOID )
{
for ( ; i < nargs ; i + + )
{
if ( typeids [ i ] ! = ptype )
break ;
}
if ( i = = nargs )
return ptype ;
}
/*
* Nope , so set up for the full algorithm . Note that at this point , we
* can skip array entries before " i " ; they are all equal to ptype .
*/
ptype = getBaseType ( ptype ) ;
get_type_category_preferred ( ptype , & pcategory , & pispreferred ) ;
for ( ; i < nargs ; i + + )
{
Oid ntype = getBaseType ( typeids [ i ] ) ;
/* move on to next one if no new information... */
if ( ntype ! = UNKNOWNOID & & ntype ! = ptype )
{
TYPCATEGORY ncategory ;
bool nispreferred ;
get_type_category_preferred ( ntype , & ncategory , & nispreferred ) ;
if ( ptype = = UNKNOWNOID )
{
/* so far, only unknowns so take anything... */
ptype = ntype ;
pcategory = ncategory ;
pispreferred = nispreferred ;
}
else if ( ncategory ! = pcategory )
{
/*
* both types in different categories ? then not much hope . . .
*/
if ( noerror )
return InvalidOid ;
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " argument types %s and %s cannot be matched " ,
format_type_be ( ptype ) ,
format_type_be ( ntype ) ) ) ) ;
}
else if ( ! pispreferred & &
can_coerce_type ( 1 , & ptype , & ntype , COERCION_IMPLICIT ) & &
! can_coerce_type ( 1 , & ntype , & ptype , COERCION_IMPLICIT ) )
{
/*
* take new type if can coerce to it implicitly but not the
* other way ; but if we have a preferred type , stay on it .
*/
ptype = ntype ;
pcategory = ncategory ;
pispreferred = nispreferred ;
}
}
}
/* Like select_common_type(), choose TEXT if all inputs were UNKNOWN */
if ( ptype = = UNKNOWNOID )
ptype = TEXTOID ;
return ptype ;
}
2008-08-28 19:09:48 -04:00
/*
* coerce_to_common_type ( )
2000-10-05 15:11:39 -04:00
* Coerce an expression to the given type .
*
* This is used following select_common_type ( ) to coerce the individual
* expressions to the desired type . ' context ' is a phrase to use in the
* error message if we fail to coerce .
2003-04-29 18:13:11 -04:00
*
* As with coerce_type , pstate may be NULL if no special unknown - Param
* processing is wanted .
2000-10-05 15:11:39 -04:00
*/
Node *
2003-04-29 18:13:11 -04:00
coerce_to_common_type ( ParseState * pstate , Node * node ,
Oid targetTypeId , const char * context )
2000-10-05 15:11:39 -04:00
{
Oid inputTypeId = exprType ( node ) ;
if ( inputTypeId = = targetTypeId )
return node ; /* no work */
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
if ( can_coerce_type ( 1 , & inputTypeId , & targetTypeId , COERCION_IMPLICIT ) )
2004-06-15 21:27:00 -04:00
node = coerce_type ( pstate , node , inputTypeId , targetTypeId , - 1 ,
2008-08-28 19:09:48 -04:00
COERCION_IMPLICIT , COERCE_IMPLICIT_CAST , - 1 ) ;
2000-10-05 15:11:39 -04:00
else
2003-07-19 16:20:53 -04:00
ereport ( ERROR ,
( errcode ( ERRCODE_CANNOT_COERCE ) ,
/* translator: first %s is name of a SQL construct, eg CASE */
2003-07-27 20:09:16 -04:00
errmsg ( " %s could not convert type %s to %s " ,
2003-07-19 16:20:53 -04:00
context ,
format_type_be ( inputTypeId ) ,
2008-08-28 19:09:48 -04:00
format_type_be ( targetTypeId ) ) ,
parser_errposition ( pstate , exprLocation ( node ) ) ) ) ;
2000-10-05 15:11:39 -04:00
return node ;
}
Fix failure to validate the result of select_common_type().
Although select_common_type() has a failure-return convention, an
apparent successful return just provides a type OID that *might* work
as a common supertype; we've not validated that the required casts
actually exist. In the mainstream use-cases that doesn't matter,
because we'll proceed to invoke coerce_to_common_type() on each input,
which will fail appropriately if the proposed common type doesn't
actually work. However, a few callers didn't read the (nonexistent)
fine print, and thought that if they got back a nonzero OID then the
coercions were sure to work.
This affects in particular the recently-added "anycompatible"
polymorphic types; we might think that a function/operator using
such types matches cases it really doesn't. A likely end result
of that is unexpected "ambiguous operator" errors, as for example
in bug #17387 from James Inform. Another, much older, case is that
the parser might try to transform an "x IN (list)" construct to
a ScalarArrayOpExpr even when the list elements don't actually have
a common supertype.
It doesn't seem desirable to add more checking to select_common_type
itself, as that'd just slow down the mainstream use-cases. Instead,
write a separate function verify_common_type that performs the
missing checks, and add a call to that where necessary. Likewise add
verify_common_type_from_oids to go with select_common_type_from_oids.
Back-patch to v13 where the "anycompatible" types came in. (The
symptom complained of in bug #17387 doesn't appear till v14, but
that's just because we didn't get around to converting || to use
anycompatible till then.) In principle the "x IN (list)" fix could
go back all the way, but I'm not currently convinced that it makes
much difference in real-world cases, so I won't bother for now.
Discussion: https://postgr.es/m/17387-5dfe54b988444963@postgresql.org
2022-01-29 11:41:12 -05:00
/*
* verify_common_type ( )
* Verify that all input types can be coerced to a proposed common type .
* Return true if so , false if not all coercions are possible .
*
* Most callers of select_common_type ( ) don ' t need to do this explicitly
* because the checks will happen while trying to convert input expressions
* to the right type , e . g . in coerce_to_common_type ( ) . However , if a separate
* check step is needed to validate the applicability of the common type , call
* this .
*/
bool
verify_common_type ( Oid common_type , List * exprs )
{
ListCell * lc ;
foreach ( lc , exprs )
{
Node * nexpr = ( Node * ) lfirst ( lc ) ;
Oid ntype = exprType ( nexpr ) ;
if ( ! can_coerce_type ( 1 , & ntype , & common_type , COERCION_IMPLICIT ) )
return false ;
}
return true ;
}
/*
* verify_common_type_from_oids ( )
* As above , but work from an array of type OIDs .
*/
static bool
verify_common_type_from_oids ( Oid common_type , int nargs , const Oid * typeids )
{
for ( int i = 0 ; i < nargs ; i + + )
{
if ( ! can_coerce_type ( 1 , & typeids [ i ] , & common_type , COERCION_IMPLICIT ) )
return false ;
}
return true ;
}
2020-10-27 12:39:23 -04:00
/*
* select_common_typmod ( )
* Determine the common typmod of a list of input expressions .
*
* common_type is the selected common type of the expressions , typically
* computed using select_common_type ( ) .
*/
int32
select_common_typmod ( ParseState * pstate , List * exprs , Oid common_type )
{
ListCell * lc ;
bool first = true ;
int32 result = - 1 ;
foreach ( lc , exprs )
{
2021-01-04 11:03:22 -05:00
Node * expr = ( Node * ) lfirst ( lc ) ;
2020-10-27 12:39:23 -04:00
/* Types must match */
if ( exprType ( expr ) ! = common_type )
return - 1 ;
else if ( first )
{
result = exprTypmod ( expr ) ;
first = false ;
}
else
{
/* As soon as we see a non-matching typmod, fall back to -1 */
if ( result ! = exprTypmod ( expr ) )
return - 1 ;
}
}
return result ;
}
2003-04-08 19:20:04 -04:00
/*
* check_generic_type_consistency ( )
* Are the actual arguments potentially compatible with a
* polymorphic function ?
*
* The argument consistency rules are :
*
2011-11-20 23:50:27 -05:00
* 1 ) All arguments declared ANYELEMENT must have the same datatype .
* 2 ) All arguments declared ANYARRAY must have the same datatype ,
* which must be a varlena array type .
2021-07-27 15:01:49 -04:00
* 3 ) All arguments declared ANYRANGE must be the same range type .
* Similarly , all arguments declared ANYMULTIRANGE must be the same
* multirange type ; and if both of these appear , the ANYRANGE type
* must be the element type of the ANYMULTIRANGE type .
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
* 4 ) If there are arguments of more than one of these polymorphic types ,
* the array element type and / or range subtype must be the same as each
* other and the same as the ANYELEMENT type .
* 5 ) ANYENUM is treated the same as ANYELEMENT except that if it is used
2011-11-20 23:50:27 -05:00
* ( alone or in combination with plain ANYELEMENT ) , we add the extra
* condition that the ANYELEMENT type must be an enum .
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
* 6 ) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used ,
2011-11-20 23:50:27 -05:00
* we add the extra condition that the ANYELEMENT type must not be an array .
* ( This is a no - op if used in combination with ANYARRAY or ANYENUM , but
* is an extra restriction if not . )
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
* 7 ) All arguments declared ANYCOMPATIBLE must be implicitly castable
* to a common supertype ( chosen as per select_common_type ' s rules ) .
* ANYCOMPATIBLENONARRAY works like ANYCOMPATIBLE but also requires the
* common supertype to not be an array . If there are ANYCOMPATIBLEARRAY
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
* or ANYCOMPATIBLERANGE or ANYCOMPATIBLEMULTIRANGE arguments , their element
* types or subtypes are included while making the choice of common supertype .
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
* 8 ) The resolved type of ANYCOMPATIBLEARRAY arguments will be the array
* type over the common supertype ( which might not be the same array type
* as any of the original arrays ) .
* 9 ) All ANYCOMPATIBLERANGE arguments must be the exact same range type
* ( after domain flattening ) , since we have no preference rule that would
* let us choose one over another . Furthermore , that range ' s subtype
* must exactly match the common supertype chosen by rule 7.
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
* 10 ) All ANYCOMPATIBLEMULTIRANGE arguments must be the exact same multirange
2021-07-27 15:01:49 -04:00
* type ( after domain flattening ) , since we have no preference rule that
* would let us choose one over another . Furthermore , if ANYCOMPATIBLERANGE
* also appears , that range type must be the multirange ' s element type ;
* otherwise , the multirange ' s range ' s subtype must exactly match the
* common supertype chosen by rule 7.
2003-04-08 19:20:04 -04:00
*
2011-06-08 12:52:12 -04:00
* Domains over arrays match ANYARRAY , and are immediately flattened to their
* base type . ( Thus , for example , we will consider it a match if one ANYARRAY
2011-11-20 23:50:27 -05:00
* argument is a domain over int4 [ ] while another one is just int4 [ ] . ) Also
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
* notice that such a domain does * not * match ANYNONARRAY . The same goes
* for ANYCOMPATIBLEARRAY and ANYCOMPATIBLENONARRAY .
2011-06-08 12:52:12 -04:00
*
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
* Similarly , domains over ranges match ANYRANGE or ANYCOMPATIBLERANGE ,
2021-07-27 15:01:49 -04:00
* and are immediately flattened to their base type . Likewise , domains
* over multiranges match ANYMULTIRANGE or ANYCOMPATIBLEMULTIRANGE and are
* immediately flattened to their base type .
2011-11-20 23:50:27 -05:00
*
* Note that domains aren ' t currently considered to match ANYENUM ,
* even if their base type would match .
*
2007-06-06 19:00:50 -04:00
* If we have UNKNOWN input ( ie , an untyped literal ) for any polymorphic
* argument , assume it is okay .
2003-04-08 19:20:04 -04:00
*
2017-08-16 00:22:32 -04:00
* We do not ereport here , but just return false if a rule is violated .
2003-04-08 19:20:04 -04:00
*/
bool
2018-10-23 06:17:16 -04:00
check_generic_type_consistency ( const Oid * actual_arg_types ,
const Oid * declared_arg_types ,
2003-04-08 19:20:04 -04:00
int nargs )
{
Oid elem_typeid = InvalidOid ;
Oid array_typeid = InvalidOid ;
2011-11-03 07:16:28 -04:00
Oid range_typeid = InvalidOid ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
Oid multirange_typeid = InvalidOid ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
Oid anycompatible_range_typeid = InvalidOid ;
Oid anycompatible_range_typelem = InvalidOid ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
Oid anycompatible_multirange_typeid = InvalidOid ;
Oid anycompatible_multirange_typelem = InvalidOid ;
Oid range_typelem = InvalidOid ;
2007-06-06 19:00:50 -04:00
bool have_anynonarray = false ;
2007-04-01 23:49:42 -04:00
bool have_anyenum = false ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
bool have_anycompatible_nonarray = false ;
int n_anycompatible_args = 0 ;
Oid anycompatible_actual_types [ FUNC_MAX_ARGS ] ;
2003-04-08 19:20:04 -04:00
/*
2007-06-06 19:00:50 -04:00
* Loop through the arguments to see if we have any that are polymorphic .
* If so , require the actual types to be consistent .
2003-04-08 19:20:04 -04:00
*/
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
Assert ( nargs < = FUNC_MAX_ARGS ) ;
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
for ( int j = 0 ; j < nargs ; j + + )
2003-04-08 19:20:04 -04:00
{
2007-06-06 19:00:50 -04:00
Oid decl_type = declared_arg_types [ j ] ;
2003-04-08 19:20:04 -04:00
Oid actual_type = actual_arg_types [ j ] ;
2007-06-06 19:00:50 -04:00
if ( decl_type = = ANYELEMENTOID | |
decl_type = = ANYNONARRAYOID | |
decl_type = = ANYENUMOID )
2003-04-08 19:20:04 -04:00
{
2007-06-06 19:00:50 -04:00
if ( decl_type = = ANYNONARRAYOID )
have_anynonarray = true ;
else if ( decl_type = = ANYENUMOID )
2007-04-01 23:49:42 -04:00
have_anyenum = true ;
2003-04-08 19:20:04 -04:00
if ( actual_type = = UNKNOWNOID )
continue ;
if ( OidIsValid ( elem_typeid ) & & actual_type ! = elem_typeid )
return false ;
elem_typeid = actual_type ;
}
2007-06-06 19:00:50 -04:00
else if ( decl_type = = ANYARRAYOID )
2003-04-08 19:20:04 -04:00
{
if ( actual_type = = UNKNOWNOID )
continue ;
2011-06-08 12:52:12 -04:00
actual_type = getBaseType ( actual_type ) ; /* flatten domains */
2003-04-08 19:20:04 -04:00
if ( OidIsValid ( array_typeid ) & & actual_type ! = array_typeid )
return false ;
array_typeid = actual_type ;
}
2011-11-03 07:16:28 -04:00
else if ( decl_type = = ANYRANGEOID )
{
if ( actual_type = = UNKNOWNOID )
continue ;
2011-11-20 23:50:27 -05:00
actual_type = getBaseType ( actual_type ) ; /* flatten domains */
2011-11-03 07:16:28 -04:00
if ( OidIsValid ( range_typeid ) & & actual_type ! = range_typeid )
return false ;
range_typeid = actual_type ;
}
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
else if ( decl_type = = ANYMULTIRANGEOID )
{
if ( actual_type = = UNKNOWNOID )
continue ;
actual_type = getBaseType ( actual_type ) ; /* flatten domains */
if ( OidIsValid ( multirange_typeid ) & & actual_type ! = multirange_typeid )
return false ;
multirange_typeid = actual_type ;
}
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
else if ( decl_type = = ANYCOMPATIBLEOID | |
decl_type = = ANYCOMPATIBLENONARRAYOID )
{
if ( decl_type = = ANYCOMPATIBLENONARRAYOID )
have_anycompatible_nonarray = true ;
if ( actual_type = = UNKNOWNOID )
continue ;
/* collect the actual types of non-unknown COMPATIBLE args */
anycompatible_actual_types [ n_anycompatible_args + + ] = actual_type ;
}
else if ( decl_type = = ANYCOMPATIBLEARRAYOID )
{
Oid elem_type ;
if ( actual_type = = UNKNOWNOID )
continue ;
actual_type = getBaseType ( actual_type ) ; /* flatten domains */
elem_type = get_element_type ( actual_type ) ;
if ( ! OidIsValid ( elem_type ) )
return false ; /* not an array */
/* collect the element type for common-supertype choice */
anycompatible_actual_types [ n_anycompatible_args + + ] = elem_type ;
}
else if ( decl_type = = ANYCOMPATIBLERANGEOID )
{
if ( actual_type = = UNKNOWNOID )
continue ;
actual_type = getBaseType ( actual_type ) ; /* flatten domains */
if ( OidIsValid ( anycompatible_range_typeid ) )
{
/* All ANYCOMPATIBLERANGE arguments must be the same type */
if ( anycompatible_range_typeid ! = actual_type )
return false ;
}
else
{
anycompatible_range_typeid = actual_type ;
anycompatible_range_typelem = get_range_subtype ( actual_type ) ;
if ( ! OidIsValid ( anycompatible_range_typelem ) )
return false ; /* not a range type */
/* collect the subtype for common-supertype choice */
anycompatible_actual_types [ n_anycompatible_args + + ] = anycompatible_range_typelem ;
}
}
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
else if ( decl_type = = ANYCOMPATIBLEMULTIRANGEOID )
{
if ( actual_type = = UNKNOWNOID )
continue ;
actual_type = getBaseType ( actual_type ) ; /* flatten domains */
if ( OidIsValid ( anycompatible_multirange_typeid ) )
{
/* All ANYCOMPATIBLEMULTIRANGE arguments must be the same type */
if ( anycompatible_multirange_typeid ! = actual_type )
return false ;
}
else
{
anycompatible_multirange_typeid = actual_type ;
anycompatible_multirange_typelem = get_multirange_range ( actual_type ) ;
if ( ! OidIsValid ( anycompatible_multirange_typelem ) )
return false ; /* not a multirange type */
2021-07-27 15:01:49 -04:00
/* we'll consider the subtype below */
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
}
}
2003-04-08 19:20:04 -04:00
}
/* Get the element type based on the array type, if we have one */
if ( OidIsValid ( array_typeid ) )
{
2003-09-23 13:12:53 -04:00
if ( array_typeid = = ANYARRAYOID )
2003-04-08 19:20:04 -04:00
{
/*
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
* Special case for matching ANYARRAY input to an ANYARRAY
* argument : allow it for now . enforce_generic_type_consistency ( )
* might complain later , depending on the presence of other
* polymorphic arguments or results , but it will deliver a less
* surprising error message than " function does not exist " .
*
* ( If you think to change this , note that can_coerce_type will
* consider such a situation as a match , so that we might not even
* get here . )
2003-04-08 19:20:04 -04:00
*/
}
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
else
2003-04-08 19:20:04 -04:00
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
Oid array_typelem ;
array_typelem = get_element_type ( array_typeid ) ;
if ( ! OidIsValid ( array_typelem ) )
return false ; /* should be an array, but isn't */
if ( ! OidIsValid ( elem_typeid ) )
{
/*
* if we don ' t have an element type yet , use the one we just
* got
*/
elem_typeid = array_typelem ;
}
else if ( array_typelem ! = elem_typeid )
{
/* otherwise, they better match */
return false ;
}
2003-04-08 19:20:04 -04:00
}
}
2021-07-27 15:01:49 -04:00
/* Deduce range type from multirange type, or check that they agree */
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
if ( OidIsValid ( multirange_typeid ) )
{
Oid multirange_typelem ;
multirange_typelem = get_multirange_range ( multirange_typeid ) ;
if ( ! OidIsValid ( multirange_typelem ) )
return false ; /* should be a multirange, but isn't */
if ( ! OidIsValid ( range_typeid ) )
{
2021-07-27 15:01:49 -04:00
/* If we don't have a range type yet, use the one we just got */
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
range_typeid = multirange_typelem ;
range_typelem = get_range_subtype ( multirange_typelem ) ;
if ( ! OidIsValid ( range_typelem ) )
return false ; /* should be a range, but isn't */
}
else if ( multirange_typelem ! = range_typeid )
{
/* otherwise, they better match */
return false ;
}
2021-07-27 15:01:49 -04:00
}
/* Get the element type based on the range type, if we have one */
if ( OidIsValid ( range_typeid ) )
{
range_typelem = get_range_subtype ( range_typeid ) ;
if ( ! OidIsValid ( range_typelem ) )
return false ; /* should be a range, but isn't */
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
if ( ! OidIsValid ( elem_typeid ) )
{
/*
* If we don ' t have an element type yet , use the one we just got
*/
elem_typeid = range_typelem ;
}
else if ( range_typelem ! = elem_typeid )
{
/* otherwise, they better match */
return false ;
}
}
2011-11-20 23:50:27 -05:00
if ( have_anynonarray )
{
/* require the element type to not be an array or domain over array */
if ( type_is_array_domain ( elem_typeid ) )
return false ;
}
if ( have_anyenum )
{
/* require the element type to be an enum */
if ( ! type_is_enum ( elem_typeid ) )
return false ;
}
2021-07-27 15:01:49 -04:00
/* Deduce range type from multirange type, or check that they agree */
if ( OidIsValid ( anycompatible_multirange_typeid ) )
{
if ( OidIsValid ( anycompatible_range_typeid ) )
{
if ( anycompatible_multirange_typelem ! =
anycompatible_range_typeid )
return false ;
}
else
{
anycompatible_range_typeid = anycompatible_multirange_typelem ;
anycompatible_range_typelem = get_range_subtype ( anycompatible_range_typeid ) ;
if ( ! OidIsValid ( anycompatible_range_typelem ) )
return false ; /* not a range type */
/* collect the subtype for common-supertype choice */
anycompatible_actual_types [ n_anycompatible_args + + ] =
anycompatible_range_typelem ;
}
}
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/* Check matching of ANYCOMPATIBLE-family arguments, if any */
if ( n_anycompatible_args > 0 )
{
Oid anycompatible_typeid ;
anycompatible_typeid =
select_common_type_from_oids ( n_anycompatible_args ,
anycompatible_actual_types ,
true ) ;
if ( ! OidIsValid ( anycompatible_typeid ) )
Fix failure to validate the result of select_common_type().
Although select_common_type() has a failure-return convention, an
apparent successful return just provides a type OID that *might* work
as a common supertype; we've not validated that the required casts
actually exist. In the mainstream use-cases that doesn't matter,
because we'll proceed to invoke coerce_to_common_type() on each input,
which will fail appropriately if the proposed common type doesn't
actually work. However, a few callers didn't read the (nonexistent)
fine print, and thought that if they got back a nonzero OID then the
coercions were sure to work.
This affects in particular the recently-added "anycompatible"
polymorphic types; we might think that a function/operator using
such types matches cases it really doesn't. A likely end result
of that is unexpected "ambiguous operator" errors, as for example
in bug #17387 from James Inform. Another, much older, case is that
the parser might try to transform an "x IN (list)" construct to
a ScalarArrayOpExpr even when the list elements don't actually have
a common supertype.
It doesn't seem desirable to add more checking to select_common_type
itself, as that'd just slow down the mainstream use-cases. Instead,
write a separate function verify_common_type that performs the
missing checks, and add a call to that where necessary. Likewise add
verify_common_type_from_oids to go with select_common_type_from_oids.
Back-patch to v13 where the "anycompatible" types came in. (The
symptom complained of in bug #17387 doesn't appear till v14, but
that's just because we didn't get around to converting || to use
anycompatible till then.) In principle the "x IN (list)" fix could
go back all the way, but I'm not currently convinced that it makes
much difference in real-world cases, so I won't bother for now.
Discussion: https://postgr.es/m/17387-5dfe54b988444963@postgresql.org
2022-01-29 11:41:12 -05:00
return false ; /* there's definitely no common supertype */
/* We have to verify that the selected type actually works */
if ( ! verify_common_type_from_oids ( anycompatible_typeid ,
n_anycompatible_args ,
anycompatible_actual_types ) )
return false ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
if ( have_anycompatible_nonarray )
{
/*
* require the anycompatible type to not be an array or domain
* over array
*/
if ( type_is_array_domain ( anycompatible_typeid ) )
return false ;
}
/*
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
* The anycompatible type must exactly match the range element type ,
* if we were able to identify one . This checks compatibility for
* anycompatiblemultirange too since that also sets
* anycompatible_range_typelem above .
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
*/
if ( OidIsValid ( anycompatible_range_typelem ) & &
anycompatible_range_typelem ! = anycompatible_typeid )
return false ;
}
2003-04-08 19:20:04 -04:00
/* Looks valid */
return true ;
}
/*
* enforce_generic_type_consistency ( )
* Make sure a polymorphic function is legally callable , and
* deduce actual argument and result types .
*
2007-06-06 19:00:50 -04:00
* If any polymorphic pseudotype is used in a function ' s arguments or
2003-04-08 19:20:04 -04:00
* return type , we make sure the actual data types are consistent with
2011-11-20 23:50:27 -05:00
* each other . The argument consistency rules are shown above for
2003-04-08 19:20:04 -04:00
* check_generic_type_consistency ( ) .
*
2007-04-01 23:49:42 -04:00
* If we have UNKNOWN input ( ie , an untyped literal ) for any polymorphic
* argument , we attempt to deduce the actual type it should have . If
* successful , we alter that position of declared_arg_types [ ] so that
* make_fn_arguments will coerce the literal to the right thing .
2003-04-08 19:20:04 -04:00
*
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
* If we have polymorphic arguments of the ANYCOMPATIBLE family ,
* we similarly alter declared_arg_types [ ] entries to show the resolved
* common supertype , so that make_fn_arguments will coerce the actual
* arguments to the proper type .
*
2003-04-08 19:20:04 -04:00
* Rules are applied to the function ' s return type ( possibly altering it )
2020-04-04 18:03:30 -04:00
* if it is declared as a polymorphic type and there is at least one
* polymorphic argument type :
2003-04-08 19:20:04 -04:00
*
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
* 1 ) If return type is ANYELEMENT , and any argument is ANYELEMENT , use the
2011-11-20 23:50:27 -05:00
* argument ' s actual type as the function ' s return type .
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
* 2 ) If return type is ANYARRAY , and any argument is ANYARRAY , use the
2011-11-20 23:50:27 -05:00
* argument ' s actual type as the function ' s return type .
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
* 3 ) Similarly , if return type is ANYRANGE or ANYMULTIRANGE , and any
2021-07-27 15:01:49 -04:00
* argument is ANYRANGE or ANYMULTIRANGE , use that argument ' s actual type
* ( or the corresponding range or multirange type ) as the function ' s return
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
* type .
2021-07-27 15:01:49 -04:00
* 4 ) Otherwise , if return type is ANYELEMENT or ANYARRAY , and there is
* at least one ANYELEMENT , ANYARRAY , ANYRANGE , or ANYMULTIRANGE input ,
* deduce the return type from those inputs , or throw error if we can ' t .
* 5 ) Otherwise , if return type is ANYRANGE or ANYMULTIRANGE , throw error .
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
* ( We have no way to select a specific range type if the arguments don ' t
2021-07-27 15:01:49 -04:00
* include ANYRANGE or ANYMULTIRANGE . )
* 6 ) ANYENUM is treated the same as ANYELEMENT except that if it is used
2011-11-20 23:50:27 -05:00
* ( alone or in combination with plain ANYELEMENT ) , we add the extra
* condition that the ANYELEMENT type must be an enum .
2021-07-27 15:01:49 -04:00
* 7 ) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used ,
2011-11-20 23:50:27 -05:00
* we add the extra condition that the ANYELEMENT type must not be an array .
* ( This is a no - op if used in combination with ANYARRAY or ANYENUM , but
* is an extra restriction if not . )
2021-07-27 15:01:49 -04:00
* 8 ) ANYCOMPATIBLE , ANYCOMPATIBLEARRAY , and ANYCOMPATIBLENONARRAY are handled
* by resolving the common supertype of those arguments ( or their element
* types , for array inputs ) , and then coercing all those arguments to the
* common supertype , or the array type over the common supertype for
* ANYCOMPATIBLEARRAY .
* 9 ) For ANYCOMPATIBLERANGE and ANYCOMPATIBLEMULTIRANGE , there must be at
* least one non - UNKNOWN input matching those arguments , and all such
* inputs must be the same range type ( or its multirange type , as
* appropriate ) , since we cannot deduce a range type from non - range types .
* Furthermore , the range type ' s subtype is included while choosing the
* common supertype for ANYCOMPATIBLE et al , and it must exactly match
* that common supertype .
2008-01-11 13:39:41 -05:00
*
2011-11-03 07:16:28 -04:00
* Domains over arrays or ranges match ANYARRAY or ANYRANGE arguments ,
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
* respectively , and are immediately flattened to their base type . ( In
* particular , if the return type is also ANYARRAY or ANYRANGE , we ' ll set
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
* it to the base type not the domain type . ) The same is true for
2021-07-27 15:01:49 -04:00
* ANYMULTIRANGE , ANYCOMPATIBLEARRAY , ANYCOMPATIBLERANGE , and
* ANYCOMPATIBLEMULTIRANGE .
2011-06-08 12:52:12 -04:00
*
2008-01-11 13:39:41 -05:00
* When allow_poly is false , we are not expecting any of the actual_arg_types
* to be polymorphic , and we should not return a polymorphic result type
2011-11-20 23:50:27 -05:00
* either . When allow_poly is true , it is okay to have polymorphic " actual "
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
* arg types , and we can return a matching polymorphic type as the result .
* ( This case is currently used only to check compatibility of an aggregate ' s
* declaration with the underlying transfn . )
2008-12-14 14:45:52 -05:00
*
* A special case is that we could see ANYARRAY as an actual_arg_type even
* when allow_poly is false ( this is possible only because pg_statistic has
2011-11-20 23:50:27 -05:00
* columns shown as anyarray in the catalogs ) . We allow this to match a
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
* declared ANYARRAY argument , but only if there is no other polymorphic
* argument that we would need to match it with , and no need to determine
* the element type to infer the result type . Note this means that functions
* taking ANYARRAY had better behave sanely if applied to the pg_statistic
* columns ; they can ' t just assume that successive inputs are of the same
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
* actual element type . There is no similar logic for ANYCOMPATIBLEARRAY ;
* there isn ' t a need for it since there are no catalog columns of that type ,
* so we won ' t see it as input . We could consider matching an actual ANYARRAY
* input to an ANYCOMPATIBLEARRAY argument , but at present that seems useless
* as well , since there ' s no value in using ANYCOMPATIBLEARRAY unless there ' s
* at least one other ANYCOMPATIBLE - family argument or result .
2020-04-04 18:03:30 -04:00
*
* Also , if there are no arguments declared to be of polymorphic types ,
* we ' ll return the rettype unmodified even if it ' s polymorphic . This should
* never occur for user - declared functions , because CREATE FUNCTION prevents
* it . But it does happen for some built - in functions , such as array_in ( ) .
2003-04-08 19:20:04 -04:00
*/
Oid
2018-10-23 06:17:16 -04:00
enforce_generic_type_consistency ( const Oid * actual_arg_types ,
2003-04-08 19:20:04 -04:00
Oid * declared_arg_types ,
int nargs ,
2008-01-11 13:39:41 -05:00
Oid rettype ,
bool allow_poly )
2003-04-08 19:20:04 -04:00
{
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
bool have_poly_anycompatible = false ;
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
bool have_poly_unknowns = false ;
2003-04-08 19:20:04 -04:00
Oid elem_typeid = InvalidOid ;
Oid array_typeid = InvalidOid ;
2011-11-03 07:16:28 -04:00
Oid range_typeid = InvalidOid ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
Oid multirange_typeid = InvalidOid ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
Oid anycompatible_typeid = InvalidOid ;
Oid anycompatible_array_typeid = InvalidOid ;
Oid anycompatible_range_typeid = InvalidOid ;
Oid anycompatible_range_typelem = InvalidOid ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
Oid anycompatible_multirange_typeid = InvalidOid ;
Oid anycompatible_multirange_typelem = InvalidOid ;
2007-06-06 19:00:50 -04:00
bool have_anynonarray = ( rettype = = ANYNONARRAYOID ) ;
2007-04-01 23:49:42 -04:00
bool have_anyenum = ( rettype = = ANYENUMOID ) ;
2021-07-27 15:01:49 -04:00
bool have_anymultirange = ( rettype = = ANYMULTIRANGEOID ) ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
bool have_anycompatible_nonarray = ( rettype = = ANYCOMPATIBLENONARRAYOID ) ;
bool have_anycompatible_array = ( rettype = = ANYCOMPATIBLEARRAYOID ) ;
bool have_anycompatible_range = ( rettype = = ANYCOMPATIBLERANGEOID ) ;
2021-07-27 15:01:49 -04:00
bool have_anycompatible_multirange = ( rettype = = ANYCOMPATIBLEMULTIRANGEOID ) ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
int n_poly_args = 0 ; /* this counts all family-1 arguments */
int n_anycompatible_args = 0 ; /* this counts only non-unknowns */
Oid anycompatible_actual_types [ FUNC_MAX_ARGS ] ;
2003-04-08 19:20:04 -04:00
/*
2007-06-06 19:00:50 -04:00
* Loop through the arguments to see if we have any that are polymorphic .
* If so , require the actual types to be consistent .
2003-04-08 19:20:04 -04:00
*/
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
Assert ( nargs < = FUNC_MAX_ARGS ) ;
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
for ( int j = 0 ; j < nargs ; j + + )
2003-04-08 19:20:04 -04:00
{
2007-06-06 19:00:50 -04:00
Oid decl_type = declared_arg_types [ j ] ;
2003-04-08 19:20:04 -04:00
Oid actual_type = actual_arg_types [ j ] ;
2007-06-06 19:00:50 -04:00
if ( decl_type = = ANYELEMENTOID | |
decl_type = = ANYNONARRAYOID | |
decl_type = = ANYENUMOID )
2003-04-08 19:20:04 -04:00
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
n_poly_args + + ;
2007-06-06 19:00:50 -04:00
if ( decl_type = = ANYNONARRAYOID )
have_anynonarray = true ;
else if ( decl_type = = ANYENUMOID )
2007-04-01 23:49:42 -04:00
have_anyenum = true ;
2003-04-08 19:20:04 -04:00
if ( actual_type = = UNKNOWNOID )
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
have_poly_unknowns = true ;
2003-04-08 19:20:04 -04:00
continue ;
}
2008-01-11 13:39:41 -05:00
if ( allow_poly & & decl_type = = actual_type )
continue ; /* no new information here */
2003-04-08 19:20:04 -04:00
if ( OidIsValid ( elem_typeid ) & & actual_type ! = elem_typeid )
2003-07-19 16:20:53 -04:00
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
2021-05-12 01:20:10 -04:00
errmsg ( " arguments declared \" %s \" are not all alike " , " anyelement " ) ,
2003-07-19 16:20:53 -04:00
errdetail ( " %s versus %s " ,
format_type_be ( elem_typeid ) ,
format_type_be ( actual_type ) ) ) ) ;
2003-04-08 19:20:04 -04:00
elem_typeid = actual_type ;
}
2007-06-06 19:00:50 -04:00
else if ( decl_type = = ANYARRAYOID )
2003-04-08 19:20:04 -04:00
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
n_poly_args + + ;
2003-04-08 19:20:04 -04:00
if ( actual_type = = UNKNOWNOID )
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
have_poly_unknowns = true ;
2003-04-08 19:20:04 -04:00
continue ;
}
2008-01-11 13:39:41 -05:00
if ( allow_poly & & decl_type = = actual_type )
continue ; /* no new information here */
2011-06-08 12:52:12 -04:00
actual_type = getBaseType ( actual_type ) ; /* flatten domains */
2003-04-08 19:20:04 -04:00
if ( OidIsValid ( array_typeid ) & & actual_type ! = array_typeid )
2003-07-19 16:20:53 -04:00
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
2021-05-12 01:20:10 -04:00
errmsg ( " arguments declared \" %s \" are not all alike " , " anyarray " ) ,
2003-07-19 16:20:53 -04:00
errdetail ( " %s versus %s " ,
format_type_be ( array_typeid ) ,
format_type_be ( actual_type ) ) ) ) ;
2003-04-08 19:20:04 -04:00
array_typeid = actual_type ;
}
2011-11-03 07:16:28 -04:00
else if ( decl_type = = ANYRANGEOID )
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
n_poly_args + + ;
2011-11-03 07:16:28 -04:00
if ( actual_type = = UNKNOWNOID )
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
have_poly_unknowns = true ;
2011-11-03 07:16:28 -04:00
continue ;
}
if ( allow_poly & & decl_type = = actual_type )
continue ; /* no new information here */
actual_type = getBaseType ( actual_type ) ; /* flatten domains */
if ( OidIsValid ( range_typeid ) & & actual_type ! = range_typeid )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
2021-05-12 01:20:10 -04:00
errmsg ( " arguments declared \" %s \" are not all alike " , " anyrange " ) ,
2011-11-03 07:16:28 -04:00
errdetail ( " %s versus %s " ,
format_type_be ( range_typeid ) ,
format_type_be ( actual_type ) ) ) ) ;
range_typeid = actual_type ;
}
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
else if ( decl_type = = ANYMULTIRANGEOID )
{
n_poly_args + + ;
2021-07-27 15:01:49 -04:00
have_anymultirange = true ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
if ( actual_type = = UNKNOWNOID )
{
have_poly_unknowns = true ;
continue ;
}
if ( allow_poly & & decl_type = = actual_type )
continue ; /* no new information here */
actual_type = getBaseType ( actual_type ) ; /* flatten domains */
if ( OidIsValid ( multirange_typeid ) & & actual_type ! = multirange_typeid )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
2021-05-12 01:20:10 -04:00
errmsg ( " arguments declared \" %s \" are not all alike " , " anymultirange " ) ,
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
errdetail ( " %s versus %s " ,
format_type_be ( multirange_typeid ) ,
format_type_be ( actual_type ) ) ) ) ;
multirange_typeid = actual_type ;
}
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
else if ( decl_type = = ANYCOMPATIBLEOID | |
decl_type = = ANYCOMPATIBLENONARRAYOID )
{
have_poly_anycompatible = true ;
if ( decl_type = = ANYCOMPATIBLENONARRAYOID )
have_anycompatible_nonarray = true ;
if ( actual_type = = UNKNOWNOID )
continue ;
if ( allow_poly & & decl_type = = actual_type )
continue ; /* no new information here */
/* collect the actual types of non-unknown COMPATIBLE args */
anycompatible_actual_types [ n_anycompatible_args + + ] = actual_type ;
}
else if ( decl_type = = ANYCOMPATIBLEARRAYOID )
{
Oid anycompatible_elem_type ;
have_poly_anycompatible = true ;
have_anycompatible_array = true ;
if ( actual_type = = UNKNOWNOID )
continue ;
if ( allow_poly & & decl_type = = actual_type )
continue ; /* no new information here */
actual_type = getBaseType ( actual_type ) ; /* flatten domains */
anycompatible_elem_type = get_element_type ( actual_type ) ;
if ( ! OidIsValid ( anycompatible_elem_type ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " argument declared %s is not an array but type %s " ,
" anycompatiblearray " ,
format_type_be ( actual_type ) ) ) ) ;
/* collect the element type for common-supertype choice */
anycompatible_actual_types [ n_anycompatible_args + + ] = anycompatible_elem_type ;
}
else if ( decl_type = = ANYCOMPATIBLERANGEOID )
{
have_poly_anycompatible = true ;
have_anycompatible_range = true ;
if ( actual_type = = UNKNOWNOID )
continue ;
if ( allow_poly & & decl_type = = actual_type )
continue ; /* no new information here */
actual_type = getBaseType ( actual_type ) ; /* flatten domains */
if ( OidIsValid ( anycompatible_range_typeid ) )
{
/* All ANYCOMPATIBLERANGE arguments must be the same type */
if ( anycompatible_range_typeid ! = actual_type )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
2021-05-12 01:20:10 -04:00
errmsg ( " arguments declared \" %s \" are not all alike " , " anycompatiblerange " ) ,
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
errdetail ( " %s versus %s " ,
format_type_be ( anycompatible_range_typeid ) ,
format_type_be ( actual_type ) ) ) ) ;
}
else
{
anycompatible_range_typeid = actual_type ;
anycompatible_range_typelem = get_range_subtype ( actual_type ) ;
if ( ! OidIsValid ( anycompatible_range_typelem ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " argument declared %s is not a range type but type %s " ,
" anycompatiblerange " ,
format_type_be ( actual_type ) ) ) ) ;
/* collect the subtype for common-supertype choice */
anycompatible_actual_types [ n_anycompatible_args + + ] = anycompatible_range_typelem ;
}
}
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
else if ( decl_type = = ANYCOMPATIBLEMULTIRANGEOID )
{
have_poly_anycompatible = true ;
2021-07-27 15:01:49 -04:00
have_anycompatible_multirange = true ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
if ( actual_type = = UNKNOWNOID )
continue ;
if ( allow_poly & & decl_type = = actual_type )
continue ; /* no new information here */
actual_type = getBaseType ( actual_type ) ; /* flatten domains */
if ( OidIsValid ( anycompatible_multirange_typeid ) )
{
/* All ANYCOMPATIBLEMULTIRANGE arguments must be the same type */
if ( anycompatible_multirange_typeid ! = actual_type )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
2021-05-12 01:20:10 -04:00
errmsg ( " arguments declared \" %s \" are not all alike " , " anycompatiblemultirange " ) ,
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
errdetail ( " %s versus %s " ,
format_type_be ( anycompatible_multirange_typeid ) ,
format_type_be ( actual_type ) ) ) ) ;
}
else
{
anycompatible_multirange_typeid = actual_type ;
anycompatible_multirange_typelem = get_multirange_range ( actual_type ) ;
if ( ! OidIsValid ( anycompatible_multirange_typelem ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " argument declared %s is not a multirange type but type %s " ,
" anycompatiblemultirange " ,
format_type_be ( actual_type ) ) ) ) ;
2021-07-27 15:01:49 -04:00
/* we'll consider the subtype below */
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
}
}
2003-04-08 19:20:04 -04:00
}
/*
2007-04-01 23:49:42 -04:00
* Fast Track : if none of the arguments are polymorphic , return the
2020-04-04 18:03:30 -04:00
* unmodified rettype . Not our job to resolve it if it ' s polymorphic .
2003-04-08 19:20:04 -04:00
*/
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
if ( n_poly_args = = 0 & & ! have_poly_anycompatible )
2003-04-08 19:20:04 -04:00
return rettype ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/* Check matching of family-1 polymorphic arguments, if any */
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
if ( n_poly_args )
2003-04-08 19:20:04 -04:00
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
/* Get the element type based on the array type, if we have one */
if ( OidIsValid ( array_typeid ) )
2008-12-14 14:45:52 -05:00
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
Oid array_typelem ;
if ( array_typeid = = ANYARRAYOID )
{
/*
* Special case for matching ANYARRAY input to an ANYARRAY
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
* argument : allow it iff no other arguments are family - 1
* polymorphics ( otherwise we couldn ' t be sure whether the
* array element type matches up ) and the result type doesn ' t
* require us to infer a specific element type .
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
*/
if ( n_poly_args ! = 1 | |
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
( rettype ! = ANYARRAYOID & &
IsPolymorphicTypeFamily1 ( rettype ) ) )
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " cannot determine element type of \" anyarray \" argument " ) ) ) ;
array_typelem = ANYELEMENTOID ;
}
else
{
array_typelem = get_element_type ( array_typeid ) ;
if ( ! OidIsValid ( array_typelem ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " argument declared %s is not an array but type %s " ,
" anyarray " , format_type_be ( array_typeid ) ) ) ) ;
}
if ( ! OidIsValid ( elem_typeid ) )
{
/*
* if we don ' t have an element type yet , use the one we just
* got
*/
elem_typeid = array_typelem ;
}
else if ( array_typelem ! = elem_typeid )
{
/* otherwise, they better match */
2008-12-14 14:45:52 -05:00
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
errmsg ( " argument declared %s is not consistent with argument declared %s " ,
" anyarray " , " anyelement " ) ,
errdetail ( " %s versus %s " ,
format_type_be ( array_typeid ) ,
format_type_be ( elem_typeid ) ) ) ) ;
}
2008-12-14 14:45:52 -05:00
}
2003-04-08 19:20:04 -04:00
2021-07-27 15:01:49 -04:00
/* Deduce range type from multirange type, or vice versa */
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
if ( OidIsValid ( multirange_typeid ) )
{
2021-07-27 15:01:49 -04:00
Oid multirange_typelem ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
multirange_typelem = get_multirange_range ( multirange_typeid ) ;
if ( ! OidIsValid ( multirange_typelem ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " argument declared %s is not a multirange type but type %s " ,
" anymultirange " ,
format_type_be ( multirange_typeid ) ) ) ) ;
if ( ! OidIsValid ( range_typeid ) )
{
2021-07-27 15:01:49 -04:00
/* if we don't have a range type yet, use the one we just got */
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
range_typeid = multirange_typelem ;
}
else if ( multirange_typelem ! = range_typeid )
{
/* otherwise, they better match */
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " argument declared %s is not consistent with argument declared %s " ,
" anymultirange " , " anyrange " ) ,
errdetail ( " %s versus %s " ,
format_type_be ( multirange_typeid ) ,
format_type_be ( range_typeid ) ) ) ) ;
}
2021-07-27 15:01:49 -04:00
}
else if ( have_anymultirange & & OidIsValid ( range_typeid ) )
{
multirange_typeid = get_range_multirange ( range_typeid ) ;
/* We'll complain below if that didn't work */
}
/* Get the element type based on the range type, if we have one */
if ( OidIsValid ( range_typeid ) )
{
Oid range_typelem ;
range_typelem = get_range_subtype ( range_typeid ) ;
if ( ! OidIsValid ( range_typelem ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " argument declared %s is not a range type but type %s " ,
" anyrange " ,
format_type_be ( range_typeid ) ) ) ) ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
if ( ! OidIsValid ( elem_typeid ) )
{
/*
2021-01-04 11:03:22 -05:00
* if we don ' t have an element type yet , use the one we just
* got
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
*/
elem_typeid = range_typelem ;
}
else if ( range_typelem ! = elem_typeid )
{
/* otherwise, they better match */
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " argument declared %s is not consistent with argument declared %s " ,
2021-07-27 15:01:49 -04:00
" anyrange " , " anyelement " ) ,
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
errdetail ( " %s versus %s " ,
2021-07-27 15:01:49 -04:00
format_type_be ( range_typeid ) ,
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
format_type_be ( elem_typeid ) ) ) ) ;
}
}
2011-11-03 07:16:28 -04:00
if ( ! OidIsValid ( elem_typeid ) )
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
if ( allow_poly )
{
elem_typeid = ANYELEMENTOID ;
array_typeid = ANYARRAYOID ;
range_typeid = ANYRANGEOID ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
multirange_typeid = ANYMULTIRANGEOID ;
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
}
else
{
/*
2020-09-07 14:52:33 -04:00
* Only way to get here is if all the family - 1 polymorphic
* arguments have UNKNOWN inputs .
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
*/
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " could not determine polymorphic type because input has type %s " ,
" unknown " ) ) ) ;
}
2011-11-03 07:16:28 -04:00
}
2011-11-20 23:50:27 -05:00
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
if ( have_anynonarray & & elem_typeid ! = ANYELEMENTOID )
2008-01-11 13:39:41 -05:00
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
/*
* require the element type to not be an array or domain over
* array
*/
if ( type_is_array_domain ( elem_typeid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " type matched to anynonarray is an array type: %s " ,
format_type_be ( elem_typeid ) ) ) ) ;
2008-01-11 13:39:41 -05:00
}
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
if ( have_anyenum & & elem_typeid ! = ANYELEMENTOID )
2008-01-11 13:39:41 -05:00
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
/* require the element type to be an enum */
if ( ! type_is_enum ( elem_typeid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " type matched to anyenum is not an enum type: %s " ,
format_type_be ( elem_typeid ) ) ) ) ;
2008-01-11 13:39:41 -05:00
}
2007-04-01 23:49:42 -04:00
}
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/* Check matching of family-2 polymorphic arguments, if any */
if ( have_poly_anycompatible )
{
2021-07-27 15:01:49 -04:00
/* Deduce range type from multirange type, or vice versa */
if ( OidIsValid ( anycompatible_multirange_typeid ) )
{
if ( OidIsValid ( anycompatible_range_typeid ) )
{
if ( anycompatible_multirange_typelem ! =
anycompatible_range_typeid )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " argument declared %s is not consistent with argument declared %s " ,
" anycompatiblemultirange " ,
" anycompatiblerange " ) ,
errdetail ( " %s versus %s " ,
format_type_be ( anycompatible_multirange_typeid ) ,
format_type_be ( anycompatible_range_typeid ) ) ) ) ;
}
else
{
anycompatible_range_typeid = anycompatible_multirange_typelem ;
anycompatible_range_typelem = get_range_subtype ( anycompatible_range_typeid ) ;
if ( ! OidIsValid ( anycompatible_range_typelem ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " argument declared %s is not a multirange type but type %s " ,
" anycompatiblemultirange " ,
format_type_be ( anycompatible_multirange_typeid ) ) ) ) ;
/* this enables element type matching check below */
have_anycompatible_range = true ;
/* collect the subtype for common-supertype choice */
anycompatible_actual_types [ n_anycompatible_args + + ] =
anycompatible_range_typelem ;
}
}
else if ( have_anycompatible_multirange & &
OidIsValid ( anycompatible_range_typeid ) )
{
anycompatible_multirange_typeid = get_range_multirange ( anycompatible_range_typeid ) ;
/* We'll complain below if that didn't work */
}
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
if ( n_anycompatible_args > 0 )
{
anycompatible_typeid =
select_common_type_from_oids ( n_anycompatible_args ,
anycompatible_actual_types ,
false ) ;
Fix failure to validate the result of select_common_type().
Although select_common_type() has a failure-return convention, an
apparent successful return just provides a type OID that *might* work
as a common supertype; we've not validated that the required casts
actually exist. In the mainstream use-cases that doesn't matter,
because we'll proceed to invoke coerce_to_common_type() on each input,
which will fail appropriately if the proposed common type doesn't
actually work. However, a few callers didn't read the (nonexistent)
fine print, and thought that if they got back a nonzero OID then the
coercions were sure to work.
This affects in particular the recently-added "anycompatible"
polymorphic types; we might think that a function/operator using
such types matches cases it really doesn't. A likely end result
of that is unexpected "ambiguous operator" errors, as for example
in bug #17387 from James Inform. Another, much older, case is that
the parser might try to transform an "x IN (list)" construct to
a ScalarArrayOpExpr even when the list elements don't actually have
a common supertype.
It doesn't seem desirable to add more checking to select_common_type
itself, as that'd just slow down the mainstream use-cases. Instead,
write a separate function verify_common_type that performs the
missing checks, and add a call to that where necessary. Likewise add
verify_common_type_from_oids to go with select_common_type_from_oids.
Back-patch to v13 where the "anycompatible" types came in. (The
symptom complained of in bug #17387 doesn't appear till v14, but
that's just because we didn't get around to converting || to use
anycompatible till then.) In principle the "x IN (list)" fix could
go back all the way, but I'm not currently convinced that it makes
much difference in real-world cases, so I won't bother for now.
Discussion: https://postgr.es/m/17387-5dfe54b988444963@postgresql.org
2022-01-29 11:41:12 -05:00
/* We have to verify that the selected type actually works */
if ( ! verify_common_type_from_oids ( anycompatible_typeid ,
n_anycompatible_args ,
anycompatible_actual_types ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " arguments of anycompatible family cannot be cast to a common type " ) ) ) ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
if ( have_anycompatible_array )
{
anycompatible_array_typeid = get_array_type ( anycompatible_typeid ) ;
if ( ! OidIsValid ( anycompatible_array_typeid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_OBJECT ) ,
errmsg ( " could not find array type for data type %s " ,
format_type_be ( anycompatible_typeid ) ) ) ) ;
}
if ( have_anycompatible_range )
{
/* we can't infer a range type from the others */
if ( ! OidIsValid ( anycompatible_range_typeid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " could not determine polymorphic type %s because input has type %s " ,
" anycompatiblerange " , " unknown " ) ) ) ;
/*
* the anycompatible type must exactly match the range element
* type
*/
if ( anycompatible_range_typelem ! = anycompatible_typeid )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " anycompatiblerange type %s does not match anycompatible type %s " ,
format_type_be ( anycompatible_range_typeid ) ,
format_type_be ( anycompatible_typeid ) ) ) ) ;
}
2021-07-27 15:01:49 -04:00
if ( have_anycompatible_multirange )
{
/* we can't infer a multirange type from the others */
if ( ! OidIsValid ( anycompatible_multirange_typeid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " could not determine polymorphic type %s because input has type %s " ,
" anycompatiblemultirange " , " unknown " ) ) ) ;
/*
* the anycompatible type must exactly match the multirange
* element type
*/
if ( anycompatible_range_typelem ! = anycompatible_typeid )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " anycompatiblemultirange type %s does not match anycompatible type %s " ,
format_type_be ( anycompatible_multirange_typeid ) ,
format_type_be ( anycompatible_typeid ) ) ) ) ;
}
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
if ( have_anycompatible_nonarray )
{
/*
* require the element type to not be an array or domain over
* array
*/
if ( type_is_array_domain ( anycompatible_typeid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " type matched to anycompatiblenonarray is an array type: %s " ,
format_type_be ( anycompatible_typeid ) ) ) ) ;
}
}
else
{
if ( allow_poly )
{
anycompatible_typeid = ANYCOMPATIBLEOID ;
anycompatible_array_typeid = ANYCOMPATIBLEARRAYOID ;
anycompatible_range_typeid = ANYCOMPATIBLERANGEOID ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
anycompatible_multirange_typeid = ANYCOMPATIBLEMULTIRANGEOID ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
}
else
{
/*
2020-09-07 14:52:33 -04:00
* Only way to get here is if all the family - 2 polymorphic
* arguments have UNKNOWN inputs . Resolve to TEXT as
* select_common_type ( ) would do . That doesn ' t license us to
2021-07-27 15:01:49 -04:00
* use TEXTRANGE or TEXTMULTIRANGE , though .
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
*/
anycompatible_typeid = TEXTOID ;
anycompatible_array_typeid = TEXTARRAYOID ;
if ( have_anycompatible_range )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " could not determine polymorphic type %s because input has type %s " ,
" anycompatiblerange " , " unknown " ) ) ) ;
2021-07-27 15:01:49 -04:00
if ( have_anycompatible_multirange )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " could not determine polymorphic type %s because input has type %s " ,
" anycompatiblemultirange " , " unknown " ) ) ) ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
}
}
2020-09-07 14:52:33 -04:00
/* replace family-2 polymorphic types by selected types */
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
for ( int j = 0 ; j < nargs ; j + + )
{
Oid decl_type = declared_arg_types [ j ] ;
if ( decl_type = = ANYCOMPATIBLEOID | |
decl_type = = ANYCOMPATIBLENONARRAYOID )
declared_arg_types [ j ] = anycompatible_typeid ;
else if ( decl_type = = ANYCOMPATIBLEARRAYOID )
declared_arg_types [ j ] = anycompatible_array_typeid ;
else if ( decl_type = = ANYCOMPATIBLERANGEOID )
declared_arg_types [ j ] = anycompatible_range_typeid ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
else if ( decl_type = = ANYCOMPATIBLEMULTIRANGEOID )
declared_arg_types [ j ] = anycompatible_multirange_typeid ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
}
}
2003-04-08 19:20:04 -04:00
/*
2020-09-07 14:52:33 -04:00
* If we had any UNKNOWN inputs for family - 1 polymorphic arguments ,
* re - scan to assign correct types to them .
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
*
* Note : we don ' t have to consider unknown inputs that were matched to
2020-09-07 14:52:33 -04:00
* family - 2 polymorphic arguments , because we forcibly updated their
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
* declared_arg_types [ ] positions just above .
2003-04-08 19:20:04 -04:00
*/
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
if ( have_poly_unknowns )
2003-04-08 19:20:04 -04:00
{
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
for ( int j = 0 ; j < nargs ; j + + )
2003-04-08 19:20:04 -04:00
{
2007-06-06 19:00:50 -04:00
Oid decl_type = declared_arg_types [ j ] ;
2003-04-08 19:20:04 -04:00
Oid actual_type = actual_arg_types [ j ] ;
if ( actual_type ! = UNKNOWNOID )
continue ;
2007-06-06 19:00:50 -04:00
if ( decl_type = = ANYELEMENTOID | |
decl_type = = ANYNONARRAYOID | |
decl_type = = ANYENUMOID )
2003-04-08 19:20:04 -04:00
declared_arg_types [ j ] = elem_typeid ;
2007-06-06 19:00:50 -04:00
else if ( decl_type = = ANYARRAYOID )
2003-04-08 19:20:04 -04:00
{
if ( ! OidIsValid ( array_typeid ) )
{
array_typeid = get_array_type ( elem_typeid ) ;
if ( ! OidIsValid ( array_typeid ) )
2003-07-19 16:20:53 -04:00
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_OBJECT ) ,
2003-09-25 02:58:07 -04:00
errmsg ( " could not find array type for data type %s " ,
2003-07-19 16:20:53 -04:00
format_type_be ( elem_typeid ) ) ) ) ;
2003-04-08 19:20:04 -04:00
}
declared_arg_types [ j ] = array_typeid ;
}
2011-11-03 07:16:28 -04:00
else if ( decl_type = = ANYRANGEOID )
{
if ( ! OidIsValid ( range_typeid ) )
{
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/* we can't infer a range type from the others */
2011-11-03 07:16:28 -04:00
ereport ( ERROR ,
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " could not determine polymorphic type %s because input has type %s " ,
" anyrange " , " unknown " ) ) ) ;
2011-11-03 07:16:28 -04:00
}
declared_arg_types [ j ] = range_typeid ;
}
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
else if ( decl_type = = ANYMULTIRANGEOID )
{
if ( ! OidIsValid ( multirange_typeid ) )
{
2021-07-27 15:01:49 -04:00
/* we can't infer a multirange type from the others */
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
ereport ( ERROR ,
2021-07-27 15:01:49 -04:00
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg ( " could not determine polymorphic type %s because input has type %s " ,
" anymultirange " , " unknown " ) ) ) ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
}
declared_arg_types [ j ] = multirange_typeid ;
}
2003-04-08 19:20:04 -04:00
}
}
Adjust handling of an ANYARRAY actual input for an ANYARRAY argument.
Ordinarily it's impossible for an actual input of a function to have
declared type ANYARRAY, since we'd resolve that to a concrete array
type before doing argument type resolution for the function. But an
exception arises for functions applied to certain columns of pg_statistic
or pg_stats, since we abuse the "anyarray" pseudotype by using it to
declare those columns. So parse_coerce.c has to deal with the case.
Previously we allowed an ANYARRAY actual input to match an ANYARRAY
polymorphic argument, but only if no other argument or result was
declared ANYELEMENT. When that logic was written, those were the only
two polymorphic types, and I fear nobody thought carefully about how it
ought to extend to the other ones that came along later. But actually
it was wrong even then, because if a function has two ANYARRAY
arguments, it should be able to expect that they have identical element
types, and we'd not be able to ensure that.
The correct generalization is that we can match an ANYARRAY actual input
to an ANYARRAY polymorphic argument only if no other argument or result
is of any polymorphic type, so that no promises are being made about
element type compatibility. check_generic_type_consistency can't test
that condition, but it seems better anyway to accept such matches there
and then throw an error if needed in enforce_generic_type_consistency.
That way we can produce a specific error message rather than an
unintuitive "function does not exist" complaint. (There's some risk
perhaps of getting new ambiguous-function complaints, but I think that
any set of functions for which that could happen would be ambiguous
against ordinary array columns as well.) While we're at it, we can
improve the message that's produced in cases that the code did already
object to, as shown in the regression test changes.
Also, remove a similar test that got cargo-culted in for ANYRANGE;
there are no catalog columns of type ANYRANGE, and I hope we never
create any, so that's not needed. (It was incomplete anyway.)
While here, update some comments and rearrange the code a bit in
preparation for upcoming additions of more polymorphic types.
In practical situations I believe this is just exchanging one error
message for another, hopefully better, one. So it doesn't seem
needful to back-patch, even though the mistake is ancient.
Discussion: https://postgr.es/m/21569.1584314271@sss.pgh.pa.us
2020-03-17 18:29:07 -04:00
/* if we return ANYELEMENT use the appropriate argument type */
if ( rettype = = ANYELEMENTOID | |
rettype = = ANYNONARRAYOID | |
rettype = = ANYENUMOID )
return elem_typeid ;
2007-04-01 23:49:42 -04:00
/* if we return ANYARRAY use the appropriate argument type */
2003-04-08 19:20:04 -04:00
if ( rettype = = ANYARRAYOID )
{
if ( ! OidIsValid ( array_typeid ) )
{
2003-06-25 17:30:34 -04:00
array_typeid = get_array_type ( elem_typeid ) ;
2003-04-08 19:20:04 -04:00
if ( ! OidIsValid ( array_typeid ) )
2003-07-19 16:20:53 -04:00
ereport ( ERROR ,
( errcode ( ERRCODE_UNDEFINED_OBJECT ) ,
2003-09-25 02:58:07 -04:00
errmsg ( " could not find array type for data type %s " ,
2003-07-19 16:20:53 -04:00
format_type_be ( elem_typeid ) ) ) ) ;
2003-04-08 19:20:04 -04:00
}
return array_typeid ;
}
2011-11-03 07:16:28 -04:00
/* if we return ANYRANGE use the appropriate argument type */
if ( rettype = = ANYRANGEOID )
{
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/* this error is unreachable if the function signature is valid: */
2011-11-03 07:16:28 -04:00
if ( ! OidIsValid ( range_typeid ) )
ereport ( ERROR ,
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
2021-07-27 15:01:49 -04:00
errmsg_internal ( " could not determine polymorphic type %s because input has type %s " ,
" anyrange " , " unknown " ) ) ) ;
2011-11-03 07:16:28 -04:00
return range_typeid ;
}
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
/* if we return ANYMULTIRANGE use the appropriate argument type */
if ( rettype = = ANYMULTIRANGEOID )
{
2021-07-27 15:01:49 -04:00
/* this error is unreachable if the function signature is valid: */
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
if ( ! OidIsValid ( multirange_typeid ) )
2021-07-27 15:01:49 -04:00
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg_internal ( " could not determine polymorphic type %s because input has type %s " ,
" anymultirange " , " unknown " ) ) ) ;
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
return multirange_typeid ;
}
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/* if we return ANYCOMPATIBLE use the appropriate type */
if ( rettype = = ANYCOMPATIBLEOID | |
rettype = = ANYCOMPATIBLENONARRAYOID )
{
/* this error is unreachable if the function signature is valid: */
if ( ! OidIsValid ( anycompatible_typeid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg_internal ( " could not identify anycompatible type " ) ) ) ;
return anycompatible_typeid ;
}
/* if we return ANYCOMPATIBLEARRAY use the appropriate type */
if ( rettype = = ANYCOMPATIBLEARRAYOID )
{
/* this error is unreachable if the function signature is valid: */
if ( ! OidIsValid ( anycompatible_array_typeid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg_internal ( " could not identify anycompatiblearray type " ) ) ) ;
return anycompatible_array_typeid ;
}
/* if we return ANYCOMPATIBLERANGE use the appropriate argument type */
if ( rettype = = ANYCOMPATIBLERANGEOID )
{
/* this error is unreachable if the function signature is valid: */
if ( ! OidIsValid ( anycompatible_range_typeid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg_internal ( " could not identify anycompatiblerange type " ) ) ) ;
return anycompatible_range_typeid ;
}
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
/* if we return ANYCOMPATIBLEMULTIRANGE use the appropriate argument type */
if ( rettype = = ANYCOMPATIBLEMULTIRANGEOID )
{
/* this error is unreachable if the function signature is valid: */
if ( ! OidIsValid ( anycompatible_multirange_typeid ) )
ereport ( ERROR ,
( errcode ( ERRCODE_DATATYPE_MISMATCH ) ,
errmsg_internal ( " could not identify anycompatiblemultirange type " ) ) ) ;
return anycompatible_multirange_typeid ;
}
2003-04-08 19:20:04 -04:00
/* we don't return a generic type; send back the original return type */
return rettype ;
}
2020-03-17 19:36:41 -04:00
/*
* check_valid_polymorphic_signature ( )
* Is a proposed function signature valid per polymorphism rules ?
*
* Returns NULL if the signature is valid ( either ret_type is not polymorphic ,
* or it can be deduced from the given declared argument types ) . Otherwise ,
* returns a palloc ' d , already translated errdetail string saying why not .
*/
char *
check_valid_polymorphic_signature ( Oid ret_type ,
const Oid * declared_arg_types ,
int nargs )
{
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
if ( ret_type = = ANYRANGEOID | | ret_type = = ANYMULTIRANGEOID )
2020-03-17 19:36:41 -04:00
{
/*
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
* ANYRANGE and ANYMULTIRANGE require an ANYRANGE or ANYMULTIRANGE
* input , else we can ' t tell which of several range types with the
* same element type to use .
2020-03-17 19:36:41 -04:00
*/
for ( int i = 0 ; i < nargs ; i + + )
{
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
if ( declared_arg_types [ i ] = = ANYRANGEOID | |
declared_arg_types [ i ] = = ANYMULTIRANGEOID )
2020-03-17 19:36:41 -04:00
return NULL ; /* OK */
}
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
return psprintf ( _ ( " A result of type %s requires at least one input of type anyrange or anymultirange. " ) ,
format_type_be ( ret_type ) ) ;
}
else if ( ret_type = = ANYCOMPATIBLERANGEOID | | ret_type = = ANYCOMPATIBLEMULTIRANGEOID )
{
/*
* ANYCOMPATIBLERANGE and ANYCOMPATIBLEMULTIRANGE require an
* ANYCOMPATIBLERANGE or ANYCOMPATIBLEMULTIRANGE input , else we can ' t
* tell which of several range types with the same element type to
* use .
*/
for ( int i = 0 ; i < nargs ; i + + )
{
if ( declared_arg_types [ i ] = = ANYCOMPATIBLERANGEOID | |
declared_arg_types [ i ] = = ANYCOMPATIBLEMULTIRANGEOID )
return NULL ; /* OK */
}
return psprintf ( _ ( " A result of type %s requires at least one input of type anycompatiblerange or anycompatiblemultirange. " ) ,
format_type_be ( ret_type ) ) ;
2020-03-17 19:36:41 -04:00
}
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
else if ( IsPolymorphicTypeFamily1 ( ret_type ) )
2020-03-17 19:36:41 -04:00
{
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/* Otherwise, any family-1 type can be deduced from any other */
2020-03-17 19:36:41 -04:00
for ( int i = 0 ; i < nargs ; i + + )
{
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
if ( IsPolymorphicTypeFamily1 ( declared_arg_types [ i ] ) )
2020-03-17 19:36:41 -04:00
return NULL ; /* OK */
}
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/* Keep this list in sync with IsPolymorphicTypeFamily1! */
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
return psprintf ( _ ( " A result of type %s requires at least one input of type anyelement, anyarray, anynonarray, anyenum, anyrange, or anymultirange. " ) ,
2020-03-17 19:36:41 -04:00
format_type_be ( ret_type ) ) ;
}
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
else if ( IsPolymorphicTypeFamily2 ( ret_type ) )
{
/* Otherwise, any family-2 type can be deduced from any other */
for ( int i = 0 ; i < nargs ; i + + )
{
if ( IsPolymorphicTypeFamily2 ( declared_arg_types [ i ] ) )
return NULL ; /* OK */
}
/* Keep this list in sync with IsPolymorphicTypeFamily2! */
2021-07-27 15:01:49 -04:00
return psprintf ( _ ( " A result of type %s requires at least one input of type anycompatible, anycompatiblearray, anycompatiblenonarray, anycompatiblerange, or anycompatiblemultirange. " ) ,
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
format_type_be ( ret_type ) ) ;
}
2020-03-17 19:36:41 -04:00
else
return NULL ; /* OK, ret_type is not polymorphic */
}
/*
* check_valid_internal_signature ( )
* Is a proposed function signature valid per INTERNAL safety rules ?
*
* Returns NULL if OK , or a suitable error message if ret_type is INTERNAL but
* none of the declared arg types are . ( It ' s unsafe to create such a function
* since it would allow invocation of INTERNAL - consuming functions directly
* from SQL . ) It ' s overkill to return the error detail message , since there
* is only one possibility , but we do it like this to keep the API similar to
* check_valid_polymorphic_signature ( ) .
*/
char *
check_valid_internal_signature ( Oid ret_type ,
const Oid * declared_arg_types ,
int nargs )
{
if ( ret_type = = INTERNALOID )
{
for ( int i = 0 ; i < nargs ; i + + )
{
if ( declared_arg_types [ i ] = = ret_type )
return NULL ; /* OK */
}
return pstrdup ( _ ( " A result of type internal requires at least one input of type internal. " ) ) ;
}
else
return NULL ; /* OK, ret_type is not INTERNAL */
}
2000-10-05 15:11:39 -04:00
1998-05-09 19:31:34 -04:00
/* TypeCategory()
2003-05-25 20:11:29 -04:00
* Assign a category to the specified type OID .
*
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
* NB : this must not return TYPCATEGORY_INVALID .
1998-05-09 19:31:34 -04:00
*/
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
TYPCATEGORY
TypeCategory ( Oid type )
1998-05-09 19:31:34 -04:00
{
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
char typcategory ;
bool typispreferred ;
1998-05-09 19:31:34 -04:00
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
get_type_category_preferred ( type , & typcategory , & typispreferred ) ;
Assert ( typcategory ! = TYPCATEGORY_INVALID ) ;
return ( TYPCATEGORY ) typcategory ;
}
1998-05-09 19:31:34 -04:00
/* IsPreferredType()
2003-05-25 20:11:29 -04:00
* Check if this type is a preferred type for the given category .
*
2017-08-16 00:22:32 -04:00
* If category is TYPCATEGORY_INVALID , then we ' ll return true for preferred
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
* types of any category ; otherwise , only for preferred types of that
* category .
1998-05-09 19:31:34 -04:00
*/
bool
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
IsPreferredType ( TYPCATEGORY category , Oid type )
1998-05-09 19:31:34 -04:00
{
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
char typcategory ;
bool typispreferred ;
1998-05-09 19:31:34 -04:00
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
get_type_category_preferred ( type , & typcategory , & typispreferred ) ;
if ( category = = typcategory | | category = = TYPCATEGORY_INVALID )
return typispreferred ;
else
2003-05-25 20:11:29 -04:00
return false ;
Replace the hard-wired type knowledge in TypeCategory() and IsPreferredType()
with system catalog lookups, as was foreseen to be necessary almost since
their creation. Instead put the information into two new pg_type columns,
typcategory and typispreferred. Add support for setting these when
creating a user-defined base type.
The category column is just a "char" (i.e. a poor man's enum), allowing
a crude form of user extensibility of the category list: just use an
otherwise-unused character. This seems sufficient for foreseen uses,
but we could upgrade to having an actual category catalog someday, if
there proves to be a huge demand for custom type categories.
In this patch I have attempted to hew exactly to the behavior of the
previous hardwired logic, except for introducing new type categories for
arrays, composites, and enums. In particular the default preferred state
for user-defined types remains TRUE. That seems worth revisiting, but it
should be done as a separate patch from introducing the infrastructure.
Likewise, any adjustment of the standard set of categories should be done
separately.
2008-07-30 13:05:05 -04:00
}
2002-03-18 21:18:25 -05:00
2002-08-31 22:27:32 -04:00
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
/* IsBinaryCoercible()
* Check if srctype is binary - coercible to targettype .
2002-03-20 14:45:13 -05:00
*
2002-08-31 22:27:32 -04:00
* This notion allows us to cheat and directly exchange values without
2003-05-25 20:11:29 -04:00
* going through the trouble of calling a conversion function . Note that
* in general , this should only be an implementation shortcut . Before 7.4 ,
* this was also used as a heuristic for resolving overloaded functions and
* operators , but that ' s basically a bad idea .
2002-03-20 14:45:13 -05:00
*
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
* As of 7.3 , binary coercibility isn ' t hardwired into the code anymore .
* We consider two types binary - coercible if there is an implicitly
2003-05-25 20:11:29 -04:00
* invokable , no - function - needed pg_cast entry . Also , a domain is always
* binary - coercible to its base type , though * not * vice versa ( in the other
* direction , one must apply domain constraint checks before accepting the
2008-10-13 12:25:20 -04:00
* value as legitimate ) . We also need to special - case various polymorphic
* types .
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
*
* This function replaces IsBinaryCompatible ( ) , which was an inherently
* symmetric test . Since the pg_cast entries aren ' t necessarily symmetric ,
* the order of the operands is now significant .
2002-08-31 22:27:32 -04:00
*/
bool
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
IsBinaryCoercible ( Oid srctype , Oid targettype )
2002-08-31 22:27:32 -04:00
{
HeapTuple tuple ;
Form_pg_cast castForm ;
bool result ;
/* Fast path if same type */
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
if ( srctype = = targettype )
2002-08-31 22:27:32 -04:00
return true ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/* Anything is coercible to ANY or ANYELEMENT or ANYCOMPATIBLE */
if ( targettype = = ANYOID | | targettype = = ANYELEMENTOID | |
targettype = = ANYCOMPATIBLEOID )
Support ordered-set (WITHIN GROUP) aggregates.
This patch introduces generic support for ordered-set and hypothetical-set
aggregate functions, as well as implementations of the instances defined in
SQL:2008 (percentile_cont(), percentile_disc(), rank(), dense_rank(),
percent_rank(), cume_dist()). We also added mode() though it is not in the
spec, as well as versions of percentile_cont() and percentile_disc() that
can compute multiple percentile values in one pass over the data.
Unlike the original submission, this patch puts full control of the sorting
process in the hands of the aggregate's support functions. To allow the
support functions to find out how they're supposed to sort, a new API
function AggGetAggref() is added to nodeAgg.c. This allows retrieval of
the aggregate call's Aggref node, which may have other uses beyond the
immediate need. There is also support for ordered-set aggregates to
install cleanup callback functions, so that they can be sure that
infrastructure such as tuplesort objects gets cleaned up.
In passing, make some fixes in the recently-added support for variadic
aggregates, and make some editorial adjustments in the recent FILTER
additions for aggregates. Also, simplify use of IsBinaryCoercible() by
allowing it to succeed whenever the target type is ANY or ANYELEMENT.
It was inconsistent that it dealt with other polymorphic target types
but not these.
Atri Sharma and Andrew Gierth; reviewed by Pavel Stehule and Vik Fearing,
and rather heavily editorialized upon by Tom Lane
2013-12-23 16:11:35 -05:00
return true ;
2003-05-25 20:11:29 -04:00
/* If srctype is a domain, reduce to its base type */
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
if ( OidIsValid ( srctype ) )
srctype = getBaseType ( srctype ) ;
2002-08-31 22:27:32 -04:00
2003-05-25 20:11:29 -04:00
/* Somewhat-fast path for domain -> base type case */
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
if ( srctype = = targettype )
2002-08-31 22:27:32 -04:00
return true ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/* Also accept any array type as coercible to ANY[COMPATIBLE]ARRAY */
if ( targettype = = ANYARRAYOID | | targettype = = ANYCOMPATIBLEARRAYOID )
2011-11-20 23:50:27 -05:00
if ( type_is_array ( srctype ) )
2007-06-06 19:00:50 -04:00
return true ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/* Also accept any non-array type as coercible to ANY[COMPATIBLE]NONARRAY */
if ( targettype = = ANYNONARRAYOID | | targettype = = ANYCOMPATIBLENONARRAYOID )
2011-11-20 23:50:27 -05:00
if ( ! type_is_array ( srctype ) )
2003-06-26 20:33:26 -04:00
return true ;
2007-04-01 23:49:42 -04:00
/* Also accept any enum type as coercible to ANYENUM */
if ( targettype = = ANYENUMOID )
if ( type_is_enum ( srctype ) )
return true ;
Introduce "anycompatible" family of polymorphic types.
This patch adds the pseudo-types anycompatible, anycompatiblearray,
anycompatiblenonarray, and anycompatiblerange. They work much like
anyelement, anyarray, anynonarray, and anyrange respectively, except
that the actual input values need not match precisely in type.
Instead, if we can find a common supertype (using the same rules
as for UNION/CASE type resolution), then the parser automatically
promotes the input values to that type. For example,
"myfunc(anycompatible, anycompatible)" can match a call with one
integer and one bigint argument, with the integer automatically
promoted to bigint. With anyelement in the definition, the user
would have had to cast the integer explicitly.
The new types also provide a second, independent set of type variables
for function matching; thus with "myfunc(anyelement, anyelement,
anycompatible) returns anycompatible" the first two arguments are
constrained to be the same type, but the third can be some other
type, and the result has the type of the third argument. The need
for more than one set of type variables was foreseen back when we
first invented the polymorphic types, but we never did anything
about it.
Pavel Stehule, revised a bit by me
Discussion: https://postgr.es/m/CAFj8pRDna7VqNi8gR+Tt2Ktmz0cq5G93guc3Sbn_NVPLdXAkqA@mail.gmail.com
2020-03-19 11:43:11 -04:00
/* Also accept any range type as coercible to ANY[COMPATIBLE]RANGE */
if ( targettype = = ANYRANGEOID | | targettype = = ANYCOMPATIBLERANGEOID )
2011-11-03 07:16:28 -04:00
if ( type_is_range ( srctype ) )
return true ;
2021-07-27 15:01:49 -04:00
/* Also, any multirange type is coercible to ANY[COMPATIBLE]MULTIRANGE */
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-19 23:20:33 -05:00
if ( targettype = = ANYMULTIRANGEOID | | targettype = = ANYCOMPATIBLEMULTIRANGEOID )
if ( type_is_multirange ( srctype ) )
return true ;
2008-10-13 12:25:20 -04:00
/* Also accept any composite type as coercible to RECORD */
if ( targettype = = RECORDOID )
if ( ISCOMPLEX ( srctype ) )
return true ;
/* Also accept any composite array type as coercible to RECORD[] */
if ( targettype = = RECORDARRAYOID )
if ( is_complex_array ( srctype ) )
return true ;
2002-08-31 22:27:32 -04:00
/* Else look in pg_cast */
2010-02-14 13:42:19 -05:00
tuple = SearchSysCache2 ( CASTSOURCETARGET ,
ObjectIdGetDatum ( srctype ) ,
ObjectIdGetDatum ( targettype ) ) ;
2002-08-31 22:27:32 -04:00
if ( ! HeapTupleIsValid ( tuple ) )
return false ; /* no cast */
castForm = ( Form_pg_cast ) GETSTRUCT ( tuple ) ;
2010-03-04 04:39:53 -05:00
result = ( castForm - > castmethod = = COERCION_METHOD_BINARY & &
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
castForm - > castcontext = = COERCION_CODE_IMPLICIT ) ;
2002-08-31 22:27:32 -04:00
ReleaseSysCache ( tuple ) ;
return result ;
}
/*
* find_coercion_pathway
* Look for a coercion pathway between two types .
2002-03-20 14:45:13 -05:00
*
2007-06-05 17:31:09 -04:00
* Currently , this deals only with scalar - type cases ; it does not consider
* polymorphic types nor casts between composite types . ( Perhaps fold
* those in someday ? )
*
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
* ccontext determines the set of available casts .
*
2007-06-05 17:31:09 -04:00
* The possible result codes are :
* COERCION_PATH_NONE : failed to find any coercion pathway
* * funcid is set to InvalidOid
* COERCION_PATH_FUNC : apply the coercion function returned in * funcid
* COERCION_PATH_RELABELTYPE : binary - compatible cast , no function needed
* * funcid is set to InvalidOid
* COERCION_PATH_ARRAYCOERCE : need an ArrayCoerceExpr node
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
* * funcid is set to InvalidOid
2007-06-05 17:31:09 -04:00
* COERCION_PATH_COERCEVIAIO : need a CoerceViaIO node
* * funcid is set to InvalidOid
2003-05-25 20:11:29 -04:00
*
2007-06-05 17:31:09 -04:00
* Note : COERCION_PATH_RELABELTYPE does not necessarily mean that no work is
2003-05-25 20:11:29 -04:00
* needed to do the coercion ; if the target is a domain then we may need to
* apply domain constraint checking . If you want to check for a zero - effort
* conversion then use IsBinaryCoercible ( ) .
2002-03-18 21:18:25 -05:00
*/
2007-06-05 17:31:09 -04:00
CoercionPathType
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
find_coercion_pathway ( Oid targetTypeId , Oid sourceTypeId ,
CoercionContext ccontext ,
2007-06-05 17:31:09 -04:00
Oid * funcid )
2002-07-18 19:11:32 -04:00
{
2007-06-05 17:31:09 -04:00
CoercionPathType result = COERCION_PATH_NONE ;
2002-07-18 19:11:32 -04:00
HeapTuple tuple ;
2002-08-31 22:27:32 -04:00
* funcid = InvalidOid ;
/* Perhaps the types are domains; if so, look at their base types */
if ( OidIsValid ( sourceTypeId ) )
sourceTypeId = getBaseType ( sourceTypeId ) ;
if ( OidIsValid ( targetTypeId ) )
targetTypeId = getBaseType ( targetTypeId ) ;
2003-05-25 20:11:29 -04:00
/* Domains are always coercible to and from their base type */
2002-08-31 22:27:32 -04:00
if ( sourceTypeId = = targetTypeId )
2007-06-05 17:31:09 -04:00
return COERCION_PATH_RELABELTYPE ;
2002-08-31 22:27:32 -04:00
2003-04-08 19:20:04 -04:00
/* Look in pg_cast */
2010-02-14 13:42:19 -05:00
tuple = SearchSysCache2 ( CASTSOURCETARGET ,
ObjectIdGetDatum ( sourceTypeId ) ,
ObjectIdGetDatum ( targetTypeId ) ) ;
2002-07-18 19:11:32 -04:00
if ( HeapTupleIsValid ( tuple ) )
{
2002-08-31 22:27:32 -04:00
Form_pg_cast castForm = ( Form_pg_cast ) GETSTRUCT ( tuple ) ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
CoercionContext castcontext ;
/* convert char value for castcontext to CoercionContext enum */
switch ( castForm - > castcontext )
{
case COERCION_CODE_IMPLICIT :
castcontext = COERCION_IMPLICIT ;
break ;
case COERCION_CODE_ASSIGNMENT :
castcontext = COERCION_ASSIGNMENT ;
break ;
case COERCION_CODE_EXPLICIT :
castcontext = COERCION_EXPLICIT ;
break ;
default :
2003-07-19 16:20:53 -04:00
elog ( ERROR , " unrecognized castcontext: %d " ,
( int ) castForm - > castcontext ) ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
castcontext = 0 ; /* keep compiler quiet */
break ;
}
2002-07-18 19:11:32 -04:00
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
/* Rely on ordering of enum for correct behavior here */
if ( ccontext > = castcontext )
2002-08-31 22:27:32 -04:00
{
2008-10-31 04:39:22 -04:00
switch ( castForm - > castmethod )
{
case COERCION_METHOD_FUNCTION :
result = COERCION_PATH_FUNC ;
* funcid = castForm - > castfunc ;
break ;
case COERCION_METHOD_INOUT :
result = COERCION_PATH_COERCEVIAIO ;
break ;
case COERCION_METHOD_BINARY :
result = COERCION_PATH_RELABELTYPE ;
break ;
default :
elog ( ERROR , " unrecognized castmethod: %d " ,
( int ) castForm - > castmethod ) ;
break ;
}
2002-08-31 22:27:32 -04:00
}
2002-07-18 19:11:32 -04:00
ReleaseSysCache ( tuple ) ;
}
2003-04-08 19:20:04 -04:00
else
{
/*
* If there ' s no pg_cast entry , perhaps we are dealing with a pair of
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
* array types . If so , and if their element types have a conversion
* pathway , report that we can coerce with an ArrayCoerceExpr .
Improve handling of domains over arrays.
This patch eliminates various bizarre behaviors caused by sloppy thinking
about the difference between a domain type and its underlying array type.
In particular, the operation of updating one element of such an array
has to be considered as yielding a value of the underlying array type,
*not* a value of the domain, because there's no assurance that the
domain's CHECK constraints are still satisfied. If we're intending to
store the result back into a domain column, we have to re-cast to the
domain type so that constraints are re-checked.
For similar reasons, such a domain can't be blindly matched to an ANYARRAY
polymorphic parameter, because the polymorphic function is likely to apply
array-ish operations that could invalidate the domain constraints. For the
moment, we just forbid such matching. We might later wish to insert an
automatic downcast to the underlying array type, but such a change should
also change matching of domains to ANYELEMENT for consistency.
To ensure that all such logic is rechecked, this patch removes the original
hack of setting a domain's pg_type.typelem field to match its base type;
the typelem will always be zero instead. In those places where it's really
okay to look through the domain type with no other logic changes, use the
newly added get_base_element_type function in place of get_element_type.
catversion bumped due to change in pg_type contents.
Per bug #5717 from Richard Huxton and subsequent discussion.
2010-10-21 16:07:17 -04:00
*
2005-03-28 19:17:27 -05:00
* Hack : disallow coercions to oidvector and int2vector , which
* otherwise tend to capture coercions that should go to " real " array
* types . We want those types to be considered " real " arrays for many
2007-03-27 19:21:12 -04:00
* purposes , but not this one . ( Also , ArrayCoerceExpr isn ' t
2005-03-28 19:17:27 -05:00
* guaranteed to produce an output that meets the restrictions of
* these datatypes , such as being 1 - dimensional . )
2003-04-08 19:20:04 -04:00
*/
2007-06-05 17:31:09 -04:00
if ( targetTypeId ! = OIDVECTOROID & & targetTypeId ! = INT2VECTOROID )
2003-04-08 19:20:04 -04:00
{
2007-06-05 17:31:09 -04:00
Oid targetElem ;
Oid sourceElem ;
if ( ( targetElem = get_element_type ( targetTypeId ) ) ! = InvalidOid & &
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
( sourceElem = get_element_type ( sourceTypeId ) ) ! = InvalidOid )
2003-04-08 19:20:04 -04:00
{
2007-06-05 17:31:09 -04:00
CoercionPathType elempathtype ;
Oid elemfuncid ;
elempathtype = find_coercion_pathway ( targetElem ,
sourceElem ,
ccontext ,
& elemfuncid ) ;
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
if ( elempathtype ! = COERCION_PATH_NONE )
2007-06-05 17:31:09 -04:00
{
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
result = COERCION_PATH_ARRAYCOERCE ;
2007-06-05 17:31:09 -04:00
}
2003-04-08 19:20:04 -04:00
}
}
2007-04-01 23:49:42 -04:00
2007-06-05 17:31:09 -04:00
/*
* If we still haven ' t found a possibility , consider automatic casting
2008-07-30 17:23:17 -04:00
* using I / O functions . We allow assignment casts to string types and
* explicit casts from string types to be handled this way . ( The
2007-06-05 17:31:09 -04:00
* CoerceViaIO mechanism is a lot more general than that , but this is
* all we want to allow in the absence of a pg_cast entry . ) It would
* probably be better to insist on explicit casts in both directions ,
* but this is a compromise to preserve something of the pre - 8.3
* behavior that many types had implicit ( yipes ! ) casts to text .
*/
if ( result = = COERCION_PATH_NONE )
{
if ( ccontext > = COERCION_ASSIGNMENT & &
2008-07-30 17:23:17 -04:00
TypeCategory ( targetTypeId ) = = TYPCATEGORY_STRING )
2007-06-05 17:31:09 -04:00
result = COERCION_PATH_COERCEVIAIO ;
else if ( ccontext > = COERCION_EXPLICIT & &
2008-07-30 17:23:17 -04:00
TypeCategory ( sourceTypeId ) = = TYPCATEGORY_STRING )
2007-06-05 17:31:09 -04:00
result = COERCION_PATH_COERCEVIAIO ;
2007-04-01 23:49:42 -04:00
}
2003-04-08 19:20:04 -04:00
}
2002-07-18 19:11:32 -04:00
2021-01-04 11:52:00 -05:00
/*
* When parsing PL / pgSQL assignments , allow an I / O cast to be used
* whenever no normal coercion is available .
*/
if ( result = = COERCION_PATH_NONE & &
ccontext = = COERCION_PLPGSQL )
result = COERCION_PATH_COERCEVIAIO ;
2002-08-31 22:27:32 -04:00
return result ;
2002-07-18 19:11:32 -04:00
}
2002-08-31 22:27:32 -04:00
/*
* find_typmod_coercion_function - - does the given type need length coercion ?
*
2004-06-15 21:27:00 -04:00
* If the target type possesses a pg_cast function from itself to itself ,
* it must need length coercion .
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
*
2002-08-31 22:27:32 -04:00
* " bpchar " ( ie , char ( N ) ) and " numeric " are examples of such types .
*
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
* If the given type is a varlena array type , we do not look for a coercion
* function associated directly with the array type , but instead look for
2007-06-05 17:31:09 -04:00
* one associated with the element type . An ArrayCoerceExpr node must be
Support arrays over domains.
Allowing arrays with a domain type as their element type was left un-done
in the original domain patch, but not for any very good reason. This
omission leads to such surprising results as array_agg() not working on
a domain column, because the parser can't identify a suitable output type
for the polymorphic aggregate.
In order to fix this, first clean up the APIs of coerce_to_domain() and
some internal functions in parse_coerce.c so that we consistently pass
around a CoercionContext along with CoercionForm. Previously, we sometimes
passed an "isExplicit" boolean flag instead, which is strictly less
information; and coerce_to_domain() didn't even get that, but instead had
to reverse-engineer isExplicit from CoercionForm. That's contrary to the
documentation in primnodes.h that says that CoercionForm only affects
display and not semantics. I don't think this change fixes any live bugs,
but it makes things more consistent. The main reason for doing it though
is that now build_coercion_expression() receives ccontext, which it needs
in order to be able to recursively invoke coerce_to_target_type().
Next, reimplement ArrayCoerceExpr so that the node does not directly know
any details of what has to be done to the individual array elements while
performing the array coercion. Instead, the per-element processing is
represented by a sub-expression whose input is a source array element and
whose output is a target array element. This simplifies life in
parse_coerce.c, because it can build that sub-expression by a recursive
invocation of coerce_to_target_type(). The executor now handles the
per-element processing as a compiled expression instead of hard-wired code.
The main advantage of this is that we can use a single ArrayCoerceExpr to
handle as many as three successive steps per element: base type conversion,
typmod coercion, and domain constraint checking. The old code used two
stacked ArrayCoerceExprs to handle type + typmod coercion, which was pretty
inefficient, and adding yet another array deconstruction to do domain
constraint checking seemed very unappetizing.
In the case where we just need a single, very simple coercion function,
doing this straightforwardly leads to a noticeable increase in the
per-array-element runtime cost. Hence, add an additional shortcut evalfunc
in execExprInterp.c that skips unnecessary overhead for that specific form
of expression. The runtime speed of simple cases is within 1% or so of
where it was before, while cases that previously required two levels of
array processing are significantly faster.
Finally, create an implicit array type for every domain type, as we do for
base types, enums, etc. Everything except the array-coercion case seems
to just work without further effort.
Tom Lane, reviewed by Andrew Dunstan
Discussion: https://postgr.es/m/9852.1499791473@sss.pgh.pa.us
2017-09-30 13:40:56 -04:00
* used to apply such a function . ( Note : currently , it ' s pointless to
* return the funcid in this case , because it ' ll just get looked up again
* in the recursive construction of the ArrayCoerceExpr ' s elemexpr . )
2007-06-05 17:31:09 -04:00
*
* We use the same result enum as find_coercion_pathway , but the only possible
* result codes are :
* COERCION_PATH_NONE : no length coercion needed
* COERCION_PATH_FUNC : apply the function returned in * funcid
* COERCION_PATH_ARRAYCOERCE : apply the function using ArrayCoerceExpr
2002-08-31 22:27:32 -04:00
*/
2007-06-05 17:31:09 -04:00
CoercionPathType
2007-03-27 19:21:12 -04:00
find_typmod_coercion_function ( Oid typeId ,
2007-06-05 17:31:09 -04:00
Oid * funcid )
2002-03-18 21:18:25 -05:00
{
2007-06-05 17:31:09 -04:00
CoercionPathType result ;
2002-04-09 16:35:55 -04:00
Type targetType ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
Form_pg_type typeForm ;
2004-06-15 21:27:00 -04:00
HeapTuple tuple ;
2002-03-18 21:18:25 -05:00
2007-03-27 19:21:12 -04:00
* funcid = InvalidOid ;
2007-06-05 17:31:09 -04:00
result = COERCION_PATH_FUNC ;
2007-03-27 19:21:12 -04:00
2002-07-18 19:11:32 -04:00
targetType = typeidType ( typeId ) ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
typeForm = ( Form_pg_type ) GETSTRUCT ( targetType ) ;
2002-04-09 16:35:55 -04:00
Support subscripting of arbitrary types, not only arrays.
This patch generalizes the subscripting infrastructure so that any
data type can be subscripted, if it provides a handler function to
define what that means. Traditional variable-length (varlena) arrays
all use array_subscript_handler(), while the existing fixed-length
types that support subscripting use raw_array_subscript_handler().
It's expected that other types that want to use subscripting notation
will define their own handlers. (This patch provides no such new
features, though; it only lays the foundation for them.)
To do this, move the parser's semantic processing of subscripts
(including coercion to whatever data type is required) into a
method callback supplied by the handler. On the execution side,
replace the ExecEvalSubscriptingRef* layer of functions with direct
calls to callback-supplied execution routines. (Thus, essentially
no new run-time overhead should be caused by this patch. Indeed,
there is room to remove some overhead by supplying specialized
execution routines. This patch does a little bit in that line,
but more could be done.)
Additional work is required here and there to remove formerly
hard-wired assumptions about the result type, collation, etc
of a SubscriptingRef expression node; and to remove assumptions
that the subscript values must be integers.
One useful side-effect of this is that we now have a less squishy
mechanism for identifying whether a data type is a "true" array:
instead of wiring in weird rules about typlen, we can look to see
if pg_type.typsubscript == F_ARRAY_SUBSCRIPT_HANDLER. For this
to be bulletproof, we have to forbid user-defined types from using
that handler directly; but there seems no good reason for them to
do so.
This patch also removes assumptions that the number of subscripts
is limited to MAXDIM (6), or indeed has any hard-wired limit.
That limit still applies to types handled by array_subscript_handler
or raw_array_subscript_handler, but to discourage other dependencies
on this constant, I've moved it from c.h to utils/array.h.
Dmitry Dolgov, reviewed at various times by Tom Lane, Arthur Zakirov,
Peter Eisentraut, Pavel Stehule
Discussion: https://postgr.es/m/CA+q6zcVDuGBv=M0FqBYX8DPebS3F_0KQ6OVFobGJPM507_SZ_w@mail.gmail.com
Discussion: https://postgr.es/m/CA+q6zcVovR+XY4mfk-7oNk-rF91gH0PebnNfuUjuuDsyHjOcVA@mail.gmail.com
2020-12-09 12:40:37 -05:00
/* Check for a "true" array type */
if ( IsTrueArrayType ( typeForm ) )
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
{
/* Yes, switch our attention to the element type */
typeId = typeForm - > typelem ;
2007-06-05 17:31:09 -04:00
result = COERCION_PATH_ARRAYCOERCE ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
}
2004-06-15 21:27:00 -04:00
ReleaseSysCache ( targetType ) ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
2004-06-15 21:27:00 -04:00
/* Look in pg_cast */
2010-02-14 13:42:19 -05:00
tuple = SearchSysCache2 ( CASTSOURCETARGET ,
ObjectIdGetDatum ( typeId ) ,
ObjectIdGetDatum ( typeId ) ) ;
2002-04-11 16:00:18 -04:00
2004-06-15 21:27:00 -04:00
if ( HeapTupleIsValid ( tuple ) )
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
{
2004-06-15 21:27:00 -04:00
Form_pg_cast castForm = ( Form_pg_cast ) GETSTRUCT ( tuple ) ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
2007-03-27 19:21:12 -04:00
* funcid = castForm - > castfunc ;
2004-06-15 21:27:00 -04:00
ReleaseSysCache ( tuple ) ;
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 17:35:25 -04:00
}
2007-06-05 17:31:09 -04:00
if ( ! OidIsValid ( * funcid ) )
result = COERCION_PATH_NONE ;
return result ;
2002-03-20 14:45:13 -05:00
}
2008-10-13 12:25:20 -04:00
/*
* is_complex_array
* Is this type an array of composite ?
*
* Note : this will not return true for record [ ] ; check for RECORDARRAYOID
* separately if needed .
*/
static bool
is_complex_array ( Oid typid )
{
Oid elemtype = get_element_type ( typid ) ;
return ( OidIsValid ( elemtype ) & & ISCOMPLEX ( elemtype ) ) ;
}
2011-01-01 15:44:32 -05:00
/*
* Check whether reltypeId is the row type of a typed table of type
2017-10-26 13:47:45 -04:00
* reloftypeId , or is a domain over such a row type . ( This is conceptually
* similar to the subtype relationship checked by typeInheritsFrom ( ) . )
2011-01-01 15:44:32 -05:00
*/
static bool
typeIsOfTypedTable ( Oid reltypeId , Oid reloftypeId )
{
2017-10-26 13:47:45 -04:00
Oid relid = typeOrDomainTypeRelid ( reltypeId ) ;
2011-01-01 15:44:32 -05:00
bool result = false ;
if ( relid )
{
HeapTuple tp ;
Form_pg_class reltup ;
tp = SearchSysCache1 ( RELOID , ObjectIdGetDatum ( relid ) ) ;
if ( ! HeapTupleIsValid ( tp ) )
elog ( ERROR , " cache lookup failed for relation %u " , relid ) ;
reltup = ( Form_pg_class ) GETSTRUCT ( tp ) ;
if ( reltup - > reloftype = = reloftypeId )
result = true ;
ReleaseSysCache ( tp ) ;
}
return result ;
}