Skip to content

Commit 970c050

Browse files
committed
Fix assertion failure in check_new_partition_bound().
Commit 6b2c4e5 was overly confident about not being able to see a negative cmpval result from partition_range_bsearch(). Adjust the code to cope with that. Report and patch by Amul Sul; some additional cosmetic changes by me Discussion: https://postgr.es/m/CAAJ_b97WCO=EyVA7fKzc86kKfojHXLU04_zs7-7+yVzm=-1QkQ@mail.gmail.com
1 parent 6f0bc5e commit 970c050

File tree

3 files changed

+25
-20
lines changed

3 files changed

+25
-20
lines changed

src/backend/partitioning/partbounds.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2703,10 +2703,10 @@ add_merged_range_bounds(int partnatts, FmgrInfo *partsupfuncs,
27032703
prev_ub.lower = false;
27042704

27052705
/*
2706-
* We pass to partition_rbound_cmp() lower1 as false to prevent it
2707-
* from considering the last upper bound to be smaller than the lower
2708-
* bound of the merged partition when the values of the two range
2709-
* bounds compare equal.
2706+
* We pass lower1 = false to partition_rbound_cmp() to prevent it from
2707+
* considering the last upper bound to be smaller than the lower bound
2708+
* of the merged partition when the values of the two range bounds
2709+
* compare equal.
27102710
*/
27112711
cmpval = partition_rbound_cmp(partnatts, partsupfuncs, partcollations,
27122712
merged_lb->datums, merged_lb->kind,
@@ -2978,16 +2978,19 @@ check_new_partition_bound(char *relname, Relation parent,
29782978

29792979
/*
29802980
* First check if the resulting range would be empty with
2981-
* specified lower and upper bounds
2981+
* specified lower and upper bounds. partition_rbound_cmp
2982+
* cannot return zero here, since the lower-bound flags are
2983+
* different.
29822984
*/
29832985
cmpval = partition_rbound_cmp(key->partnatts,
29842986
key->partsupfunc,
29852987
key->partcollation,
29862988
lower->datums, lower->kind,
29872989
true, upper);
2988-
if (cmpval >= 0)
2990+
Assert(cmpval != 0);
2991+
if (cmpval > 0)
29892992
{
2990-
/* Fetch the problematic key from the lower datums list. */
2993+
/* Point to problematic key in the lower datums list. */
29912994
PartitionRangeDatum *datum = list_nth(spec->lowerdatums,
29922995
cmpval - 1);
29932996

@@ -3057,11 +3060,11 @@ check_new_partition_bound(char *relname, Relation parent,
30573060
if (cmpval < 0)
30583061
{
30593062
/*
3060-
* Fetch the problematic key from the upper
3063+
* Point to problematic key in the upper
30613064
* datums list.
30623065
*/
30633066
PartitionRangeDatum *datum =
3064-
list_nth(spec->upperdatums, -cmpval - 1);
3067+
list_nth(spec->upperdatums, Abs(cmpval) - 1);
30653068

30663069
/*
30673070
* The new partition overlaps with the
@@ -3083,15 +3086,11 @@ check_new_partition_bound(char *relname, Relation parent,
30833086
PartitionRangeDatum *datum;
30843087

30853088
/*
3086-
* Fetch the problematic key from the lower datums
3087-
* list. Given the way partition_range_bsearch()
3088-
* works, the new lower bound is certainly >= the
3089-
* bound at offset. If the bound matches exactly, we
3090-
* flag the 1st key.
3089+
* Point to problematic key in the lower datums list;
3090+
* if we have equality, point to the first one.
30913091
*/
3092-
Assert(cmpval >= 0);
30933092
datum = cmpval == 0 ? linitial(spec->lowerdatums) :
3094-
list_nth(spec->lowerdatums, cmpval - 1);
3093+
list_nth(spec->lowerdatums, Abs(cmpval) - 1);
30953094
overlap = true;
30963095
overlap_location = datum->location;
30973096
with = boundinfo->indexes[offset + 1];
@@ -3393,13 +3392,14 @@ partition_rbound_cmp(int partnatts, FmgrInfo *partsupfunc,
33933392
else if (kind1[i] > kind2[i])
33943393
return colnum;
33953394
else if (kind1[i] != PARTITION_RANGE_DATUM_VALUE)
3396-
3395+
{
33973396
/*
33983397
* The column bounds are both MINVALUE or both MAXVALUE. No later
33993398
* columns should be considered, but we still need to compare
34003399
* whether they are upper or lower bounds.
34013400
*/
34023401
break;
3402+
}
34033403

34043404
cmpval = DatumGetInt32(FunctionCall2Coll(&partsupfunc[i],
34053405
partcollation[i],
@@ -3692,9 +3692,9 @@ qsort_partition_rbound_cmp(const void *a, const void *b, void *arg)
36923692
PartitionRangeBound *b2 = (*(PartitionRangeBound *const *) b);
36933693
PartitionKey key = (PartitionKey) arg;
36943694

3695-
return partition_rbound_cmp(key->partnatts, key->partsupfunc,
3696-
key->partcollation, b1->datums, b1->kind,
3697-
b1->lower, b2);
3695+
return compare_range_bounds(key->partnatts, key->partsupfunc,
3696+
key->partcollation,
3697+
b1, b2);
36983698
}
36993699

37003700
/*

src/test/regress/expected/create_table.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,10 @@ ERROR: partition "fail_part" would overlap partition "part0"
856856
LINE 1: ..._part PARTITION OF range_parted2 FOR VALUES FROM (minvalue) ...
857857
^
858858
CREATE TABLE part1 PARTITION OF range_parted2 FOR VALUES FROM (1) TO (10);
859+
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (-1) TO (1);
860+
ERROR: partition "fail_part" would overlap partition "part0"
861+
LINE 1: ..._part PARTITION OF range_parted2 FOR VALUES FROM (-1) TO (1)...
862+
^
859863
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (9) TO (maxvalue);
860864
ERROR: partition "fail_part" would overlap partition "part1"
861865
LINE 1: ..._part PARTITION OF range_parted2 FOR VALUES FROM (9) TO (max...

src/test/regress/sql/create_table.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (1);
687687
CREATE TABLE part0 PARTITION OF range_parted2 FOR VALUES FROM (minvalue) TO (1);
688688
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (minvalue) TO (2);
689689
CREATE TABLE part1 PARTITION OF range_parted2 FOR VALUES FROM (1) TO (10);
690+
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (-1) TO (1);
690691
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (9) TO (maxvalue);
691692
CREATE TABLE part2 PARTITION OF range_parted2 FOR VALUES FROM (20) TO (30);
692693
CREATE TABLE part3 PARTITION OF range_parted2 FOR VALUES FROM (30) TO (40);

0 commit comments

Comments
 (0)