diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 66cac46acf..5dbba3b6a0 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -94,10 +94,9 @@ static bool ExecCheckRTEPermsModified(Oid relOid, Oid userid, Bitmapset *modifiedCols, AclMode requiredPerms); static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt); -static char *ExecBuildSlotValueDescription(Oid reloid, +static char *ExecBuildSlotValueDescription(EState *estate, + ResultRelInfo *resultRelInfo, TupleTableSlot *slot, - TupleDesc tupdesc, - Bitmapset *modifiedCols, int maxfieldlen); static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree); @@ -1906,49 +1905,14 @@ ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate) { - Relation rel = resultRelInfo->ri_RelationDesc; - Relation orig_rel = rel; - TupleDesc tupdesc = RelationGetDescr(rel); char *val_desc; - Bitmapset *modifiedCols; - Bitmapset *insertedCols; - Bitmapset *updatedCols; - /* - * Need to first convert the tuple to the root partitioned table's row - * type. For details, check similar comments in ExecConstraints(). - */ - if (resultRelInfo->ri_PartitionRoot) - { - HeapTuple tuple = ExecFetchSlotTuple(slot); - TupleDesc old_tupdesc = RelationGetDescr(rel); - TupleConversionMap *map; - - rel = resultRelInfo->ri_PartitionRoot; - tupdesc = RelationGetDescr(rel); - /* a reverse map */ - map = convert_tuples_by_name(old_tupdesc, tupdesc, - gettext_noop("could not convert row type")); - if (map != NULL) - { - tuple = do_convert_tuple(tuple, map); - ExecSetSlotDescriptor(slot, tupdesc); - ExecStoreTuple(tuple, slot, InvalidBuffer, false); - } - } - - insertedCols = GetInsertedColumns(resultRelInfo, estate); - updatedCols = GetUpdatedColumns(resultRelInfo, estate); - modifiedCols = bms_union(insertedCols, updatedCols); - val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel), - 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", - RelationGetRelationName(orig_rel)), + RelationGetRelationName(resultRelInfo->ri_RelationDesc)), val_desc ? errdetail("Failing row contains %s.", val_desc) : 0)); } @@ -1970,9 +1934,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); @@ -1988,49 +1949,17 @@ 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) - { - HeapTuple tuple = ExecFetchSlotTuple(slot); - TupleConversionMap *map; - - rel = resultRelInfo->ri_PartitionRoot; - tupdesc = RelationGetDescr(rel); - /* a reverse map */ - map = convert_tuples_by_name(orig_tupdesc, tupdesc, - gettext_noop("could not convert row type")); - if (map != NULL) - { - tuple = do_convert_tuple(tuple, map); - ExecSetSlotDescriptor(slot, tupdesc); - ExecStoreTuple(tuple, slot, InvalidBuffer, false); - } - } - - 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\" violates not-null constraint", NameStr(att->attname)), val_desc ? errdetail("Failing row contains %s.", val_desc) : 0, - errtablecol(orig_rel, attrChk))); + errtablecol(rel, attrChk))); } } } @@ -2042,42 +1971,15 @@ 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) - { - HeapTuple tuple = ExecFetchSlotTuple(slot); - TupleDesc old_tupdesc = RelationGetDescr(rel); - TupleConversionMap *map; - - rel = resultRelInfo->ri_PartitionRoot; - tupdesc = RelationGetDescr(rel); - /* a reverse map */ - map = convert_tuples_by_name(old_tupdesc, tupdesc, - gettext_noop("could not convert row type")); - if (map != NULL) - { - tuple = do_convert_tuple(tuple, map); - ExecSetSlotDescriptor(slot, tupdesc); - ExecStoreTuple(tuple, slot, InvalidBuffer, false); - } - } - - insertedCols = GetInsertedColumns(resultRelInfo, estate); - updatedCols = GetUpdatedColumns(resultRelInfo, estate); - modifiedCols = bms_union(insertedCols, updatedCols); - val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel), - slot, - tupdesc, - modifiedCols, - 64); + val_desc = ExecBuildSlotValueDescription(estate, resultRelInfo, + slot, 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))); } } } @@ -2095,8 +1997,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; @@ -2134,9 +2034,6 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo, if (!ExecQual(wcoExpr, econtext)) { char *val_desc; - Bitmapset *modifiedCols; - Bitmapset *insertedCols; - Bitmapset *updatedCols; switch (wco->kind) { @@ -2150,33 +2047,9 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo, * USING policy. */ case WCO_VIEW_CHECK: - /* See the comment in ExecConstraints(). */ - if (resultRelInfo->ri_PartitionRoot) - { - HeapTuple tuple = ExecFetchSlotTuple(slot); - TupleDesc old_tupdesc = RelationGetDescr(rel); - TupleConversionMap *map; - - rel = resultRelInfo->ri_PartitionRoot; - tupdesc = RelationGetDescr(rel); - /* a reverse map */ - map = convert_tuples_by_name(old_tupdesc, tupdesc, - gettext_noop("could not convert row type")); - if (map != NULL) - { - tuple = do_convert_tuple(tuple, map); - ExecSetSlotDescriptor(slot, tupdesc); - ExecStoreTuple(tuple, slot, InvalidBuffer, false); - } - } - - 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, @@ -2229,8 +2102,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 @@ -2239,10 +2111,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; @@ -2253,6 +2124,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, @@ -2262,6 +2136,39 @@ 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) + { + HeapTuple tuple = ExecFetchSlotTuple(slot); + TupleDesc old_tupdesc; + TupleConversionMap *map; + + tupdesc = RelationGetDescr(resultRelInfo->ri_PartitionRoot); + + old_tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc); + /* a reverse map */ + map = convert_tuples_by_name(old_tupdesc, tupdesc, + gettext_noop("could not convert row type")); + if (map != NULL) + { + tuple = do_convert_tuple(tuple, map); + + /* Create a temporary slot with the new tuple descriptor. */ + slot = MakeTupleTableSlot(tupdesc); + ExecStoreTuple(tuple, slot, InvalidBuffer, false); + } + } + else + tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc); + + modifiedCols = bms_union(GetInsertedColumns(resultRelInfo, estate), + GetUpdatedColumns(resultRelInfo, estate)); + initStringInfo(&buf); appendStringInfoChar(&buf, '(');