131#include "utils/fmgroids.h"
144#define DEFAULT_PAGE_CPU_MULTIPLIER 50.0
153#ifndef USE_ASSERT_CHECKING
154#define EQJOINSEL_MCV_HASH_THRESHOLD 200
156#define EQJOINSEL_MCV_HASH_THRESHOLD 20
188 Oid hashLeft,
Oid hashRight,
190 double nd1,
double nd2,
191 bool isdefault1,
bool isdefault2,
194 bool have_mcvs1,
bool have_mcvs2,
195 bool *hasmatch1,
bool *hasmatch2,
198 Oid hashLeft,
Oid hashRight,
201 double nd1,
double nd2,
202 bool isdefault1,
bool isdefault2,
205 bool have_mcvs1,
bool have_mcvs2,
206 bool *hasmatch1,
bool *hasmatch2,
210 Oid hashLeft,
Oid hashRight,
213 int nvalues1,
int nvalues2,
214 bool *hasmatch1,
bool *hasmatch2,
215 int *p_nmatches,
double *p_matchprodfreq);
223 double *scaledlobound,
double *scaledhibound);
228 double *scaledlobound,
230 double *scaledhibound);
234 double *scaledlobound,
236 double *scaledhibound);
238 int rangelo,
int rangehi);
240 int rangelo,
int rangehi);
253 Oid sortop,
Oid collation,
257 Oid collation,
int16 typLen,
bool typByVal,
261 Oid sortop,
Oid collation,
271 Datum *endpointDatum);
277#define SH_PREFIX MCVHashTable
278#define SH_ELEMENT_TYPE MCVHashEntry
279#define SH_KEY_TYPE Datum
281#define SH_HASH_KEY(tab,key) hash_mcv(tab, key)
282#define SH_EQUAL(tab,key0,key1) mcvs_equal(tab, key0, key1)
283#define SH_SCOPE static inline
285#define SH_GET_HASH(tab,ent) (ent)->hash
340 &vardata, &other, &varonleft))
350 ((
Const *) other)->constvalue,
351 ((
Const *) other)->constisnull,
369 Datum constval,
bool constisnull,
370 bool varonleft,
bool negate)
373 double nullfrac = 0.0;
393 nullfrac = stats->stanullfrac;
439 fcinfo->args[0].isnull =
false;
440 fcinfo->args[1].isnull =
false;
443 fcinfo->args[1].value = constval;
445 fcinfo->args[0].value = constval;
452 fcinfo->args[0].value = sslot.
values[
i];
454 fcinfo->args[1].value = sslot.
values[
i];
455 fcinfo->isnull =
false;
485 double sumcommon = 0.0;
486 double otherdistinct;
490 selec = 1.0 - sumcommon - nullfrac;
500 if (otherdistinct > 1)
501 selec /= otherdistinct;
525 selec = 1.0 - selec - nullfrac;
541 bool varonleft,
bool negate)
544 double nullfrac = 0.0;
555 nullfrac = stats->stanullfrac;
584 selec = 1.0 - nullfrac;
614 selec = 1.0 - selec - nullfrac;
698 if (block >= vardata->
rel->
pages - 1)
713 block +=
Min(offset / density, 1.0);
720 selec = block / (vardata->
rel->
pages - 0.5);
730 if (iseq == isgt && vardata->
rel->
tuples >= 1.0)
754 mcv_selec =
mcv_selectivity(vardata, &opproc, collation, constval,
true,
762 operator, &opproc, isgt, iseq,
764 constval, consttype);
771 selec = 1.0 - stats->stanullfrac - sumcommon;
773 if (hist_selec >= 0.0)
806 Datum constval,
bool varonleft,
834 fcinfo->args[0].isnull =
false;
835 fcinfo->args[1].isnull =
false;
838 fcinfo->args[1].value = constval;
840 fcinfo->args[0].value = constval;
847 fcinfo->args[0].value = sslot.
values[
i];
849 fcinfo->args[1].value = sslot.
values[
i];
850 fcinfo->isnull =
false;
859 *sumcommonp = sumcommon;
898 Datum constval,
bool varonleft,
899 int min_hist_size,
int n_skip,
907 Assert(min_hist_size > 2 * n_skip);
916 if (sslot.
nvalues >= min_hist_size)
932 fcinfo->args[0].isnull =
false;
933 fcinfo->args[1].isnull =
false;
936 fcinfo->args[1].value = constval;
938 fcinfo->args[0].value = constval;
940 for (
i = n_skip;
i < sslot.
nvalues - n_skip;
i++)
945 fcinfo->args[0].value = sslot.
values[
i];
947 fcinfo->args[1].value = sslot.
values[
i];
948 fcinfo->isnull =
false;
953 result = ((double) nmatch) / ((double) (sslot.
nvalues - 2 * n_skip));
989 double default_selectivity)
1001 &vardata, &other, &varonleft))
1002 return default_selectivity;
1009 ((
Const *) other)->constisnull)
1018 Datum constval = ((
Const *) other)->constvalue;
1031 constval, varonleft,
1041 constval, varonleft,
1046 selec = default_selectivity;
1048 else if (hist_size < 100)
1055 double hist_weight = hist_size / 100.0;
1057 selec = selec * hist_weight +
1058 default_selectivity * (1.0 - hist_weight);
1064 else if (selec > 0.9999)
1078 selec *= 1.0 - nullfrac - mcvsum;
1084 selec = default_selectivity;
1116 Oid opoid,
FmgrInfo *opproc,
bool isgt,
bool iseq,
1168 bool have_end =
false;
1184 while (lobound < hibound)
1186 int probe = (lobound + hibound) / 2;
1194 if (probe == 0 && sslot.
nvalues > 2)
1216 lobound = probe + 1;
1233 else if (lobound >= sslot.
nvalues)
1244 double eq_selec = 0;
1266 if (
i == 1 || isgt == iseq)
1268 double otherdistinct;
1286 if (otherdistinct > 1)
1287 eq_selec = 1.0 / otherdistinct;
1306 else if (
val <= low)
1308 else if (
val >= high)
1312 binfrac = (
val - low) / (high - low);
1320 if (isnan(binfrac) ||
1321 binfrac < 0.0 || binfrac > 1.0)
1343 histfrac = (double) (
i - 1) + binfrac;
1344 histfrac /= (double) (sslot.
nvalues - 1);
1379 histfrac += eq_selec * (1.0 - binfrac);
1387 histfrac -= eq_selec;
1394 hist_selec = isgt ? (1.0 - histfrac) : histfrac;
1409 double cutoff = 0.01 / (double) (sslot.
nvalues - 1);
1411 if (hist_selec < cutoff)
1412 hist_selec = cutoff;
1413 else if (hist_selec > 1.0 - cutoff)
1414 hist_selec = 1.0 - cutoff;
1431 fcinfo->args[0].isnull =
false;
1432 fcinfo->args[1].isnull =
false;
1433 fcinfo->args[1].value = constval;
1438 fcinfo->args[0].value = sslot.
values[
i];
1439 fcinfo->isnull =
false;
1444 hist_selec = ((double) nmatch) / ((double) sslot.
nvalues);
1453 double cutoff = 0.01 / (double) (sslot.
nvalues - 1);
1455 if (hist_selec < cutoff)
1456 hist_selec = cutoff;
1457 else if (hist_selec > 1.0 - cutoff)
1458 hist_selec = 1.0 - cutoff;
1492 &vardata, &other, &varonleft))
1508 if (((
Const *) other)->constisnull)
1513 constval = ((
Const *) other)->constvalue;
1514 consttype = ((
Const *) other)->consttype;
1533 &vardata, constval, consttype);
1639 freq_null = stats->stanullfrac;
1655 freq_true = 1.0 - sslot.
numbers[0] - freq_null;
1661 freq_false = 1.0 - freq_true - freq_null;
1663 switch (booltesttype)
1671 selec = 1.0 - freq_null;
1679 selec = 1.0 - freq_true;
1687 selec = 1.0 - freq_false;
1690 elog(
ERROR,
"unrecognized booltesttype: %d",
1691 (
int) booltesttype);
1705 switch (booltesttype)
1713 selec = 1.0 - freq_null;
1718 selec = (1.0 - freq_null) / 2.0;
1724 selec = (freq_null + 1.0) / 2.0;
1727 elog(
ERROR,
"unrecognized booltesttype: %d",
1728 (
int) booltesttype);
1742 switch (booltesttype)
1763 elog(
ERROR,
"unrecognized booltesttype: %d",
1764 (
int) booltesttype);
1796 freq_null = stats->stanullfrac;
1798 switch (nulltesttype)
1813 selec = 1.0 - freq_null;
1816 elog(
ERROR,
"unrecognized nulltesttype: %d",
1817 (
int) nulltesttype);
1822 ((
Var *) vardata.
var)->varattno < 0)
1828 selec = (nulltesttype ==
IS_NULL) ? 0.0 : 1.0;
1835 switch (nulltesttype)
1844 elog(
ERROR,
"unrecognized nulltesttype: %d",
1845 (
int) nulltesttype);
1902 bool is_join_clause,
1908 bool useOr = clause->
useOr;
1909 bool isEquality =
false;
1910 bool isInequality =
false;
1913 Oid nominal_element_type;
1914 Oid nominal_element_collation;
1947 if (
operator == typentry->
eq_opr)
1950 isInequality =
true;
1959 if ((isEquality || isInequality) && !is_join_clause)
1962 nominal_element_type,
1963 isEquality, useOr, varRelid);
1988 if (oprsel == F_EQSEL || oprsel == F_EQJOINSEL)
1990 else if (oprsel == F_NEQSEL || oprsel == F_NEQJOINSEL)
1991 isInequality =
true;
2005 if (rightop &&
IsA(rightop,
Const))
2007 Datum arraydatum = ((
Const *) rightop)->constvalue;
2008 bool arrayisnull = ((
Const *) rightop)->constisnull;
2022 &elmlen, &elmbyval, &elmalign);
2025 elmlen, elmbyval, elmalign,
2026 &elem_values, &elem_nulls, &num_elems);
2042 s1 = s1disjoint = (useOr ? 0.0 : 1.0);
2044 for (
i = 0;
i < num_elems;
i++)
2052 nominal_element_collation,
2059 clause->inputcollid,
2067 clause->inputcollid,
2083 s1disjoint +=
s2 - 1.0;
2088 if ((useOr ? isEquality : isInequality) &&
2089 s1disjoint >= 0.0 && s1disjoint <= 1.0)
2101 &elmlen, &elmbyval);
2110 s1 = s1disjoint = (useOr ? 0.0 : 1.0);
2112 foreach(l, arrayexpr->elements)
2126 clause->inputcollid,
2134 clause->inputcollid,
2150 s1disjoint +=
s2 - 1.0;
2155 if ((useOr ? isEquality : isInequality) &&
2156 s1disjoint >= 0.0 && s1disjoint <= 1.0)
2172 dummyexpr->
typeId = nominal_element_type;
2173 dummyexpr->typeMod = -1;
2174 dummyexpr->collation = clause->inputcollid;
2178 clause->inputcollid,
2186 clause->inputcollid,
2191 s1 = useOr ? 0.0 : 1.0;
2198 for (
i = 0;
i < 10;
i++)
2228 if (arrayexpr &&
IsA(arrayexpr,
Const))
2230 Datum arraydatum = ((
Const *) arrayexpr)->constvalue;
2231 bool arrayisnull = ((
Const *) arrayexpr)->constisnull;
2244 else if (arrayexpr &&
root)
2297 bool is_join_clause;
2313 is_join_clause =
false;
2315 else if (sjinfo == NULL)
2321 is_join_clause =
false;
2383 bool have_mcvs1 =
false;
2384 bool have_mcvs2 =
false;
2385 bool *hasmatch1 = NULL;
2386 bool *hasmatch2 = NULL;
2389 bool join_is_reversed;
2393 &vardata1, &vardata2, &join_is_reversed);
2400 memset(&sslot1, 0,
sizeof(sslot1));
2401 memset(&sslot2, 0,
sizeof(sslot2));
2420 if (get_mcv_stats &&
2431 if (get_mcv_stats &&
2439 if (have_mcvs1 && have_mcvs2)
2453 memset(&eqproc, 0,
sizeof(eqproc));
2457 hashLeft, hashRight,
2458 &vardata1, &vardata2,
2460 isdefault1, isdefault2,
2463 have_mcvs1, have_mcvs2,
2464 hasmatch1, hasmatch2,
2472 selec = selec_inner;
2485 if (!join_is_reversed)
2487 hashLeft, hashRight,
2489 &vardata1, &vardata2,
2491 isdefault1, isdefault2,
2494 have_mcvs1, have_mcvs2,
2495 hasmatch1, hasmatch2,
2500 hashLeft, hashRight,
2502 &vardata2, &vardata1,
2504 isdefault2, isdefault1,
2507 have_mcvs2, have_mcvs1,
2508 hasmatch2, hasmatch1,
2522 selec =
Min(selec, inner_rel->
rows * selec_inner);
2526 elog(
ERROR,
"unrecognized join type: %d",
2560 Oid hashLeft,
Oid hashRight,
2562 double nd1,
double nd2,
2563 bool isdefault1,
bool isdefault2,
2566 bool have_mcvs1,
bool have_mcvs2,
2567 bool *hasmatch1,
bool *hasmatch2,
2572 if (have_mcvs1 && have_mcvs2)
2586 double nullfrac1 = stats1->stanullfrac;
2587 double nullfrac2 = stats2->stanullfrac;
2588 double matchprodfreq,
2602 hashLeft, hashRight,
2606 hasmatch1, hasmatch2,
2607 p_nmatches, &matchprodfreq);
2608 nmatches = *p_nmatches;
2612 matchfreq1 = unmatchfreq1 = 0.0;
2618 unmatchfreq1 += sslot1->
numbers[
i];
2622 matchfreq2 = unmatchfreq2 = 0.0;
2628 unmatchfreq2 += sslot2->
numbers[
i];
2637 otherfreq1 = 1.0 - nullfrac1 - matchfreq1 - unmatchfreq1;
2638 otherfreq2 = 1.0 - nullfrac2 - matchfreq2 - unmatchfreq2;
2650 totalsel1 = matchprodfreq;
2652 totalsel1 += unmatchfreq1 * otherfreq2 / (nd2 - sslot2->
nvalues);
2654 totalsel1 += otherfreq1 * (otherfreq2 + unmatchfreq2) /
2657 totalsel2 = matchprodfreq;
2659 totalsel2 += unmatchfreq2 * otherfreq1 / (nd1 - sslot1->
nvalues);
2661 totalsel2 += otherfreq2 * (otherfreq1 + unmatchfreq1) /
2670 selec = (totalsel1 < totalsel2) ? totalsel1 : totalsel2;
2694 double nullfrac1 = stats1 ? stats1->stanullfrac : 0.0;
2695 double nullfrac2 = stats2 ? stats2->stanullfrac : 0.0;
2697 selec = (1.0 - nullfrac1) * (1.0 - nullfrac2);
2719 Oid hashLeft,
Oid hashRight,
2720 bool op_is_reversed,
2722 double nd1,
double nd2,
2723 bool isdefault1,
bool isdefault2,
2726 bool have_mcvs1,
bool have_mcvs2,
2727 bool *hasmatch1,
bool *hasmatch2,
2754 if (nd2 >= vardata2->
rel->
rows)
2760 if (nd2 >= inner_rel->
rows)
2762 nd2 = inner_rel->
rows;
2766 if (have_mcvs1 && have_mcvs2)
2776 double nullfrac1 = stats1->stanullfrac;
2777 double matchprodfreq,
2792 clamped_nvalues2 =
Min(sslot2->
nvalues, nd2);
2804 if (clamped_nvalues2 != sslot2->
nvalues)
2807 memset(hasmatch1, 0, sslot1->
nvalues *
sizeof(
bool));
2808 memset(hasmatch2, 0, clamped_nvalues2 *
sizeof(
bool));
2811 hashLeft, hashRight,
2814 sslot1->
nvalues, clamped_nvalues2,
2815 hasmatch1, hasmatch2,
2816 p_nmatches, &matchprodfreq);
2818 nmatches = *p_nmatches;
2844 if (!isdefault1 && !isdefault2)
2848 if (nd1 <= nd2 || nd2 < 0)
2849 uncertainfrac = 1.0;
2851 uncertainfrac = nd2 / nd1;
2854 uncertainfrac = 0.5;
2855 uncertain = 1.0 - matchfreq1 - nullfrac1;
2857 selec = matchfreq1 + uncertainfrac * uncertain;
2865 double nullfrac1 = stats1 ? stats1->stanullfrac : 0.0;
2867 if (!isdefault1 && !isdefault2)
2869 if (nd1 <= nd2 || nd2 < 0)
2870 selec = 1.0 - nullfrac1;
2872 selec = (nd2 / nd1) * (1.0 - nullfrac1);
2875 selec = 0.5 * (1.0 - nullfrac1);
2910 Oid hashLeft,
Oid hashRight,
2911 bool op_is_reversed,
2913 int nvalues1,
int nvalues2,
2914 bool *hasmatch1,
bool *hasmatch2,
2915 int *p_nmatches,
double *p_matchprodfreq)
2918 double matchprodfreq = 0.0;
2928 fcinfo->args[0].isnull =
false;
2929 fcinfo->args[1].isnull =
false;
2940 bool *hasMatchProbe;
2948 statsProbe = sslot1;
2950 hasMatchProbe = hasmatch1;
2951 hasMatchHash = hasmatch2;
2952 nvaluesProbe = nvalues1;
2953 nvaluesHash = nvalues2;
2958 op_is_reversed = !op_is_reversed;
2959 statsProbe = sslot2;
2961 hasMatchProbe = hasmatch2;
2962 hasMatchHash = hasmatch1;
2963 nvaluesProbe = nvalues2;
2964 nvaluesHash = nvalues1;
2971 fmgr_info(op_is_reversed ? hashLeft : hashRight, &hash_proc);
2974 hash_fcinfo->args[0].isnull =
false;
2988 for (
int i = 0;
i < nvaluesHash;
i++)
3015 if (hashLeft != hashRight)
3017 fmgr_info(op_is_reversed ? hashRight : hashLeft, &hash_proc);
3021 hash_fcinfo->args[0].isnull =
false;
3025 for (
int i = 0;
i < nvaluesProbe;
i++)
3031 if (entry != NULL && !hasMatchHash[entry->
index])
3033 hasMatchHash[entry->
index] = hasMatchProbe[
i] =
true;
3039 MCVHashTable_destroy(hashTable);
3059 for (
int i = 0;
i < nvalues1;
i++)
3061 fcinfo->args[index1].value = sslot1->
values[
i];
3063 for (
int j = 0;
j < nvalues2;
j++)
3069 fcinfo->args[index2].value = sslot2->
values[
j];
3070 fcinfo->isnull =
false;
3074 hasmatch1[
i] = hasmatch2[
j] =
true;
3083 *p_nmatches = nmatches;
3084 *p_matchprodfreq = matchprodfreq;
3098 fcinfo->isnull =
false;
3194 result = 1.0 - nullfrac;
3220 result = 1.0 - result;
3321 *leftstart = *rightstart = 0.0;
3322 *leftend = *rightend = 1.0;
3327 opno = ((
OpExpr *) clause)->opno;
3328 collation = ((
OpExpr *) clause)->inputcollid;
3360 if (op_lefttype == op_righttype)
3364 op_lefttype, op_righttype,
3367 op_lefttype, op_righttype,
3379 op_lefttype, op_righttype,
3382 op_lefttype, op_righttype,
3385 op_lefttype, op_lefttype,
3388 op_righttype, op_righttype,
3393 op_righttype, op_lefttype,
3396 op_righttype, op_lefttype,
3406 if (op_lefttype == op_righttype)
3410 op_lefttype, op_righttype,
3413 op_lefttype, op_righttype,
3418 op_lefttype, op_lefttype,
3427 op_lefttype, op_righttype,
3430 op_lefttype, op_righttype,
3433 op_lefttype, op_lefttype,
3436 op_righttype, op_righttype,
3439 op_lefttype, op_lefttype,
3442 op_righttype, op_righttype,
3445 op_righttype, op_lefttype,
3448 op_righttype, op_lefttype,
3470 &leftmin, &leftmax))
3473 &rightmin, &rightmax))
3480 &leftmax, &leftmin))
3483 &rightmax, &rightmin))
3493 rightmax, op_righttype);
3499 leftmax, op_lefttype);
3509 if (*leftend > *rightend)
3511 else if (*leftend < *rightend)
3514 *leftend = *rightend = 1.0;
3523 rightmin, op_righttype);
3529 leftmin, op_lefttype);
3531 *rightstart = selec;
3539 if (*leftstart < *rightstart)
3541 else if (*leftstart > *rightstart)
3544 *leftstart = *rightstart = 0.0;
3559 *leftstart += stats->stanullfrac;
3561 *leftend += stats->stanullfrac;
3567 *rightstart += stats->stanullfrac;
3569 *rightend += stats->stanullfrac;
3575 if (*leftstart >= *leftend)
3580 if (*rightstart >= *rightend)
3660 foreach(lc, varinfos)
3673 if (vardata->
rel != varinfo->
rel &&
3692 varinfo->
rel = vardata->
rel;
3695 varinfos =
lappend(varinfos, varinfo);
3775 double srf_multiplier = 1.0;
3781 if (estinfo != NULL)
3797 if (groupExprs ==
NIL || (pgset && *pgset ==
NIL))
3810 foreach(l, groupExprs)
3813 double this_srf_multiplier;
3834 if (srf_multiplier < this_srf_multiplier)
3835 srf_multiplier = this_srf_multiplier;
3838 if (
exprType(groupexpr) == BOOLOID)
3861 groupexpr, &vardata);
3884 if (varshere ==
NIL)
3894 foreach(l2, varshere)
3908 if (varinfos ==
NIL)
3911 numdistinct *= srf_multiplier;
3913 numdistinct = ceil(numdistinct);
3915 if (numdistinct > input_rows)
3916 numdistinct = input_rows;
3917 if (numdistinct < 1.0)
3934 double reldistinct = 1;
3935 double relmaxndistinct = reldistinct;
3936 int relvarcount = 0;
3944 relvarinfos =
lappend(relvarinfos, varinfo1);
3949 if (varinfo2->
rel == varinfo1->
rel)
3952 relvarinfos =
lappend(relvarinfos, varinfo2);
3957 newvarinfos =
lappend(newvarinfos, varinfo2);
3980 reldistinct *= mvndistinct;
3981 if (relmaxndistinct < mvndistinct)
3982 relmaxndistinct = mvndistinct;
3987 foreach(l, relvarinfos)
3992 if (relmaxndistinct < varinfo2->ndistinct)
4000 if (estinfo != NULL && varinfo2->
isdefault)
4022 double clamp = rel->
tuples;
4024 if (relvarcount > 1)
4027 if (clamp < relmaxndistinct)
4029 clamp = relmaxndistinct;
4035 if (reldistinct > clamp)
4036 reldistinct = clamp;
4043 if (reldistinct > 0 && rel->
rows < rel->
tuples)
4081 rel->
tuples / reldistinct));
4088 numdistinct *= reldistinct;
4091 varinfos = newvarinfos;
4092 }
while (varinfos !=
NIL);
4095 numdistinct *= srf_multiplier;
4098 numdistinct = ceil(numdistinct);
4101 if (numdistinct > input_rows)
4102 numdistinct = input_rows;
4103 if (numdistinct < 1.0)
4146 while (clauses !=
NIL)
4153 List *origin_varinfos;
4154 int group_relid = -1;
4165 foreach(lc, clauses)
4177 relids = rinfo->outer_is_left ?
4178 rinfo->right_relids : rinfo->left_relids;
4179 expr = rinfo->outer_is_left ?
4183 root->simple_rel_array[relid]->statlist !=
NIL)
4185 bool is_duplicate =
false;
4191 if (group_relid < 0)
4195 if (!rte || (rte->relkind != RELKIND_RELATION &&
4196 rte->relkind != RELKIND_MATVIEW &&
4197 rte->relkind != RELKIND_FOREIGN_TABLE &&
4198 rte->relkind != RELKIND_PARTITIONED_TABLE))
4201 otherclauses =
lappend(otherclauses, rinfo);
4206 group_relid = relid;
4207 group_rel =
root->simple_rel_array[relid];
4209 else if (group_relid != relid)
4245 foreach(lc1, varinfos)
4252 is_duplicate =
true;
4271 varinfo->
var = expr;
4272 varinfo->
rel =
root->simple_rel_array[relid];
4273 varinfos =
lappend(varinfos, varinfo);
4279 origin_rinfos =
lappend(origin_rinfos, rinfo);
4284 otherclauses =
lappend(otherclauses, rinfo);
4296 otherclauses =
list_concat(otherclauses, origin_rinfos);
4302 Assert(group_rel != NULL);
4305 origin_varinfos = varinfos;
4321 if (ndistinct < mvndistinct)
4322 ndistinct = mvndistinct;
4323 Assert(ndistinct >= 1.0);
4329 forboth(lc1, origin_varinfos, lc2, origin_rinfos)
4342 *innerbucketsize = 1.0 / ndistinct;
4343 return otherclauses;
4430 *mcv_freq = 1.0 / vardata.
rel->
rows;
4454 stanullfrac = stats->stanullfrac;
4460 avgfreq = (1.0 - stanullfrac) / ndistinct;
4481 if (ndistinct > nbuckets)
4482 estfract = 1.0 / nbuckets;
4484 estfract = 1.0 / ndistinct;
4489 if (avgfreq > 0.0 && *mcv_freq > avgfreq)
4490 estfract *= *mcv_freq / avgfreq;
4497 if (estfract < 1.0e-6)
4499 else if (estfract > 1.0)
4527 path->pathtarget->width,
4536 return hashentrysize * dNumGroups;
4563 List **varinfos,
double *ndistinct)
4584 int nshared_vars = 0;
4585 int nshared_exprs = 0;
4588 if (info->
kind != STATS_EXT_NDISTINCT)
4600 foreach(lc2, *varinfos)
4628 foreach(lc3, info->
exprs)
4646 if (nshared_vars + nshared_exprs < 2)
4657 if ((nshared_exprs > nmatches_exprs) ||
4658 (((nshared_exprs == nmatches_exprs)) && (nshared_vars > nmatches_vars)))
4661 nmatches_vars = nshared_vars;
4662 nmatches_exprs = nshared_exprs;
4663 matched_info = info;
4671 Assert(nmatches_vars + nmatches_exprs > 1);
4693 if (matched_info->
exprs)
4699 foreach(lc2, *varinfos)
4747 foreach(lc3, matched_info->
exprs)
4814 elog(
ERROR,
"corrupt MVNDistinct entry");
4817 foreach(lc, *varinfos)
4839 newlist =
lappend(newlist, varinfo);
4848 newlist =
lappend(newlist, varinfo);
4864 foreach(lc3, matched_info->
exprs)
4879 newlist =
lappend(newlist, varinfo);
4882 *varinfos = newlist;
4922 double *scaledlobound,
double *scaledhibound)
4924 bool failure =
false;
4958 case REGPROCEDUREOID:
4960 case REGOPERATOROID:
4963 case REGCOLLATIONOID:
4965 case REGDICTIONARYOID:
4967 case REGNAMESPACEOID:
4968 case REGDATABASEOID:
5002 lostr, scaledlobound,
5003 histr, scaledhibound);
5016 if (boundstypid != BYTEAOID)
5019 lobound, scaledlobound,
5020 hibound, scaledhibound);
5028 case TIMESTAMPTZOID:
5057 *scaledvalue = *scaledlobound = *scaledhibound = 0;
5091 case REGPROCEDUREOID:
5093 case REGOPERATOROID:
5096 case REGCOLLATIONOID:
5098 case REGDICTIONARYOID:
5100 case REGNAMESPACEOID:
5101 case REGDATABASEOID:
5132 double *scaledvalue,
5134 double *scaledlobound,
5136 double *scaledhibound)
5142 rangelo = rangehi = (
unsigned char) hibound[0];
5143 for (sptr = lobound; *sptr; sptr++)
5145 if (rangelo > (
unsigned char) *sptr)
5146 rangelo = (
unsigned char) *sptr;
5147 if (rangehi < (
unsigned char) *sptr)
5148 rangehi = (
unsigned char) *sptr;
5150 for (sptr = hibound; *sptr; sptr++)
5152 if (rangelo > (
unsigned char) *sptr)
5153 rangelo = (
unsigned char) *sptr;
5154 if (rangehi < (
unsigned char) *sptr)
5155 rangehi = (
unsigned char) *sptr;
5158 if (rangelo <= 'Z' && rangehi >=
'A')
5166 if (rangelo <= 'z' && rangehi >=
'a')
5174 if (rangelo <= '9' && rangehi >=
'0')
5186 if (rangehi - rangelo < 9)
5197 if (*lobound != *hibound || *lobound != *
value)
5199 lobound++, hibound++,
value++;
5213 int slen = strlen(
value);
5234 base = rangehi - rangelo + 1;
5239 int ch = (
unsigned char) *
value++;
5243 else if (ch > rangehi)
5245 num += ((double) (ch - rangelo)) / denom;
5320 if (xfrmlen == INT_MAX)
5323 xfrmstr = (
char *)
palloc(xfrmlen + 1);
5330 Assert(xfrmlen2 <= xfrmlen);
5351 double *scaledvalue,
5353 double *scaledlobound,
5355 double *scaledhibound)
5367 unsigned char *valstr = (
unsigned char *)
VARDATA_ANY(valuep);
5368 unsigned char *lostr = (
unsigned char *)
VARDATA_ANY(loboundp);
5369 unsigned char *histr = (
unsigned char *)
VARDATA_ANY(hiboundp);
5380 minlen =
Min(
Min(valuelen, loboundlen), hiboundlen);
5381 for (
i = 0;
i < minlen;
i++)
5383 if (*lostr != *histr || *lostr != *valstr)
5385 lostr++, histr++, valstr++;
5386 loboundlen--, hiboundlen--, valuelen--;
5399 int rangelo,
int rangehi)
5416 base = rangehi - rangelo + 1;
5419 while (valuelen-- > 0)
5425 else if (ch > rangehi)
5427 num += ((double) (ch - rangelo)) / denom;
5447 case TIMESTAMPTZOID:
5474 return (
double) (timetz->
time + (timetz->
zone * 1000000.0));
5532 if (vardata->
rel && rdata.
rel == NULL)
5540 if (vardata->
rel == NULL && rdata.
rel)
5569 bool *join_is_reversed)
5575 elog(
ERROR,
"join operator should take two arguments");
5583 if (vardata1->
rel &&
5585 *join_is_reversed =
true;
5586 else if (vardata2->
rel &&
5588 *join_is_reversed =
true;
5590 *join_is_reversed =
false;
5668 if (
IsA(basenode,
Var) &&
5669 (varRelid == 0 || varRelid == ((
Var *) basenode)->varno))
5671 Var *var = (
Var *) basenode;
5674 vardata->
var = basenode;
5676 vardata->
atttype = var->vartype;
5707 if (varRelid == 0 || varRelid == relid)
5710 vardata->
rel = onerel;
5737 vardata->
var = node;
5774 if (indexpr_item == NULL)
5777 for (pos = 0; pos <
index->ncolumns; pos++)
5779 if (
index->indexkeys[pos] == 0)
5783 if (indexpr_item == NULL)
5784 elog(
ERROR,
"too few entries in indexprs list");
5788 if (
equal(node, indexkey))
5794 if (
index->unique &&
5795 index->nkeycolumns == 1 &&
5821 elog(
ERROR,
"no function provided to release variable stats with");
5870 indexpr_item =
lnext(
index->indexprs, indexpr_item);
5898 if (info->
kind != STATS_EXT_EXPRESSIONS)
5906 foreach(expr_item, info->
exprs)
5917 if (
equal(node, expr))
5974 if (
root->glob->lastPHId == 0)
6044 elog(
ERROR,
"no function provided to release variable stats with");
6135 while (levelsup-- > 0)
6137 cteroot = cteroot->parent_root;
6167 if (subroot == NULL)
6178 subquery = subroot->
parse;
6199 if (ste == NULL || ste->resjunk)
6200 elog(
ERROR,
"subquery %s does not have attribute %d",
6201 rte->eref->aliasname, var->
varattno);
6242 if (rte->security_barrier)
6246 if (var &&
IsA(var,
Var) &&
6345 if (
root->append_rel_array != NULL)
6349 appinfo =
root->append_rel_array[varno];
6385 parent_attno = appinfo->parent_colnos[attno - 1];
6386 if (parent_attno == 0)
6398 parent_attno = attno;
6404 parent_attno = appinfo->parent_colnos[attno - 1];
6405 if (parent_attno == 0)
6416 varattnos = parent_varattnos;
6417 appinfo =
root->append_rel_array[varno];
6429 if (rte->securityQuals !=
NIL)
6447 if (varattnos == NULL)
6505 if (
index->indexkeys[indexcol] != 0)
6513 colnum =
index->indexkeys[indexcol];
6525 elog(
ERROR,
"no function provided to release variable stats with");
6539 relid =
index->indexoid;
6540 colnum = indexcol + 1;
6551 elog(
ERROR,
"no function provided to release variable stats with");
6585 (
errmsg_internal(
"not using statistics because function \"%s\" is not leakproof",
6605 double stanullfrac = 0.0;
6622 stadistinct = stats->stadistinct;
6623 stanullfrac = stats->stanullfrac;
6625 else if (vardata->
vartype == BOOLOID)
6654 switch (((
Var *) vardata->
var)->varattno)
6683 stadistinct = -1.0 * (1.0 - stanullfrac);
6688 if (stadistinct > 0.0)
6694 if (vardata->
rel == NULL)
6709 if (stadistinct < 0.0)
6736 Oid sortop,
Oid collation,
6741 bool have_data =
false;
6786 STATISTIC_KIND_HISTOGRAM, sortop,
6810 collation, typLen, typByVal,
6811 &tmin, &tmax, &have_data);
6828 bool use_mcvs = have_data;
6832 double sumcommon = 0.0;
6839 if (sumcommon + nullfrac > 0.99999)
6845 collation, typLen, typByVal,
6846 &tmin, &tmax, &have_data);
6863 Oid collation,
int16 typLen,
bool typByVal,
6868 bool have_data = *p_have_data;
6869 bool found_tmin =
false;
6870 bool found_tmax =
false;
6873 if (opproc->
fn_oid != opfuncoid)
6881 tmin = tmax = sslot->
values[
i];
6882 found_tmin = found_tmax =
true;
6883 *p_have_data = have_data =
true;
6906 *min =
datumCopy(tmin, typByVal, typLen);
6908 *max =
datumCopy(tmax, typByVal, typLen);
6926 Oid sortop,
Oid collation,
6929 bool have_data =
false;
6938 rte =
root->simple_rte_array[rel->
relid];
6942 if (rte->relkind == RELKIND_PARTITIONED_TABLE)
6953 if (
index->sortopfamily == NULL)
6967 if (
index->hypothetical)
6974 if (!
index->canreturn[0])
6981 if (collation !=
index->indexcollations[0])
6989 if (
index->reverse_sort[0])
6995 if (
index->reverse_sort[0])
7021 "get_actual_variable_range workspace",
7066 if (max && have_data)
7122 Datum *endpointDatum)
7124 bool have_data =
false;
7129 int n_visited_heap_pages = 0;
7183 &SnapshotNonVacuumable, NULL,
7211#define VISITED_PAGES_LIMIT 100
7213 if (block != last_heap_block)
7215 last_heap_block = block;
7216 n_visited_heap_pages++;
7238 elog(
ERROR,
"no data returned for index-only scan");
7253 elog(
ERROR,
"found unexpected null value in index \"%s\"",
7294 elog(
ERROR,
"could not find RelOptInfo for given relids");
7316 foreach(lc, indexclauses)
7325 result =
lappend(result, rinfo);
7343 Cost qual_arg_cost = 0;
7346 foreach(lc, indexquals)
7349 Node *other_operand;
7379 other_operand = NULL;
7383 elog(
ERROR,
"unsupported indexqual type: %d",
7385 other_operand = NULL;
7391 return qual_arg_cost;
7403 Cost indexStartupCost;
7404 Cost indexTotalCost;
7406 double indexCorrelation;
7407 double numIndexPages;
7408 double numIndexTuples;
7409 double spc_random_page_cost;
7410 double num_sa_scans;
7411 double num_outer_scans;
7413 double qual_op_cost;
7414 double qual_arg_cost;
7415 List *selectivityQuals;
7431 if (num_sa_scans < 1)
7434 foreach(l, indexQuals)
7444 num_sa_scans *= alength;
7461 if (numIndexTuples <= 0.0)
7463 numIndexTuples = indexSelectivity *
index->rel->tuples;
7472 numIndexTuples = rint(numIndexTuples / num_sa_scans);
7480 if (numIndexTuples >
index->tuples)
7481 numIndexTuples =
index->tuples;
7482 if (numIndexTuples < 1.0)
7483 numIndexTuples = 1.0;
7498 numIndexPages = ceil(numIndexTuples *
index->pages /
index->tuples);
7500 numIndexPages = 1.0;
7504 &spc_random_page_cost,
7524 num_outer_scans = loop_count;
7525 num_scans = num_sa_scans * num_outer_scans;
7529 double pages_fetched;
7532 pages_fetched = numIndexPages * num_scans;
7537 (
double)
index->pages,
7545 indexTotalCost = (pages_fetched * spc_random_page_cost)
7554 indexTotalCost = numIndexPages * spc_random_page_cost;
7576 indexStartupCost = qual_arg_cost;
7577 indexTotalCost += qual_arg_cost;
7583 indexCorrelation = 0.0;
7626 foreach(lc,
index->indpred)
7632 predExtraQuals =
list_concat(predExtraQuals, oneQual);
7653 double indexCorrelation = 0;
7658 index->opcintype[0],
7659 index->opcintype[0],
7663 STATISTIC_KIND_CORRELATION, sortop,
7666 double varCorrelation;
7669 varCorrelation = sslot.
numbers[0];
7671 if (
index->reverse_sort[0])
7672 varCorrelation = -varCorrelation;
7674 if (
index->nkeycolumns > 1)
7675 indexCorrelation = varCorrelation * 0.75;
7677 indexCorrelation = varCorrelation;
7682 return indexCorrelation;
7687 Cost *indexStartupCost,
Cost *indexTotalCost,
7688 Selectivity *indexSelectivity,
double *indexCorrelation,
7694 double numIndexTuples;
7696 List *indexBoundQuals;
7697 List *indexSkipQuals;
7700 bool found_row_compare;
7702 bool found_is_null_op;
7703 bool have_correlation =
false;
7704 double num_sa_scans;
7705 double correlation = 0.0;
7728 indexBoundQuals =
NIL;
7729 indexSkipQuals =
NIL;
7732 found_row_compare =
false;
7733 found_array =
false;
7734 found_is_null_op =
false;
7741 if (indexcol < iclause->indexcol)
7743 double num_sa_scans_prev_cols = num_sa_scans;
7769 if (found_row_compare)
7784 indexSkipQuals =
NIL;
7788 while (indexcol < iclause->indexcol)
7791 bool isdefault =
true;
7811 have_correlation =
true;
7822 num_sa_scans = num_sa_scans_prev_cols;
7829 if (indexSkipQuals !=
NIL)
7831 List *partialSkipQuals;
7856 num_sa_scans = num_sa_scans_prev_cols;
7861 ndistinct = rint(ndistinct * ndistinctfrac);
7862 ndistinct =
Max(ndistinct, 1);
7883 if (indexSkipQuals ==
NIL)
7894 num_sa_scans *= ndistinct;
7913 if (
index->pages < num_sa_scans)
7915 num_sa_scans = num_sa_scans_prev_cols;
7920 indexSkipQuals =
NIL;
7950 clause_op = op->
opno;
7957 found_row_compare =
true;
7965 clause_op = saop->
opno;
7969 num_sa_scans *= alength;
7977 found_is_null_op =
true;
7983 elog(
ERROR,
"unsupported indexqual type: %d",
7990 index->opfamily[indexcol]);
7991 Assert(op_strategy != 0);
7996 indexBoundQuals =
lappend(indexBoundQuals, rinfo);
8003 if (!eqQualHere && !found_row_compare &&
8004 indexcol < index->nkeycolumns - 1)
8005 indexSkipQuals =
lappend(indexSkipQuals, rinfo);
8015 if (
index->unique &&
8016 indexcol ==
index->nkeycolumns - 1 &&
8020 numIndexTuples = 1.0;
8023 List *selectivityQuals;
8037 numIndexTuples = btreeSelectivity *
index->rel->tuples;
8062 num_sa_scans =
Min(num_sa_scans, ceil(
index->pages * 0.3333333));
8063 num_sa_scans =
Max(num_sa_scans, 1);
8084 numIndexTuples = rint(numIndexTuples / num_sa_scans);
8106 if (
index->tuples > 1)
8128 if (!have_correlation)
8150 Cost *indexStartupCost,
Cost *indexTotalCost,
8151 Selectivity *indexSelectivity,
double *indexCorrelation,
8192 Cost *indexStartupCost,
Cost *indexTotalCost,
8193 Selectivity *indexSelectivity,
double *indexCorrelation,
8211 if (
index->tree_height < 0)
8213 if (
index->pages > 1)
8214 index->tree_height = (int) (log(
index->pages) / log(100.0));
8216 index->tree_height = 0;
8224 if (
index->tuples > 1)
8247 Cost *indexStartupCost,
Cost *indexTotalCost,
8248 Selectivity *indexSelectivity,
double *indexCorrelation,
8266 if (
index->tree_height < 0)
8268 if (
index->pages > 1)
8269 index->tree_height = (int) (log(
index->pages) / log(100.0));
8271 index->tree_height = 0;
8279 if (
index->tuples > 1)
8332 bool *partial_matches = NULL;
8334 bool *nullFlags = NULL;
8338 Assert(indexcol < index->nkeycolumns);
8347 &strategy_op, &lefttype, &righttype);
8355 index->opcintype[indexcol],
8356 index->opcintype[indexcol],
8362 elog(
ERROR,
"missing support function %d for attribute %d of index \"%s\"",
8371 collation =
index->indexcollations[indexcol];
8373 collation = DEFAULT_COLLATION_OID;
8395 for (
i = 0;
i < nentries;
i++)
8401 if (partial_matches && partial_matches[
i])
8463 if (((
Const *) operand)->constisnull)
8468 ((
Const *) operand)->constvalue,
8489 double numIndexEntries,
8502 int numPossible = 0;
8528 if (((
Const *) rightop)->constisnull)
8534 &elmlen, &elmbyval, &elmalign);
8537 elmlen, elmbyval, elmalign,
8538 &elemValues, &elemNulls, &numElems);
8540 memset(&arraycounts, 0,
sizeof(arraycounts));
8542 for (
i = 0;
i < numElems;
i++)
8551 memset(&elemcounts, 0,
sizeof(elemcounts));
8577 if (numPossible == 0)
8602 Cost *indexStartupCost,
Cost *indexTotalCost,
8603 Selectivity *indexSelectivity,
double *indexCorrelation,
8608 List *selectivityQuals;
8609 double numPages =
index->pages,
8610 numTuples =
index->tuples;
8611 double numEntryPages,
8618 double partialScale;
8619 double entryPagesFetched,
8621 dataPagesFetchedBySel;
8622 double qual_op_cost,
8624 spc_random_page_cost,
8636 if (!
index->hypothetical)
8645 memset(&ginStats, 0,
sizeof(ginStats));
8662 numPendingPages = 0;
8664 if (numPages > 0 && ginStats.
nTotalPages <= numPages &&
8679 numEntryPages =
Min(numEntryPages, numPages - numPendingPages);
8680 numDataPages =
Min(numDataPages,
8681 numPages - numPendingPages - numEntryPages);
8698 numPages =
Max(numPages, 10);
8699 numEntryPages = floor((numPages - numPendingPages) * 0.90);
8700 numDataPages = numPages - numPendingPages - numEntryPages;
8701 numEntries = floor(numEntryPages * 100);
8723 &spc_random_page_cost,
8729 *indexCorrelation = 0.0;
8734 memset(&counts, 0,
sizeof(counts));
8736 matchPossible =
true;
8772 elog(
ERROR,
"unsupported GIN indexqual type: %d",
8781 *indexStartupCost = 0;
8782 *indexTotalCost = 0;
8783 *indexSelectivity = 0;
8793 fullIndexScan =
false;
8794 for (
i = 0;
i <
index->nkeycolumns;
i++)
8798 fullIndexScan =
true;
8803 if (fullIndexScan || indexQuals ==
NIL)
8815 outer_scans = loop_count;
8821 entryPagesFetched = numPendingPages;
8830 entryPagesFetched += ceil(counts.
searchEntries * rint(pow(numEntryPages, 0.15)));
8840 partialScale =
Min(partialScale, 1.0);
8842 entryPagesFetched += ceil(numEntryPages * partialScale);
8849 dataPagesFetched = ceil(numDataPages * partialScale);
8851 *indexStartupCost = 0;
8852 *indexTotalCost = 0;
8897 if (outer_scans > 1 || counts.
arrayScans > 1)
8899 entryPagesFetched *= outer_scans * counts.
arrayScans;
8902 numEntryPages,
root);
8903 entryPagesFetched /= outer_scans;
8904 dataPagesFetched *= outer_scans * counts.
arrayScans;
8907 numDataPages,
root);
8908 dataPagesFetched /= outer_scans;
8915 *indexStartupCost += (entryPagesFetched + dataPagesFetched) * spc_random_page_cost;
8925 dataPagesFetched = ceil(numDataPages * counts.
exactEntries / numEntries);
8938 dataPagesFetchedBySel = ceil(*indexSelectivity *
8939 (numTuples / (BLCKSZ / 3)));
8940 if (dataPagesFetchedBySel > dataPagesFetched)
8941 dataPagesFetched = dataPagesFetchedBySel;
8953 if (outer_scans > 1 || counts.
arrayScans > 1)
8955 dataPagesFetched *= outer_scans * counts.
arrayScans;
8958 numDataPages,
root);
8959 dataPagesFetched /= outer_scans;
8963 *indexTotalCost += *indexStartupCost +
8964 dataPagesFetched * spc_random_page_cost;
8974 *indexStartupCost += qual_arg_cost;
8975 *indexTotalCost += qual_arg_cost;
8984 *indexPages = dataPagesFetched;
8992 Cost *indexStartupCost,
Cost *indexTotalCost,
8993 Selectivity *indexSelectivity,
double *indexCorrelation,
8998 double numPages =
index->pages;
9001 Cost spc_seq_page_cost;
9002 Cost spc_random_page_cost;
9003 double qual_arg_cost;
9004 double qualSelectivity;
9007 double minimalRanges;
9008 double estimatedRanges;
9018 &spc_random_page_cost,
9019 &spc_seq_page_cost);
9025 if (!
index->hypothetical)
9035 indexRanges =
Max(ceil((
double) baserel->
pages /
9044 indexRanges =
Max(ceil((
double) baserel->
pages /
9059 *indexCorrelation = 0;
9079 "no function provided to release variable stats with");
9110 elog(
ERROR,
"no function provided to release variable stats with");
9130 double varCorrelation = 0.0;
9133 varCorrelation = fabs(sslot.
numbers[0]);
9135 if (varCorrelation > *indexCorrelation)
9136 *indexCorrelation = varCorrelation;
9153 minimalRanges = ceil(indexRanges * qualSelectivity);
9160 if (*indexCorrelation < 1.0e-10)
9161 estimatedRanges = indexRanges;
9163 estimatedRanges =
Min(minimalRanges / *indexCorrelation, indexRanges);
9166 selec = estimatedRanges / indexRanges;
9170 *indexSelectivity = selec;
9185 *indexStartupCost += qual_arg_cost;
9192 *indexTotalCost = *indexStartupCost +
9193 spc_random_page_cost * (numPages - statsData.
revmapNumPages) * loop_count;
9205 *indexPages =
index->pages;
Datum idx(PG_FUNCTION_ARGS)
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
StrategyNumber IndexAmTranslateCompareType(CompareType cmptype, Oid amoid, Oid opfamily, bool missing_ok)
CompareType IndexAmTranslateStrategy(StrategyNumber strategy, Oid amoid, Oid opfamily, bool missing_ok)
#define DatumGetArrayTypeP(X)
Selectivity scalararraysel_containment(PlannerInfo *root, Node *leftop, Node *rightop, Oid elemtype, bool isEquality, bool useOr, int varRelid)
void deconstruct_array(const ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
int ArrayGetNItems(int ndim, const int *dims)
#define AttrNumberIsForUserDefinedAttr(attributeNumber)
#define InvalidAttrNumber
Datum numeric_float8_no_overflow(PG_FUNCTION_ARGS)
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_make_singleton(int x)
int bms_next_member(const Bitmapset *a, int prevbit)
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
void bms_free(Bitmapset *a)
int bms_num_members(const Bitmapset *a)
bool bms_is_member(int x, const Bitmapset *a)
Bitmapset * bms_add_member(Bitmapset *a, int x)
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
bool bms_get_singleton_member(const Bitmapset *a, int *member)
#define InvalidBlockNumber
static Datum values[MAXATTR]
void brinGetStats(Relation index, BrinStatsData *stats)
#define BRIN_DEFAULT_PAGES_PER_RANGE
#define REVMAP_PAGE_MAXITEMS
void ReleaseBuffer(Buffer buffer)
#define TextDatumGetCString(d)
#define PG_USED_FOR_ASSERTS_ONLY
#define MemSet(start, val, len)
#define OidIsValid(objectId)
int NumRelids(PlannerInfo *root, Node *clause)
Node * estimate_expression_value(PlannerInfo *root, Node *node)
bool contain_volatile_functions(Node *clause)
double expression_returns_set_rows(PlannerInfo *root, Node *clause)
Selectivity clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Selectivity clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
double index_pages_fetched(double tuples_fetched, BlockNumber pages, double index_pages, PlannerInfo *root)
void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
double clamp_row_est(double nrows)
double cpu_index_tuple_cost
double date2timestamp_no_overflow(DateADT dateVal)
static TimeTzADT * DatumGetTimeTzADTP(Datum X)
static DateADT DatumGetDateADT(Datum X)
static TimeADT DatumGetTimeADT(Datum X)
Datum datumCopy(Datum value, bool typByVal, int typLen)
bool datum_image_eq(Datum value1, Datum value2, bool typByVal, int typLen)
int errmsg_internal(const char *fmt,...)
#define ereport(elevel,...)
bool equal(const void *a, const void *b)
bool exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2, Oid opfamily)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
HeapTuple statext_expressions_load(Oid stxoid, bool inh, int idx)
#define palloc_object(type)
#define palloc0_object(type)
Datum FunctionCall4Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4)
void set_fn_opclass_options(FmgrInfo *flinfo, bytea *options)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Datum FunctionCall5Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5)
Datum DirectFunctionCall5Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5)
Datum FunctionCall7Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7)
#define DatumGetByteaPP(X)
#define PG_RETURN_FLOAT8(x)
#define PG_GETARG_POINTER(n)
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
#define DirectFunctionCall1(func, arg1)
#define LOCAL_FCINFO(name, nargs)
#define FunctionCallInvoke(fcinfo)
#define PG_GETARG_INT32(n)
#define PG_GET_COLLATION()
#define PG_GETARG_INT16(n)
#define GIN_EXTRACTQUERY_PROC
#define GIN_SEARCH_MODE_DEFAULT
#define GIN_SEARCH_MODE_INCLUDE_EMPTY
void ginGetStats(Relation index, GinStatsData *stats)
Assert(PointerIsAligned(start, uint64))
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, Snapshot snapshot, IndexScanInstrumentation *instrument, int nkeys, int norderbys)
void index_close(Relation relation, LOCKMODE lockmode)
ItemPointer index_getnext_tid(IndexScanDesc scan, ScanDirection direction)
bool index_fetch_heap(IndexScanDesc scan, TupleTableSlot *slot)
void index_endscan(IndexScanDesc scan)
Relation index_open(Oid relationId, LOCKMODE lockmode)
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
void index_deform_tuple(IndexTuple tup, TupleDesc tupleDescriptor, Datum *values, bool *isnull)
bool match_index_to_operand(Node *operand, int indexcol, IndexOptInfo *index)
if(TABLE==NULL||TABLE_index==NULL)
static OffsetNumber ItemPointerGetOffsetNumberNoCheck(const ItemPointerData *pointer)
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
static BlockNumber ItemPointerGetBlockNumberNoCheck(const ItemPointerData *pointer)
ItemPointerData * ItemPointer
List * lappend(List *list, void *datum)
List * list_concat(List *list1, const List *list2)
List * list_copy(const List *oldlist)
bool list_member_ptr(const List *list, const void *datum)
void list_free(List *list)
bool list_member_int(const List *list, int datum)
void list_free_deep(List *list)
char * get_rel_name(Oid relid)
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
RegProcedure get_oprrest(Oid opno)
void free_attstatsslot(AttStatsSlot *sslot)
bool comparison_ops_are_compatible(Oid opno1, Oid opno2)
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
RegProcedure get_oprjoin(Oid opno)
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
RegProcedure get_opcode(Oid opno)
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
bool get_func_leakproof(Oid funcid)
char * get_func_name(Oid funcid)
Oid get_base_element_type(Oid typid)
Oid get_opfamily_method(Oid opfid)
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
bool get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple, int reqkind, Oid reqop, int flags)
Oid get_negator(Oid opno)
Oid get_commutator(Oid opno)
#define ATTSTATSSLOT_NUMBERS
#define ATTSTATSSLOT_VALUES
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
char * pstrdup(const char *in)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
MVNDistinct * statext_ndistinct_load(Oid mvoid, bool inh)
double convert_network_to_scalar(Datum value, Oid typid, bool *failure)
Size hash_agg_entry_size(int numTrans, Size tupleWidth, Size transitionSpace)
Oid exprType(const Node *expr)
int32 exprTypmod(const Node *expr)
Oid exprCollation(const Node *expr)
#define expression_tree_mutator(n, m, c)
static Node * get_rightop(const void *clause)
static bool is_opclause(const void *clause)
static bool is_funcclause(const void *clause)
#define expression_tree_walker(n, w, c)
static Node * get_leftop(const void *clause)
#define IsA(nodeptr, _type_)
#define PVC_RECURSE_AGGREGATES
#define PVC_RECURSE_PLACEHOLDERS
#define PVC_RECURSE_WINDOWFUNCS
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
bool targetIsInSortList(TargetEntry *tle, Oid sortop, List *sortList)
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
#define IS_SIMPLE_REL(rel)
#define planner_rt_fetch(rti, root)
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define forboth(cell1, list1, cell2, list2)
#define foreach_delete_current(lst, var_or_cell)
#define for_each_from(cell, lst, N)
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_make2(x1, x2)
static int list_nth_int(const List *list, int n)
pg_locale_t pg_newlocale_from_collation(Oid collid)
size_t pg_strxfrm(char *dest, const char *src, size_t destsize, pg_locale_t locale)
FormData_pg_statistic * Form_pg_statistic
Selectivity restriction_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, int varRelid)
bool has_unique_index(RelOptInfo *rel, AttrNumber attno)
Selectivity join_selectivity(PlannerInfo *root, Oid operatorid, List *args, Oid inputcollid, JoinType jointype, SpecialJoinInfo *sjinfo)
static uint32 DatumGetUInt32(Datum X)
static bool DatumGetBool(Datum X)
static int64 DatumGetInt64(Datum X)
static Datum PointerGetDatum(const void *X)
static float4 DatumGetFloat4(Datum X)
static Oid DatumGetObjectId(Datum X)
static Datum Int16GetDatum(int16 X)
static Datum UInt16GetDatum(uint16 X)
static Datum BoolGetDatum(bool X)
static float8 DatumGetFloat8(Datum X)
static Datum ObjectIdGetDatum(Oid X)
static Pointer DatumGetPointer(Datum X)
static char DatumGetChar(Datum X)
static Datum Int32GetDatum(int32 X)
static int16 DatumGetInt16(Datum X)
static int32 DatumGetInt32(Datum X)
bool predicate_implied_by(List *predicate_list, List *clause_list, bool weak)
GlobalVisState * GlobalVisTestFor(Relation rel)
#define RelationGetRelationName(relation)
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
RelOptInfo * find_base_rel_noerr(PlannerInfo *root, int relid)
RelOptInfo * find_join_rel(PlannerInfo *root, Relids relids)
Node * remove_nulling_relids(Node *node, const Bitmapset *removable_relids, const Bitmapset *except_relids)
void ScanKeyEntryInitialize(ScanKey entry, int flags, AttrNumber attributeNumber, StrategyNumber strategy, Oid subtype, Oid collation, RegProcedure procedure, Datum argument)
static bool get_actual_variable_endpoint(Relation heapRel, Relation indexRel, ScanDirection indexscandir, ScanKey scankeys, int16 typLen, bool typByVal, TupleTableSlot *tableslot, MemoryContext outercontext, Datum *endpointDatum)
bool get_restriction_variable(PlannerInfo *root, List *args, int varRelid, VariableStatData *vardata, Node **other, bool *varonleft)
Datum neqsel(PG_FUNCTION_ARGS)
static RelOptInfo * find_join_input_rel(PlannerInfo *root, Relids relids)
void mergejoinscansel(PlannerInfo *root, Node *clause, Oid opfamily, CompareType cmptype, bool nulls_first, Selectivity *leftstart, Selectivity *leftend, Selectivity *rightstart, Selectivity *rightend)
bool all_rows_selectable(PlannerInfo *root, Index varno, Bitmapset *varattnos)
static Node * strip_all_phvs_mutator(Node *node, void *context)
static bool get_variable_range(PlannerInfo *root, VariableStatData *vardata, Oid sortop, Oid collation, Datum *min, Datum *max)
void btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
List * get_quals_from_indexclauses(List *indexclauses)
static void convert_string_to_scalar(char *value, double *scaledvalue, char *lobound, double *scaledlobound, char *hibound, double *scaledhibound)
double var_eq_const(VariableStatData *vardata, Oid oproid, Oid collation, Datum constval, bool constisnull, bool varonleft, bool negate)
List * add_predicate_to_index_quals(IndexOptInfo *index, List *indexQuals)
double generic_restriction_selectivity(PlannerInfo *root, Oid oproid, Oid collation, List *args, int varRelid, double default_selectivity)
#define VISITED_PAGES_LIMIT
void spgcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
static double eqjoinsel_inner(FmgrInfo *eqproc, Oid collation, Oid hashLeft, Oid hashRight, VariableStatData *vardata1, VariableStatData *vardata2, double nd1, double nd2, bool isdefault1, bool isdefault2, AttStatsSlot *sslot1, AttStatsSlot *sslot2, Form_pg_statistic stats1, Form_pg_statistic stats2, bool have_mcvs1, bool have_mcvs2, bool *hasmatch1, bool *hasmatch2, int *p_nmatches)
Datum scalargtsel(PG_FUNCTION_ARGS)
#define DEFAULT_PAGE_CPU_MULTIPLIER
static bool estimate_multivariate_ndistinct(PlannerInfo *root, RelOptInfo *rel, List **varinfos, double *ndistinct)
Selectivity booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Datum eqjoinsel(PG_FUNCTION_ARGS)
double estimate_array_length(PlannerInfo *root, Node *arrayexpr)
double mcv_selectivity(VariableStatData *vardata, FmgrInfo *opproc, Oid collation, Datum constval, bool varonleft, double *sumcommonp)
Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype, Node *arg, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
static void examine_simple_variable(PlannerInfo *root, Var *var, VariableStatData *vardata)
static List * add_unique_group_var(PlannerInfo *root, List *varinfos, Node *var, VariableStatData *vardata)
Datum matchingsel(PG_FUNCTION_ARGS)
Datum eqsel(PG_FUNCTION_ARGS)
static bool mcvs_equal(MCVHashTable_hash *tab, Datum key0, Datum key1)
void examine_variable(PlannerInfo *root, Node *node, int varRelid, VariableStatData *vardata)
Datum scalargtjoinsel(PG_FUNCTION_ARGS)
static double convert_one_string_to_scalar(char *value, int rangelo, int rangehi)
static Datum scalarineqsel_wrapper(PG_FUNCTION_ARGS, bool isgt, bool iseq)
static Node * strip_all_phvs_deep(PlannerInfo *root, Node *node)
void gincostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
static void eqjoinsel_find_matches(FmgrInfo *eqproc, Oid collation, Oid hashLeft, Oid hashRight, bool op_is_reversed, AttStatsSlot *sslot1, AttStatsSlot *sslot2, int nvalues1, int nvalues2, bool *hasmatch1, bool *hasmatch2, int *p_nmatches, double *p_matchprodfreq)
static double convert_timevalue_to_scalar(Datum value, Oid typid, bool *failure)
static double convert_numeric_to_scalar(Datum value, Oid typid, bool *failure)
#define EQJOINSEL_MCV_HASH_THRESHOLD
static Node * strip_array_coercion(Node *node)
double estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows, List **pgset, EstimationInfo *estinfo)
static bool convert_to_scalar(Datum value, Oid valuetypid, Oid collid, double *scaledvalue, Datum lobound, Datum hibound, Oid boundstypid, double *scaledlobound, double *scaledhibound)
double ineq_histogram_selectivity(PlannerInfo *root, VariableStatData *vardata, Oid opoid, FmgrInfo *opproc, bool isgt, bool iseq, Oid collation, Datum constval, Oid consttype)
void genericcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, GenericCosts *costs)
List * estimate_multivariate_bucketsize(PlannerInfo *root, RelOptInfo *inner, List *hashclauses, Selectivity *innerbucketsize)
Datum scalarltjoinsel(PG_FUNCTION_ARGS)
static bool gincost_pattern(IndexOptInfo *index, int indexcol, Oid clause_op, Datum query, GinQualCounts *counts)
static bool contain_placeholder_walker(Node *node, void *context)
struct MCVHashTable_hash MCVHashTable_hash
void brincostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
void gistcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
Datum scalargejoinsel(PG_FUNCTION_ARGS)
static double eqjoinsel_semi(FmgrInfo *eqproc, Oid collation, Oid hashLeft, Oid hashRight, bool op_is_reversed, VariableStatData *vardata1, VariableStatData *vardata2, double nd1, double nd2, bool isdefault1, bool isdefault2, AttStatsSlot *sslot1, AttStatsSlot *sslot2, Form_pg_statistic stats1, Form_pg_statistic stats2, bool have_mcvs1, bool have_mcvs2, bool *hasmatch1, bool *hasmatch2, int *p_nmatches, RelOptInfo *inner_rel)
get_index_stats_hook_type get_index_stats_hook
Datum matchingjoinsel(PG_FUNCTION_ARGS)
static bool gincost_scalararrayopexpr(PlannerInfo *root, IndexOptInfo *index, int indexcol, ScalarArrayOpExpr *clause, double numIndexEntries, GinQualCounts *counts)
struct MCVHashEntry MCVHashEntry
double histogram_selectivity(VariableStatData *vardata, FmgrInfo *opproc, Oid collation, Datum constval, bool varonleft, int min_hist_size, int n_skip, int *hist_size)
static uint32 hash_mcv(MCVHashTable_hash *tab, Datum key)
Selectivity boolvarsel(PlannerInfo *root, Node *arg, int varRelid)
static void examine_indexcol_variable(PlannerInfo *root, IndexOptInfo *index, int indexcol, VariableStatData *vardata)
struct MCVHashContext MCVHashContext
Datum scalarlesel(PG_FUNCTION_ARGS)
Datum scalargesel(PG_FUNCTION_ARGS)
static double scalarineqsel(PlannerInfo *root, Oid operator, bool isgt, bool iseq, Oid collation, VariableStatData *vardata, Datum constval, Oid consttype)
static double convert_one_bytea_to_scalar(unsigned char *value, int valuelen, int rangelo, int rangehi)
Selectivity scalararraysel(PlannerInfo *root, ScalarArrayOpExpr *clause, bool is_join_clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Datum scalarltsel(PG_FUNCTION_ARGS)
static double btcost_correlation(IndexOptInfo *index, VariableStatData *vardata)
double var_eq_non_const(VariableStatData *vardata, Oid oproid, Oid collation, Node *other, bool varonleft, bool negate)
static bool get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata, Oid sortop, Oid collation, Datum *min, Datum *max)
Datum scalarlejoinsel(PG_FUNCTION_ARGS)
double get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
bool statistic_proc_security_check(VariableStatData *vardata, Oid func_oid)
void hashcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
Datum neqjoinsel(PG_FUNCTION_ARGS)
double estimate_hashagg_tablesize(PlannerInfo *root, Path *path, const AggClauseCosts *agg_costs, double dNumGroups)
void estimate_hash_bucket_stats(PlannerInfo *root, Node *hashkey, double nbuckets, Selectivity *mcv_freq, Selectivity *bucketsize_frac)
static void convert_bytea_to_scalar(Datum value, double *scaledvalue, Datum lobound, double *scaledlobound, Datum hibound, double *scaledhibound)
Cost index_other_operands_eval_cost(PlannerInfo *root, List *indexquals)
get_relation_stats_hook_type get_relation_stats_hook
Selectivity rowcomparesel(PlannerInfo *root, RowCompareExpr *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
static bool gincost_opexpr(PlannerInfo *root, IndexOptInfo *index, int indexcol, OpExpr *clause, GinQualCounts *counts)
static void ReleaseDummy(HeapTuple tuple)
static char * convert_string_datum(Datum value, Oid typid, Oid collid, bool *failure)
static double eqsel_internal(PG_FUNCTION_ARGS, bool negate)
static void get_stats_slot_range(AttStatsSlot *sslot, Oid opfuncoid, FmgrInfo *opproc, Oid collation, int16 typLen, bool typByVal, Datum *min, Datum *max, bool *p_have_data)
void get_join_variables(PlannerInfo *root, List *args, SpecialJoinInfo *sjinfo, VariableStatData *vardata1, VariableStatData *vardata2, bool *join_is_reversed)
#define DEFAULT_NOT_UNK_SEL
#define ReleaseVariableStats(vardata)
#define CLAMP_PROBABILITY(p)
bool(* get_relation_stats_hook_type)(PlannerInfo *root, RangeTblEntry *rte, AttrNumber attnum, VariableStatData *vardata)
#define DEFAULT_RANGE_INEQ_SEL
bool(* get_index_stats_hook_type)(PlannerInfo *root, Oid indexOid, AttrNumber indexattnum, VariableStatData *vardata)
#define DEFAULT_MATCHING_SEL
#define DEFAULT_NUM_DISTINCT
#define SELFLAG_USED_DEFAULT
#define InitNonVacuumableSnapshot(snapshotdata, vistestp)
void get_tablespace_page_costs(Oid spcid, double *spc_random_page_cost, double *spc_seq_page_cost)
#define BTLessStrategyNumber
#define BTEqualStrategyNumber
BlockNumber revmapNumPages
BlockNumber pagesPerRange
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Selectivity indexSelectivity
double spc_random_page_cost
bool attHasNormalScan[INDEX_MAX_KEYS]
bool attHasFullScan[INDEX_MAX_KEYS]
BlockNumber nPendingPages
struct TupleDescData * xs_itupdesc
FunctionCallInfo hash_fcinfo
FunctionCallInfo equal_fcinfo
MVNDistinctItem items[FLEXIBLE_ARRAY_MEMBER]
NullTestType nulltesttype
void(* freefunc)(HeapTuple tuple)
#define FirstLowInvalidHeapAttributeNumber
#define TableOidAttributeNumber
#define SelfItemPointerAttributeNumber
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
static Interval * DatumGetIntervalP(Datum X)
static Timestamp DatumGetTimestamp(Datum X)
static TimestampTz DatumGetTimestampTz(Datum X)
Relids pull_varnos(PlannerInfo *root, Node *node)
List * pull_var_clause(Node *node, int flags)
static Size VARSIZE_ANY_EXHDR(const void *PTR)
static char * VARDATA_ANY(const void *PTR)
#define VM_ALL_VISIBLE(r, b, v)