@ -107,11 +107,11 @@ static List *simplify_and_arguments(List *args,
eval_const_expressions_context * context ,
eval_const_expressions_context * context ,
bool * haveNull , bool * forceFalse ) ;
bool * haveNull , bool * forceFalse ) ;
static Node * simplify_boolean_equality ( Oid opno , List * args ) ;
static Node * simplify_boolean_equality ( Oid opno , List * args ) ;
static Expr * simplify_function ( Expr * oldexpr , Oid funcid ,
static Expr * simplify_function ( Oid funcid ,
Oid result_type , int32 result_typmod , Oid result_collid ,
Oid result_type , int32 result_typmod ,
Oid input_collid , List * * args ,
Oid result_collid , Oid input_collid , List * * args ,
bool has_named_args ,
bool has_named_args ,
bool allow_inline ,
bool allow_non_const ,
eval_const_expressions_context * context ) ;
eval_const_expressions_context * context ) ;
static List * reorder_function_arguments ( List * args , Oid result_type ,
static List * reorder_function_arguments ( List * args , Oid result_type ,
HeapTuple func_tuple ,
HeapTuple func_tuple ,
@ -2332,8 +2332,7 @@ eval_const_expressions_mutator(Node *node,
* length coercion ; we want to preserve the typmod in the
* length coercion ; we want to preserve the typmod in the
* eventual Const if so .
* eventual Const if so .
*/
*/
simple = simplify_function ( ( Expr * ) expr ,
simple = simplify_function ( expr - > funcid ,
expr - > funcid ,
expr - > funcresulttype ,
expr - > funcresulttype ,
exprTypmod ( node ) ,
exprTypmod ( node ) ,
expr - > funccollid ,
expr - > funccollid ,
@ -2389,8 +2388,7 @@ eval_const_expressions_mutator(Node *node,
* Code for op / func reduction is pretty bulky , so split it out
* Code for op / func reduction is pretty bulky , so split it out
* as a separate function .
* as a separate function .
*/
*/
simple = simplify_function ( ( Expr * ) expr ,
simple = simplify_function ( expr - > opfuncid ,
expr - > opfuncid ,
expr - > opresulttype , - 1 ,
expr - > opresulttype , - 1 ,
expr - > opcollid ,
expr - > opcollid ,
expr - > inputcollid ,
expr - > inputcollid ,
@ -2491,8 +2489,7 @@ eval_const_expressions_mutator(Node *node,
* Code for op / func reduction is pretty bulky , so split it
* Code for op / func reduction is pretty bulky , so split it
* out as a separate function .
* out as a separate function .
*/
*/
simple = simplify_function ( ( Expr * ) expr ,
simple = simplify_function ( expr - > opfuncid ,
expr - > opfuncid ,
expr - > opresulttype , - 1 ,
expr - > opresulttype , - 1 ,
expr - > opcollid ,
expr - > opcollid ,
expr - > inputcollid ,
expr - > inputcollid ,
@ -2698,8 +2695,7 @@ eval_const_expressions_mutator(Node *node,
getTypeInputInfo ( expr - > resulttype ,
getTypeInputInfo ( expr - > resulttype ,
& infunc , & intypioparam ) ;
& infunc , & intypioparam ) ;
simple = simplify_function ( NULL ,
simple = simplify_function ( outfunc ,
outfunc ,
CSTRINGOID , - 1 ,
CSTRINGOID , - 1 ,
InvalidOid ,
InvalidOid ,
InvalidOid ,
InvalidOid ,
@ -2728,8 +2724,7 @@ eval_const_expressions_mutator(Node *node,
false ,
false ,
true ) ) ;
true ) ) ;
simple = simplify_function ( NULL ,
simple = simplify_function ( infunc ,
infunc ,
expr - > resulttype , - 1 ,
expr - > resulttype , - 1 ,
expr - > resultcollid ,
expr - > resultcollid ,
InvalidOid ,
InvalidOid ,
@ -3581,15 +3576,11 @@ simplify_boolean_equality(Oid opno, List *args)
* Subroutine for eval_const_expressions : try to simplify a function call
* Subroutine for eval_const_expressions : try to simplify a function call
* ( which might originally have been an operator ; we don ' t care )
* ( which might originally have been an operator ; we don ' t care )
*
*
* Inputs are the original expression ( can be NULL ) , function OID , actual
* Inputs are the function OID , actual result type OID ( which is needed for
* result type OID ( which is needed for polymorphic functions ) , result typmod ,
* polymorphic functions ) , result typmod , result collation ,
* result collation , the input collation to use for the function , the
* the input collation to use for the function ,
* pre - simplified argument list , and some flags ; also the context data for
* the pre - simplified argument list , and some flags ;
* eval_const_expressions . In common cases , several of the arguments could be
* also the context data for eval_const_expressions .
* 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 .
*
*
* Returns a simplified expression if successful , or NULL if cannot
* Returns a simplified expression if successful , or NULL if cannot
* simplify the function call .
* 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 .
* pass - by - reference , and it may get modified even if simplification fails .
*/
*/
static Expr *
static Expr *
simplify_function ( Expr * oldexpr , Oid funcid ,
simplify_function ( Oid funcid , Oid result_type , int32 result_typmod ,
Oid result_type , int32 result_typmod , Oid result_collid ,
Oid result_collid , Oid input_collid , List * * args ,
Oid input_collid , List * * args ,
bool has_named_args ,
bool has_named_args ,
bool allow_inline ,
bool allow_non_const ,
eval_const_expressions_context * context )
eval_const_expressions_context * context )
{
{
HeapTuple func_tuple ;
HeapTuple func_tuple ;
Form_pg_proc func_form ;
Expr * newexpr ;
Expr * newexpr ;
Oid transform ;
/*
/*
* We have three strategies for simplification : execute the function to
* We have three strategies for simplification : execute the function to
* deliver a constant result , use a transform function to generate a
* deliver a constant result , use a transform function to generate a
* substitute node tree , or expand in - line the body of the function
* substitute node tree , or expand in - line the body of the function
* definition ( which only works for simple SQL - language functions , but
* definition ( which only works for simple SQL - language functions , but
* that is a common case ) . Each needs access to the function ' s pg_proc
* that is a common case ) . Each case needs access to the function ' s
* tuple , so fetch it just once .
* 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 ) ) ;
func_tuple = SearchSysCache1 ( PROCOID , ObjectIdGetDatum ( funcid ) ) ;
if ( ! HeapTupleIsValid ( func_tuple ) )
if ( ! HeapTupleIsValid ( func_tuple ) )
elog ( ERROR , " cache lookup failed for function %u " , funcid ) ;
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
* 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 )
if ( has_named_args )
* args = reorder_function_arguments ( * args , result_type , func_tuple ,
* args = reorder_function_arguments ( * args , result_type , func_tuple ,
context ) ;
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 ) ;
* args = add_function_defaults ( * args , result_type , func_tuple , context ) ;
newexpr = evaluate_function ( funcid , result_type , result_typmod ,
newexpr = evaluate_function ( funcid , result_type , result_typmod ,
result_collid , input_collid , * args ,
result_collid , input_collid , * args ,
func_tuple , context ) ;
func_tuple , context ) ;
/*
if ( ! newexpr & & allow_non_const & & OidIsValid ( func_form - > protransform ) )
* 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
* Build a dummy FuncExpr node containing the simplified arg list . We
* simplify to " n " . To define such function - specific optimizations , write
* use this approach to present a uniform interface to the transform
* a " transform function " and store its OID in the pg_proc . protransform of
* function regardless of how the function is actually being invoked .
* the primary function . Give each transform function the signature
*/
* " protransform(internal) RETURNS internal " . The argument , internally an
FuncExpr fexpr ;
* Expr * , is the node representing a call to the primary function . If
* the transform function ' s study of that node proves that a simplified
fexpr . xpr . type = T_FuncExpr ;
* Expr substitutes for all possible concrete calls represented thereby ,
fexpr . funcid = funcid ;
* return that simplified Expr . Otherwise , return the NULL pointer .
fexpr . funcresulttype = result_type ;
*
fexpr . funcretset = func_form - > proretset ;
* Currently , the specific Expr nodetag can be FuncExpr , OpExpr or
fexpr . funcformat = COERCE_DONTCARE ;
* DistinctExpr . This list may change in the future . The function should
fexpr . funccollid = result_collid ;
* check the nodetag and return the NULL pointer for unexpected inputs .
fexpr . inputcollid = input_collid ;
*
fexpr . args = * args ;
* We make no guarantee that PostgreSQL will never call the primary
fexpr . location = - 1 ;
* function in cases that the transform function would simplify . Ensure
* rigorous equivalence between the simplified expression and an actual
newexpr = ( Expr * )
* call to the primary function .
DatumGetPointer ( OidFunctionCall1 ( func_form - > protransform ,
*
PointerGetDatum ( & fexpr ) ) ) ;
* 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_inline )
if ( ! newexpr & & allow_non_const )
newexpr = inline_function ( funcid , result_type , result_collid ,
newexpr = inline_function ( funcid , result_type , result_collid ,
input_collid , * args ,
input_collid , * args ,
func_tuple , context ) ;
func_tuple , context ) ;