@@ -380,15 +380,18 @@ group_keys_reorder_by_pathkeys(List *pathkeys, List **group_pathkeys,
380380
381381 /*
382382 * We're going to search within just the first num_groupby_pathkeys of
383- * *group_pathkeys. The thing is that root->group_pathkeys is passed as
383+ * *group_pathkeys. The thing is that root->group_pathkeys is passed as
384384 * *group_pathkeys containing grouping pathkeys altogether with aggregate
385- * pathkeys. If we process aggregate pathkeys we could get an invalid
385+ * pathkeys. If we process aggregate pathkeys we could get an invalid
386386 * result of get_sortgroupref_clause_noerr(), because their
387- * pathkey->pk_eclass->ec_sortref doesn't reference query targetlist. So,
387+ * pathkey->pk_eclass->ec_sortref doesn't reference query targetlist. So,
388388 * we allocate a separate list of pathkeys for lookups.
389389 */
390390 grouping_pathkeys = list_copy_head (* group_pathkeys , num_groupby_pathkeys );
391391
392+ /* Make a new copy before reordering clauses */
393+ * group_clauses = list_copy (* group_clauses );
394+
392395 /*
393396 * Walk the pathkeys (determining ordering of the input path) and see if
394397 * there's a matching GROUP BY key. If we find one, we append it to the
@@ -400,8 +403,8 @@ group_keys_reorder_by_pathkeys(List *pathkeys, List **group_pathkeys,
400403 */
401404 foreach (lc , pathkeys )
402405 {
403- PathKey * pathkey = (PathKey * ) lfirst (lc );
404- SortGroupClause * sgc ;
406+ PathKey * pathkey = (PathKey * ) lfirst (lc );
407+ SortGroupClause * sgc ;
405408
406409 /*
407410 * Pathkeys are built in a way that allows simply comparing pointers.
@@ -431,17 +434,25 @@ group_keys_reorder_by_pathkeys(List *pathkeys, List **group_pathkeys,
431434 Assert (OidIsValid (sgc -> sortop ));
432435
433436 new_group_pathkeys = lappend (new_group_pathkeys , pathkey );
437+
438+ /*
439+ * Keeping in mind that the SortGroupClause list doesn't guarantee
440+ * unique pointers we must explicitly transfer elements one-by-one.
441+ */
434442 new_group_clauses = lappend (new_group_clauses , sgc );
443+ * group_clauses = list_delete_ptr (* group_clauses , sgc );
435444 }
436445
437446 /* remember the number of pathkeys with a matching GROUP BY key */
438447 n = list_length (new_group_pathkeys );
439448
440- /* append the remaining group pathkeys (will be treated as not sorted) */
449+ /*
450+ * Append the remaining group pathkeys (will be treated as not sorted) and
451+ * grouping clauses.
452+ */
441453 * group_pathkeys = list_concat_unique_ptr (new_group_pathkeys ,
442454 * group_pathkeys );
443- * group_clauses = list_concat_unique_ptr (new_group_clauses ,
444- * group_clauses );
455+ * group_clauses = list_concat (new_group_clauses , * group_clauses );
445456
446457 list_free (grouping_pathkeys );
447458 return n ;
@@ -484,9 +495,9 @@ pathkeys_are_duplicate(List *infos, List *pathkeys)
484495List *
485496get_useful_group_keys_orderings (PlannerInfo * root , Path * path )
486497{
487- Query * parse = root -> parse ;
488- List * infos = NIL ;
489- PathKeyInfo * info ;
498+ Query * parse = root -> parse ;
499+ List * infos = NIL ;
500+ PathKeyInfo * info ;
490501
491502 List * pathkeys = root -> group_pathkeys ;
492503 List * clauses = root -> processed_groupClause ;
@@ -561,6 +572,23 @@ get_useful_group_keys_orderings(PlannerInfo *root, Path *path)
561572 }
562573 }
563574
575+ #ifdef USE_ASSERT_CHECKING
576+ {
577+ PathKeyInfo * pinfo = linitial_node (PathKeyInfo , infos );
578+ ListCell * lc ;
579+
580+ /* Test consistency of info structures */
581+ for_each_from (lc , infos , 1 )
582+ {
583+ info = lfirst_node (PathKeyInfo , lc );
584+
585+ Assert (list_length (info -> clauses ) == list_length (pinfo -> clauses ));
586+ Assert (list_length (info -> pathkeys ) == list_length (pinfo -> pathkeys ));
587+ Assert (list_difference (info -> clauses , pinfo -> clauses ) == NIL );
588+ Assert (list_difference_ptr (info -> pathkeys , pinfo -> pathkeys ) == NIL );
589+ }
590+ }
591+ #endif
564592 return infos ;
565593}
566594
0 commit comments