@@ -119,6 +119,9 @@ static Node *eval_const_expressions_mutator(Node *node,
119
119
static bool contain_non_const_walker (Node * node , void * context );
120
120
static bool ece_function_is_safe (Oid funcid ,
121
121
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 );
122
125
static List * simplify_or_arguments (List * args ,
123
126
eval_const_expressions_context * context ,
124
127
bool * haveNull , bool * forceTrue );
@@ -2774,46 +2777,19 @@ eval_const_expressions_mutator(Node *node,
2774
2777
return node ;
2775
2778
case T_RelabelType :
2776
2779
{
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
- */
2783
2780
RelabelType * relabel = (RelabelType * ) node ;
2784
2781
Node * arg ;
2785
2782
2783
+ /* Simplify the input ... */
2786
2784
arg = eval_const_expressions_mutator ((Node * ) relabel -> arg ,
2787
2785
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 );
2817
2793
}
2818
2794
case T_CoerceViaIO :
2819
2795
{
@@ -2947,48 +2923,25 @@ eval_const_expressions_mutator(Node *node,
2947
2923
case T_CollateExpr :
2948
2924
{
2949
2925
/*
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.
2956
2931
*/
2957
2932
CollateExpr * collate = (CollateExpr * ) node ;
2958
2933
Node * arg ;
2959
2934
2935
+ /* Simplify the input ... */
2960
2936
arg = eval_const_expressions_mutator ((Node * ) collate -> arg ,
2961
2937
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 );
2992
2945
}
2993
2946
case T_CaseExpr :
2994
2947
{
@@ -3490,32 +3443,12 @@ eval_const_expressions_mutator(Node *node,
3490
3443
cdomain -> resulttype );
3491
3444
3492
3445
/* 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 );
3519
3452
}
3520
3453
3521
3454
newcdomain = makeNode (CoerceToDomain );
@@ -3648,6 +3581,58 @@ ece_function_is_safe(Oid funcid, eval_const_expressions_context *context)
3648
3581
return false;
3649
3582
}
3650
3583
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
+
3651
3636
/*
3652
3637
* Subroutine for eval_const_expressions: process arguments of an OR clause
3653
3638
*
0 commit comments