* ExecConstraints - check constraints of the tuple in 'slot' * * This checks the traditional NOT NULL and check constraints. * * The partition constraint is *NOT* checked. * * Note: 'slot' contains the tuple to check the constraints of, which may * have been converted from the original input tuple after tuple routing. * 'resultRelInfo' is the final result relation, after tuple routing. */
| 3081 | * 'resultRelInfo' is the final result relation, after tuple routing. |
| 3082 | */ |
| 3083 | void |
| 3084 | ExecConstraints(ResultRelInfo *resultRelInfo, |
| 3085 | TupleTableSlot *slot, EState *estate) |
| 3086 | { |
| 3087 | Relation rel = resultRelInfo->ri_RelationDesc; |
| 3088 | TupleDesc tupdesc = RelationGetDescr(rel); |
| 3089 | TupleConstr *constr = tupdesc->constr; |
| 3090 | Bitmapset *modifiedCols; |
| 3091 | |
| 3092 | Assert(constr); /* we should not be called otherwise */ |
| 3093 | |
| 3094 | if (constr->has_not_null) |
| 3095 | { |
| 3096 | int natts = tupdesc->natts; |
| 3097 | int attrChk; |
| 3098 | |
| 3099 | for (attrChk = 1; attrChk <= natts; attrChk++) |
| 3100 | { |
| 3101 | Form_pg_attribute att = TupleDescAttr(tupdesc, attrChk - 1); |
| 3102 | |
| 3103 | if (att->attnotnull && slot_attisnull(slot, attrChk)) |
| 3104 | { |
| 3105 | char *val_desc; |
| 3106 | Relation orig_rel = rel; |
| 3107 | TupleDesc orig_tupdesc = RelationGetDescr(rel); |
| 3108 | |
| 3109 | /* |
| 3110 | * If the tuple has been routed, it's been converted to the |
| 3111 | * partition's rowtype, which might differ from the root |
| 3112 | * table's. We must convert it back to the root table's |
| 3113 | * rowtype so that val_desc shown error message matches the |
| 3114 | * input tuple. |
| 3115 | */ |
| 3116 | if (resultRelInfo->ri_RootResultRelInfo) |
| 3117 | { |
| 3118 | ResultRelInfo *rootrel = resultRelInfo->ri_RootResultRelInfo; |
| 3119 | AttrMap *map; |
| 3120 | |
| 3121 | tupdesc = RelationGetDescr(rootrel->ri_RelationDesc); |
| 3122 | /* a reverse map */ |
| 3123 | map = build_attrmap_by_name_if_req(orig_tupdesc, |
| 3124 | tupdesc); |
| 3125 | |
| 3126 | /* |
| 3127 | * Partition-specific slot's tupdesc can't be changed, so |
| 3128 | * allocate a new one. |
| 3129 | */ |
| 3130 | if (map != NULL) |
| 3131 | slot = execute_attr_map_slot(map, slot, |
| 3132 | MakeTupleTableSlot(tupdesc, &TTSOpsVirtual)); |
| 3133 | modifiedCols = bms_union(ExecGetInsertedCols(rootrel, estate), |
| 3134 | ExecGetUpdatedCols(rootrel, estate)); |
| 3135 | rel = rootrel->ri_RelationDesc; |
| 3136 | } |
| 3137 | else |
| 3138 | modifiedCols = bms_union(ExecGetInsertedCols(resultRelInfo, estate), |
| 3139 | ExecGetUpdatedCols(resultRelInfo, estate)); |
| 3140 | val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel), |
no test coverage detected