45{
50
51
52typedef struct
53{
54 bool nonempty;
55
58
59
60typedef struct
61{
66 bool unclassifiable;
68
69
70typedef struct
71{
73 int indexcol;
75
76
82 List **bitindexpaths);
89 List *indexjoinclauses,
90 int considered_clauses,
91 List **considered_relids);
99 List **considered_relids);
101 List *indexjoinclauses);
104 List **bitindexpaths);
107 bool useful_predicate,
109 bool *skip_nonnative_saop);
111 List *clauses,
List *other_clauses);
113 List *clauses,
List *other_clauses);
130 double rowcount);
138 List **joinorclauses);
152 int indexcol,
160 int indexcol,
164 int indexcol,
169 int indexarg,
170 int indexcol,
174 int indexcol,
178 int indexcol,
182 int indexcol,
186 int indexcol,
189 bool var_on_left);
191 List **orderby_clauses_p,
192 List **clause_columns_p);
194 int indexcol,
Expr *clause,
Oid pk_opfamily);
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237void
239{
248
249
251 return;
252
253
254 bitindexpaths = bitjoinpaths = joinorclauses =
NIL;
255
256
258 {
260
261
263
264
265
266
267
268
270 continue;
271
272
273
274
275 MemSet(&rclauseset, 0,
sizeof(rclauseset));
277
278
279
280
281
282
284 &bitindexpaths);
285
286
287
288
289
290
291
292 MemSet(&jclauseset, 0,
sizeof(jclauseset));
294 &jclauseset, &joinorclauses);
295
296
297
298
299
300 MemSet(&eclauseset, 0,
sizeof(eclauseset));
302 &eclauseset);
303
304
305
306
307
310 &rclauseset,
311 &jclauseset,
312 &eclauseset,
313 &bitjoinpaths);
314 }
315
316
317
318
319
322 bitindexpaths =
list_concat(bitindexpaths, indexpaths);
323
324
325
326
327
330 bitjoinpaths =
list_concat(bitjoinpaths, indexpaths);
331
332
333
334
335
336
337
338
339 if (bitindexpaths !=
NIL)
340 {
343
348
349
352 }
353
354
355
356
357
358
359
360
361
362
363
364 if (bitjoinpaths !=
NIL)
365 {
366 List *all_path_outers;
367
368
369 all_path_outers =
NIL;
370 foreach(lc, bitjoinpaths)
371 {
374
376 required_outer);
377 }
378
379
380 foreach(lc, all_path_outers)
381 {
386 double loop_count;
389
390
392 foreach(lcp, bitjoinpaths)
393 {
395
397 this_path_set =
lappend(this_path_set, path);
398 }
399
400
401
402
403
404 this_path_set =
list_concat(this_path_set, bitindexpaths);
405
406
408
409
413 required_outer, loop_count, 0);
415 }
416 }
417}
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434static void
440 List **bitindexpaths)
441{
442 int considered_clauses = 0;
444 int indexcol;
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467 for (indexcol = 0; indexcol <
index->nkeycolumns; indexcol++)
468 {
469
472 rclauseset, jclauseset, eclauseset,
473 bitindexpaths,
475 considered_clauses,
476 &considered_relids);
477
480 rclauseset, jclauseset, eclauseset,
481 bitindexpaths,
483 considered_clauses,
484 &considered_relids);
485 }
486}
487
488
489
490
491
492
493
494
495
496
497
498
499
500static void
506 List **bitindexpaths,
507 List *indexjoinclauses,
508 int considered_clauses,
509 List **considered_relids)
510{
512
513
514 foreach(lc, indexjoinclauses)
515 {
517 Relids clause_relids = iclause->
rinfo->clause_relids;
519 int num_considered_relids;
520
521
522 if (
list_member(*considered_relids, clause_relids))
523 continue;
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538 num_considered_relids =
list_length(*considered_relids);
539 for (int pos = 0; pos < num_considered_relids; pos++)
540 {
542
543
544
545
546
547
548
550 continue;
551
552
553
554
555
556
557
558
559
560 if (parent_ec &&
562 indexjoinclauses))
563 continue;
564
565
566
567
568
569
570 if (
list_length(*considered_relids) >= 10 * considered_clauses)
571 break;
572
573
575 rclauseset, jclauseset, eclauseset,
576 bitindexpaths,
578 considered_relids);
579 }
580
581
583 rclauseset, jclauseset, eclauseset,
584 bitindexpaths,
585 clause_relids,
586 considered_relids);
587 }
588}
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603static void
609 List **bitindexpaths,
611 List **considered_relids)
612{
614 int indexcol;
615
616
618 return;
619
620
621 MemSet(&clauseset, 0,
sizeof(clauseset));
622
623 for (indexcol = 0; indexcol <
index->nkeycolumns; indexcol++)
624 {
626
627
629 {
631
635 }
636
637
638
639
640
641
642
644 {
646
648 {
651 break;
652 }
653 }
654
655
659
662 }
663
664
666
667
669
670
671
672
673 *considered_relids =
lappend(*considered_relids, relids);
674}
675
676
677
678
679
680
681static bool
683 List *indexjoinclauses)
684{
686
687 foreach(lc, indexjoinclauses)
688 {
691
692 if (rinfo->parent_ec == parent_ec &&
694 return true;
695 }
696 return false;
697}
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713static void
716 List **bitindexpaths)
717{
719 bool skip_nonnative_saop = false;
721
722
723
724
725
730 &skip_nonnative_saop);
731
732
733
734
735
736
737
738
739
740
741
742
743
744 foreach(lc, indexpaths)
745 {
747
748 if (
index->amhasgettuple)
750
751 if (
index->amhasgetbitmap &&
754 *bitindexpaths =
lappend(*bitindexpaths, ipath);
755 }
756
757
758
759
760
761
762 if (skip_nonnative_saop)
763 {
766 false,
768 NULL);
769 *bitindexpaths =
list_concat(*bitindexpaths, indexpaths);
770 }
771}
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
810 bool useful_predicate,
812 bool *skip_nonnative_saop)
813{
818 double loop_count;
819 List *orderbyclauses;
820 List *orderbyclausecols;
821 List *index_pathkeys;
822 List *useful_pathkeys;
823 bool pathkeys_possibly_useful;
824 bool index_is_ordered;
825 bool index_only_scan;
826 int indexcol;
827
829
830
831
832
833 switch (scantype)
834 {
836 if (!
index->amhasgettuple)
838 break;
840 if (!
index->amhasgetbitmap)
842 break;
844
845 break;
846 }
847
848
849
850
851
852
853
854
855
856
857
858
859
862 for (indexcol = 0; indexcol <
index->nkeycolumns; indexcol++)
863 {
865
867 {
870
871 if (skip_nonnative_saop && !
index->amsearcharray &&
873 {
874
875
876
877
878
879
880
881 *skip_nonnative_saop = true;
882 continue;
883 }
884
885
886 index_clauses =
lappend(index_clauses, iclause);
888 rinfo->clause_relids);
889 }
890
891
892
893
894
895
896
897
898
899 if (index_clauses ==
NIL && !
index->amoptionalkey)
901 }
902
903
905
906
908
909
910
911
912
913
916 index_is_ordered = (
index->sortopfamily != NULL);
917 if (index_is_ordered && pathkeys_possibly_useful)
918 {
922 index_pathkeys);
923 orderbyclauses =
NIL;
924 orderbyclausecols =
NIL;
925 }
926 else if (
index->amcanorderbyop && pathkeys_possibly_useful)
927 {
928
929
930
931
932
933
935 &orderbyclauses,
936 &orderbyclausecols);
938 useful_pathkeys =
root->query_pathkeys;
939 else
942 }
943 else
944 {
945 useful_pathkeys =
NIL;
946 orderbyclauses =
NIL;
947 orderbyclausecols =
NIL;
948 }
949
950
951
952
953
954
957
958
959
960
961
962
963
964 if (index_clauses !=
NIL || useful_pathkeys !=
NIL || useful_predicate ||
965 index_only_scan)
966 {
968 index_clauses,
969 orderbyclauses,
970 orderbyclausecols,
971 useful_pathkeys,
973 index_only_scan,
974 outer_relids,
975 loop_count,
976 false);
978
979
980
981
982
983 if (
index->amcanparallel &&
986 {
988 index_clauses,
989 orderbyclauses,
990 orderbyclausecols,
991 useful_pathkeys,
993 index_only_scan,
994 outer_relids,
995 loop_count,
996 true);
997
998
999
1000
1001
1004 else
1006 }
1007 }
1008
1009
1010
1011
1012 if (index_is_ordered && pathkeys_possibly_useful)
1013 {
1017 index_pathkeys);
1018 if (useful_pathkeys !=
NIL)
1019 {
1021 index_clauses,
1024 useful_pathkeys,
1026 index_only_scan,
1027 outer_relids,
1028 loop_count,
1029 false);
1031
1032
1033 if (
index->amcanparallel &&
1036 {
1038 index_clauses,
1041 useful_pathkeys,
1043 index_only_scan,
1044 outer_relids,
1045 loop_count,
1046 true);
1047
1048
1049
1050
1051
1054 else
1056 }
1057 }
1058 }
1059
1061}
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1091 List *clauses,
List *other_clauses)
1092{
1096
1098 {
1102 bool useful_predicate;
1103
1104
1105 if (!
index->amhasgetbitmap)
1106 continue;
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120 useful_predicate = false;
1122 {
1124 {
1125
1126 }
1127 else
1128 {
1129
1130 if (all_clauses ==
NIL)
1132
1134 continue;
1135
1137 useful_predicate = true;
1138 }
1139 }
1140
1141
1142
1143
1144 MemSet(&clauseset, 0,
sizeof(clauseset));
1146
1147
1148
1149
1150
1151 if (!clauseset.
nonempty && !useful_predicate)
1152 continue;
1153
1154
1155
1156
1158
1159
1160
1161
1164 useful_predicate,
1166 NULL);
1168 }
1169
1171}
1172
1173
1174
1175
1176
1177
1178typedef struct
1179{
1180 int indexnum;
1181
1182 int colnum;
1183
1185
1187 int argindex;
1188
1189 int groupindex;
1190
1192
1193
1194
1195
1196
1197static int
1199{
1202
1204 return -1;
1206 return 1;
1207
1209 return -1;
1211 return 1;
1212
1214 return -1;
1215 else if (match_a->
opno > match_b->
opno)
1216 return 1;
1217
1219 return -1;
1221 return 1;
1222
1224 return -1;
1226 return 1;
1227
1228 return 0;
1229}
1230
1231
1232
1233
1234
1235static int
1237{
1240
1242 return -1;
1244 return 1;
1245
1247 return -1;
1249 return 1;
1250
1251 return 0;
1252}
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1270{
1271 int n;
1273 int group_start;
1275 bool matched = false;
1281
1283 orargs = ((
BoolExpr *) rinfo->orclause)->args;
1285
1286
1287
1288
1289
1290
1293 foreach(lc, orargs)
1294 {
1300 *rightop;
1302 int indexnum;
1303 int colnum;
1304
1312
1314 continue;
1315
1317
1318
1320 continue;
1321
1323 opno = clause->
opno;
1324
1325
1327 continue;
1328
1329
1330
1331
1332
1333
1334
1338
1342
1343
1344
1345
1346
1347
1348
1349
1353 {
1355
1357 {
1358
1359 continue;
1360 }
1361 nonConstExpr = rightop;
1362 }
1366 {
1367 nonConstExpr = leftop;
1368 }
1369 else
1370 {
1371 continue;
1372 }
1373
1374
1375
1376
1377
1378
1379
1380
1381 indexnum = 0;
1383 {
1385
1386
1387
1388
1389
1390 if (!
index->amhasgetbitmap || !
index->amsearcharray)
1391 continue;
1392
1393 for (colnum = 0; colnum <
index->nkeycolumns; colnum++)
1394 {
1396 {
1399 matches[
i].
opno = opno;
1401 matched = true;
1402 break;
1403 }
1404 }
1405
1406
1407
1408
1409
1410 if (matches[
i].indexnum >= 0)
1411 break;
1412 indexnum++;
1413 }
1414 }
1415
1416
1417
1418
1419
1420 if (!matched)
1421 {
1423 return orargs;
1424 }
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1438
1439
1440 for (
i = 1;
i < n;
i++)
1441 {
1442
1443
1444
1445
1446
1447
1448
1449 if (matches[
i].indexnum == matches[
i - 1].indexnum &&
1450 matches[
i].colnum == matches[
i - 1].colnum &&
1451 matches[
i].opno == matches[
i - 1].opno &&
1452 matches[
i].inputcollid == matches[
i - 1].inputcollid &&
1453 matches[
i].indexnum != -1)
1455 }
1456
1457
1459
1460
1461
1462
1463
1464 group_start = 0;
1465 for (
i = 1;
i <= n;
i++)
1466 {
1467
1468 if (group_start >= 0 &&
1470 matches[
i].indexnum != matches[group_start].indexnum ||
1471 matches[
i].colnum != matches[group_start].colnum ||
1472 matches[
i].opno != matches[group_start].opno ||
1473 matches[
i].inputcollid != matches[group_start].inputcollid ||
1474 matches[
i].indexnum == -1))
1475 {
1476
1477
1478
1479 if (
i - group_start == 1)
1480 {
1483 matches[group_start].argindex));
1484 }
1485 else
1486 {
1487
1488
1489
1494
1496
1497
1498 for (
j = group_start;
j <
i;
j++)
1499 {
1501
1505 else
1507 }
1508
1509
1516 rinfo->pseudoconstant,
1522 }
1523
1525 }
1526 }
1529}
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1548{
1554 Cost jointcost = 0.0,
1555 splitcost = 0.0;
1558
1559
1560
1561
1564 orargs,
1565 other_clauses);
1567 {
1571 }
1572
1573
1574
1575
1576
1577
1578
1579 if (jointlist !=
NIL && other_clauses ==
NIL)
1580 return jointlist;
1581
1582
1583
1584
1585 foreach(lc, args)
1586 {
1588
1590 orargs,
1591 other_clauses);
1592
1594 {
1596 break;
1597 }
1598
1601 splitlist =
lappend(splitlist, bitmapqual);
1602 }
1603
1604
1605
1606
1607 if (splitlist ==
NIL)
1608 return jointlist;
1609 else if (jointlist ==
NIL)
1610 return splitlist;
1611 else
1612 return (jointcost < splitcost) ? jointlist : splitlist;
1613}
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1628 List *clauses,
List *other_clauses)
1629{
1633
1634
1635
1636
1637
1639
1640 foreach(lc, clauses)
1641 {
1647 List *inner_other_clauses =
NIL;
1648
1649
1651 continue;
1652
1653
1654
1655
1656
1658
1659
1660
1661
1662
1663
1665
1666 if (groupedArgs != ((
BoolExpr *) rinfo->orclause)->args)
1667 {
1668
1669
1670
1671
1672
1673
1674
1675
1676
1678 }
1679
1680 foreach(
j, groupedArgs)
1681 {
1684
1685
1687 {
1689
1691 andargs,
1692 all_clauses);
1693
1694
1697 andargs,
1698 all_clauses));
1699 }
1701 {
1703
1704
1705
1706
1707
1709 rel, ri,
1710 inner_other_clauses);
1711
1713 {
1715 break;
1716 }
1717 else
1718 {
1720 continue;
1721 }
1722 }
1723 else
1724 {
1727
1729
1731 orargs,
1732 all_clauses);
1733 }
1734
1735
1736
1737
1738
1740 {
1742 break;
1743 }
1744
1745
1746
1747
1748
1750 pathlist =
lappend(pathlist, bitmapqual);
1751 }
1752
1753 if (inner_other_clauses !=
NIL)
1755
1756
1757
1758
1759
1760 if (pathlist !=
NIL)
1761 {
1764 }
1765 }
1766
1768}
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1784{
1794
1796 if (npaths == 1)
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1856 npaths = 0;
1857 foreach(l, paths)
1858 {
1860
1862
1863
1865 {
1866 pathinfoarray[npaths++] = pathinfo;
1867 continue;
1868 }
1869
1870 for (
i = 0;
i < npaths;
i++)
1871 {
1872 if (!pathinfoarray[
i]->unclassifiable &&
1874 break;
1875 }
1877 {
1878
1883
1886 if (ncost < ocost)
1887 pathinfoarray[
i] = pathinfo;
1888 }
1889 else
1890 {
1891
1892 pathinfoarray[npaths++] = pathinfo;
1893 }
1894 }
1895
1896
1897 if (npaths == 1)
1898 return pathinfoarray[0]->
path;
1899
1900
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913 for (
i = 0;
i < npaths;
i++)
1914 {
1918
1919 pathinfo = pathinfoarray[
i];
1924
1925 for (
j =
i + 1;
j < npaths;
j++)
1926 {
1928
1929 pathinfo = pathinfoarray[
j];
1930
1932 continue;
1933 if (pathinfo->
preds)
1934 {
1935 bool redundant = false;
1936
1937
1938 foreach(l, pathinfo->
preds)
1939 {
1941
1943 {
1944 redundant = true;
1945 break;
1946 }
1947 }
1948 if (redundant)
1949 continue;
1950 }
1951
1954 if (newcost < costsofar)
1955 {
1956
1957 costsofar = newcost;
1962 }
1963 else
1964 {
1965
1967 }
1968 }
1969
1970
1971 if (
i == 0 || costsofar < bestcost)
1972 {
1973 bestpaths = paths;
1974 bestcost = costsofar;
1975 }
1976
1977
1979 }
1980
1984}
1985
1986
1987static int
1989{
1996
1999
2000
2001
2002
2003 if (acost < bcost)
2004 return -1;
2005 if (acost > bcost)
2006 return 1;
2007
2008 if (aselec < bselec)
2009 return -1;
2010 if (aselec > bselec)
2011 return 1;
2012
2013 return 0;
2014}
2015
2016
2017
2018
2019
2022{
2024
2025
2026 bpath.
path.type = T_BitmapHeapPath;
2028 bpath.
path.parent = rel;
2030 bpath.
path.param_info = ipath->param_info;
2033
2034
2035
2036
2037
2039
2040
2042 bpath.
path.param_info,
2043 ipath,
2046
2048}
2049
2050
2051
2052
2053
2056{
2058
2059
2060
2061
2062
2064
2066}
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2085{
2089
2092
2093
2097
2098
2099
2100
2101
2102
2103
2104
2105
2107 {
2108 result->clauseids = NULL;
2109 result->unclassifiable =
true;
2111 }
2112
2113
2114 clauseids = NULL;
2115 foreach(lc,
result->quals)
2116 {
2118
2121 }
2122 foreach(lc,
result->preds)
2123 {
2125
2128 }
2129 result->clauseids = clauseids;
2130 result->unclassifiable =
false;
2131
2133}
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151static void
2153{
2155 {
2158
2160 {
2162 }
2163 }
2165 {
2168
2170 {
2172 }
2173 }
2175 {
2178
2180 {
2182
2184 }
2186 }
2187 else
2189}
2190
2191
2192
2193
2194
2195
2196
2197
2198static int
2200{
2203
2205 foreach(lc, *nodelist)
2206 {
2208
2209 if (
equal(node, oldnode))
2212 }
2213
2214 *nodelist =
lappend(*nodelist, node);
2215
2217}
2218
2219
2220
2221
2222
2223
2224static bool
2226{
2229 Bitmapset *index_canreturn_attrs = NULL;
2232
2233
2235 return false;
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260 foreach(lc,
index->indrestrictinfo)
2261 {
2263
2265 }
2266
2267
2268
2269
2270
2271 for (
i = 0;
i <
index->ncolumns;
i++)
2272 {
2273 int attno =
index->indexkeys[
i];
2274
2275
2276
2277
2278
2279 if (attno == 0)
2280 continue;
2281
2283 index_canreturn_attrs =
2286 }
2287
2288
2290
2293
2295}
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323static double
2325{
2327 int outer_relid;
2328
2329
2330 if (outer_relids == NULL)
2331 return 1.0;
2332
2334 outer_relid = -1;
2335 while ((outer_relid =
bms_next_member(outer_relids, outer_relid)) >= 0)
2336 {
2338 double rowcount;
2339
2340
2341 if (outer_relid >=
root->simple_rel_array_size)
2342 continue;
2343 outer_rel =
root->simple_rel_array[outer_relid];
2344 if (outer_rel == NULL)
2345 continue;
2347
2348
2350 continue;
2351
2352
2354
2355
2357 cur_relid,
2358 outer_relid,
2360
2361
2364 }
2365
2367}
2368
2369
2370
2371
2372
2373
2374
2375
2376static double
2380 double rowcount)
2381{
2383
2384 foreach(lc,
root->join_info_list)
2385 {
2387
2391 {
2392
2393 double nraw;
2394 double nunique;
2395
2399 nraw,
2400 NULL,
2401 NULL);
2402 if (rowcount > nunique)
2403 rowcount = nunique;
2404 }
2405 }
2406 return rowcount;
2407}
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420static double
2422{
2423 double rowcount = 1.0;
2424 int relid;
2425
2426 relid = -1;
2428 {
2430
2431
2432 if (relid >=
root->simple_rel_array_size)
2433 continue;
2434 rel =
root->simple_rel_array[relid];
2435 if (rel == NULL)
2436 continue;
2438
2439
2441 continue;
2442
2443
2445
2446
2447 rowcount *= rel->
rows;
2448 }
2449 return rowcount;
2450}
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462static void
2466{
2467
2469}
2470
2471
2472
2473
2474
2475
2476
2477
2478static void
2482 List **joinorclauses)
2483{
2485
2486
2488 {
2490
2491
2493 continue;
2494
2495
2496
2497
2498
2499
2502
2504 }
2505}
2506
2507
2508
2509
2510
2511
2512static void
2515{
2516 int indexcol;
2517
2518
2519 if (!
index->rel->has_eclass_joins)
2520 return;
2521
2522 for (indexcol = 0; indexcol <
index->nkeycolumns; indexcol++)
2523 {
2526
2527
2529 arg.indexcol = indexcol;
2534 index->rel->lateral_referencers);
2535
2536
2537
2538
2539
2540
2542 }
2543}
2544
2545
2546
2547
2548
2549
2550static void
2555{
2557
2558 foreach(lc, clauses)
2559 {
2561
2563 }
2564}
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583static void
2588{
2589 int indexcol;
2590
2591
2592
2593
2594
2595
2596
2597 if (rinfo->pseudoconstant)
2598 return;
2599
2600
2601
2602
2603
2605 return;
2606
2607
2608 for (indexcol = 0; indexcol <
index->nkeycolumns; indexcol++)
2609 {
2612
2613
2615 {
2617
2618 if (iclause->
rinfo == rinfo)
2619 return;
2620 }
2621
2622
2624 rinfo,
2625 indexcol,
2627 if (iclause)
2628 {
2629
2633 return;
2634 }
2635 }
2636}
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2710 int indexcol,
2712{
2716
2717 Assert(indexcol < index->nkeycolumns);
2718
2719
2720
2721
2722
2723 if (clause == NULL)
2724 return NULL;
2725
2726
2727 opfamily =
index->opfamily[indexcol];
2729 {
2731 if (iclause)
2732 return iclause;
2733 }
2734
2735
2736
2737
2738
2739
2741 {
2743 }
2745 {
2747 }
2749 {
2751 }
2753 {
2755 }
2757 {
2759 }
2761 {
2763
2764 if (!nt->argisrow &&
2766 {
2768 iclause->
rinfo = rinfo;
2770 iclause->
lossy =
false;
2773 return iclause;
2774 }
2775 }
2776
2777 return NULL;
2778}
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788static bool
2790{
2792 return IsBuiltinBooleanOpfamily(opfamily);
2793 else
2795}
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2816 int indexcol,
2818{
2821
2822
2824 {
2825
2830 }
2831
2833 {
2835
2837 {
2838
2843 }
2844 }
2845
2846
2847
2848
2849
2850
2852 {
2855
2856 if (btest->booltesttype ==
IS_TRUE &&
2858 {
2859
2864 }
2865 else if (btest->booltesttype ==
IS_FALSE &&
2867 {
2868
2873 }
2874 }
2875
2876
2877
2878
2879
2880 if (op)
2881 {
2883
2884 iclause->
rinfo = rinfo;
2886 iclause->
lossy =
false;
2889 return iclause;
2890 }
2891
2892 return NULL;
2893}
2894
2895
2896
2897
2898
2899
2903 int indexcol,
2905{
2909 *rightop;
2915
2916
2917
2918
2919
2920
2922 return NULL;
2923
2926 expr_op = clause->opno;
2927 expr_coll = clause->inputcollid;
2928
2929 index_relid =
index->rel->relid;
2930 opfamily =
index->opfamily[indexcol];
2931 idxcollation =
index->indexcollations[indexcol];
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2945 {
2948 {
2950 iclause->
rinfo = rinfo;
2952 iclause->
lossy =
false;
2955 return iclause;
2956 }
2957
2958
2959
2960
2961
2964 rinfo,
2965 clause->opfuncid,
2966 0,
2967 indexcol,
2969 }
2970
2974 {
2976 {
2978
2981 {
2983
2984
2986
2987
2989 iclause->
rinfo = rinfo;
2991 iclause->
lossy =
false;
2994 return iclause;
2995 }
2996 }
2997
2998
2999
3000
3001
3004 rinfo,
3005 clause->opfuncid,
3006 1,
3007 indexcol,
3009 }
3010
3011 return NULL;
3012}
3013
3014
3015
3016
3017
3018
3022 int indexcol,
3024{
3026 int indexarg;
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039 indexarg = 0;
3040 foreach(lc, clause->args)
3041 {
3043
3045 {
3047 rinfo,
3048 clause->funcid,
3049 indexarg,
3050 indexcol,
3052 }
3053
3054 indexarg++;
3055 }
3056
3057 return NULL;
3058}
3059
3060
3061
3062
3063
3064
3069 int indexarg,
3070 int indexcol,
3072{
3076
3078 return NULL;
3079
3080 req.
type = T_SupportRequestIndexCondition;
3089
3091
3095
3097 {
3101
3102
3103
3104
3105
3106 foreach(lc, sresult)
3107 {
3109
3110 indexquals =
lappend(indexquals,
3112 }
3113
3114 iclause->
rinfo = rinfo;
3119
3120 return iclause;
3121 }
3122
3123 return NULL;
3124}
3125
3126
3127
3128
3129
3130
3134 int indexcol,
3136{
3139 *rightop;
3146
3147
3148 if (!saop->useOr)
3149 return NULL;
3153 expr_op = saop->opno;
3154 expr_coll = saop->inputcollid;
3155
3156 index_relid =
index->rel->relid;
3157 opfamily =
index->opfamily[indexcol];
3158 idxcollation =
index->indexcollations[indexcol];
3159
3160
3161
3162
3166 {
3169 {
3171
3172 iclause->
rinfo = rinfo;
3174 iclause->
lossy =
false;
3177 return iclause;
3178 }
3179
3180
3181
3182
3183
3184 }
3185
3186 return NULL;
3187}
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3202 int indexcol,
3204{
3210 *rightop;
3211 bool var_on_left;
3214
3215
3216 if (
index->relam != BTREE_AM_OID)
3217 return NULL;
3218
3219 index_relid =
index->rel->relid;
3220 opfamily =
index->opfamily[indexcol];
3221 idxcollation =
index->indexcollations[indexcol];
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3237
3238
3240 return NULL;
3241
3242
3243
3244
3248 {
3249
3250 var_on_left = true;
3251 }
3255 {
3256
3259 return NULL;
3260 var_on_left = false;
3261 }
3262 else
3263 return NULL;
3264
3265
3267 {
3273 rinfo,
3274 indexcol,
3276 expr_op,
3277 var_on_left);
3278 }
3279
3280 return NULL;
3281}
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3296 int indexcol,
3298{
3301 Node *indexExpr = NULL;
3306 bool firstTime = true;
3307 bool haveNonConst = false;
3312
3313
3314 if (!
index->amsearcharray)
3315 return NULL;
3316
3317
3318
3319
3320
3321
3322
3323
3324 foreach(lc, orclause->args)
3325 {
3330 *rightop;
3332
3333
3335 break;
3336
3337
3339 break;
3340
3342 opno = subClause->
opno;
3343
3344
3346 break;
3347
3348
3349
3350
3351
3352
3358 {
3359 indexExpr = leftop;
3360 constExpr = rightop;
3361 }
3365 {
3368 {
3369
3370 break;
3371 }
3372 indexExpr = rightop;
3373 constExpr = leftop;
3374 }
3375 else
3376 {
3377 break;
3378 }
3379
3380
3381
3382
3383
3384
3385 if (firstTime)
3386 {
3387 matchOpno = opno;
3390 inputcollid = subClause->inputcollid;
3391
3392
3393
3394
3395
3396
3398 inputcollid) ||
3401 break;
3402
3403
3404
3405
3406
3407 if (consttype == RECORDOID ||
exprType(indexExpr) == RECORDOID)
3408 break;
3409
3410 firstTime = false;
3411 }
3412 else
3413 {
3414 if (matchOpno != opno ||
3415 inputcollid != subClause->inputcollid ||
3417 break;
3418 }
3419
3420
3421
3422
3423
3425 haveNonConst = true;
3426
3427 consts =
lappend(consts, constExpr);
3428 }
3429
3430
3431
3432
3433
3434
3435
3436 if (lc != NULL || indexExpr == NULL)
3437 {
3439 return NULL;
3440 }
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451 saopexpr =
make_SAOP_expr(matchOpno, indexExpr, consttype, inputcollid,
3452 inputcollid, consts, haveNonConst);
3453 Assert(saopexpr != NULL);
3454
3455
3456
3457
3459 iclause->
rinfo = rinfo;
3461 (
Expr *) saopexpr));
3462 iclause->
lossy =
false;
3465 return iclause;
3466}
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3494 int indexcol,
3497 bool var_on_left)
3498{
3501 int op_strategy;
3504 int matching_cols;
3512
3513 iclause->
rinfo = rinfo;
3515
3516 if (var_on_left)
3517 {
3518 var_args = clause->largs;
3519 non_var_args = clause->rargs;
3520 }
3521 else
3522 {
3523 var_args = clause->rargs;
3524 non_var_args = clause->largs;
3525 }
3526
3528 &op_strategy,
3529 &op_lefttype,
3530 &op_righttype);
3531
3532
3534
3535
3540
3541
3542
3543
3544
3545
3546
3547 matching_cols = 1;
3548
3550 {
3554
3556 if (!var_on_left)
3557 {
3558
3561 break;
3562 }
3564 break;
3566 break;
3567
3568
3569
3570
3571 for (
i = 0;
i <
index->nkeycolumns;
i++)
3572 {
3575 index->opfamily[
i]) == op_strategy &&
3578 matching_cols)))
3579 break;
3580 }
3581 if (
i >=
index->nkeycolumns)
3582 break;
3583
3584
3586
3587
3589 &op_strategy,
3590 &op_lefttype,
3591 &op_righttype);
3595 righttypes =
lappend_oid(righttypes, op_righttype);
3596
3597
3598 matching_cols++;
3599 }
3600
3601
3603
3604
3605
3606
3607
3608 if (var_on_left && !iclause->
lossy)
3610 else
3611 {
3612
3613
3614
3615
3616
3617 if (!iclause->
lossy)
3618 {
3619
3620 new_ops = expr_ops;
3621 }
3624 {
3625
3627 }
3628 else
3629 {
3633
3638 else
3639 elog(
ERROR,
"unexpected strategy number %d", op_strategy);
3641 forthree(opfamilies_cell, opfamilies,
3642 lefttypes_cell, lefttypes,
3643 righttypes_cell, righttypes)
3644 {
3648
3650 op_strategy);
3652 elog(
ERROR,
"missing operator %d(%u,%u) in opfamily %u",
3653 op_strategy, lefttype, righttype, opfam);
3655 }
3656 }
3657
3658
3659 if (matching_cols > 1)
3660 {
3662
3664 rc->opnos = new_ops;
3666 matching_cols);
3668 matching_cols);
3673 }
3674 else
3675 {
3677
3678
3680
3687 }
3688 }
3689
3690 return iclause;
3691}
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713static void
3715 List **orderby_clauses_p,
3716 List **clause_columns_p)
3717{
3719
3720 *orderby_clauses_p =
NIL;
3721 *clause_columns_p =
NIL;
3722
3723
3724 if (!
index->amcanorderbyop)
3725 return;
3726
3727 foreach(lc1, pathkeys)
3728 {
3730 bool found = false;
3733
3734
3735
3737 return;
3738
3739
3740 if (pathkey->pk_eclass->ec_has_volatile)
3741 return;
3742
3743
3744
3745
3746
3747
3748
3749
3750
3752 index->rel->relids);
3754 {
3755 int indexcol;
3756
3757
3759 continue;
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769 for (indexcol = 0; indexcol <
index->nkeycolumns; indexcol++)
3770 {
3772
3774 indexcol,
3777 if (expr)
3778 {
3779 *orderby_clauses_p =
lappend(*orderby_clauses_p, expr);
3780 *clause_columns_p =
lappend_int(*clause_columns_p, indexcol);
3781 found = true;
3782 break;
3783 }
3784 }
3785
3786 if (found)
3787 break;
3788 }
3789
3790
3791
3792
3793
3794 if (!found)
3795 return;
3796 }
3797}
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3826 int indexcol,
3829{
3833 *rightop;
3837 bool commuted;
3838
3839 Assert(indexcol < index->nkeycolumns);
3840
3841 opfamily =
index->opfamily[indexcol];
3842 idxcollation =
index->indexcollations[indexcol];
3843
3844
3845
3846
3848 return NULL;
3851 if (!leftop || !rightop)
3852 return NULL;
3853 expr_op = ((
OpExpr *) clause)->opno;
3854 expr_coll = ((
OpExpr *) clause)->inputcollid;
3855
3856
3857
3858
3860 return NULL;
3861
3862
3863
3864
3865
3869 {
3870 commuted = false;
3871 }
3875 {
3876
3879 return NULL;
3880 commuted = true;
3881 }
3882 else
3883 return NULL;
3884
3885
3886
3887
3888
3890 if (sortfamily != pk_opfamily)
3891 return NULL;
3892
3893
3894 if (commuted)
3895 {
3897
3898
3900
3901
3902 newclause->
opno = expr_op;
3905
3906 clause = (
Expr *) newclause;
3907 }
3908
3909 return clause;
3910}
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938void
3940{
3942 bool have_partial;
3943 bool is_target_rel;
3946
3947
3949
3950
3951
3952
3953
3954
3955 have_partial = false;
3957 {
3959
3962 have_partial = true;
3963 }
3964 if (!have_partial)
3965 return;
3966
3967
3968
3969
3970
3971
3972
3973
3975
3976
3978 {
3980
3981
3983 continue;
3984
3985 clauselist =
lappend(clauselist, rinfo);
3986 }
3987
3988
3989
3990
3991
3992
3993
3994
3995
3999 else
4002
4004 clauselist =
4008 otherrels),
4009 otherrels,
4010 rel,
4011 NULL));
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4027
4028
4029
4030
4031
4032
4033
4034
4036 {
4039
4041 continue;
4042
4045 false);
4046
4047
4048 if (is_target_rel)
4049 continue;
4050
4051
4052
4053
4054
4055
4056
4057
4058 if (!
index->amoptionalkey)
4059 continue;
4060
4061
4064 {
4066
4067
4070 index->indpred,
false))
4072 }
4073 }
4074}
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086static bool
4090{
4095
4096 Assert(indexcol < index->nkeycolumns);
4097
4098 curFamily =
index->opfamily[indexcol];
4099 curCollation =
index->indexcollations[indexcol];
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111 if (
index->relam == BTREE_AM_OID &&
4113 return false;
4114
4115
4117 return false;
4118
4120}
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142bool
4144 List *restrictlist,
List **extra_clauses)
4145{
4147
4148
4150 return false;
4151
4152
4153
4154
4155
4157 {
4159
4160
4161
4162
4163
4164
4165 if (restrictinfo->mergeopfamilies ==
NIL)
4166 continue;
4167
4168
4169
4170
4171
4173 {
4174
4175 restrictinfo->outer_is_left = true;
4176 }
4178 {
4179
4180 restrictinfo->outer_is_left = false;
4181 }
4182 else
4183 continue;
4184
4185
4186 restrictlist =
lappend(restrictlist, restrictinfo);
4187 }
4188
4189
4190 if (restrictlist ==
NIL)
4191 return false;
4192
4193
4195 {
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208 if (!
ind->unique || !
ind->immediate ||
ind->indpred !=
NIL)
4209 continue;
4210
4211
4212
4213
4214
4215 for (
c = 0;
c <
ind->nkeycolumns;
c++)
4216 {
4218
4219 foreach(lc, restrictlist)
4220 {
4223
4224
4225
4226
4227
4228
4229
4231 continue;
4232
4233
4234
4235
4236
4237
4238
4239
4240 if (rinfo->outer_is_left)
4242 else
4244
4246 {
4248 {
4251
4252
4253
4254
4255
4256
4259 if (extra_clauses)
4260 exprs =
lappend(exprs, rinfo);
4262 }
4263
4264 break;
4265 }
4266 }
4267
4268 if (lc == NULL)
4269 break;
4270 }
4271
4272
4273 if (
c ==
ind->nkeycolumns)
4274 {
4275 if (extra_clauses)
4276 *extra_clauses = exprs;
4277 return true;
4278 }
4279 }
4280
4281 return false;
4282}
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300bool
4303 int indexcol)
4304{
4306
4307
4309 return false;
4310
4311
4312 foreach(lc,
index->rel->baserestrictinfo)
4313 {
4315
4316
4317
4318
4319
4320
4321 if (rinfo->pseudoconstant)
4322 continue;
4323
4324
4326 return true;
4327 }
4328
4329 return false;
4330}
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351bool
4353 int indexcol,
4355{
4356 int indkey;
4357
4358
4359
4360
4361
4362
4363
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4377
4378 indkey =
index->indexkeys[indexcol];
4379 if (indkey != 0)
4380 {
4381
4382
4383
4384 if (operand &&
IsA(operand,
Var) &&
4385 index->rel->relid == ((
Var *) operand)->varno &&
4386 indkey == ((
Var *) operand)->varattno &&
4387 ((
Var *) operand)->varnullingrels == NULL)
4388 return true;
4389 }
4390 else
4391 {
4392
4393
4394
4395
4396
4400
4402 for (
i = 0;
i < indexcol;
i++)
4403 {
4404 if (
index->indexkeys[
i] == 0)
4405 {
4406 if (indexpr_item == NULL)
4407 elog(
ERROR,
"wrong number of index expressions");
4408 indexpr_item =
lnext(
index->indexprs, indexpr_item);
4409 }
4410 }
4411 if (indexpr_item == NULL)
4412 elog(
ERROR,
"wrong number of index expressions");
4414
4415
4416
4417
4420
4421 if (
equal(indexkey, operand))
4422 return true;
4423 }
4424
4425 return false;
4426}
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448bool
4450{
4451
4453 return false;
4455 return false;
4456 return true;
4457}
void create_partial_bitmap_paths(PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual)
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
int bms_next_member(const Bitmapset *a, int prevbit)
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_del_member(Bitmapset *a, int x)
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
void bms_free(Bitmapset *a)
bool bms_is_member(int x, const Bitmapset *a)
Bitmapset * bms_add_member(Bitmapset *a, int x)
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
BMS_Membership bms_membership(const Bitmapset *a)
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_copy(const Bitmapset *a)
#define Assert(condition)
#define MemSet(start, val, len)
#define OidIsValid(objectId)
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
bool contain_mutable_functions(Node *clause)
ScalarArrayOpExpr * make_SAOP_expr(Oid oper, Node *leftexpr, Oid coltype, Oid arraycollid, Oid inputcollid, List *exprs, bool haveNonConst)
bool contain_volatile_functions(Node *clause)
void cost_bitmap_tree_node(Path *path, Cost *cost, Selectivity *selec)
void cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *param_info, Path *bitmapqual, double loop_count)
bool equal(const void *a, const void *b)
void setup_eclass_member_iterator(EquivalenceMemberIterator *it, EquivalenceClass *ec, Relids child_relids)
List * generate_implied_equalities_for_column(PlannerInfo *root, RelOptInfo *rel, ec_matches_callback_type callback, void *callback_arg, Relids prohibited_rels)
EquivalenceMember * eclass_member_iterator_next(EquivalenceMemberIterator *it)
List * generate_join_implied_equalities(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
#define palloc_object(type)
#define palloc_array(type, count)
#define OidFunctionCall1(functionId, arg1)
static bool IsBooleanOpfamily(Oid opfamily)
static Path * choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)
static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths)
static void find_indexpath_quals(Path *bitmapqual, List **quals, List **preds)
static void get_join_index_paths(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths, Relids relids, List **considered_relids)
static int or_arg_index_match_cmp(const void *a, const void *b)
static void match_clause_to_index(PlannerInfo *root, RestrictInfo *rinfo, IndexOptInfo *index, IndexClauseSet *clauseset)
bool is_pseudo_constant_for_index(PlannerInfo *root, Node *expr, IndexOptInfo *index)
static bool eclass_already_used(EquivalenceClass *parent_ec, Relids oldrelids, List *indexjoinclauses)
static void match_join_clauses_to_index(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauseset, List **joinorclauses)
static IndexClause * match_saopclause_to_indexcol(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
static bool check_index_only(RelOptInfo *rel, IndexOptInfo *index)
static void match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index, IndexClauseSet *clauseset)
static PathClauseUsage * classify_index_clause_usage(Path *path, List **clauselist)
static void get_index_paths(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauses, List **bitindexpaths)
void check_index_predicates(PlannerInfo *root, RelOptInfo *rel)
static List * build_index_paths(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *clauses, bool useful_predicate, ScanTypeControl scantype, bool *skip_nonnative_saop)
static void match_pathkeys_to_index(IndexOptInfo *index, List *pathkeys, List **orderby_clauses_p, List **clause_columns_p)
static int find_list_position(Node *node, List **nodelist)
static void match_clauses_to_index(PlannerInfo *root, List *clauses, IndexOptInfo *index, IndexClauseSet *clauseset)
static double get_loop_count(PlannerInfo *root, Index cur_relid, Relids outer_relids)
static void consider_index_join_outer_rels(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths, List *indexjoinclauses, int considered_clauses, List **considered_relids)
void create_index_paths(PlannerInfo *root, RelOptInfo *rel)
static double adjust_rowcount_for_semijoins(PlannerInfo *root, Index cur_relid, Index outer_relid, double rowcount)
static IndexClause * match_clause_to_indexcol(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
static bool ec_member_matches_indexcol(PlannerInfo *root, RelOptInfo *rel, EquivalenceClass *ec, EquivalenceMember *em, void *arg)
static IndexClause * get_index_clause_from_support(PlannerInfo *root, RestrictInfo *rinfo, Oid funcid, int indexarg, int indexcol, IndexOptInfo *index)
#define IndexCollMatchesExprColl(idxcollation, exprcollation)
static IndexClause * match_orclause_to_indexcol(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
static IndexClause * match_opclause_to_indexcol(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
static Cost bitmap_scan_cost_est(PlannerInfo *root, RelOptInfo *rel, Path *ipath)
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
static IndexClause * match_boolean_index_clause(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
static void consider_index_join_clauses(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, IndexClauseSet *rclauseset, IndexClauseSet *jclauseset, IndexClauseSet *eclauseset, List **bitindexpaths)
static int or_arg_index_match_cmp_group(const void *a, const void *b)
static IndexClause * expand_indexqual_rowcompare(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index, Oid expr_op, bool var_on_left)
static void match_restriction_clauses_to_index(PlannerInfo *root, IndexOptInfo *index, IndexClauseSet *clauseset)
static IndexClause * match_rowcompare_to_indexcol(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
static List * build_paths_for_OR(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *other_clauses)
bool indexcol_is_bool_constant_for_query(PlannerInfo *root, IndexOptInfo *index, int indexcol)
static IndexClause * match_funcclause_to_indexcol(PlannerInfo *root, RestrictInfo *rinfo, int indexcol, IndexOptInfo *index)
static int path_usage_comparator(const void *a, const void *b)
static List * group_similar_or_args(PlannerInfo *root, RelOptInfo *rel, RestrictInfo *rinfo)
static double approximate_joinrel_size(PlannerInfo *root, Relids relids)
static Expr * match_clause_to_ordering_op(IndexOptInfo *index, int indexcol, Expr *clause, Oid pk_opfamily)
bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel, List *restrictlist, List **extra_clauses)
static List * generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *other_clauses)
static List * make_bitmap_paths_for_or_group(PlannerInfo *root, RelOptInfo *rel, RestrictInfo *ri, List *other_clauses)
List * lappend(List *list, void *datum)
List * list_delete(List *list, void *datum)
List * list_append_unique(List *list, void *datum)
List * list_concat(List *list1, const List *list2)
List * list_concat_copy(const List *list1, const List *list2)
List * list_copy(const List *oldlist)
List * lappend_int(List *list, int datum)
List * lappend_oid(List *list, Oid datum)
void list_free(List *list)
bool list_member_oid(const List *list, Oid datum)
List * list_truncate(List *list, int new_size)
bool list_member(const List *list, const void *datum)
List * list_copy_head(const List *oldlist, int len)
List * list_append_unique_ptr(List *list, void *datum)
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
Oid get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
RegProcedure get_func_support(Oid funcid)
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Oid get_array_type(Oid typid)
bool op_in_opfamily(Oid opno, Oid opfamily)
Oid get_commutator(Oid opno)
Expr * make_orclause(List *orclauses)
Node * makeBoolConst(bool value, bool isnull)
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
void pfree(void *pointer)
Oid exprType(const Node *expr)
void set_opfuncid(OpExpr *opexpr)
static bool is_andclause(const void *clause)
static Node * get_rightop(const void *clause)
static bool is_opclause(const void *clause)
static bool is_notclause(const void *clause)
static Expr * get_notclausearg(const void *notclause)
static Node * get_leftop(const void *clause)
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
List * truncate_useless_pathkeys(PlannerInfo *root, RelOptInfo *rel, List *pathkeys)
bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel)
List * build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index, ScanDirection scandir)
BitmapAndPath * create_bitmap_and_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals)
IndexPath * create_index_path(PlannerInfo *root, IndexOptInfo *index, List *indexclauses, List *indexorderbys, List *indexorderbycols, List *pathkeys, ScanDirection indexscandir, bool indexonly, Relids required_outer, double loop_count, bool partial_path)
void add_partial_path(RelOptInfo *parent_rel, Path *new_path)
BitmapOrPath * create_bitmap_or_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals)
BitmapHeapPath * create_bitmap_heap_path(PlannerInfo *root, RelOptInfo *rel, Path *bitmapqual, Relids required_outer, double loop_count, int parallel_degree)
void add_path(RelOptInfo *parent_rel, Path *new_path)
#define IS_SIMPLE_REL(rel)
#define PGS_CONSIDER_INDEXONLY
#define PATH_REQ_OUTER(path)
@ RELOPT_OTHER_MEMBER_REL
#define lfirst_node(type, lc)
static int list_length(const List *l)
static Oid list_nth_oid(const List *list, int n)
#define list_make1_oid(x1)
#define forthree(cell1, list1, cell2, list2, cell3, list3)
static void * list_nth(const List *list, int n)
static ListCell * list_head(const List *l)
static ListCell * lnext(const List *l, const ListCell *c)
#define list_make1_int(x1)
#define list_make2(x1, x2)
Node * strip_noop_phvs(Node *node)
#define qsort(a, b, c, d)
static Datum PointerGetDatum(const void *X)
static Pointer DatumGetPointer(Datum X)
bool predicate_implied_by(List *predicate_list, List *clause_list, bool weak)
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
bool restriction_is_or_clause(RestrictInfo *restrictinfo)
bool restriction_is_securely_promotable(RestrictInfo *restrictinfo, RelOptInfo *rel)
RestrictInfo * make_plain_restrictinfo(PlannerInfo *root, Expr *clause, Expr *orclause, bool is_pushed_down, bool has_clone, bool is_clone, bool pseudoconstant, Index security_level, Relids required_relids, Relids incompatible_relids, Relids outer_relids)
bool join_clause_is_movable_to(RestrictInfo *rinfo, RelOptInfo *baserel)
RestrictInfo * commute_restrictinfo(RestrictInfo *rinfo, Oid comm_op)
#define make_simple_restrictinfo(root, clause)
double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset, EstimationInfo *estinfo)
#define BTGreaterStrategyNumber
#define BTLessStrategyNumber
#define BTLessEqualStrategyNumber
#define BTGreaterEqualStrategyNumber
List * indexclauses[INDEX_MAX_KEYS]
struct RestrictInfo * rinfo
Selectivity indexselectivity
struct PathTarget * reltarget
Relids incompatible_relids
#define FirstLowInvalidHeapAttributeNumber
#define FirstNormalObjectId
bool contain_var_clause(Node *node)
Relids pull_varnos(PlannerInfo *root, Node *node)
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)