86 : ((
value) && (match)))
87
88
89
90
91
92
93
94
95
96
97#define RESULT_IS_FINAL(value, is_or) ((is_or) ? (value) : (!(value)))
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144static double
146{
147 double n = samplerows;
151
153 denom = N - n + 0.04 * n * (N - 1);
154
155
157 return 0.0;
158
160}
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
178{
181 numrows,
189
190
192
193
196
199
200
202 numrows =
data->numrows;
203
204
206
207
208
209
210
211
212
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
235
236
237
238
239
240
242 {
244 {
246 break;
247 }
248 }
249
250
251
252
253
254
256 {
260
261
264
265
268
269
272
273
274
275
278
283
284
287
288
290 {
291
293
296
297
300
301
303
304
306
307
310 {
312
313
316
317
320
324
326 }
327 }
328
331 }
332
335
337}
338
339
340
341
342
345{
348
349
351
352
354 {
357
360 elog(
ERROR,
"cache lookup failed for ordering operator for type %u",
362
364 }
365
367}
368
369
370
371
372
373
374
375static int
377{
379 int ndistinct;
380
381 ndistinct = 1;
382 for (
i = 1;
i < numrows;
i++)
383 {
384
386
388 ndistinct += 1;
389 }
390
391 return ndistinct;
392}
393
394
395
396
397
398
399static int
401{
404
405 if (
ia->count ==
ib->count)
406 return 0;
407 else if (
ia->count >
ib->count)
408 return -1;
409
410 return 1;
411}
412
413
414
415
416
417
418
419
422 int *ndistinct)
423{
427
429
433
434 for (
i = 1;
i < numrows;
i++)
435 {
436
438
439
441 {
444 }
445
447 }
448
449
451
452
455
458}
459
460
461static int
463{
467
469 ib->values[0],
ib->isnull[0],
470 ssup);
471}
472
473
474
475
476
477
478
479
480
481
482
483
484
485
489{
491 dim;
493 char *ptr;
494
497
498
501
502
505
506 for (dim = 0; dim <
mss->ndims; dim++)
507 {
509
510
513
514
516 {
517
521 }
522
523
526
527
528
529
530
531
534 {
536 {
538 continue;
539 }
540
541 result[dim][
ncounts[dim]] = result[dim][
i];
542
544 }
545 }
546
547 return result;
548}
549
550
551
552
553
556{
558 bool isnull;
562
564 elog(
ERROR,
"cache lookup failed for statistics object %u",
mvoid);
565
568
569 if (isnull)
571 "requested statistics kind \"%c\" is not yet built for statistics object %u",
573
575
577
578 return result;
579}
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
619{
621 int dim;
622 int ndims =
mcvlist->ndimensions;
623
626
628
629
631 char *ptr;
633
634
637
638
639
640
641
642
643
644
645
647
648
650
651
652 for (dim = 0; dim < ndims; dim++)
653 {
654 int ndistinct;
656
657
658
659
660
662
663
666
667
669
671 {
672
674 continue;
675
676
678 counts[dim] += 1;
679 }
680
681
682 if (counts[dim] == 0)
683 continue;
684
685
689
691
694
695
696
697
698
699
700
701 ndistinct = 1;
702 for (
i = 1;
i < counts[dim];
i++)
703 {
704
706
707
709 continue;
710
712 ndistinct += 1;
713 }
714
715
717
718
719
720
721
722
723
725
726 if (info[dim].typbyval)
727 {
729
730
731
732
733
735 }
736 else if (info[dim].typlen > 0)
737 {
738
739
740
741
742
743
744
745
746
749 }
750 else if (info[dim].typlen == -1)
751 {
755 {
757
758
759
760
761
762
763
765
766
770
771
772
773
774
776 }
777 }
778 else if (info[dim].typlen == -2)
779 {
783 {
785
786
787
788
789
790
791
792
793
797
798
800 }
801 }
802
803
804 Assert(info[dim].nbytes > 0);
805 }
806
807
808
809
810
811
814 + (ndims *
sizeof(
Oid));
815
816
818
819
820 for (
i = 0;
i < ndims;
i++)
822
823
824
825
826
828
829
830
831
832
835
838
839
842
845
848
851
853 ptr += (
sizeof(
Oid) * ndims);
854
855
858
859
860 for (dim = 0; dim < ndims; dim++)
861 {
862
864
866 {
868
869 if (info[dim].typbyval)
870 {
872
873
874
875
876
877
878
879
880
881
883
884 memcpy(ptr, &tmp, info[dim].typlen);
886 }
887 else if (info[dim].typlen > 0)
888 {
889
892 }
893 else if (info[dim].typlen == -1)
894 {
896
897
900
901
904 }
905 else if (info[dim].typlen == -2)
906 {
908
909
912
913
916 }
917
918
920 }
921
922
924 }
925
926
928 {
930
931
933
934
936 ptr +=
sizeof(
bool) * ndims;
937
940
943
944
945 for (dim = 0; dim < ndims; dim++)
946 {
949
950
952 {
954 info[dim].nvalues,
sizeof(
Datum),
956
958
959
960
962
963
965 }
966
967
970 }
971
972
974 }
975
976
978
981
983}
984
985
986
987
988
989
990
991
994{
995 int dim,
1000 char *ptr;
1002
1003 int ndims,
1006
1007
1009
1010
1012
1013
1015 char *dataptr;
1017 char *isnullptr;
1018
1021
1022
1023
1024
1025
1026
1028 elog(
ERROR,
"invalid MCV size %zu (expected at least %zu)",
1030
1031
1033
1034
1038
1039
1042
1045
1048
1051
1053 elog(
ERROR,
"invalid MCV magic %u (expected %u)",
1055
1057 elog(
ERROR,
"invalid MCV type %u (expected %u)",
1059
1060 if (
mcvlist->ndimensions == 0)
1061 elog(
ERROR,
"invalid zero-length dimension array in MCVList");
1064 elog(
ERROR,
"invalid length (%d) dimension array in MCVList",
1066
1068 elog(
ERROR,
"invalid zero-length item array in MCVList");
1070 elog(
ERROR,
"invalid length (%u) item array in MCVList",
1072
1075
1076
1077
1078
1079
1080
1082
1083
1084
1085
1086
1087
1089 elog(
ERROR,
"invalid MCV size %zu (expected %zu)",
1091
1092
1094 ptr += (
sizeof(
Oid) * ndims);
1095
1096
1098
1101
1102
1103 for (dim = 0; dim < ndims; dim++)
1104 {
1105
1106
1107
1108
1109 Assert(info[dim].nvalues >= 0);
1110 Assert(info[dim].nbytes >= 0);
1111
1113 }
1114
1115
1116
1117
1118
1119
1121 elog(
ERROR,
"invalid MCV size %zu (expected %zu)",
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133 datalen = 0;
1135
1136 for (dim = 0; dim < ndims; dim++)
1137 {
1139
1140
1142 }
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1155
1156
1159
1160
1162
1163
1165
1166
1169
1171
1173
1174
1175
1176
1177
1178 for (dim = 0; dim < ndims; dim++)
1179 {
1180
1182
1183 if (info[dim].typbyval)
1184 {
1185
1187 {
1189
1190 memcpy(&v, ptr, info[dim].typlen);
1192
1193 map[dim][
i] =
fetch_att(&v,
true, info[dim].typlen);
1194
1195
1197 }
1198 }
1199 else
1200 {
1201
1202
1203
1204 if (info[dim].typlen > 0)
1205 {
1207 {
1208 memcpy(dataptr, ptr, info[dim].typlen);
1210
1211
1213 dataptr +=
MAXALIGN(info[dim].typlen);
1214 }
1215 }
1216 else if (info[dim].typlen == -1)
1217 {
1218
1220 {
1222
1223
1226
1227
1231
1232
1234
1235
1237 }
1238 }
1239 else if (info[dim].typlen == -2)
1240 {
1241
1243 {
1245
1248
1251
1252
1255 }
1256 }
1257
1258
1260
1261
1263 }
1264
1265
1267 }
1268
1269
1271
1272
1274 {
1276
1279
1280 item->
isnull = (
bool *) isnullptr;
1281 isnullptr +=
MAXALIGN(
sizeof(
bool) * ndims);
1282
1284 ptr +=
sizeof(
bool) * ndims;
1285
1288
1291
1292
1293 for (dim = 0; dim < ndims; dim++)
1294 {
1296
1299
1301 continue;
1302
1304 }
1305
1306
1308 }
1309
1310
1312
1313
1314 for (dim = 0; dim < ndims; dim++)
1316
1318
1320}
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1336{
1338
1339
1341 {
1345
1346
1348
1349
1351
1353
1355
1356
1360
1361
1365 errmsg(
"function returning record called in context "
1366 "that cannot accept type record")));
1368
1369
1370
1371
1372
1374
1376 }
1377
1378
1380
1382
1383 {
1385 bool nulls[5];
1390
1394
1396
1398
1400
1402 {
1403
1406 false,
1409
1411 {
1417
1418
1421
1424
1427 false,
1430 }
1431 else
1434 true,
1437 }
1438
1444
1445
1446 memset(nulls, 0,
sizeof(nulls));
1447
1448
1450
1451
1453
1455 }
1456 else
1457 {
1459 }
1460}
1461
1462
1463
1464
1465
1466
1467
1470{
1471
1472
1473
1474
1477 errmsg(
"cannot accept a value of type %s",
"pg_mcv_list")));
1478
1480}
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1496{
1498}
1499
1500
1501
1502
1505{
1508 errmsg(
"cannot accept a value of type %s",
"pg_mcv_list")));
1509
1511}
1512
1513
1514
1515
1516
1517
1518
1521{
1523}
1524
1525
1526
1527
1528
1529
1530
1531static int
1533{
1535
1537 {
1538
1540
1542 *
collid = var->varcollid;
1543
1545
1547 elog(
ERROR,
"variable not found in statistics object");
1548 }
1549 else
1550 {
1551
1553
1556
1557
1560 {
1562
1564 break;
1565
1567 }
1568
1570 elog(
ERROR,
"expression not found in statistics object");
1571 }
1572
1574}
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595static bool *
1599{
1602
1603
1608
1611
1612
1613
1614
1615
1616 foreach(l, clauses)
1617 {
1619
1620
1623
1624
1625
1626
1627
1629 {
1632
1633
1639
1641
1642
1645
1646
1648
1649
1650
1651
1652
1653
1655 {
1656 bool match = true;
1658
1660
1661
1662
1663
1664
1665
1667 {
1669 continue;
1670 }
1671
1672
1673
1674
1675
1676
1678 continue;
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1697 else
1702
1703
1705 }
1706 }
1708 {
1711
1712
1718
1719
1724 int num_elems;
1726 bool *elem_nulls;
1727
1729
1730
1733
1734
1737
1738
1739
1740
1741
1742 if (!
cst->constisnull)
1743 {
1750 &elem_values, &elem_nulls, &num_elems);
1751 }
1752
1753
1755
1756
1757
1758
1759
1760
1762 {
1764 bool match = !expr->
useOr;
1766
1767
1768
1769
1770
1771
1773 {
1775 continue;
1776 }
1777
1778
1779
1780
1781
1782
1784 continue;
1785
1786 for (
j = 0;
j < num_elems;
j++)
1787 {
1791
1792
1794 {
1796 continue;
1797 }
1798
1799
1800
1801
1802
1803
1805 break;
1806
1811
1813 }
1814
1815
1817 }
1818 }
1820 {
1823
1824
1826
1827
1828
1829
1830
1831
1833 {
1834 bool match = false;
1836
1837
1839 {
1841 match = (item->
isnull[
idx]) ?
true : match;
1842 break;
1843
1845 match = (!item->
isnull[
idx]) ?
true : match;
1846 break;
1847 }
1848
1849
1851 }
1852 }
1854 {
1855
1856
1860
1861
1863
1866
1867
1870
1871
1872
1873
1874
1875
1878
1880 }
1882 {
1883
1884
1888
1889
1891
1894
1895
1898
1899
1900
1901
1902
1903
1906
1908 }
1909 else if (
IsA(clause,
Var))
1910 {
1911
1912
1913 Var *var = (
Var *) (clause);
1914
1915
1917
1919
1920
1921
1922
1923
1924
1926 {
1928 bool match = false;
1929
1930
1932 match = true;
1933
1934
1936 }
1937 }
1938 else
1939 {
1940
1942
1943
1945
1946
1947
1948
1949
1950
1952 {
1953 bool match;
1955
1956
1958
1959
1961 }
1962 }
1963 }
1964
1966}
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2007{
2010
2011
2014
2015
2018
2019
2022
2024}
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2046 List *clauses,
int varRelid,
2050{
2055
2056
2058
2059
2061
2062
2064 mcv, false);
2065
2066
2069 for (
i = 0;
i < mcv->nitems;
i++)
2070 {
2072
2074 {
2075 *
basesel += mcv->items[
i].base_frequency;
2076 s += mcv->items[
i].frequency;
2077 }
2078 }
2079
2080 return s;
2081}
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2127{
2131
2132
2135
2136
2138 stat->exprs, mcv,
false);
2139
2140
2141
2142
2143
2144
2149 for (
i = 0;
i < mcv->nitems;
i++)
2150 {
2152
2154 {
2155 s += mcv->items[
i].frequency;
2156 *
basesel += mcv->items[
i].base_frequency;
2157
2159 {
2162 }
2163 }
2164
2165
2167 }
2168
2170
2171 return s;
2172}
2173
2174
2175
2176
2177void
2179{
2181 {
2183
2186 }
2188}
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2207{
2211
2212
2213
2214
2217
2222
2223
2225 {
2227
2232 }
2233
2234
2235
2236
2237
2238
2239
2241 {
2246
2249
2250
2252
2254 {
2256
2258 {
2259
2262 }
2263 else
2264 {
2267
2270 {
2273 errmsg(
"could not parse MCV element \"%s\": incorrect value", s)));
2276 }
2277
2279 }
2280
2282 }
2283 }
2284
2285
2286
2287
2288
2289
2291
2293 {
2296
2298
2300 elog(
ERROR,
"cache lookup failed for type %u", typid);
2301
2303
2307 }
2308
2310
2312 {
2314 }
2316
2319
2321 {
2324 errmsg(
"could not import MCV list")));
2326 }
2327
2329
2333}
Datum idx(PG_FUNCTION_ARGS)
#define DatumGetArrayTypeP(X)
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
void deconstruct_array(const ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
int bms_num_members(const Bitmapset *a)
int bms_member_index(Bitmapset *a, int x)
static Datum values[MAXATTR]
#define TextDatumGetCString(d)
Datum byteaout(PG_FUNCTION_ARGS)
Datum byteasend(PG_FUNCTION_ARGS)
#define PG_USED_FOR_ASSERTS_ONLY
#define Assert(condition)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
bool equal(const void *a, const void *b)
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
int compare_scalars_simple(const void *a, const void *b, void *arg)
int compare_datums_simple(Datum a, Datum b, SortSupport ssup)
SortItem * build_sorted_items(StatsBuildData *data, int *nitems, MultiSortSupport mss, int numattrs, AttrNumber *attnums)
int multi_sort_compare(const void *a, const void *b, void *arg)
MultiSortSupport multi_sort_init(int ndims)
void multi_sort_add_dimension(MultiSortSupport mss, int sortdim, Oid oper, Oid collation)
bool examine_opclause_args(List *args, Node **exprp, Const **cstp, bool *expronleftp)
MultiSortSupportData * MultiSortSupport
#define palloc_array(type, count)
#define palloc0_array(type, count)
#define palloc0_object(type)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
void fmgr_info(Oid functionId, FmgrInfo *finfo)
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, Node *escontext, Datum *result)
#define PG_DETOAST_DATUM(datum)
#define FunctionCall1(flinfo, arg1)
#define PG_GETARG_BYTEA_P(n)
#define DatumGetByteaP(X)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
#define SRF_IS_FIRSTCALL()
#define SRF_PERCALL_SETUP()
#define SRF_RETURN_NEXT(_funcctx, _result)
#define SRF_FIRSTCALL_INIT()
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
#define SRF_RETURN_DONE(_funcctx)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
RegProcedure get_opcode(Oid opno)
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
void statext_mcv_free(MCVList *mcvlist)
Datum pg_stats_ext_mcvlist_items(PG_FUNCTION_ARGS)
Datum pg_mcv_list_in(PG_FUNCTION_ARGS)
MCVList * statext_mcv_deserialize(bytea *data)
Selectivity mcv_clauselist_selectivity(PlannerInfo *root, StatisticExtInfo *stat, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Selectivity *basesel, Selectivity *totalsel)
static MultiSortSupport build_mss(StatsBuildData *data)
static int compare_sort_item_count(const void *a, const void *b, void *arg)
MCVList * statext_mcv_load(Oid mvoid, bool inh)
Datum pg_mcv_list_out(PG_FUNCTION_ARGS)
static int count_distinct_groups(int numrows, SortItem *items, MultiSortSupport mss)
Datum statext_mcv_import(int elevel, int numattrs, Oid *atttypids, int32 *atttypmods, Oid *atttypcolls, int nitems, Datum *mcv_elems, bool *mcv_nulls, float8 *freqs, float8 *base_freqs)
Datum pg_mcv_list_send(PG_FUNCTION_ARGS)
#define SizeOfMCVList(ndims, nitems)
static bool * mcv_get_match_bitmap(PlannerInfo *root, List *clauses, Bitmapset *keys, List *exprs, MCVList *mcvlist, bool is_or)
#define RESULT_MERGE(value, is_or, match)
static double get_mincount_for_mcv_list(int samplerows, double totalrows)
Selectivity mcv_combine_selectivities(Selectivity simple_sel, Selectivity mcv_sel, Selectivity mcv_basesel, Selectivity mcv_totalsel)
Selectivity mcv_clause_selectivity_or(PlannerInfo *root, StatisticExtInfo *stat, MCVList *mcv, Node *clause, bool **or_matches, Selectivity *basesel, Selectivity *overlap_mcvsel, Selectivity *overlap_basesel, Selectivity *totalsel)
#define RESULT_IS_FINAL(value, is_or)
static int mcv_match_expression(Node *expr, Bitmapset *keys, List *exprs, Oid *collid)
MCVList * statext_mcv_build(StatsBuildData *data, double totalrows, int stattarget)
Datum pg_mcv_list_recv(PG_FUNCTION_ARGS)
static int sort_item_compare(const void *a, const void *b, void *arg)
static SortItem ** build_column_frequencies(SortItem *groups, int ngroups, MultiSortSupport mss, int *ncounts)
bytea * statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats)
static SortItem * build_distinct_groups(int numrows, SortItem *items, MultiSortSupport mss, int *ndistinct)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
Oid exprCollation(const Node *expr)
static bool is_andclause(const void *clause)
static bool is_orclause(const void *clause)
static bool is_opclause(const void *clause)
static bool is_notclause(const void *clause)
#define IsA(nodeptr, _type_)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
static int list_length(const List *l)
FormData_pg_type * Form_pg_type
void * bsearch_arg(const void *key, const void *base0, size_t nmemb, size_t size, int(*compar)(const void *, const void *, void *), void *arg)
void qsort_interruptible(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
static bool DatumGetBool(Datum X)
static Datum PointerGetDatum(const void *X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static char * DatumGetCString(Datum X)
static Pointer DatumGetPointer(Datum X)
static Datum Float8GetDatum(float8 X)
static Datum Int32GetDatum(int32 X)
#define CLAMP_PROBABILITY(p)
void PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
struct SortSupportData * SortSupport
static int ApplySortComparator(Datum datum1, bool isNull1, Datum datum2, bool isNull2, SortSupport ssup)
#define STATS_MCV_TYPE_BASIC
#define STATS_MCVLIST_MAX_ITEMS
#define STATS_MAX_DIMENSIONS
SortSupportData ssup[FLEXIBLE_ARRAY_MEMBER]
NullTestType nulltesttype
void ReleaseSysCache(HeapTuple tuple)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
#define SearchSysCacheCopy1(cacheId, key1)
static Datum fetch_att(const void *T, bool attbyval, int attlen)
static void store_att_byval(void *T, Datum newdatum, int attlen)
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
static Size VARSIZE_ANY(const void *PTR)
static Size VARSIZE_ANY_EXHDR(const void *PTR)
static char * VARDATA(const void *PTR)
static char * VARDATA_ANY(const void *PTR)
static void SET_VARSIZE(void *PTR, Size len)
text * cstring_to_text(const char *s)