@@ -54,7 +54,7 @@ static bool right_merge_direction(PlannerInfo *root, PathKey *pathkey);
54
54
PathKey *
55
55
make_canonical_pathkey (PlannerInfo * root ,
56
56
EquivalenceClass * eclass , Oid opfamily ,
57
- int strategy , bool nulls_first )
57
+ int strategy , bool nulls_first , Expr * src_expr )
58
58
{
59
59
PathKey * pk ;
60
60
ListCell * lc ;
@@ -89,6 +89,7 @@ make_canonical_pathkey(PlannerInfo *root,
89
89
pk -> pk_opfamily = opfamily ;
90
90
pk -> pk_strategy = strategy ;
91
91
pk -> pk_nulls_first = nulls_first ;
92
+ pk -> source_expr = src_expr ;
92
93
93
94
root -> canon_pathkeys = lappend (root -> canon_pathkeys , pk );
94
95
@@ -241,7 +242,7 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
241
242
242
243
/* And finally we can find or create a PathKey node */
243
244
return make_canonical_pathkey (root , eclass , opfamily ,
244
- strategy , nulls_first );
245
+ strategy , nulls_first , expr );
245
246
}
246
247
247
248
/*
@@ -1117,7 +1118,8 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
1117
1118
outer_ec ,
1118
1119
sub_pathkey -> pk_opfamily ,
1119
1120
sub_pathkey -> pk_strategy ,
1120
- sub_pathkey -> pk_nulls_first );
1121
+ sub_pathkey -> pk_nulls_first ,
1122
+ (Expr * ) outer_var );
1121
1123
}
1122
1124
}
1123
1125
else
@@ -1199,7 +1201,8 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
1199
1201
outer_ec ,
1200
1202
sub_pathkey -> pk_opfamily ,
1201
1203
sub_pathkey -> pk_strategy ,
1202
- sub_pathkey -> pk_nulls_first );
1204
+ sub_pathkey -> pk_nulls_first ,
1205
+ (Expr * ) outer_var );
1203
1206
/* score = # of equivalence peers */
1204
1207
score = list_length (outer_ec -> ec_members ) - 1 ;
1205
1208
/* +1 if it matches the proper query_pathkeys item */
@@ -1646,6 +1649,7 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
1646
1649
List * pathkeys = NIL ;
1647
1650
int nClauses = list_length (mergeclauses );
1648
1651
EquivalenceClass * * ecs ;
1652
+ Expr * * exprs ;
1649
1653
int * scores ;
1650
1654
int necs ;
1651
1655
ListCell * lc ;
@@ -1660,6 +1664,7 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
1660
1664
* duplicates) and their "popularity" scores.
1661
1665
*/
1662
1666
ecs = (EquivalenceClass * * ) palloc (nClauses * sizeof (EquivalenceClass * ));
1667
+ exprs = (Expr * * ) palloc (nClauses * sizeof (Expr * ));
1663
1668
scores = (int * ) palloc (nClauses * sizeof (int ));
1664
1669
necs = 0 ;
1665
1670
@@ -1669,14 +1674,21 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
1669
1674
EquivalenceClass * oeclass ;
1670
1675
int score ;
1671
1676
ListCell * lc2 ;
1677
+ Expr * expr ;
1672
1678
1673
1679
/* get the outer eclass */
1674
1680
update_mergeclause_eclasses (root , rinfo );
1675
1681
1676
1682
if (rinfo -> outer_is_left )
1683
+ {
1677
1684
oeclass = rinfo -> left_ec ;
1685
+ expr = (Expr * ) linitial (((OpExpr * ) rinfo -> clause )-> args );
1686
+ }
1678
1687
else
1688
+ {
1679
1689
oeclass = rinfo -> right_ec ;
1690
+ expr = (Expr * ) lsecond (((OpExpr * ) rinfo -> clause )-> args );
1691
+ }
1680
1692
1681
1693
/* reject duplicates */
1682
1694
for (j = 0 ; j < necs ; j ++ )
@@ -1700,6 +1712,8 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
1700
1712
}
1701
1713
1702
1714
ecs [necs ] = oeclass ;
1715
+ exprs [necs ] = expr ;
1716
+
1703
1717
scores [necs ] = score ;
1704
1718
necs ++ ;
1705
1719
}
@@ -1801,7 +1815,8 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
1801
1815
ec ,
1802
1816
linitial_oid (ec -> ec_opfamilies ),
1803
1817
BTLessStrategyNumber ,
1804
- false);
1818
+ false,
1819
+ exprs [best_j ]);
1805
1820
/* can't be redundant because no duplicate ECs */
1806
1821
Assert (!pathkey_is_redundant (pathkey , pathkeys ));
1807
1822
pathkeys = lappend (pathkeys , pathkey );
@@ -1855,18 +1870,23 @@ make_inner_pathkeys_for_merge(PlannerInfo *root,
1855
1870
EquivalenceClass * oeclass ;
1856
1871
EquivalenceClass * ieclass ;
1857
1872
PathKey * pathkey ;
1873
+ Expr * src_expr ;
1858
1874
1859
1875
update_mergeclause_eclasses (root , rinfo );
1860
1876
1877
+ Assert (IsA (rinfo -> clause , OpExpr ) && rinfo -> orclause == NULL );
1878
+
1861
1879
if (rinfo -> outer_is_left )
1862
1880
{
1863
1881
oeclass = rinfo -> left_ec ;
1864
1882
ieclass = rinfo -> right_ec ;
1883
+ src_expr = (Expr * ) lsecond (((OpExpr * ) rinfo -> clause )-> args );
1865
1884
}
1866
1885
else
1867
1886
{
1868
1887
oeclass = rinfo -> right_ec ;
1869
1888
ieclass = rinfo -> left_ec ;
1889
+ src_expr = (Expr * ) linitial (((OpExpr * ) rinfo -> clause )-> args );
1870
1890
}
1871
1891
1872
1892
/* outer eclass should match current or next pathkeys */
@@ -1894,7 +1914,8 @@ make_inner_pathkeys_for_merge(PlannerInfo *root,
1894
1914
ieclass ,
1895
1915
opathkey -> pk_opfamily ,
1896
1916
opathkey -> pk_strategy ,
1897
- opathkey -> pk_nulls_first );
1917
+ opathkey -> pk_nulls_first ,
1918
+ src_expr );
1898
1919
1899
1920
/*
1900
1921
* Don't generate redundant pathkeys (which can happen if multiple
0 commit comments