12
12
#include "postgres.h"
13
13
#include "fmgr.h"
14
14
#include "miscadmin.h"
15
+ #include "nodes/makefuncs.h"
15
16
#include "nodes/nodeFuncs.h"
16
17
#include "nodes/pg_list.h"
17
18
#include "nodes/relation.h"
@@ -95,11 +96,13 @@ static void set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel,
95
96
static void set_plain_rel_pathlist (PlannerInfo * root ,RelOptInfo * rel ,RangeTblEntry * rte );
96
97
static void set_append_rel_size (PlannerInfo * root ,RelOptInfo * rel ,
97
98
Index rti ,RangeTblEntry * rte );
98
- static void set_append_rel_pathlist (PlannerInfo * root ,RelOptInfo * rel ,Index rti ,RangeTblEntry * rte );
99
+ static void set_append_rel_pathlist (PlannerInfo * root ,RelOptInfo * rel ,Index rti ,RangeTblEntry * rte , PathKey * pathkeyAsc , PathKey * pathkeyDesc );
99
100
static List * accumulate_append_subpath (List * subpaths ,Path * path );
100
101
static void generate_mergeappend_paths (PlannerInfo * root ,RelOptInfo * rel ,
101
102
List * live_childrels ,
102
- List * all_child_pathkeys );
103
+ List * all_child_pathkeys ,
104
+ PathKey * pathkeyAsc ,
105
+ PathKey * pathkeyDesc );
103
106
104
107
105
108
char *
@@ -407,6 +410,41 @@ pathman_set_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, Ran
407
410
Oid * dsm_arr ;
408
411
List * ranges ,
409
412
* wrappers ;
413
+ PathKey * pathkeyAsc = NULL ,
414
+ * pathkeyDesc = NULL ;
415
+
416
+ if (prel -> parttype == PT_RANGE )
417
+ {
418
+ /*
419
+ * Get pathkeys for ascending and descending sort by patition
420
+ * column.
421
+ */
422
+ List * pathkeys ;
423
+ Var * var ;
424
+ Oid vartypeid ,
425
+ varcollid ;
426
+ int32 type_mod ;
427
+ TypeCacheEntry * tce ;
428
+
429
+ /* Make Var from patition column */
430
+ get_rte_attribute_type (rte ,prel -> attnum ,
431
+ & vartypeid ,& type_mod ,& varcollid );
432
+ var = makeVar (rti ,prel -> attnum ,vartypeid ,type_mod ,varcollid ,0 );
433
+ var -> location = -1 ;
434
+
435
+ /* Determine operator type */
436
+ tce = lookup_type_cache (var -> vartype ,TYPECACHE_LT_OPR |TYPECACHE_GT_OPR );
437
+
438
+ /* Make pathkeys */
439
+ pathkeys = build_expression_pathkey (root , (Expr * )var ,NULL ,
440
+ tce -> lt_opr ,NULL , false);
441
+ if (pathkeys )
442
+ pathkeyAsc = (PathKey * )linitial (pathkeys );
443
+ pathkeys = build_expression_pathkey (root , (Expr * )var ,NULL ,
444
+ tce -> gt_opr ,NULL , false);
445
+ if (pathkeys )
446
+ pathkeyDesc = (PathKey * )linitial (pathkeys );
447
+ }
410
448
411
449
rte -> inh = true;
412
450
dsm_arr = (Oid * )dsm_array_get_pointer (& prel -> children );
@@ -491,9 +529,8 @@ pathman_set_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, Ran
491
529
}
492
530
493
531
rel -> pathlist = NIL ;
494
- set_append_rel_pathlist (root ,rel ,rti ,rte );
532
+ set_append_rel_pathlist (root ,rel ,rti ,rte , pathkeyAsc , pathkeyDesc );
495
533
set_append_rel_size (root ,rel ,rti ,rte );
496
-
497
534
}
498
535
499
536
/* Invoke original hook if needed */
@@ -1387,7 +1424,8 @@ set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
1387
1424
*/
1388
1425
static void
1389
1426
set_append_rel_pathlist (PlannerInfo * root ,RelOptInfo * rel ,
1390
- Index rti ,RangeTblEntry * rte )
1427
+ Index rti ,RangeTblEntry * rte ,
1428
+ PathKey * pathkeyAsc ,PathKey * pathkeyDesc )
1391
1429
{
1392
1430
int parentRTindex = rti ;
1393
1431
List * live_childrels = NIL ;
@@ -1536,7 +1574,8 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
1536
1574
*/
1537
1575
if (subpaths_valid )
1538
1576
generate_mergeappend_paths (root ,rel ,live_childrels ,
1539
- all_child_pathkeys );
1577
+ all_child_pathkeys ,pathkeyAsc ,
1578
+ pathkeyDesc );
1540
1579
}
1541
1580
1542
1581
static List *
@@ -1550,7 +1589,21 @@ accumulate_append_subpath(List *subpaths, Path *path)
1550
1589
1551
1590
//---------------------------------------------------------------
1552
1591
1592
+ /*
1593
+ * Returns the same list in reversed order.
1594
+ */
1595
+ static List *
1596
+ list_reverse (List * l )
1597
+ {
1598
+ List * result = NIL ;
1599
+ ListCell * lc ;
1553
1600
1601
+ foreach (lc ,l )
1602
+ {
1603
+ result = lcons (lfirst (lc ),result );
1604
+ }
1605
+ return result ;
1606
+ }
1554
1607
1555
1608
/*
1556
1609
* generate_mergeappend_paths
@@ -1578,7 +1631,8 @@ accumulate_append_subpath(List *subpaths, Path *path)
1578
1631
static void
1579
1632
generate_mergeappend_paths (PlannerInfo * root ,RelOptInfo * rel ,
1580
1633
List * live_childrels ,
1581
- List * all_child_pathkeys )
1634
+ List * all_child_pathkeys ,
1635
+ PathKey * pathkeyAsc ,PathKey * pathkeyDesc )
1582
1636
{
1583
1637
ListCell * lcp ;
1584
1638
@@ -1588,6 +1642,7 @@ generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
1588
1642
List * startup_subpaths = NIL ;
1589
1643
List * total_subpaths = NIL ;
1590
1644
bool startup_neq_total = false;
1645
+ bool presorted = true;
1591
1646
ListCell * lcr ;
1592
1647
1593
1648
/* Select the child paths for this ordering... */
@@ -1619,6 +1674,7 @@ generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
1619
1674
childrel -> cheapest_total_path ;
1620
1675
/* Assert we do have an unparameterized path for this child */
1621
1676
Assert (cheapest_total -> param_info == NULL );
1677
+ presorted = false;
1622
1678
}
1623
1679
1624
1680
/*
@@ -1635,17 +1691,61 @@ generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
1635
1691
accumulate_append_subpath (total_subpaths ,cheapest_total );
1636
1692
}
1637
1693
1638
- /* ... and build the MergeAppend paths */
1639
- add_path (rel , (Path * )create_merge_append_path (root ,
1640
- rel ,
1641
- startup_subpaths ,
1642
- pathkeys ,
1643
- NULL ));
1644
- if (startup_neq_total )
1694
+ /*
1695
+ * When first pathkey matching ascending/descending sort by partition
1696
+ * column then build path with Append node, because MergeAppend is not
1697
+ * required in this case.
1698
+ */
1699
+ if ((PathKey * )linitial (pathkeys )== pathkeyAsc && presorted )
1700
+ {
1701
+ Path * path ;
1702
+
1703
+ path = (Path * )create_append_path (rel ,startup_subpaths ,NULL );
1704
+ path -> pathkeys = pathkeys ;
1705
+ add_path (rel ,path );
1706
+
1707
+ if (startup_neq_total )
1708
+ {
1709
+ path = (Path * )create_append_path (rel ,total_subpaths ,NULL );
1710
+ path -> pathkeys = pathkeys ;
1711
+ add_path (rel ,path );
1712
+ }
1713
+ }
1714
+ else if ((PathKey * )linitial (pathkeys )== pathkeyDesc && presorted )
1715
+ {
1716
+ /*
1717
+ * When pathkey is descending sort by partition column then we
1718
+ * need to scan partitions in reversed order.
1719
+ */
1720
+ Path * path ;
1721
+
1722
+ path = (Path * )create_append_path (rel ,
1723
+ list_reverse (startup_subpaths ),NULL );
1724
+ path -> pathkeys = pathkeys ;
1725
+ add_path (rel ,path );
1726
+
1727
+ if (startup_neq_total )
1728
+ {
1729
+ path = (Path * )create_append_path (rel ,
1730
+ list_reverse (total_subpaths ),NULL );
1731
+ path -> pathkeys = pathkeys ;
1732
+ add_path (rel ,path );
1733
+ }
1734
+ }
1735
+ else
1736
+ {
1737
+ /* ... and build the MergeAppend paths */
1645
1738
add_path (rel , (Path * )create_merge_append_path (root ,
1646
1739
rel ,
1647
- total_subpaths ,
1740
+ startup_subpaths ,
1648
1741
pathkeys ,
1649
1742
NULL ));
1743
+ if (startup_neq_total )
1744
+ add_path (rel , (Path * )create_merge_append_path (root ,
1745
+ rel ,
1746
+ total_subpaths ,
1747
+ pathkeys ,
1748
+ NULL ));
1749
+ }
1650
1750
}
1651
1751
}