2525((IsA(node, FuncExpr) && ((FuncExpr *) (node))->funcretset) || \
2626 (IsA(node, OpExpr) && ((OpExpr *) (node))->opretset))
2727
28- /* Workspace for split_pathtarget_walker */
28+ /*
29+ * Data structures for split_pathtarget_at_srfs(). To preserve the identity
30+ * of sortgroupref items even if they are textually equal(), what we track is
31+ * not just bare expressions but expressions plus their sortgroupref indexes.
32+ */
33+ typedef struct
34+ {
35+ Node * expr ;/* some subexpression of a PathTarget */
36+ Index sortgroupref ;/* its sortgroupref, or 0 if none */
37+ }split_pathtarget_item ;
38+
2939typedef struct
3040{
41+ /* This is a List of bare expressions: */
3142List * input_target_exprs ;/* exprs available from input */
32- List * level_srfs ;/* list of lists of SRF exprs */
33- List * level_input_vars ;/* vars needed by SRFs of each level */
34- List * level_input_srfs ;/* SRFs needed by SRFs of each level */
43+ /* These are Lists of Lists of split_pathtarget_items: */
44+ List * level_srfs ;/* SRF exprs to evaluate at each level */
45+ List * level_input_vars ;/* input vars needed at each level */
46+ List * level_input_srfs ;/* input SRFs needed at each level */
47+ /* These are Lists of split_pathtarget_items: */
3548List * current_input_vars ;/* vars needed in current subexpr */
3649List * current_input_srfs ;/* SRFs needed in current subexpr */
50+ /* Auxiliary data for current split_pathtarget_walker traversal: */
3751int current_depth ;/* max SRF depth in current subexpr */
52+ Index current_sgref ;/* current subexpr's sortgroupref, or 0 */
3853}split_pathtarget_context ;
3954
4055static bool split_pathtarget_walker (Node * node ,
4156split_pathtarget_context * context );
57+ static void add_sp_item_to_pathtarget (PathTarget * target ,
58+ split_pathtarget_item * item );
59+ static void add_sp_items_to_pathtarget (PathTarget * target ,List * items );
4260
4361
4462/*****************************************************************************
@@ -822,6 +840,9 @@ apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target)
822840 * already meant as a reference to a lower subexpression). So, don't expand
823841 * any tlist expressions that appear in input_target, if that's not NULL.
824842 *
843+ * It's also important that we preserve any sortgroupref annotation appearing
844+ * in the given target, especially on expressions matching input_target items.
845+ *
825846 * The outputs of this function are two parallel lists, one a list of
826847 * PathTargets and the other an integer list of bool flags indicating
827848 * whether the corresponding PathTarget contains any evaluatable SRFs.
@@ -845,6 +866,7 @@ split_pathtarget_at_srfs(PlannerInfo *root,
845866int max_depth ;
846867bool need_extra_projection ;
847868List * prev_level_tlist ;
869+ int lci ;
848870ListCell * lc ,
849871* lc1 ,
850872* lc2 ,
@@ -884,10 +906,15 @@ split_pathtarget_at_srfs(PlannerInfo *root,
884906need_extra_projection = false;
885907
886908/* Scan each expression in the PathTarget looking for SRFs */
909+ lci = 0 ;
887910foreach (lc ,target -> exprs )
888911{
889912Node * node = (Node * )lfirst (lc );
890913
914+ /* Tell split_pathtarget_walker about this expr's sortgroupref */
915+ context .current_sgref = get_pathtarget_sortgroupref (target ,lci );
916+ lci ++ ;
917+
891918/*
892919 * Find all SRFs and Vars (and Var-like nodes) in this expression, and
893920 * enter them into appropriate lists within the context struct.
@@ -981,16 +1008,14 @@ split_pathtarget_at_srfs(PlannerInfo *root,
9811008 * This target should actually evaluate any SRFs of the current
9821009 * level, and it needs to propagate forward any Vars needed by
9831010 * later levels, as well as SRFs computed earlier and needed by
984- * later levels. We rely on add_new_columns_to_pathtarget() to
985- * remove duplicate items. Also, for safety, make a separate copy
986- * of each item for each PathTarget.
1011+ * later levels.
9871012 */
988- add_new_columns_to_pathtarget (ntarget ,copyObject ( level_srfs ) );
1013+ add_sp_items_to_pathtarget (ntarget ,level_srfs );
9891014for_each_cell (lc ,lnext (lc2 ))
9901015{
9911016List * input_vars = (List * )lfirst (lc );
9921017
993- add_new_columns_to_pathtarget (ntarget ,copyObject ( input_vars ) );
1018+ add_sp_items_to_pathtarget (ntarget ,input_vars );
9941019}
9951020for_each_cell (lc ,lnext (lc3 ))
9961021{
@@ -999,10 +1024,10 @@ split_pathtarget_at_srfs(PlannerInfo *root,
9991024
10001025foreach (lcx ,input_srfs )
10011026{
1002- Expr * srf = ( Expr * ) lfirst (lcx );
1027+ split_pathtarget_item * item = lfirst (lcx );
10031028
1004- if (list_member (prev_level_tlist ,srf ))
1005- add_new_column_to_pathtarget (ntarget ,copyObject ( srf ) );
1029+ if (list_member (prev_level_tlist ,item -> expr ))
1030+ add_sp_item_to_pathtarget (ntarget ,item );
10061031}
10071032}
10081033set_pathtarget_cost_width (root ,ntarget );
@@ -1037,12 +1062,17 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
10371062 * input_target can be treated like a Var (which indeed it will be after
10381063 * setrefs.c gets done with it), even if it's actually a SRF. Record it
10391064 * as being needed for the current expression, and ignore any
1040- * substructure.
1065+ * substructure. (Note in particular that this preserves the identity of
1066+ * any expressions that appear as sortgrouprefs in input_target.)
10411067 */
10421068if (list_member (context -> input_target_exprs ,node ))
10431069{
1070+ split_pathtarget_item * item = palloc (sizeof (split_pathtarget_item ));
1071+
1072+ item -> expr = node ;
1073+ item -> sortgroupref = context -> current_sgref ;
10441074context -> current_input_vars = lappend (context -> current_input_vars ,
1045- node );
1075+ item );
10461076return false;
10471077}
10481078
@@ -1057,8 +1087,12 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
10571087IsA (node ,GroupingFunc )||
10581088IsA (node ,WindowFunc ))
10591089{
1090+ split_pathtarget_item * item = palloc (sizeof (split_pathtarget_item ));
1091+
1092+ item -> expr = node ;
1093+ item -> sortgroupref = context -> current_sgref ;
10601094context -> current_input_vars = lappend (context -> current_input_vars ,
1061- node );
1095+ item );
10621096return false;
10631097}
10641098
@@ -1068,15 +1102,20 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
10681102 */
10691103if (IS_SRF_CALL (node ))
10701104{
1105+ split_pathtarget_item * item = palloc (sizeof (split_pathtarget_item ));
10711106List * save_input_vars = context -> current_input_vars ;
10721107List * save_input_srfs = context -> current_input_srfs ;
10731108int save_current_depth = context -> current_depth ;
10741109int srf_depth ;
10751110ListCell * lc ;
10761111
1112+ item -> expr = node ;
1113+ item -> sortgroupref = context -> current_sgref ;
1114+
10771115context -> current_input_vars = NIL ;
10781116context -> current_input_srfs = NIL ;
10791117context -> current_depth = 0 ;
1118+ context -> current_sgref = 0 ;/* subexpressions are not sortgroup items */
10801119
10811120(void )expression_tree_walker (node ,split_pathtarget_walker ,
10821121 (void * )context );
@@ -1094,7 +1133,7 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
10941133
10951134/* Record this SRF as needing to be evaluated at appropriate level */
10961135lc = list_nth_cell (context -> level_srfs ,srf_depth );
1097- lfirst (lc )= lappend (lfirst (lc ),node );
1136+ lfirst (lc )= lappend (lfirst (lc ),item );
10981137
10991138/* Record its inputs as being needed at the same level */
11001139lc = list_nth_cell (context -> level_input_vars ,srf_depth );
@@ -1108,7 +1147,7 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
11081147 * surrounding expression.
11091148 */
11101149context -> current_input_vars = save_input_vars ;
1111- context -> current_input_srfs = lappend (save_input_srfs ,node );
1150+ context -> current_input_srfs = lappend (save_input_srfs ,item );
11121151context -> current_depth = Max (save_current_depth ,srf_depth );
11131152
11141153/* We're done here */
@@ -1119,6 +1158,79 @@ split_pathtarget_walker(Node *node, split_pathtarget_context *context)
11191158 * Otherwise, the node is a scalar (non-set) expression, so recurse to
11201159 * examine its inputs.
11211160 */
1161+ context -> current_sgref = 0 ;/* subexpressions are not sortgroup items */
11221162return expression_tree_walker (node ,split_pathtarget_walker ,
11231163 (void * )context );
11241164}
1165+
1166+ /*
1167+ * Add a split_pathtarget_item to the PathTarget, unless a matching item is
1168+ * already present. This is like add_new_column_to_pathtarget, but allows
1169+ * for sortgrouprefs to be handled. An item having zero sortgroupref can
1170+ * be merged with one that has a sortgroupref, acquiring the latter's
1171+ * sortgroupref.
1172+ *
1173+ * Note that we don't worry about possibly adding duplicate sortgrouprefs
1174+ * to the PathTarget. That would be bad, but it should be impossible unless
1175+ * the target passed to split_pathtarget_at_srfs already had duplicates.
1176+ * As long as it didn't, we can have at most one split_pathtarget_item with
1177+ * any particular nonzero sortgroupref.
1178+ */
1179+ static void
1180+ add_sp_item_to_pathtarget (PathTarget * target ,split_pathtarget_item * item )
1181+ {
1182+ int lci ;
1183+ ListCell * lc ;
1184+
1185+ /*
1186+ * Look for a pre-existing entry that is equal() and does not have a
1187+ * conflicting sortgroupref already.
1188+ */
1189+ lci = 0 ;
1190+ foreach (lc ,target -> exprs )
1191+ {
1192+ Node * node = (Node * )lfirst (lc );
1193+ Index sgref = get_pathtarget_sortgroupref (target ,lci );
1194+
1195+ if ((item -> sortgroupref == sgref ||
1196+ item -> sortgroupref == 0 ||
1197+ sgref == 0 )&&
1198+ equal (item -> expr ,node ))
1199+ {
1200+ /* Found a match. Assign item's sortgroupref if it has one. */
1201+ if (item -> sortgroupref )
1202+ {
1203+ if (target -> sortgrouprefs == NULL )
1204+ {
1205+ target -> sortgrouprefs = (Index * )
1206+ palloc0 (list_length (target -> exprs )* sizeof (Index ));
1207+ }
1208+ target -> sortgrouprefs [lci ]= item -> sortgroupref ;
1209+ }
1210+ return ;
1211+ }
1212+ lci ++ ;
1213+ }
1214+
1215+ /*
1216+ * No match, so add item to PathTarget. Copy the expr for safety.
1217+ */
1218+ add_column_to_pathtarget (target , (Expr * )copyObject (item -> expr ),
1219+ item -> sortgroupref );
1220+ }
1221+
1222+ /*
1223+ * Apply add_sp_item_to_pathtarget to each element of list.
1224+ */
1225+ static void
1226+ add_sp_items_to_pathtarget (PathTarget * target ,List * items )
1227+ {
1228+ ListCell * lc ;
1229+
1230+ foreach (lc ,items )
1231+ {
1232+ split_pathtarget_item * item = lfirst (lc );
1233+
1234+ add_sp_item_to_pathtarget (target ,item );
1235+ }
1236+ }