I had a bit of trouble parsing the error message "every hash partition
modulus must be a factor of the next larger modulus", so I went into the
code, added some comments and added errdetail messages for each case. I
think it's a bit clearer now.
From e7f392e2f8950236a22f007cc3aed36729da22e1 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Tue, 2 Feb 2021 11:21:21 +0100
Subject: [PATCH] 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 involved. Also comment the code more.
---
src/backend/partitioning/partbounds.c | 58 +++++++++++++++-------
src/test/regress/expected/alter_table.out | 1 +
src/test/regress/expected/create_table.out | 2 +
3 files changed, 43 insertions(+), 18 deletions(-)
diff --git a/src/backend/partitioning/partbounds.c
b/src/backend/partitioning/partbounds.c
index 0c3f212ff2..7425e34040 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -2832,14 +2832,9 @@ check_new_partition_bound(char *relname, Relation parent,
if (partdesc->nparts > 0)
{
- Datum **datums = boundinfo->datums;
- int ndatums =
boundinfo->ndatums;
int
greatest_modulus;
int remainder;
int offset;
- bool valid_modulus = true;
- int prev_modulus,
/* Previous largest modulus */
- next_modulus;
/* Next largest modulus */
/*
* Check rule that every modulus must
be a factor of the
@@ -2849,7 +2844,9 @@ check_new_partition_bound(char *relname, Relation parent,
* modulus 15, but you cannot add both
a partition with
* modulus 10 and a partition with
modulus 15, because 10
* is not a factor of 15.
- *
+ */
+
+ /*
* Get the greatest (modulus,
remainder) pair contained in
* boundinfo->datums that is less than
or equal to the
* (spec->modulus, spec->remainder)
pair.
@@ -2859,26 +2856,51 @@ check_new_partition_bound(char *relname, Relation
parent,
spec->remainder);
if (offset < 0)
{
- next_modulus =
DatumGetInt32(datums[0][0]);
- valid_modulus = (next_modulus %
spec->modulus) == 0;
+ int
next_modulus;
+
+ /*
+ * All existing moduli are
greater or equal, so the
+ * new one must be a factor of
the smallest one, which
+ * is first in the boundinfo.
+ */
+ next_modulus =
DatumGetInt32(boundinfo->datums[0][0]);
+ if (next_modulus %
spec->modulus != 0)
+ ereport(ERROR,
+
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+
errmsg("every hash partition modulus must be a factor of the next larger
modulus"),
+
errdetail("The new modulus %d is not a factor of the existing modulus %d.",
+
spec->modulus, next_modulus)));
}
else
{
- prev_modulus =
DatumGetInt32(datums[offset][0]);
- valid_modulus = (spec->modulus
% prev_modulus) == 0;
+ int
prev_modulus;
- if (valid_modulus && (offset +
1) < ndatums)
+ /* We found the largest modulus
less than or equal to ours. */
+ prev_modulus =
DatumGetInt32(boundinfo->datums[offset][0]);
+
+ if (spec->modulus %
prev_modulus != 0)
+ ereport(ERROR,
+
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+
errmsg("every hash partition modulus must be a factor of the next larger
modulus"),
+
errdetail("The existing modulus %d is not a factor of the new modulus %d.",
+
prev_modulus, spec->modulus)));
+
+ if (offset + 1 <
boundinfo->ndatums)
{
- next_modulus =
DatumGetInt32(datums[offset + 1][0]);
- valid_modulus =
(next_modulus % spec->modulus) == 0;
+ int
next_modulus;
+
+ /* Look at the next
higher modulus */
+ next_modulus =
DatumGetInt32(boundinfo->datums[offset + 1][0]);
+
+ if (next_modulus %
spec->modulus != 0)
+ ereport(ERROR,
+
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+
errmsg("every hash partition modulus must be a factor of the next larger
modulus"),
+
errdetail("The new modulus %d is not factor of the existing modulus %d.",
+
spec->modulus, next_modulus)));
}
}
- if (!valid_modulus)
- ereport(ERROR,
-
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("every
hash partition modulus must be a factor of the next larger modulus")));
-
greatest_modulus = boundinfo->nindexes;
remainder = spec->remainder;
diff --git a/src/test/regress/expected/alter_table.out
b/src/test/regress/expected/alter_table.out
index 0ce6ee4622..62bf27fc50 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -4109,6 +4109,7 @@ ALTER TABLE hash_parted ATTACH PARTITION fail_part FOR
VALUES WITH (MODULUS 8, R
ERROR: remainder for hash partition must be less than modulus
ALTER TABLE hash_parted ATTACH PARTITION fail_part FOR VALUES WITH (MODULUS 3,
REMAINDER 2);
ERROR: every hash partition modulus must be a factor of the next larger
modulus
+DETAIL: The new modulus 3 is not a factor of the existing modulus 4.
DROP TABLE fail_part;
--
-- DETACH PARTITION
diff --git a/src/test/regress/expected/create_table.out
b/src/test/regress/expected/create_table.out
index ed8c01b8de..95d8ed4c45 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -783,9 +783,11 @@ CREATE TABLE hpart_3 PARTITION OF hash_parted FOR VALUES
WITH (MODULUS 200, REMA
-- modulus 25 is factor of modulus of 50 but 10 is not factor of 25.
CREATE TABLE fail_part PARTITION OF hash_parted FOR VALUES WITH (MODULUS 25,
REMAINDER 3);
ERROR: every hash partition modulus must be a factor of the next larger
modulus
+DETAIL: The existing modulus 10 is not a factor of the new modulus 25.
-- previous modulus 50 is factor of 150 but this modulus is not factor of next
modulus 200.
CREATE TABLE fail_part PARTITION OF hash_parted FOR VALUES WITH (MODULUS 150,
REMAINDER 3);
ERROR: every hash partition modulus must be a factor of the next larger
modulus
+DETAIL: The new modulus 150 is not factor of the existing modulus 200.
-- trying to specify range for the hash partitioned table
CREATE TABLE fail_part PARTITION OF hash_parted FOR VALUES FROM ('a', 1) TO
('z');
ERROR: invalid bound specification for a hash partition
--
2.30.0