@@ -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 );
@@ -2776,46 +2779,19 @@ eval_const_expressions_mutator(Node *node,
2776
2779
return node ;
2777
2780
case T_RelabelType :
2778
2781
{
2779
- /*
2780
- * If we can simplify the input to a constant, then we don't
2781
- * need the RelabelType node anymore: just change the type
2782
- * field of the Const node. Otherwise, must copy the
2783
- * RelabelType node.
2784
- */
2785
2782
RelabelType * relabel = (RelabelType * ) node ;
2786
2783
Node * arg ;
2787
2784
2785
+ /* Simplify the input ... */
2788
2786
arg = eval_const_expressions_mutator ((Node * ) relabel -> arg ,
2789
2787
context );
2790
-
2791
- /*
2792
- * If we find stacked RelabelTypes (eg, from foo :: int ::
2793
- * oid) we can discard all but the top one.
2794
- */
2795
- while (arg && IsA (arg , RelabelType ))
2796
- arg = (Node * ) ((RelabelType * ) arg )-> arg ;
2797
-
2798
- if (arg && IsA (arg , Const ))
2799
- {
2800
- Const * con = (Const * ) arg ;
2801
-
2802
- con -> consttype = relabel -> resulttype ;
2803
- con -> consttypmod = relabel -> resulttypmod ;
2804
- con -> constcollid = relabel -> resultcollid ;
2805
- return (Node * ) con ;
2806
- }
2807
- else
2808
- {
2809
- RelabelType * newrelabel = makeNode (RelabelType );
2810
-
2811
- newrelabel -> arg = (Expr * ) arg ;
2812
- newrelabel -> resulttype = relabel -> resulttype ;
2813
- newrelabel -> resulttypmod = relabel -> resulttypmod ;
2814
- newrelabel -> resultcollid = relabel -> resultcollid ;
2815
- newrelabel -> relabelformat = relabel -> relabelformat ;
2816
- newrelabel -> location = relabel -> location ;
2817
- return (Node * ) newrelabel ;
2818
- }
2788
+ /* ... and attach a new RelabelType node, if needed */
2789
+ return apply_const_relabel (arg ,
2790
+ relabel -> resulttype ,
2791
+ relabel -> resulttypmod ,
2792
+ relabel -> resultcollid ,
2793
+ relabel -> relabelformat ,
2794
+ relabel -> location );
2819
2795
}
2820
2796
case T_CoerceViaIO :
2821
2797
{
@@ -2949,48 +2925,25 @@ eval_const_expressions_mutator(Node *node,
2949
2925
case T_CollateExpr :
2950
2926
{
2951
2927
/*
2952
- * If we can simplify the input to a constant, then we don't
2953
- * need the CollateExpr node at all: just change the
2954
- * constcollid field of the Const node. Otherwise, replace
2955
- * the CollateExpr with a RelabelType. (We do that so as to
2956
- * improve uniformity of expression representation and thus
2957
- * simplify comparison of expressions.)
2928
+ * We replace CollateExpr with RelabelType, so as to improve
2929
+ * uniformity of expression representation and thus simplify
2930
+ * comparison of expressions. Hence this looks very nearly
2931
+ * the same as the RelabelType case, and we can apply the same
2932
+ * optimizations to avoid unnecessary RelabelTypes.
2958
2933
*/
2959
2934
CollateExpr * collate = (CollateExpr * ) node ;
2960
2935
Node * arg ;
2961
2936
2937
+ /* Simplify the input ... */
2962
2938
arg = eval_const_expressions_mutator ((Node * ) collate -> arg ,
2963
2939
context );
2964
-
2965
- if (arg && IsA (arg , Const ))
2966
- {
2967
- Const * con = (Const * ) arg ;
2968
-
2969
- con -> constcollid = collate -> collOid ;
2970
- return (Node * ) con ;
2971
- }
2972
- else if (collate -> collOid == exprCollation (arg ))
2973
- {
2974
- /* Don't need a RelabelType either... */
2975
- return arg ;
2976
- }
2977
- else
2978
- {
2979
- RelabelType * relabel = makeNode (RelabelType );
2980
-
2981
- relabel -> resulttype = exprType (arg );
2982
- relabel -> resulttypmod = exprTypmod (arg );
2983
- relabel -> resultcollid = collate -> collOid ;
2984
- relabel -> relabelformat = COERCE_IMPLICIT_CAST ;
2985
- relabel -> location = collate -> location ;
2986
-
2987
- /* Don't create stacked RelabelTypes */
2988
- while (arg && IsA (arg , RelabelType ))
2989
- arg = (Node * ) ((RelabelType * ) arg )-> arg ;
2990
- relabel -> arg = (Expr * ) arg ;
2991
-
2992
- return (Node * ) relabel ;
2993
- }
2940
+ /* ... and attach a new RelabelType node, if needed */
2941
+ return apply_const_relabel (arg ,
2942
+ exprType (arg ),
2943
+ exprTypmod (arg ),
2944
+ collate -> collOid ,
2945
+ COERCE_IMPLICIT_CAST ,
2946
+ collate -> location );
2994
2947
}
2995
2948
case T_CaseExpr :
2996
2949
{
@@ -3492,32 +3445,12 @@ eval_const_expressions_mutator(Node *node,
3492
3445
cdomain -> resulttype );
3493
3446
3494
3447
/* Generate RelabelType to substitute for CoerceToDomain */
3495
- /* This should match the RelabelType logic above */
3496
-
3497
- while (arg && IsA (arg , RelabelType ))
3498
- arg = (Node * ) ((RelabelType * ) arg )-> arg ;
3499
-
3500
- if (arg && IsA (arg , Const ))
3501
- {
3502
- Const * con = (Const * ) arg ;
3503
-
3504
- con -> consttype = cdomain -> resulttype ;
3505
- con -> consttypmod = cdomain -> resulttypmod ;
3506
- con -> constcollid = cdomain -> resultcollid ;
3507
- return (Node * ) con ;
3508
- }
3509
- else
3510
- {
3511
- RelabelType * newrelabel = makeNode (RelabelType );
3512
-
3513
- newrelabel -> arg = (Expr * ) arg ;
3514
- newrelabel -> resulttype = cdomain -> resulttype ;
3515
- newrelabel -> resulttypmod = cdomain -> resulttypmod ;
3516
- newrelabel -> resultcollid = cdomain -> resultcollid ;
3517
- newrelabel -> relabelformat = cdomain -> coercionformat ;
3518
- newrelabel -> location = cdomain -> location ;
3519
- return (Node * ) newrelabel ;
3520
- }
3448
+ return apply_const_relabel (arg ,
3449
+ cdomain -> resulttype ,
3450
+ cdomain -> resulttypmod ,
3451
+ cdomain -> resultcollid ,
3452
+ cdomain -> coercionformat ,
3453
+ cdomain -> location );
3521
3454
}
3522
3455
3523
3456
newcdomain = makeNode (CoerceToDomain );
@@ -3650,6 +3583,58 @@ ece_function_is_safe(Oid funcid, eval_const_expressions_context *context)
3650
3583
return false;
3651
3584
}
3652
3585
3586
+ /*
3587
+ * Subroutine for eval_const_expressions: apply RelabelType if needed
3588
+ */
3589
+ static Node *
3590
+ apply_const_relabel (Node * arg , Oid rtype , int32 rtypmod , Oid rcollid ,
3591
+ CoercionForm rformat , int rlocation )
3592
+ {
3593
+ /*
3594
+ * If we find stacked RelabelTypes (eg, from foo::int::oid) we can discard
3595
+ * all but the top one, and must do so to ensure that semantically
3596
+ * equivalent expressions are equal().
3597
+ */
3598
+ while (arg && IsA (arg , RelabelType ))
3599
+ arg = (Node * ) ((RelabelType * ) arg )-> arg ;
3600
+
3601
+ if (arg && IsA (arg , Const ))
3602
+ {
3603
+ /*
3604
+ * If it's a Const, just modify it in-place; since this is part of
3605
+ * eval_const_expressions, we want to end up with a simple Const not
3606
+ * an expression tree. We assume the Const is newly generated and
3607
+ * hence safe to modify.
3608
+ */
3609
+ Const * con = (Const * ) arg ;
3610
+
3611
+ con -> consttype = rtype ;
3612
+ con -> consttypmod = rtypmod ;
3613
+ con -> constcollid = rcollid ;
3614
+ return (Node * ) con ;
3615
+ }
3616
+ else if (exprType (arg ) == rtype &&
3617
+ exprTypmod (arg ) == rtypmod &&
3618
+ exprCollation (arg ) == rcollid )
3619
+ {
3620
+ /* Sometimes we find a nest of relabels that net out to nothing. */
3621
+ return arg ;
3622
+ }
3623
+ else
3624
+ {
3625
+ /* Nope, gotta have a RelabelType. */
3626
+ RelabelType * newrelabel = makeNode (RelabelType );
3627
+
3628
+ newrelabel -> arg = (Expr * ) arg ;
3629
+ newrelabel -> resulttype = rtype ;
3630
+ newrelabel -> resulttypmod = rtypmod ;
3631
+ newrelabel -> resultcollid = rcollid ;
3632
+ newrelabel -> relabelformat = rformat ;
3633
+ newrelabel -> location = rlocation ;
3634
+ return (Node * ) newrelabel ;
3635
+ }
3636
+ }
3637
+
3653
3638
/*
3654
3639
* Subroutine for eval_const_expressions: process arguments of an OR clause
3655
3640
*
0 commit comments