v1-0001-poc-partition-by-range.patch
text/x-patch
Filename: v1-0001-poc-partition-by-range.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v1-0001
| File | + | − |
|---|---|---|
| src/backend/executor/execPartition.c | 1 | 1 |
| src/backend/partitioning/partbounds.c | 213 | 153 |
| src/backend/partitioning/partdesc.c | 23 | 2 |
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index d96d4f9947b..1093cb5044c 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -1680,7 +1680,7 @@ get_partition_for_tuple(PartitionDispatch pd, const Datum *values, const bool *i
if (range_partkey_has_null)
break;
- if (partdesc->last_found_count >= PARTITION_CACHED_FIND_THRESHOLD)
+ if (partdesc->last_found_count >= PARTITION_CACHED_FIND_THRESHOLD && false /* temporary disable */)
{
int last_datum_offset = partdesc->last_found_datum_index;
Datum *lastDatums = boundinfo->datums[last_datum_offset];
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index f867d1b75a5..5b6099c7b3b 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -224,7 +224,8 @@ static int32 partition_rbound_cmp(int partnatts, FmgrInfo *partsupfunc,
static int partition_range_bsearch(int partnatts, FmgrInfo *partsupfunc,
Oid *partcollation,
PartitionBoundInfo boundinfo,
- PartitionRangeBound *probe, int32 *cmpval);
+ PartitionRangeBound *lower,
+ PartitionRangeBound *upper);
static Expr *make_partition_op_expr(PartitionKey key, int keynum,
uint16 strategy, Expr *arg1, Expr *arg2);
static Oid get_partition_operator(PartitionKey key, int col,
@@ -677,8 +678,7 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
{
PartitionBoundInfo boundinfo;
PartitionRangeBound **rbounds = NULL;
- PartitionRangeBound **all_bounds,
- *prev;
+ PartitionRangeBound **all_bounds;
int i,
k,
partnatts;
@@ -728,61 +728,12 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
Assert(ndatums == nparts * 2 ||
(default_index != -1 && ndatums == (nparts - 1) * 2));
- /* Sort all the bounds in ascending order */
- qsort_arg(all_bounds, ndatums,
- sizeof(PartitionRangeBound *),
- qsort_partition_rbound_cmp,
- key);
-
- /* Save distinct bounds from all_bounds into rbounds. */
rbounds = (PartitionRangeBound **)
palloc(ndatums * sizeof(PartitionRangeBound *));
k = 0;
- prev = NULL;
for (i = 0; i < ndatums; i++)
{
- PartitionRangeBound *cur = all_bounds[i];
- bool is_distinct = false;
- int j;
-
- /* Is the current bound distinct from the previous one? */
- for (j = 0; j < key->partnatts; j++)
- {
- Datum cmpval;
-
- if (prev == NULL || cur->kind[j] != prev->kind[j])
- {
- is_distinct = true;
- break;
- }
-
- /*
- * If the bounds are both MINVALUE or MAXVALUE, stop now and treat
- * them as equal, since any values after this point must be
- * ignored.
- */
- if (cur->kind[j] != PARTITION_RANGE_DATUM_VALUE)
- break;
-
- cmpval = FunctionCall2Coll(&key->partsupfunc[j],
- key->partcollation[j],
- cur->datums[j],
- prev->datums[j]);
- if (DatumGetInt32(cmpval) != 0)
- {
- is_distinct = true;
- break;
- }
- }
-
- /*
- * Only if the bound is distinct save it into a temporary array, i.e,
- * rbounds which is later copied into boundinfo datums array.
- */
- if (is_distinct)
rbounds[k++] = all_bounds[i];
-
- prev = cur;
}
pfree(all_bounds);
@@ -3127,6 +3078,7 @@ check_new_partition_bound(char *relname, Relation parent,
if (partdesc->nparts > 0)
{
+ /* if key->partnatts == 1 or ? boundinfo->ndatums */
int offset;
Assert(boundinfo &&
@@ -3152,68 +3104,10 @@ check_new_partition_bound(char *relname, Relation parent,
offset = partition_range_bsearch(key->partnatts,
key->partsupfunc,
key->partcollation,
- boundinfo, lower,
- &cmpval);
+ boundinfo, lower, upper);
- if (boundinfo->indexes[offset + 1] < 0)
- {
- /*
- * Check that the new partition will fit in the gap.
- * For it to fit, the new upper bound must be less
- * than or equal to the lower bound of the next
- * partition, if there is one.
- */
- if (offset + 1 < boundinfo->ndatums)
- {
- Datum *datums;
- PartitionRangeDatumKind *kind;
- bool is_lower;
-
- datums = boundinfo->datums[offset + 1];
- kind = boundinfo->kind[offset + 1];
- is_lower = (boundinfo->indexes[offset + 1] == -1);
-
- cmpval = partition_rbound_cmp(key->partnatts,
- key->partsupfunc,
- key->partcollation,
- datums, kind,
- is_lower, upper);
- if (cmpval < 0)
- {
- /*
- * Point to problematic key in the upper
- * datums list.
- */
- PartitionRangeDatum *datum =
- list_nth(spec->upperdatums, abs(cmpval) - 1);
-
- /*
- * The new partition overlaps with the
- * existing partition between offset + 1 and
- * offset + 2.
- */
- overlap = true;
- overlap_location = datum->location;
- with = boundinfo->indexes[offset + 2];
- }
- }
- }
- else
- {
- /*
- * The new partition overlaps with the existing
- * partition between offset and offset + 1.
- */
- PartitionRangeDatum *datum;
-
- /*
- * Point to problematic key in the lower datums list;
- * if we have equality, point to the first one.
- */
- datum = cmpval == 0 ? linitial(spec->lowerdatums) :
- list_nth(spec->lowerdatums, abs(cmpval) - 1);
+ if (offset > -1) {
overlap = true;
- overlap_location = datum->location;
with = boundinfo->indexes[offset + 1];
}
}
@@ -3646,34 +3540,133 @@ static int
partition_range_bsearch(int partnatts, FmgrInfo *partsupfunc,
Oid *partcollation,
PartitionBoundInfo boundinfo,
- PartitionRangeBound *probe, int32 *cmpval)
+ PartitionRangeBound *lower,
+ PartitionRangeBound *upper)
{
- int lo,
- hi,
- mid;
+ int offset = -1;
+ int d, partattr;
+ int32 cmpval1, cmpval2;
- lo = -1;
- hi = boundinfo->ndatums - 1;
- while (lo < hi)
+ Datum *lower_datums, *upper_datums;
+
+ fprintf(stdout,"Func : partition_range_bsearch : \n");
+ fprintf(stdout,"\n# Partition by range (relevant for 2D partition key, for Python script) : \n");
+
+ /* New the partition by range */
+ partattr = 0;
+ fprintf(stdout,"range((");
+ while (partattr < partnatts) {
+ fprintf(stdout, "%lu, ", lower->datums[partattr]);
+ partattr++;
+ }
+ fprintf(stdout,"), ");
+
+ partattr = 0;
+ fprintf(stdout,"(");
+ while (partattr < partnatts) {
+ fprintf(stdout, "%lu, ", upper->datums[partattr]);
+ partattr++;
+ }
+ fprintf(stdout,"), 'new', facecolor='black', edgecolor='yellow')\n");
+
+ /* Existing the partition by range */
+ d = 0;
+ while ( d < boundinfo->ndatums - 1 )
{
- mid = (lo + hi + 1) / 2;
- *cmpval = partition_rbound_cmp(partnatts, partsupfunc,
- partcollation,
- boundinfo->datums[mid],
- boundinfo->kind[mid],
- (boundinfo->indexes[mid] == -1),
- probe);
- if (*cmpval <= 0)
+ if ( boundinfo->indexes[d] == -1 && boundinfo->indexes[d+1] > -1 )
{
- lo = mid;
- if (*cmpval == 0)
- break;
+ lower_datums = boundinfo->datums[d];
+ upper_datums = boundinfo->datums[d+1];
+
+ partattr = 0;
+ fprintf(stdout,"range((");
+ while (partattr < partnatts) {
+ fprintf(stdout, "%lu, ", lower_datums[partattr]);
+ partattr++;
+ }
+ fprintf(stdout,"), ");
+
+ partattr = 0;
+ fprintf(stdout,"(");
+ while (partattr < partnatts) {
+ fprintf(stdout, "%lu, ", upper_datums[partattr]);
+ partattr++;
+ }
+ fprintf(stdout,"),'p-%d')\n", boundinfo->indexes[d+1]);
+
+ d+=2;
}
else
- hi = mid - 1;
+ d++;
}
+ fprintf(stdout,"\n");
+ fflush(stdout);
- return lo;
+ /* Search algorithm */
+ d = 0;
+ while ( d < boundinfo->ndatums )
+ {
+ if ( (boundinfo->indexes[d] == -1) && (boundinfo->indexes[d+1] > -1) )
+ {
+ lower_datums = boundinfo->datums[d];
+ upper_datums = boundinfo->datums[d+1];
+
+ partattr = 0;
+ while (partattr < partnatts)
+ {
+ cmpval1 = DatumGetInt32(FunctionCall2Coll(&partsupfunc[partattr], partcollation[partattr],
+ upper_datums[partattr], lower->datums[partattr]));
+
+ cmpval2 = DatumGetInt32(FunctionCall2Coll(&partsupfunc[partattr], partcollation[partattr],
+ upper->datums[partattr], lower_datums[partattr]));
+
+ /* Step of the search algorithm */
+ /* datums_lower[partattr], datums_upper[partattr] ;
+ * probe->datums[partattr], upper->datums[partattr];
+ * a,a'; b,b' -> a_k' < b_k OR b_k' < a_k
+ */
+ fprintf(stdout, "Range : Exists( %lu, %lu), New( %lu, %lu)\n",
+ lower_datums[partattr], upper_datums[partattr],
+ lower->datums[partattr], upper->datums[partattr]);
+ fprintf(stdout, "Condition: 1) %lu < %lu : result = %d or 2) %lu < %lu : result = %d; attr = %d; ",
+ upper_datums[partattr], lower->datums[partattr], cmpval1,
+ upper->datums[partattr], lower_datums[partattr], cmpval2,
+ partattr);
+
+ if ( cmpval1 < 1 || cmpval2 < 1 )
+ {
+ /* The partition range passed the check - there are no intersections
+ * with the new partition range.
+ * Then exit the loop with the value partnatts++
+ */
+ partattr = partnatts;
+ fprintf(stdout, "[CHECK OK].");
+ }
+
+ partattr++;
+ fprintf(stdout,"\n");
+ fflush(stdout);
+ }
+
+ if (partattr == partnatts)
+ {
+ /* This condition means that in the while loop for all <partattr>,
+ * there is an intersection of ranges across all partition key value.
+ * Therefore, we can skip further partition range checks.
+ */
+ offset = d;
+ d = boundinfo->ndatums + 3;
+ }
+ d+=2;
+ }
+ else
+ d++;
+ }
+
+ fprintf(stdout,"New the partition by range : %s.\n", (d == boundinfo->ndatums + 3) ? "ERROR" : "OK" );
+ fflush(stdout);
+
+ return offset;
}
/*
@@ -3689,36 +3682,103 @@ partition_range_datum_bsearch(FmgrInfo *partsupfunc, Oid *partcollation,
PartitionBoundInfo boundinfo,
int nvalues, const Datum *values, bool *is_equal)
{
- int lo,
- hi,
- mid;
+ int offset = -1;
+ int d, partattr;
+ int32 cmpval1, cmpval2;
+
+ Datum *lower_datums, *upper_datums;
+ fprintf(stdout,"Func : partition_range_datum_bsearch : nvalues = %d\n", nvalues);
+ fprintf(stdout,"\n# Partition by range (relevant for 2D partition key, for Python script) : \n");
+
+ /* New the partition key */
+ partattr = 0;
+ fprintf(stdout,"key((");
+ while (partattr < nvalues) {
+ fprintf(stdout, "%lu, ", values[partattr]);
+ partattr++;
+ }
+ fprintf(stdout,"), 0.3)\n");
- lo = -1;
- hi = boundinfo->ndatums - 1;
- while (lo < hi)
+ /* Existing the partition by range */
+ d = 0;
+ while ( d < boundinfo->ndatums - 1 )
{
- int32 cmpval;
+ if ( boundinfo->indexes[d] == -1 && boundinfo->indexes[d+1] > -1 )
+ {
+ lower_datums = boundinfo->datums[d];
+ upper_datums = boundinfo->datums[d+1];
+
+ partattr = 0;
+ fprintf(stdout,"range((");
+ while (partattr < nvalues) {
+ fprintf(stdout, "%lu, ", lower_datums[partattr]);
+ partattr++;
+ }
+ fprintf(stdout,"), ");
- mid = (lo + hi + 1) / 2;
- cmpval = partition_rbound_datum_cmp(partsupfunc,
- partcollation,
- boundinfo->datums[mid],
- boundinfo->kind[mid],
- values,
- nvalues);
- if (cmpval <= 0)
+ partattr = 0;
+ fprintf(stdout,"(");
+ while (partattr < nvalues) {
+ fprintf(stdout, "%lu, ", upper_datums[partattr]);
+ partattr++;
+ }
+ fprintf(stdout,"),'p-%d')\n", boundinfo->indexes[d+1]);
+
+ d+=2;
+ }
+ else
+ d++;
+ }
+ fprintf(stdout,"\n");
+ fflush(stdout);
+
+ /* Search algorithm */
+ d = 0;
+ while ( d < boundinfo->ndatums )
+ {
+ if ( (boundinfo->indexes[d] == -1) && (boundinfo->indexes[d+1] > -1) )
{
- lo = mid;
- *is_equal = (cmpval == 0);
+ lower_datums = boundinfo->datums[d];
+ upper_datums = boundinfo->datums[d+1];
- if (*is_equal)
- break;
+ partattr = 0;
+ while (partattr < nvalues)
+ {
+ cmpval1 = DatumGetInt32(FunctionCall2Coll(&partsupfunc[partattr], partcollation[partattr],
+ lower_datums[partattr], values[partattr]));
+
+ cmpval2 = DatumGetInt32(FunctionCall2Coll(&partsupfunc[partattr], partcollation[partattr],
+ values[partattr], upper_datums[partattr]));
+
+ /* Step of the search algorithm */
+ fprintf(stdout, "Range : Exists(%lu, %lu), Key(%lu)\n", lower_datums[partattr], upper_datums[partattr], values[partattr]);
+
+ if ( !(cmpval1 < 1 && cmpval2 < 1) )
+ {
+ partattr = nvalues;
+ fprintf(stdout, "[KEY OUT RANGE].");
+ }
+
+ partattr++;
+ fprintf(stdout,"\n");
+ fflush(stdout);
+ }
+
+ if (partattr == nvalues)
+ {
+ offset = d;
+ d = boundinfo->ndatums + 3;
+ }
+ d+=2;
}
else
- hi = mid - 1;
+ d++;
}
- return lo;
+ fprintf(stdout,"New partition key : %s.\n", (d == boundinfo->ndatums + 3) ? "OK" : "ERROR" );
+ fflush(stdout);
+
+ return offset;
}
/*
diff --git a/src/backend/partitioning/partdesc.c b/src/backend/partitioning/partdesc.c
index c3d275f8726..77ef116172c 100644
--- a/src/backend/partitioning/partdesc.c
+++ b/src/backend/partitioning/partdesc.c
@@ -71,7 +71,7 @@ PartitionDesc
RelationGetPartitionDesc(Relation rel, bool omit_detached)
{
Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
-
+ return RelationBuildPartitionDesc(rel, omit_detached);
/*
* If relcache has a partition descriptor, use that. However, we can only
* do so when we are asked to include all partitions including detached;
@@ -307,9 +307,30 @@ retry:
* Create PartitionBoundInfo and mapping, working in the caller's context.
* This could fail, but we haven't done any damage if so.
*/
- if (nparts > 0)
+ if (nparts > 0) {
boundinfo = partition_bounds_create(boundspecs, nparts, key, &mapping);
+ int d = 0, partattr;
+
+ fprintf(stdout,"BoundInfo : \n");
+ while ( d < boundinfo->ndatums )
+ {
+ /*cur_datum = boundinfo->datums[d];*/
+ fprintf(stdout,"Index = %d, Range (",boundinfo->indexes[d]);
+
+ partattr = 0;
+ while (partattr < key->partnatts)
+ {
+ fprintf(stdout," %lu, ", boundinfo->datums[d][partattr]);
+ partattr++;
+ }
+ fprintf(stdout,");\n");
+ fflush(stdout);
+
+ d++;
+ }
+ }
+
/*
* Now build the actual relcache partition descriptor, copying all the
* data into a new, small context. As per above comment, we don't make