* rewriteTargetView - * Attempt to rewrite a query where the target relation is a view, so that * the view's base relation becomes the target relation. * * Note that the base relation here may itself be a view, which may or may not * have INSTEAD OF triggers or rules to handle the update. That is handled by * the recursion in RewriteQuery. */
| 3108 | * the recursion in RewriteQuery. |
| 3109 | */ |
| 3110 | static Query * |
| 3111 | rewriteTargetView(Query *parsetree, Relation view) |
| 3112 | { |
| 3113 | Query *viewquery; |
| 3114 | const char *auto_update_detail; |
| 3115 | RangeTblRef *rtr; |
| 3116 | int base_rt_index; |
| 3117 | int new_rt_index; |
| 3118 | RangeTblEntry *base_rte; |
| 3119 | RangeTblEntry *view_rte; |
| 3120 | RangeTblEntry *new_rte; |
| 3121 | Relation base_rel; |
| 3122 | List *view_targetlist; |
| 3123 | ListCell *lc; |
| 3124 | |
| 3125 | /* |
| 3126 | * Get the Query from the view's ON SELECT rule. We're going to munge the |
| 3127 | * Query to change the view's base relation into the target relation, |
| 3128 | * along with various other changes along the way, so we need to make a |
| 3129 | * copy of it (get_view_query() returns a pointer into the relcache, so we |
| 3130 | * have to treat it as read-only). |
| 3131 | */ |
| 3132 | viewquery = copyObject(get_view_query(view)); |
| 3133 | |
| 3134 | /* The view must be updatable, else fail */ |
| 3135 | auto_update_detail = |
| 3136 | view_query_is_auto_updatable(viewquery, |
| 3137 | parsetree->commandType != CMD_DELETE); |
| 3138 | |
| 3139 | if (auto_update_detail) |
| 3140 | { |
| 3141 | /* messages here should match execMain.c's CheckValidResultRel */ |
| 3142 | switch (parsetree->commandType) |
| 3143 | { |
| 3144 | case CMD_INSERT: |
| 3145 | ereport(ERROR, |
| 3146 | (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
| 3147 | errmsg("cannot insert into view \"%s\"", |
| 3148 | RelationGetRelationName(view)), |
| 3149 | errdetail_internal("%s", _(auto_update_detail)), |
| 3150 | errhint("To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule."))); |
| 3151 | break; |
| 3152 | case CMD_UPDATE: |
| 3153 | ereport(ERROR, |
| 3154 | (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
| 3155 | errmsg("cannot update view \"%s\"", |
| 3156 | RelationGetRelationName(view)), |
| 3157 | errdetail_internal("%s", _(auto_update_detail)), |
| 3158 | errhint("To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule."))); |
| 3159 | break; |
| 3160 | case CMD_DELETE: |
| 3161 | ereport(ERROR, |
| 3162 | (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
| 3163 | errmsg("cannot delete from view \"%s\"", |
| 3164 | RelationGetRelationName(view)), |
| 3165 | errdetail_internal("%s", _(auto_update_detail)), |
| 3166 | errhint("To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule."))); |
| 3167 | break; |
no test coverage detected