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)
322 *mapping = (
int *)
palloc(
sizeof(
int) * nparts);
323 for (
i = 0;
i < nparts;
i++)
326 switch (
key->strategy)
353 int greatest_modulus;
367 for (
i = 0;
i < nparts;
i++)
372 elog(
ERROR,
"invalid strategy in partition bound spec");
384 greatest_modulus = hbounds[nparts - 1].
modulus;
388 boundinfo->
kind = NULL;
390 boundinfo->
nindexes = greatest_modulus;
391 boundinfo->
indexes = (
int *)
palloc(greatest_modulus *
sizeof(
int));
392 for (
i = 0;
i < greatest_modulus;
i++)
407 for (
i = 0;
i < nparts;
i++)
412 boundinfo->
datums[
i] = &boundDatums[
i * 2];
416 while (remainder < greatest_modulus)
421 remainder += modulus;
424 (*mapping)[hbounds[
i].
index] =
i;
441 for (
i = 0;
i < nparts;
i++)
445 foreach(lc, boundspecs[
i]->listdatums)
449 if (!
val->constisnull)
471 int default_index = -1;
487 for (
j = 0,
i = 0;
i < nparts;
i++)
493 elog(
ERROR,
"invalid strategy in partition bound spec");
510 if (!
val->constisnull)
522 if (null_index != -1)
523 elog(
ERROR,
"found null more than once");
537 boundinfo->
kind = NULL;
555 for (
i = 0;
i < ndatums;
i++)
557 int orig_index = all_values[
i].
index;
559 boundinfo->
datums[
i] = &boundDatums[
i];
561 key->parttypbyval[0],
565 if ((*mapping)[orig_index] == -1)
566 (*mapping)[orig_index] = next_index++;
568 boundinfo->
indexes[
i] = (*mapping)[orig_index];
581 if (null_index != -1)
584 if ((*mapping)[null_index] == -1)
585 (*mapping)[null_index] = next_index++;
586 boundinfo->
null_index = (*mapping)[null_index];
590 if (default_index != -1)
597 Assert(default_index >= 0);
598 Assert((*mapping)[default_index] == -1);
599 (*mapping)[default_index] = next_index++;
637 if (
index < last_index)
668 Assert(next_index == nparts);
688 int default_index = -1;
706 for (
i = 0;
i < nparts;
i++)
713 elog(
ERROR,
"invalid strategy in partition bound spec");
728 all_bounds[ndatums++] =
lower;
729 all_bounds[ndatums++] =
upper;
732 Assert(ndatums == nparts * 2 ||
733 (default_index != -1 && ndatums == (nparts - 1) * 2));
746 for (
i = 0;
i < ndatums;
i++)
749 bool is_distinct =
false;
753 for (
j = 0;
j <
key->partnatts;
j++)
757 if (prev == NULL ||
cur->kind[
j] != prev->
kind[
j])
772 key->partcollation[
j],
787 rbounds[k++] = all_bounds[
i];
817 boundinfo->
indexes = (
int *)
palloc((ndatums + 1) *
sizeof(int));
825 partnatts =
key->partnatts;
830 for (
i = 0;
i < ndatums;
i++)
834 boundinfo->
datums[
i] = &boundDatums[
i * partnatts];
835 boundinfo->
kind[
i] = &boundKinds[
i * partnatts];
836 for (
j = 0;
j < partnatts;
j++)
841 key->parttypbyval[
j],
858 int orig_index = rbounds[
i]->
index;
861 if ((*mapping)[orig_index] == -1)
862 (*mapping)[orig_index] = next_index++;
864 boundinfo->
indexes[
i] = (*mapping)[orig_index];
871 if (default_index != -1)
873 Assert(default_index >= 0 && (*mapping)[default_index] == -1);
874 (*mapping)[default_index] = next_index++;
883 Assert(next_index == nparts);
941 #ifdef USE_ASSERT_CHECKING
953 for (
j = 0;
j < partnatts;
j++)
956 if (b1->
kind != NULL)
984 parttypbyval[
j], parttyplen[
j]))
1019 partnatts =
key->partnatts;
1026 if (src->
kind != NULL)
1044 for (
i = 0;
i < ndatums;
i++)
1046 dest->kind[
i] = &boundKinds[
i * partnatts];
1062 natts = hash_part ? 2 : partnatts;
1063 boundDatums =
palloc(ndatums * natts *
sizeof(
Datum));
1065 for (
i = 0;
i < ndatums;
i++)
1069 dest->datums[
i] = &boundDatums[
i * natts];
1071 for (
j = 0;
j < natts;
j++)
1078 typlen =
sizeof(
int32);
1083 byval =
key->parttypbyval[
j];
1084 typlen =
key->parttyplen[
j];
1087 if (
dest->kind == NULL ||
1094 dest->indexes = (
int *)
palloc(
sizeof(
int) * nindexes);
1095 memcpy(
dest->indexes, src->
indexes,
sizeof(
int) * nindexes);
1122 List **outer_parts,
List **inner_parts)
1133 Assert(outer_rel->boundinfo->strategy == inner_rel->boundinfo->strategy);
1135 *outer_parts = *inner_parts =
NIL;
1136 switch (outer_rel->boundinfo->strategy)
1201 List **outer_parts,
List **inner_parts)
1217 int null_index = -1;
1218 int default_index = -1;
1237 outer_has_default =
false;
1239 inner_has_default =
false;
1248 outer_pos = inner_pos = 0;
1249 while (outer_pos < outer_bi->ndatums || inner_pos < inner_bi->ndatums)
1251 int outer_index = -1;
1252 int inner_index = -1;
1253 Datum *outer_datums;
1254 Datum *inner_datums;
1256 Datum *merged_datum = NULL;
1257 int merged_index = -1;
1259 if (outer_pos < outer_bi->ndatums)
1265 outer_index = outer_bi->
indexes[outer_pos];
1272 if (inner_pos < inner_bi->ndatums)
1278 inner_index = inner_bi->
indexes[inner_pos];
1287 outer_datums = outer_pos < outer_bi->
ndatums ?
1288 outer_bi->
datums[outer_pos] : NULL;
1289 inner_datums = inner_pos < inner_bi->
ndatums ?
1290 inner_bi->
datums[inner_pos] : NULL;
1301 if (outer_pos >= outer_bi->
ndatums)
1303 else if (inner_pos >= inner_bi->
ndatums)
1307 Assert(outer_datums != NULL && inner_datums != NULL);
1317 Assert(outer_pos < outer_bi->ndatums);
1318 Assert(inner_pos < inner_bi->ndatums);
1319 Assert(outer_index >= 0);
1320 Assert(inner_index >= 0);
1327 outer_index, inner_index,
1329 if (merged_index == -1)
1332 merged_datum = outer_datums;
1338 else if (cmpval < 0)
1341 Assert(outer_pos < outer_bi->ndatums);
1352 outer_index = outer_bi->
indexes[outer_pos];
1353 Assert(outer_index >= 0);
1363 if (merged_index == -1)
1365 merged_datum = outer_datums;
1375 Assert(inner_pos < inner_bi->ndatums);
1383 if (outer_has_default || jointype ==
JOIN_FULL)
1386 inner_index = inner_bi->
indexes[inner_pos];
1387 Assert(inner_index >= 0);
1397 if (merged_index == -1)
1399 merged_datum = inner_datums;
1410 if (merged_index >= 0 && merged_index != default_index)
1412 merged_datums =
lappend(merged_datums, merged_datum);
1413 merged_indexes =
lappend_int(merged_indexes, merged_index);
1421 if (outer_has_null &&
1423 outer_has_null =
false;
1424 if (inner_has_null &&
1426 inner_has_null =
false;
1429 if (outer_has_null || inner_has_null)
1431 outer_has_null, inner_has_null,
1433 jointype, &next_index, &null_index);
1435 Assert(null_index == -1);
1438 if (outer_has_default || inner_has_default)
1440 outer_has_default, inner_has_default,
1441 outer_default, inner_default,
1442 jointype, &next_index, &default_index);
1444 Assert(default_index == -1);
1454 next_index, merged_indexes);
1459 &outer_map, &inner_map,
1461 outer_parts, inner_parts);
1484 return merged_bounds;
1507 Oid *partcollations,
1510 List **outer_parts,
List **inner_parts)
1530 int default_index = -1;
1548 outer_has_default =
false;
1550 inner_has_default =
false;
1561 outer_lb_pos = inner_lb_pos = 0;
1563 &outer_lb, &outer_ub);
1565 &inner_lb, &inner_ub);
1566 while (outer_index >= 0 || inner_index >= 0)
1573 int merged_index = -1;
1584 if (outer_index == -1)
1590 else if (inner_index == -1)
1599 &outer_lb, &outer_ub,
1600 &inner_lb, &inner_ub,
1601 &lb_cmpval, &ub_cmpval);
1611 Assert(outer_index >= 0);
1613 outer_map.
merged[outer_index] ==
false);
1614 Assert(inner_index >= 0);
1616 inner_map.
merged[inner_index] ==
false);
1623 outer_index, inner_index,
1625 Assert(merged_index >= 0);
1629 partcollations, jointype,
1630 &outer_lb, &outer_ub,
1631 &inner_lb, &inner_ub,
1632 lb_cmpval, ub_cmpval,
1633 &merged_lb, &merged_ub);
1636 save_outer_ub = outer_ub;
1637 save_inner_ub = inner_ub;
1641 &outer_lb, &outer_ub);
1643 &inner_lb, &inner_ub);
1652 if (ub_cmpval > 0 && inner_index >= 0 &&
1654 &save_outer_ub, &inner_lb) > 0)
1656 if (ub_cmpval < 0 && outer_index >= 0 &&
1658 &outer_lb, &save_inner_ub) < 0)
1667 if ((outer_has_default && (lb_cmpval > 0 || ub_cmpval < 0)) ||
1668 (inner_has_default && (lb_cmpval < 0 || ub_cmpval > 0)))
1671 else if (ub_cmpval < 0)
1676 Assert(outer_index >= 0);
1678 outer_map.
merged[outer_index] ==
false);
1697 if (merged_index == -1)
1699 merged_lb = outer_lb;
1700 merged_ub = outer_ub;
1705 &outer_lb, &outer_ub);
1713 Assert(inner_index >= 0);
1715 inner_map.
merged[inner_index] ==
false);
1723 if (outer_has_default || jointype ==
JOIN_FULL)
1734 if (merged_index == -1)
1736 merged_lb = inner_lb;
1737 merged_ub = inner_ub;
1742 &inner_lb, &inner_ub);
1749 if (merged_index >= 0 && merged_index != default_index)
1751 &merged_lb, &merged_ub, merged_index,
1752 &merged_datums, &merged_kinds,
1757 if (outer_has_default || inner_has_default)
1759 outer_has_default, inner_has_default,
1760 outer_default, inner_default,
1761 jointype, &next_index, &default_index);
1763 Assert(default_index == -1);
1777 &outer_map, &inner_map,
1779 outer_parts, inner_parts);
1803 return merged_bounds;
1813 int nparts = rel->
nparts;
1821 for (
i = 0;
i < nparts;
i++)
1848 part_rel = rel->part_rels[part_index];
1863 int outer_index,
int inner_index,
int *next_index)
1865 int outer_merged_index;
1866 int inner_merged_index;
1870 Assert(outer_index >= 0 && outer_index < outer_map->nparts);
1872 outer_merged = outer_map->
merged[outer_index];
1873 Assert(inner_index >= 0 && inner_index < inner_map->nparts);
1875 inner_merged = inner_map->
merged[inner_index];
1881 if (outer_merged_index >= 0 && inner_merged_index >= 0)
1890 if (outer_merged_index == inner_merged_index)
1894 return outer_merged_index;
1896 if (!outer_merged && !inner_merged)
1905 if (outer_merged_index < inner_merged_index)
1907 outer_map->
merged[outer_index] =
true;
1909 inner_map->
merged[inner_index] =
true;
1911 inner_map->
old_indexes[inner_index] = inner_merged_index;
1912 return outer_merged_index;
1916 inner_map->
merged[inner_index] =
true;
1918 outer_map->
merged[outer_index] =
true;
1920 outer_map->
old_indexes[outer_index] = outer_merged_index;
1921 return inner_merged_index;
1928 Assert(outer_merged_index == -1 || inner_merged_index == -1);
1936 if (outer_merged_index == -1 && inner_merged_index == -1)
1938 int merged_index = *next_index;
1943 outer_map->
merged[outer_index] =
true;
1945 inner_map->
merged[inner_index] =
true;
1946 *next_index = *next_index + 1;
1947 return merged_index;
1949 if (outer_merged_index >= 0 && !outer_map->
merged[outer_index])
1951 Assert(inner_merged_index == -1);
1954 inner_map->
merged[inner_index] =
true;
1955 outer_map->
merged[outer_index] =
true;
1956 return outer_merged_index;
1958 if (inner_merged_index >= 0 && !inner_map->
merged[inner_index])
1960 Assert(outer_merged_index == -1);
1963 outer_map->
merged[outer_index] =
true;
1964 inner_map->
merged[inner_index] =
true;
1965 return inner_merged_index;
1982 bool outer_has_default,
1983 bool inner_has_default,
1990 int merged_index = -1;
1992 Assert(outer_index >= 0);
2002 if (inner_has_default)
2004 Assert(inner_default >= 0);
2013 if (outer_has_default)
2017 outer_index, inner_default,
2019 if (merged_index == -1)
2032 if (*default_index == -1)
2033 *default_index = merged_index;
2035 Assert(*default_index == merged_index);
2045 if (merged_index == -1)
2049 return merged_index;
2064 bool outer_has_default,
2065 bool inner_has_default,
2072 int merged_index = -1;
2074 Assert(inner_index >= 0);
2084 if (outer_has_default)
2086 Assert(outer_default >= 0);
2095 if (inner_has_default)
2099 outer_default, inner_index,
2101 if (merged_index == -1)
2115 if (*default_index == -1)
2116 *default_index = merged_index;
2118 Assert(*default_index == merged_index);
2127 if (merged_index == -1)
2131 return merged_index;
2149 bool outer_has_null,
2150 bool inner_has_null,
2157 bool consider_outer_null =
false;
2158 bool consider_inner_null =
false;
2160 Assert(outer_has_null || inner_has_null);
2161 Assert(*null_index == -1);
2169 Assert(outer_null >= 0 && outer_null < outer_map->nparts);
2171 consider_outer_null =
true;
2175 Assert(inner_null >= 0 && inner_null < inner_map->nparts);
2177 consider_inner_null =
true;
2181 if (!consider_outer_null && !consider_inner_null)
2184 if (consider_outer_null && !consider_inner_null)
2203 else if (!consider_outer_null && consider_inner_null)
2221 Assert(consider_outer_null && consider_inner_null);
2242 outer_null, inner_null,
2244 Assert(*null_index >= 0);
2259 bool outer_has_default,
2260 bool inner_has_default,
2267 int outer_merged_index = -1;
2268 int inner_merged_index = -1;
2270 Assert(outer_has_default || inner_has_default);
2273 if (outer_has_default)
2275 Assert(outer_default >= 0 && outer_default < outer_map->nparts);
2278 if (inner_has_default)
2280 Assert(inner_default >= 0 && inner_default < inner_map->nparts);
2284 if (outer_has_default && !inner_has_default)
2297 if (outer_merged_index == -1)
2299 Assert(*default_index == -1);
2305 Assert(*default_index == outer_merged_index);
2308 Assert(*default_index == -1);
2310 else if (!outer_has_default && inner_has_default)
2322 if (inner_merged_index == -1)
2324 Assert(*default_index == -1);
2330 Assert(*default_index == inner_merged_index);
2333 Assert(*default_index == -1);
2337 Assert(outer_has_default && inner_has_default);
2346 Assert(outer_merged_index == -1);
2347 Assert(inner_merged_index == -1);
2348 Assert(*default_index == -1);
2354 Assert(*default_index >= 0);
2369 int merged_index = *next_index;
2376 *next_index = *next_index + 1;
2377 return merged_index;
2386 int nmerged,
List *merged_indexes)
2395 new_indexes = (
int *)
palloc(
sizeof(
int) * nmerged);
2396 for (
i = 0;
i < nmerged;
i++)
2397 new_indexes[
i] = -1;
2405 if (merged_index >= 0)
2414 if (merged_index >= 0)
2420 foreach(lc, merged_indexes)
2423 Assert(merged_index >= 0);
2424 if (new_indexes[merged_index] >= 0)
2442 List **outer_parts,
List **inner_parts)
2444 int outer_nparts = outer_map->
nparts;
2445 int inner_nparts = inner_map->
nparts;
2455 outer_indexes = (
int *)
palloc(
sizeof(
int) * nmerged);
2456 inner_indexes = (
int *)
palloc(
sizeof(
int) * nmerged);
2457 for (
i = 0;
i < nmerged;
i++)
2458 outer_indexes[
i] = inner_indexes[
i] = -1;
2463 max_nparts =
Max(outer_nparts, inner_nparts);
2464 for (
i = 0;
i < max_nparts;
i++)
2466 if (
i < outer_nparts)
2470 if (merged_index >= 0)
2472 Assert(merged_index < nmerged);
2473 outer_indexes[merged_index] =
i;
2476 if (
i < inner_nparts)
2480 if (merged_index >= 0)
2482 Assert(merged_index < nmerged);
2483 inner_indexes[merged_index] =
i;
2489 for (
i = 0;
i < nmerged;
i++)
2491 int outer_index = outer_indexes[
i];
2492 int inner_index = inner_indexes[
i];
2500 if (outer_index == -1 && inner_index == -1)
2503 *outer_parts =
lappend(*outer_parts, outer_index >= 0 ?
2504 outer_rel->part_rels[outer_index] : NULL);
2505 *inner_parts =
lappend(*inner_parts, inner_index >= 0 ?
2506 inner_rel->part_rels[inner_index] : NULL);
2509 pfree(outer_indexes);
2510 pfree(inner_indexes);
2519 List *merged_kinds,
List *merged_indexes,
2520 int null_index,
int default_index)
2528 merged_bounds->
strategy = strategy;
2529 merged_bounds->
ndatums = ndatums;
2533 foreach(lc, merged_datums)
2542 foreach(lc, merged_kinds)
2553 merged_bounds->
kind = NULL;
2561 merged_bounds->
indexes = (
int *)
palloc(
sizeof(
int) * ndatums);
2563 foreach(lc, merged_indexes)
2569 return merged_bounds;
2594 if (part_index == -1)
2632 if (*lb_pos + 2 >= bi->
ndatums)
2641 if (bi->
indexes[*lb_pos + 2] < 0)
2642 *lb_pos = *lb_pos + 2;
2644 *lb_pos = *lb_pos + 1;
2663 Oid *partcollations,
2668 int *lb_cmpval,
int *ub_cmpval)
2675 outer_ub, inner_lb) < 0)
2687 outer_lb, inner_ub) > 0)
2696 outer_lb, inner_lb);
2698 outer_ub, inner_ub);
2717 int lb_cmpval,
int ub_cmpval,
2722 outer_lb, inner_lb) == lb_cmpval);
2724 outer_ub, inner_ub) == ub_cmpval);
2737 *merged_lb = (lb_cmpval > 0) ? *outer_lb : *inner_lb;
2738 *merged_ub = (ub_cmpval < 0) ? *outer_ub : *inner_ub;
2749 *merged_lb = *outer_lb;
2750 *merged_ub = *outer_ub;
2761 *merged_lb = (lb_cmpval < 0) ? *outer_lb : *inner_lb;
2762 *merged_ub = (ub_cmpval > 0) ? *outer_ub : *inner_ub;
2766 elog(
ERROR,
"unrecognized join type: %d", (
int) jointype);
2776 Oid *partcollations,
2780 List **merged_datums,
2781 List **merged_kinds,
2782 List **merged_indexes)
2786 if (!*merged_datums)
2790 Assert(!*merged_indexes);
2805 prev_ub.
lower =
false;
2827 *merged_datums =
lappend(*merged_datums, merged_lb->
datums);
2828 *merged_kinds =
lappend(*merged_kinds, merged_lb->
kind);
2829 *merged_indexes =
lappend_int(*merged_indexes, -1);
2833 *merged_datums =
lappend(*merged_datums, merged_ub->
datums);
2834 *merged_kinds =
lappend(*merged_kinds, merged_ub->
kind);
2835 *merged_indexes =
lappend_int(*merged_indexes, merged_index);
2854 Assert(boundinfo != NULL);
2903 bool overlap =
false;
2904 int overlap_location = -1;
2919 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2920 errmsg(
"partition \"%s\" conflicts with existing default partition \"%s\"",
2925 switch (
key->strategy)
2932 if (partdesc->
nparts > 0)
2934 int greatest_modulus;
2969 if (next_modulus % spec->
modulus != 0)
2971 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2972 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
2973 errdetail(
"The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\".",
2988 if (spec->
modulus % prev_modulus != 0)
2990 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2991 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
2992 errdetail(
"The new modulus %d is not divisible by %d, the modulus of existing partition \"%s\".",
2997 if (offset + 1 < boundinfo->
ndatums)
3010 if (next_modulus % spec->
modulus != 0)
3012 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3013 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
3014 errdetail(
"The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\".",
3020 greatest_modulus = boundinfo->
nindexes;
3029 if (remainder >= greatest_modulus)
3030 remainder = remainder % greatest_modulus;
3035 if (boundinfo->
indexes[remainder] != -1)
3039 with = boundinfo->
indexes[remainder];
3043 }
while (remainder < greatest_modulus);
3053 if (partdesc->
nparts > 0)
3067 overlap_location =
val->location;
3068 if (!
val->constisnull)
3078 if (offset >= 0 &&
equal)
3081 with = boundinfo->
indexes[offset];
3126 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3127 errmsg(
"empty range bound specified for partition \"%s\"",
3129 errdetail(
"Specified lower bound %s is greater than or equal to upper bound %s.",
3135 if (partdesc->
nparts > 0)
3165 if (boundinfo->
indexes[offset + 1] < 0)
3173 if (offset + 1 < boundinfo->
ndatums)
3179 datums = boundinfo->
datums[offset + 1];
3180 kind = boundinfo->
kind[offset + 1];
3181 is_lower = (boundinfo->
indexes[offset + 1] == -1);
3203 overlap_location = datum->
location;
3204 with = boundinfo->
indexes[offset + 2];
3223 overlap_location = datum->
location;
3224 with = boundinfo->
indexes[offset + 1];
3236 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3237 errmsg(
"partition \"%s\" would overlap partition \"%s\"",
3254 List *new_part_constraints;
3255 List *def_part_constraints;
3262 def_part_constraints =
3269 def_part_constraints =
3281 (
errmsg_internal(
"updated partition constraint for default partition \"%s\" is implied by existing constraints",
3290 if (default_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3296 foreach(lc, all_parts)
3300 Expr *partition_constraint;
3319 partition_constraint = (
Expr *)
3321 part_rel, default_rel);
3329 def_part_constraints))
3332 (
errmsg_internal(
"updated partition constraint for default partition \"%s\" is implied by existing constraints",
3341 part_rel = default_rel;
3349 if (part_rel->
rd_rel->relkind != RELKIND_RELATION)
3351 if (part_rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
3353 (
errcode(ERRCODE_CHECK_VIOLATION),
3354 errmsg(
"skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"",
3384 if (!
ExecCheck(partqualstate, econtext))
3386 (
errcode(ERRCODE_CHECK_VIOLATION),
3387 errmsg(
"updated partition constraint for default partition \"%s\" would be violated by some row",
3455 if (
val->constisnull)
3456 elog(
ERROR,
"invalid range bound datum");
3498 bool lower2 = b2->
lower;
3500 for (
i = 0;
i < partnatts;
i++)
3511 if (kind1[
i] < kind2[
i])
3513 else if (kind1[
i] > kind2[
i])
3539 if (cmpval == 0 && lower1 != lower2)
3540 cmpval = lower1 ? 1 : -1;
3542 return cmpval == 0 ? 0 : (cmpval < 0 ? -colnum : colnum);
3558 Datum *tuple_datums,
int n_tuple_datums)
3563 for (
i = 0;
i < n_tuple_datums;
i++)
3589 if (modulus1 < modulus2)
3591 if (modulus1 > modulus2)
3593 if (modulus1 == modulus2 && remainder1 != remainder2)
3594 return (remainder1 > remainder2) ? 1 : -1;
3621 mid = (lo + hi + 1) / 2;
3624 boundinfo->
datums[mid][0],
3629 *is_equal = (cmpval == 0);
3666 mid = (lo + hi + 1) / 2;
3670 boundinfo->
kind[mid],
3671 (boundinfo->
indexes[mid] == -1),
3709 mid = (lo + hi + 1) / 2;
3713 boundinfo->
kind[mid],
3719 *is_equal = (cmpval == 0);
3739 int modulus,
int remainder)
3753 mid = (lo + hi + 1) / 2;
3757 modulus, remainder);
3800 key->partcollation[0],
3842 key->partopcintype[col],
3843 key->partopcintype[col],
3846 elog(
ERROR,
"missing operator %d(%u,%u) in partition opfamily %u",
3847 strategy,
key->partopcintype[col],
key->partopcintype[col],
3848 key->partopfamily[col]);
3855 *need_relabel = (
key->parttypid[col] !=
key->partopcintype[col] &&
3856 key->partopcintype[col] != RECORDOID &&
3857 !IsPolymorphicType(
key->partopcintype[col]));
3872 bool need_relabel =
false;
3873 Expr *result = NULL;
3885 key->partcollation[keynum] !=
key->parttypcoll[keynum]))
3887 key->partopcintype[keynum],
3889 key->partcollation[keynum],
3893 switch (
key->strategy)
3911 arrexpr->array_typeid =
3913 arrexpr->array_collid =
key->parttypcoll[keynum];
3914 arrexpr->element_typeid =
key->parttypid[keynum];
3916 arrexpr->multidims =
false;
3921 saopexpr->
opno = operoid;
3925 saopexpr->
useOr =
true;
3926 saopexpr->inputcollid =
key->partcollation[keynum];
3930 result = (
Expr *) saopexpr;
3947 key->partcollation[keynum]);
3948 elemops =
lappend(elemops, elemop);
3962 key->partcollation[keynum]);
3989 Node *remainderConst;
4023 for (
i = 0;
i <
key->partnatts;
i++)
4028 if (
key->partattrs[
i] != 0)
4034 key->parttypcoll[
i],
4040 partexprs_item =
lnext(
key->partexprs, partexprs_item);
4075 bool list_has_null =
false;
4084 if (
key->partattrs[0] != 0)
4089 key->parttypcoll[0],
4111 list_has_null =
true;
4118 if (ndatums == 0 && !list_has_null)
4121 for (
i = 0;
i < ndatums;
i++)
4132 key->parttypcoll[0],
4135 key->parttypbyval[0],
4136 key->parttyplen[0]),
4138 key->parttypbyval[0]);
4152 if (
val->constisnull)
4153 list_has_null =
true;
4166 keyCol, (
Expr *) elems);
4185 nulltest->
arg = keyCol;
4187 nulltest->argisrow =
false;
4199 nulltest->
arg = keyCol;
4201 nulltest->argisrow =
false;
4282 *partexprs_item_saved;
4291 List *lower_or_arms,
4296 *upper_or_start_datum;
4297 bool need_next_lower_arm,
4298 need_next_upper_arm;
4305 int nparts = pdesc->
nparts,
4308 for (k = 0; k < nparts; k++)
4310 Oid inhrelid = inhoids[k];
4317 elog(
ERROR,
"cache lookup failed for relation %u", inhrelid);
4320 Anum_pg_class_relpartbound);
4324 elog(
ERROR,
"expected PartitionBoundSpec");
4343 if (or_expr_args !=
NIL)
4345 Expr *other_parts_constr;
4353 other_parts_constr =
4390 partexprs_item_saved = partexprs_item;
4408 partexprs_item_saved = partexprs_item;
4413 &lower_val, &upper_val);
4421 if (!lower_val || !upper_val)
4429 (
Expr *) upper_val);
4447 if (
i ==
key->partnatts - 1)
4448 elog(
ERROR,
"invalid range bound specification");
4453 keyCol, (
Expr *) lower_val));
4459 lower_or_start_datum = cell1;
4460 upper_or_start_datum = cell2;
4463 num_or_arms =
key->partnatts -
i;
4465 lower_or_arms = upper_or_arms =
NIL;
4466 need_next_lower_arm = need_next_upper_arm =
true;
4467 while (current_or_arm < num_or_arms)
4469 List *lower_or_arm_args =
NIL,
4470 *upper_or_arm_args =
NIL;
4474 partexprs_item = partexprs_item_saved;
4480 *udatum_next = NULL;
4493 &lower_val, &upper_val);
4495 if (need_next_lower_arm && lower_val)
4505 if (
j -
i < current_or_arm)
4507 else if (
j ==
key->partnatts - 1 ||
4514 lower_or_arm_args =
lappend(lower_or_arm_args,
4518 (
Expr *) lower_val));
4521 if (need_next_upper_arm && upper_val)
4530 if (
j -
i < current_or_arm)
4532 else if (udatum_next &&
4538 upper_or_arm_args =
lappend(upper_or_arm_args,
4542 (
Expr *) upper_val));
4551 if (
j -
i > current_or_arm)
4557 if (!lower_val || !ldatum_next ||
4559 need_next_lower_arm =
false;
4560 if (!upper_val || !udatum_next ||
4562 need_next_upper_arm =
false;
4567 if (lower_or_arm_args !=
NIL)
4568 lower_or_arms =
lappend(lower_or_arms,
4573 if (upper_or_arm_args !=
NIL)
4574 upper_or_arms =
lappend(upper_or_arms,
4580 if (!need_next_lower_arm && !need_next_upper_arm)
4591 if (lower_or_arms !=
NIL)
4596 if (upper_or_arms !=
NIL)
4609 result = for_default
4640 if (
key->partattrs[keynum] != 0)
4643 key->partattrs[keynum],
4644 key->parttypid[keynum],
4645 key->parttypmod[keynum],
4646 key->parttypcoll[keynum],
4651 if (*partexprs_item == NULL)
4652 elog(
ERROR,
"wrong number of partition key expressions");
4654 *partexprs_item =
lnext(
key->partexprs, *partexprs_item);
4684 for (
i = 0;
i <
key->partnatts;
i++)
4688 if (
key->partattrs[
i] != 0)
4694 key->parttypcoll[
i],
4699 if (partexprs_item == NULL)
4700 elog(
ERROR,
"wrong number of partition key expressions");
4702 partexprs_item =
lnext(
key->partexprs, partexprs_item);
4706 nulltest->
arg = keyCol;
4708 nulltest->argisrow =
false;
4710 result =
lappend(result, nulltest);
4729 for (
i = 0;
i < partnatts;
i++)
4773 typedef struct ColumnsHashData
4778 int16 variadic_typlen;
4779 bool variadic_typbyval;
4780 char variadic_typalign;
4788 ColumnsHashData *my_extra;
4801 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4802 errmsg(
"modulus for hash partition must be an integer value greater than zero")));
4805 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4806 errmsg(
"remainder for hash partition must be an integer value greater than or equal to zero")));
4807 if (remainder >= modulus)
4809 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4810 errmsg(
"remainder for hash partition must be less than modulus")));
4815 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4816 if (my_extra == NULL || my_extra->relid != parentId)
4829 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4830 errmsg(
"\"%s\" is not a hash partitioned table",
4838 if (
key->partnatts != nargs)
4840 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4841 errmsg(
"number of partitioning columns (%d) does not match number of partition keys provided (%d)",
4842 key->partnatts, nargs)));
4845 fcinfo->flinfo->fn_extra =
4847 offsetof(ColumnsHashData, partsupfunc) +
4849 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4850 my_extra->relid = parentId;
4851 my_extra->nkeys =
key->partnatts;
4852 memcpy(my_extra->partcollid,
key->partcollation,
4853 key->partnatts *
sizeof(
Oid));
4856 for (
j = 0;
j <
key->partnatts; ++
j)
4862 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4863 errmsg(
"column %d of the partition key has type %s, but supplied value is of type %s",
4867 &
key->partsupfunc[
j],
4868 fcinfo->flinfo->fn_mcxt);
4876 fcinfo->flinfo->fn_extra =
4878 offsetof(ColumnsHashData, partsupfunc) +
4880 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4881 my_extra->relid = parentId;
4882 my_extra->nkeys =
key->partnatts;
4883 my_extra->variadic_type =
ARR_ELEMTYPE(variadic_array);
4885 &my_extra->variadic_typlen,
4886 &my_extra->variadic_typbyval,
4887 &my_extra->variadic_typalign);
4888 my_extra->partcollid[0] =
key->partcollation[0];
4891 for (
j = 0;
j <
key->partnatts; ++
j)
4892 if (
key->parttypid[
j] != my_extra->variadic_type)
4894 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4895 errmsg(
"column %d of the partition key has type \"%s\", but supplied value is of type \"%s\"",
4901 &
key->partsupfunc[0],
4902 fcinfo->flinfo->fn_mcxt);
4911 int nkeys = my_extra->nkeys;
4920 for (
i = 0;
i < nkeys;
i++)
4931 my_extra->partcollid[
i],
4948 my_extra->variadic_type,
4949 my_extra->variadic_typlen,
4950 my_extra->variadic_typbyval,
4951 my_extra->variadic_typalign,
4952 &datum, &isnull, &nelems);
4955 if (nelems != my_extra->nkeys)
4957 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4958 errmsg(
"number of partitioning columns (%d) does not match number of partition keys provided (%d)",
4959 my_extra->nkeys, nelems)));
4961 for (
i = 0;
i < nelems;
i++)
4969 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 Assert(condition)
#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)
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
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)
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)
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 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)
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)
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)
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 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)
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)
MemoryContextSwitchTo(old_ctx)
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 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)