PostgreSQL Source Code: src/backend/optimizer/util/relnode.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
16
17#include <limits.h>
18
36
37
39{
43
47 List *pushed_down_joins,
48 bool can_null);
60 Relids both_input_relids,
61 List *new_restrictlist);
63 List *joininfo_list,
64 List *new_joininfo);
72 List *restrictlist);
77 bool strict_op);
84 int nappinfos,
86
87
88
89
90
91
92
93void
95{
96 int size;
99
100
102 root->simple_rel_array_size = size;
103
104
105
106
107
110
111
114 rti = 1;
115 foreach(lc, root->parse->rtable)
116 {
118
119 root->simple_rte_array[rti++] = rte;
120 }
121
122
123 if (root->append_rel_list == NIL)
124 {
125 root->append_rel_array = NULL;
126 return;
127 }
128
131
132
133
134
135
136
137
138 foreach(lc, root->append_rel_list)
139 {
142
143
144 Assert(child_relid < size);
145
146 if (root->append_rel_array[child_relid])
147 elog(ERROR, "child relation already exists");
148
149 root->append_rel_array[child_relid] = appinfo;
150 }
151}
152
153
154
155
156
157
158
159
160
161
162void
164{
165 int new_size;
166
168
169 new_size = root->simple_rel_array_size + add_size;
170
171 root->simple_rel_array =
173
174 root->simple_rte_array =
176
177 if (root->append_rel_array)
178 root->append_rel_array =
180 else
181 root->append_rel_array =
183
184 root->simple_rel_array_size = new_size;
185}
186
187
188
189
190
193{
196
197
198 Assert(relid > 0 && relid < root->simple_rel_array_size);
199 if (root->simple_rel_array[relid] != NULL)
200 elog(ERROR, "rel %d already exists", relid);
201
202
203 rte = root->simple_rte_array[relid];
205
209 rel->rows = 0;
210
222 rel->relid = relid;
224
239 {
240 Assert(parent == NULL ||
243
244
245
246
247
248
249
250
251
252
256 {
258
261 }
262 else
264 }
265 else
268 rel->fdwroutine = NULL;
269 rel->fdw_private = NULL;
279 rel->part_scheme = NULL;
281 rel->boundinfo = NULL;
284 rel->part_rels = NULL;
287 rel->partexprs = NULL;
288 rel->nullable_partexprs = NULL;
289
290
291
292
293 if (parent)
294 {
295
296 rel->parent = parent;
297 rel->top_parent = parent->top_parent ? parent->top_parent : parent;
299
300
301
302
303
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
323 }
324 else
325 {
326 rel->parent = NULL;
327 rel->top_parent = NULL;
333 }
334
335
337 {
339
341 break;
348
349
350
351
352
353
354
357 rel->attr_needed = (Relids *)
359 rel->attr_widths = (int32 *)
361 break;
363
366 rel->attr_needed = NULL;
367 rel->attr_widths = NULL;
368 break;
369 default:
370 elog(ERROR, "unrecognized RTE kind: %d",
372 break;
373 }
374
375
376
377
378
379
380 root->simple_rel_array[relid] = rel;
381
382
383
384
385
386
387
388
389
390
391 if (parent)
392 {
394
395 Assert(appinfo != NULL);
397 {
398
399
400
401
403 }
404 }
405
406 return rel;
407}
408
409
410
411
412
415{
417
418
420 {
421 rel = root->simple_rel_array[relid];
422 if (rel)
423 return rel;
424 }
425
426 elog(ERROR, "no relation entry for relid %d", relid);
427
428 return NULL;
429}
430
431
432
433
434
437{
438
440 return root->simple_rel_array[relid];
441 return NULL;
442}
443
444
445
446
447
448
449
450
451
452
455{
456
458 {
461
462 rel = root->simple_rel_array[relid];
463 if (rel)
464 return rel;
465
466
467
468
469
470
471 rte = root->simple_rte_array[relid];
473 return NULL;
474 }
475
476 elog(ERROR, "no relation entry for relid %d", relid);
477
478 return NULL;
479}
480
481
482
483
484
485static void
487{
488 HTAB *hashtab;
491
492
498 hashtab = hash_create("JoinRelHashTable",
499 256L,
500 &hash_ctl,
502
503
504 foreach(l, root->join_rel_list)
505 {
508 bool found;
509
513 &found);
516 }
517
518 root->join_rel_hash = hashtab;
519}
520
521
522
523
524
525
528{
529
530
531
532
535
536
537
538
539
540
541
542
543
544 if (root->join_rel_hash)
545 {
546 Relids hashkey = relids;
548
550 &hashkey,
552 NULL);
553 if (hentry)
555 }
556 else
557 {
559
560 foreach(l, root->join_rel_list)
561 {
563
565 return rel;
566 }
567 }
568
569 return NULL;
570}
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588static void
591{
594 {
596 {
600 joinrel->fdwroutine = outer_rel->fdwroutine;
601 }
604 {
608 joinrel->fdwroutine = outer_rel->fdwroutine;
609 }
612 {
616 joinrel->fdwroutine = outer_rel->fdwroutine;
617 }
618 }
619}
620
621
622
623
624
625
626static void
628{
629
630 root->join_rel_list = lappend(root->join_rel_list, joinrel);
631
632
633 if (root->join_rel_hash)
634 {
636 bool found;
637
641 &found);
644 }
645}
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
670 List *pushed_down_joins,
671 List **restrictlist_ptr)
672{
674 List *restrictlist;
675
676
678
679
680
681
683
684 if (joinrel)
685 {
686
687
688
689
690 if (restrictlist_ptr)
692 joinrel,
693 outer_rel,
694 inner_rel,
695 sjinfo);
696 return joinrel;
697 }
698
699
700
701
705 joinrel->rows = 0;
706
718
723 outer_rel, inner_rel);
724 joinrel->relid = 0;
728 joinrel->attr_needed = NULL;
729 joinrel->attr_widths = NULL;
736 joinrel->pages = 0;
747 joinrel->fdwroutine = NULL;
748 joinrel->fdw_private = NULL;
758 joinrel->parent = NULL;
759 joinrel->top_parent = NULL;
761 joinrel->part_scheme = NULL;
762 joinrel->nparts = -1;
763 joinrel->boundinfo = NULL;
766 joinrel->part_rels = NULL;
769 joinrel->partexprs = NULL;
770 joinrel->nullable_partexprs = NULL;
771
772
774
775
776
777
778
779
780
781
782
783
789
790
791
792
793
794
795
796
799
800
801
802
803
804
806 outer_rel, inner_rel,
807 sjinfo);
808 if (restrictlist_ptr)
809 *restrictlist_ptr = restrictlist;
811
812
813
814
815
817
818
820 restrictlist);
821
822
823
824
826 sjinfo, restrictlist);
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
846
847
849
850
851
852
853
854
855
856 if (root->join_rel_level)
857 {
860 root->join_rel_level[root->join_cur_level] =
861 lappend(root->join_rel_level[root->join_cur_level], joinrel);
862 }
863
864 return joinrel;
865}
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
886{
888
889
891
892
894
897 nappinfos, appinfos);
898 joinrel->rows = 0;
899
913 joinrel->relid = 0;
917 joinrel->attr_needed = NULL;
918 joinrel->attr_widths = NULL;
924 joinrel->pages = 0;
934 joinrel->fdwroutine = NULL;
935 joinrel->fdw_private = NULL;
942 joinrel->parent = parent_joinrel;
943 joinrel->top_parent = parent_joinrel->top_parent ? parent_joinrel->top_parent : parent_joinrel;
945 joinrel->part_scheme = NULL;
946 joinrel->nparts = -1;
947 joinrel->boundinfo = NULL;
950 joinrel->part_rels = NULL;
953 joinrel->partexprs = NULL;
954 joinrel->nullable_partexprs = NULL;
955
956
958
959
961 nappinfos, appinfos);
962
963
966 nappinfos,
967 appinfos);
968
969
970
971
972
975
976
977
978
979
981
982
984 restrictlist);
985
986
988
989
991 sjinfo, restrictlist);
992
993
995
996
998
999
1000
1001
1002
1003
1004
1007 nappinfos, appinfos,
1008 parent_joinrel, joinrel);
1009
1010 return joinrel;
1011}
1012
1013
1014
1015
1016
1017
1018
1019
1020
1026{
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1044 return result;
1045}
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
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
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099static void
1103 List *pushed_down_joins,
1104 bool can_null)
1105{
1110
1112 {
1114
1115
1116
1117
1119 {
1122
1123
1125 {
1126
1127
1128
1129
1130
1131 if (can_null)
1132 {
1134
1135 if (sjinfo->ojrelid != 0 &&
1142 foreach(lc, pushed_down_joins)
1143 {
1145
1150 }
1154 relids));
1155 }
1156
1158 phv);
1159
1160 tuple_width += phinfo->ph_width;
1161 }
1162 continue;
1163 }
1164
1165
1166
1167
1168
1169
1171 elog(ERROR, "unexpected node type in rel targetlist: %d",
1173
1175 {
1176
1179
1180
1182 }
1183 else
1184 {
1186 int ndx;
1187
1188
1190
1191
1194 continue;
1195
1196
1197 tuple_width += baserel->attr_widths[ndx];
1198 }
1199
1200
1201
1202
1203
1204
1205
1207 {
1209
1210 if (sjinfo->ojrelid != 0 &&
1215 var->varnullingrels = bms_add_member(var->varnullingrels,
1217 foreach(lc, pushed_down_joins)
1218 {
1220
1223 var->varnullingrels = bms_add_member(var->varnullingrels,
1225 }
1226 var->varnullingrels =
1227 bms_join(var->varnullingrels,
1229 relids));
1230 }
1231
1233 var);
1234
1235
1236 }
1237
1239}
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284static List *
1290{
1291 List *result;
1292 Relids both_input_relids;
1293
1295
1296
1297
1298
1299
1300
1302 both_input_relids, NIL);
1304 both_input_relids, result);
1305
1306
1307
1308
1309
1310
1315 inner_rel,
1316 sjinfo));
1317
1318 return result;
1319}
1320
1321static void
1325{
1326 List *result;
1327
1328
1329
1330
1331
1332
1335
1337}
1338
1339static List *
1343 Relids both_input_relids,
1344 List *new_restrictlist)
1345{
1347
1348 foreach(l, input_rel->joininfo)
1349 {
1351
1353 {
1354
1355
1356
1357
1358
1359
1360
1361
1362
1364 {
1367 continue;
1369 continue;
1370 }
1371 else
1372 {
1373
1374
1375
1376
1377
1378
1379
1382 both_input_relids));
1383 }
1384
1385
1386
1387
1388
1389
1390
1392 }
1393 else
1394 {
1395
1396
1397
1398
1399 }
1400 }
1401
1402 return new_restrictlist;
1403}
1404
1405static List *
1407 List *joininfo_list,
1408 List *new_joininfo)
1409{
1411
1412
1414
1415 foreach(l, joininfo_list)
1416 {
1418
1420 {
1421
1422
1423
1424
1425
1426 }
1427 else
1428 {
1429
1430
1431
1432
1433
1434
1435
1437 }
1438 }
1439
1440 return new_joininfo;
1441}
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1459{
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471 foreach(lc, root->upper_rels[kind])
1472 {
1474
1476 return upperrel;
1477 }
1478
1482
1483
1486 upperrel->consider_parallel = false;
1493
1494 root->upper_rels[kind] = lappend(root->upper_rels[kind], upperrel);
1495
1496 return upperrel;
1497}
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1510{
1511 Relids result = NULL;
1512
1515
1516 do
1517 {
1520
1522
1523
1526
1528
1529 return result;
1530}
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1546 Relids required_outer)
1547{
1550 List *pclauses;
1551 List *eqclauses;
1553 double rows;
1555
1556
1558
1559
1561 return NULL;
1562
1564
1565
1567 return ppi;
1568
1569
1570
1571
1572
1573 joinrelids = bms_union(baserel->relids, required_outer);
1574 pclauses = NIL;
1575 foreach(lc, baserel->joininfo)
1576 {
1578
1581 joinrelids))
1582 pclauses = lappend(pclauses, rinfo);
1583 }
1584
1585
1586
1587
1588
1589
1591 joinrelids,
1592 required_outer,
1593 baserel,
1594 NULL);
1595#ifdef USE_ASSERT_CHECKING
1596 foreach(lc, eqclauses)
1597 {
1599
1602 joinrelids));
1603 }
1604#endif
1605 pclauses = list_concat(pclauses, eqclauses);
1606
1607
1608 pserials = NULL;
1609 foreach(lc, pclauses)
1610 {
1612
1614 }
1615
1616
1618
1619
1626
1627 return ppi;
1628}
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1660 Path *outer_path,
1661 Path *inner_path,
1663 Relids required_outer,
1664 List **restrict_clauses)
1665{
1667 Relids join_and_req;
1668 Relids outer_and_req;
1669 Relids inner_and_req;
1670 List *pclauses;
1671 List *eclauses;
1672 List *dropped_ecs;
1673 double rows;
1675
1676
1678
1679
1681 return NULL;
1682
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694 join_and_req = bms_union(joinrel->relids, required_outer);
1695 if (outer_path->param_info)
1696 outer_and_req = bms_union(outer_path->parent->relids,
1698 else
1699 outer_and_req = NULL;
1700 if (inner_path->param_info)
1701 inner_and_req = bms_union(inner_path->parent->relids,
1703 else
1704 inner_and_req = NULL;
1705
1706 pclauses = NIL;
1707 foreach(lc, joinrel->joininfo)
1708 {
1710
1713 join_and_req) &&
1715 outer_path->parent->relids,
1716 outer_and_req) &&
1718 inner_path->parent->relids,
1719 inner_and_req))
1720 pclauses = lappend(pclauses, rinfo);
1721 }
1722
1723
1725 join_and_req,
1726 required_outer,
1727 joinrel,
1728 NULL);
1729
1730 dropped_ecs = NIL;
1731 foreach(lc, eclauses)
1732 {
1734
1737 join_and_req));
1739 outer_path->parent->relids,
1740 outer_and_req))
1741 continue;
1743 inner_path->parent->relids,
1744 inner_and_req))
1745 {
1746
1747 Assert(rinfo->left_ec == rinfo->right_ec);
1748 dropped_ecs = lappend(dropped_ecs, rinfo->left_ec);
1749 continue;
1750 }
1751 pclauses = lappend(pclauses, rinfo);
1752 }
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784 if (dropped_ecs)
1785 {
1786 Relids real_outer_and_req;
1787
1788 real_outer_and_req = bms_union(outer_path->parent->relids,
1789 required_outer);
1790 eclauses =
1792 dropped_ecs,
1793 real_outer_and_req,
1794 required_outer,
1795 outer_path->parent);
1796 foreach(lc, eclauses)
1797 {
1799
1801 outer_path->parent->relids,
1802 real_outer_and_req));
1804 outer_path->parent->relids,
1805 outer_and_req))
1806 pclauses = lappend(pclauses, rinfo);
1807 }
1808 }
1809
1810
1811
1812
1813
1814
1815 *restrict_clauses = list_concat(pclauses, *restrict_clauses);
1816
1817
1819 return ppi;
1820
1821
1823 outer_path,
1824 inner_path,
1825 sjinfo,
1826 *restrict_clauses);
1827
1828
1829
1830
1831
1832
1833
1834
1841
1842 return ppi;
1843}
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1857{
1859
1860
1862
1863
1865 return NULL;
1866
1868
1869
1871 return ppi;
1872
1873
1880
1881 return ppi;
1882}
1883
1884
1885
1886
1887
1890{
1892
1893 foreach(lc, rel->ppilist)
1894 {
1896
1898 return ppi;
1899 }
1900
1901 return NULL;
1902}
1903
1904
1905
1906
1907
1908
1911{
1912 if (path->param_info == NULL)
1913 return NULL;
1914
1915
1916
1917
1918
1920
1924 {
1925
1926
1927
1928
1929
1930
1931
1932
1936
1937 pserials = NULL;
1943 {
1945
1947 }
1948 return pserials;
1949 }
1951 {
1952
1953
1954
1955
1959
1960 pserials = NULL;
1961 foreach(lc, apath->subpaths)
1962 {
1965
1968 pserials = bms_copy(subserials);
1969 else
1971 }
1972 return pserials;
1973 }
1974 else
1975 {
1976
1977
1978
1979
1980 return path->param_info->ppi_serials;
1981 }
1982}
1983
1984
1985
1986
1987
1988
1989
1990static void
1994 List *restrictlist)
1995{
1997
1998
2000 {
2002 return;
2003 }
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016 if (outer_rel->part_scheme == NULL || inner_rel->part_scheme == NULL ||
2019 outer_rel->part_scheme != inner_rel->part_scheme ||
2021 sjinfo->jointype, restrictlist))
2022 {
2024 return;
2025 }
2026
2027 part_scheme = outer_rel->part_scheme;
2028
2029
2030
2031
2032
2033 Assert(!joinrel->part_scheme && !joinrel->partexprs &&
2034 !joinrel->nullable_partexprs && !joinrel->part_rels &&
2035 !joinrel->boundinfo);
2036
2037
2038
2039
2040
2041
2042
2043
2044 joinrel->part_scheme = part_scheme;
2047
2048
2049
2050
2054}
2055
2056
2057
2058
2059
2060
2061
2062
2063static bool
2067{
2070 int num_equal_pks;
2072
2073
2074
2075
2076
2077 Assert(rel1->part_scheme == rel2->part_scheme);
2078 Assert(part_scheme);
2079
2080
2081 memset(pk_known_equal, 0, sizeof(pk_known_equal));
2082
2083 num_equal_pks = 0;
2084
2085
2086 foreach(lc, restrictlist)
2087 {
2090 Expr *expr1;
2091 Expr *expr2;
2092 bool strict_op;
2093 int ipk1;
2094 int ipk2;
2095
2096
2099 continue;
2100
2101
2102 if (!rinfo->can_join)
2103 continue;
2104
2105
2106 if (!rinfo->mergeopfamilies && (rinfo->hashjoinoperator))
2107 continue;
2108
2109
2111
2112
2115 {
2118 }
2121 {
2124 }
2125 else
2126 continue;
2127
2128
2129
2130
2131
2133
2134
2135
2136
2137
2138
2139
2140 if (strict_op)
2141 {
2144 root->outer_join_rels,
2145 NULL);
2148 root->outer_join_rels,
2149 NULL);
2150 }
2151
2152
2153
2154
2155
2157 if (ipk1 < 0)
2158 continue;
2160 if (ipk2 < 0)
2161 continue;
2162
2163
2164
2165
2166
2167 if (ipk1 != ipk2)
2168 continue;
2169
2170
2171 if (pk_known_equal[ipk1])
2172 continue;
2173
2174
2175 if (rel1->part_scheme->partcollation[ipk1] != opexpr->inputcollid)
2176 return false;
2177
2178
2179
2180
2181
2183 {
2184 if ((rinfo->hashjoinoperator) ||
2187 continue;
2188 }
2191 continue;
2192
2193
2194 pk_known_equal[ipk1] = true;
2195
2196
2197 if (++num_equal_pks == part_scheme->partnatts)
2198 return true;
2199 }
2200
2201
2202
2203
2204
2205
2206
2207
2208 for (int ipk = 0; ipk < part_scheme->partnatts; ipk++)
2209 {
2210 Oid btree_opfamily;
2211
2212
2213 if (pk_known_equal[ipk])
2214 continue;
2215
2216
2217
2218
2219
2220
2221
2222
2224 {
2225 Oid eq_op;
2226 List *eq_opfamilies;
2227
2233 break;
2235 if (eq_opfamilies == NIL)
2236 break;
2237 btree_opfamily = linitial_oid(eq_opfamilies);
2238 }
2239 else
2240 btree_opfamily = part_scheme->partopfamily[ipk];
2241
2242
2243
2244
2245
2246
2247 foreach(lc, rel1->partexprs[ipk])
2248 {
2251 Oid partcoll1 = rel1->part_scheme->partcollation[ipk];
2253
2254 foreach(lc2, rel2->partexprs[ipk])
2255 {
2257
2259 {
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269 if (partcoll1 == exprcoll1)
2270 {
2272 rel2->part_scheme->partcollation[ipk];
2275
2276 Assert(partcoll2 == exprcoll2);
2277 pk_known_equal[ipk] = true;
2278 break;
2279 }
2280 }
2281 }
2282 if (pk_known_equal[ipk])
2283 break;
2284 }
2285
2286 if (pk_known_equal[ipk])
2287 {
2288
2289 if (++num_equal_pks == part_scheme->partnatts)
2290 return true;
2291 }
2292 else
2293 break;
2294 }
2295
2296 return false;
2297}
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310static int
2312{
2313 int cnt;
2314
2315
2316 Assert(rel->part_scheme);
2317 Assert(rel->partexprs);
2318 Assert(rel->nullable_partexprs);
2319
2320
2323
2324 for (cnt = 0; cnt < rel->part_scheme->partnatts; cnt++)
2325 {
2327
2328
2329 foreach(lc, rel->partexprs[cnt])
2330 {
2332 return cnt;
2333 }
2334
2335 if (!strict_op)
2336 continue;
2337
2338
2339
2340
2341
2342
2343
2344
2345 foreach(lc, rel->nullable_partexprs[cnt])
2346 {
2348 return cnt;
2349 }
2350 }
2351
2352 return -1;
2353}
2354
2355
2356
2357
2358
2359static void
2363{
2365 int partnatts = part_scheme->partnatts;
2366
2367 joinrel->partexprs = (List **) palloc0(sizeof(List *) * partnatts);
2368 joinrel->nullable_partexprs =
2370
2371
2372
2373
2374
2375
2376
2377 for (int cnt = 0; cnt < partnatts; cnt++)
2378 {
2379
2380 const List *outer_expr = outer_rel->partexprs[cnt];
2381 const List *outer_null_expr = outer_rel->nullable_partexprs[cnt];
2382 const List *inner_expr = inner_rel->partexprs[cnt];
2383 const List *inner_null_expr = inner_rel->nullable_partexprs[cnt];
2385 List *nullable_partexpr = NIL;
2387
2388 switch (jointype)
2389 {
2390
2391
2392
2393
2394
2395
2396
2397
2398
2402 inner_null_expr);
2403 break;
2404
2405
2406
2407
2408
2409
2410
2411
2414 partexpr = list_copy(outer_expr);
2415 nullable_partexpr = list_copy(outer_null_expr);
2416 break;
2417
2418
2419
2420
2421
2422
2423
2424
2426 partexpr = list_copy(outer_expr);
2428 outer_null_expr);
2429 nullable_partexpr = list_concat(nullable_partexpr,
2430 inner_null_expr);
2431 break;
2432
2433
2434
2435
2436
2437
2438
2441 inner_expr);
2442 nullable_partexpr = list_concat(nullable_partexpr,
2443 outer_null_expr);
2444 nullable_partexpr = list_concat(nullable_partexpr,
2445 inner_null_expr);
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2472 {
2475
2477 {
2480
2481 c->coalescetype = exprType(larg);
2484 c->location = -1;
2485 nullable_partexpr = lappend(nullable_partexpr, c);
2486 }
2487 }
2488 break;
2489
2490 default:
2491 elog(ERROR, "unrecognized join type: %d", (int) jointype);
2492 }
2493
2494 joinrel->partexprs[cnt] = partexpr;
2495 joinrel->nullable_partexprs[cnt] = nullable_partexpr;
2496 }
2497}
2498
2499
2500
2501
2502
2503static void
2507 int nappinfos,
2509{
2510
2514 nappinfos, appinfos);
2515
2516
2520}
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Bitmapset * bms_make_singleton(int x)
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
uint32 bitmap_hash(const void *key, Size keysize)
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
int bms_num_members(const 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)
int bitmap_match(const void *key1, const void *key2, Size keysize)
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_copy(const Bitmapset *a)
#define PG_USED_FOR_ASSERTS_ONLY
#define OidIsValid(objectId)
bool is_parallel_safe(PlannerInfo *root, Node *node)
double get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, List *param_clauses)
double get_parameterized_joinrel_size(PlannerInfo *root, RelOptInfo *rel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, List *restrict_clauses)
void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *restrictlist)
bool enable_partitionwise_join
int32 clamp_width_est(int64 tuple_width)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
bool equal(const void *a, const void *b)
bool exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2, Oid opfamily)
List * generate_join_implied_equalities_for_ecs(PlannerInfo *root, List *eclasses, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel)
void add_child_join_rel_equivalences(PlannerInfo *root, int nappinfos, AppendRelInfo **appinfos, RelOptInfo *parent_joinrel, RelOptInfo *child_joinrel)
List * generate_join_implied_equalities(PlannerInfo *root, Relids join_relids, Relids outer_relids, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
bool has_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1)
#define palloc0_array(type, count)
Assert(PointerIsAligned(start, uint64))
bool apply_child_basequals(PlannerInfo *root, RelOptInfo *parentrel, RelOptInfo *childrel, RangeTblEntry *childRTE, AppendRelInfo *appinfo)
void mark_dummy_rel(RelOptInfo *rel)
List * lappend(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)
bool list_member_oid(const List *list, Oid datum)
List * list_append_unique_ptr(List *list, void *datum)
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
List * get_mergejoin_opfamilies(Oid opno)
bool op_in_opfamily(Oid opno, Oid opfamily)
Datum subpath(PG_FUNCTION_ARGS)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
Oid exprType(const Node *expr)
Oid exprCollation(const Node *expr)
#define IsA(nodeptr, _type_)
#define IS_OUTER_JOIN(jointype)
#define castNode(_type_, nodeptr)
#define repalloc0_array(pointer, type, oldcount, count)
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ PARTITION_STRATEGY_HASH
bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel)
#define RINFO_IS_PUSHED_DOWN(rinfo, joinrelids)
#define IS_PARTITIONED_REL(rel)
#define PATH_REQ_OUTER(path)
@ RELOPT_OTHER_MEMBER_REL
#define IS_OTHER_REL(rel)
#define PARTITION_MAX_KEYS
#define lfirst_node(type, lc)
static int list_length(const List *l)
static void * list_nth(const List *list, int n)
static ListCell * list_head(const List *l)
#define list_make2(x1, x2)
PlaceHolderInfo * find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
void add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
void get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel)
static void build_joinrel_partition_info(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *restrictlist)
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
void setup_simple_rel_arrays(PlannerInfo *root)
static void set_joinrel_partition_key_exprs(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinType jointype)
ParamPathInfo * get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel, SpecialJoinInfo *sjinfo, List *pushed_down_joins, bool can_null)
RelOptInfo * build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel, RelOptInfo *parent_joinrel, List *restrictlist, SpecialJoinInfo *sjinfo, int nappinfos, AppendRelInfo **appinfos)
static bool have_partkey_equi_join(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *rel1, RelOptInfo *rel2, JoinType jointype, List *restrictlist)
RelOptInfo * find_base_rel_noerr(PlannerInfo *root, int relid)
Relids min_join_parameterization(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
RelOptInfo * find_join_rel(PlannerInfo *root, Relids relids)
static void build_join_rel_hash(PlannerInfo *root)
ParamPathInfo * get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel, Path *outer_path, Path *inner_path, SpecialJoinInfo *sjinfo, Relids required_outer, List **restrict_clauses)
Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
void expand_planner_arrays(PlannerInfo *root, int add_size)
ParamPathInfo * get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, Relids required_outer)
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
RelOptInfo * build_join_rel(PlannerInfo *root, Relids joinrelids, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo, List *pushed_down_joins, List **restrictlist_ptr)
static void build_child_join_reltarget(PlannerInfo *root, RelOptInfo *parentrel, RelOptInfo *childrel, int nappinfos, AppendRelInfo **appinfos)
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
static List * build_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, SpecialJoinInfo *sjinfo)
static int match_expr_to_partition_keys(Expr *expr, RelOptInfo *rel, bool strict_op)
ParamPathInfo * find_param_path_info(RelOptInfo *rel, Relids required_outer)
static void set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
struct JoinHashEntry JoinHashEntry
static void build_joinrel_joinlist(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
Bitmapset * get_param_path_clause_serials(Path *path)
static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel)
RelOptInfo * find_base_rel_ignore_join(PlannerInfo *root, int relid)
static List * subbuild_joinrel_joinlist(RelOptInfo *joinrel, List *joininfo_list, List *new_joininfo)
static List * subbuild_joinrel_restrictlist(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *input_rel, Relids both_input_relids, List *new_restrictlist)
bool join_clause_is_movable_into(RestrictInfo *rinfo, Relids currentrelids, Relids current_and_outer)
Node * remove_nulling_relids(Node *node, const Bitmapset *removable_relids, const Bitmapset *except_relids)
Size add_size(Size s1, Size s2)
#define HTEqualStrategyNumber
bool consider_param_startup
Bitmapset * notnullattnums
struct PathTarget * reltarget
List * cheapest_parameterized_paths
struct Path * cheapest_unique_path
Relids lateral_referencers
struct Path * cheapest_startup_path
QualCost baserestrictcost
struct Path * cheapest_total_path
List * non_unique_for_rels
Bitmapset * eclass_indexes
Relids direct_lateral_relids
bool consider_partitionwise_join
Index baserestrict_min_security
Relids incompatible_relids
PathTarget * create_empty_pathtarget(void)