@@ -107,11 +107,11 @@ static List *simplify_and_arguments(List *args,
107
107
eval_const_expressions_context * context ,
108
108
bool * haveNull , bool * forceFalse );
109
109
static Node * simplify_boolean_equality (Oid opno , List * args );
110
- static Expr * simplify_function (Expr * oldexpr , Oid funcid ,
111
- Oid result_type , int32 result_typmod , Oid result_collid ,
112
- Oid input_collid , List * * args ,
110
+ static Expr * simplify_function (Oid funcid ,
111
+ Oid result_type , int32 result_typmod ,
112
+ Oid result_collid , Oid input_collid , List * * args ,
113
113
bool has_named_args ,
114
- bool allow_inline ,
114
+ bool allow_non_const ,
115
115
eval_const_expressions_context * context );
116
116
static List * reorder_function_arguments (List * args , Oid result_type ,
117
117
HeapTuple func_tuple ,
@@ -2332,8 +2332,7 @@ eval_const_expressions_mutator(Node *node,
2332
2332
* length coercion; we want to preserve the typmod in the
2333
2333
* eventual Const if so.
2334
2334
*/
2335
- simple = simplify_function ((Expr * ) expr ,
2336
- expr -> funcid ,
2335
+ simple = simplify_function (expr -> funcid ,
2337
2336
expr -> funcresulttype ,
2338
2337
exprTypmod (node ),
2339
2338
expr -> funccollid ,
@@ -2389,8 +2388,7 @@ eval_const_expressions_mutator(Node *node,
2389
2388
* Code for op/func reduction is pretty bulky, so split it out
2390
2389
* as a separate function.
2391
2390
*/
2392
- simple = simplify_function ((Expr * ) expr ,
2393
- expr -> opfuncid ,
2391
+ simple = simplify_function (expr -> opfuncid ,
2394
2392
expr -> opresulttype , -1 ,
2395
2393
expr -> opcollid ,
2396
2394
expr -> inputcollid ,
@@ -2491,8 +2489,7 @@ eval_const_expressions_mutator(Node *node,
2491
2489
* Code for op/func reduction is pretty bulky, so split it
2492
2490
* out as a separate function.
2493
2491
*/
2494
- simple = simplify_function ((Expr * ) expr ,
2495
- expr -> opfuncid ,
2492
+ simple = simplify_function (expr -> opfuncid ,
2496
2493
expr -> opresulttype , -1 ,
2497
2494
expr -> opcollid ,
2498
2495
expr -> inputcollid ,
@@ -2698,8 +2695,7 @@ eval_const_expressions_mutator(Node *node,
2698
2695
getTypeInputInfo (expr -> resulttype ,
2699
2696
& infunc , & intypioparam );
2700
2697
2701
- simple = simplify_function (NULL ,
2702
- outfunc ,
2698
+ simple = simplify_function (outfunc ,
2703
2699
CSTRINGOID , -1 ,
2704
2700
InvalidOid ,
2705
2701
InvalidOid ,
@@ -2728,8 +2724,7 @@ eval_const_expressions_mutator(Node *node,
2728
2724
false,
2729
2725
true));
2730
2726
2731
- simple = simplify_function (NULL ,
2732
- infunc ,
2727
+ simple = simplify_function (infunc ,
2733
2728
expr -> resulttype , -1 ,
2734
2729
expr -> resultcollid ,
2735
2730
InvalidOid ,
@@ -3581,15 +3576,11 @@ simplify_boolean_equality(Oid opno, List *args)
3581
3576
* Subroutine for eval_const_expressions: try to simplify a function call
3582
3577
* (which might originally have been an operator; we don't care)
3583
3578
*
3584
- * Inputs are the original expression (can be NULL), function OID, actual
3585
- * result type OID (which is needed for polymorphic functions), result typmod,
3586
- * result collation, the input collation to use for the function, the
3587
- * pre-simplified argument list, and some flags; also the context data for
3588
- * eval_const_expressions. In common cases, several of the arguments could be
3589
- * derived from the original expression. Sending them separately avoids
3590
- * duplicating NodeTag-specific knowledge, and it's necessary for CoerceViaIO.
3591
- * A NULL original expression disables use of transform functions while
3592
- * retaining all other behaviors.
3579
+ * Inputs are the function OID, actual result type OID (which is needed for
3580
+ * polymorphic functions), result typmod, result collation,
3581
+ * the input collation to use for the function,
3582
+ * the pre-simplified argument list, and some flags;
3583
+ * also the context data for eval_const_expressions.
3593
3584
*
3594
3585
* Returns a simplified expression if successful, or NULL if cannot
3595
3586
* simplify the function call.
@@ -3601,28 +3592,32 @@ simplify_boolean_equality(Oid opno, List *args)
3601
3592
* pass-by-reference, and it may get modified even if simplification fails.
3602
3593
*/
3603
3594
static Expr *
3604
- simplify_function (Expr * oldexpr , Oid funcid ,
3605
- Oid result_type , int32 result_typmod , Oid result_collid ,
3606
- Oid input_collid , List * * args ,
3595
+ simplify_function (Oid funcid , Oid result_type , int32 result_typmod ,
3596
+ Oid result_collid , Oid input_collid , List * * args ,
3607
3597
bool has_named_args ,
3608
- bool allow_inline ,
3598
+ bool allow_non_const ,
3609
3599
eval_const_expressions_context * context )
3610
3600
{
3611
3601
HeapTuple func_tuple ;
3602
+ Form_pg_proc func_form ;
3612
3603
Expr * newexpr ;
3613
- Oid transform ;
3614
3604
3615
3605
/*
3616
3606
* We have three strategies for simplification: execute the function to
3617
3607
* deliver a constant result, use a transform function to generate a
3618
3608
* substitute node tree, or expand in-line the body of the function
3619
3609
* definition (which only works for simple SQL-language functions, but
3620
- * that is a common case). Each needs access to the function's pg_proc
3621
- * tuple, so fetch it just once.
3610
+ * that is a common case). Each case needs access to the function's
3611
+ * pg_proc tuple, so fetch it just once.
3612
+ *
3613
+ * Note: the allow_non_const flag suppresses both the second and third
3614
+ * strategies; so if !allow_non_const, simplify_function can only return
3615
+ * a Const or NULL. Argument-list rewriting happens anyway, though.
3622
3616
*/
3623
3617
func_tuple = SearchSysCache1 (PROCOID , ObjectIdGetDatum (funcid ));
3624
3618
if (!HeapTupleIsValid (func_tuple ))
3625
3619
elog (ERROR , "cache lookup failed for function %u" , funcid );
3620
+ func_form = (Form_pg_proc ) GETSTRUCT (func_tuple );
3626
3621
3627
3622
/*
3628
3623
* While we have the tuple, reorder named arguments and add default
@@ -3631,48 +3626,38 @@ simplify_function(Expr *oldexpr, Oid funcid,
3631
3626
if (has_named_args )
3632
3627
* args = reorder_function_arguments (* args , result_type , func_tuple ,
3633
3628
context );
3634
- else if ((( Form_pg_proc ) GETSTRUCT ( func_tuple )) -> pronargs > list_length (* args ))
3629
+ else if (func_form -> pronargs > list_length (* args ))
3635
3630
* args = add_function_defaults (* args , result_type , func_tuple , context );
3636
3631
3637
3632
newexpr = evaluate_function (funcid , result_type , result_typmod ,
3638
3633
result_collid , input_collid , * args ,
3639
3634
func_tuple , context );
3640
3635
3641
- /*
3642
- * Some functions calls can be simplified at plan time based on properties
3643
- * specific to the function. For example, "varchar(s::varchar(4), 8,
3644
- * true)" simplifies to "s::varchar(4)", and "int4mul(n, 1)" could
3645
- * simplify to "n". To define such function-specific optimizations, write
3646
- * a "transform function" and store its OID in the pg_proc.protransform of
3647
- * the primary function. Give each transform function the signature
3648
- * "protransform(internal) RETURNS internal". The argument, internally an
3649
- * Expr *, is the node representing a call to the primary function. If
3650
- * the transform function's study of that node proves that a simplified
3651
- * Expr substitutes for all possible concrete calls represented thereby,
3652
- * return that simplified Expr. Otherwise, return the NULL pointer.
3653
- *
3654
- * Currently, the specific Expr nodetag can be FuncExpr, OpExpr or
3655
- * DistinctExpr. This list may change in the future. The function should
3656
- * check the nodetag and return the NULL pointer for unexpected inputs.
3657
- *
3658
- * We make no guarantee that PostgreSQL will never call the primary
3659
- * function in cases that the transform function would simplify. Ensure
3660
- * rigorous equivalence between the simplified expression and an actual
3661
- * call to the primary function.
3662
- *
3663
- * Currently, this facility is undocumented and not exposed to users at
3664
- * the SQL level. Core length coercion casts use it to avoid calls
3665
- * guaranteed to return their input unchanged. This in turn allows ALTER
3666
- * TABLE ALTER TYPE to avoid rewriting tables for some typmod changes. In
3667
- * the future, this facility may find other applications, like simplifying
3668
- * x*0, x*1, and x+0.
3669
- */
3670
- transform = ((Form_pg_proc ) GETSTRUCT (func_tuple ))-> protransform ;
3671
- if (!newexpr && OidIsValid (transform ) && oldexpr )
3672
- newexpr = (Expr * ) DatumGetPointer (OidFunctionCall1 (transform ,
3673
- PointerGetDatum (oldexpr )));
3636
+ if (!newexpr && allow_non_const && OidIsValid (func_form -> protransform ))
3637
+ {
3638
+ /*
3639
+ * Build a dummy FuncExpr node containing the simplified arg list. We
3640
+ * use this approach to present a uniform interface to the transform
3641
+ * function regardless of how the function is actually being invoked.
3642
+ */
3643
+ FuncExpr fexpr ;
3644
+
3645
+ fexpr .xpr .type = T_FuncExpr ;
3646
+ fexpr .funcid = funcid ;
3647
+ fexpr .funcresulttype = result_type ;
3648
+ fexpr .funcretset = func_form -> proretset ;
3649
+ fexpr .funcformat = COERCE_DONTCARE ;
3650
+ fexpr .funccollid = result_collid ;
3651
+ fexpr .inputcollid = input_collid ;
3652
+ fexpr .args = * args ;
3653
+ fexpr .location = -1 ;
3654
+
3655
+ newexpr = (Expr * )
3656
+ DatumGetPointer (OidFunctionCall1 (func_form -> protransform ,
3657
+ PointerGetDatum (& fexpr )));
3658
+ }
3674
3659
3675
- if (!newexpr && allow_inline )
3660
+ if (!newexpr && allow_non_const )
3676
3661
newexpr = inline_function (funcid , result_type , result_collid ,
3677
3662
input_collid , * args ,
3678
3663
func_tuple , context );
0 commit comments