@@ -52,6 +52,9 @@ typedef struct
52
52
int num_vars ; /* number of plain Var tlist entries */
53
53
bool has_ph_vars ; /* are there PlaceHolderVar entries? */
54
54
bool has_non_vars ; /* are there other entries? */
55
+ bool has_conv_whole_rows ; /* are there ConvertRowtypeExpr
56
+ * entries encapsulating a whole-row
57
+ * Var? */
55
58
tlist_vinfo vars [FLEXIBLE_ARRAY_MEMBER ]; /* has num_vars entries */
56
59
} indexed_tlist ;
57
60
@@ -211,6 +214,7 @@ static List *set_windowagg_runcondition_references(PlannerInfo *root,
211
214
List * runcondition ,
212
215
Plan * plan );
213
216
217
+ static bool is_converted_whole_row_reference (Node * node );
214
218
215
219
/*****************************************************************************
216
220
*
@@ -2738,6 +2742,7 @@ build_tlist_index(List *tlist)
2738
2742
itlist -> tlist = tlist ;
2739
2743
itlist -> has_ph_vars = false;
2740
2744
itlist -> has_non_vars = false;
2745
+ itlist -> has_conv_whole_rows = false;
2741
2746
2742
2747
/* Find the Vars and fill in the index array */
2743
2748
vinfo = itlist -> vars ;
@@ -2757,6 +2762,8 @@ build_tlist_index(List *tlist)
2757
2762
}
2758
2763
else if (tle -> expr && IsA (tle -> expr , PlaceHolderVar ))
2759
2764
itlist -> has_ph_vars = true;
2765
+ else if (is_converted_whole_row_reference ((Node * ) tle -> expr ))
2766
+ itlist -> has_conv_whole_rows = true;
2760
2767
else
2761
2768
itlist -> has_non_vars = true;
2762
2769
}
@@ -2772,7 +2779,10 @@ build_tlist_index(List *tlist)
2772
2779
* This is like build_tlist_index, but we only index tlist entries that
2773
2780
* are Vars belonging to some rel other than the one specified. We will set
2774
2781
* has_ph_vars (allowing PlaceHolderVars to be matched), but not has_non_vars
2775
- * (so nothing other than Vars and PlaceHolderVars can be matched).
2782
+ * (so nothing other than Vars and PlaceHolderVars can be matched). In case of
2783
+ * DML, where this function will be used, returning lists from child relations
2784
+ * will be appended similar to a simple append relation. That does not require
2785
+ * fixing ConvertRowtypeExpr references. So, those are not considered here.
2776
2786
*/
2777
2787
static indexed_tlist *
2778
2788
build_tlist_index_other_vars (List * tlist , int ignore_rel )
@@ -2789,6 +2799,7 @@ build_tlist_index_other_vars(List *tlist, int ignore_rel)
2789
2799
itlist -> tlist = tlist ;
2790
2800
itlist -> has_ph_vars = false;
2791
2801
itlist -> has_non_vars = false;
2802
+ itlist -> has_conv_whole_rows = false;
2792
2803
2793
2804
/* Find the desired Vars and fill in the index array */
2794
2805
vinfo = itlist -> vars ;
@@ -3094,6 +3105,7 @@ static Node *
3094
3105
fix_join_expr_mutator (Node * node , fix_join_expr_context * context )
3095
3106
{
3096
3107
Var * newvar ;
3108
+ bool converted_whole_row ;
3097
3109
3098
3110
if (node == NULL )
3099
3111
return NULL ;
@@ -3182,15 +3194,16 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
3182
3194
return fix_join_expr_mutator ((Node * ) phv -> phexpr , context );
3183
3195
}
3184
3196
/* Try matching more complex expressions too, if tlists have any */
3185
- if (context -> outer_itlist && context -> outer_itlist -> has_non_vars )
3197
+ converted_whole_row = is_converted_whole_row_reference (node );
3198
+ if (context -> outer_itlist && (context -> outer_itlist -> has_non_vars || (context -> outer_itlist -> has_conv_whole_rows && converted_whole_row )))
3186
3199
{
3187
3200
newvar = search_indexed_tlist_for_non_var ((Expr * ) node ,
3188
3201
context -> outer_itlist ,
3189
3202
OUTER_VAR );
3190
3203
if (newvar )
3191
3204
return (Node * ) newvar ;
3192
3205
}
3193
- if (context -> inner_itlist && context -> inner_itlist -> has_non_vars )
3206
+ if (context -> inner_itlist && ( context -> inner_itlist -> has_non_vars || ( context -> inner_itlist -> has_conv_whole_rows && converted_whole_row )) )
3194
3207
{
3195
3208
newvar = search_indexed_tlist_for_non_var ((Expr * ) node ,
3196
3209
context -> inner_itlist ,
@@ -3301,7 +3314,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
3301
3314
return fix_upper_expr_mutator ((Node * ) phv -> phexpr , context );
3302
3315
}
3303
3316
/* Try matching more complex expressions too, if tlist has any */
3304
- if (context -> subplan_itlist -> has_non_vars )
3317
+ if (context -> subplan_itlist -> has_non_vars || ( context -> subplan_itlist -> has_conv_whole_rows && is_converted_whole_row_reference ( node )) )
3305
3318
{
3306
3319
newvar = search_indexed_tlist_for_non_var ((Expr * ) node ,
3307
3320
context -> subplan_itlist ,
@@ -3701,3 +3714,33 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
3701
3714
return expression_tree_walker (node , extract_query_dependencies_walker ,
3702
3715
context );
3703
3716
}
3717
+
3718
+ /*
3719
+ * is_converted_whole_row_reference
3720
+ * If the given node is a ConvertRowtypeExpr encapsulating a whole-row
3721
+ * reference as implicit cast, return true. Otherwise return false.
3722
+ */
3723
+ static bool
3724
+ is_converted_whole_row_reference (Node * node )
3725
+ {
3726
+ ConvertRowtypeExpr * convexpr ;
3727
+
3728
+ if (!node || !IsA (node , ConvertRowtypeExpr ))
3729
+ return false;
3730
+
3731
+ /* Traverse nested ConvertRowtypeExpr's. */
3732
+ convexpr = castNode (ConvertRowtypeExpr , node );
3733
+ while (convexpr -> convertformat == COERCE_IMPLICIT_CAST &&
3734
+ IsA (convexpr -> arg , ConvertRowtypeExpr ))
3735
+ convexpr = castNode (ConvertRowtypeExpr , convexpr -> arg );
3736
+
3737
+ if (IsA (convexpr -> arg , Var ))
3738
+ {
3739
+ Var * var = castNode (Var , convexpr -> arg );
3740
+
3741
+ if (var -> varattno == 0 )
3742
+ return true;
3743
+ }
3744
+
3745
+ return false;
3746
+ }
0 commit comments