mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Fix reporting of constraint violations for table partitioning.
After a tuple is routed to a partition, it has been converted from the root table's row type to the partition's row type. ExecConstraints needs to report the failure using the original tuple and the parent's tuple descriptor rather than the ones for the selected partition. Amit Langote
This commit is contained in:
@ -828,6 +828,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
|
||||
resultRelation,
|
||||
resultRelationIndex,
|
||||
true,
|
||||
NULL,
|
||||
estate->es_instrument);
|
||||
resultRelInfo++;
|
||||
}
|
||||
@ -1218,6 +1219,7 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
|
||||
Relation resultRelationDesc,
|
||||
Index resultRelationIndex,
|
||||
bool load_partition_check,
|
||||
Relation partition_root,
|
||||
int instrument_options)
|
||||
{
|
||||
MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
|
||||
@ -1259,6 +1261,11 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
|
||||
resultRelInfo->ri_PartitionCheck =
|
||||
RelationGetPartitionQual(resultRelationDesc,
|
||||
true);
|
||||
/*
|
||||
* The following gets set to NULL unless we are initializing leaf
|
||||
* partitions for tuple-routing.
|
||||
*/
|
||||
resultRelInfo->ri_PartitionRoot = partition_root;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1322,6 +1329,7 @@ ExecGetTriggerResultRel(EState *estate, Oid relid)
|
||||
rel,
|
||||
0, /* dummy rangetable index */
|
||||
true,
|
||||
NULL,
|
||||
estate->es_instrument);
|
||||
estate->es_trig_target_relations =
|
||||
lappend(estate->es_trig_target_relations, rInfo);
|
||||
@ -1743,9 +1751,21 @@ ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
|
||||
return ExecQual(resultRelInfo->ri_PartitionCheckExpr, econtext, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* ExecConstraints - check constraints of the tuple in 'slot'
|
||||
*
|
||||
* This checks the traditional NOT NULL and check constraints, as well as
|
||||
* the partition constraint, if any.
|
||||
*
|
||||
* Note: 'slot' contains the tuple to check the constraints of, which may
|
||||
* have been converted from the original input tuple after tuple routing,
|
||||
* while 'orig_slot' contains the original tuple to be shown in the message,
|
||||
* if an error occurs.
|
||||
*/
|
||||
void
|
||||
ExecConstraints(ResultRelInfo *resultRelInfo,
|
||||
TupleTableSlot *slot, EState *estate)
|
||||
TupleTableSlot *slot, TupleTableSlot *orig_slot,
|
||||
EState *estate)
|
||||
{
|
||||
Relation rel = resultRelInfo->ri_RelationDesc;
|
||||
TupleDesc tupdesc = RelationGetDescr(rel);
|
||||
@ -1767,12 +1787,24 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
|
||||
slot_attisnull(slot, attrChk))
|
||||
{
|
||||
char *val_desc;
|
||||
Relation orig_rel = rel;
|
||||
TupleDesc orig_tupdesc = tupdesc;
|
||||
|
||||
/*
|
||||
* choose the correct relation to build val_desc from the
|
||||
* tuple contained in orig_slot
|
||||
*/
|
||||
if (resultRelInfo->ri_PartitionRoot)
|
||||
{
|
||||
rel = resultRelInfo->ri_PartitionRoot;
|
||||
tupdesc = RelationGetDescr(rel);
|
||||
}
|
||||
|
||||
insertedCols = GetInsertedColumns(resultRelInfo, estate);
|
||||
updatedCols = GetUpdatedColumns(resultRelInfo, estate);
|
||||
modifiedCols = bms_union(insertedCols, updatedCols);
|
||||
val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
|
||||
slot,
|
||||
orig_slot,
|
||||
tupdesc,
|
||||
modifiedCols,
|
||||
64);
|
||||
@ -1780,9 +1812,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NOT_NULL_VIOLATION),
|
||||
errmsg("null value in column \"%s\" violates not-null constraint",
|
||||
NameStr(tupdesc->attrs[attrChk - 1]->attname)),
|
||||
NameStr(orig_tupdesc->attrs[attrChk - 1]->attname)),
|
||||
val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
|
||||
errtablecol(rel, attrChk)));
|
||||
errtablecol(orig_rel, attrChk)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1794,21 +1826,29 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
|
||||
if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
|
||||
{
|
||||
char *val_desc;
|
||||
Relation orig_rel = rel;
|
||||
|
||||
/* See the comment above. */
|
||||
if (resultRelInfo->ri_PartitionRoot)
|
||||
{
|
||||
rel = resultRelInfo->ri_PartitionRoot;
|
||||
tupdesc = RelationGetDescr(rel);
|
||||
}
|
||||
|
||||
insertedCols = GetInsertedColumns(resultRelInfo, estate);
|
||||
updatedCols = GetUpdatedColumns(resultRelInfo, estate);
|
||||
modifiedCols = bms_union(insertedCols, updatedCols);
|
||||
val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
|
||||
slot,
|
||||
orig_slot,
|
||||
tupdesc,
|
||||
modifiedCols,
|
||||
64);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_CHECK_VIOLATION),
|
||||
errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
|
||||
RelationGetRelationName(rel), failed),
|
||||
RelationGetRelationName(orig_rel), failed),
|
||||
val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
|
||||
errtableconstraint(rel, failed)));
|
||||
errtableconstraint(orig_rel, failed)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1816,19 +1856,27 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
|
||||
!ExecPartitionCheck(resultRelInfo, slot, estate))
|
||||
{
|
||||
char *val_desc;
|
||||
Relation orig_rel = rel;
|
||||
|
||||
/* See the comment above. */
|
||||
if (resultRelInfo->ri_PartitionRoot)
|
||||
{
|
||||
rel = resultRelInfo->ri_PartitionRoot;
|
||||
tupdesc = RelationGetDescr(rel);
|
||||
}
|
||||
|
||||
insertedCols = GetInsertedColumns(resultRelInfo, estate);
|
||||
updatedCols = GetUpdatedColumns(resultRelInfo, estate);
|
||||
modifiedCols = bms_union(insertedCols, updatedCols);
|
||||
val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
|
||||
slot,
|
||||
orig_slot,
|
||||
tupdesc,
|
||||
modifiedCols,
|
||||
64);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_CHECK_VIOLATION),
|
||||
errmsg("new row for relation \"%s\" violates partition constraint",
|
||||
RelationGetRelationName(rel)),
|
||||
RelationGetRelationName(orig_rel)),
|
||||
val_desc ? errdetail("Failing row contains %s.", val_desc) : 0));
|
||||
}
|
||||
}
|
||||
@ -3086,6 +3134,7 @@ ExecSetupPartitionTupleRouting(Relation rel,
|
||||
partrel,
|
||||
1, /* dummy */
|
||||
false,
|
||||
rel,
|
||||
0);
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user