Skip to content

Commit efbfb64

Browse files
committed
Improve new hash partition bound check error messages
For the error message "every hash partition modulus must be a factor of the next larger modulus", add a detail message that shows the particular numbers and existing partition involved. Also comment the code more. Reviewed-by: Amit Langote <amitlangote09@gmail.com> Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi> Discussion: https://www.postgresql.org/message-id/flat/bb9d60b4-aadb-607a-1a9d-fdc3434dddcd%40enterprisedb.com
1 parent 9294264 commit efbfb64

File tree

3 files changed

+47
-18
lines changed

3 files changed

+47
-18
lines changed

src/backend/partitioning/partbounds.c

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2832,14 +2832,9 @@ check_new_partition_bound(char *relname, Relation parent,
28322832

28332833
if (partdesc->nparts > 0)
28342834
{
2835-
Datum **datums = boundinfo->datums;
2836-
int ndatums = boundinfo->ndatums;
28372835
int greatest_modulus;
28382836
int remainder;
28392837
int offset;
2840-
bool valid_modulus = true;
2841-
int prev_modulus, /* Previous largest modulus */
2842-
next_modulus; /* Next largest modulus */
28432838

28442839
/*
28452840
* Check rule that every modulus must be a factor of the
@@ -2849,7 +2844,9 @@ check_new_partition_bound(char *relname, Relation parent,
28492844
* modulus 15, but you cannot add both a partition with
28502845
* modulus 10 and a partition with modulus 15, because 10
28512846
* is not a factor of 15.
2852-
*
2847+
*/
2848+
2849+
/*
28532850
* Get the greatest (modulus, remainder) pair contained in
28542851
* boundinfo->datums that is less than or equal to the
28552852
* (spec->modulus, spec->remainder) pair.
@@ -2859,26 +2856,55 @@ check_new_partition_bound(char *relname, Relation parent,
28592856
spec->remainder);
28602857
if (offset < 0)
28612858
{
2862-
next_modulus = DatumGetInt32(datums[0][0]);
2863-
valid_modulus = (next_modulus % spec->modulus) == 0;
2859+
int next_modulus;
2860+
2861+
/*
2862+
* All existing moduli are greater or equal, so the
2863+
* new one must be a factor of the smallest one, which
2864+
* is first in the boundinfo.
2865+
*/
2866+
next_modulus = DatumGetInt32(boundinfo->datums[0][0]);
2867+
if (next_modulus % spec->modulus != 0)
2868+
ereport(ERROR,
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\".",
2872+
spec->modulus, next_modulus,
2873+
get_rel_name(partdesc->oids[boundinfo->indexes[0]]))));
28642874
}
28652875
else
28662876
{
2867-
prev_modulus = DatumGetInt32(datums[offset][0]);
2868-
valid_modulus = (spec->modulus % prev_modulus) == 0;
2877+
int prev_modulus;
2878+
2879+
/* We found the largest modulus less than or equal to ours. */
2880+
prev_modulus = DatumGetInt32(boundinfo->datums[offset][0]);
2881+
2882+
if (spec->modulus % prev_modulus != 0)
2883+
ereport(ERROR,
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\".",
2887+
spec->modulus,
2888+
prev_modulus,
2889+
get_rel_name(partdesc->oids[boundinfo->indexes[offset]]))));
28692890

2870-
if (valid_modulus && (offset + 1) < ndatums)
2891+
if (offset + 1 < boundinfo->ndatums)
28712892
{
2872-
next_modulus = DatumGetInt32(datums[offset + 1][0]);
2873-
valid_modulus = (next_modulus % spec->modulus) == 0;
2893+
int next_modulus;
2894+
2895+
/* Look at the next higher modulus */
2896+
next_modulus = DatumGetInt32(boundinfo->datums[offset + 1][0]);
2897+
2898+
if (next_modulus % spec->modulus != 0)
2899+
ereport(ERROR,
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\".",
2903+
spec->modulus, next_modulus,
2904+
get_rel_name(partdesc->oids[boundinfo->indexes[offset + 1]]))));
28742905
}
28752906
}
28762907

2877-
if (!valid_modulus)
2878-
ereport(ERROR,
2879-
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2880-
errmsg("every hash partition modulus must be a factor of the next larger modulus")));
2881-
28822908
greatest_modulus = boundinfo->nindexes;
28832909
remainder = spec->remainder;
28842910

src/test/regress/expected/alter_table.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4109,6 +4109,7 @@ ALTER TABLE hash_parted ATTACH PARTITION fail_part FOR VALUES WITH (MODULUS 8, R
41094109
ERROR: remainder for hash partition must be less than modulus
41104110
ALTER TABLE hash_parted ATTACH PARTITION fail_part FOR VALUES WITH (MODULUS 3, REMAINDER 2);
41114111
ERROR: every hash partition modulus must be a factor of the next larger modulus
4112+
DETAIL: The new modulus 3 is not a factor of 4, the modulus of existing partition "hpart_1".
41124113
DROP TABLE fail_part;
41134114
--
41144115
-- DETACH PARTITION

src/test/regress/expected/create_table.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,9 +783,11 @@ CREATE TABLE hpart_3 PARTITION OF hash_parted FOR VALUES WITH (MODULUS 200, REMA
783783
-- modulus 25 is factor of modulus of 50 but 10 is not factor of 25.
784784
CREATE TABLE fail_part PARTITION OF hash_parted FOR VALUES WITH (MODULUS 25, REMAINDER 3);
785785
ERROR: every hash partition modulus must be a factor of the next larger modulus
786+
DETAIL: The new modulus 25 is not divisible by 10, the modulus of existing partition "hpart_1".
786787
-- previous modulus 50 is factor of 150 but this modulus is not factor of next modulus 200.
787788
CREATE TABLE fail_part PARTITION OF hash_parted FOR VALUES WITH (MODULUS 150, REMAINDER 3);
788789
ERROR: every hash partition modulus must be a factor of the next larger modulus
790+
DETAIL: The new modulus 150 is not factor of 200, the modulus of existing partition "hpart_3".
789791
-- trying to specify range for the hash partitioned table
790792
CREATE TABLE fail_part PARTITION OF hash_parted FOR VALUES FROM ('a', 1) TO ('z');
791793
ERROR: invalid bound specification for a hash partition

0 commit comments

Comments
 (0)