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);
275 elog(
ERROR,
"unexpected partition strategy: %d",
327 *mapping = (
int *)
palloc(
sizeof(
int) * nparts);
328 for (i = 0; i < nparts; i++)
343 elog(
ERROR,
"unexpected partition strategy: %d",
364 int greatest_modulus;
378 for (i = 0; i < nparts; i++)
383 elog(
ERROR,
"invalid strategy in partition bound spec");
396 greatest_modulus = hbounds[ndatums - 1]->
modulus;
400 boundinfo->
nindexes = greatest_modulus;
401 boundinfo->
indexes = (
int *)
palloc(greatest_modulus *
sizeof(
int));
402 for (i = 0; i < greatest_modulus; i++)
410 for (i = 0; i < nparts; i++)
419 while (remainder < greatest_modulus)
427 (*mapping)[hbounds[
i]->
index] =
i;
449 int default_index = -1;
461 for (i = 0; i < nparts; i++)
467 elog(
ERROR,
"invalid strategy in partition bound spec");
498 if (null_index != -1)
499 elog(
ERROR,
"found null more than once");
504 non_null_values =
lappend(non_null_values, list_value);
517 foreach(cell, non_null_values)
542 for (i = 0; i < ndatums; i++)
544 int orig_index = all_values[
i]->
index;
548 key->parttypbyval[0],
552 if ((*mapping)[orig_index] == -1)
553 (*mapping)[orig_index] = next_index++;
555 boundinfo->
indexes[
i] = (*mapping)[orig_index];
566 if (null_index != -1)
569 if ((*mapping)[null_index] == -1)
570 (*mapping)[null_index] = next_index++;
571 boundinfo->
null_index = (*mapping)[null_index];
575 if (default_index != -1)
582 Assert(default_index >= 0);
583 Assert((*mapping)[default_index] == -1);
584 (*mapping)[default_index] = next_index++;
589 Assert(next_index == nparts);
608 int default_index = -1;
624 for (i = 0; i < nparts; i++)
631 elog(
ERROR,
"invalid strategy in partition bound spec");
646 all_bounds[ndatums++] =
lower;
647 all_bounds[ndatums++] =
upper;
650 Assert(ndatums == nparts * 2 ||
651 (default_index != -1 && ndatums == (nparts - 1) * 2));
664 for (i = 0; i < ndatums; i++)
667 bool is_distinct =
false;
671 for (j = 0; j < key->partnatts; j++)
675 if (prev == NULL || cur->
kind[j] != prev->
kind[j])
690 key->partcollation[j],
705 rbounds[k++] = all_bounds[
i];
732 boundinfo->
indexes = (
int *)
palloc((ndatums + 1) *
sizeof(int));
734 for (i = 0; i < ndatums; i++)
743 for (j = 0; j < key->partnatts; j++)
748 key->parttypbyval[j],
761 if (rbounds[i]->
lower)
765 int orig_index = rbounds[
i]->
index;
768 if ((*mapping)[orig_index] == -1)
769 (*mapping)[orig_index] = next_index++;
771 boundinfo->
indexes[
i] = (*mapping)[orig_index];
776 if (default_index != -1)
778 Assert(default_index >= 0 && (*mapping)[default_index] == -1);
779 (*mapping)[default_index] = next_index++;
788 Assert(next_index == nparts);
846 #ifdef USE_ASSERT_CHECKING 847 for (i = 0; i < b1->
ndatums; i++)
854 for (i = 0; i < b1->
ndatums; i++)
858 for (j = 0; j < partnatts; j++)
861 if (b1->
kind != NULL)
864 if (b1->
kind[i][j] != b2->
kind[i][j])
889 parttypbyval[j], parttyplen[j]))
930 if (src->
kind != NULL)
934 for (i = 0; i < ndatums; i++)
951 natts = hash_part ? 2 : partnatts;
953 for (i = 0; i < ndatums; i++)
959 for (j = 0; j < natts; j++)
966 typlen =
sizeof(
int32);
975 if (dest->
kind == NULL ||
1010 List **outer_parts,
List **inner_parts)
1023 *outer_parts = *inner_parts =
NIL;
1064 elog(
ERROR,
"unexpected partition strategy: %d",
1092 List **outer_parts,
List **inner_parts)
1108 int null_index = -1;
1109 int default_index = -1;
1128 outer_has_default =
false;
1130 inner_has_default =
false;
1139 outer_pos = inner_pos = 0;
1140 while (outer_pos < outer_bi->ndatums || inner_pos < inner_bi->ndatums)
1142 int outer_index = -1;
1143 int inner_index = -1;
1144 Datum *outer_datums;
1145 Datum *inner_datums;
1147 Datum *merged_datum = NULL;
1148 int merged_index = -1;
1150 if (outer_pos < outer_bi->ndatums)
1156 outer_index = outer_bi->
indexes[outer_pos];
1163 if (inner_pos < inner_bi->ndatums)
1169 inner_index = inner_bi->
indexes[inner_pos];
1178 outer_datums = outer_pos < outer_bi->
ndatums ?
1179 outer_bi->
datums[outer_pos] : NULL;
1180 inner_datums = inner_pos < inner_bi->
ndatums ?
1181 inner_bi->
datums[inner_pos] : NULL;
1192 if (outer_pos >= outer_bi->
ndatums)
1194 else if (inner_pos >= inner_bi->
ndatums)
1198 Assert(outer_datums != NULL && inner_datums != NULL);
1208 Assert(outer_pos < outer_bi->ndatums);
1209 Assert(inner_pos < inner_bi->ndatums);
1210 Assert(outer_index >= 0);
1211 Assert(inner_index >= 0);
1218 outer_index, inner_index,
1220 if (merged_index == -1)
1223 merged_datum = outer_datums;
1229 else if (cmpval < 0)
1232 Assert(outer_pos < outer_bi->ndatums);
1243 outer_index = outer_bi->
indexes[outer_pos];
1244 Assert(outer_index >= 0);
1254 if (merged_index == -1)
1256 merged_datum = outer_datums;
1266 Assert(inner_pos < inner_bi->ndatums);
1274 if (outer_has_default || jointype ==
JOIN_FULL)
1277 inner_index = inner_bi->
indexes[inner_pos];
1278 Assert(inner_index >= 0);
1288 if (merged_index == -1)
1290 merged_datum = inner_datums;
1301 if (merged_index >= 0 && merged_index != default_index)
1303 merged_datums =
lappend(merged_datums, merged_datum);
1304 merged_indexes =
lappend_int(merged_indexes, merged_index);
1312 if (outer_has_null &&
1314 outer_has_null =
false;
1315 if (inner_has_null &&
1317 inner_has_null =
false;
1320 if (outer_has_null || inner_has_null)
1322 outer_has_null, inner_has_null,
1324 jointype, &next_index, &null_index);
1326 Assert(null_index == -1);
1329 if (outer_has_default || inner_has_default)
1331 outer_has_default, inner_has_default,
1332 outer_default, inner_default,
1333 jointype, &next_index, &default_index);
1335 Assert(default_index == -1);
1345 next_index, merged_indexes);
1350 &outer_map, &inner_map,
1352 outer_parts, inner_parts);
1375 return merged_bounds;
1398 Oid *partcollations,
1401 List **outer_parts,
List **inner_parts)
1421 int default_index = -1;
1439 outer_has_default =
false;
1441 inner_has_default =
false;
1452 outer_lb_pos = inner_lb_pos = 0;
1454 &outer_lb, &outer_ub);
1456 &inner_lb, &inner_ub);
1457 while (outer_index >= 0 || inner_index >= 0)
1464 int merged_index = -1;
1475 if (outer_index == -1)
1481 else if (inner_index == -1)
1490 &outer_lb, &outer_ub,
1491 &inner_lb, &inner_ub,
1492 &lb_cmpval, &ub_cmpval);
1502 Assert(outer_index >= 0);
1504 outer_map.
merged[outer_index] ==
false);
1505 Assert(inner_index >= 0);
1507 inner_map.
merged[inner_index] ==
false);
1514 outer_index, inner_index,
1516 Assert(merged_index >= 0);
1520 partcollations, jointype,
1521 &outer_lb, &outer_ub,
1522 &inner_lb, &inner_ub,
1523 lb_cmpval, ub_cmpval,
1524 &merged_lb, &merged_ub);
1527 save_outer_ub = outer_ub;
1528 save_inner_ub = inner_ub;
1532 &outer_lb, &outer_ub);
1534 &inner_lb, &inner_ub);
1543 if (ub_cmpval > 0 && inner_index >= 0 &&
1545 &save_outer_ub, &inner_lb) > 0)
1547 if (ub_cmpval < 0 && outer_index >= 0 &&
1549 &outer_lb, &save_inner_ub) < 0)
1558 if ((outer_has_default && (lb_cmpval > 0 || ub_cmpval < 0)) ||
1559 (inner_has_default && (lb_cmpval < 0 || ub_cmpval > 0)))
1562 else if (ub_cmpval < 0)
1567 Assert(outer_index >= 0);
1569 outer_map.
merged[outer_index] ==
false);
1588 if (merged_index == -1)
1590 merged_lb = outer_lb;
1591 merged_ub = outer_ub;
1596 &outer_lb, &outer_ub);
1604 Assert(inner_index >= 0);
1606 inner_map.
merged[inner_index] ==
false);
1614 if (outer_has_default || jointype ==
JOIN_FULL)
1625 if (merged_index == -1)
1627 merged_lb = inner_lb;
1628 merged_ub = inner_ub;
1633 &inner_lb, &inner_ub);
1640 if (merged_index >= 0 && merged_index != default_index)
1642 &merged_lb, &merged_ub, merged_index,
1643 &merged_datums, &merged_kinds,
1648 if (outer_has_default || inner_has_default)
1650 outer_has_default, inner_has_default,
1651 outer_default, inner_default,
1652 jointype, &next_index, &default_index);
1654 Assert(default_index == -1);
1668 &outer_map, &inner_map,
1670 outer_parts, inner_parts);
1694 return merged_bounds;
1704 int nparts = rel->
nparts;
1712 for (i = 0; i < nparts; i++)
1754 int outer_index,
int inner_index,
int *next_index)
1756 int outer_merged_index;
1757 int inner_merged_index;
1761 Assert(outer_index >= 0 && outer_index < outer_map->nparts);
1763 outer_merged = outer_map->
merged[outer_index];
1764 Assert(inner_index >= 0 && inner_index < inner_map->nparts);
1766 inner_merged = inner_map->
merged[inner_index];
1772 if (outer_merged_index >= 0 && inner_merged_index >= 0)
1781 if (outer_merged_index == inner_merged_index)
1785 return outer_merged_index;
1787 if (!outer_merged && !inner_merged)
1796 if (outer_merged_index < inner_merged_index)
1798 outer_map->
merged[outer_index] =
true;
1800 inner_map->
merged[inner_index] =
true;
1802 inner_map->
old_indexes[inner_index] = inner_merged_index;
1803 return outer_merged_index;
1807 inner_map->
merged[inner_index] =
true;
1809 outer_map->
merged[outer_index] =
true;
1811 outer_map->
old_indexes[outer_index] = outer_merged_index;
1812 return inner_merged_index;
1819 Assert(outer_merged_index == -1 || inner_merged_index == -1);
1827 if (outer_merged_index == -1 && inner_merged_index == -1)
1829 int merged_index = *next_index;
1834 outer_map->
merged[outer_index] =
true;
1836 inner_map->
merged[inner_index] =
true;
1837 *next_index = *next_index + 1;
1838 return merged_index;
1840 if (outer_merged_index >= 0 && !outer_map->
merged[outer_index])
1842 Assert(inner_merged_index == -1);
1845 inner_map->
merged[inner_index] =
true;
1846 outer_map->
merged[outer_index] =
true;
1847 return outer_merged_index;
1849 if (inner_merged_index >= 0 && !inner_map->
merged[inner_index])
1851 Assert(outer_merged_index == -1);
1854 outer_map->
merged[outer_index] =
true;
1855 inner_map->
merged[inner_index] =
true;
1856 return inner_merged_index;
1873 bool outer_has_default,
1874 bool inner_has_default,
1881 int merged_index = -1;
1883 Assert(outer_index >= 0);
1893 if (inner_has_default)
1895 Assert(inner_default >= 0);
1904 if (outer_has_default)
1908 outer_index, inner_default,
1910 if (merged_index == -1)
1923 if (*default_index == -1)
1924 *default_index = merged_index;
1926 Assert(*default_index == merged_index);
1936 if (merged_index == -1)
1940 return merged_index;
1955 bool outer_has_default,
1956 bool inner_has_default,
1963 int merged_index = -1;
1965 Assert(inner_index >= 0);
1975 if (outer_has_default)
1977 Assert(outer_default >= 0);
1986 if (inner_has_default)
1990 outer_default, inner_index,
1992 if (merged_index == -1)
2006 if (*default_index == -1)
2007 *default_index = merged_index;
2009 Assert(*default_index == merged_index);
2018 if (merged_index == -1)
2022 return merged_index;
2040 bool outer_has_null,
2041 bool inner_has_null,
2048 bool consider_outer_null =
false;
2049 bool consider_inner_null =
false;
2051 Assert(outer_has_null || inner_has_null);
2052 Assert(*null_index == -1);
2060 Assert(outer_null >= 0 && outer_null < outer_map->nparts);
2062 consider_outer_null =
true;
2066 Assert(inner_null >= 0 && inner_null < inner_map->nparts);
2068 consider_inner_null =
true;
2072 if (!consider_outer_null && !consider_inner_null)
2075 if (consider_outer_null && !consider_inner_null)
2094 else if (!consider_outer_null && consider_inner_null)
2112 Assert(consider_outer_null && consider_inner_null);
2133 outer_null, inner_null,
2135 Assert(*null_index >= 0);
2150 bool outer_has_default,
2151 bool inner_has_default,
2158 int outer_merged_index = -1;
2159 int inner_merged_index = -1;
2161 Assert(outer_has_default || inner_has_default);
2164 if (outer_has_default)
2166 Assert(outer_default >= 0 && outer_default < outer_map->nparts);
2169 if (inner_has_default)
2171 Assert(inner_default >= 0 && inner_default < inner_map->nparts);
2175 if (outer_has_default && !inner_has_default)
2188 if (outer_merged_index == -1)
2190 Assert(*default_index == -1);
2196 Assert(*default_index == outer_merged_index);
2199 Assert(*default_index == -1);
2201 else if (!outer_has_default && inner_has_default)
2213 if (inner_merged_index == -1)
2215 Assert(*default_index == -1);
2221 Assert(*default_index == inner_merged_index);
2224 Assert(*default_index == -1);
2228 Assert(outer_has_default && inner_has_default);
2237 Assert(outer_merged_index == -1);
2238 Assert(inner_merged_index == -1);
2239 Assert(*default_index == -1);
2245 Assert(*default_index >= 0);
2260 int merged_index = *next_index;
2267 *next_index = *next_index + 1;
2268 return merged_index;
2277 int nmerged,
List *merged_indexes)
2286 new_indexes = (
int *)
palloc(
sizeof(
int) * nmerged);
2287 for (i = 0; i < nmerged; i++)
2288 new_indexes[i] = -1;
2293 for (i = 0; i < outer_map->
nparts; i++)
2296 if (merged_index >= 0)
2302 for (i = 0; i < inner_map->
nparts; i++)
2305 if (merged_index >= 0)
2311 foreach(lc, merged_indexes)
2314 Assert(merged_index >= 0);
2315 if (new_indexes[merged_index] >= 0)
2333 List **outer_parts,
List **inner_parts)
2335 int outer_nparts = outer_map->
nparts;
2336 int inner_nparts = inner_map->
nparts;
2346 outer_indexes = (
int *)
palloc(
sizeof(
int) * nmerged);
2347 inner_indexes = (
int *)
palloc(
sizeof(
int) * nmerged);
2348 for (i = 0; i < nmerged; i++)
2349 outer_indexes[i] = inner_indexes[i] = -1;
2354 max_nparts =
Max(outer_nparts, inner_nparts);
2355 for (i = 0; i < max_nparts; i++)
2357 if (i < outer_nparts)
2361 if (merged_index >= 0)
2363 Assert(merged_index < nmerged);
2364 outer_indexes[merged_index] =
i;
2367 if (i < inner_nparts)
2371 if (merged_index >= 0)
2373 Assert(merged_index < nmerged);
2374 inner_indexes[merged_index] =
i;
2380 for (i = 0; i < nmerged; i++)
2382 int outer_index = outer_indexes[
i];
2383 int inner_index = inner_indexes[
i];
2391 if (outer_index == -1 && inner_index == -1)
2394 *outer_parts =
lappend(*outer_parts, outer_index >= 0 ?
2395 outer_rel->
part_rels[outer_index] : NULL);
2396 *inner_parts =
lappend(*inner_parts, inner_index >= 0 ?
2397 inner_rel->
part_rels[inner_index] : NULL);
2400 pfree(outer_indexes);
2401 pfree(inner_indexes);
2410 List *merged_kinds,
List *merged_indexes,
2411 int null_index,
int default_index)
2419 merged_bounds->
strategy = strategy;
2420 merged_bounds->
ndatums = ndatums;
2424 foreach(lc, merged_datums)
2433 foreach(lc, merged_kinds)
2444 merged_bounds->
kind = NULL;
2449 merged_bounds->
indexes = (
int *)
palloc(
sizeof(
int) * ndatums);
2451 foreach(lc, merged_indexes)
2457 return merged_bounds;
2482 if (part_index == -1)
2520 if (*lb_pos + 2 >= bi->
ndatums)
2529 if (bi->
indexes[*lb_pos + 2] < 0)
2530 *lb_pos = *lb_pos + 2;
2532 *lb_pos = *lb_pos + 1;
2551 Oid *partcollations,
2556 int *lb_cmpval,
int *ub_cmpval)
2563 outer_ub, inner_lb) < 0)
2575 outer_lb, inner_ub) > 0)
2584 outer_lb, inner_lb);
2586 outer_ub, inner_ub);
2605 int lb_cmpval,
int ub_cmpval,
2610 outer_lb, inner_lb) == lb_cmpval);
2612 outer_ub, inner_ub) == ub_cmpval);
2625 *merged_lb = (lb_cmpval > 0) ? *outer_lb : *inner_lb;
2626 *merged_ub = (ub_cmpval < 0) ? *outer_ub : *inner_ub;
2637 *merged_lb = *outer_lb;
2638 *merged_ub = *outer_ub;
2649 *merged_lb = (lb_cmpval < 0) ? *outer_lb : *inner_lb;
2650 *merged_ub = (ub_cmpval > 0) ? *outer_ub : *inner_ub;
2654 elog(
ERROR,
"unrecognized join type: %d", (
int) jointype);
2664 Oid *partcollations,
2668 List **merged_datums,
2669 List **merged_kinds,
2670 List **merged_indexes)
2674 if (!*merged_datums)
2678 Assert(!*merged_indexes);
2693 prev_ub.
lower =
false;
2715 *merged_datums =
lappend(*merged_datums, merged_lb->
datums);
2716 *merged_kinds =
lappend(*merged_kinds, merged_lb->
kind);
2717 *merged_indexes =
lappend_int(*merged_indexes, -1);
2721 *merged_datums =
lappend(*merged_datums, merged_ub->
datums);
2722 *merged_kinds =
lappend(*merged_kinds, merged_ub->
kind);
2723 *merged_indexes =
lappend_int(*merged_indexes, merged_index);
2740 Assert(boundinfo != NULL);
2804 bool overlap =
false;
2805 int overlap_location = -1;
2820 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2821 errmsg(
"partition \"%s\" conflicts with existing default partition \"%s\"",
2833 if (partdesc->
nparts > 0)
2835 int greatest_modulus;
2867 if (next_modulus % spec->
modulus != 0)
2869 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2870 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
2871 errdetail(
"The new modulus %d is not a factor of %d, the modulus of existing partition \"%s\".",
2882 if (spec->
modulus % prev_modulus != 0)
2884 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2885 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
2886 errdetail(
"The new modulus %d is not divisible by %d, the modulus of existing partition \"%s\".",
2891 if (offset + 1 < boundinfo->
ndatums)
2898 if (next_modulus % spec->
modulus != 0)
2900 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2901 errmsg(
"every hash partition modulus must be a factor of the next larger modulus"),
2902 errdetail(
"The new modulus %d is not factor of %d, the modulus of existing partition \"%s\".",
2908 greatest_modulus = boundinfo->
nindexes;
2917 if (remainder >= greatest_modulus)
2918 remainder = remainder % greatest_modulus;
2923 if (boundinfo->
indexes[remainder] != -1)
2931 }
while (remainder < greatest_modulus);
2941 if (partdesc->
nparts > 0)
2966 if (offset >= 0 && equal)
2969 with = boundinfo->
indexes[offset];
3014 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3015 errmsg(
"empty range bound specified for partition \"%s\"",
3017 errdetail(
"Specified lower bound %s is greater than or equal to upper bound %s.",
3023 if (partdesc->
nparts > 0)
3053 if (boundinfo->
indexes[offset + 1] < 0)
3061 if (offset + 1 < boundinfo->
ndatums)
3067 datums = boundinfo->
datums[offset + 1];
3068 kind = boundinfo->
kind[offset + 1];
3069 is_lower = (boundinfo->
indexes[offset + 1] == -1);
3091 overlap_location = datum->
location;
3092 with = boundinfo->
indexes[offset + 2];
3111 overlap_location = datum->
location;
3112 with = boundinfo->
indexes[offset + 1];
3120 elog(
ERROR,
"unexpected partition strategy: %d",
3128 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3129 errmsg(
"partition \"%s\" would overlap partition \"%s\"",
3146 List *new_part_constraints;
3147 List *def_part_constraints;
3154 def_part_constraints =
3161 def_part_constraints =
3173 (
errmsg_internal(
"updated partition constraint for default partition \"%s\" is implied by existing constraints",
3182 if (default_rel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3188 foreach(lc, all_parts)
3192 Expr *partition_constraint;
3211 partition_constraint = (
Expr *)
3213 part_rel, default_rel);
3221 def_part_constraints))
3224 (
errmsg_internal(
"updated partition constraint for default partition \"%s\" is implied by existing constraints",
3233 part_rel = default_rel;
3241 if (part_rel->
rd_rel->relkind != RELKIND_RELATION)
3243 if (part_rel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE)
3245 (
errcode(ERRCODE_CHECK_VIOLATION),
3246 errmsg(
"skipped scanning foreign table \"%s\" which is a partition of default partition \"%s\"",
3276 if (!
ExecCheck(partqualstate, econtext))
3278 (
errcode(ERRCODE_CHECK_VIOLATION),
3279 errmsg(
"updated partition constraint for default partition \"%s\" would be violated by some row",
3348 elog(
ERROR,
"invalid range bound datum");
3390 bool lower2 = b2->
lower;
3392 for (i = 0; i < partnatts; i++)
3403 if (kind1[i] < kind2[i])
3405 else if (kind1[i] > kind2[i])
3431 if (cmpval == 0 && lower1 != lower2)
3432 cmpval = lower1 ? 1 : -1;
3434 return cmpval == 0 ? 0 : (cmpval < 0 ? -colnum : colnum);
3450 Datum *tuple_datums,
int n_tuple_datums)
3455 for (i = 0; i < n_tuple_datums; i++)
3481 if (modulus1 < modulus2)
3483 if (modulus1 > modulus2)
3485 if (modulus1 == modulus2 && remainder1 != remainder2)
3486 return (remainder1 > remainder2) ? 1 : -1;
3513 mid = (lo + hi + 1) / 2;
3516 boundinfo->
datums[mid][0],
3521 *is_equal = (cmpval == 0);
3558 mid = (lo + hi + 1) / 2;
3562 boundinfo->
kind[mid],
3563 (boundinfo->
indexes[mid] == -1),
3601 mid = (lo + hi + 1) / 2;
3605 boundinfo->
kind[mid],
3611 *is_equal = (cmpval == 0);
3645 mid = (lo + hi + 1) / 2;
3649 modulus, remainder);
3738 elog(
ERROR,
"missing operator %d(%u,%u) in partition opfamily %u",
3764 bool need_relabel =
false;
3765 Expr *result = NULL;
3813 saopexpr->
opno = operoid;
3815 saopexpr->
useOr =
true;
3820 result = (
Expr *) saopexpr;
3838 elemops =
lappend(elemops, elemop);
3856 elog(
ERROR,
"invalid partitioning strategy");
3879 Node *remainderConst;
3909 args =
list_make3(relidConst, modulusConst, remainderConst);
3965 bool list_has_null =
false;
4001 list_has_null =
true;
4008 if (ndatums == 0 && !list_has_null)
4011 for (i = 0; i < ndatums; i++)
4043 list_has_null =
true;
4056 keyCol, (
Expr *) elems);
4075 nulltest->
arg = keyCol;
4089 nulltest->
arg = keyCol;
4172 *partexprs_item_saved;
4181 List *lower_or_arms,
4186 *upper_or_start_datum;
4187 bool need_next_lower_arm,
4188 need_next_upper_arm;
4195 int nparts = pdesc->
nparts,
4198 for (i = 0; i < nparts; i++)
4200 Oid inhrelid = inhoids[
i];
4208 elog(
ERROR,
"cache lookup failed for relation %u", inhrelid);
4211 Anum_pg_class_relpartbound,
4214 elog(
ERROR,
"null relpartbound for relation %u", inhrelid);
4219 elog(
ERROR,
"expected PartitionBoundSpec");
4238 if (or_expr_args !=
NIL)
4240 Expr *other_parts_constr;
4248 other_parts_constr =
4285 partexprs_item_saved = partexprs_item;
4303 partexprs_item_saved = partexprs_item;
4308 &lower_val, &upper_val);
4316 if (!lower_val || !upper_val)
4324 (
Expr *) upper_val);
4343 elog(
ERROR,
"invalid range bound specification");
4348 keyCol, (
Expr *) lower_val));
4354 lower_or_start_datum = cell1;
4355 upper_or_start_datum = cell2;
4360 lower_or_arms = upper_or_arms =
NIL;
4361 need_next_lower_arm = need_next_upper_arm =
true;
4362 while (current_or_arm < num_or_arms)
4364 List *lower_or_arm_args =
NIL,
4365 *upper_or_arm_args =
NIL;
4369 partexprs_item = partexprs_item_saved;
4375 *udatum_next = NULL;
4388 &lower_val, &upper_val);
4390 if (need_next_lower_arm && lower_val)
4400 if (j - i < current_or_arm)
4409 lower_or_arm_args =
lappend(lower_or_arm_args,
4413 (
Expr *) lower_val));
4416 if (need_next_upper_arm && upper_val)
4425 if (j - i < current_or_arm)
4427 else if (udatum_next &&
4433 upper_or_arm_args =
lappend(upper_or_arm_args,
4437 (
Expr *) upper_val));
4446 if (j - i > current_or_arm)
4452 if (!lower_val || !ldatum_next ||
4454 need_next_lower_arm =
false;
4455 if (!upper_val || !udatum_next ||
4457 need_next_upper_arm =
false;
4462 if (lower_or_arm_args !=
NIL)
4463 lower_or_arms =
lappend(lower_or_arms,
4468 if (upper_or_arm_args !=
NIL)
4469 upper_or_arms =
lappend(upper_or_arms,
4475 if (!need_next_lower_arm && !need_next_upper_arm)
4486 if (lower_or_arms !=
NIL)
4491 if (upper_or_arms !=
NIL)
4504 result = for_default
4546 if (*partexprs_item == NULL)
4547 elog(
ERROR,
"wrong number of partition key expressions");
4594 if (partexprs_item == NULL)
4595 elog(
ERROR,
"wrong number of partition key expressions");
4601 nulltest->
arg = keyCol;
4605 result =
lappend(result, nulltest);
4624 for (i = 0; i < partnatts; i++)
4668 typedef struct ColumnsHashData
4673 int16 variadic_typlen;
4674 bool variadic_typbyval;
4675 char variadic_typalign;
4683 ColumnsHashData *my_extra;
4696 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4697 errmsg(
"modulus for hash partition must be a positive integer")));
4700 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4701 errmsg(
"remainder for hash partition must be a non-negative integer")));
4702 if (remainder >= modulus)
4704 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4705 errmsg(
"remainder for hash partition must be less than modulus")));
4710 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4711 if (my_extra == NULL || my_extra->relid != parentId)
4724 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4725 errmsg(
"\"%s\" is not a hash partitioned table",
4735 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4736 errmsg(
"number of partitioning columns (%d) does not match number of partition keys provided (%d)",
4740 fcinfo->flinfo->fn_extra =
4742 offsetof(ColumnsHashData, partsupfunc) +
4744 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4745 my_extra->relid = parentId;
4757 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4758 errmsg(
"column %d of the partition key has type %s, but supplied value is of type %s",
4771 fcinfo->flinfo->fn_extra =
4773 offsetof(ColumnsHashData, partsupfunc) +
4775 my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
4776 my_extra->relid = parentId;
4778 my_extra->variadic_type =
ARR_ELEMTYPE(variadic_array);
4780 &my_extra->variadic_typlen,
4781 &my_extra->variadic_typbyval,
4782 &my_extra->variadic_typalign);
4787 if (key->
parttypid[j] != my_extra->variadic_type)
4789 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4790 errmsg(
"column %d of the partition key has type \"%s\", but supplied value is of type \"%s\"",
4806 int nkeys = my_extra->nkeys;
4815 for (i = 0; i < nkeys; i++)
4826 my_extra->partcollid[i],
4843 my_extra->variadic_type,
4844 my_extra->variadic_typlen,
4845 my_extra->variadic_typbyval,
4846 my_extra->variadic_typalign,
4847 &datum, &isnull, &nelems);
4850 if (nelems != my_extra->nkeys)
4852 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4853 errmsg(
"number of partitioning columns (%d) does not match number of partition keys provided (%d)",
4854 my_extra->nkeys, nelems)));
4856 for (i = 0; i < nelems; i++)
4864 my_extra->partcollid[0],
TupleTableSlot * table_slot_create(Relation relation, List **reglist)
#define list_make2(x1, x2)
#define list_make3(x1, x2, x3)
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 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 PG_GETARG_INT32(n)
static PartitionBoundInfo merge_list_bounds(FmgrInfo *partsupfunc, Oid *collations, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinType jointype, List **outer_parts, List **inner_parts)
PartitionRangeDatumKind ** kind
#define IsA(nodeptr, _type_)
PartitionRangeDatumKind * kind
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
void table_close(Relation relation, LOCKMODE lockmode)
#define BTGreaterStrategyNumber
#define forboth(cell1, list1, cell2, list2)
static int32 qsort_partition_hbound_cmp(const void *a, const void *b)
static PartitionBoundInfo build_merged_partition_bounds(char strategy, List *merged_datums, List *merged_kinds, List *merged_indexes, int null_index, int default_index)
Snapshot RegisterSnapshot(Snapshot snapshot)
static ListCell * lnext(const List *l, const ListCell *c)
bool equal(const void *a, const void *b)
Datum lower(PG_FUNCTION_ARGS)
#define castNode(_type_, nodeptr)
static List * get_qual_for_hash(Relation parent, PartitionBoundSpec *spec)
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
static int merge_matching_partitions(PartitionMap *outer_map, PartitionMap *inner_map, int outer_part, int inner_part, int *next_index)
#define PG_GETARG_DATUM(n)
Oid get_array_type(Oid typid)
void fix_opfuncids(Node *node)
#define UInt64GetDatum(X)
bool datumIsEqual(Datum value1, Datum value2, bool typByVal, int typLen)
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)
List * get_qual_from_partbound(Relation rel, Relation parent, PartitionBoundSpec *spec)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
#define IS_OUTER_JOIN(jointype)
PartitionRangeDatumKind kind
#define FLEXIBLE_ARRAY_MEMBER
bool get_fn_expr_variadic(FmgrInfo *flinfo)
int errcode(int sqlerrcode)
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 List * get_range_nulltest(PartitionKey key)
void * stringToNode(const char *str)
static int32 qsort_partition_rbound_cmp(const void *a, const void *b, void *arg)
#define PARTITION_MAX_KEYS
Datum upper(PG_FUNCTION_ARGS)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
static bool table_scan_getnextslot(TableScanDesc sscan, ScanDirection direction, TupleTableSlot *slot)
PartitionKey RelationGetPartitionKey(Relation rel)
struct PartitionRangeBound PartitionRangeBound
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)
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
static uint64 hash_combine64(uint64 a, uint64 b)
#define OidIsValid(objectId)
static void free_partition_map(PartitionMap *map)
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Expr * makeBoolExpr(BoolExprType boolop, List *args, int location)
PartitionBoundInfo boundinfo
#define BTLessEqualStrategyNumber
static int get_range_partition_internal(PartitionBoundInfo bi, int *lb_pos, PartitionRangeBound *lb, PartitionRangeBound *ub)
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)
void FreeExecutorState(EState *estate)
static Expr * make_partition_op_expr(PartitionKey key, int keynum, uint16 strategy, Expr *arg1, Expr *arg2)
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)
#define GetPerTupleExprContext(estate)
static PartitionRangeBound * make_one_partition_rbound(PartitionKey key, int index, List *datums, bool lower)
#define PG_GETARG_ARRAYTYPE_P(n)
int partition_range_datum_bsearch(FmgrInfo *partsupfunc, Oid *partcollation, PartitionBoundInfo boundinfo, int nvalues, Datum *values, bool *is_equal)
void check_new_partition_bound(char *relname, Relation parent, PartitionBoundSpec *spec, ParseState *pstate)
void pfree(void *pointer)
MemoryContext es_query_cxt
#define ObjectIdGetDatum(X)
static TableScanDesc table_beginscan(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key)
static void * list_nth(const List *list, int n)
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
static void fix_merged_indexes(PartitionMap *outer_map, PartitionMap *inner_map, int nmerged, List *merged_indexes)
Node * makeBoolConst(bool value, bool isnull)
struct PartitionMap PartitionMap
void check_default_partition_contents(Relation parent, Relation default_rel, PartitionBoundSpec *new_spec)
static PartitionBoundInfo create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts, PartitionKey key, int **mapping)
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
int get_hash_partition_greatest_modulus(PartitionBoundInfo bound)
static PartitionBoundInfo create_list_bounds(PartitionBoundSpec **boundspecs, int nparts, PartitionKey key, int **mapping)
int32 partition_rbound_datum_cmp(FmgrInfo *partsupfunc, Oid *partcollation, Datum *rb_datums, PartitionRangeDatumKind *rb_kind, Datum *tuple_datums, int n_tuple_datums)
List * get_proposed_default_constraint(List *new_part_constraints)
RelabelType * makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, Oid rcollid, CoercionForm rformat)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
int errdetail(const char *fmt,...)
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
static int32 partition_hbound_cmp(int modulus1, int remainder1, int modulus2, int remainder2)
static int merge_partition_with_dummy(PartitionMap *map, int index, int *next_index)
PartitionDesc RelationGetPartitionDesc(Relation rel)
static bool is_dummy_partition(RelOptInfo *rel, int part_index)
#define RelationGetRelationName(relation)
#define partition_bound_has_default(bi)
static ListCell * list_head(const List *l)
int partition_hash_bsearch(PartitionBoundInfo boundinfo, int modulus, int remainder)
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Datum datumCopy(Datum value, bool typByVal, int typLen)
EState * CreateExecutorState(void)
List * lappend_int(List *list, int datum)
char * get_range_partbound_string(List *bound_datums)
void UnregisterSnapshot(Snapshot snapshot)
bool IsBinaryCoercible(Oid srctype, Oid targettype)
List * lappend(List *list, void *datum)
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
#define TextDatumGetCString(d)
PartitionBoundInfo partition_bounds_copy(PartitionBoundInfo src, PartitionKey key)
void * palloc0(Size size)
#define PG_RETURN_BOOL(x)
void ReleaseSysCache(HeapTuple tuple)
#define for_both_cell(cell1, list1, initcell1, cell2, list2, initcell2)
Expr * make_ands_explicit(List *andclauses)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
#define list_make1_oid(x1)
static void cleanup(void)
struct PartitionBoundInfoData * boundinfo
static Oid get_partition_operator(PartitionKey key, int col, StrategyNumber strategy, bool *need_relabel)
#define PARTITION_STRATEGY_HASH
NullTestType nulltesttype
#define partition_bound_accepts_nulls(bi)
void * MemoryContextAllocZero(MemoryContext context, Size size)
static void init_partition_map(RelOptInfo *rel, PartitionMap *map)
struct PartitionListValue PartitionListValue
int partition_list_bsearch(FmgrInfo *partsupfunc, Oid *partcollation, PartitionBoundInfo boundinfo, Datum value, bool *is_equal)
uint64 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc, Oid *partcollation, Datum *values, bool *isnull)
RegProcedure get_opcode(Oid opno)
#define ereport(elevel,...)
static int32 partition_rbound_cmp(int partnatts, FmgrInfo *partsupfunc, Oid *partcollation, Datum *datums1, PartitionRangeDatumKind *kind1, bool lower1, PartitionRangeBound *b2)
int errmsg_internal(const char *fmt,...)
static List * get_qual_for_range(Relation parent, PartitionBoundSpec *spec, bool for_default)
#define DatumGetUInt64(X)
bool partitions_are_ordered(PartitionBoundInfo boundinfo, int nparts)
#define HeapTupleIsValid(tuple)
void relation_close(Relation relation, LOCKMODE lockmode)
#define Assert(condition)
static int partition_range_bsearch(int partnatts, FmgrInfo *partsupfunc, Oid *partcollation, PartitionBoundInfo boundinfo, PartitionRangeBound *probe, int32 *cmpval)
struct RelOptInfo ** part_rels
static int list_length(const List *l)
int parser_errposition(ParseState *pstate, int location)
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)
TupleTableSlot * ecxt_scantuple
#define type_is_array(typid)
#define HASH_PARTITION_SEED
#define PARTITION_STRATEGY_LIST
Snapshot GetLatestSnapshot(void)
#define GetPerTupleMemoryContext(estate)
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)
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
static void table_endscan(TableScanDesc scan)
static Datum values[MAXATTR]
#define PARTITION_STRATEGY_RANGE
#define AccessExclusiveLock
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
static PartitionBoundInfo create_range_bounds(PartitionBoundSpec **boundspecs, int nparts, PartitionKey key, int **mapping)
int errmsg(const char *fmt,...)
bool partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval, PartitionBoundInfo b1, PartitionBoundInfo b2)
void list_free(List *list)
bool ExecCheck(ExprState *state, ExprContext *econtext)
#define compare_range_bounds(partnatts, partsupfunc, partcollations, bound1, bound2)
Datum satisfies_hash_partition(PG_FUNCTION_ARGS)
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
#define CHECK_FOR_INTERRUPTS()
struct PartitionBoundInfoData * PartitionBoundInfo
#define qsort(a, b, c, d)
PartitionBoundInfo partition_bounds_merge(int partnatts, FmgrInfo *partsupfunc, Oid *partcollation, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinType jointype, List **outer_parts, List **inner_parts)
#define BTLessStrategyNumber
Relation table_open(Oid relationId, LOCKMODE lockmode)
static int32 qsort_partition_list_value_cmp(const void *a, const void *b, void *arg)
static unsigned hash(unsigned *uv, int n)
char * get_rel_name(Oid relid)
int errtable(Relation rel)
List * map_partition_varattnos(List *expr, int fromrel_varno, Relation to_rel, Relation from_rel)
#define RelationGetRelid(relation)
PartitionBoundInfo partition_bounds_create(PartitionBoundSpec **boundspecs, int nparts, PartitionKey key, int **mapping)
static List * get_qual_for_list(Relation parent, PartitionBoundSpec *spec)
#define BTEqualStrategyNumber
#define offsetof(type, field)
#define BTGreaterEqualStrategyNumber
#define ResetExprContext(econtext)
bool PartConstraintImpliedByRelConstraint(Relation scanrel, List *partConstraint)
FuncExpr * makeFuncExpr(Oid funcid, Oid rettype, List *args, Oid funccollid, Oid inputcollid, CoercionForm fformat)
struct PartitionKeyData * PartitionKey
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)
static int get_range_partition(RelOptInfo *rel, PartitionBoundInfo bi, int *lb_pos, PartitionRangeBound *lb, PartitionRangeBound *ub)
struct PartitionHashBound PartitionHashBound