diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 28130fbc2b..cd516ab2d3 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -93,11 +93,10 @@ static bool ExecCheckRTEPermsModified(Oid relOid, Oid userid, Bitmapset *modifiedCols, AclMode requiredPerms); static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt); -static char *ExecBuildSlotValueDescription(Oid reloid, - TupleTableSlot *slot, - TupleDesc tupdesc, - Bitmapset *modifiedCols, - int maxfieldlen); +static char *ExecBuildSlotValueDescription(EState *estate, + ResultRelInfo *resultRelInfo, + TupleTableSlot *slot, + int maxfieldlen); static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree); /* @@ -1829,51 +1828,10 @@ ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate) { - Oid root_relid; - TupleDesc tupdesc; char *val_desc; - Bitmapset *modifiedCols; - /* - * If the tuple has been routed, it's been converted to the partition's - * rowtype, which might differ from the root table's. We must convert it - * back to the root table's rowtype so that val_desc in the error message - * matches the input tuple. - */ - if (resultRelInfo->ri_PartitionRoot) - { - TupleDesc old_tupdesc; - AttrMap *map; - - root_relid = RelationGetRelid(resultRelInfo->ri_PartitionRoot); - tupdesc = RelationGetDescr(resultRelInfo->ri_PartitionRoot); - - old_tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc); - /* a reverse map */ - map = build_attrmap_by_name_if_req(old_tupdesc, tupdesc); - - /* - * Partition-specific slot's tupdesc can't be changed, so allocate a - * new one. - */ - if (map != NULL) - slot = execute_attr_map_slot(map, slot, - MakeTupleTableSlot(tupdesc, &TTSOpsVirtual)); - } - else - { - root_relid = RelationGetRelid(resultRelInfo->ri_RelationDesc); - tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc); - } - - modifiedCols = bms_union(GetInsertedColumns(resultRelInfo, estate), - GetUpdatedColumns(resultRelInfo, estate)); - - val_desc = ExecBuildSlotValueDescription(root_relid, - slot, - tupdesc, - modifiedCols, - 64); + val_desc = ExecBuildSlotValueDescription(estate, resultRelInfo, + slot, 64); ereport(ERROR, (errcode(ERRCODE_CHECK_VIOLATION), errmsg("new row for relation \"%s\" violates partition constraint", @@ -1899,9 +1857,6 @@ ExecConstraints(ResultRelInfo *resultRelInfo, Relation rel = resultRelInfo->ri_RelationDesc; TupleDesc tupdesc = RelationGetDescr(rel); TupleConstr *constr = tupdesc->constr; - Bitmapset *modifiedCols; - Bitmapset *insertedCols; - Bitmapset *updatedCols; Assert(constr || resultRelInfo->ri_PartitionCheck); @@ -1917,51 +1872,19 @@ ExecConstraints(ResultRelInfo *resultRelInfo, if (att->attnotnull && slot_attisnull(slot, attrChk)) { char *val_desc; - Relation orig_rel = rel; - TupleDesc orig_tupdesc = RelationGetDescr(rel); - /* - * If the tuple has been routed, it's been converted to the - * partition's rowtype, which might differ from the root - * table's. We must convert it back to the root table's - * rowtype so that val_desc shown error message matches the - * input tuple. - */ - if (resultRelInfo->ri_PartitionRoot) - { - AttrMap *map; - - rel = resultRelInfo->ri_PartitionRoot; - tupdesc = RelationGetDescr(rel); - /* a reverse map */ - map = build_attrmap_by_name_if_req(orig_tupdesc, - tupdesc); - - /* - * Partition-specific slot's tupdesc can't be changed, so - * allocate a new one. - */ - if (map != NULL) - slot = execute_attr_map_slot(map, slot, - MakeTupleTableSlot(tupdesc, &TTSOpsVirtual)); - } - - insertedCols = GetInsertedColumns(resultRelInfo, estate); - updatedCols = GetUpdatedColumns(resultRelInfo, estate); - modifiedCols = bms_union(insertedCols, updatedCols); - val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel), + val_desc = ExecBuildSlotValueDescription(estate, + resultRelInfo, slot, - tupdesc, - modifiedCols, 64); ereport(ERROR, (errcode(ERRCODE_NOT_NULL_VIOLATION), errmsg("null value in column \"%s\" of relation \"%s\" violates not-null constraint", NameStr(att->attname), - RelationGetRelationName(orig_rel)), + RelationGetRelationName(rel)), val_desc ? errdetail("Failing row contains %s.", val_desc) : 0, - errtablecol(orig_rel, attrChk))); + errtablecol(rel, attrChk))); } } } @@ -1973,43 +1896,17 @@ 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) - { - TupleDesc old_tupdesc = RelationGetDescr(rel); - AttrMap *map; - - rel = resultRelInfo->ri_PartitionRoot; - tupdesc = RelationGetDescr(rel); - /* a reverse map */ - map = build_attrmap_by_name_if_req(old_tupdesc, - tupdesc); - - /* - * Partition-specific slot's tupdesc can't be changed, so - * allocate a new one. - */ - if (map != NULL) - slot = execute_attr_map_slot(map, slot, - MakeTupleTableSlot(tupdesc, &TTSOpsVirtual)); - } - - insertedCols = GetInsertedColumns(resultRelInfo, estate); - updatedCols = GetUpdatedColumns(resultRelInfo, estate); - modifiedCols = bms_union(insertedCols, updatedCols); - val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel), + val_desc = ExecBuildSlotValueDescription(estate, + resultRelInfo, slot, - tupdesc, - modifiedCols, 64); ereport(ERROR, (errcode(ERRCODE_CHECK_VIOLATION), errmsg("new row for relation \"%s\" violates check constraint \"%s\"", - RelationGetRelationName(orig_rel), failed), + RelationGetRelationName(rel), failed), val_desc ? errdetail("Failing row contains %s.", val_desc) : 0, - errtableconstraint(orig_rel, failed))); + errtableconstraint(rel, failed))); } } } @@ -2027,8 +1924,6 @@ void ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate) { - Relation rel = resultRelInfo->ri_RelationDesc; - TupleDesc tupdesc = RelationGetDescr(rel); ExprContext *econtext; ListCell *l1, *l2; @@ -2066,9 +1961,6 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo, if (!ExecQual(wcoExpr, econtext)) { char *val_desc; - Bitmapset *modifiedCols; - Bitmapset *insertedCols; - Bitmapset *updatedCols; switch (wco->kind) { @@ -2082,34 +1974,9 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo, * USING policy. */ case WCO_VIEW_CHECK: - /* See the comment in ExecConstraints(). */ - if (resultRelInfo->ri_PartitionRoot) - { - TupleDesc old_tupdesc = RelationGetDescr(rel); - AttrMap *map; - - rel = resultRelInfo->ri_PartitionRoot; - tupdesc = RelationGetDescr(rel); - /* a reverse map */ - map = build_attrmap_by_name_if_req(old_tupdesc, - tupdesc); - - /* - * Partition-specific slot's tupdesc can't be changed, - * so allocate a new one. - */ - if (map != NULL) - slot = execute_attr_map_slot(map, slot, - MakeTupleTableSlot(tupdesc, &TTSOpsVirtual)); - } - - insertedCols = GetInsertedColumns(resultRelInfo, estate); - updatedCols = GetUpdatedColumns(resultRelInfo, estate); - modifiedCols = bms_union(insertedCols, updatedCols); - val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel), + val_desc = ExecBuildSlotValueDescription(estate, + resultRelInfo, slot, - tupdesc, - modifiedCols, 64); ereport(ERROR, @@ -2162,8 +2029,7 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo, * * Also, unlike the case with index entries, we need to be prepared to ignore * dropped columns. We used to use the slot's tuple descriptor to decode the - * data, but the slot's descriptor doesn't identify dropped columns, so we - * now need to be passed the relation's descriptor. + * data, but the slot's descriptor doesn't identify dropped columns. * * Note that, like BuildIndexValueDescription, if the user does not have * permission to view any of the columns involved, a NULL is returned. Unlike @@ -2172,10 +2038,9 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo, * columns they are. */ static char * -ExecBuildSlotValueDescription(Oid reloid, +ExecBuildSlotValueDescription(EState *estate, + ResultRelInfo *resultRelInfo, TupleTableSlot *slot, - TupleDesc tupdesc, - Bitmapset *modifiedCols, int maxfieldlen) { StringInfoData buf; @@ -2186,6 +2051,9 @@ ExecBuildSlotValueDescription(Oid reloid, AclResult aclresult; bool table_perm = false; bool any_perm = false; + Oid reloid = RelationGetRelid(resultRelInfo->ri_RelationDesc); + TupleDesc tupdesc; + Bitmapset *modifiedCols; /* * Check if RLS is enabled and should be active for the relation; if so, @@ -2195,6 +2063,34 @@ ExecBuildSlotValueDescription(Oid reloid, if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED) return NULL; + /* + * If the tuple has been routed, it's been converted to the partition's + * rowtype, which might differ from the root table's. We must convert it + * back to the root table's rowtype so that val_desc matches the input + * tuple. + */ + if (resultRelInfo->ri_PartitionRoot) + { + TupleDesc old_tupdesc; + AttrMap *map; + + tupdesc = RelationGetDescr(resultRelInfo->ri_PartitionRoot); + + old_tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc); + /* a reverse map */ + map = build_attrmap_by_name_if_req(old_tupdesc, tupdesc); + + /* Note that this uses a new slot for the converted tuple. */ + if (map != NULL) + slot = execute_attr_map_slot(map, slot, + MakeTupleTableSlot(tupdesc, &TTSOpsVirtual)); + } + else + tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc); + + modifiedCols = bms_union(GetInsertedColumns(resultRelInfo, estate), + GetUpdatedColumns(resultRelInfo, estate)); + initStringInfo(&buf); appendStringInfoChar(&buf, '(');