@@ -107,11 +107,11 @@ static List *simplify_and_arguments(List *args,
107107eval_const_expressions_context * context ,
108108bool * haveNull ,bool * forceFalse );
109109static 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 ,
113113bool has_named_args ,
114- bool allow_inline ,
114+ bool allow_non_const ,
115115eval_const_expressions_context * context );
116116static List * reorder_function_arguments (List * args ,Oid result_type ,
117117HeapTuple func_tuple ,
@@ -2332,8 +2332,7 @@ eval_const_expressions_mutator(Node *node,
23322332 * length coercion; we want to preserve the typmod in the
23332333 * eventual Const if so.
23342334 */
2335- simple = simplify_function ((Expr * )expr ,
2336- expr -> funcid ,
2335+ simple = simplify_function (expr -> funcid ,
23372336expr -> funcresulttype ,
23382337exprTypmod (node ),
23392338expr -> funccollid ,
@@ -2389,8 +2388,7 @@ eval_const_expressions_mutator(Node *node,
23892388 * Code for op/func reduction is pretty bulky, so split it out
23902389 * as a separate function.
23912390 */
2392- simple = simplify_function ((Expr * )expr ,
2393- expr -> opfuncid ,
2391+ simple = simplify_function (expr -> opfuncid ,
23942392expr -> opresulttype ,-1 ,
23952393expr -> opcollid ,
23962394expr -> inputcollid ,
@@ -2491,8 +2489,7 @@ eval_const_expressions_mutator(Node *node,
24912489 * Code for op/func reduction is pretty bulky, so split it
24922490 * out as a separate function.
24932491 */
2494- simple = simplify_function ((Expr * )expr ,
2495- expr -> opfuncid ,
2492+ simple = simplify_function (expr -> opfuncid ,
24962493expr -> opresulttype ,-1 ,
24972494expr -> opcollid ,
24982495expr -> inputcollid ,
@@ -2698,8 +2695,7 @@ eval_const_expressions_mutator(Node *node,
26982695getTypeInputInfo (expr -> resulttype ,
26992696& infunc ,& intypioparam );
27002697
2701- simple = simplify_function (NULL ,
2702- outfunc ,
2698+ simple = simplify_function (outfunc ,
27032699CSTRINGOID ,-1 ,
27042700InvalidOid ,
27052701InvalidOid ,
@@ -2728,8 +2724,7 @@ eval_const_expressions_mutator(Node *node,
27282724false,
27292725true));
27302726
2731- simple = simplify_function (NULL ,
2732- infunc ,
2727+ simple = simplify_function (infunc ,
27332728expr -> resulttype ,-1 ,
27342729expr -> resultcollid ,
27352730InvalidOid ,
@@ -3581,15 +3576,11 @@ simplify_boolean_equality(Oid opno, List *args)
35813576 * Subroutine for eval_const_expressions: try to simplify a function call
35823577 * (which might originally have been an operator; we don't care)
35833578 *
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.
35933584 *
35943585 * Returns a simplified expression if successful, or NULL if cannot
35953586 * simplify the function call.
@@ -3601,28 +3592,32 @@ simplify_boolean_equality(Oid opno, List *args)
36013592 * pass-by-reference, and it may get modified even if simplification fails.
36023593 */
36033594static 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 ,
36073597bool has_named_args ,
3608- bool allow_inline ,
3598+ bool allow_non_const ,
36093599eval_const_expressions_context * context )
36103600{
36113601HeapTuple func_tuple ;
3602+ Form_pg_proc func_form ;
36123603Expr * newexpr ;
3613- Oid transform ;
36143604
36153605/*
36163606 * We have three strategies for simplification: execute the function to
36173607 * deliver a constant result, use a transform function to generate a
36183608 * substitute node tree, or expand in-line the body of the function
36193609 * 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.
36223616 */
36233617func_tuple = SearchSysCache1 (PROCOID ,ObjectIdGetDatum (funcid ));
36243618if (!HeapTupleIsValid (func_tuple ))
36253619elog (ERROR ,"cache lookup failed for function %u" ,funcid );
3620+ func_form = (Form_pg_proc )GETSTRUCT (func_tuple );
36263621
36273622/*
36283623 * While we have the tuple, reorder named arguments and add default
@@ -3631,48 +3626,38 @@ simplify_function(Expr *oldexpr, Oid funcid,
36313626if (has_named_args )
36323627* args = reorder_function_arguments (* args ,result_type ,func_tuple ,
36333628context );
3634- else if ((( Form_pg_proc ) GETSTRUCT ( func_tuple )) -> pronargs > list_length (* args ))
3629+ else if (func_form -> pronargs > list_length (* args ))
36353630* args = add_function_defaults (* args ,result_type ,func_tuple ,context );
36363631
36373632newexpr = evaluate_function (funcid ,result_type ,result_typmod ,
36383633result_collid ,input_collid ,* args ,
36393634func_tuple ,context );
36403635
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+ }
36743659
3675- if (!newexpr && allow_inline )
3660+ if (!newexpr && allow_non_const )
36763661newexpr = inline_function (funcid ,result_type ,result_collid ,
36773662input_collid ,* args ,
36783663func_tuple ,context );