@@ -83,6 +83,24 @@ static SortItem **build_column_frequencies(SortItem *groups, int ngroups,
83
83
static int count_distinct_groups (int numrows , SortItem * items ,
84
84
MultiSortSupport mss );
85
85
86
+ /*
87
+ * Compute new value for bitmap item, considering whether it's used for
88
+ * clauses connected by AND/OR.
89
+ */
90
+ #define RESULT_MERGE (value , is_or , match ) \
91
+ ((is_or) ? ((value) || (match)) : ((value) && (match)))
92
+
93
+ /*
94
+ * When processing a list of clauses, the bitmap item may get set to a value
95
+ * such that additional clauses can't change it. For example, when processing
96
+ * a list of clauses connected to AND, as soon as the item gets set to 'false'
97
+ * then it'll remain like that. Similarly clauses connected by OR and 'true'.
98
+ *
99
+ * Returns true when the value in the bitmap can't change no matter how the
100
+ * remaining clauses are evaluated.
101
+ */
102
+ #define RESULT_IS_FINAL (value , is_or ) ((is_or) ? (value) : (!(value)))
103
+
86
104
/*
87
105
* get_mincount_for_mcv_list
88
106
* Determine the minimum number of times a value needs to appear in
@@ -1589,7 +1607,7 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
1589
1607
*/
1590
1608
for (i = 0 ; i < mcvlist -> nitems ; i ++ )
1591
1609
{
1592
- bool mismatch = false ;
1610
+ bool match = true ;
1593
1611
MCVItem * item = & mcvlist -> items [i ];
1594
1612
1595
1613
/*
@@ -1599,17 +1617,16 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
1599
1617
*/
1600
1618
if (item -> isnull [idx ] || cst -> constisnull )
1601
1619
{
1602
- /* we only care about AND, because OR can't change */
1603
- if (!is_or )
1604
- matches [i ] = false;
1605
-
1620
+ matches [i ] = RESULT_MERGE (matches [i ], is_or , false);
1606
1621
continue ;
1607
1622
}
1608
1623
1609
- /* skip MCV items that were already ruled out */
1610
- if ((!is_or ) && (matches [i ] == false))
1611
- continue ;
1612
- else if (is_or && (matches [i ] == true))
1624
+ /*
1625
+ * Skip MCV items that can't change result in the bitmap.
1626
+ * Once the value gets false for AND-lists, or true for
1627
+ * OR-lists, we don't need to look at more clauses.
1628
+ */
1629
+ if (RESULT_IS_FINAL (matches [i ], is_or ))
1613
1630
continue ;
1614
1631
1615
1632
switch (oprrest )
@@ -1622,10 +1639,10 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
1622
1639
* it does not matter whether it's (var op const)
1623
1640
* or (const op var).
1624
1641
*/
1625
- mismatch = ! DatumGetBool (FunctionCall2Coll (& opproc ,
1626
- DEFAULT_COLLATION_OID ,
1627
- cst -> constvalue ,
1628
- item -> values [idx ]));
1642
+ match = DatumGetBool (FunctionCall2Coll (& opproc ,
1643
+ DEFAULT_COLLATION_OID ,
1644
+ cst -> constvalue ,
1645
+ item -> values [idx ]));
1629
1646
1630
1647
break ;
1631
1648
@@ -1640,39 +1657,21 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
1640
1657
* bucket, because there's no overlap).
1641
1658
*/
1642
1659
if (isgt )
1643
- mismatch = ! DatumGetBool (FunctionCall2Coll (& opproc ,
1644
- DEFAULT_COLLATION_OID ,
1645
- cst -> constvalue ,
1646
- item -> values [idx ]));
1660
+ match = DatumGetBool (FunctionCall2Coll (& opproc ,
1661
+ DEFAULT_COLLATION_OID ,
1662
+ cst -> constvalue ,
1663
+ item -> values [idx ]));
1647
1664
else
1648
- mismatch = ! DatumGetBool (FunctionCall2Coll (& opproc ,
1649
- DEFAULT_COLLATION_OID ,
1650
- item -> values [idx ],
1651
- cst -> constvalue ));
1665
+ match = DatumGetBool (FunctionCall2Coll (& opproc ,
1666
+ DEFAULT_COLLATION_OID ,
1667
+ item -> values [idx ],
1668
+ cst -> constvalue ));
1652
1669
1653
1670
break ;
1654
1671
}
1655
1672
1656
- /*
1657
- * XXX The conditions on matches[i] are not needed, as we
1658
- * skip MCV items that can't become true/false, depending
1659
- * on the current flag. See beginning of the loop over MCV
1660
- * items.
1661
- */
1662
-
1663
- if ((is_or ) && (!mismatch ))
1664
- {
1665
- /* OR - was not a match before, matches now */
1666
- matches [i ] = true;
1667
- continue ;
1668
- }
1669
- else if ((!is_or ) && mismatch )
1670
- {
1671
- /* AND - was a match before, does not match anymore */
1672
- matches [i ] = false;
1673
- continue ;
1674
- }
1675
-
1673
+ /* update the match bitmap with the result */
1674
+ matches [i ] = RESULT_MERGE (matches [i ], is_or , match );
1676
1675
}
1677
1676
}
1678
1677
}
@@ -1707,10 +1706,7 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
1707
1706
}
1708
1707
1709
1708
/* now, update the match bitmap, depending on OR/AND type */
1710
- if (is_or )
1711
- matches [i ] = Max (matches [i ], match );
1712
- else
1713
- matches [i ] = Min (matches [i ], match );
1709
+ matches [i ] = RESULT_MERGE (matches [i ], is_or , match );
1714
1710
}
1715
1711
}
1716
1712
else if (is_orclause (clause ) || is_andclause (clause ))
@@ -1737,13 +1733,7 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
1737
1733
* condition when merging the results.
1738
1734
*/
1739
1735
for (i = 0 ; i < mcvlist -> nitems ; i ++ )
1740
- {
1741
- /* Is this OR or AND clause? */
1742
- if (is_or )
1743
- matches [i ] = Max (matches [i ], bool_matches [i ]);
1744
- else
1745
- matches [i ] = Min (matches [i ], bool_matches [i ]);
1746
- }
1736
+ matches [i ] = RESULT_MERGE (matches [i ], is_or , bool_matches [i ]);
1747
1737
1748
1738
pfree (bool_matches );
1749
1739
}
@@ -1767,25 +1757,11 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
1767
1757
1768
1758
/*
1769
1759
* Merge the bitmap produced by mcv_get_match_bitmap into the
1770
- * current one.
1760
+ * current one. We're handling a NOT clause, so invert the result
1761
+ * before merging it into the global bitmap.
1771
1762
*/
1772
1763
for (i = 0 ; i < mcvlist -> nitems ; i ++ )
1773
- {
1774
- /*
1775
- * When handling a NOT clause, we need to invert the result
1776
- * before merging it into the global result.
1777
- */
1778
- if (not_matches [i ] == false)
1779
- not_matches [i ] = true;
1780
- else
1781
- not_matches [i ] = false;
1782
-
1783
- /* Is this OR or AND clause? */
1784
- if (is_or )
1785
- matches [i ] = Max (matches [i ], not_matches [i ]);
1786
- else
1787
- matches [i ] = Min (matches [i ], not_matches [i ]);
1788
- }
1764
+ matches [i ] = RESULT_MERGE (matches [i ], is_or , !not_matches [i ]);
1789
1765
1790
1766
pfree (not_matches );
1791
1767
}
@@ -1814,17 +1790,12 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
1814
1790
if (!item -> isnull [idx ] && DatumGetBool (item -> values [idx ]))
1815
1791
match = true;
1816
1792
1817
- /* now, update the match bitmap, depending on OR/AND type */
1818
- if (is_or )
1819
- matches [i ] = Max (matches [i ], match );
1820
- else
1821
- matches [i ] = Min (matches [i ], match );
1793
+ /* update the result bitmap */
1794
+ matches [i ] = RESULT_MERGE (matches [i ], is_or , match );
1822
1795
}
1823
1796
}
1824
1797
else
1825
- {
1826
1798
elog (ERROR , "unknown clause type: %d" , clause -> type );
1827
- }
1828
1799
}
1829
1800
1830
1801
return matches ;
0 commit comments