37#include "utils/fmgroids.h"
89#define compare_range_bounds(partnatts, partsupfunc, partcollations, \
91 (partition_rbound_cmp(partnatts, partsupfunc, partcollations, \
92 (bound1)->datums, (bound1)->kind, (bound1)->lower, \
131 bool outer_has_default,
132 bool inner_has_default,
140 bool outer_has_default,
141 bool inner_has_default,
158 bool outer_has_default,
159 bool inner_has_default,
169 int nmerged,
List *merged_indexes);
180 List *merged_indexes,
198 int *lb_cmpval,
int *ub_cmpval);
205 int lb_cmpval,
int ub_cmpval,
213 List **merged_datums,
215 List **merged_indexes);
257 switch (
key->strategy)
324 for (
i = 0;
i < nparts;
i++)
327 switch (
key->strategy)
354 int greatest_modulus;
366 for (
i = 0;
i < nparts;
i++)
371 elog(
ERROR,
"invalid strategy in partition bound spec");
383 greatest_modulus = hbounds[nparts - 1].
modulus;
387 boundinfo->
kind = NULL;
389 boundinfo->
nindexes = greatest_modulus;
390 boundinfo->
indexes = (
int *)
palloc(greatest_modulus *
sizeof(
int));
391 for (
i = 0;
i < greatest_modulus;
i++)
406 for (
i = 0;
i < nparts;
i++)
411 boundinfo->
datums[
i] = &boundDatums[
i * 2];
423 (*mapping)[hbounds[
i].
index] =
i;
440 for (
i = 0;
i < nparts;
i++)
444 foreach(lc, boundspecs[
i]->listdatums)
448 if (!
val->constisnull)
470 int default_index = -1;
485 for (
j = 0,
i = 0;
i < nparts;
i++)
491 elog(
ERROR,
"invalid strategy in partition bound spec");
508 if (!
val->constisnull)
520 if (null_index != -1)
521 elog(
ERROR,
"found null more than once");
535 boundinfo->
kind = NULL;
553 for (
i = 0;
i < ndatums;
i++)
555 int orig_index = all_values[
i].
index;
557 boundinfo->
datums[
i] = &boundDatums[
i];
559 key->parttypbyval[0],
563 if ((*mapping)[orig_index] == -1)
564 (*mapping)[orig_index] = next_index++;
566 boundinfo->
indexes[
i] = (*mapping)[orig_index];
579 if (null_index != -1)
582 if ((*mapping)[null_index] == -1)
583 (*mapping)[null_index] = next_index++;
584 boundinfo->
null_index = (*mapping)[null_index];
588 if (default_index != -1)
595 Assert(default_index >= 0);
596 Assert((*mapping)[default_index] == -1);
597 (*mapping)[default_index] = next_index++;
635 if (
index < last_index)
666 Assert(next_index == nparts);
686 int default_index = -1;
702 for (
i = 0;
i < nparts;
i++)
709 elog(
ERROR,
"invalid strategy in partition bound spec");
724 all_bounds[ndatums++] =
lower;
725 all_bounds[ndatums++] =
upper;
728 Assert(ndatums == nparts * 2 ||
729 (default_index != -1 && ndatums == (nparts - 1) * 2));
742 for (
i = 0;
i < ndatums;
i++)
745 bool is_distinct =
false;
749 for (
j = 0;
j <
key->partnatts;
j++)
753 if (prev == NULL ||
cur->kind[
j] != prev->
kind[
j])
768 key->partcollation[
j],
783 rbounds[k++] = all_bounds[
i];
819 partnatts =
key->partnatts;
823 for (
i = 0;
i < ndatums;
i++)
827 boundinfo->
datums[
i] = &boundDatums[
i * partnatts];
828 boundinfo->
kind[
i] = &boundKinds[
i * partnatts];
829 for (
j = 0;
j < partnatts;
j++)
834 key->parttypbyval[
j],
851 int orig_index = rbounds[
i]->
index;
854 if ((*mapping)[orig_index] == -1)
855 (*mapping)[orig_index] = next_index++;
857 boundinfo->
indexes[
i] = (*mapping)[orig_index];
864 if (default_index != -1)
866 Assert(default_index >= 0 && (*mapping)[default_index] == -1);
867 (*mapping)[default_index] = next_index++;
876 Assert(next_index == nparts);
934#ifdef USE_ASSERT_CHECKING
946 for (
j = 0;
j < partnatts;
j++)
949 if (b1->
kind != NULL)
977 parttypbyval[
j], parttyplen[
j]))
1009 partnatts =
key->partnatts;
1016 if (src->
kind != NULL && ndatums > 0)
1034 for (
i = 0;
i < ndatums;
i++)
1036 dest->kind[
i] = &boundKinds[
i * partnatts];
1054 int natts = hash_part ? 2 : partnatts;
1057 for (
i = 0;
i < ndatums;
i++)
1061 dest->datums[
i] = &boundDatums[
i * natts];
1063 for (
j = 0;
j < natts;
j++)
1065 if (
dest->kind == NULL ||
1073 typlen =
sizeof(
int32);
1078 byval =
key->parttypbyval[
j];
1079 typlen =
key->parttyplen[
j];
1089 memcpy(
dest->indexes, src->
indexes,
sizeof(
int) * nindexes);
1116 List **outer_parts,
List **inner_parts)
1127 Assert(outer_rel->boundinfo->strategy == inner_rel->boundinfo->strategy);
1129 *outer_parts = *inner_parts =
NIL;
1130 switch (outer_rel->boundinfo->strategy)
1195 List **outer_parts,
List **inner_parts)
1211 int null_index = -1;
1212 int default_index = -1;
1231 outer_has_default =
false;
1233 inner_has_default =
false;
1242 outer_pos = inner_pos = 0;
1243 while (outer_pos < outer_bi->ndatums || inner_pos < inner_bi->ndatums)
1245 int outer_index = -1;
1246 int inner_index = -1;
1247 Datum *outer_datums;
1248 Datum *inner_datums;
1250 Datum *merged_datum = NULL;
1251 int merged_index = -1;
1253 if (outer_pos < outer_bi->ndatums)
1259 outer_index = outer_bi->
indexes[outer_pos];
1266 if (inner_pos < inner_bi->ndatums)
1272 inner_index = inner_bi->
indexes[inner_pos];
1281 outer_datums = outer_pos < outer_bi->
ndatums ?
1282 outer_bi->
datums[outer_pos] : NULL;
1283 inner_datums = inner_pos < inner_bi->
ndatums ?
1284 inner_bi->
datums[inner_pos] : NULL;
1295 if (outer_pos >= outer_bi->
ndatums)
1297 else if (inner_pos >= inner_bi->
ndatums)
1301 Assert(outer_datums != NULL && inner_datums != NULL);
1311 Assert(outer_pos < outer_bi->ndatums);
1312 Assert(inner_pos < inner_bi->ndatums);
1313 Assert(outer_index >= 0);
1314 Assert(inner_index >= 0);
1321 outer_index, inner_index,
1323 if (merged_index == -1)
1326 merged_datum = outer_datums;
1332 else if (cmpval < 0)
1335 Assert(outer_pos < outer_bi->ndatums);
1346 outer_index = outer_bi->
indexes[outer_pos];
1347 Assert(outer_index >= 0);
1357 if (merged_index == -1)
1359 merged_datum = outer_datums;
1369 Assert(inner_pos < inner_bi->ndatums);
1377 if (outer_has_default || jointype ==
JOIN_FULL)
1380 inner_index = inner_bi->
indexes[inner_pos];
1381 Assert(inner_index >= 0);
1391 if (merged_index == -1)
1393 merged_datum = inner_datums;
1404 if (merged_index >= 0 && merged_index != default_index)
1406 merged_datums =
lappend(merged_datums, merged_datum);
1407 merged_indexes =
lappend_int(merged_indexes, merged_index);
1415 if (outer_has_null &&
1417 outer_has_null =
false;
1418 if (inner_has_null &&
1420 inner_has_null =
false;
1423 if (outer_has_null || inner_has_null)
1425 outer_has_null, inner_has_null,
1427 jointype, &next_index, &null_index);
1429 Assert(null_index == -1);
1432 if (outer_has_default || inner_has_default)
1434 outer_has_default, inner_has_default,
1435 outer_default, inner_default,
1436 jointype, &next_index, &default_index);
1438 Assert(default_index == -1);
1448 next_index, merged_indexes);
1453 &outer_map, &inner_map,
1455 outer_parts, inner_parts);
1478 return merged_bounds;
1501 Oid *partcollations,
1504 List **outer_parts,
List **inner_parts)
1524 int default_index = -1;
1542 outer_has_default =
false;
1544 inner_has_default =
false;
1555 outer_lb_pos = inner_lb_pos = 0;
1557 &outer_lb, &outer_ub);
1559 &inner_lb, &inner_ub);
1560 while (outer_index >= 0 || inner_index >= 0)
1567 int merged_index = -1;
1578 if (outer_index == -1)
1584 else if (inner_index == -1)
1593 &outer_lb, &outer_ub,
1594 &inner_lb, &inner_ub,
1595 &lb_cmpval, &ub_cmpval);
1605 Assert(outer_index >= 0);
1607 outer_map.
merged[outer_index] ==
false);
1608 Assert(inner_index >= 0);
1610 inner_map.
merged[inner_index] ==
false);
1617 outer_index, inner_index,
1619 Assert(merged_index >= 0);
1623 partcollations, jointype,
1624 &outer_lb, &outer_ub,
1625 &inner_lb, &inner_ub,
1626 lb_cmpval, ub_cmpval,
1627 &merged_lb, &merged_ub);
1630 save_outer_ub = outer_ub;
1631 save_inner_ub = inner_ub;
1635 &outer_lb, &outer_ub);
1637 &inner_lb, &inner_ub);
1646 if (ub_cmpval > 0 && inner_index >= 0 &&
1648 &save_outer_ub, &inner_lb) > 0)
1650 if (ub_cmpval < 0 && outer_index >= 0 &&
1652 &outer_lb, &save_inner_ub) < 0)
1661 if ((outer_has_default && (lb_cmpval > 0 || ub_cmpval < 0)) ||
1662 (inner_has_default && (lb_cmpval < 0 || ub_cmpval > 0)))
1665 else if (ub_cmpval < 0)
1670 Assert(outer_index >= 0);
1672 outer_map.
merged[outer_index] ==
false);
1691 if (merged_index == -1)
1693 merged_lb = outer_lb;
1694 merged_ub = outer_ub;
1699 &outer_lb, &outer_ub);
1707 Assert(inner_index >= 0);
1709 inner_map.
merged[inner_index] ==
false);
1717 if (outer_has_default || jointype ==
JOIN_FULL)
1728 if (merged_index == -1)
1730 merged_lb = inner_lb;
1731 merged_ub = inner_ub;
1736 &inner_lb, &inner_ub);
1743 if (merged_index >= 0 && merged_index != default_index)
1745 &merged_lb, &merged_ub, merged_index,
1746 &merged_datums, &merged_kinds,
1751 if (outer_has_default || inner_has_default)
1753 outer_has_default, inner_has_default,
1754 outer_default, inner_default,
1755 jointype, &next_index, &default_index);
1757 Assert(default_index == -1);
1771 &outer_map, &inner_map,
1773 outer_parts, inner_parts);
1797 return merged_bounds;
1807 int nparts = rel->
nparts;
1815 for (
i = 0;
i < nparts;
i++)
1842 part_rel = rel->part_rels[part_index];
1857 int outer_index,
int inner_index,
int *next_index)
1859 int outer_merged_index;
1860 int inner_merged_index;
1864 Assert(outer_index >= 0 && outer_index < outer_map->nparts);
1866 outer_merged = outer_map->
merged[outer_index];
1867 Assert(inner_index >= 0 && inner_index < inner_map->nparts);
1869 inner_merged = inner_map->
merged[inner_index];
1875 if (outer_merged_index >= 0 && inner_merged_index >= 0)
1884 if (outer_merged_index == inner_merged_index)
1888 return outer_merged_index;
1890 if (!outer_merged && !inner_merged)
1899 if (outer_merged_index < inner_merged_index)
1901 outer_map->
merged[outer_index] =
true;
1903 inner_map->
merged[inner_index] =
true;
1905 inner_map->
old_indexes[inner_index] = inner_merged_index;
1906 return outer_merged_index;
1910 inner_map->
merged[inner_index] =
true;
1912 outer_map->
merged[outer_index] =
true;
1914 outer_map->
old_indexes[outer_index] = outer_merged_index;
1915 return inner_merged_index;
1922 Assert(outer_merged_index == -1 || inner_merged_index == -1);
1930 if (outer_merged_index == -1 && inner_merged_index == -1)
1932 int merged_index = *next_index;
1937 outer_map->
merged[outer_index] =
true;
1939 inner_map->
merged[inner_index] =
true;
1940 *next_index = *next_index + 1;
1941 return merged_index;
1943 if (outer_merged_index >= 0 && !outer_map->
merged[outer_index])
1945 Assert(inner_merged_index == -1);
1948 inner_map->
merged[inner_index] =
true;
1949 outer_map->
merged[outer_index] =
true;
1950 return outer_merged_index;
1952 if (inner_merged_index >= 0 && !inner_map->
merged[inner_index])
1954 Assert(outer_merged_index == -1);
1957 outer_map->
merged[outer_index] =
true;
1958 inner_map->
merged[inner_index] =
true;
1959 return inner_merged_index;
1976 bool outer_has_default,
1977 bool inner_has_default,
1984 int merged_index = -1;
1986 Assert(outer_index >= 0);
1996 if (inner_has_default)
1998 Assert(inner_default >= 0);
2007 if (outer_has_default)
2011 outer_index, inner_default,
2013 if (merged_index == -1)
2026 if (*default_index == -1)
2027 *default_index = merged_index;
2029 Assert(*default_index == merged_index);
2039 if (merged_index == -1)
2043 return merged_index;
2058 bool outer_has_default,
2059 bool inner_has_default,
2066 int merged_index = -1;
2068 Assert(inner_index >= 0);
2078 if (outer_has_default)
2080 Assert(outer_default >= 0);
2089 if (inner_has_default)
2093 outer_default, inner_index,
2095 if (merged_index == -1)
2109 if (*default_index == -1)
2110 *default_index = merged_index;
2112 Assert(*default_index == merged_index);
2121 if (merged_index == -1)
2125 return merged_index;
2143 bool outer_has_null,
2144 bool inner_has_null,
2151 bool consider_outer_null =
false;
2152 bool consider_inner_null =
false;
2154 Assert(outer_has_null || inner_has_null);
2155 Assert(*null_index == -1);
2163 Assert(outer_null >= 0 && outer_null < outer_map->nparts);
2165 consider_outer_null =
true;
2169 Assert(inner_null >= 0 && inner_null < inner_map->nparts);
2171 consider_inner_null =
true;
2175 if (!consider_outer_null && !consider_inner_null)
2178 if (consider_outer_null && !consider_inner_null)
2197 else if (!consider_outer_null && consider_inner_null)
2215 Assert(consider_outer_null && consider_inner_null);
2236 outer_null, inner_null,
2238 Assert(*null_index >= 0);
2253 bool outer_has_default,
2254 bool inner_has_default,
2261 int outer_merged_index = -1;
2262 int inner_merged_index = -1;
2264 Assert(outer_has_default || inner_has_default);
2267 if (outer_has_default)
2269 Assert(outer_default >= 0 && outer_default < outer_map->nparts);
2272 if (inner_has_default)
2274 Assert(inner_default >= 0 && inner_default < inner_map->nparts);
2278 if (outer_has_default && !inner_has_default)
2291 if (outer_merged_index == -1)
2293 Assert(*default_index == -1);
2299 Assert(*default_index == outer_merged_index);
2302 Assert(*default_index == -1);
2304 else if (!outer_has_default && inner_has_default)
2316 if (inner_merged_index == -1)
2318 Assert(*default_index == -1);
2324 Assert(*default_index == inner_merged_index);
2327 Assert(*default_index == -1);
2331 Assert(outer_has_default && inner_has_default);
2340 Assert(outer_merged_index == -1);
2341 Assert(inner_merged_index == -1);
2342 Assert(*default_index == -1);
2348 Assert(*default_index >= 0);
2363 int merged_index = *next_index;
2370 *next_index = *next_index + 1;
2371 return merged_index;
2380 int nmerged,
List *merged_indexes)
2390 for (
i = 0;
i < nmerged;
i++)
2391 new_indexes[
i] = -1;
2399 if (merged_index >= 0)
2408 if (merged_index >= 0)
2414 foreach(lc, merged_indexes)
2417 Assert(merged_index >= 0);
2418 if (new_indexes[merged_index] >= 0)
2436 List **outer_parts,
List **inner_parts)
2438 int outer_nparts = outer_map->
nparts;
2439 int inner_nparts = inner_map->
nparts;
2451 for (
i = 0;
i < nmerged;
i++)
2452 outer_indexes[
i] = inner_indexes[
i] = -1;
2457 max_nparts =
Max(outer_nparts, inner_nparts);
2458 for (
i = 0;
i < max_nparts;
i++)
2460 if (
i < outer_nparts)
2464 if (merged_index >= 0)
2466 Assert(merged_index < nmerged);
2467 outer_indexes[merged_index] =
i;
2470 if (
i < inner_nparts)
2474 if (merged_index >= 0)
2476 Assert(merged_index < nmerged);
2477 inner_indexes[merged_index] =
i;
2483 for (
i = 0;
i < nmerged;
i++)
2485 int outer_index = outer_indexes[
i];
2486 int inner_index = inner_indexes[
i];
2494 if (outer_index == -1 && inner_index == -1)
2497 *outer_parts =
lappend(*outer_parts, outer_index >= 0 ?
2498 outer_rel->part_rels[outer_index] : NULL);
2499 *inner_parts =
lappend(*inner_parts, inner_index >= 0 ?
2500 inner_rel->part_rels[inner_index] : NULL);
2503 pfree(outer_indexes);
2504 pfree(inner_indexes);
2513 List *merged_kinds,
List *merged_indexes,
2514 int null_index,
int default_index)
2522 merged_bounds->
strategy = strategy;
2523 merged_bounds->
ndatums = ndatums;
2527 foreach(lc, merged_datums)
2535 foreach(lc, merged_kinds)
2546 merged_bounds->
kind = NULL;
2556 foreach(lc, merged_indexes)
2562 return merged_bounds;
2587 if (part_index == -1)
2625 if (*lb_pos + 2 >= bi->
ndatums)
2634 if (bi->
indexes[*lb_pos + 2] < 0)
2635 *lb_pos = *lb_pos + 2;
2637 *lb_pos = *lb_pos + 1;
2656 Oid *partcollations,
2661 int *lb_cmpval,
int *ub_cmpval)
2668 outer_ub, inner_lb) < 0)
2680 outer_lb, inner_ub) > 0)
2689 outer_lb, inner_lb);
2691 outer_ub, inner_ub);
2710 int lb_cmpval,
int ub_cmpval,
2715 outer_lb, inner_lb) == lb_cmpval);
2717 outer_ub, inner_ub) == ub_cmpval);
2730 *merged_lb = (lb_cmpval > 0) ? *outer_lb : *inner_lb;
2731 *merged_ub = (ub_cmpval < 0) ? *outer_ub : *inner_ub;
2742 *merged_lb = *outer_lb;
2743 *merged_ub = *outer_ub;
2754 *merged_lb = (lb_cmpval < 0) ? *outer_lb : *inner_lb;
2755 *merged_ub = (ub_cmpval > 0) ? *outer_ub : *inner_ub;
2759 elog(
ERROR,
"unrecognized join type: %d", (
int) jointype);
2769 Oid *partcollations,
2773 List **merged_datums,
2774 List **merged_kinds,
2775 List **merged_indexes)
2779 if (!*merged_datums)
2783 Assert(!*merged_indexes);
2798 prev_ub.
lower =
false;
2820 *merged_datums =
lappend(*merged_datums, merged_lb->
datums);
2821 *merged_kinds =
lappend(*merged_kinds, merged_lb->
kind);
2822 *merged_indexes =
lappend_int(*merged_indexes, -1);
2826 *merged_datums =
lappend(*merged_datums, merged_ub->
datums);
2827 *merged_kinds =
lappend(*merged_kinds, merged_ub->
kind);
2828 *merged_indexes =
lappend_int(*merged_indexes, merged_index);
2847 Assert(boundinfo != NULL);
2896 bool overlap =
false;
2897 int overlap_location = -1;
2912 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2913 errmsg(
"partition \"%s\" conflicts with existing default partition \"%s\"",
2918 switch (
key->strategy)
2925 if (partdesc->
nparts > 0)
2927 int greatest_modulus;
2962 if (next_modulus % spec->
modulus != 0)
2964 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2965 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
2966 errdetail(
"The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\".",
2981 if (spec->
modulus % prev_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 divisible by %d, the modulus of existing partition \"%s\".",
2990 if (offset + 1 < boundinfo->
ndatums)
3003 if (next_modulus % spec->
modulus != 0)
3005 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3006 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
3007 errdetail(
"The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\".",
3013 greatest_modulus = boundinfo->
nindexes;
3046 if (partdesc->
nparts > 0)
3060 overlap_location =
val->location;
3061 if (!
val->constisnull)
3071 if (offset >= 0 &&
equal)
3074 with = boundinfo->
indexes[offset];
3119 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3120 errmsg(
"empty range bound specified for partition \"%s\"",
3122 errdetail(
"Specified lower bound %s is greater than or equal to upper bound %s.",
3128 if (partdesc->
nparts > 0)
3158 if (boundinfo->
indexes[offset + 1] < 0)
3166 if (offset + 1 < boundinfo->
ndatums)
3172 datums = boundinfo->
datums[offset + 1];
3173 kind = boundinfo->
kind[offset + 1];
3174 is_lower = (boundinfo->
indexes[offset + 1] == -1);
3196 overlap_location = datum->
location;
3197 with = boundinfo->
indexes[offset + 2];
3216 overlap_location = datum->
location;
3217 with = boundinfo->
indexes[offset + 1];
3229 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3230 errmsg(
"partition \"%s\" would overlap partition \"%s\"",
3247 List *new_part_constraints;
3248 List *def_part_constraints;
3255 def_part_constraints =
3262 def_part_constraints =
3274 (
errmsg_internal(
"updated partition constraint for default partition \"%s\" is implied by existing constraints",
3283 if (default_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3289 foreach(lc, all_parts)
3293 Expr *partition_constraint;
3312 partition_constraint = (
Expr *)
3314 part_rel, default_rel);
3322 def_part_constraints))
3325 (
errmsg_internal(
"updated partition constraint for default partition \"%s\" is implied by existing constraints",
3334 part_rel = default_rel;
3342 if (part_rel->
rd_rel->relkind != RELKIND_RELATION)
3344 if (part_rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
3346 (
errcode(ERRCODE_CHECK_VIOLATION),
3347 errmsg(
"skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"",
3377 if (!
ExecCheck(partqualstate, econtext))
3379 (
errcode(ERRCODE_CHECK_VIOLATION),
3380 errmsg(
"updated partition constraint for default partition \"%s\" would be violated by some row",
3447 if (
val->constisnull)
3448 elog(
ERROR,
"invalid range bound datum");
3490 bool lower2 = b2->
lower;
3492 for (
i = 0;
i < partnatts;
i++)
3503 if (kind1[
i] < kind2[
i])
3505 else if (kind1[
i] > kind2[
i])
3531 if (cmpval == 0 && lower1 != lower2)
3532 cmpval = lower1 ? 1 : -1;
3534 return cmpval == 0 ? 0 : (cmpval < 0 ? -colnum : colnum);
3550 const Datum *tuple_datums,
int n_tuple_datums)
3555 for (
i = 0;
i < n_tuple_datums;
i++)
3581 if (modulus1 < modulus2)
3583 if (modulus1 > modulus2)
3585 if (modulus1 == modulus2 && remainder1 != remainder2)
3586 return (remainder1 > remainder2) ? 1 : -1;
3613 mid = (lo + hi + 1) / 2;
3616 boundinfo->
datums[mid][0],
3621 *is_equal = (cmpval == 0);
3658 mid = (lo + hi + 1) / 2;
3662 boundinfo->
kind[mid],
3663 (boundinfo->
indexes[mid] == -1),
3701 mid = (lo + hi + 1) / 2;
3705 boundinfo->
kind[mid],
3711 *is_equal = (cmpval == 0);
3745 mid = (lo + hi + 1) / 2;
3792 key->partcollation[0],
3834 key->partopcintype[col],
3835 key->partopcintype[col],
3838 elog(
ERROR,
"missing operator %d(%u,%u) in partition opfamily %u",
3839 strategy,
key->partopcintype[col],
key->partopcintype[col],
3840 key->partopfamily[col]);
3847 *need_relabel = (
key->parttypid[col] !=
key->partopcintype[col] &&
3848 key->partopcintype[col] != RECORDOID &&
3849 !IsPolymorphicType(
key->partopcintype[col]));
3864 bool need_relabel =
false;
3865 Expr *result = NULL;
3877 key->partcollation[keynum] !=
key->parttypcoll[keynum]))
3879 key->partopcintype[keynum],
3881 key->partcollation[keynum],
3885 switch (
key->strategy)
3903 arrexpr->array_typeid =
3905 arrexpr->array_collid =
key->parttypcoll[keynum];
3906 arrexpr->element_typeid =
key->parttypid[keynum];
3907 arrexpr->elements = elems;
3908 arrexpr->multidims =
false;
3913 saopexpr->
opno = operoid;
3917 saopexpr->
useOr =
true;
3918 saopexpr->inputcollid =
key->partcollation[keynum];
3922 result = (
Expr *) saopexpr;
3939 key->partcollation[keynum]);
3940 elemops =
lappend(elemops, elemop);
3954 key->partcollation[keynum]);
3981 Node *remainderConst;
4015 for (
i = 0;
i <
key->partnatts;
i++)
4020 if (
key->partattrs[
i] != 0)
4026 key->parttypcoll[
i],
4032 partexprs_item =
lnext(
key->partexprs, partexprs_item);
4067 bool list_has_null =
false;
4076 if (
key->partattrs[0] != 0)
4081 key->parttypcoll[0],
4103 list_has_null =
true;
4110 if (ndatums == 0 && !list_has_null)
4113 for (
i = 0;
i < ndatums;
i++)
4124 key->parttypcoll[0],
4127 key->parttypbyval[0],
4128 key->parttyplen[0]),
4130 key->parttypbyval[0]);
4144 if (
val->constisnull)
4145 list_has_null =
true;
4158 keyCol, (
Expr *) elems);
4177 nulltest->
arg = keyCol;
4179 nulltest->argisrow =
false;
4191 nulltest->
arg = keyCol;
4193 nulltest->argisrow =
false;
4274 *partexprs_item_saved;
4283 List *lower_or_arms,
4288 *upper_or_start_datum;
4289 bool need_next_lower_arm,
4290 need_next_upper_arm;
4297 int nparts = pdesc->
nparts,
4300 for (k = 0; k < nparts; k++)
4302 Oid inhrelid = inhoids[k];
4309 elog(
ERROR,
"cache lookup failed for relation %u", inhrelid);
4312 Anum_pg_class_relpartbound);
4316 elog(
ERROR,
"expected PartitionBoundSpec");
4335 if (or_expr_args !=
NIL)
4337 Expr *other_parts_constr;
4345 other_parts_constr =
4382 partexprs_item_saved = partexprs_item;
4400 partexprs_item_saved = partexprs_item;
4405 &lower_val, &upper_val);
4413 if (!lower_val || !upper_val)
4421 (
Expr *) upper_val);
4439 if (
i ==
key->partnatts - 1)
4440 elog(
ERROR,
"invalid range bound specification");
4445 keyCol, (
Expr *) lower_val));
4451 lower_or_start_datum = cell1;
4452 upper_or_start_datum = cell2;
4455 num_or_arms =
key->partnatts -
i;
4457 lower_or_arms = upper_or_arms =
NIL;
4458 need_next_lower_arm = need_next_upper_arm =
true;
4459 while (current_or_arm < num_or_arms)
4461 List *lower_or_arm_args =
NIL,
4462 *upper_or_arm_args =
NIL;
4466 partexprs_item = partexprs_item_saved;
4472 *udatum_next = NULL;
4485 &lower_val, &upper_val);
4487 if (need_next_lower_arm && lower_val)
4497 if (
j -
i < current_or_arm)
4499 else if (
j ==
key->partnatts - 1 ||
4506 lower_or_arm_args =
lappend(lower_or_arm_args,
4510 (
Expr *) lower_val));
4513 if (need_next_upper_arm && upper_val)
4522 if (
j -
i < current_or_arm)
4524 else if (udatum_next &&
4530 upper_or_arm_args =
lappend(upper_or_arm_args,
4534 (
Expr *) upper_val));
4543 if (
j -
i > current_or_arm)
4549 if (!lower_val || !ldatum_next ||
4551 need_next_lower_arm =
false;
4552 if (!upper_val || !udatum_next ||
4554 need_next_upper_arm =
false;
4559 if (lower_or_arm_args !=
NIL)
4560 lower_or_arms =
lappend(lower_or_arms,
4565 if (upper_or_arm_args !=
NIL)
4566 upper_or_arms =
lappend(upper_or_arms,
4572 if (!need_next_lower_arm && !need_next_upper_arm)
4583 if (lower_or_arms !=
NIL)
4588 if (upper_or_arms !=
NIL)
4601 result = for_default
4632 if (
key->partattrs[keynum] != 0)
4635 key->partattrs[keynum],
4636 key->parttypid[keynum],
4637 key->parttypmod[keynum],
4638 key->parttypcoll[keynum],
4643 if (*partexprs_item == NULL)
4644 elog(
ERROR,
"wrong number of partition key expressions");
4646 *partexprs_item =
lnext(
key->partexprs, *partexprs_item);
4676 for (
i = 0;
i <
key->partnatts;
i++)
4680 if (
key->partattrs[
i] != 0)
4686 key->parttypcoll[
i],
4691 if (partexprs_item == NULL)
4692 elog(
ERROR,
"wrong number of partition key expressions");
4694 partexprs_item =
lnext(
key->partexprs, partexprs_item);
4698 nulltest->
arg = keyCol;
4700 nulltest->argisrow =
false;
4702 result =
lappend(result, nulltest);
4721 for (
i = 0;
i < partnatts;
i++)
4765 typedef struct ColumnsHashData
4770 int16 variadic_typlen;
4771 bool variadic_typbyval;
4772 char variadic_typalign;
4780 ColumnsHashData *my_extra;
4793 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4794 errmsg(
"modulus for hash partition must be an integer value greater than zero")));
4797 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4798 errmsg(
"remainder for hash partition must be an integer value greater than or equal to zero")));
4801 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4802 errmsg(
"remainder for hash partition must be less than modulus")));
4807 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4808 if (my_extra == NULL || my_extra->relid != parentId)
4821 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4822 errmsg(
"\"%s\" is not a hash partitioned table",
4830 if (
key->partnatts != nargs)
4832 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4833 errmsg(
"number of partitioning columns (%d) does not match number of partition keys provided (%d)",
4834 key->partnatts, nargs)));
4837 fcinfo->flinfo->fn_extra =
4839 offsetof(ColumnsHashData, partsupfunc) +
4841 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4842 my_extra->relid = parentId;
4843 my_extra->nkeys =
key->partnatts;
4844 memcpy(my_extra->partcollid,
key->partcollation,
4845 key->partnatts *
sizeof(
Oid));
4848 for (
j = 0;
j <
key->partnatts; ++
j)
4854 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4855 errmsg(
"column %d of the partition key has type %s, but supplied value is of type %s",
4859 &
key->partsupfunc[
j],
4860 fcinfo->flinfo->fn_mcxt);
4868 fcinfo->flinfo->fn_extra =
4870 offsetof(ColumnsHashData, partsupfunc) +
4872 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4873 my_extra->relid = parentId;
4874 my_extra->nkeys =
key->partnatts;
4875 my_extra->variadic_type =
ARR_ELEMTYPE(variadic_array);
4877 &my_extra->variadic_typlen,
4878 &my_extra->variadic_typbyval,
4879 &my_extra->variadic_typalign);
4880 my_extra->partcollid[0] =
key->partcollation[0];
4883 for (
j = 0;
j <
key->partnatts; ++
j)
4884 if (
key->parttypid[
j] != my_extra->variadic_type)
4886 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4887 errmsg(
"column %d of the partition key has type \"%s\", but supplied value is of type \"%s\"",
4893 &
key->partsupfunc[0],
4894 fcinfo->flinfo->fn_mcxt);
4903 int nkeys = my_extra->nkeys;
4912 for (
i = 0;
i < nkeys;
i++)
4923 my_extra->partcollid[
i],
4940 my_extra->variadic_type,
4941 my_extra->variadic_typlen,
4942 my_extra->variadic_typbyval,
4943 my_extra->variadic_typalign,
4944 &datum, &isnull, &nelems);
4947 if (nelems != my_extra->nkeys)
4949 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4950 errmsg(
"number of partitioning columns (%d) does not match number of partition keys provided (%d)",
4951 my_extra->nkeys, nelems)));
4953 for (
i = 0;
i < nelems;
i++)
4961 my_extra->partcollid[0],
5024 false, first_upper);
5025 if ((!defaultPart && cmpval) || (defaultPart && cmpval < 0))
5031 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5032 errmsg(
"can not merge partition \"%s\" together with partition \"%s\"",
5034 errdetail(
"lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
5036 errhint(
"ALTER TABLE ... MERGE PARTITIONS requires the partition bounds to be adjacent."),
5040 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5041 errmsg(
"can not split to partition \"%s\" together with partition \"%s\"",
5043 errdetail(
"lower bound of partition \"%s\" is not equal to the upper bound of partition \"%s\"",
5045 errhint(
"ALTER TABLE ... SPLIT PARTITION requires the partition bounds to be adjacent."),
5066 elog(
ERROR,
"cache lookup failed for relation %u", partOid);
5069 Anum_pg_class_relpartbound,
5072 elog(
ERROR,
"partition bound for relation %u is null",
5078 elog(
ERROR,
"expected PartitionBoundSpec for relation %u",
5109 switch (
key->strategy)
5130 bounds =
lappend(bounds, bound);
5138 for (
i = 1;
i < nparts;
i++)
5141 int prev_index = lower_bounds[
i - 1]->
index;
5167 pfree(lower_bounds);
5184 elog(
ERROR,
"unexpected partition strategy: %d",
5185 (
int)
key->strategy);
5205 const List *list1,
const List *list2)
5209 if (list1 ==
NIL || list2 ==
NIL)
5214 bool isnull1 = val1->constisnull;
5218 if (val2->constisnull)
5222 result =
lappend(result, val1);
5234 val2->constvalue)) == 0)
5236 result =
lappend(result, val1);
5272 for (
i = 0;
i < nparts;
i++)
5276 for (
j =
i + 1;
j < nparts;
j++)
5289 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5290 errmsg(
"new partition \"%s\" would overlap with another new partition \"%s\"",
5361 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5362 errmsg(
"empty range bound specified for partition \"%s\"",
5364 errdetail(
"Specified lower bound %s is greater than or equal to upper bound %s.",
5403 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5404 errmsg(
"lower bound of partition \"%s\" is not equal to lower bound of split partition \"%s\"",
5407 errhint(
"%s require combined bounds of new partitions must exactly match the bound of the split partition",
5408 "ALTER TABLE ... SPLIT PARTITION"),
5411 else if (cmpval < 0)
5413 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5414 errmsg(
"lower bound of partition \"%s\" is less than lower bound of split partition \"%s\"",
5417 errhint(
"%s require combined bounds of new partitions must exactly match the bound of the split partition",
5418 "ALTER TABLE ... SPLIT PARTITION"),
5431 false, split_upper);
5445 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5446 errmsg(
"upper bound of partition \"%s\" is not equal to upper bound of split partition \"%s\"",
5449 errhint(
"%s require combined bounds of new partitions must exactly match the bound of the split partition",
5450 "ALTER TABLE ... SPLIT PARTITION"),
5453 else if (cmpval > 0)
5455 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5456 errmsg(
"upper bound of partition \"%s\" is greater than upper bound of split partition \"%s\"",
5459 errhint(
"%s require combined bounds of new partitions must exactly match the bound of the split partition",
5460 "ALTER TABLE ... SPLIT PARTITION"),
5490 bool overlap =
false;
5491 int overlap_location = -1;
5505 if (!
val->constisnull)
5515 if (offset >= 0 &&
equal)
5517 with = boundinfo->
indexes[offset];
5518 if (partdesc->
oids[with] != splitPartOid)
5526 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5527 errmsg(
"new partition \"%s\" cannot have this value because split partition \"%s\" does not have",
5535 if (partdesc->
oids[with] != splitPartOid)
5543 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5544 errmsg(
"new partition \"%s\" cannot have NULL value because split partition \"%s\" does not have",
5554 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5555 errmsg(
"new partition \"%s\" would overlap with another (not split) partition \"%s\"",
5585 for (
int i = 0;
i < nparts;
i++)
5591 if (isnull &&
val->constisnull)
5594 if (!isnull && !
val->constisnull)
5645 key->partcollation, parts, nparts, datum,
true))
5651 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5652 errmsg(
"new partitions combined partition bounds do not contain value (%s) but split partition \"%s\" does",
5655 errhint(
"%s require combined bounds of new partitions must exactly match the bound of the split partition",
5656 "ALTER TABLE ... SPLIT PARTITION"));
5667 datum = boundinfo->
datums[
i][0];
5669 key->partcollation, parts, nparts, datum,
false))
5687 key->parttypcoll[0],
5691 key->parttypbyval[0]);
5694 errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
5695 errmsg(
"new partitions combined partition bounds do not contain value (%s) but split partition \"%s\" does",
5698 errhint(
"%s require combined bounds of new partitions must exactly match the bound of the split partition",
5699 "ALTER TABLE ... SPLIT PARTITION"));
5731 bool isSplitPartDefault;
5732 bool createDefaultPart =
false;
5733 int default_index = -1;
5760 isSplitPartDefault = (defaultPartOid == splitPartOid);
5764 if (sps->bound->is_default)
5767 new_parts[nparts++] = sps;
5771 if (default_index != -1)
5773 createDefaultPart =
true;
5790 for (
i = 0;
i < nparts;
i++)
5793 new_parts[
i]->bound->lowerdatums,
true);
5801 tmp_new_parts = new_parts;
5803 for (
i = 0;
i < nparts;
i++)
5804 new_parts[
i] = tmp_new_parts[lower_bounds[
i]->
index];
5806 pfree(tmp_new_parts);
5807 pfree(lower_bounds);
5810 for (
i = 0;
i < nparts;
i++)
5814 if (isSplitPartDefault)
5835 bool first = (
i == 0);
5836 bool last = (
i == (nparts - 1));
5839 splitPartOid, first, last,
5840 createDefaultPart, pstate);
5844 sps->
bound, splitPartOid, pstate);
5869 if (!createDefaultPart)
5871 new_parts, nparts, pstate);
#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 PG_USED_FOR_ASSERTS_ONLY
#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 errhint(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 * list_concat(List *list1, const List *list2)
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()
int exprLocation(const Node *expr)
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 void check_partition_bounds_for_split_list(Relation parent, char *relname, PartitionBoundSpec *spec, Oid splitPartOid, ParseState *pstate)
static List * get_qual_for_list(Relation parent, PartitionBoundSpec *spec)
static void check_parent_values_in_new_partitions(Relation parent, Oid partOid, SinglePartitionSpec **parts, int nparts, ParseState *pstate)
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)
static void check_two_partitions_bounds_range(Relation parent, RangeVar *first_name, PartitionBoundSpec *first_bound, RangeVar *second_name, PartitionBoundSpec *second_bound, bool defaultPart, bool is_merge, ParseState *pstate)
#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 PartitionBoundSpec * get_partition_bound_spec(Oid partOid)
static int merge_partition_with_dummy(PartitionMap *map, int index, int *next_index)
static void check_partition_bounds_for_split_range(Relation parent, char *relname, PartitionBoundSpec *spec, Oid splitPartOid, bool first, bool last, bool defaultPart, ParseState *pstate)
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 bool find_value_in_new_partitions_list(FmgrInfo *partsupfunc, Oid *partcollation, SinglePartitionSpec **parts, int nparts, Datum value, bool isnull)
void check_partitions_for_split(Relation parent, Oid splitPartOid, List *partlist, ParseState *pstate)
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 List * partitions_listdatum_intersection(FmgrInfo *partsupfunc, Oid *partcollation, const List *list1, const List *list2)
void calculate_partition_bound_for_merge(Relation parent, List *partNames, List *partOids, PartitionBoundSpec *spec, ParseState *pstate)
static int32 qsort_partition_list_value_cmp(const void *a, const void *b, void *arg)
static void check_partitions_not_overlap_list(Relation parent, SinglePartitionSpec **parts, int nparts, ParseState *pstate)
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)
static int get_partition_strategy(PartitionKey key)
struct PartitionKeyData * PartitionKey
struct PartitionBoundInfoData * PartitionBoundInfo
PartitionDesc RelationGetPartitionDesc(Relation rel, bool omit_detached)
Oid get_default_oid_from_partdesc(PartitionDesc partdesc)
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 linitial_node(type, l)
#define forboth(cell1, list1, cell2, list2)
#define foreach_current_index(var_or_cell)
#define list_make1_oid(x1)
static void * list_nth(const List *list, int n)
#define list_make3(x1, x2, x3)
#define foreach_node(type, var, lst)
static ListCell * list_head(const List *l)
#define for_both_cell(cell1, list1, initcell1, cell2, list2, initcell2)
#define foreach_oid(var, lst)
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 PointerGetDatum(const void *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 * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
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
PartitionBoundSpec * bound
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
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)