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)
274 elog(
ERROR,
"unexpected partition strategy: %d",
275 (
int)
key->strategy);
326 *mapping = (
int *)
palloc(
sizeof(
int) * nparts);
327 for (
i = 0;
i < nparts;
i++)
330 switch (
key->strategy)
342 elog(
ERROR,
"unexpected partition strategy: %d",
343 (
int)
key->strategy);
362 int greatest_modulus;
376 for (
i = 0;
i < nparts;
i++)
381 elog(
ERROR,
"invalid strategy in partition bound spec");
393 greatest_modulus = hbounds[nparts - 1].
modulus;
397 boundinfo->
kind = NULL;
399 boundinfo->
nindexes = greatest_modulus;
400 boundinfo->
indexes = (
int *)
palloc(greatest_modulus *
sizeof(
int));
401 for (
i = 0;
i < greatest_modulus;
i++)
416 for (
i = 0;
i < nparts;
i++)
421 boundinfo->
datums[
i] = &boundDatums[
i * 2];
425 while (remainder < greatest_modulus)
430 remainder += modulus;
433 (*mapping)[hbounds[
i].
index] =
i;
450 for (
i = 0;
i < nparts;
i++)
454 foreach(lc, boundspecs[
i]->listdatums)
458 if (!
val->constisnull)
480 int default_index = -1;
496 for (
j = 0,
i = 0;
i < nparts;
i++)
502 elog(
ERROR,
"invalid strategy in partition bound spec");
519 if (!
val->constisnull)
531 if (null_index != -1)
532 elog(
ERROR,
"found null more than once");
546 boundinfo->
kind = NULL;
564 for (
i = 0;
i < ndatums;
i++)
566 int orig_index = all_values[
i].
index;
568 boundinfo->
datums[
i] = &boundDatums[
i];
570 key->parttypbyval[0],
574 if ((*mapping)[orig_index] == -1)
575 (*mapping)[orig_index] = next_index++;
577 boundinfo->
indexes[
i] = (*mapping)[orig_index];
590 if (null_index != -1)
593 if ((*mapping)[null_index] == -1)
594 (*mapping)[null_index] = next_index++;
595 boundinfo->
null_index = (*mapping)[null_index];
599 if (default_index != -1)
606 Assert(default_index >= 0);
607 Assert((*mapping)[default_index] == -1);
608 (*mapping)[default_index] = next_index++;
646 if (
index < last_index)
676 Assert(next_index == nparts);
696 int default_index = -1;
714 for (
i = 0;
i < nparts;
i++)
721 elog(
ERROR,
"invalid strategy in partition bound spec");
736 all_bounds[ndatums++] =
lower;
737 all_bounds[ndatums++] =
upper;
740 Assert(ndatums == nparts * 2 ||
741 (default_index != -1 && ndatums == (nparts - 1) * 2));
754 for (
i = 0;
i < ndatums;
i++)
757 bool is_distinct =
false;
761 for (
j = 0;
j <
key->partnatts;
j++)
765 if (prev == NULL ||
cur->kind[
j] != prev->
kind[
j])
780 key->partcollation[
j],
795 rbounds[k++] = all_bounds[
i];
825 boundinfo->
indexes = (
int *)
palloc((ndatums + 1) *
sizeof(int));
833 partnatts =
key->partnatts;
838 for (
i = 0;
i < ndatums;
i++)
842 boundinfo->
datums[
i] = &boundDatums[
i * partnatts];
843 boundinfo->
kind[
i] = &boundKinds[
i * partnatts];
844 for (
j = 0;
j < partnatts;
j++)
849 key->parttypbyval[
j],
866 int orig_index = rbounds[
i]->
index;
869 if ((*mapping)[orig_index] == -1)
870 (*mapping)[orig_index] = next_index++;
872 boundinfo->
indexes[
i] = (*mapping)[orig_index];
879 if (default_index != -1)
881 Assert(default_index >= 0 && (*mapping)[default_index] == -1);
882 (*mapping)[default_index] = next_index++;
891 Assert(next_index == nparts);
949 #ifdef USE_ASSERT_CHECKING
961 for (
j = 0;
j < partnatts;
j++)
964 if (b1->
kind != NULL)
992 parttypbyval[
j], parttyplen[
j]))
1027 partnatts =
key->partnatts;
1034 if (src->
kind != NULL)
1052 for (
i = 0;
i < ndatums;
i++)
1054 dest->kind[
i] = &boundKinds[
i * partnatts];
1070 natts = hash_part ? 2 : partnatts;
1071 boundDatums =
palloc(ndatums * natts *
sizeof(
Datum));
1073 for (
i = 0;
i < ndatums;
i++)
1077 dest->datums[
i] = &boundDatums[
i * natts];
1079 for (
j = 0;
j < natts;
j++)
1086 typlen =
sizeof(
int32);
1091 byval =
key->parttypbyval[
j];
1092 typlen =
key->parttyplen[
j];
1095 if (
dest->kind == NULL ||
1102 dest->indexes = (
int *)
palloc(
sizeof(
int) * nindexes);
1103 memcpy(
dest->indexes, src->
indexes,
sizeof(
int) * nindexes);
1130 List **outer_parts,
List **inner_parts)
1143 *outer_parts = *inner_parts =
NIL;
1184 elog(
ERROR,
"unexpected partition strategy: %d",
1212 List **outer_parts,
List **inner_parts)
1228 int null_index = -1;
1229 int default_index = -1;
1248 outer_has_default =
false;
1250 inner_has_default =
false;
1259 outer_pos = inner_pos = 0;
1260 while (outer_pos < outer_bi->ndatums || inner_pos < inner_bi->ndatums)
1262 int outer_index = -1;
1263 int inner_index = -1;
1264 Datum *outer_datums;
1265 Datum *inner_datums;
1267 Datum *merged_datum = NULL;
1268 int merged_index = -1;
1270 if (outer_pos < outer_bi->ndatums)
1276 outer_index = outer_bi->
indexes[outer_pos];
1283 if (inner_pos < inner_bi->ndatums)
1289 inner_index = inner_bi->
indexes[inner_pos];
1298 outer_datums = outer_pos < outer_bi->
ndatums ?
1299 outer_bi->
datums[outer_pos] : NULL;
1300 inner_datums = inner_pos < inner_bi->
ndatums ?
1301 inner_bi->
datums[inner_pos] : NULL;
1312 if (outer_pos >= outer_bi->
ndatums)
1314 else if (inner_pos >= inner_bi->
ndatums)
1318 Assert(outer_datums != NULL && inner_datums != NULL);
1328 Assert(outer_pos < outer_bi->ndatums);
1329 Assert(inner_pos < inner_bi->ndatums);
1330 Assert(outer_index >= 0);
1331 Assert(inner_index >= 0);
1338 outer_index, inner_index,
1340 if (merged_index == -1)
1343 merged_datum = outer_datums;
1349 else if (cmpval < 0)
1352 Assert(outer_pos < outer_bi->ndatums);
1363 outer_index = outer_bi->
indexes[outer_pos];
1364 Assert(outer_index >= 0);
1374 if (merged_index == -1)
1376 merged_datum = outer_datums;
1386 Assert(inner_pos < inner_bi->ndatums);
1394 if (outer_has_default || jointype ==
JOIN_FULL)
1397 inner_index = inner_bi->
indexes[inner_pos];
1398 Assert(inner_index >= 0);
1408 if (merged_index == -1)
1410 merged_datum = inner_datums;
1421 if (merged_index >= 0 && merged_index != default_index)
1423 merged_datums =
lappend(merged_datums, merged_datum);
1424 merged_indexes =
lappend_int(merged_indexes, merged_index);
1432 if (outer_has_null &&
1434 outer_has_null =
false;
1435 if (inner_has_null &&
1437 inner_has_null =
false;
1440 if (outer_has_null || inner_has_null)
1442 outer_has_null, inner_has_null,
1444 jointype, &next_index, &null_index);
1446 Assert(null_index == -1);
1449 if (outer_has_default || inner_has_default)
1451 outer_has_default, inner_has_default,
1452 outer_default, inner_default,
1453 jointype, &next_index, &default_index);
1455 Assert(default_index == -1);
1465 next_index, merged_indexes);
1470 &outer_map, &inner_map,
1472 outer_parts, inner_parts);
1495 return merged_bounds;
1518 Oid *partcollations,
1521 List **outer_parts,
List **inner_parts)
1541 int default_index = -1;
1559 outer_has_default =
false;
1561 inner_has_default =
false;
1572 outer_lb_pos = inner_lb_pos = 0;
1574 &outer_lb, &outer_ub);
1576 &inner_lb, &inner_ub);
1577 while (outer_index >= 0 || inner_index >= 0)
1584 int merged_index = -1;
1595 if (outer_index == -1)
1601 else if (inner_index == -1)
1610 &outer_lb, &outer_ub,
1611 &inner_lb, &inner_ub,
1612 &lb_cmpval, &ub_cmpval);
1622 Assert(outer_index >= 0);
1624 outer_map.
merged[outer_index] ==
false);
1625 Assert(inner_index >= 0);
1627 inner_map.
merged[inner_index] ==
false);
1634 outer_index, inner_index,
1636 Assert(merged_index >= 0);
1640 partcollations, jointype,
1641 &outer_lb, &outer_ub,
1642 &inner_lb, &inner_ub,
1643 lb_cmpval, ub_cmpval,
1644 &merged_lb, &merged_ub);
1647 save_outer_ub = outer_ub;
1648 save_inner_ub = inner_ub;
1652 &outer_lb, &outer_ub);
1654 &inner_lb, &inner_ub);
1663 if (ub_cmpval > 0 && inner_index >= 0 &&
1665 &save_outer_ub, &inner_lb) > 0)
1667 if (ub_cmpval < 0 && outer_index >= 0 &&
1669 &outer_lb, &save_inner_ub) < 0)
1678 if ((outer_has_default && (lb_cmpval > 0 || ub_cmpval < 0)) ||
1679 (inner_has_default && (lb_cmpval < 0 || ub_cmpval > 0)))
1682 else if (ub_cmpval < 0)
1687 Assert(outer_index >= 0);
1689 outer_map.
merged[outer_index] ==
false);
1708 if (merged_index == -1)
1710 merged_lb = outer_lb;
1711 merged_ub = outer_ub;
1716 &outer_lb, &outer_ub);
1724 Assert(inner_index >= 0);
1726 inner_map.
merged[inner_index] ==
false);
1734 if (outer_has_default || jointype ==
JOIN_FULL)
1745 if (merged_index == -1)
1747 merged_lb = inner_lb;
1748 merged_ub = inner_ub;
1753 &inner_lb, &inner_ub);
1760 if (merged_index >= 0 && merged_index != default_index)
1762 &merged_lb, &merged_ub, merged_index,
1763 &merged_datums, &merged_kinds,
1768 if (outer_has_default || inner_has_default)
1770 outer_has_default, inner_has_default,
1771 outer_default, inner_default,
1772 jointype, &next_index, &default_index);
1774 Assert(default_index == -1);
1788 &outer_map, &inner_map,
1790 outer_parts, inner_parts);
1814 return merged_bounds;
1824 int nparts = rel->
nparts;
1832 for (
i = 0;
i < nparts;
i++)
1874 int outer_index,
int inner_index,
int *next_index)
1876 int outer_merged_index;
1877 int inner_merged_index;
1881 Assert(outer_index >= 0 && outer_index < outer_map->nparts);
1883 outer_merged = outer_map->
merged[outer_index];
1884 Assert(inner_index >= 0 && inner_index < inner_map->nparts);
1886 inner_merged = inner_map->
merged[inner_index];
1892 if (outer_merged_index >= 0 && inner_merged_index >= 0)
1901 if (outer_merged_index == inner_merged_index)
1905 return outer_merged_index;
1907 if (!outer_merged && !inner_merged)
1916 if (outer_merged_index < inner_merged_index)
1918 outer_map->
merged[outer_index] =
true;
1920 inner_map->
merged[inner_index] =
true;
1922 inner_map->
old_indexes[inner_index] = inner_merged_index;
1923 return outer_merged_index;
1927 inner_map->
merged[inner_index] =
true;
1929 outer_map->
merged[outer_index] =
true;
1931 outer_map->
old_indexes[outer_index] = outer_merged_index;
1932 return inner_merged_index;
1939 Assert(outer_merged_index == -1 || inner_merged_index == -1);
1947 if (outer_merged_index == -1 && inner_merged_index == -1)
1949 int merged_index = *next_index;
1954 outer_map->
merged[outer_index] =
true;
1956 inner_map->
merged[inner_index] =
true;
1957 *next_index = *next_index + 1;
1958 return merged_index;
1960 if (outer_merged_index >= 0 && !outer_map->
merged[outer_index])
1962 Assert(inner_merged_index == -1);
1965 inner_map->
merged[inner_index] =
true;
1966 outer_map->
merged[outer_index] =
true;
1967 return outer_merged_index;
1969 if (inner_merged_index >= 0 && !inner_map->
merged[inner_index])
1971 Assert(outer_merged_index == -1);
1974 outer_map->
merged[outer_index] =
true;
1975 inner_map->
merged[inner_index] =
true;
1976 return inner_merged_index;
1993 bool outer_has_default,
1994 bool inner_has_default,
2001 int merged_index = -1;
2003 Assert(outer_index >= 0);
2013 if (inner_has_default)
2015 Assert(inner_default >= 0);
2024 if (outer_has_default)
2028 outer_index, inner_default,
2030 if (merged_index == -1)
2043 if (*default_index == -1)
2044 *default_index = merged_index;
2046 Assert(*default_index == merged_index);
2056 if (merged_index == -1)
2060 return merged_index;
2075 bool outer_has_default,
2076 bool inner_has_default,
2083 int merged_index = -1;
2085 Assert(inner_index >= 0);
2095 if (outer_has_default)
2097 Assert(outer_default >= 0);
2106 if (inner_has_default)
2110 outer_default, inner_index,
2112 if (merged_index == -1)
2126 if (*default_index == -1)
2127 *default_index = merged_index;
2129 Assert(*default_index == merged_index);
2138 if (merged_index == -1)
2142 return merged_index;
2160 bool outer_has_null,
2161 bool inner_has_null,
2168 bool consider_outer_null =
false;
2169 bool consider_inner_null =
false;
2171 Assert(outer_has_null || inner_has_null);
2172 Assert(*null_index == -1);
2180 Assert(outer_null >= 0 && outer_null < outer_map->nparts);
2182 consider_outer_null =
true;
2186 Assert(inner_null >= 0 && inner_null < inner_map->nparts);
2188 consider_inner_null =
true;
2192 if (!consider_outer_null && !consider_inner_null)
2195 if (consider_outer_null && !consider_inner_null)
2214 else if (!consider_outer_null && consider_inner_null)
2232 Assert(consider_outer_null && consider_inner_null);
2253 outer_null, inner_null,
2255 Assert(*null_index >= 0);
2270 bool outer_has_default,
2271 bool inner_has_default,
2278 int outer_merged_index = -1;
2279 int inner_merged_index = -1;
2281 Assert(outer_has_default || inner_has_default);
2284 if (outer_has_default)
2286 Assert(outer_default >= 0 && outer_default < outer_map->nparts);
2289 if (inner_has_default)
2291 Assert(inner_default >= 0 && inner_default < inner_map->nparts);
2295 if (outer_has_default && !inner_has_default)
2308 if (outer_merged_index == -1)
2310 Assert(*default_index == -1);
2316 Assert(*default_index == outer_merged_index);
2319 Assert(*default_index == -1);
2321 else if (!outer_has_default && inner_has_default)
2333 if (inner_merged_index == -1)
2335 Assert(*default_index == -1);
2341 Assert(*default_index == inner_merged_index);
2344 Assert(*default_index == -1);
2348 Assert(outer_has_default && inner_has_default);
2357 Assert(outer_merged_index == -1);
2358 Assert(inner_merged_index == -1);
2359 Assert(*default_index == -1);
2365 Assert(*default_index >= 0);
2380 int merged_index = *next_index;
2387 *next_index = *next_index + 1;
2388 return merged_index;
2397 int nmerged,
List *merged_indexes)
2406 new_indexes = (
int *)
palloc(
sizeof(
int) * nmerged);
2407 for (
i = 0;
i < nmerged;
i++)
2408 new_indexes[
i] = -1;
2416 if (merged_index >= 0)
2425 if (merged_index >= 0)
2431 foreach(lc, merged_indexes)
2434 Assert(merged_index >= 0);
2435 if (new_indexes[merged_index] >= 0)
2453 List **outer_parts,
List **inner_parts)
2455 int outer_nparts = outer_map->
nparts;
2456 int inner_nparts = inner_map->
nparts;
2466 outer_indexes = (
int *)
palloc(
sizeof(
int) * nmerged);
2467 inner_indexes = (
int *)
palloc(
sizeof(
int) * nmerged);
2468 for (
i = 0;
i < nmerged;
i++)
2469 outer_indexes[
i] = inner_indexes[
i] = -1;
2474 max_nparts =
Max(outer_nparts, inner_nparts);
2475 for (
i = 0;
i < max_nparts;
i++)
2477 if (
i < outer_nparts)
2481 if (merged_index >= 0)
2483 Assert(merged_index < nmerged);
2484 outer_indexes[merged_index] =
i;
2487 if (
i < inner_nparts)
2491 if (merged_index >= 0)
2493 Assert(merged_index < nmerged);
2494 inner_indexes[merged_index] =
i;
2500 for (
i = 0;
i < nmerged;
i++)
2502 int outer_index = outer_indexes[
i];
2503 int inner_index = inner_indexes[
i];
2511 if (outer_index == -1 && inner_index == -1)
2514 *outer_parts =
lappend(*outer_parts, outer_index >= 0 ?
2515 outer_rel->
part_rels[outer_index] : NULL);
2516 *inner_parts =
lappend(*inner_parts, inner_index >= 0 ?
2517 inner_rel->
part_rels[inner_index] : NULL);
2520 pfree(outer_indexes);
2521 pfree(inner_indexes);
2530 List *merged_kinds,
List *merged_indexes,
2531 int null_index,
int default_index)
2539 merged_bounds->
strategy = strategy;
2540 merged_bounds->
ndatums = ndatums;
2544 foreach(lc, merged_datums)
2553 foreach(lc, merged_kinds)
2564 merged_bounds->
kind = NULL;
2572 merged_bounds->
indexes = (
int *)
palloc(
sizeof(
int) * ndatums);
2574 foreach(lc, merged_indexes)
2580 return merged_bounds;
2605 if (part_index == -1)
2643 if (*lb_pos + 2 >= bi->
ndatums)
2652 if (bi->
indexes[*lb_pos + 2] < 0)
2653 *lb_pos = *lb_pos + 2;
2655 *lb_pos = *lb_pos + 1;
2674 Oid *partcollations,
2679 int *lb_cmpval,
int *ub_cmpval)
2686 outer_ub, inner_lb) < 0)
2698 outer_lb, inner_ub) > 0)
2707 outer_lb, inner_lb);
2709 outer_ub, inner_ub);
2728 int lb_cmpval,
int ub_cmpval,
2733 outer_lb, inner_lb) == lb_cmpval);
2735 outer_ub, inner_ub) == ub_cmpval);
2748 *merged_lb = (lb_cmpval > 0) ? *outer_lb : *inner_lb;
2749 *merged_ub = (ub_cmpval < 0) ? *outer_ub : *inner_ub;
2760 *merged_lb = *outer_lb;
2761 *merged_ub = *outer_ub;
2772 *merged_lb = (lb_cmpval < 0) ? *outer_lb : *inner_lb;
2773 *merged_ub = (ub_cmpval > 0) ? *outer_ub : *inner_ub;
2777 elog(
ERROR,
"unrecognized join type: %d", (
int) jointype);
2787 Oid *partcollations,
2791 List **merged_datums,
2792 List **merged_kinds,
2793 List **merged_indexes)
2797 if (!*merged_datums)
2801 Assert(!*merged_indexes);
2816 prev_ub.
lower =
false;
2838 *merged_datums =
lappend(*merged_datums, merged_lb->
datums);
2839 *merged_kinds =
lappend(*merged_kinds, merged_lb->
kind);
2840 *merged_indexes =
lappend_int(*merged_indexes, -1);
2844 *merged_datums =
lappend(*merged_datums, merged_ub->
datums);
2845 *merged_kinds =
lappend(*merged_kinds, merged_ub->
kind);
2846 *merged_indexes =
lappend_int(*merged_indexes, merged_index);
2865 Assert(boundinfo != NULL);
2915 bool overlap =
false;
2916 int overlap_location = -1;
2931 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2932 errmsg(
"partition \"%s\" conflicts with existing default partition \"%s\"",
2937 switch (
key->strategy)
2944 if (partdesc->
nparts > 0)
2946 int greatest_modulus;
2981 if (next_modulus % spec->
modulus != 0)
2983 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2984 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
2985 errdetail(
"The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\".",
3000 if (spec->
modulus % prev_modulus != 0)
3002 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3003 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
3004 errdetail(
"The new modulus %d is not divisible by %d, the modulus of existing partition \"%s\".",
3009 if (offset + 1 < boundinfo->
ndatums)
3022 if (next_modulus % spec->
modulus != 0)
3024 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3025 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
3026 errdetail(
"The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\".",
3032 greatest_modulus = boundinfo->
nindexes;
3041 if (remainder >= greatest_modulus)
3042 remainder = remainder % greatest_modulus;
3047 if (boundinfo->
indexes[remainder] != -1)
3051 with = boundinfo->
indexes[remainder];
3055 }
while (remainder < greatest_modulus);
3065 if (partdesc->
nparts > 0)
3079 overlap_location =
val->location;
3080 if (!
val->constisnull)
3090 if (offset >= 0 &&
equal)
3093 with = boundinfo->
indexes[offset];
3138 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3139 errmsg(
"empty range bound specified for partition \"%s\"",
3141 errdetail(
"Specified lower bound %s is greater than or equal to upper bound %s.",
3147 if (partdesc->
nparts > 0)
3177 if (boundinfo->
indexes[offset + 1] < 0)
3185 if (offset + 1 < boundinfo->
ndatums)
3191 datums = boundinfo->
datums[offset + 1];
3192 kind = boundinfo->
kind[offset + 1];
3193 is_lower = (boundinfo->
indexes[offset + 1] == -1);
3215 overlap_location = datum->
location;
3216 with = boundinfo->
indexes[offset + 2];
3235 overlap_location = datum->
location;
3236 with = boundinfo->
indexes[offset + 1];
3244 elog(
ERROR,
"unexpected partition strategy: %d",
3245 (
int)
key->strategy);
3252 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3253 errmsg(
"partition \"%s\" would overlap partition \"%s\"",
3270 List *new_part_constraints;
3271 List *def_part_constraints;
3278 def_part_constraints =
3285 def_part_constraints =
3297 (
errmsg_internal(
"updated partition constraint for default partition \"%s\" is implied by existing constraints",
3306 if (default_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3312 foreach(lc, all_parts)
3316 Expr *partition_constraint;
3335 partition_constraint = (
Expr *)
3337 part_rel, default_rel);
3345 def_part_constraints))
3348 (
errmsg_internal(
"updated partition constraint for default partition \"%s\" is implied by existing constraints",
3357 part_rel = default_rel;
3365 if (part_rel->
rd_rel->relkind != RELKIND_RELATION)
3367 if (part_rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
3369 (
errcode(ERRCODE_CHECK_VIOLATION),
3370 errmsg(
"skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"",
3400 if (!
ExecCheck(partqualstate, econtext))
3402 (
errcode(ERRCODE_CHECK_VIOLATION),
3403 errmsg(
"updated partition constraint for default partition \"%s\" would be violated by some row",
3471 if (
val->constisnull)
3472 elog(
ERROR,
"invalid range bound datum");
3514 bool lower2 = b2->
lower;
3516 for (
i = 0;
i < partnatts;
i++)
3527 if (kind1[
i] < kind2[
i])
3529 else if (kind1[
i] > kind2[
i])
3555 if (cmpval == 0 && lower1 != lower2)
3556 cmpval = lower1 ? 1 : -1;
3558 return cmpval == 0 ? 0 : (cmpval < 0 ? -colnum : colnum);
3574 Datum *tuple_datums,
int n_tuple_datums)
3579 for (
i = 0;
i < n_tuple_datums;
i++)
3605 if (modulus1 < modulus2)
3607 if (modulus1 > modulus2)
3609 if (modulus1 == modulus2 && remainder1 != remainder2)
3610 return (remainder1 > remainder2) ? 1 : -1;
3637 mid = (lo + hi + 1) / 2;
3640 boundinfo->
datums[mid][0],
3645 *is_equal = (cmpval == 0);
3682 mid = (lo + hi + 1) / 2;
3686 boundinfo->
kind[mid],
3687 (boundinfo->
indexes[mid] == -1),
3725 mid = (lo + hi + 1) / 2;
3729 boundinfo->
kind[mid],
3735 *is_equal = (cmpval == 0);
3755 int modulus,
int remainder)
3769 mid = (lo + hi + 1) / 2;
3773 modulus, remainder);
3816 key->partcollation[0],
3858 key->partopcintype[col],
3859 key->partopcintype[col],
3862 elog(
ERROR,
"missing operator %d(%u,%u) in partition opfamily %u",
3863 strategy,
key->partopcintype[col],
key->partopcintype[col],
3864 key->partopfamily[col]);
3871 *need_relabel = (
key->parttypid[col] !=
key->partopcintype[col] &&
3872 key->partopcintype[col] != RECORDOID &&
3873 !IsPolymorphicType(
key->partopcintype[col]));
3888 bool need_relabel =
false;
3889 Expr *result = NULL;
3901 key->partcollation[keynum] !=
key->parttypcoll[keynum]))
3903 key->partopcintype[keynum],
3905 key->partcollation[keynum],
3909 switch (
key->strategy)
3937 saopexpr->
opno = operoid;
3941 saopexpr->
useOr =
true;
3946 result = (
Expr *) saopexpr;
3963 key->partcollation[keynum]);
3964 elemops =
lappend(elemops, elemop);
3978 key->partcollation[keynum]);
3982 elog(
ERROR,
"invalid partitioning strategy");
4005 Node *remainderConst;
4039 for (
i = 0;
i <
key->partnatts;
i++)
4044 if (
key->partattrs[
i] != 0)
4050 key->parttypcoll[
i],
4056 partexprs_item =
lnext(
key->partexprs, partexprs_item);
4091 bool list_has_null =
false;
4100 if (
key->partattrs[0] != 0)
4105 key->parttypcoll[0],
4127 list_has_null =
true;
4134 if (ndatums == 0 && !list_has_null)
4137 for (
i = 0;
i < ndatums;
i++)
4148 key->parttypcoll[0],
4151 key->parttypbyval[0],
4152 key->parttyplen[0]),
4154 key->parttypbyval[0]);
4168 if (
val->constisnull)
4169 list_has_null =
true;
4182 keyCol, (
Expr *) elems);
4201 nulltest->
arg = keyCol;
4215 nulltest->
arg = keyCol;
4298 *partexprs_item_saved;
4307 List *lower_or_arms,
4312 *upper_or_start_datum;
4313 bool need_next_lower_arm,
4314 need_next_upper_arm;
4321 int nparts = pdesc->
nparts,
4324 for (
i = 0;
i < nparts;
i++)
4326 Oid inhrelid = inhoids[
i];
4334 elog(
ERROR,
"cache lookup failed for relation %u", inhrelid);
4337 Anum_pg_class_relpartbound,
4340 elog(
ERROR,
"null relpartbound for relation %u", inhrelid);
4345 elog(
ERROR,
"expected PartitionBoundSpec");
4364 if (or_expr_args !=
NIL)
4366 Expr *other_parts_constr;
4374 other_parts_constr =
4411 partexprs_item_saved = partexprs_item;
4429 partexprs_item_saved = partexprs_item;
4434 &lower_val, &upper_val);
4442 if (!lower_val || !upper_val)
4450 (
Expr *) upper_val);
4468 if (
i ==
key->partnatts - 1)
4469 elog(
ERROR,
"invalid range bound specification");
4474 keyCol, (
Expr *) lower_val));
4480 lower_or_start_datum = cell1;
4481 upper_or_start_datum = cell2;
4484 num_or_arms =
key->partnatts -
i;
4486 lower_or_arms = upper_or_arms =
NIL;
4487 need_next_lower_arm = need_next_upper_arm =
true;
4488 while (current_or_arm < num_or_arms)
4490 List *lower_or_arm_args =
NIL,
4491 *upper_or_arm_args =
NIL;
4495 partexprs_item = partexprs_item_saved;
4501 *udatum_next = NULL;
4514 &lower_val, &upper_val);
4516 if (need_next_lower_arm && lower_val)
4526 if (
j -
i < current_or_arm)
4528 else if (
j ==
key->partnatts - 1 ||
4535 lower_or_arm_args =
lappend(lower_or_arm_args,
4539 (
Expr *) lower_val));
4542 if (need_next_upper_arm && upper_val)
4551 if (
j -
i < current_or_arm)
4553 else if (udatum_next &&
4559 upper_or_arm_args =
lappend(upper_or_arm_args,
4563 (
Expr *) upper_val));
4572 if (
j -
i > current_or_arm)
4578 if (!lower_val || !ldatum_next ||
4580 need_next_lower_arm =
false;
4581 if (!upper_val || !udatum_next ||
4583 need_next_upper_arm =
false;
4588 if (lower_or_arm_args !=
NIL)
4589 lower_or_arms =
lappend(lower_or_arms,
4594 if (upper_or_arm_args !=
NIL)
4595 upper_or_arms =
lappend(upper_or_arms,
4601 if (!need_next_lower_arm && !need_next_upper_arm)
4612 if (lower_or_arms !=
NIL)
4617 if (upper_or_arms !=
NIL)
4630 result = for_default
4661 if (
key->partattrs[keynum] != 0)
4664 key->partattrs[keynum],
4665 key->parttypid[keynum],
4666 key->parttypmod[keynum],
4667 key->parttypcoll[keynum],
4672 if (*partexprs_item == NULL)
4673 elog(
ERROR,
"wrong number of partition key expressions");
4675 *partexprs_item =
lnext(
key->partexprs, *partexprs_item);
4705 for (
i = 0;
i <
key->partnatts;
i++)
4709 if (
key->partattrs[
i] != 0)
4715 key->parttypcoll[
i],
4720 if (partexprs_item == NULL)
4721 elog(
ERROR,
"wrong number of partition key expressions");
4723 partexprs_item =
lnext(
key->partexprs, partexprs_item);
4727 nulltest->
arg = keyCol;
4731 result =
lappend(result, nulltest);
4750 for (
i = 0;
i < partnatts;
i++)
4794 typedef struct ColumnsHashData
4799 int16 variadic_typlen;
4800 bool variadic_typbyval;
4801 char variadic_typalign;
4809 ColumnsHashData *my_extra;
4822 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4823 errmsg(
"modulus for hash partition must be an integer value greater than zero")));
4826 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4827 errmsg(
"remainder for hash partition must be an integer value greater than or equal to zero")));
4828 if (remainder >= modulus)
4830 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4831 errmsg(
"remainder for hash partition must be less than modulus")));
4836 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4837 if (my_extra == NULL || my_extra->relid != parentId)
4850 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4851 errmsg(
"\"%s\" is not a hash partitioned table",
4859 if (
key->partnatts != nargs)
4861 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4862 errmsg(
"number of partitioning columns (%d) does not match number of partition keys provided (%d)",
4863 key->partnatts, nargs)));
4866 fcinfo->flinfo->fn_extra =
4868 offsetof(ColumnsHashData, partsupfunc) +
4870 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4871 my_extra->relid = parentId;
4872 my_extra->nkeys =
key->partnatts;
4873 memcpy(my_extra->partcollid,
key->partcollation,
4874 key->partnatts *
sizeof(
Oid));
4877 for (
j = 0;
j <
key->partnatts; ++
j)
4883 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4884 errmsg(
"column %d of the partition key has type %s, but supplied value is of type %s",
4888 &
key->partsupfunc[
j],
4889 fcinfo->flinfo->fn_mcxt);
4897 fcinfo->flinfo->fn_extra =
4899 offsetof(ColumnsHashData, partsupfunc) +
4901 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4902 my_extra->relid = parentId;
4903 my_extra->nkeys =
key->partnatts;
4904 my_extra->variadic_type =
ARR_ELEMTYPE(variadic_array);
4906 &my_extra->variadic_typlen,
4907 &my_extra->variadic_typbyval,
4908 &my_extra->variadic_typalign);
4909 my_extra->partcollid[0] =
key->partcollation[0];
4912 for (
j = 0;
j <
key->partnatts; ++
j)
4913 if (
key->parttypid[
j] != my_extra->variadic_type)
4915 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4916 errmsg(
"column %d of the partition key has type \"%s\", but supplied value is of type \"%s\"",
4922 &
key->partsupfunc[0],
4923 fcinfo->flinfo->fn_mcxt);
4932 int nkeys = my_extra->nkeys;
4941 for (
i = 0;
i < nkeys;
i++)
4952 my_extra->partcollid[
i],
4969 my_extra->variadic_type,
4970 my_extra->variadic_typlen,
4971 my_extra->variadic_typbyval,
4972 my_extra->variadic_typalign,
4973 &datum, &isnull, &nelems);
4976 if (nelems != my_extra->nkeys)
4978 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4979 errmsg(
"number of partitioning columns (%d) does not match number of partition keys provided (%d)",
4980 my_extra->nkeys, nelems)));
4982 for (
i = 0;
i < nelems;
i++)
4990 my_extra->partcollid[0],
#define PG_GETARG_ARRAYTYPE_P(n)
void deconstruct_array(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 offsetof(type, field)
#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 * ExecPrepareExpr(Expr *node, EState *estate)
bool ExecCheck(ExprState *state, ExprContext *econtext)
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
EState * CreateExecutorState(void)
void FreeExecutorState(EState *estate)
#define GetPerTupleExprContext(estate)
#define ResetExprContext(econtext)
#define GetPerTupleMemoryContext(estate)
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
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)
#define HeapTupleIsValid(tuple)
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
List * lappend_int(List *list, int datum)
void list_free(List *list)
#define AccessExclusiveLock
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
RegProcedure get_opcode(Oid opno)
char * get_rel_name(Oid relid)
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_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
FuncExpr * makeFuncExpr(Oid funcid, Oid rettype, List *args, Oid funccollid, Oid inputcollid, CoercionForm fformat)
RelabelType * makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, Oid rcollid, CoercionForm rformat)
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Expr * make_ands_explicit(List *andclauses)
Expr * makeBoolExpr(BoolExprType boolop, List *args, int location)
Node * makeBoolConst(bool value, bool isnull)
void pfree(void *pointer)
void * palloc0(Size size)
void * MemoryContextAllocZero(MemoryContext context, Size size)
#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)
#define PARTITION_STRATEGY_LIST
@ PARTITION_RANGE_DATUM_MAXVALUE
@ PARTITION_RANGE_DATUM_VALUE
@ PARTITION_RANGE_DATUM_MINVALUE
#define PARTITION_STRATEGY_RANGE
#define PARTITION_STRATEGY_HASH
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)
int32 partition_rbound_datum_cmp(FmgrInfo *partsupfunc, Oid *partcollation, Datum *rb_datums, PartitionRangeDatumKind *rb_kind, Datum *tuple_datums, int n_tuple_datums)
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)
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 List * get_qual_for_hash(Relation parent, PartitionBoundSpec *spec)
static PartitionBoundInfo merge_list_bounds(FmgrInfo *partsupfunc, Oid *collations, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinType jointype, List **outer_parts, List **inner_parts)
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)
List * get_qual_from_partbound(Relation parent, PartitionBoundSpec *spec)
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)
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 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)
uint64 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc, Oid *partcollation, Datum *values, bool *isnull)
int partition_range_datum_bsearch(FmgrInfo *partsupfunc, Oid *partcollation, PartitionBoundInfo boundinfo, int nvalues, Datum *values, bool *is_equal)
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)
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 int merge_matching_partitions(PartitionMap *outer_map, PartitionMap *inner_map, int outer_part, int inner_part, int *next_index)
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)
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 ListCell * list_head(const List *l)
#define list_make3(x1, x2, x3)
#define for_both_cell(cell1, list1, initcell1, cell2, list2, initcell2)
static void * list_nth(const List *list, int n)
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)
#define DatumGetUInt64(X)
#define ObjectIdGetDatum(X)
#define UInt64GetDatum(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
Bitmapset * interleaved_parts
PartitionBoundInfo boundinfo
PartitionRangeDatumKind * kind
PartitionRangeDatumKind kind
struct PartitionBoundInfoData * boundinfo
struct RelOptInfo ** part_rels
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
static void table_endscan(TableScanDesc scan)
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
bool PartConstraintImpliedByRelConstraint(Relation scanrel, List *partConstraint)