@@ -119,6 +119,9 @@ static Node *eval_const_expressions_mutator(Node *node,
119119static bool contain_non_const_walker (Node * node , void * context );
120120static bool ece_function_is_safe (Oid funcid ,
121121 eval_const_expressions_context * context );
122+ static Node * apply_const_relabel (Node * arg , Oid rtype ,
123+ int32 rtypmod , Oid rcollid ,
124+ CoercionForm rformat , int rlocation );
122125static List * simplify_or_arguments (List * args ,
123126 eval_const_expressions_context * context ,
124127 bool * haveNull , bool * forceTrue );
@@ -2774,46 +2777,19 @@ eval_const_expressions_mutator(Node *node,
27742777 return node ;
27752778 case T_RelabelType :
27762779 {
2777- /*
2778- * If we can simplify the input to a constant, then we don't
2779- * need the RelabelType node anymore: just change the type
2780- * field of the Const node. Otherwise, must copy the
2781- * RelabelType node.
2782- */
27832780 RelabelType * relabel = (RelabelType * ) node ;
27842781 Node * arg ;
27852782
2783+ /* Simplify the input ... */
27862784 arg = eval_const_expressions_mutator ((Node * ) relabel -> arg ,
27872785 context );
2788-
2789- /*
2790- * If we find stacked RelabelTypes (eg, from foo :: int ::
2791- * oid) we can discard all but the top one.
2792- */
2793- while (arg && IsA (arg , RelabelType ))
2794- arg = (Node * ) ((RelabelType * ) arg )-> arg ;
2795-
2796- if (arg && IsA (arg , Const ))
2797- {
2798- Const * con = (Const * ) arg ;
2799-
2800- con -> consttype = relabel -> resulttype ;
2801- con -> consttypmod = relabel -> resulttypmod ;
2802- con -> constcollid = relabel -> resultcollid ;
2803- return (Node * ) con ;
2804- }
2805- else
2806- {
2807- RelabelType * newrelabel = makeNode (RelabelType );
2808-
2809- newrelabel -> arg = (Expr * ) arg ;
2810- newrelabel -> resulttype = relabel -> resulttype ;
2811- newrelabel -> resulttypmod = relabel -> resulttypmod ;
2812- newrelabel -> resultcollid = relabel -> resultcollid ;
2813- newrelabel -> relabelformat = relabel -> relabelformat ;
2814- newrelabel -> location = relabel -> location ;
2815- return (Node * ) newrelabel ;
2816- }
2786+ /* ... and attach a new RelabelType node, if needed */
2787+ return apply_const_relabel (arg ,
2788+ relabel -> resulttype ,
2789+ relabel -> resulttypmod ,
2790+ relabel -> resultcollid ,
2791+ relabel -> relabelformat ,
2792+ relabel -> location );
28172793 }
28182794 case T_CoerceViaIO :
28192795 {
@@ -2947,48 +2923,25 @@ eval_const_expressions_mutator(Node *node,
29472923 case T_CollateExpr :
29482924 {
29492925 /*
2950- * If we can simplify the input to a constant, then we don't
2951- * need the CollateExpr node at all: just change the
2952- * constcollid field of the Const node. Otherwise, replace
2953- * the CollateExpr with a RelabelType. (We do that so as to
2954- * improve uniformity of expression representation and thus
2955- * simplify comparison of expressions.)
2926+ * We replace CollateExpr with RelabelType, so as to improve
2927+ * uniformity of expression representation and thus simplify
2928+ * comparison of expressions. Hence this looks very nearly
2929+ * the same as the RelabelType case, and we can apply the same
2930+ * optimizations to avoid unnecessary RelabelTypes.
29562931 */
29572932 CollateExpr * collate = (CollateExpr * ) node ;
29582933 Node * arg ;
29592934
2935+ /* Simplify the input ... */
29602936 arg = eval_const_expressions_mutator ((Node * ) collate -> arg ,
29612937 context );
2962-
2963- if (arg && IsA (arg , Const ))
2964- {
2965- Const * con = (Const * ) arg ;
2966-
2967- con -> constcollid = collate -> collOid ;
2968- return (Node * ) con ;
2969- }
2970- else if (collate -> collOid == exprCollation (arg ))
2971- {
2972- /* Don't need a RelabelType either... */
2973- return arg ;
2974- }
2975- else
2976- {
2977- RelabelType * relabel = makeNode (RelabelType );
2978-
2979- relabel -> resulttype = exprType (arg );
2980- relabel -> resulttypmod = exprTypmod (arg );
2981- relabel -> resultcollid = collate -> collOid ;
2982- relabel -> relabelformat = COERCE_IMPLICIT_CAST ;
2983- relabel -> location = collate -> location ;
2984-
2985- /* Don't create stacked RelabelTypes */
2986- while (arg && IsA (arg , RelabelType ))
2987- arg = (Node * ) ((RelabelType * ) arg )-> arg ;
2988- relabel -> arg = (Expr * ) arg ;
2989-
2990- return (Node * ) relabel ;
2991- }
2938+ /* ... and attach a new RelabelType node, if needed */
2939+ return apply_const_relabel (arg ,
2940+ exprType (arg ),
2941+ exprTypmod (arg ),
2942+ collate -> collOid ,
2943+ COERCE_IMPLICIT_CAST ,
2944+ collate -> location );
29922945 }
29932946 case T_CaseExpr :
29942947 {
@@ -3490,32 +3443,12 @@ eval_const_expressions_mutator(Node *node,
34903443 cdomain -> resulttype );
34913444
34923445 /* Generate RelabelType to substitute for CoerceToDomain */
3493- /* This should match the RelabelType logic above */
3494-
3495- while (arg && IsA (arg , RelabelType ))
3496- arg = (Node * ) ((RelabelType * ) arg )-> arg ;
3497-
3498- if (arg && IsA (arg , Const ))
3499- {
3500- Const * con = (Const * ) arg ;
3501-
3502- con -> consttype = cdomain -> resulttype ;
3503- con -> consttypmod = cdomain -> resulttypmod ;
3504- con -> constcollid = cdomain -> resultcollid ;
3505- return (Node * ) con ;
3506- }
3507- else
3508- {
3509- RelabelType * newrelabel = makeNode (RelabelType );
3510-
3511- newrelabel -> arg = (Expr * ) arg ;
3512- newrelabel -> resulttype = cdomain -> resulttype ;
3513- newrelabel -> resulttypmod = cdomain -> resulttypmod ;
3514- newrelabel -> resultcollid = cdomain -> resultcollid ;
3515- newrelabel -> relabelformat = cdomain -> coercionformat ;
3516- newrelabel -> location = cdomain -> location ;
3517- return (Node * ) newrelabel ;
3518- }
3446+ return apply_const_relabel (arg ,
3447+ cdomain -> resulttype ,
3448+ cdomain -> resulttypmod ,
3449+ cdomain -> resultcollid ,
3450+ cdomain -> coercionformat ,
3451+ cdomain -> location );
35193452 }
35203453
35213454 newcdomain = makeNode (CoerceToDomain );
@@ -3648,6 +3581,58 @@ ece_function_is_safe(Oid funcid, eval_const_expressions_context *context)
36483581 return false;
36493582}
36503583
3584+ /*
3585+ * Subroutine for eval_const_expressions: apply RelabelType if needed
3586+ */
3587+ static Node *
3588+ apply_const_relabel (Node * arg , Oid rtype , int32 rtypmod , Oid rcollid ,
3589+ CoercionForm rformat , int rlocation )
3590+ {
3591+ /*
3592+ * If we find stacked RelabelTypes (eg, from foo::int::oid) we can discard
3593+ * all but the top one, and must do so to ensure that semantically
3594+ * equivalent expressions are equal().
3595+ */
3596+ while (arg && IsA (arg , RelabelType ))
3597+ arg = (Node * ) ((RelabelType * ) arg )-> arg ;
3598+
3599+ if (arg && IsA (arg , Const ))
3600+ {
3601+ /*
3602+ * If it's a Const, just modify it in-place; since this is part of
3603+ * eval_const_expressions, we want to end up with a simple Const not
3604+ * an expression tree. We assume the Const is newly generated and
3605+ * hence safe to modify.
3606+ */
3607+ Const * con = (Const * ) arg ;
3608+
3609+ con -> consttype = rtype ;
3610+ con -> consttypmod = rtypmod ;
3611+ con -> constcollid = rcollid ;
3612+ return (Node * ) con ;
3613+ }
3614+ else if (exprType (arg ) == rtype &&
3615+ exprTypmod (arg ) == rtypmod &&
3616+ exprCollation (arg ) == rcollid )
3617+ {
3618+ /* Sometimes we find a nest of relabels that net out to nothing. */
3619+ return arg ;
3620+ }
3621+ else
3622+ {
3623+ /* Nope, gotta have a RelabelType. */
3624+ RelabelType * newrelabel = makeNode (RelabelType );
3625+
3626+ newrelabel -> arg = (Expr * ) arg ;
3627+ newrelabel -> resulttype = rtype ;
3628+ newrelabel -> resulttypmod = rtypmod ;
3629+ newrelabel -> resultcollid = rcollid ;
3630+ newrelabel -> relabelformat = rformat ;
3631+ newrelabel -> location = rlocation ;
3632+ return (Node * ) newrelabel ;
3633+ }
3634+ }
3635+
36513636/*
36523637 * Subroutine for eval_const_expressions: process arguments of an OR clause
36533638 *
0 commit comments