36#include "utils/fmgroids.h"
88#define compare_range_bounds(partnatts, partsupfunc, partcollations, \
90 (partition_rbound_cmp(partnatts, partsupfunc, partcollations, \
91 (bound1)->datums, (bound1)->kind, (bound1)->lower, \
130 bool outer_has_default,
131 bool inner_has_default,
139 bool outer_has_default,
140 bool inner_has_default,
157 bool outer_has_default,
158 bool inner_has_default,
168 int nmerged,
List *merged_indexes);
179 List *merged_indexes,
197 int *lb_cmpval,
int *ub_cmpval);
204 int lb_cmpval,
int ub_cmpval,
212 List **merged_datums,
214 List **merged_indexes);
256 switch (
key->strategy)
323 for (
i = 0;
i < nparts;
i++)
326 switch (
key->strategy)
353 int greatest_modulus;
365 for (
i = 0;
i < nparts;
i++)
370 elog(
ERROR,
"invalid strategy in partition bound spec");
382 greatest_modulus = hbounds[nparts - 1].
modulus;
386 boundinfo->
kind = NULL;
388 boundinfo->
nindexes = greatest_modulus;
389 boundinfo->
indexes = (
int *)
palloc(greatest_modulus *
sizeof(
int));
390 for (
i = 0;
i < greatest_modulus;
i++)
405 for (
i = 0;
i < nparts;
i++)
410 boundinfo->
datums[
i] = &boundDatums[
i * 2];
422 (*mapping)[hbounds[
i].
index] =
i;
439 for (
i = 0;
i < nparts;
i++)
443 foreach(lc, boundspecs[
i]->listdatums)
447 if (!
val->constisnull)
469 int default_index = -1;
484 for (
j = 0,
i = 0;
i < nparts;
i++)
490 elog(
ERROR,
"invalid strategy in partition bound spec");
507 if (!
val->constisnull)
519 if (null_index != -1)
520 elog(
ERROR,
"found null more than once");
534 boundinfo->
kind = NULL;
552 for (
i = 0;
i < ndatums;
i++)
554 int orig_index = all_values[
i].
index;
556 boundinfo->
datums[
i] = &boundDatums[
i];
558 key->parttypbyval[0],
562 if ((*mapping)[orig_index] == -1)
563 (*mapping)[orig_index] = next_index++;
565 boundinfo->
indexes[
i] = (*mapping)[orig_index];
578 if (null_index != -1)
581 if ((*mapping)[null_index] == -1)
582 (*mapping)[null_index] = next_index++;
583 boundinfo->
null_index = (*mapping)[null_index];
587 if (default_index != -1)
594 Assert(default_index >= 0);
595 Assert((*mapping)[default_index] == -1);
596 (*mapping)[default_index] = next_index++;
634 if (
index < last_index)
665 Assert(next_index == nparts);
685 int default_index = -1;
701 for (
i = 0;
i < nparts;
i++)
708 elog(
ERROR,
"invalid strategy in partition bound spec");
723 all_bounds[ndatums++] =
lower;
724 all_bounds[ndatums++] =
upper;
727 Assert(ndatums == nparts * 2 ||
728 (default_index != -1 && ndatums == (nparts - 1) * 2));
741 for (
i = 0;
i < ndatums;
i++)
744 bool is_distinct =
false;
748 for (
j = 0;
j <
key->partnatts;
j++)
752 if (prev == NULL ||
cur->kind[
j] != prev->
kind[
j])
767 key->partcollation[
j],
782 rbounds[k++] = all_bounds[
i];
818 partnatts =
key->partnatts;
822 for (
i = 0;
i < ndatums;
i++)
826 boundinfo->
datums[
i] = &boundDatums[
i * partnatts];
827 boundinfo->
kind[
i] = &boundKinds[
i * partnatts];
828 for (
j = 0;
j < partnatts;
j++)
833 key->parttypbyval[
j],
850 int orig_index = rbounds[
i]->
index;
853 if ((*mapping)[orig_index] == -1)
854 (*mapping)[orig_index] = next_index++;
856 boundinfo->
indexes[
i] = (*mapping)[orig_index];
863 if (default_index != -1)
865 Assert(default_index >= 0 && (*mapping)[default_index] == -1);
866 (*mapping)[default_index] = next_index++;
875 Assert(next_index == nparts);
933#ifdef USE_ASSERT_CHECKING
945 for (
j = 0;
j < partnatts;
j++)
948 if (b1->
kind != NULL)
976 parttypbyval[
j], parttyplen[
j]))
1008 partnatts =
key->partnatts;
1015 if (src->
kind != NULL && ndatums > 0)
1033 for (
i = 0;
i < ndatums;
i++)
1035 dest->kind[
i] = &boundKinds[
i * partnatts];
1053 int natts = hash_part ? 2 : partnatts;
1056 for (
i = 0;
i < ndatums;
i++)
1060 dest->datums[
i] = &boundDatums[
i * natts];
1062 for (
j = 0;
j < natts;
j++)
1064 if (
dest->kind == NULL ||
1072 typlen =
sizeof(
int32);
1077 byval =
key->parttypbyval[
j];
1078 typlen =
key->parttyplen[
j];
1088 memcpy(
dest->indexes, src->
indexes,
sizeof(
int) * nindexes);
1115 List **outer_parts,
List **inner_parts)
1126 Assert(outer_rel->boundinfo->strategy == inner_rel->boundinfo->strategy);
1128 *outer_parts = *inner_parts =
NIL;
1129 switch (outer_rel->boundinfo->strategy)
1194 List **outer_parts,
List **inner_parts)
1210 int null_index = -1;
1211 int default_index = -1;
1230 outer_has_default =
false;
1232 inner_has_default =
false;
1241 outer_pos = inner_pos = 0;
1242 while (outer_pos < outer_bi->ndatums || inner_pos < inner_bi->ndatums)
1244 int outer_index = -1;
1245 int inner_index = -1;
1246 Datum *outer_datums;
1247 Datum *inner_datums;
1249 Datum *merged_datum = NULL;
1250 int merged_index = -1;
1252 if (outer_pos < outer_bi->ndatums)
1258 outer_index = outer_bi->
indexes[outer_pos];
1265 if (inner_pos < inner_bi->ndatums)
1271 inner_index = inner_bi->
indexes[inner_pos];
1280 outer_datums = outer_pos < outer_bi->
ndatums ?
1281 outer_bi->
datums[outer_pos] : NULL;
1282 inner_datums = inner_pos < inner_bi->
ndatums ?
1283 inner_bi->
datums[inner_pos] : NULL;
1294 if (outer_pos >= outer_bi->
ndatums)
1296 else if (inner_pos >= inner_bi->
ndatums)
1300 Assert(outer_datums != NULL && inner_datums != NULL);
1310 Assert(outer_pos < outer_bi->ndatums);
1311 Assert(inner_pos < inner_bi->ndatums);
1312 Assert(outer_index >= 0);
1313 Assert(inner_index >= 0);
1320 outer_index, inner_index,
1322 if (merged_index == -1)
1325 merged_datum = outer_datums;
1331 else if (cmpval < 0)
1334 Assert(outer_pos < outer_bi->ndatums);
1345 outer_index = outer_bi->
indexes[outer_pos];
1346 Assert(outer_index >= 0);
1356 if (merged_index == -1)
1358 merged_datum = outer_datums;
1368 Assert(inner_pos < inner_bi->ndatums);
1376 if (outer_has_default || jointype ==
JOIN_FULL)
1379 inner_index = inner_bi->
indexes[inner_pos];
1380 Assert(inner_index >= 0);
1390 if (merged_index == -1)
1392 merged_datum = inner_datums;
1403 if (merged_index >= 0 && merged_index != default_index)
1405 merged_datums =
lappend(merged_datums, merged_datum);
1406 merged_indexes =
lappend_int(merged_indexes, merged_index);
1414 if (outer_has_null &&
1416 outer_has_null =
false;
1417 if (inner_has_null &&
1419 inner_has_null =
false;
1422 if (outer_has_null || inner_has_null)
1424 outer_has_null, inner_has_null,
1426 jointype, &next_index, &null_index);
1428 Assert(null_index == -1);
1431 if (outer_has_default || inner_has_default)
1433 outer_has_default, inner_has_default,
1434 outer_default, inner_default,
1435 jointype, &next_index, &default_index);
1437 Assert(default_index == -1);
1447 next_index, merged_indexes);
1452 &outer_map, &inner_map,
1454 outer_parts, inner_parts);
1477 return merged_bounds;
1500 Oid *partcollations,
1503 List **outer_parts,
List **inner_parts)
1523 int default_index = -1;
1541 outer_has_default =
false;
1543 inner_has_default =
false;
1554 outer_lb_pos = inner_lb_pos = 0;
1556 &outer_lb, &outer_ub);
1558 &inner_lb, &inner_ub);
1559 while (outer_index >= 0 || inner_index >= 0)
1566 int merged_index = -1;
1577 if (outer_index == -1)
1583 else if (inner_index == -1)
1592 &outer_lb, &outer_ub,
1593 &inner_lb, &inner_ub,
1594 &lb_cmpval, &ub_cmpval);
1604 Assert(outer_index >= 0);
1606 outer_map.
merged[outer_index] ==
false);
1607 Assert(inner_index >= 0);
1609 inner_map.
merged[inner_index] ==
false);
1616 outer_index, inner_index,
1618 Assert(merged_index >= 0);
1622 partcollations, jointype,
1623 &outer_lb, &outer_ub,
1624 &inner_lb, &inner_ub,
1625 lb_cmpval, ub_cmpval,
1626 &merged_lb, &merged_ub);
1629 save_outer_ub = outer_ub;
1630 save_inner_ub = inner_ub;
1634 &outer_lb, &outer_ub);
1636 &inner_lb, &inner_ub);
1645 if (ub_cmpval > 0 && inner_index >= 0 &&
1647 &save_outer_ub, &inner_lb) > 0)
1649 if (ub_cmpval < 0 && outer_index >= 0 &&
1651 &outer_lb, &save_inner_ub) < 0)
1660 if ((outer_has_default && (lb_cmpval > 0 || ub_cmpval < 0)) ||
1661 (inner_has_default && (lb_cmpval < 0 || ub_cmpval > 0)))
1664 else if (ub_cmpval < 0)
1669 Assert(outer_index >= 0);
1671 outer_map.
merged[outer_index] ==
false);
1690 if (merged_index == -1)
1692 merged_lb = outer_lb;
1693 merged_ub = outer_ub;
1698 &outer_lb, &outer_ub);
1706 Assert(inner_index >= 0);
1708 inner_map.
merged[inner_index] ==
false);
1716 if (outer_has_default || jointype ==
JOIN_FULL)
1727 if (merged_index == -1)
1729 merged_lb = inner_lb;
1730 merged_ub = inner_ub;
1735 &inner_lb, &inner_ub);
1742 if (merged_index >= 0 && merged_index != default_index)
1744 &merged_lb, &merged_ub, merged_index,
1745 &merged_datums, &merged_kinds,
1750 if (outer_has_default || inner_has_default)
1752 outer_has_default, inner_has_default,
1753 outer_default, inner_default,
1754 jointype, &next_index, &default_index);
1756 Assert(default_index == -1);
1770 &outer_map, &inner_map,
1772 outer_parts, inner_parts);
1796 return merged_bounds;
1806 int nparts = rel->
nparts;
1814 for (
i = 0;
i < nparts;
i++)
1841 part_rel = rel->part_rels[part_index];
1856 int outer_index,
int inner_index,
int *next_index)
1858 int outer_merged_index;
1859 int inner_merged_index;
1863 Assert(outer_index >= 0 && outer_index < outer_map->nparts);
1865 outer_merged = outer_map->
merged[outer_index];
1866 Assert(inner_index >= 0 && inner_index < inner_map->nparts);
1868 inner_merged = inner_map->
merged[inner_index];
1874 if (outer_merged_index >= 0 && inner_merged_index >= 0)
1883 if (outer_merged_index == inner_merged_index)
1887 return outer_merged_index;
1889 if (!outer_merged && !inner_merged)
1898 if (outer_merged_index < inner_merged_index)
1900 outer_map->
merged[outer_index] =
true;
1902 inner_map->
merged[inner_index] =
true;
1904 inner_map->
old_indexes[inner_index] = inner_merged_index;
1905 return outer_merged_index;
1909 inner_map->
merged[inner_index] =
true;
1911 outer_map->
merged[outer_index] =
true;
1913 outer_map->
old_indexes[outer_index] = outer_merged_index;
1914 return inner_merged_index;
1921 Assert(outer_merged_index == -1 || inner_merged_index == -1);
1929 if (outer_merged_index == -1 && inner_merged_index == -1)
1931 int merged_index = *next_index;
1936 outer_map->
merged[outer_index] =
true;
1938 inner_map->
merged[inner_index] =
true;
1939 *next_index = *next_index + 1;
1940 return merged_index;
1942 if (outer_merged_index >= 0 && !outer_map->
merged[outer_index])
1944 Assert(inner_merged_index == -1);
1947 inner_map->
merged[inner_index] =
true;
1948 outer_map->
merged[outer_index] =
true;
1949 return outer_merged_index;
1951 if (inner_merged_index >= 0 && !inner_map->
merged[inner_index])
1953 Assert(outer_merged_index == -1);
1956 outer_map->
merged[outer_index] =
true;
1957 inner_map->
merged[inner_index] =
true;
1958 return inner_merged_index;
1975 bool outer_has_default,
1976 bool inner_has_default,
1983 int merged_index = -1;
1985 Assert(outer_index >= 0);
1995 if (inner_has_default)
1997 Assert(inner_default >= 0);
2006 if (outer_has_default)
2010 outer_index, inner_default,
2012 if (merged_index == -1)
2025 if (*default_index == -1)
2026 *default_index = merged_index;
2028 Assert(*default_index == merged_index);
2038 if (merged_index == -1)
2042 return merged_index;
2057 bool outer_has_default,
2058 bool inner_has_default,
2065 int merged_index = -1;
2067 Assert(inner_index >= 0);
2077 if (outer_has_default)
2079 Assert(outer_default >= 0);
2088 if (inner_has_default)
2092 outer_default, inner_index,
2094 if (merged_index == -1)
2108 if (*default_index == -1)
2109 *default_index = merged_index;
2111 Assert(*default_index == merged_index);
2120 if (merged_index == -1)
2124 return merged_index;
2142 bool outer_has_null,
2143 bool inner_has_null,
2150 bool consider_outer_null =
false;
2151 bool consider_inner_null =
false;
2153 Assert(outer_has_null || inner_has_null);
2154 Assert(*null_index == -1);
2162 Assert(outer_null >= 0 && outer_null < outer_map->nparts);
2164 consider_outer_null =
true;
2168 Assert(inner_null >= 0 && inner_null < inner_map->nparts);
2170 consider_inner_null =
true;
2174 if (!consider_outer_null && !consider_inner_null)
2177 if (consider_outer_null && !consider_inner_null)
2196 else if (!consider_outer_null && consider_inner_null)
2214 Assert(consider_outer_null && consider_inner_null);
2235 outer_null, inner_null,
2237 Assert(*null_index >= 0);
2252 bool outer_has_default,
2253 bool inner_has_default,
2260 int outer_merged_index = -1;
2261 int inner_merged_index = -1;
2263 Assert(outer_has_default || inner_has_default);
2266 if (outer_has_default)
2268 Assert(outer_default >= 0 && outer_default < outer_map->nparts);
2271 if (inner_has_default)
2273 Assert(inner_default >= 0 && inner_default < inner_map->nparts);
2277 if (outer_has_default && !inner_has_default)
2290 if (outer_merged_index == -1)
2292 Assert(*default_index == -1);
2298 Assert(*default_index == outer_merged_index);
2301 Assert(*default_index == -1);
2303 else if (!outer_has_default && inner_has_default)
2315 if (inner_merged_index == -1)
2317 Assert(*default_index == -1);
2323 Assert(*default_index == inner_merged_index);
2326 Assert(*default_index == -1);
2330 Assert(outer_has_default && inner_has_default);
2339 Assert(outer_merged_index == -1);
2340 Assert(inner_merged_index == -1);
2341 Assert(*default_index == -1);
2347 Assert(*default_index >= 0);
2362 int merged_index = *next_index;
2369 *next_index = *next_index + 1;
2370 return merged_index;
2379 int nmerged,
List *merged_indexes)
2389 for (
i = 0;
i < nmerged;
i++)
2390 new_indexes[
i] = -1;
2398 if (merged_index >= 0)
2407 if (merged_index >= 0)
2413 foreach(lc, merged_indexes)
2416 Assert(merged_index >= 0);
2417 if (new_indexes[merged_index] >= 0)
2435 List **outer_parts,
List **inner_parts)
2437 int outer_nparts = outer_map->
nparts;
2438 int inner_nparts = inner_map->
nparts;
2450 for (
i = 0;
i < nmerged;
i++)
2451 outer_indexes[
i] = inner_indexes[
i] = -1;
2456 max_nparts =
Max(outer_nparts, inner_nparts);
2457 for (
i = 0;
i < max_nparts;
i++)
2459 if (
i < outer_nparts)
2463 if (merged_index >= 0)
2465 Assert(merged_index < nmerged);
2466 outer_indexes[merged_index] =
i;
2469 if (
i < inner_nparts)
2473 if (merged_index >= 0)
2475 Assert(merged_index < nmerged);
2476 inner_indexes[merged_index] =
i;
2482 for (
i = 0;
i < nmerged;
i++)
2484 int outer_index = outer_indexes[
i];
2485 int inner_index = inner_indexes[
i];
2493 if (outer_index == -1 && inner_index == -1)
2496 *outer_parts =
lappend(*outer_parts, outer_index >= 0 ?
2497 outer_rel->part_rels[outer_index] : NULL);
2498 *inner_parts =
lappend(*inner_parts, inner_index >= 0 ?
2499 inner_rel->part_rels[inner_index] : NULL);
2502 pfree(outer_indexes);
2503 pfree(inner_indexes);
2512 List *merged_kinds,
List *merged_indexes,
2513 int null_index,
int default_index)
2521 merged_bounds->
strategy = strategy;
2522 merged_bounds->
ndatums = ndatums;
2526 foreach(lc, merged_datums)
2534 foreach(lc, merged_kinds)
2545 merged_bounds->
kind = NULL;
2555 foreach(lc, merged_indexes)
2561 return merged_bounds;
2586 if (part_index == -1)
2624 if (*lb_pos + 2 >= bi->
ndatums)
2633 if (bi->
indexes[*lb_pos + 2] < 0)
2634 *lb_pos = *lb_pos + 2;
2636 *lb_pos = *lb_pos + 1;
2655 Oid *partcollations,
2660 int *lb_cmpval,
int *ub_cmpval)
2667 outer_ub, inner_lb) < 0)
2679 outer_lb, inner_ub) > 0)
2688 outer_lb, inner_lb);
2690 outer_ub, inner_ub);
2709 int lb_cmpval,
int ub_cmpval,
2714 outer_lb, inner_lb) == lb_cmpval);
2716 outer_ub, inner_ub) == ub_cmpval);
2729 *merged_lb = (lb_cmpval > 0) ? *outer_lb : *inner_lb;
2730 *merged_ub = (ub_cmpval < 0) ? *outer_ub : *inner_ub;
2741 *merged_lb = *outer_lb;
2742 *merged_ub = *outer_ub;
2753 *merged_lb = (lb_cmpval < 0) ? *outer_lb : *inner_lb;
2754 *merged_ub = (ub_cmpval > 0) ? *outer_ub : *inner_ub;
2758 elog(
ERROR,
"unrecognized join type: %d", (
int) jointype);
2768 Oid *partcollations,
2772 List **merged_datums,
2773 List **merged_kinds,
2774 List **merged_indexes)
2778 if (!*merged_datums)
2782 Assert(!*merged_indexes);
2797 prev_ub.
lower =
false;
2819 *merged_datums =
lappend(*merged_datums, merged_lb->
datums);
2820 *merged_kinds =
lappend(*merged_kinds, merged_lb->
kind);
2821 *merged_indexes =
lappend_int(*merged_indexes, -1);
2825 *merged_datums =
lappend(*merged_datums, merged_ub->
datums);
2826 *merged_kinds =
lappend(*merged_kinds, merged_ub->
kind);
2827 *merged_indexes =
lappend_int(*merged_indexes, merged_index);
2846 Assert(boundinfo != NULL);
2895 bool overlap =
false;
2896 int overlap_location = -1;
2911 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2912 errmsg(
"partition \"%s\" conflicts with existing default partition \"%s\"",
2917 switch (
key->strategy)
2924 if (partdesc->
nparts > 0)
2926 int greatest_modulus;
2961 if (next_modulus % spec->
modulus != 0)
2963 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2964 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
2965 errdetail(
"The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\".",
2980 if (spec->
modulus % prev_modulus != 0)
2982 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2983 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
2984 errdetail(
"The new modulus %d is not divisible by %d, the modulus of existing partition \"%s\".",
2989 if (offset + 1 < boundinfo->
ndatums)
3002 if (next_modulus % spec->
modulus != 0)
3004 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3005 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
3006 errdetail(
"The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\".",
3012 greatest_modulus = boundinfo->
nindexes;
3045 if (partdesc->
nparts > 0)
3059 overlap_location =
val->location;
3060 if (!
val->constisnull)
3070 if (offset >= 0 &&
equal)
3073 with = boundinfo->
indexes[offset];
3118 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3119 errmsg(
"empty range bound specified for partition \"%s\"",
3121 errdetail(
"Specified lower bound %s is greater than or equal to upper bound %s.",
3127 if (partdesc->
nparts > 0)
3157 if (boundinfo->
indexes[offset + 1] < 0)
3165 if (offset + 1 < boundinfo->
ndatums)
3171 datums = boundinfo->
datums[offset + 1];
3172 kind = boundinfo->
kind[offset + 1];
3173 is_lower = (boundinfo->
indexes[offset + 1] == -1);
3195 overlap_location = datum->
location;
3196 with = boundinfo->
indexes[offset + 2];
3215 overlap_location = datum->
location;
3216 with = boundinfo->
indexes[offset + 1];
3228 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3229 errmsg(
"partition \"%s\" would overlap partition \"%s\"",
3246 List *new_part_constraints;
3247 List *def_part_constraints;
3254 def_part_constraints =
3261 def_part_constraints =
3273 (
errmsg_internal(
"updated partition constraint for default partition \"%s\" is implied by existing constraints",
3282 if (default_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3288 foreach(lc, all_parts)
3292 Expr *partition_constraint;
3311 partition_constraint = (
Expr *)
3313 part_rel, default_rel);
3321 def_part_constraints))
3324 (
errmsg_internal(
"updated partition constraint for default partition \"%s\" is implied by existing constraints",
3333 part_rel = default_rel;
3341 if (part_rel->
rd_rel->relkind != RELKIND_RELATION)
3343 if (part_rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
3345 (
errcode(ERRCODE_CHECK_VIOLATION),
3346 errmsg(
"skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"",
3376 if (!
ExecCheck(partqualstate, econtext))
3378 (
errcode(ERRCODE_CHECK_VIOLATION),
3379 errmsg(
"updated partition constraint for default partition \"%s\" would be violated by some row",
3446 if (
val->constisnull)
3447 elog(
ERROR,
"invalid range bound datum");
3489 bool lower2 = b2->
lower;
3491 for (
i = 0;
i < partnatts;
i++)
3502 if (kind1[
i] < kind2[
i])
3504 else if (kind1[
i] > kind2[
i])
3530 if (cmpval == 0 && lower1 != lower2)
3531 cmpval = lower1 ? 1 : -1;
3533 return cmpval == 0 ? 0 : (cmpval < 0 ? -colnum : colnum);
3549 const Datum *tuple_datums,
int n_tuple_datums)
3554 for (
i = 0;
i < n_tuple_datums;
i++)
3580 if (modulus1 < modulus2)
3582 if (modulus1 > modulus2)
3584 if (modulus1 == modulus2 && remainder1 != remainder2)
3585 return (remainder1 > remainder2) ? 1 : -1;
3612 mid = (lo + hi + 1) / 2;
3615 boundinfo->
datums[mid][0],
3620 *is_equal = (cmpval == 0);
3657 mid = (lo + hi + 1) / 2;
3661 boundinfo->
kind[mid],
3662 (boundinfo->
indexes[mid] == -1),
3700 mid = (lo + hi + 1) / 2;
3704 boundinfo->
kind[mid],
3710 *is_equal = (cmpval == 0);
3744 mid = (lo + hi + 1) / 2;
3791 key->partcollation[0],
3833 key->partopcintype[col],
3834 key->partopcintype[col],
3837 elog(
ERROR,
"missing operator %d(%u,%u) in partition opfamily %u",
3838 strategy,
key->partopcintype[col],
key->partopcintype[col],
3839 key->partopfamily[col]);
3846 *need_relabel = (
key->parttypid[col] !=
key->partopcintype[col] &&
3847 key->partopcintype[col] != RECORDOID &&
3848 !IsPolymorphicType(
key->partopcintype[col]));
3863 bool need_relabel =
false;
3864 Expr *result = NULL;
3876 key->partcollation[keynum] !=
key->parttypcoll[keynum]))
3878 key->partopcintype[keynum],
3880 key->partcollation[keynum],
3884 switch (
key->strategy)
3902 arrexpr->array_typeid =
3904 arrexpr->array_collid =
key->parttypcoll[keynum];
3905 arrexpr->element_typeid =
key->parttypid[keynum];
3906 arrexpr->elements = elems;
3907 arrexpr->multidims =
false;
3912 saopexpr->
opno = operoid;
3916 saopexpr->
useOr =
true;
3917 saopexpr->inputcollid =
key->partcollation[keynum];
3921 result = (
Expr *) saopexpr;
3938 key->partcollation[keynum]);
3939 elemops =
lappend(elemops, elemop);
3953 key->partcollation[keynum]);
3980 Node *remainderConst;
4014 for (
i = 0;
i <
key->partnatts;
i++)
4019 if (
key->partattrs[
i] != 0)
4025 key->parttypcoll[
i],
4031 partexprs_item =
lnext(
key->partexprs, partexprs_item);
4066 bool list_has_null =
false;
4075 if (
key->partattrs[0] != 0)
4080 key->parttypcoll[0],
4102 list_has_null =
true;
4109 if (ndatums == 0 && !list_has_null)
4112 for (
i = 0;
i < ndatums;
i++)
4123 key->parttypcoll[0],
4126 key->parttypbyval[0],
4127 key->parttyplen[0]),
4129 key->parttypbyval[0]);
4143 if (
val->constisnull)
4144 list_has_null =
true;
4157 keyCol, (
Expr *) elems);
4176 nulltest->
arg = keyCol;
4178 nulltest->argisrow =
false;
4190 nulltest->
arg = keyCol;
4192 nulltest->argisrow =
false;
4273 *partexprs_item_saved;
4282 List *lower_or_arms,
4287 *upper_or_start_datum;
4288 bool need_next_lower_arm,
4289 need_next_upper_arm;
4296 int nparts = pdesc->
nparts,
4299 for (k = 0; k < nparts; k++)
4301 Oid inhrelid = inhoids[k];
4308 elog(
ERROR,
"cache lookup failed for relation %u", inhrelid);
4311 Anum_pg_class_relpartbound);
4315 elog(
ERROR,
"expected PartitionBoundSpec");
4334 if (or_expr_args !=
NIL)
4336 Expr *other_parts_constr;
4344 other_parts_constr =
4381 partexprs_item_saved = partexprs_item;
4399 partexprs_item_saved = partexprs_item;
4404 &lower_val, &upper_val);
4412 if (!lower_val || !upper_val)
4420 (
Expr *) upper_val);
4438 if (
i ==
key->partnatts - 1)
4439 elog(
ERROR,
"invalid range bound specification");
4444 keyCol, (
Expr *) lower_val));
4450 lower_or_start_datum = cell1;
4451 upper_or_start_datum = cell2;
4454 num_or_arms =
key->partnatts -
i;
4456 lower_or_arms = upper_or_arms =
NIL;
4457 need_next_lower_arm = need_next_upper_arm =
true;
4458 while (current_or_arm < num_or_arms)
4460 List *lower_or_arm_args =
NIL,
4461 *upper_or_arm_args =
NIL;
4465 partexprs_item = partexprs_item_saved;
4471 *udatum_next = NULL;
4484 &lower_val, &upper_val);
4486 if (need_next_lower_arm && lower_val)
4496 if (
j -
i < current_or_arm)
4498 else if (
j ==
key->partnatts - 1 ||
4505 lower_or_arm_args =
lappend(lower_or_arm_args,
4509 (
Expr *) lower_val));
4512 if (need_next_upper_arm && upper_val)
4521 if (
j -
i < current_or_arm)
4523 else if (udatum_next &&
4529 upper_or_arm_args =
lappend(upper_or_arm_args,
4533 (
Expr *) upper_val));
4542 if (
j -
i > current_or_arm)
4548 if (!lower_val || !ldatum_next ||
4550 need_next_lower_arm =
false;
4551 if (!upper_val || !udatum_next ||
4553 need_next_upper_arm =
false;
4558 if (lower_or_arm_args !=
NIL)
4559 lower_or_arms =
lappend(lower_or_arms,
4564 if (upper_or_arm_args !=
NIL)
4565 upper_or_arms =
lappend(upper_or_arms,
4571 if (!need_next_lower_arm && !need_next_upper_arm)
4582 if (lower_or_arms !=
NIL)
4587 if (upper_or_arms !=
NIL)
4600 result = for_default
4631 if (
key->partattrs[keynum] != 0)
4634 key->partattrs[keynum],
4635 key->parttypid[keynum],
4636 key->parttypmod[keynum],
4637 key->parttypcoll[keynum],
4642 if (*partexprs_item == NULL)
4643 elog(
ERROR,
"wrong number of partition key expressions");
4645 *partexprs_item =
lnext(
key->partexprs, *partexprs_item);
4675 for (
i = 0;
i <
key->partnatts;
i++)
4679 if (
key->partattrs[
i] != 0)
4685 key->parttypcoll[
i],
4690 if (partexprs_item == NULL)
4691 elog(
ERROR,
"wrong number of partition key expressions");
4693 partexprs_item =
lnext(
key->partexprs, partexprs_item);
4697 nulltest->
arg = keyCol;
4699 nulltest->argisrow =
false;
4701 result =
lappend(result, nulltest);
4720 for (
i = 0;
i < partnatts;
i++)
4764 typedef struct ColumnsHashData
4769 int16 variadic_typlen;
4770 bool variadic_typbyval;
4771 char variadic_typalign;
4779 ColumnsHashData *my_extra;
4792 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4793 errmsg(
"modulus for hash partition must be an integer value greater than zero")));
4796 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4797 errmsg(
"remainder for hash partition must be an integer value greater than or equal to zero")));
4800 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4801 errmsg(
"remainder for hash partition must be less than modulus")));
4806 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4807 if (my_extra == NULL || my_extra->relid != parentId)
4820 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4821 errmsg(
"\"%s\" is not a hash partitioned table",
4829 if (
key->partnatts != nargs)
4831 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4832 errmsg(
"number of partitioning columns (%d) does not match number of partition keys provided (%d)",
4833 key->partnatts, nargs)));
4836 fcinfo->flinfo->fn_extra =
4838 offsetof(ColumnsHashData, partsupfunc) +
4840 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4841 my_extra->relid = parentId;
4842 my_extra->nkeys =
key->partnatts;
4843 memcpy(my_extra->partcollid,
key->partcollation,
4844 key->partnatts *
sizeof(
Oid));
4847 for (
j = 0;
j <
key->partnatts; ++
j)
4853 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4854 errmsg(
"column %d of the partition key has type %s, but supplied value is of type %s",
4858 &
key->partsupfunc[
j],
4859 fcinfo->flinfo->fn_mcxt);
4867 fcinfo->flinfo->fn_extra =
4869 offsetof(ColumnsHashData, partsupfunc) +
4871 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4872 my_extra->relid = parentId;
4873 my_extra->nkeys =
key->partnatts;
4874 my_extra->variadic_type =
ARR_ELEMTYPE(variadic_array);
4876 &my_extra->variadic_typlen,
4877 &my_extra->variadic_typbyval,
4878 &my_extra->variadic_typalign);
4879 my_extra->partcollid[0] =
key->partcollation[0];
4882 for (
j = 0;
j <
key->partnatts; ++
j)
4883 if (
key->parttypid[
j] != my_extra->variadic_type)
4885 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4886 errmsg(
"column %d of the partition key has type \"%s\", but supplied value is of type \"%s\"",
4892 &
key->partsupfunc[0],
4893 fcinfo->flinfo->fn_mcxt);
4902 int nkeys = my_extra->nkeys;
4911 for (
i = 0;
i < nkeys;
i++)
4922 my_extra->partcollid[
i],
4939 my_extra->variadic_type,
4940 my_extra->variadic_typlen,
4941 my_extra->variadic_typbyval,
4942 my_extra->variadic_typalign,
4943 &datum, &isnull, &nelems);
4946 if (nelems != my_extra->nkeys)
4948 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4949 errmsg(
"number of partitioning columns (%d) does not match number of partition keys provided (%d)",
4950 my_extra->nkeys, nelems)));
4952 for (
i = 0;
i < nelems;
i++)
4960 my_extra->partcollid[0],
#define PG_GETARG_ARRAYTYPE_P(n)
void deconstruct_array(const ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
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)
Bitmapset * bms_copy(const Bitmapset *a)
static Datum values[MAXATTR]
static void cleanup(void)
#define TextDatumGetCString(d)
#define FLEXIBLE_ARRAY_MEMBER
#define OidIsValid(objectId)
Datum datumCopy(Datum value, bool typByVal, int typLen)
bool datumIsEqual(Datum value1, Datum value2, bool typByVal, int typLen)
int errmsg_internal(const char *fmt,...)
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
bool equal(const void *a, const void *b)
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
bool ExecCheck(ExprState *state, ExprContext *econtext)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
void FreeExecutorState(EState *estate)
EState * CreateExecutorState(void)
#define GetPerTupleExprContext(estate)
#define ResetExprContext(econtext)
#define GetPerTupleMemoryContext(estate)
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
#define palloc_object(type)
#define palloc_array(type, count)
#define palloc0_array(type, count)
#define palloc0_object(type)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
bool get_fn_expr_variadic(FmgrInfo *flinfo)
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
#define PG_GETARG_DATUM(n)
#define PG_GETARG_INT32(n)
#define PG_RETURN_BOOL(x)
static uint64 hash_combine64(uint64 a, uint64 b)
Assert(PointerIsAligned(start, uint64))
#define HeapTupleIsValid(tuple)
if(TABLE==NULL||TABLE_index==NULL)
List * lappend(List *list, void *datum)
List * lappend_int(List *list, int datum)
void list_free(List *list)
#define AccessExclusiveLock
char * get_rel_name(Oid relid)
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
RegProcedure get_opcode(Oid opno)
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Oid get_array_type(Oid typid)
#define type_is_array(typid)
Expr * make_ands_explicit(List *andclauses)
Expr * makeBoolExpr(BoolExprType boolop, List *args, int location)
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Node * makeBoolConst(bool value, bool isnull)
RelabelType * makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, Oid rcollid, CoercionForm rformat)
FuncExpr * makeFuncExpr(Oid funcid, Oid rettype, List *args, Oid funccollid, Oid inputcollid, CoercionForm fformat)
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
void * MemoryContextAllocZero(MemoryContext context, Size size)
void pfree(void *pointer)
#define CHECK_FOR_INTERRUPTS()
void fix_opfuncids(Node *node)
#define IsA(nodeptr, _type_)
#define IS_OUTER_JOIN(jointype)
#define castNode(_type_, nodeptr)
Datum lower(PG_FUNCTION_ARGS)
Datum upper(PG_FUNCTION_ARGS)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
bool IsBinaryCoercible(Oid srctype, Oid targettype)
int parser_errposition(ParseState *pstate, int location)
@ PARTITION_STRATEGY_HASH
@ PARTITION_STRATEGY_LIST
@ PARTITION_STRATEGY_RANGE
@ PARTITION_RANGE_DATUM_MAXVALUE
@ PARTITION_RANGE_DATUM_VALUE
@ PARTITION_RANGE_DATUM_MINVALUE
static int partition_range_bsearch(int partnatts, FmgrInfo *partsupfunc, Oid *partcollation, PartitionBoundInfo boundinfo, PartitionRangeBound *probe, int32 *cmpval)
static int process_inner_partition(PartitionMap *outer_map, PartitionMap *inner_map, bool outer_has_default, bool inner_has_default, int inner_index, int outer_default, JoinType jointype, int *next_index, int *default_index)
static void merge_default_partitions(PartitionMap *outer_map, PartitionMap *inner_map, bool outer_has_default, bool inner_has_default, int outer_default, int inner_default, JoinType jointype, int *next_index, int *default_index)
static void init_partition_map(RelOptInfo *rel, PartitionMap *map)
static List * get_qual_for_list(Relation parent, PartitionBoundSpec *spec)
static int32 qsort_partition_rbound_cmp(const void *a, const void *b, void *arg)
static int32 partition_rbound_cmp(int partnatts, FmgrInfo *partsupfunc, Oid *partcollation, Datum *datums1, PartitionRangeDatumKind *kind1, bool lower1, PartitionRangeBound *b2)
struct PartitionListValue PartitionListValue
static PartitionBoundInfo create_list_bounds(PartitionBoundSpec **boundspecs, int nparts, PartitionKey key, int **mapping)
static bool is_dummy_partition(RelOptInfo *rel, int part_index)
static PartitionBoundInfo merge_range_bounds(int partnatts, FmgrInfo *partsupfuncs, Oid *partcollations, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinType jointype, List **outer_parts, List **inner_parts)
struct PartitionMap PartitionMap
bool partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval, PartitionBoundInfo b1, PartitionBoundInfo b2)
int32 partition_rbound_datum_cmp(FmgrInfo *partsupfunc, Oid *partcollation, const Datum *rb_datums, PartitionRangeDatumKind *rb_kind, const Datum *tuple_datums, int n_tuple_datums)
PartitionBoundInfo partition_bounds_merge(int partnatts, FmgrInfo *partsupfunc, Oid *partcollation, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinType jointype, List **outer_parts, List **inner_parts)
static int merge_matching_partitions(PartitionMap *outer_map, PartitionMap *inner_map, int outer_index, int inner_index, int *next_index)
static List * get_qual_for_hash(Relation parent, PartitionBoundSpec *spec)
static void get_merged_range_bounds(int partnatts, FmgrInfo *partsupfuncs, Oid *partcollations, JoinType jointype, PartitionRangeBound *outer_lb, PartitionRangeBound *outer_ub, PartitionRangeBound *inner_lb, PartitionRangeBound *inner_ub, int lb_cmpval, int ub_cmpval, PartitionRangeBound *merged_lb, PartitionRangeBound *merged_ub)
#define compare_range_bounds(partnatts, partsupfunc, partcollations, bound1, bound2)
static int32 qsort_partition_hbound_cmp(const void *a, const void *b)
static void free_partition_map(PartitionMap *map)
static int get_non_null_list_datum_count(PartitionBoundSpec **boundspecs, int nparts)
void check_new_partition_bound(char *relname, Relation parent, PartitionBoundSpec *spec, ParseState *pstate)
static void fix_merged_indexes(PartitionMap *outer_map, PartitionMap *inner_map, int nmerged, List *merged_indexes)
static int merge_partition_with_dummy(PartitionMap *map, int index, int *next_index)
static Expr * make_partition_op_expr(PartitionKey key, int keynum, uint16 strategy, Expr *arg1, Expr *arg2)
uint64 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc, const Oid *partcollation, const Datum *values, const bool *isnull)
PartitionBoundInfo partition_bounds_create(PartitionBoundSpec **boundspecs, int nparts, PartitionKey key, int **mapping)
struct PartitionRangeBound PartitionRangeBound
static PartitionBoundInfo create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts, PartitionKey key, int **mapping)
bool partitions_are_ordered(PartitionBoundInfo boundinfo, Bitmapset *live_parts)
static List * get_qual_for_range(Relation parent, PartitionBoundSpec *spec, bool for_default)
static PartitionBoundInfo merge_list_bounds(FmgrInfo *partsupfunc, Oid *partcollation, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinType jointype, List **outer_parts, List **inner_parts)
static void generate_matching_part_pairs(RelOptInfo *outer_rel, RelOptInfo *inner_rel, PartitionMap *outer_map, PartitionMap *inner_map, int nmerged, List **outer_parts, List **inner_parts)
static void add_merged_range_bounds(int partnatts, FmgrInfo *partsupfuncs, Oid *partcollations, PartitionRangeBound *merged_lb, PartitionRangeBound *merged_ub, int merged_index, List **merged_datums, List **merged_kinds, List **merged_indexes)
Datum satisfies_hash_partition(PG_FUNCTION_ARGS)
static PartitionRangeBound * make_one_partition_rbound(PartitionKey key, int index, List *datums, bool lower)
int partition_hash_bsearch(PartitionBoundInfo boundinfo, int modulus, int remainder)
static void get_range_key_properties(PartitionKey key, int keynum, PartitionRangeDatum *ldatum, PartitionRangeDatum *udatum, ListCell **partexprs_item, Expr **keyCol, Const **lower_val, Const **upper_val)
List * get_qual_from_partbound(Relation parent, PartitionBoundSpec *spec)
static int32 partition_hbound_cmp(int modulus1, int remainder1, int modulus2, int remainder2)
static PartitionBoundInfo create_range_bounds(PartitionBoundSpec **boundspecs, int nparts, PartitionKey key, int **mapping)
static int32 qsort_partition_list_value_cmp(const void *a, const void *b, void *arg)
static PartitionBoundInfo build_merged_partition_bounds(char strategy, List *merged_datums, List *merged_kinds, List *merged_indexes, int null_index, int default_index)
int get_hash_partition_greatest_modulus(PartitionBoundInfo bound)
static Oid get_partition_operator(PartitionKey key, int col, StrategyNumber strategy, bool *need_relabel)
struct PartitionHashBound PartitionHashBound
static bool compare_range_partitions(int partnatts, FmgrInfo *partsupfuncs, Oid *partcollations, PartitionRangeBound *outer_lb, PartitionRangeBound *outer_ub, PartitionRangeBound *inner_lb, PartitionRangeBound *inner_ub, int *lb_cmpval, int *ub_cmpval)
static int get_range_partition(RelOptInfo *rel, PartitionBoundInfo bi, int *lb_pos, PartitionRangeBound *lb, PartitionRangeBound *ub)
int partition_range_datum_bsearch(FmgrInfo *partsupfunc, Oid *partcollation, PartitionBoundInfo boundinfo, int nvalues, const Datum *values, bool *is_equal)
static void merge_null_partitions(PartitionMap *outer_map, PartitionMap *inner_map, bool outer_has_null, bool inner_has_null, int outer_null, int inner_null, JoinType jointype, int *next_index, int *null_index)
void check_default_partition_contents(Relation parent, Relation default_rel, PartitionBoundSpec *new_spec)
static int get_range_partition_internal(PartitionBoundInfo bi, int *lb_pos, PartitionRangeBound *lb, PartitionRangeBound *ub)
static List * get_range_nulltest(PartitionKey key)
static int process_outer_partition(PartitionMap *outer_map, PartitionMap *inner_map, bool outer_has_default, bool inner_has_default, int outer_index, int inner_default, JoinType jointype, int *next_index, int *default_index)
int partition_list_bsearch(FmgrInfo *partsupfunc, Oid *partcollation, PartitionBoundInfo boundinfo, Datum value, bool *is_equal)
PartitionBoundInfo partition_bounds_copy(PartitionBoundInfo src, PartitionKey key)
#define partition_bound_has_default(bi)
#define partition_bound_accepts_nulls(bi)
PartitionKey RelationGetPartitionKey(Relation rel)
struct PartitionKeyData * PartitionKey
struct PartitionBoundInfoData * PartitionBoundInfo
PartitionDesc RelationGetPartitionDesc(Relation rel, bool omit_detached)
List * map_partition_varattnos(List *expr, int fromrel_varno, Relation to_rel, Relation from_rel)
List * get_proposed_default_constraint(List *new_part_constraints)
#define HASH_PARTITION_SEED
#define PARTITION_MAX_KEYS
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define forboth(cell1, list1, cell2, list2)
#define list_make1_oid(x1)
static void * list_nth(const List *list, int n)
#define list_make3(x1, x2, x3)
static ListCell * list_head(const List *l)
#define for_both_cell(cell1, list1, initcell1, cell2, list2, initcell2)
static ListCell * lnext(const List *l, const ListCell *c)
#define list_make2(x1, x2)
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
#define qsort(a, b, c, d)
static uint64 DatumGetUInt64(Datum X)
static bool DatumGetBool(Datum X)
static Datum UInt64GetDatum(uint64 X)
static Datum ObjectIdGetDatum(Oid X)
static Datum Int32GetDatum(int32 X)
static int32 DatumGetInt32(Datum X)
void * stringToNode(const char *str)
static unsigned hash(unsigned *uv, int n)
#define RelationGetRelid(relation)
#define RelationGetRelationName(relation)
int errtable(Relation rel)
char * get_range_partbound_string(List *bound_datums)
Snapshot GetLatestSnapshot(void)
void UnregisterSnapshot(Snapshot snapshot)
Snapshot RegisterSnapshot(Snapshot snapshot)
void relation_close(Relation relation, LOCKMODE lockmode)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
#define BTGreaterStrategyNumber
#define BTLessStrategyNumber
#define BTEqualStrategyNumber
#define BTLessEqualStrategyNumber
#define BTGreaterEqualStrategyNumber
MemoryContext es_query_cxt
TupleTableSlot * ecxt_scantuple
NullTestType nulltesttype
PartitionRangeDatumKind ** kind
PartitionStrategy strategy
Bitmapset * interleaved_parts
PartitionBoundInfo boundinfo
PartitionRangeDatumKind * kind
PartitionRangeDatumKind kind
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
static void table_endscan(TableScanDesc scan)
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, ScanKeyData *key)
bool PartConstraintImpliedByRelConstraint(Relation scanrel, List *partConstraint)