Commit bb5d6e80 authored by Robert Haas's avatar Robert Haas

Improve the error message when creating an empty range partition.

The previous message didn't mention the name of the table or the
bounds.  Put the table name in the primary error message and the
bounds in the detail message.

Amit Langote, changed slightly by me.  Suggestions on the exac
phrasing from Tom Lane, David G. Johnston, and Dean Rasheed.

Discussion: http://postgr.es/m/CA+Tgmoae6bpwVa-1BMaVcwvCCeOoJ5B9Q9-RHWo-1gJxfPBZ5Q@mail.gmail.com
parent c1ef4e5c
...@@ -722,10 +722,16 @@ check_new_partition_bound(char *relname, Relation parent, ...@@ -722,10 +722,16 @@ check_new_partition_bound(char *relname, Relation parent,
*/ */
if (partition_rbound_cmp(key, lower->datums, lower->kind, true, if (partition_rbound_cmp(key, lower->datums, lower->kind, true,
upper) >= 0) upper) >= 0)
{
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("cannot create range partition with empty range"), errmsg("empty range bound specified for partition \"%s\"",
parser_errposition(pstate, spec->location))); relname),
errdetail("Specified lower bound %s is greater than or equal to upper bound %s.",
get_range_partbound_string(spec->lowerdatums),
get_range_partbound_string(spec->upperdatums)),
parser_errposition(pstate, spec->location)));
}
if (partdesc->nparts > 0) if (partdesc->nparts > 0)
{ {
......
...@@ -8722,47 +8722,9 @@ get_rule_expr(Node *node, deparse_context *context, ...@@ -8722,47 +8722,9 @@ get_rule_expr(Node *node, deparse_context *context,
list_length(spec->lowerdatums) == list_length(spec->lowerdatums) ==
list_length(spec->upperdatums)); list_length(spec->upperdatums));
appendStringInfoString(buf, "FOR VALUES FROM ("); appendStringInfo(buf, "FOR VALUES FROM %s TO %s",
sep = ""; get_range_partbound_string(spec->lowerdatums),
foreach(cell, spec->lowerdatums) get_range_partbound_string(spec->upperdatums));
{
PartitionRangeDatum *datum =
castNode(PartitionRangeDatum, lfirst(cell));
appendStringInfoString(buf, sep);
if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
appendStringInfoString(buf, "MINVALUE");
else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
appendStringInfoString(buf, "MAXVALUE");
else
{
Const *val = castNode(Const, datum->value);
get_const_expr(val, context, -1);
}
sep = ", ";
}
appendStringInfoString(buf, ") TO (");
sep = "";
foreach(cell, spec->upperdatums)
{
PartitionRangeDatum *datum =
castNode(PartitionRangeDatum, lfirst(cell));
appendStringInfoString(buf, sep);
if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
appendStringInfoString(buf, "MINVALUE");
else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
appendStringInfoString(buf, "MAXVALUE");
else
{
Const *val = castNode(Const, datum->value);
get_const_expr(val, context, -1);
}
sep = ", ";
}
appendStringInfoString(buf, ")");
break; break;
default: default:
...@@ -10943,3 +10905,43 @@ flatten_reloptions(Oid relid) ...@@ -10943,3 +10905,43 @@ flatten_reloptions(Oid relid)
return result; return result;
} }
/*
* get_one_range_partition_bound_string
* A C string representation of one range partition bound
*/
char *
get_range_partbound_string(List *bound_datums)
{
deparse_context context;
StringInfo buf = makeStringInfo();
ListCell *cell;
char *sep;
memset(&context, 0, sizeof(deparse_context));
context.buf = buf;
appendStringInfoString(buf, "(");
sep = "";
foreach(cell, bound_datums)
{
PartitionRangeDatum *datum =
castNode(PartitionRangeDatum, lfirst(cell));
appendStringInfoString(buf, sep);
if (datum->kind == PARTITION_RANGE_DATUM_MINVALUE)
appendStringInfoString(buf, "MINVALUE");
else if (datum->kind == PARTITION_RANGE_DATUM_MAXVALUE)
appendStringInfoString(buf, "MAXVALUE");
else
{
Const *val = castNode(Const, datum->value);
get_const_expr(val, &context, -1);
}
sep = ", ";
}
appendStringInfoString(buf, ")");
return buf->data;
}
...@@ -33,5 +33,6 @@ extern List *set_deparse_context_planstate(List *dpcontext, ...@@ -33,5 +33,6 @@ extern List *set_deparse_context_planstate(List *dpcontext,
extern List *select_rtable_names_for_explain(List *rtable, extern List *select_rtable_names_for_explain(List *rtable,
Bitmapset *rels_used); Bitmapset *rels_used);
extern char *generate_collation_name(Oid collid); extern char *generate_collation_name(Oid collid);
extern char *get_range_partbound_string(List *bound_datums);
#endif /* RULEUTILS_H */ #endif /* RULEUTILS_H */
...@@ -567,10 +567,12 @@ CREATE TABLE range_parted2 ( ...@@ -567,10 +567,12 @@ CREATE TABLE range_parted2 (
) PARTITION BY RANGE (a); ) PARTITION BY RANGE (a);
-- trying to create range partition with empty range -- trying to create range partition with empty range
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (0); CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (0);
ERROR: cannot create range partition with empty range ERROR: empty range bound specified for partition "fail_part"
DETAIL: Specified lower bound (1) is greater than or equal to upper bound (0).
-- note that the range '[1, 1)' has no elements -- note that the range '[1, 1)' has no elements
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (1); CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (1) TO (1);
ERROR: cannot create range partition with empty range ERROR: empty range bound specified for partition "fail_part"
DETAIL: Specified lower bound (1) is greater than or equal to upper bound (1).
CREATE TABLE part0 PARTITION OF range_parted2 FOR VALUES FROM (minvalue) TO (1); CREATE TABLE part0 PARTITION OF range_parted2 FOR VALUES FROM (minvalue) TO (1);
CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (minvalue) TO (2); CREATE TABLE fail_part PARTITION OF range_parted2 FOR VALUES FROM (minvalue) TO (2);
ERROR: partition "fail_part" would overlap partition "part0" ERROR: partition "fail_part" would overlap partition "part0"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment