@ -107,11 +107,11 @@ static List *simplify_and_arguments(List *args,
eval_const_expressions_context * context ,
bool * haveNull , bool * forceFalse ) ;
static Node * simplify_boolean_equality ( Oid opno , List * args ) ;
static Expr * simplify_function ( Expr * oldexpr , Oid funcid ,
Oid result_type , int32 result_typmod , Oid result_collid ,
Oid input_collid , List * * args ,
static Expr * simplify_function ( Oid funcid ,
Oid result_type , int32 result_typmod ,
Oid result_collid , Oid input_collid , List * * args ,
bool has_named_args ,
bool allow_inline ,
bool allow_non_const ,
eval_const_expressions_context * context ) ;
static List * reorder_function_arguments ( List * args , Oid result_type ,
HeapTuple func_tuple ,
@ -2332,8 +2332,7 @@ eval_const_expressions_mutator(Node *node,
* length coercion ; we want to preserve the typmod in the
* eventual Const if so .
*/
simple = simplify_function ( ( Expr * ) expr ,
expr - > funcid ,
simple = simplify_function ( expr - > funcid ,
expr - > funcresulttype ,
exprTypmod ( node ) ,
expr - > funccollid ,
@ -2389,8 +2388,7 @@ eval_const_expressions_mutator(Node *node,
* Code for op / func reduction is pretty bulky , so split it out
* as a separate function .
*/
simple = simplify_function ( ( Expr * ) expr ,
expr - > opfuncid ,
simple = simplify_function ( expr - > opfuncid ,
expr - > opresulttype , - 1 ,
expr - > opcollid ,
expr - > inputcollid ,
@ -2491,8 +2489,7 @@ eval_const_expressions_mutator(Node *node,
* Code for op / func reduction is pretty bulky , so split it
* out as a separate function .
*/
simple = simplify_function ( ( Expr * ) expr ,
expr - > opfuncid ,
simple = simplify_function ( expr - > opfuncid ,
expr - > opresulttype , - 1 ,
expr - > opcollid ,
expr - > inputcollid ,
@ -2698,8 +2695,7 @@ eval_const_expressions_mutator(Node *node,
getTypeInputInfo ( expr - > resulttype ,
& infunc , & intypioparam ) ;
simple = simplify_function ( NULL ,
outfunc ,
simple = simplify_function ( outfunc ,
CSTRINGOID , - 1 ,
InvalidOid ,
InvalidOid ,
@ -2728,8 +2724,7 @@ eval_const_expressions_mutator(Node *node,
false ,
true ) ) ;
simple = simplify_function ( NULL ,
infunc ,
simple = simplify_function ( infunc ,
expr - > resulttype , - 1 ,
expr - > resultcollid ,
InvalidOid ,
@ -3581,15 +3576,11 @@ simplify_boolean_equality(Oid opno, List *args)
* Subroutine for eval_const_expressions : try to simplify a function call
* ( which might originally have been an operator ; we don ' t care )
*
* Inputs are the original expression ( can be NULL ) , function OID , actual
* result type OID ( which is needed for polymorphic functions ) , result typmod ,
* result collation , the input collation to use for the function , the
* pre - simplified argument list , and some flags ; also the context data for
* eval_const_expressions . In common cases , several of the arguments could be
* derived from the original expression . Sending them separately avoids
* duplicating NodeTag - specific knowledge , and it ' s necessary for CoerceViaIO .
* A NULL original expression disables use of transform functions while
* retaining all other behaviors .
* Inputs are the function OID , actual result type OID ( which is needed for
* polymorphic functions ) , result typmod , result collation ,
* the input collation to use for the function ,
* the pre - simplified argument list , and some flags ;
* also the context data for eval_const_expressions .
*
* Returns a simplified expression if successful , or NULL if cannot
* simplify the function call .
@ -3601,28 +3592,32 @@ simplify_boolean_equality(Oid opno, List *args)
* pass - by - reference , and it may get modified even if simplification fails .
*/
static Expr *
simplify_function ( Expr * oldexpr , Oid funcid ,
Oid result_type , int32 result_typmod , Oid result_collid ,
Oid input_collid , List * * args ,
simplify_function ( Oid funcid , Oid result_type , int32 result_typmod ,
Oid result_collid , Oid input_collid , List * * args ,
bool has_named_args ,
bool allow_inline ,
bool allow_non_const ,
eval_const_expressions_context * context )
{
HeapTuple func_tuple ;
Form_pg_proc func_form ;
Expr * newexpr ;
Oid transform ;
/*
* We have three strategies for simplification : execute the function to
* deliver a constant result , use a transform function to generate a
* substitute node tree , or expand in - line the body of the function
* definition ( which only works for simple SQL - language functions , but
* that is a common case ) . Each needs access to the function ' s pg_proc
* tuple , so fetch it just once .
* that is a common case ) . Each case needs access to the function ' s
* pg_proc tuple , so fetch it just once .
*
* Note : the allow_non_const flag suppresses both the second and third
* strategies ; so if ! allow_non_const , simplify_function can only return
* a Const or NULL . Argument - list rewriting happens anyway , though .
*/
func_tuple = SearchSysCache1 ( PROCOID , ObjectIdGetDatum ( funcid ) ) ;
if ( ! HeapTupleIsValid ( func_tuple ) )
elog ( ERROR , " cache lookup failed for function %u " , funcid ) ;
func_form = ( Form_pg_proc ) GETSTRUCT ( func_tuple ) ;
/*
* While we have the tuple , reorder named arguments and add default
@ -3631,48 +3626,38 @@ simplify_function(Expr *oldexpr, Oid funcid,
if ( has_named_args )
* args = reorder_function_arguments ( * args , result_type , func_tuple ,
context ) ;
else if ( ( ( Form_pg_proc ) GETSTRUCT ( func_tuple ) ) - > pronargs > list_length ( * args ) )
else if ( func_form - > pronargs > list_length ( * args ) )
* args = add_function_defaults ( * args , result_type , func_tuple , context ) ;
newexpr = evaluate_function ( funcid , result_type , result_typmod ,
result_collid , input_collid , * args ,
func_tuple , context ) ;
/*
* Some functions calls can be simplified at plan time based on properties
* specific to the function . For example , " varchar(s::varchar(4), 8,
* true ) " simplifies to " s : : varchar ( 4 ) " , and " int4mul ( n , 1 ) " could
* simplify to " n " . To define such function - specific optimizations , write
* a " transform function " and store its OID in the pg_proc . protransform of
* the primary function . Give each transform function the signature
* " protransform(internal) RETURNS internal " . The argument , internally an
* Expr * , is the node representing a call to the primary function . If
* the transform function ' s study of that node proves that a simplified
* Expr substitutes for all possible concrete calls represented thereby ,
* return that simplified Expr . Otherwise , return the NULL pointer .
*
* Currently , the specific Expr nodetag can be FuncExpr , OpExpr or
* DistinctExpr . This list may change in the future . The function should
* check the nodetag and return the NULL pointer for unexpected inputs .
*
* We make no guarantee that PostgreSQL will never call the primary
* function in cases that the transform function would simplify . Ensure
* rigorous equivalence between the simplified expression and an actual
* call to the primary function .
*
* Currently , this facility is undocumented and not exposed to users at
* the SQL level . Core length coercion casts use it to avoid calls
* guaranteed to return their input unchanged . This in turn allows ALTER
* TABLE ALTER TYPE to avoid rewriting tables for some typmod changes . In
* the future , this facility may find other applications , like simplifying
* x * 0 , x * 1 , and x + 0.
*/
transform = ( ( Form_pg_proc ) GETSTRUCT ( func_tuple ) ) - > protransform ;
if ( ! newexpr & & OidIsValid ( transform ) & & oldexpr )
newexpr = ( Expr * ) DatumGetPointer ( OidFunctionCall1 ( transform ,
PointerGetDatum ( oldexpr ) ) ) ;
if ( ! newexpr & & allow_non_const & & OidIsValid ( func_form - > protransform ) )
{
/*
* Build a dummy FuncExpr node containing the simplified arg list . We
* use this approach to present a uniform interface to the transform
* function regardless of how the function is actually being invoked .
*/
FuncExpr fexpr ;
fexpr . xpr . type = T_FuncExpr ;
fexpr . funcid = funcid ;
fexpr . funcresulttype = result_type ;
fexpr . funcretset = func_form - > proretset ;
fexpr . funcformat = COERCE_DONTCARE ;
fexpr . funccollid = result_collid ;
fexpr . inputcollid = input_collid ;
fexpr . args = * args ;
fexpr . location = - 1 ;
newexpr = ( Expr * )
DatumGetPointer ( OidFunctionCall1 ( func_form - > protransform ,
PointerGetDatum ( & fexpr ) ) ) ;
}
if ( ! newexpr & & allow_inline )
if ( ! newexpr & & allow_non_const )
newexpr = inline_function ( funcid , result_type , result_collid ,
input_collid , * args ,
func_tuple , context ) ;