| 1 | /*------------------------------------------------------------------------- |
| 2 | * |
| 3 | * rewriteHandler.c |
| 4 | * Primary module of query rewriter. |
| 5 | * |
| 6 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
| 7 | * Portions Copyright (c) 1994, Regents of the University of California |
| 8 | * |
| 9 | * IDENTIFICATION |
| 10 | * src/backend/rewrite/rewriteHandler.c |
| 11 | * |
| 12 | * NOTES |
| 13 | * Some of the terms used in this file are of historic nature: "retrieve" |
| 14 | * was the PostQUEL keyword for what today is SELECT. "RIR" stands for |
| 15 | * "Retrieve-Instead-Retrieve", that is an ON SELECT DO INSTEAD SELECT rule |
| 16 | * (which has to be unconditional and where only one rule can exist on each |
| 17 | * relation). |
| 18 | * |
| 19 | *------------------------------------------------------------------------- |
| 20 | */ |
| 21 | #include "postgres.h" |
| 22 | |
| 23 | #include "access/relation.h" |
| 24 | #include "access/sysattr.h" |
| 25 | #include "access/table.h" |
| 26 | #include "catalog/dependency.h" |
| 27 | #include "catalog/pg_type.h" |
| 28 | #include "commands/trigger.h" |
| 29 | #include "foreign/fdwapi.h" |
| 30 | #include "nodes/makefuncs.h" |
| 31 | #include "nodes/nodeFuncs.h" |
| 32 | #include "parser/analyze.h" |
| 33 | #include "parser/parse_coerce.h" |
| 34 | #include "parser/parse_relation.h" |
| 35 | #include "parser/parsetree.h" |
| 36 | #include "rewrite/rewriteDefine.h" |
| 37 | #include "rewrite/rewriteHandler.h" |
| 38 | #include "rewrite/rewriteManip.h" |
| 39 | #include "rewrite/rowsecurity.h" |
| 40 | #include "utils/builtins.h" |
| 41 | #include "utils/lsyscache.h" |
| 42 | #include "utils/rel.h" |
| 43 | |
| 44 | |
| 45 | /* We use a list of these to detect recursion in RewriteQuery */ |
| 46 | typedef struct rewrite_event |
| 47 | { |
| 48 | Oid relation; /* OID of relation having rules */ |
| 49 | CmdType event; /* type of rule being fired */ |
| 50 | } rewrite_event; |
| 51 | |
| 52 | typedef struct acquireLocksOnSubLinks_context |
| 53 | { |
| 54 | bool for_execute; /* AcquireRewriteLocks' forExecute param */ |
| 55 | } acquireLocksOnSubLinks_context; |
| 56 | |
| 57 | static bool acquireLocksOnSubLinks(Node *node, |
| 58 | acquireLocksOnSubLinks_context *context); |
| 59 | static Query *rewriteRuleAction(Query *parsetree, |
| 60 | Query *rule_action, |
| 61 | Node *rule_qual, |
| 62 | int rt_index, |
| 63 | CmdType event, |
| 64 | bool *returning_flag); |
| 65 | static List *adjustJoinTreeList(Query *parsetree, bool removert, int rt_index); |
| 66 | static List *rewriteTargetListIU(List *targetList, |
| 67 | CmdType commandType, |
| 68 | OverridingKind override, |
| 69 | Relation target_relation, |
| 70 | int result_rti); |
| 71 | static TargetEntry *process_matched_tle(TargetEntry *src_tle, |
| 72 | TargetEntry *prior_tle, |
| 73 | const char *attrName); |
| 74 | static Node *get_assignment_input(Node *node); |
| 75 | static bool rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti, |
| 76 | Relation target_relation, bool force_nulls); |
| 77 | static void markQueryForLocking(Query *qry, Node *jtnode, |
| 78 | LockClauseStrength strength, LockWaitPolicy waitPolicy, |
| 79 | bool pushedDown); |
| 80 | static List *matchLocks(CmdType event, RuleLock *rulelocks, |
| 81 | int varno, Query *parsetree, bool *hasUpdate); |
| 82 | static Query *fireRIRrules(Query *parsetree, List *activeRIRs); |
| 83 | static bool view_has_instead_trigger(Relation view, CmdType event); |
| 84 | static Bitmapset *adjust_view_column_set(Bitmapset *cols, List *targetlist); |
| 85 | |
| 86 | |
| 87 | /* |
| 88 | * AcquireRewriteLocks - |
| 89 | * Acquire suitable locks on all the relations mentioned in the Query. |
| 90 | * These locks will ensure that the relation schemas don't change under us |
| 91 | * while we are rewriting, planning, and executing the query. |
| 92 | * |
| 93 | * Caution: this may modify the querytree, therefore caller should usually |
| 94 | * have done a copyObject() to make a writable copy of the querytree in the |
| 95 | * current memory context. |
| 96 | * |
| 97 | * forExecute indicates that the query is about to be executed. If so, |
| 98 | * we'll acquire the lock modes specified in the RTE rellockmode fields. |
| 99 | * If forExecute is false, AccessShareLock is acquired on all relations. |
| 100 | * This case is suitable for ruleutils.c, for example, where we only need |
| 101 | * schema stability and we don't intend to actually modify any relations. |
| 102 | * |
| 103 | * forUpdatePushedDown indicates that a pushed-down FOR [KEY] UPDATE/SHARE |
| 104 | * applies to the current subquery, requiring all rels to be opened with at |
| 105 | * least RowShareLock. This should always be false at the top of the |
| 106 | * recursion. When it is true, we adjust RTE rellockmode fields to reflect |
| 107 | * the higher lock level. This flag is ignored if forExecute is false. |
| 108 | * |
| 109 | * A secondary purpose of this routine is to fix up JOIN RTE references to |
| 110 | * dropped columns (see details below). Such RTEs are modified in-place. |
| 111 | * |
| 112 | * This processing can, and for efficiency's sake should, be skipped when the |
| 113 | * querytree has just been built by the parser: parse analysis already got |
| 114 | * all the same locks we'd get here, and the parser will have omitted dropped |
| 115 | * columns from JOINs to begin with. But we must do this whenever we are |
| 116 | * dealing with a querytree produced earlier than the current command. |
| 117 | * |
| 118 | * About JOINs and dropped columns: although the parser never includes an |
| 119 | * already-dropped column in a JOIN RTE's alias var list, it is possible for |
| 120 | * such a list in a stored rule to include references to dropped columns. |
| 121 | * (If the column is not explicitly referenced anywhere else in the query, |
| 122 | * the dependency mechanism won't consider it used by the rule and so won't |
| 123 | * prevent the column drop.) To support get_rte_attribute_is_dropped(), we |
| 124 | * replace join alias vars that reference dropped columns with null pointers. |
| 125 | * |
| 126 | * (In PostgreSQL 8.0, we did not do this processing but instead had |
| 127 | * get_rte_attribute_is_dropped() recurse to detect dropped columns in joins. |
| 128 | * That approach had horrible performance unfortunately; in particular |
| 129 | * construction of a nested join was O(N^2) in the nesting depth.) |
| 130 | */ |
| 131 | void |
| 132 | AcquireRewriteLocks(Query *parsetree, |
| 133 | bool forExecute, |
| 134 | bool forUpdatePushedDown) |
| 135 | { |
| 136 | ListCell *l; |
| 137 | int rt_index; |
| 138 | acquireLocksOnSubLinks_context context; |
| 139 | |
| 140 | context.for_execute = forExecute; |
| 141 | |
| 142 | /* |
| 143 | * First, process RTEs of the current query level. |
| 144 | */ |
| 145 | rt_index = 0; |
| 146 | foreach(l, parsetree->rtable) |
| 147 | { |
| 148 | RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); |
| 149 | Relation rel; |
| 150 | LOCKMODE lockmode; |
| 151 | List *newaliasvars; |
| 152 | Index curinputvarno; |
| 153 | RangeTblEntry *curinputrte; |
| 154 | ListCell *ll; |
| 155 | |
| 156 | ++rt_index; |
| 157 | switch (rte->rtekind) |
| 158 | { |
| 159 | case RTE_RELATION: |
| 160 | |
| 161 | /* |
| 162 | * Grab the appropriate lock type for the relation, and do not |
| 163 | * release it until end of transaction. This protects the |
| 164 | * rewriter, planner, and executor against schema changes |
| 165 | * mid-query. |
| 166 | * |
| 167 | * If forExecute is false, ignore rellockmode and just use |
| 168 | * AccessShareLock. |
| 169 | */ |
| 170 | if (!forExecute) |
| 171 | lockmode = AccessShareLock; |
| 172 | else if (forUpdatePushedDown) |
| 173 | { |
| 174 | /* Upgrade RTE's lock mode to reflect pushed-down lock */ |
| 175 | if (rte->rellockmode == AccessShareLock) |
| 176 | rte->rellockmode = RowShareLock; |
| 177 | lockmode = rte->rellockmode; |
| 178 | } |
| 179 | else |
| 180 | lockmode = rte->rellockmode; |
| 181 | |
| 182 | rel = table_open(rte->relid, lockmode); |
| 183 | |
| 184 | /* |
| 185 | * While we have the relation open, update the RTE's relkind, |
| 186 | * just in case it changed since this rule was made. |
| 187 | */ |
| 188 | rte->relkind = rel->rd_rel->relkind; |
| 189 | |
| 190 | table_close(rel, NoLock); |
| 191 | break; |
| 192 | |
| 193 | case RTE_JOIN: |
| 194 | |
| 195 | /* |
| 196 | * Scan the join's alias var list to see if any columns have |
| 197 | * been dropped, and if so replace those Vars with null |
| 198 | * pointers. |
| 199 | * |
| 200 | * Since a join has only two inputs, we can expect to see |
| 201 | * multiple references to the same input RTE; optimize away |
| 202 | * multiple fetches. |
| 203 | */ |
| 204 | newaliasvars = NIL; |
| 205 | curinputvarno = 0; |
| 206 | curinputrte = NULL; |
| 207 | foreach(ll, rte->joinaliasvars) |
| 208 | { |
| 209 | Var *aliasitem = (Var *) lfirst(ll); |
| 210 | Var *aliasvar = aliasitem; |
| 211 | |
| 212 | /* Look through any implicit coercion */ |
| 213 | aliasvar = (Var *) strip_implicit_coercions((Node *) aliasvar); |
| 214 | |
| 215 | /* |
| 216 | * If the list item isn't a simple Var, then it must |
| 217 | * represent a merged column, ie a USING column, and so it |
| 218 | * couldn't possibly be dropped, since it's referenced in |
| 219 | * the join clause. (Conceivably it could also be a null |
| 220 | * pointer already? But that's OK too.) |
| 221 | */ |
| 222 | if (aliasvar && IsA(aliasvar, Var)) |
| 223 | { |
| 224 | /* |
| 225 | * The elements of an alias list have to refer to |
| 226 | * earlier RTEs of the same rtable, because that's the |
| 227 | * order the planner builds things in. So we already |
| 228 | * processed the referenced RTE, and so it's safe to |
| 229 | * use get_rte_attribute_is_dropped on it. (This might |
| 230 | * not hold after rewriting or planning, but it's OK |
| 231 | * to assume here.) |
| 232 | */ |
| 233 | Assert(aliasvar->varlevelsup == 0); |
| 234 | if (aliasvar->varno != curinputvarno) |
| 235 | { |
| 236 | curinputvarno = aliasvar->varno; |
| 237 | if (curinputvarno >= rt_index) |
| 238 | elog(ERROR, "unexpected varno %d in JOIN RTE %d" , |
| 239 | curinputvarno, rt_index); |
| 240 | curinputrte = rt_fetch(curinputvarno, |
| 241 | parsetree->rtable); |
| 242 | } |
| 243 | if (get_rte_attribute_is_dropped(curinputrte, |
| 244 | aliasvar->varattno)) |
| 245 | { |
| 246 | /* Replace the join alias item with a NULL */ |
| 247 | aliasitem = NULL; |
| 248 | } |
| 249 | } |
| 250 | newaliasvars = lappend(newaliasvars, aliasitem); |
| 251 | } |
| 252 | rte->joinaliasvars = newaliasvars; |
| 253 | break; |
| 254 | |
| 255 | case RTE_SUBQUERY: |
| 256 | |
| 257 | /* |
| 258 | * The subquery RTE itself is all right, but we have to |
| 259 | * recurse to process the represented subquery. |
| 260 | */ |
| 261 | AcquireRewriteLocks(rte->subquery, |
| 262 | forExecute, |
| 263 | (forUpdatePushedDown || |
| 264 | get_parse_rowmark(parsetree, rt_index) != NULL)); |
| 265 | break; |
| 266 | |
| 267 | default: |
| 268 | /* ignore other types of RTEs */ |
| 269 | break; |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | /* Recurse into subqueries in WITH */ |
| 274 | foreach(l, parsetree->cteList) |
| 275 | { |
| 276 | CommonTableExpr *cte = (CommonTableExpr *) lfirst(l); |
| 277 | |
| 278 | AcquireRewriteLocks((Query *) cte->ctequery, forExecute, false); |
| 279 | } |
| 280 | |
| 281 | /* |
| 282 | * Recurse into sublink subqueries, too. But we already did the ones in |
| 283 | * the rtable and cteList. |
| 284 | */ |
| 285 | if (parsetree->hasSubLinks) |
| 286 | query_tree_walker(parsetree, acquireLocksOnSubLinks, &context, |
| 287 | QTW_IGNORE_RC_SUBQUERIES); |
| 288 | } |
| 289 | |
| 290 | /* |
| 291 | * Walker to find sublink subqueries for AcquireRewriteLocks |
| 292 | */ |
| 293 | static bool |
| 294 | acquireLocksOnSubLinks(Node *node, acquireLocksOnSubLinks_context *context) |
| 295 | { |
| 296 | if (node == NULL) |
| 297 | return false; |
| 298 | if (IsA(node, SubLink)) |
| 299 | { |
| 300 | SubLink *sub = (SubLink *) node; |
| 301 | |
| 302 | /* Do what we came for */ |
| 303 | AcquireRewriteLocks((Query *) sub->subselect, |
| 304 | context->for_execute, |
| 305 | false); |
| 306 | /* Fall through to process lefthand args of SubLink */ |
| 307 | } |
| 308 | |
| 309 | /* |
| 310 | * Do NOT recurse into Query nodes, because AcquireRewriteLocks already |
| 311 | * processed subselects of subselects for us. |
| 312 | */ |
| 313 | return expression_tree_walker(node, acquireLocksOnSubLinks, context); |
| 314 | } |
| 315 | |
| 316 | |
| 317 | /* |
| 318 | * rewriteRuleAction - |
| 319 | * Rewrite the rule action with appropriate qualifiers (taken from |
| 320 | * the triggering query). |
| 321 | * |
| 322 | * Input arguments: |
| 323 | * parsetree - original query |
| 324 | * rule_action - one action (query) of a rule |
| 325 | * rule_qual - WHERE condition of rule, or NULL if unconditional |
| 326 | * rt_index - RT index of result relation in original query |
| 327 | * event - type of rule event |
| 328 | * Output arguments: |
| 329 | * *returning_flag - set true if we rewrite RETURNING clause in rule_action |
| 330 | * (must be initialized to false) |
| 331 | * Return value: |
| 332 | * rewritten form of rule_action |
| 333 | */ |
| 334 | static Query * |
| 335 | rewriteRuleAction(Query *parsetree, |
| 336 | Query *rule_action, |
| 337 | Node *rule_qual, |
| 338 | int rt_index, |
| 339 | CmdType event, |
| 340 | bool *returning_flag) |
| 341 | { |
| 342 | int current_varno, |
| 343 | new_varno; |
| 344 | int rt_length; |
| 345 | Query *sub_action; |
| 346 | Query **sub_action_ptr; |
| 347 | acquireLocksOnSubLinks_context context; |
| 348 | |
| 349 | context.for_execute = true; |
| 350 | |
| 351 | /* |
| 352 | * Make modifiable copies of rule action and qual (what we're passed are |
| 353 | * the stored versions in the relcache; don't touch 'em!). |
| 354 | */ |
| 355 | rule_action = copyObject(rule_action); |
| 356 | rule_qual = copyObject(rule_qual); |
| 357 | |
| 358 | /* |
| 359 | * Acquire necessary locks and fix any deleted JOIN RTE entries. |
| 360 | */ |
| 361 | AcquireRewriteLocks(rule_action, true, false); |
| 362 | (void) acquireLocksOnSubLinks(rule_qual, &context); |
| 363 | |
| 364 | current_varno = rt_index; |
| 365 | rt_length = list_length(parsetree->rtable); |
| 366 | new_varno = PRS2_NEW_VARNO + rt_length; |
| 367 | |
| 368 | /* |
| 369 | * Adjust rule action and qual to offset its varnos, so that we can merge |
| 370 | * its rtable with the main parsetree's rtable. |
| 371 | * |
| 372 | * If the rule action is an INSERT...SELECT, the OLD/NEW rtable entries |
| 373 | * will be in the SELECT part, and we have to modify that rather than the |
| 374 | * top-level INSERT (kluge!). |
| 375 | */ |
| 376 | sub_action = getInsertSelectQuery(rule_action, &sub_action_ptr); |
| 377 | |
| 378 | OffsetVarNodes((Node *) sub_action, rt_length, 0); |
| 379 | OffsetVarNodes(rule_qual, rt_length, 0); |
| 380 | /* but references to OLD should point at original rt_index */ |
| 381 | ChangeVarNodes((Node *) sub_action, |
| 382 | PRS2_OLD_VARNO + rt_length, rt_index, 0); |
| 383 | ChangeVarNodes(rule_qual, |
| 384 | PRS2_OLD_VARNO + rt_length, rt_index, 0); |
| 385 | |
| 386 | /* |
| 387 | * Generate expanded rtable consisting of main parsetree's rtable plus |
| 388 | * rule action's rtable; this becomes the complete rtable for the rule |
| 389 | * action. Some of the entries may be unused after we finish rewriting, |
| 390 | * but we leave them all in place for two reasons: |
| 391 | * |
| 392 | * We'd have a much harder job to adjust the query's varnos if we |
| 393 | * selectively removed RT entries. |
| 394 | * |
| 395 | * If the rule is INSTEAD, then the original query won't be executed at |
| 396 | * all, and so its rtable must be preserved so that the executor will do |
| 397 | * the correct permissions checks on it. |
| 398 | * |
| 399 | * RT entries that are not referenced in the completed jointree will be |
| 400 | * ignored by the planner, so they do not affect query semantics. But any |
| 401 | * permissions checks specified in them will be applied during executor |
| 402 | * startup (see ExecCheckRTEPerms()). This allows us to check that the |
| 403 | * caller has, say, insert-permission on a view, when the view is not |
| 404 | * semantically referenced at all in the resulting query. |
| 405 | * |
| 406 | * When a rule is not INSTEAD, the permissions checks done on its copied |
| 407 | * RT entries will be redundant with those done during execution of the |
| 408 | * original query, but we don't bother to treat that case differently. |
| 409 | * |
| 410 | * NOTE: because planner will destructively alter rtable, we must ensure |
| 411 | * that rule action's rtable is separate and shares no substructure with |
| 412 | * the main rtable. Hence do a deep copy here. |
| 413 | */ |
| 414 | sub_action->rtable = list_concat(copyObject(parsetree->rtable), |
| 415 | sub_action->rtable); |
| 416 | |
| 417 | /* |
| 418 | * There could have been some SubLinks in parsetree's rtable, in which |
| 419 | * case we'd better mark the sub_action correctly. |
| 420 | */ |
| 421 | if (parsetree->hasSubLinks && !sub_action->hasSubLinks) |
| 422 | { |
| 423 | ListCell *lc; |
| 424 | |
| 425 | foreach(lc, parsetree->rtable) |
| 426 | { |
| 427 | RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); |
| 428 | |
| 429 | switch (rte->rtekind) |
| 430 | { |
| 431 | case RTE_RELATION: |
| 432 | sub_action->hasSubLinks = |
| 433 | checkExprHasSubLink((Node *) rte->tablesample); |
| 434 | break; |
| 435 | case RTE_FUNCTION: |
| 436 | sub_action->hasSubLinks = |
| 437 | checkExprHasSubLink((Node *) rte->functions); |
| 438 | break; |
| 439 | case RTE_TABLEFUNC: |
| 440 | sub_action->hasSubLinks = |
| 441 | checkExprHasSubLink((Node *) rte->tablefunc); |
| 442 | break; |
| 443 | case RTE_VALUES: |
| 444 | sub_action->hasSubLinks = |
| 445 | checkExprHasSubLink((Node *) rte->values_lists); |
| 446 | break; |
| 447 | default: |
| 448 | /* other RTE types don't contain bare expressions */ |
| 449 | break; |
| 450 | } |
| 451 | if (sub_action->hasSubLinks) |
| 452 | break; /* no need to keep scanning rtable */ |
| 453 | } |
| 454 | } |
| 455 | |
| 456 | /* |
| 457 | * Also, we might have absorbed some RTEs with RLS conditions into the |
| 458 | * sub_action. If so, mark it as hasRowSecurity, whether or not those |
| 459 | * RTEs will be referenced after we finish rewriting. (Note: currently |
| 460 | * this is a no-op because RLS conditions aren't added till later, but it |
| 461 | * seems like good future-proofing to do this anyway.) |
| 462 | */ |
| 463 | sub_action->hasRowSecurity |= parsetree->hasRowSecurity; |
| 464 | |
| 465 | /* |
| 466 | * Each rule action's jointree should be the main parsetree's jointree |
| 467 | * plus that rule's jointree, but usually *without* the original rtindex |
| 468 | * that we're replacing (if present, which it won't be for INSERT). Note |
| 469 | * that if the rule action refers to OLD, its jointree will add a |
| 470 | * reference to rt_index. If the rule action doesn't refer to OLD, but |
| 471 | * either the rule_qual or the user query quals do, then we need to keep |
| 472 | * the original rtindex in the jointree to provide data for the quals. We |
| 473 | * don't want the original rtindex to be joined twice, however, so avoid |
| 474 | * keeping it if the rule action mentions it. |
| 475 | * |
| 476 | * As above, the action's jointree must not share substructure with the |
| 477 | * main parsetree's. |
| 478 | */ |
| 479 | if (sub_action->commandType != CMD_UTILITY) |
| 480 | { |
| 481 | bool keeporig; |
| 482 | List *newjointree; |
| 483 | |
| 484 | Assert(sub_action->jointree != NULL); |
| 485 | keeporig = (!rangeTableEntry_used((Node *) sub_action->jointree, |
| 486 | rt_index, 0)) && |
| 487 | (rangeTableEntry_used(rule_qual, rt_index, 0) || |
| 488 | rangeTableEntry_used(parsetree->jointree->quals, rt_index, 0)); |
| 489 | newjointree = adjustJoinTreeList(parsetree, !keeporig, rt_index); |
| 490 | if (newjointree != NIL) |
| 491 | { |
| 492 | /* |
| 493 | * If sub_action is a setop, manipulating its jointree will do no |
| 494 | * good at all, because the jointree is dummy. (Perhaps someday |
| 495 | * we could push the joining and quals down to the member |
| 496 | * statements of the setop?) |
| 497 | */ |
| 498 | if (sub_action->setOperations != NULL) |
| 499 | ereport(ERROR, |
| 500 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 501 | errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented" ))); |
| 502 | |
| 503 | sub_action->jointree->fromlist = |
| 504 | list_concat(newjointree, sub_action->jointree->fromlist); |
| 505 | |
| 506 | /* |
| 507 | * There could have been some SubLinks in newjointree, in which |
| 508 | * case we'd better mark the sub_action correctly. |
| 509 | */ |
| 510 | if (parsetree->hasSubLinks && !sub_action->hasSubLinks) |
| 511 | sub_action->hasSubLinks = |
| 512 | checkExprHasSubLink((Node *) newjointree); |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | /* |
| 517 | * If the original query has any CTEs, copy them into the rule action. But |
| 518 | * we don't need them for a utility action. |
| 519 | */ |
| 520 | if (parsetree->cteList != NIL && sub_action->commandType != CMD_UTILITY) |
| 521 | { |
| 522 | ListCell *lc; |
| 523 | |
| 524 | /* |
| 525 | * Annoying implementation restriction: because CTEs are identified by |
| 526 | * name within a cteList, we can't merge a CTE from the original query |
| 527 | * if it has the same name as any CTE in the rule action. |
| 528 | * |
| 529 | * This could possibly be fixed by using some sort of internally |
| 530 | * generated ID, instead of names, to link CTE RTEs to their CTEs. |
| 531 | */ |
| 532 | foreach(lc, parsetree->cteList) |
| 533 | { |
| 534 | CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc); |
| 535 | ListCell *lc2; |
| 536 | |
| 537 | foreach(lc2, sub_action->cteList) |
| 538 | { |
| 539 | CommonTableExpr *cte2 = (CommonTableExpr *) lfirst(lc2); |
| 540 | |
| 541 | if (strcmp(cte->ctename, cte2->ctename) == 0) |
| 542 | ereport(ERROR, |
| 543 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 544 | errmsg("WITH query name \"%s\" appears in both a rule action and the query being rewritten" , |
| 545 | cte->ctename))); |
| 546 | } |
| 547 | } |
| 548 | |
| 549 | /* OK, it's safe to combine the CTE lists */ |
| 550 | sub_action->cteList = list_concat(sub_action->cteList, |
| 551 | copyObject(parsetree->cteList)); |
| 552 | } |
| 553 | |
| 554 | /* |
| 555 | * Event Qualification forces copying of parsetree and splitting into two |
| 556 | * queries one w/rule_qual, one w/NOT rule_qual. Also add user query qual |
| 557 | * onto rule action |
| 558 | */ |
| 559 | AddQual(sub_action, rule_qual); |
| 560 | |
| 561 | AddQual(sub_action, parsetree->jointree->quals); |
| 562 | |
| 563 | /* |
| 564 | * Rewrite new.attribute with right hand side of target-list entry for |
| 565 | * appropriate field name in insert/update. |
| 566 | * |
| 567 | * KLUGE ALERT: since ReplaceVarsFromTargetList returns a mutated copy, we |
| 568 | * can't just apply it to sub_action; we have to remember to update the |
| 569 | * sublink inside rule_action, too. |
| 570 | */ |
| 571 | if ((event == CMD_INSERT || event == CMD_UPDATE) && |
| 572 | sub_action->commandType != CMD_UTILITY) |
| 573 | { |
| 574 | sub_action = (Query *) |
| 575 | ReplaceVarsFromTargetList((Node *) sub_action, |
| 576 | new_varno, |
| 577 | 0, |
| 578 | rt_fetch(new_varno, sub_action->rtable), |
| 579 | parsetree->targetList, |
| 580 | (event == CMD_UPDATE) ? |
| 581 | REPLACEVARS_CHANGE_VARNO : |
| 582 | REPLACEVARS_SUBSTITUTE_NULL, |
| 583 | current_varno, |
| 584 | NULL); |
| 585 | if (sub_action_ptr) |
| 586 | *sub_action_ptr = sub_action; |
| 587 | else |
| 588 | rule_action = sub_action; |
| 589 | } |
| 590 | |
| 591 | /* |
| 592 | * If rule_action has a RETURNING clause, then either throw it away if the |
| 593 | * triggering query has no RETURNING clause, or rewrite it to emit what |
| 594 | * the triggering query's RETURNING clause asks for. Throw an error if |
| 595 | * more than one rule has a RETURNING clause. |
| 596 | */ |
| 597 | if (!parsetree->returningList) |
| 598 | rule_action->returningList = NIL; |
| 599 | else if (rule_action->returningList) |
| 600 | { |
| 601 | if (*returning_flag) |
| 602 | ereport(ERROR, |
| 603 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 604 | errmsg("cannot have RETURNING lists in multiple rules" ))); |
| 605 | *returning_flag = true; |
| 606 | rule_action->returningList = (List *) |
| 607 | ReplaceVarsFromTargetList((Node *) parsetree->returningList, |
| 608 | parsetree->resultRelation, |
| 609 | 0, |
| 610 | rt_fetch(parsetree->resultRelation, |
| 611 | parsetree->rtable), |
| 612 | rule_action->returningList, |
| 613 | REPLACEVARS_REPORT_ERROR, |
| 614 | 0, |
| 615 | &rule_action->hasSubLinks); |
| 616 | |
| 617 | /* |
| 618 | * There could have been some SubLinks in parsetree's returningList, |
| 619 | * in which case we'd better mark the rule_action correctly. |
| 620 | */ |
| 621 | if (parsetree->hasSubLinks && !rule_action->hasSubLinks) |
| 622 | rule_action->hasSubLinks = |
| 623 | checkExprHasSubLink((Node *) rule_action->returningList); |
| 624 | } |
| 625 | |
| 626 | return rule_action; |
| 627 | } |
| 628 | |
| 629 | /* |
| 630 | * Copy the query's jointree list, and optionally attempt to remove any |
| 631 | * occurrence of the given rt_index as a top-level join item (we do not look |
| 632 | * for it within join items; this is OK because we are only expecting to find |
| 633 | * it as an UPDATE or DELETE target relation, which will be at the top level |
| 634 | * of the join). Returns modified jointree list --- this is a separate copy |
| 635 | * sharing no nodes with the original. |
| 636 | */ |
| 637 | static List * |
| 638 | adjustJoinTreeList(Query *parsetree, bool removert, int rt_index) |
| 639 | { |
| 640 | List *newjointree = copyObject(parsetree->jointree->fromlist); |
| 641 | ListCell *l; |
| 642 | |
| 643 | if (removert) |
| 644 | { |
| 645 | foreach(l, newjointree) |
| 646 | { |
| 647 | RangeTblRef *rtr = lfirst(l); |
| 648 | |
| 649 | if (IsA(rtr, RangeTblRef) && |
| 650 | rtr->rtindex == rt_index) |
| 651 | { |
| 652 | newjointree = list_delete_ptr(newjointree, rtr); |
| 653 | |
| 654 | /* |
| 655 | * foreach is safe because we exit loop after list_delete... |
| 656 | */ |
| 657 | break; |
| 658 | } |
| 659 | } |
| 660 | } |
| 661 | return newjointree; |
| 662 | } |
| 663 | |
| 664 | |
| 665 | /* |
| 666 | * rewriteTargetListIU - rewrite INSERT/UPDATE targetlist into standard form |
| 667 | * |
| 668 | * This has the following responsibilities: |
| 669 | * |
| 670 | * 1. For an INSERT, add tlist entries to compute default values for any |
| 671 | * attributes that have defaults and are not assigned to in the given tlist. |
| 672 | * (We do not insert anything for default-less attributes, however. The |
| 673 | * planner will later insert NULLs for them, but there's no reason to slow |
| 674 | * down rewriter processing with extra tlist nodes.) Also, for both INSERT |
| 675 | * and UPDATE, replace explicit DEFAULT specifications with column default |
| 676 | * expressions. |
| 677 | * |
| 678 | * 2. For an UPDATE on a trigger-updatable view, add tlist entries for any |
| 679 | * unassigned-to attributes, assigning them their old values. These will |
| 680 | * later get expanded to the output values of the view. (This is equivalent |
| 681 | * to what the planner's expand_targetlist() will do for UPDATE on a regular |
| 682 | * table, but it's more convenient to do it here while we still have easy |
| 683 | * access to the view's original RT index.) This is only necessary for |
| 684 | * trigger-updatable views, for which the view remains the result relation of |
| 685 | * the query. For auto-updatable views we must not do this, since it might |
| 686 | * add assignments to non-updatable view columns. For rule-updatable views it |
| 687 | * is unnecessary extra work, since the query will be rewritten with a |
| 688 | * different result relation which will be processed when we recurse via |
| 689 | * RewriteQuery. |
| 690 | * |
| 691 | * 3. Merge multiple entries for the same target attribute, or declare error |
| 692 | * if we can't. Multiple entries are only allowed for INSERT/UPDATE of |
| 693 | * portions of an array or record field, for example |
| 694 | * UPDATE table SET foo[2] = 42, foo[4] = 43; |
| 695 | * We can merge such operations into a single assignment op. Essentially, |
| 696 | * the expression we want to produce in this case is like |
| 697 | * foo = array_set_element(array_set_element(foo, 2, 42), 4, 43) |
| 698 | * |
| 699 | * 4. Sort the tlist into standard order: non-junk fields in order by resno, |
| 700 | * then junk fields (these in no particular order). |
| 701 | * |
| 702 | * We must do items 1,2,3 before firing rewrite rules, else rewritten |
| 703 | * references to NEW.foo will produce wrong or incomplete results. Item 4 |
| 704 | * is not needed for rewriting, but will be needed by the planner, and we |
| 705 | * can do it essentially for free while handling the other items. |
| 706 | * |
| 707 | * Note that for an inheritable UPDATE, this processing is only done once, |
| 708 | * using the parent relation as reference. It must not do anything that |
| 709 | * will not be correct when transposed to the child relation(s). (Step 4 |
| 710 | * is incorrect by this light, since child relations might have different |
| 711 | * column ordering, but the planner will fix things by re-sorting the tlist |
| 712 | * for each child.) |
| 713 | */ |
| 714 | static List * |
| 715 | rewriteTargetListIU(List *targetList, |
| 716 | CmdType commandType, |
| 717 | OverridingKind override, |
| 718 | Relation target_relation, |
| 719 | int result_rti) |
| 720 | { |
| 721 | TargetEntry **new_tles; |
| 722 | List *new_tlist = NIL; |
| 723 | List *junk_tlist = NIL; |
| 724 | Form_pg_attribute att_tup; |
| 725 | int attrno, |
| 726 | next_junk_attrno, |
| 727 | numattrs; |
| 728 | ListCell *temp; |
| 729 | |
| 730 | /* |
| 731 | * We process the normal (non-junk) attributes by scanning the input tlist |
| 732 | * once and transferring TLEs into an array, then scanning the array to |
| 733 | * build an output tlist. This avoids O(N^2) behavior for large numbers |
| 734 | * of attributes. |
| 735 | * |
| 736 | * Junk attributes are tossed into a separate list during the same tlist |
| 737 | * scan, then appended to the reconstructed tlist. |
| 738 | */ |
| 739 | numattrs = RelationGetNumberOfAttributes(target_relation); |
| 740 | new_tles = (TargetEntry **) palloc0(numattrs * sizeof(TargetEntry *)); |
| 741 | next_junk_attrno = numattrs + 1; |
| 742 | |
| 743 | foreach(temp, targetList) |
| 744 | { |
| 745 | TargetEntry *old_tle = (TargetEntry *) lfirst(temp); |
| 746 | |
| 747 | if (!old_tle->resjunk) |
| 748 | { |
| 749 | /* Normal attr: stash it into new_tles[] */ |
| 750 | attrno = old_tle->resno; |
| 751 | if (attrno < 1 || attrno > numattrs) |
| 752 | elog(ERROR, "bogus resno %d in targetlist" , attrno); |
| 753 | att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1); |
| 754 | |
| 755 | /* We can (and must) ignore deleted attributes */ |
| 756 | if (att_tup->attisdropped) |
| 757 | continue; |
| 758 | |
| 759 | /* Merge with any prior assignment to same attribute */ |
| 760 | new_tles[attrno - 1] = |
| 761 | process_matched_tle(old_tle, |
| 762 | new_tles[attrno - 1], |
| 763 | NameStr(att_tup->attname)); |
| 764 | } |
| 765 | else |
| 766 | { |
| 767 | /* |
| 768 | * Copy all resjunk tlist entries to junk_tlist, and assign them |
| 769 | * resnos above the last real resno. |
| 770 | * |
| 771 | * Typical junk entries include ORDER BY or GROUP BY expressions |
| 772 | * (are these actually possible in an INSERT or UPDATE?), system |
| 773 | * attribute references, etc. |
| 774 | */ |
| 775 | |
| 776 | /* Get the resno right, but don't copy unnecessarily */ |
| 777 | if (old_tle->resno != next_junk_attrno) |
| 778 | { |
| 779 | old_tle = flatCopyTargetEntry(old_tle); |
| 780 | old_tle->resno = next_junk_attrno; |
| 781 | } |
| 782 | junk_tlist = lappend(junk_tlist, old_tle); |
| 783 | next_junk_attrno++; |
| 784 | } |
| 785 | } |
| 786 | |
| 787 | for (attrno = 1; attrno <= numattrs; attrno++) |
| 788 | { |
| 789 | TargetEntry *new_tle = new_tles[attrno - 1]; |
| 790 | bool apply_default; |
| 791 | |
| 792 | att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1); |
| 793 | |
| 794 | /* We can (and must) ignore deleted attributes */ |
| 795 | if (att_tup->attisdropped) |
| 796 | continue; |
| 797 | |
| 798 | /* |
| 799 | * Handle the two cases where we need to insert a default expression: |
| 800 | * it's an INSERT and there's no tlist entry for the column, or the |
| 801 | * tlist entry is a DEFAULT placeholder node. |
| 802 | */ |
| 803 | apply_default = ((new_tle == NULL && commandType == CMD_INSERT) || |
| 804 | (new_tle && new_tle->expr && IsA(new_tle->expr, SetToDefault))); |
| 805 | |
| 806 | if (commandType == CMD_INSERT) |
| 807 | { |
| 808 | if (att_tup->attidentity == ATTRIBUTE_IDENTITY_ALWAYS && !apply_default) |
| 809 | { |
| 810 | if (override != OVERRIDING_SYSTEM_VALUE) |
| 811 | ereport(ERROR, |
| 812 | (errcode(ERRCODE_GENERATED_ALWAYS), |
| 813 | errmsg("cannot insert into column \"%s\"" , NameStr(att_tup->attname)), |
| 814 | errdetail("Column \"%s\" is an identity column defined as GENERATED ALWAYS." , |
| 815 | NameStr(att_tup->attname)), |
| 816 | errhint("Use OVERRIDING SYSTEM VALUE to override." ))); |
| 817 | } |
| 818 | |
| 819 | if (att_tup->attidentity == ATTRIBUTE_IDENTITY_BY_DEFAULT && override == OVERRIDING_USER_VALUE) |
| 820 | apply_default = true; |
| 821 | |
| 822 | if (att_tup->attgenerated && !apply_default) |
| 823 | ereport(ERROR, |
| 824 | (errcode(ERRCODE_SYNTAX_ERROR), |
| 825 | errmsg("cannot insert into column \"%s\"" , NameStr(att_tup->attname)), |
| 826 | errdetail("Column \"%s\" is a generated column." , |
| 827 | NameStr(att_tup->attname)))); |
| 828 | } |
| 829 | |
| 830 | if (commandType == CMD_UPDATE) |
| 831 | { |
| 832 | if (att_tup->attidentity == ATTRIBUTE_IDENTITY_ALWAYS && new_tle && !apply_default) |
| 833 | ereport(ERROR, |
| 834 | (errcode(ERRCODE_GENERATED_ALWAYS), |
| 835 | errmsg("column \"%s\" can only be updated to DEFAULT" , NameStr(att_tup->attname)), |
| 836 | errdetail("Column \"%s\" is an identity column defined as GENERATED ALWAYS." , |
| 837 | NameStr(att_tup->attname)))); |
| 838 | |
| 839 | if (att_tup->attgenerated && new_tle && !apply_default) |
| 840 | ereport(ERROR, |
| 841 | (errcode(ERRCODE_SYNTAX_ERROR), |
| 842 | errmsg("column \"%s\" can only be updated to DEFAULT" , NameStr(att_tup->attname)), |
| 843 | errdetail("Column \"%s\" is a generated column." , |
| 844 | NameStr(att_tup->attname)))); |
| 845 | } |
| 846 | |
| 847 | if (att_tup->attgenerated) |
| 848 | { |
| 849 | /* |
| 850 | * stored generated column will be fixed in executor |
| 851 | */ |
| 852 | new_tle = NULL; |
| 853 | } |
| 854 | else if (apply_default) |
| 855 | { |
| 856 | Node *new_expr; |
| 857 | |
| 858 | new_expr = build_column_default(target_relation, attrno); |
| 859 | |
| 860 | /* |
| 861 | * If there is no default (ie, default is effectively NULL), we |
| 862 | * can omit the tlist entry in the INSERT case, since the planner |
| 863 | * can insert a NULL for itself, and there's no point in spending |
| 864 | * any more rewriter cycles on the entry. But in the UPDATE case |
| 865 | * we've got to explicitly set the column to NULL. |
| 866 | */ |
| 867 | if (!new_expr) |
| 868 | { |
| 869 | if (commandType == CMD_INSERT) |
| 870 | new_tle = NULL; |
| 871 | else |
| 872 | { |
| 873 | new_expr = (Node *) makeConst(att_tup->atttypid, |
| 874 | -1, |
| 875 | att_tup->attcollation, |
| 876 | att_tup->attlen, |
| 877 | (Datum) 0, |
| 878 | true, /* isnull */ |
| 879 | att_tup->attbyval); |
| 880 | /* this is to catch a NOT NULL domain constraint */ |
| 881 | new_expr = coerce_to_domain(new_expr, |
| 882 | InvalidOid, -1, |
| 883 | att_tup->atttypid, |
| 884 | COERCION_IMPLICIT, |
| 885 | COERCE_IMPLICIT_CAST, |
| 886 | -1, |
| 887 | false); |
| 888 | } |
| 889 | } |
| 890 | |
| 891 | if (new_expr) |
| 892 | new_tle = makeTargetEntry((Expr *) new_expr, |
| 893 | attrno, |
| 894 | pstrdup(NameStr(att_tup->attname)), |
| 895 | false); |
| 896 | } |
| 897 | |
| 898 | /* |
| 899 | * For an UPDATE on a trigger-updatable view, provide a dummy entry |
| 900 | * whenever there is no explicit assignment. |
| 901 | */ |
| 902 | if (new_tle == NULL && commandType == CMD_UPDATE && |
| 903 | target_relation->rd_rel->relkind == RELKIND_VIEW && |
| 904 | view_has_instead_trigger(target_relation, CMD_UPDATE)) |
| 905 | { |
| 906 | Node *new_expr; |
| 907 | |
| 908 | new_expr = (Node *) makeVar(result_rti, |
| 909 | attrno, |
| 910 | att_tup->atttypid, |
| 911 | att_tup->atttypmod, |
| 912 | att_tup->attcollation, |
| 913 | 0); |
| 914 | |
| 915 | new_tle = makeTargetEntry((Expr *) new_expr, |
| 916 | attrno, |
| 917 | pstrdup(NameStr(att_tup->attname)), |
| 918 | false); |
| 919 | } |
| 920 | |
| 921 | if (new_tle) |
| 922 | new_tlist = lappend(new_tlist, new_tle); |
| 923 | } |
| 924 | |
| 925 | pfree(new_tles); |
| 926 | |
| 927 | return list_concat(new_tlist, junk_tlist); |
| 928 | } |
| 929 | |
| 930 | |
| 931 | /* |
| 932 | * Convert a matched TLE from the original tlist into a correct new TLE. |
| 933 | * |
| 934 | * This routine detects and handles multiple assignments to the same target |
| 935 | * attribute. (The attribute name is needed only for error messages.) |
| 936 | */ |
| 937 | static TargetEntry * |
| 938 | process_matched_tle(TargetEntry *src_tle, |
| 939 | TargetEntry *prior_tle, |
| 940 | const char *attrName) |
| 941 | { |
| 942 | TargetEntry *result; |
| 943 | CoerceToDomain *coerce_expr = NULL; |
| 944 | Node *src_expr; |
| 945 | Node *prior_expr; |
| 946 | Node *src_input; |
| 947 | Node *prior_input; |
| 948 | Node *priorbottom; |
| 949 | Node *newexpr; |
| 950 | |
| 951 | if (prior_tle == NULL) |
| 952 | { |
| 953 | /* |
| 954 | * Normal case where this is the first assignment to the attribute. |
| 955 | */ |
| 956 | return src_tle; |
| 957 | } |
| 958 | |
| 959 | /*---------- |
| 960 | * Multiple assignments to same attribute. Allow only if all are |
| 961 | * FieldStore or SubscriptingRef assignment operations. This is a bit |
| 962 | * tricky because what we may actually be looking at is a nest of |
| 963 | * such nodes; consider |
| 964 | * UPDATE tab SET col.fld1.subfld1 = x, col.fld2.subfld2 = y |
| 965 | * The two expressions produced by the parser will look like |
| 966 | * FieldStore(col, fld1, FieldStore(placeholder, subfld1, x)) |
| 967 | * FieldStore(col, fld2, FieldStore(placeholder, subfld2, y)) |
| 968 | * However, we can ignore the substructure and just consider the top |
| 969 | * FieldStore or SubscriptingRef from each assignment, because it works to |
| 970 | * combine these as |
| 971 | * FieldStore(FieldStore(col, fld1, |
| 972 | * FieldStore(placeholder, subfld1, x)), |
| 973 | * fld2, FieldStore(placeholder, subfld2, y)) |
| 974 | * Note the leftmost expression goes on the inside so that the |
| 975 | * assignments appear to occur left-to-right. |
| 976 | * |
| 977 | * For FieldStore, instead of nesting we can generate a single |
| 978 | * FieldStore with multiple target fields. We must nest when |
| 979 | * SubscriptingRefs are involved though. |
| 980 | * |
| 981 | * As a further complication, the destination column might be a domain, |
| 982 | * resulting in each assignment containing a CoerceToDomain node over a |
| 983 | * FieldStore or SubscriptingRef. These should have matching target |
| 984 | * domains, so we strip them and reconstitute a single CoerceToDomain over |
| 985 | * the combined FieldStore/SubscriptingRef nodes. (Notice that this has the |
| 986 | * result that the domain's checks are applied only after we do all the |
| 987 | * field or element updates, not after each one. This is arguably desirable.) |
| 988 | *---------- |
| 989 | */ |
| 990 | src_expr = (Node *) src_tle->expr; |
| 991 | prior_expr = (Node *) prior_tle->expr; |
| 992 | |
| 993 | if (src_expr && IsA(src_expr, CoerceToDomain) && |
| 994 | prior_expr && IsA(prior_expr, CoerceToDomain) && |
| 995 | ((CoerceToDomain *) src_expr)->resulttype == |
| 996 | ((CoerceToDomain *) prior_expr)->resulttype) |
| 997 | { |
| 998 | /* we assume without checking that resulttypmod/resultcollid match */ |
| 999 | coerce_expr = (CoerceToDomain *) src_expr; |
| 1000 | src_expr = (Node *) ((CoerceToDomain *) src_expr)->arg; |
| 1001 | prior_expr = (Node *) ((CoerceToDomain *) prior_expr)->arg; |
| 1002 | } |
| 1003 | |
| 1004 | src_input = get_assignment_input(src_expr); |
| 1005 | prior_input = get_assignment_input(prior_expr); |
| 1006 | if (src_input == NULL || |
| 1007 | prior_input == NULL || |
| 1008 | exprType(src_expr) != exprType(prior_expr)) |
| 1009 | ereport(ERROR, |
| 1010 | (errcode(ERRCODE_SYNTAX_ERROR), |
| 1011 | errmsg("multiple assignments to same column \"%s\"" , |
| 1012 | attrName))); |
| 1013 | |
| 1014 | /* |
| 1015 | * Prior TLE could be a nest of assignments if we do this more than once. |
| 1016 | */ |
| 1017 | priorbottom = prior_input; |
| 1018 | for (;;) |
| 1019 | { |
| 1020 | Node *newbottom = get_assignment_input(priorbottom); |
| 1021 | |
| 1022 | if (newbottom == NULL) |
| 1023 | break; /* found the original Var reference */ |
| 1024 | priorbottom = newbottom; |
| 1025 | } |
| 1026 | if (!equal(priorbottom, src_input)) |
| 1027 | ereport(ERROR, |
| 1028 | (errcode(ERRCODE_SYNTAX_ERROR), |
| 1029 | errmsg("multiple assignments to same column \"%s\"" , |
| 1030 | attrName))); |
| 1031 | |
| 1032 | /* |
| 1033 | * Looks OK to nest 'em. |
| 1034 | */ |
| 1035 | if (IsA(src_expr, FieldStore)) |
| 1036 | { |
| 1037 | FieldStore *fstore = makeNode(FieldStore); |
| 1038 | |
| 1039 | if (IsA(prior_expr, FieldStore)) |
| 1040 | { |
| 1041 | /* combine the two */ |
| 1042 | memcpy(fstore, prior_expr, sizeof(FieldStore)); |
| 1043 | fstore->newvals = |
| 1044 | list_concat(list_copy(((FieldStore *) prior_expr)->newvals), |
| 1045 | list_copy(((FieldStore *) src_expr)->newvals)); |
| 1046 | fstore->fieldnums = |
| 1047 | list_concat(list_copy(((FieldStore *) prior_expr)->fieldnums), |
| 1048 | list_copy(((FieldStore *) src_expr)->fieldnums)); |
| 1049 | } |
| 1050 | else |
| 1051 | { |
| 1052 | /* general case, just nest 'em */ |
| 1053 | memcpy(fstore, src_expr, sizeof(FieldStore)); |
| 1054 | fstore->arg = (Expr *) prior_expr; |
| 1055 | } |
| 1056 | newexpr = (Node *) fstore; |
| 1057 | } |
| 1058 | else if (IsA(src_expr, SubscriptingRef)) |
| 1059 | { |
| 1060 | SubscriptingRef *sbsref = makeNode(SubscriptingRef); |
| 1061 | |
| 1062 | memcpy(sbsref, src_expr, sizeof(SubscriptingRef)); |
| 1063 | sbsref->refexpr = (Expr *) prior_expr; |
| 1064 | newexpr = (Node *) sbsref; |
| 1065 | } |
| 1066 | else |
| 1067 | { |
| 1068 | elog(ERROR, "cannot happen" ); |
| 1069 | newexpr = NULL; |
| 1070 | } |
| 1071 | |
| 1072 | if (coerce_expr) |
| 1073 | { |
| 1074 | /* put back the CoerceToDomain */ |
| 1075 | CoerceToDomain *newcoerce = makeNode(CoerceToDomain); |
| 1076 | |
| 1077 | memcpy(newcoerce, coerce_expr, sizeof(CoerceToDomain)); |
| 1078 | newcoerce->arg = (Expr *) newexpr; |
| 1079 | newexpr = (Node *) newcoerce; |
| 1080 | } |
| 1081 | |
| 1082 | result = flatCopyTargetEntry(src_tle); |
| 1083 | result->expr = (Expr *) newexpr; |
| 1084 | return result; |
| 1085 | } |
| 1086 | |
| 1087 | /* |
| 1088 | * If node is an assignment node, return its input; else return NULL |
| 1089 | */ |
| 1090 | static Node * |
| 1091 | get_assignment_input(Node *node) |
| 1092 | { |
| 1093 | if (node == NULL) |
| 1094 | return NULL; |
| 1095 | if (IsA(node, FieldStore)) |
| 1096 | { |
| 1097 | FieldStore *fstore = (FieldStore *) node; |
| 1098 | |
| 1099 | return (Node *) fstore->arg; |
| 1100 | } |
| 1101 | else if (IsA(node, SubscriptingRef)) |
| 1102 | { |
| 1103 | SubscriptingRef *sbsref = (SubscriptingRef *) node; |
| 1104 | |
| 1105 | if (sbsref->refassgnexpr == NULL) |
| 1106 | return NULL; |
| 1107 | |
| 1108 | return (Node *) sbsref->refexpr; |
| 1109 | } |
| 1110 | |
| 1111 | return NULL; |
| 1112 | } |
| 1113 | |
| 1114 | /* |
| 1115 | * Make an expression tree for the default value for a column. |
| 1116 | * |
| 1117 | * If there is no default, return a NULL instead. |
| 1118 | */ |
| 1119 | Node * |
| 1120 | build_column_default(Relation rel, int attrno) |
| 1121 | { |
| 1122 | TupleDesc rd_att = rel->rd_att; |
| 1123 | Form_pg_attribute att_tup = TupleDescAttr(rd_att, attrno - 1); |
| 1124 | Oid atttype = att_tup->atttypid; |
| 1125 | int32 atttypmod = att_tup->atttypmod; |
| 1126 | Node *expr = NULL; |
| 1127 | Oid exprtype; |
| 1128 | |
| 1129 | if (att_tup->attidentity) |
| 1130 | { |
| 1131 | NextValueExpr *nve = makeNode(NextValueExpr); |
| 1132 | |
| 1133 | nve->seqid = getOwnedSequence(RelationGetRelid(rel), attrno); |
| 1134 | nve->typeId = att_tup->atttypid; |
| 1135 | |
| 1136 | return (Node *) nve; |
| 1137 | } |
| 1138 | |
| 1139 | /* |
| 1140 | * Scan to see if relation has a default for this column. |
| 1141 | */ |
| 1142 | if (att_tup->atthasdef && rd_att->constr && |
| 1143 | rd_att->constr->num_defval > 0) |
| 1144 | { |
| 1145 | AttrDefault *defval = rd_att->constr->defval; |
| 1146 | int ndef = rd_att->constr->num_defval; |
| 1147 | |
| 1148 | while (--ndef >= 0) |
| 1149 | { |
| 1150 | if (attrno == defval[ndef].adnum) |
| 1151 | { |
| 1152 | /* |
| 1153 | * Found it, convert string representation to node tree. |
| 1154 | */ |
| 1155 | expr = stringToNode(defval[ndef].adbin); |
| 1156 | break; |
| 1157 | } |
| 1158 | } |
| 1159 | } |
| 1160 | |
| 1161 | /* |
| 1162 | * No per-column default, so look for a default for the type itself. But |
| 1163 | * not for generated columns. |
| 1164 | */ |
| 1165 | if (expr == NULL && !att_tup->attgenerated) |
| 1166 | expr = get_typdefault(atttype); |
| 1167 | |
| 1168 | if (expr == NULL) |
| 1169 | return NULL; /* No default anywhere */ |
| 1170 | |
| 1171 | /* |
| 1172 | * Make sure the value is coerced to the target column type; this will |
| 1173 | * generally be true already, but there seem to be some corner cases |
| 1174 | * involving domain defaults where it might not be true. This should match |
| 1175 | * the parser's processing of non-defaulted expressions --- see |
| 1176 | * transformAssignedExpr(). |
| 1177 | */ |
| 1178 | exprtype = exprType(expr); |
| 1179 | |
| 1180 | expr = coerce_to_target_type(NULL, /* no UNKNOWN params here */ |
| 1181 | expr, exprtype, |
| 1182 | atttype, atttypmod, |
| 1183 | COERCION_ASSIGNMENT, |
| 1184 | COERCE_IMPLICIT_CAST, |
| 1185 | -1); |
| 1186 | if (expr == NULL) |
| 1187 | ereport(ERROR, |
| 1188 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
| 1189 | errmsg("column \"%s\" is of type %s" |
| 1190 | " but default expression is of type %s" , |
| 1191 | NameStr(att_tup->attname), |
| 1192 | format_type_be(atttype), |
| 1193 | format_type_be(exprtype)), |
| 1194 | errhint("You will need to rewrite or cast the expression." ))); |
| 1195 | |
| 1196 | return expr; |
| 1197 | } |
| 1198 | |
| 1199 | |
| 1200 | /* Does VALUES RTE contain any SetToDefault items? */ |
| 1201 | static bool |
| 1202 | searchForDefault(RangeTblEntry *rte) |
| 1203 | { |
| 1204 | ListCell *lc; |
| 1205 | |
| 1206 | foreach(lc, rte->values_lists) |
| 1207 | { |
| 1208 | List *sublist = (List *) lfirst(lc); |
| 1209 | ListCell *lc2; |
| 1210 | |
| 1211 | foreach(lc2, sublist) |
| 1212 | { |
| 1213 | Node *col = (Node *) lfirst(lc2); |
| 1214 | |
| 1215 | if (IsA(col, SetToDefault)) |
| 1216 | return true; |
| 1217 | } |
| 1218 | } |
| 1219 | return false; |
| 1220 | } |
| 1221 | |
| 1222 | /* |
| 1223 | * When processing INSERT ... VALUES with a VALUES RTE (ie, multiple VALUES |
| 1224 | * lists), we have to replace any DEFAULT items in the VALUES lists with |
| 1225 | * the appropriate default expressions. The other aspects of targetlist |
| 1226 | * rewriting need be applied only to the query's targetlist proper. |
| 1227 | * |
| 1228 | * For an auto-updatable view, each DEFAULT item in the VALUES list is |
| 1229 | * replaced with the default from the view, if it has one. Otherwise it is |
| 1230 | * left untouched so that the underlying base relation's default can be |
| 1231 | * applied instead (when we later recurse to here after rewriting the query |
| 1232 | * to refer to the base relation instead of the view). |
| 1233 | * |
| 1234 | * For other types of relation, including rule- and trigger-updatable views, |
| 1235 | * all DEFAULT items are replaced, and if the target relation doesn't have a |
| 1236 | * default, the value is explicitly set to NULL. |
| 1237 | * |
| 1238 | * Additionally, if force_nulls is true, the target relation's defaults are |
| 1239 | * ignored and all DEFAULT items in the VALUES list are explicitly set to |
| 1240 | * NULL, regardless of the target relation's type. This is used for the |
| 1241 | * product queries generated by DO ALSO rules attached to an auto-updatable |
| 1242 | * view, for which we will have already called this function with force_nulls |
| 1243 | * false. For these product queries, we must then force any remaining DEFAULT |
| 1244 | * items to NULL to provide concrete values for the rule actions. |
| 1245 | * Essentially, this is a mix of the 2 cases above --- the original query is |
| 1246 | * an insert into an auto-updatable view, and the product queries are inserts |
| 1247 | * into a rule-updatable view. |
| 1248 | * |
| 1249 | * Note that we may have subscripted or field assignment targetlist entries, |
| 1250 | * as well as more complex expressions from already-replaced DEFAULT items if |
| 1251 | * we have recursed to here for an auto-updatable view. However, it ought to |
| 1252 | * be impossible for such entries to have DEFAULTs assigned to them --- we |
| 1253 | * should only have to replace DEFAULT items for targetlist entries that |
| 1254 | * contain simple Vars referencing the VALUES RTE. |
| 1255 | * |
| 1256 | * Returns true if all DEFAULT items were replaced, and false if some were |
| 1257 | * left untouched. |
| 1258 | */ |
| 1259 | static bool |
| 1260 | rewriteValuesRTE(Query *parsetree, RangeTblEntry *rte, int rti, |
| 1261 | Relation target_relation, bool force_nulls) |
| 1262 | { |
| 1263 | List *newValues; |
| 1264 | ListCell *lc; |
| 1265 | bool isAutoUpdatableView; |
| 1266 | bool allReplaced; |
| 1267 | int numattrs; |
| 1268 | int *attrnos; |
| 1269 | |
| 1270 | /* |
| 1271 | * Rebuilding all the lists is a pretty expensive proposition in a big |
| 1272 | * VALUES list, and it's a waste of time if there aren't any DEFAULT |
| 1273 | * placeholders. So first scan to see if there are any. |
| 1274 | * |
| 1275 | * We skip this check if force_nulls is true, because we know that there |
| 1276 | * are DEFAULT items present in that case. |
| 1277 | */ |
| 1278 | if (!force_nulls && !searchForDefault(rte)) |
| 1279 | return true; /* nothing to do */ |
| 1280 | |
| 1281 | /* |
| 1282 | * Scan the targetlist for entries referring to the VALUES RTE, and note |
| 1283 | * the target attributes. As noted above, we should only need to do this |
| 1284 | * for targetlist entries containing simple Vars --- nothing else in the |
| 1285 | * VALUES RTE should contain DEFAULT items, and we complain if such a |
| 1286 | * thing does occur. |
| 1287 | */ |
| 1288 | numattrs = list_length(linitial(rte->values_lists)); |
| 1289 | attrnos = (int *) palloc0(numattrs * sizeof(int)); |
| 1290 | |
| 1291 | foreach(lc, parsetree->targetList) |
| 1292 | { |
| 1293 | TargetEntry *tle = (TargetEntry *) lfirst(lc); |
| 1294 | |
| 1295 | if (IsA(tle->expr, Var)) |
| 1296 | { |
| 1297 | Var *var = (Var *) tle->expr; |
| 1298 | |
| 1299 | if (var->varno == rti) |
| 1300 | { |
| 1301 | int attrno = var->varattno; |
| 1302 | |
| 1303 | Assert(attrno >= 1 && attrno <= numattrs); |
| 1304 | attrnos[attrno - 1] = tle->resno; |
| 1305 | } |
| 1306 | } |
| 1307 | } |
| 1308 | |
| 1309 | /* |
| 1310 | * Check if the target relation is an auto-updatable view, in which case |
| 1311 | * unresolved defaults will be left untouched rather than being set to |
| 1312 | * NULL. If force_nulls is true, we always set DEFAULT items to NULL, so |
| 1313 | * skip this check in that case --- it isn't an auto-updatable view. |
| 1314 | */ |
| 1315 | isAutoUpdatableView = false; |
| 1316 | if (!force_nulls && |
| 1317 | target_relation->rd_rel->relkind == RELKIND_VIEW && |
| 1318 | !view_has_instead_trigger(target_relation, CMD_INSERT)) |
| 1319 | { |
| 1320 | List *locks; |
| 1321 | bool hasUpdate; |
| 1322 | bool found; |
| 1323 | ListCell *l; |
| 1324 | |
| 1325 | /* Look for an unconditional DO INSTEAD rule */ |
| 1326 | locks = matchLocks(CMD_INSERT, target_relation->rd_rules, |
| 1327 | parsetree->resultRelation, parsetree, &hasUpdate); |
| 1328 | |
| 1329 | found = false; |
| 1330 | foreach(l, locks) |
| 1331 | { |
| 1332 | RewriteRule *rule_lock = (RewriteRule *) lfirst(l); |
| 1333 | |
| 1334 | if (rule_lock->isInstead && |
| 1335 | rule_lock->qual == NULL) |
| 1336 | { |
| 1337 | found = true; |
| 1338 | break; |
| 1339 | } |
| 1340 | } |
| 1341 | |
| 1342 | /* |
| 1343 | * If we didn't find an unconditional DO INSTEAD rule, assume that the |
| 1344 | * view is auto-updatable. If it isn't, rewriteTargetView() will |
| 1345 | * throw an error. |
| 1346 | */ |
| 1347 | if (!found) |
| 1348 | isAutoUpdatableView = true; |
| 1349 | } |
| 1350 | |
| 1351 | newValues = NIL; |
| 1352 | allReplaced = true; |
| 1353 | foreach(lc, rte->values_lists) |
| 1354 | { |
| 1355 | List *sublist = (List *) lfirst(lc); |
| 1356 | List *newList = NIL; |
| 1357 | ListCell *lc2; |
| 1358 | int i; |
| 1359 | |
| 1360 | Assert(list_length(sublist) == numattrs); |
| 1361 | |
| 1362 | i = 0; |
| 1363 | foreach(lc2, sublist) |
| 1364 | { |
| 1365 | Node *col = (Node *) lfirst(lc2); |
| 1366 | int attrno = attrnos[i++]; |
| 1367 | |
| 1368 | if (IsA(col, SetToDefault)) |
| 1369 | { |
| 1370 | Form_pg_attribute att_tup; |
| 1371 | Node *new_expr; |
| 1372 | |
| 1373 | if (attrno == 0) |
| 1374 | elog(ERROR, "cannot set value in column %d to DEFAULT" , i); |
| 1375 | att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1); |
| 1376 | |
| 1377 | if (!force_nulls && !att_tup->attisdropped) |
| 1378 | new_expr = build_column_default(target_relation, attrno); |
| 1379 | else |
| 1380 | new_expr = NULL; /* force a NULL if dropped */ |
| 1381 | |
| 1382 | /* |
| 1383 | * If there is no default (ie, default is effectively NULL), |
| 1384 | * we've got to explicitly set the column to NULL, unless the |
| 1385 | * target relation is an auto-updatable view. |
| 1386 | */ |
| 1387 | if (!new_expr) |
| 1388 | { |
| 1389 | if (isAutoUpdatableView) |
| 1390 | { |
| 1391 | /* Leave the value untouched */ |
| 1392 | newList = lappend(newList, col); |
| 1393 | allReplaced = false; |
| 1394 | continue; |
| 1395 | } |
| 1396 | |
| 1397 | new_expr = (Node *) makeConst(att_tup->atttypid, |
| 1398 | -1, |
| 1399 | att_tup->attcollation, |
| 1400 | att_tup->attlen, |
| 1401 | (Datum) 0, |
| 1402 | true, /* isnull */ |
| 1403 | att_tup->attbyval); |
| 1404 | /* this is to catch a NOT NULL domain constraint */ |
| 1405 | new_expr = coerce_to_domain(new_expr, |
| 1406 | InvalidOid, -1, |
| 1407 | att_tup->atttypid, |
| 1408 | COERCION_IMPLICIT, |
| 1409 | COERCE_IMPLICIT_CAST, |
| 1410 | -1, |
| 1411 | false); |
| 1412 | } |
| 1413 | newList = lappend(newList, new_expr); |
| 1414 | } |
| 1415 | else |
| 1416 | newList = lappend(newList, col); |
| 1417 | } |
| 1418 | newValues = lappend(newValues, newList); |
| 1419 | } |
| 1420 | rte->values_lists = newValues; |
| 1421 | |
| 1422 | pfree(attrnos); |
| 1423 | |
| 1424 | return allReplaced; |
| 1425 | } |
| 1426 | |
| 1427 | |
| 1428 | /* |
| 1429 | * rewriteTargetListUD - rewrite UPDATE/DELETE targetlist as needed |
| 1430 | * |
| 1431 | * This function adds a "junk" TLE that is needed to allow the executor to |
| 1432 | * find the original row for the update or delete. When the target relation |
| 1433 | * is a regular table, the junk TLE emits the ctid attribute of the original |
| 1434 | * row. When the target relation is a foreign table, we let the FDW decide |
| 1435 | * what to add. |
| 1436 | * |
| 1437 | * We used to do this during RewriteQuery(), but now that inheritance trees |
| 1438 | * can contain a mix of regular and foreign tables, we must postpone it till |
| 1439 | * planning, after the inheritance tree has been expanded. In that way we |
| 1440 | * can do the right thing for each child table. |
| 1441 | */ |
| 1442 | void |
| 1443 | rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte, |
| 1444 | Relation target_relation) |
| 1445 | { |
| 1446 | Var *var = NULL; |
| 1447 | const char *attrname; |
| 1448 | TargetEntry *tle; |
| 1449 | |
| 1450 | if (target_relation->rd_rel->relkind == RELKIND_RELATION || |
| 1451 | target_relation->rd_rel->relkind == RELKIND_MATVIEW || |
| 1452 | target_relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) |
| 1453 | { |
| 1454 | /* |
| 1455 | * Emit CTID so that executor can find the row to update or delete. |
| 1456 | */ |
| 1457 | var = makeVar(parsetree->resultRelation, |
| 1458 | SelfItemPointerAttributeNumber, |
| 1459 | TIDOID, |
| 1460 | -1, |
| 1461 | InvalidOid, |
| 1462 | 0); |
| 1463 | |
| 1464 | attrname = "ctid" ; |
| 1465 | } |
| 1466 | else if (target_relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE) |
| 1467 | { |
| 1468 | /* |
| 1469 | * Let the foreign table's FDW add whatever junk TLEs it wants. |
| 1470 | */ |
| 1471 | FdwRoutine *fdwroutine; |
| 1472 | |
| 1473 | fdwroutine = GetFdwRoutineForRelation(target_relation, false); |
| 1474 | |
| 1475 | if (fdwroutine->AddForeignUpdateTargets != NULL) |
| 1476 | fdwroutine->AddForeignUpdateTargets(parsetree, target_rte, |
| 1477 | target_relation); |
| 1478 | |
| 1479 | /* |
| 1480 | * If we have a row-level trigger corresponding to the operation, emit |
| 1481 | * a whole-row Var so that executor will have the "old" row to pass to |
| 1482 | * the trigger. Alas, this misses system columns. |
| 1483 | */ |
| 1484 | if (target_relation->trigdesc && |
| 1485 | ((parsetree->commandType == CMD_UPDATE && |
| 1486 | (target_relation->trigdesc->trig_update_after_row || |
| 1487 | target_relation->trigdesc->trig_update_before_row)) || |
| 1488 | (parsetree->commandType == CMD_DELETE && |
| 1489 | (target_relation->trigdesc->trig_delete_after_row || |
| 1490 | target_relation->trigdesc->trig_delete_before_row)))) |
| 1491 | { |
| 1492 | var = makeWholeRowVar(target_rte, |
| 1493 | parsetree->resultRelation, |
| 1494 | 0, |
| 1495 | false); |
| 1496 | |
| 1497 | attrname = "wholerow" ; |
| 1498 | } |
| 1499 | } |
| 1500 | |
| 1501 | if (var != NULL) |
| 1502 | { |
| 1503 | tle = makeTargetEntry((Expr *) var, |
| 1504 | list_length(parsetree->targetList) + 1, |
| 1505 | pstrdup(attrname), |
| 1506 | true); |
| 1507 | |
| 1508 | parsetree->targetList = lappend(parsetree->targetList, tle); |
| 1509 | } |
| 1510 | } |
| 1511 | |
| 1512 | |
| 1513 | /* |
| 1514 | * matchLocks - |
| 1515 | * match the list of locks and returns the matching rules |
| 1516 | */ |
| 1517 | static List * |
| 1518 | matchLocks(CmdType event, |
| 1519 | RuleLock *rulelocks, |
| 1520 | int varno, |
| 1521 | Query *parsetree, |
| 1522 | bool *hasUpdate) |
| 1523 | { |
| 1524 | List *matching_locks = NIL; |
| 1525 | int nlocks; |
| 1526 | int i; |
| 1527 | |
| 1528 | if (rulelocks == NULL) |
| 1529 | return NIL; |
| 1530 | |
| 1531 | if (parsetree->commandType != CMD_SELECT) |
| 1532 | { |
| 1533 | if (parsetree->resultRelation != varno) |
| 1534 | return NIL; |
| 1535 | } |
| 1536 | |
| 1537 | nlocks = rulelocks->numLocks; |
| 1538 | |
| 1539 | for (i = 0; i < nlocks; i++) |
| 1540 | { |
| 1541 | RewriteRule *oneLock = rulelocks->rules[i]; |
| 1542 | |
| 1543 | if (oneLock->event == CMD_UPDATE) |
| 1544 | *hasUpdate = true; |
| 1545 | |
| 1546 | /* |
| 1547 | * Suppress ON INSERT/UPDATE/DELETE rules that are disabled or |
| 1548 | * configured to not fire during the current sessions replication |
| 1549 | * role. ON SELECT rules will always be applied in order to keep views |
| 1550 | * working even in LOCAL or REPLICA role. |
| 1551 | */ |
| 1552 | if (oneLock->event != CMD_SELECT) |
| 1553 | { |
| 1554 | if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA) |
| 1555 | { |
| 1556 | if (oneLock->enabled == RULE_FIRES_ON_ORIGIN || |
| 1557 | oneLock->enabled == RULE_DISABLED) |
| 1558 | continue; |
| 1559 | } |
| 1560 | else /* ORIGIN or LOCAL ROLE */ |
| 1561 | { |
| 1562 | if (oneLock->enabled == RULE_FIRES_ON_REPLICA || |
| 1563 | oneLock->enabled == RULE_DISABLED) |
| 1564 | continue; |
| 1565 | } |
| 1566 | } |
| 1567 | |
| 1568 | if (oneLock->event == event) |
| 1569 | { |
| 1570 | if (parsetree->commandType != CMD_SELECT || |
| 1571 | rangeTableEntry_used((Node *) parsetree, varno, 0)) |
| 1572 | matching_locks = lappend(matching_locks, oneLock); |
| 1573 | } |
| 1574 | } |
| 1575 | |
| 1576 | return matching_locks; |
| 1577 | } |
| 1578 | |
| 1579 | |
| 1580 | /* |
| 1581 | * ApplyRetrieveRule - expand an ON SELECT rule |
| 1582 | */ |
| 1583 | static Query * |
| 1584 | ApplyRetrieveRule(Query *parsetree, |
| 1585 | RewriteRule *rule, |
| 1586 | int rt_index, |
| 1587 | Relation relation, |
| 1588 | List *activeRIRs) |
| 1589 | { |
| 1590 | Query *rule_action; |
| 1591 | RangeTblEntry *rte, |
| 1592 | *subrte; |
| 1593 | RowMarkClause *rc; |
| 1594 | |
| 1595 | if (list_length(rule->actions) != 1) |
| 1596 | elog(ERROR, "expected just one rule action" ); |
| 1597 | if (rule->qual != NULL) |
| 1598 | elog(ERROR, "cannot handle qualified ON SELECT rule" ); |
| 1599 | |
| 1600 | if (rt_index == parsetree->resultRelation) |
| 1601 | { |
| 1602 | /* |
| 1603 | * We have a view as the result relation of the query, and it wasn't |
| 1604 | * rewritten by any rule. This case is supported if there is an |
| 1605 | * INSTEAD OF trigger that will trap attempts to insert/update/delete |
| 1606 | * view rows. The executor will check that; for the moment just plow |
| 1607 | * ahead. We have two cases: |
| 1608 | * |
| 1609 | * For INSERT, we needn't do anything. The unmodified RTE will serve |
| 1610 | * fine as the result relation. |
| 1611 | * |
| 1612 | * For UPDATE/DELETE, we need to expand the view so as to have source |
| 1613 | * data for the operation. But we also need an unmodified RTE to |
| 1614 | * serve as the target. So, copy the RTE and add the copy to the |
| 1615 | * rangetable. Note that the copy does not get added to the jointree. |
| 1616 | * Also note that there's a hack in fireRIRrules to avoid calling this |
| 1617 | * function again when it arrives at the copied RTE. |
| 1618 | */ |
| 1619 | if (parsetree->commandType == CMD_INSERT) |
| 1620 | return parsetree; |
| 1621 | else if (parsetree->commandType == CMD_UPDATE || |
| 1622 | parsetree->commandType == CMD_DELETE) |
| 1623 | { |
| 1624 | RangeTblEntry *newrte; |
| 1625 | Var *var; |
| 1626 | TargetEntry *tle; |
| 1627 | |
| 1628 | rte = rt_fetch(rt_index, parsetree->rtable); |
| 1629 | newrte = copyObject(rte); |
| 1630 | parsetree->rtable = lappend(parsetree->rtable, newrte); |
| 1631 | parsetree->resultRelation = list_length(parsetree->rtable); |
| 1632 | |
| 1633 | /* |
| 1634 | * There's no need to do permissions checks twice, so wipe out the |
| 1635 | * permissions info for the original RTE (we prefer to keep the |
| 1636 | * bits set on the result RTE). |
| 1637 | */ |
| 1638 | rte->requiredPerms = 0; |
| 1639 | rte->checkAsUser = InvalidOid; |
| 1640 | rte->selectedCols = NULL; |
| 1641 | rte->insertedCols = NULL; |
| 1642 | rte->updatedCols = NULL; |
| 1643 | |
| 1644 | /* |
| 1645 | * For the most part, Vars referencing the view should remain as |
| 1646 | * they are, meaning that they implicitly represent OLD values. |
| 1647 | * But in the RETURNING list if any, we want such Vars to |
| 1648 | * represent NEW values, so change them to reference the new RTE. |
| 1649 | * |
| 1650 | * Since ChangeVarNodes scribbles on the tree in-place, copy the |
| 1651 | * RETURNING list first for safety. |
| 1652 | */ |
| 1653 | parsetree->returningList = copyObject(parsetree->returningList); |
| 1654 | ChangeVarNodes((Node *) parsetree->returningList, rt_index, |
| 1655 | parsetree->resultRelation, 0); |
| 1656 | |
| 1657 | /* |
| 1658 | * To allow the executor to compute the original view row to pass |
| 1659 | * to the INSTEAD OF trigger, we add a resjunk whole-row Var |
| 1660 | * referencing the original RTE. This will later get expanded |
| 1661 | * into a RowExpr computing all the OLD values of the view row. |
| 1662 | */ |
| 1663 | var = makeWholeRowVar(rte, rt_index, 0, false); |
| 1664 | tle = makeTargetEntry((Expr *) var, |
| 1665 | list_length(parsetree->targetList) + 1, |
| 1666 | pstrdup("wholerow" ), |
| 1667 | true); |
| 1668 | |
| 1669 | parsetree->targetList = lappend(parsetree->targetList, tle); |
| 1670 | |
| 1671 | /* Now, continue with expanding the original view RTE */ |
| 1672 | } |
| 1673 | else |
| 1674 | elog(ERROR, "unrecognized commandType: %d" , |
| 1675 | (int) parsetree->commandType); |
| 1676 | } |
| 1677 | |
| 1678 | /* |
| 1679 | * Check if there's a FOR [KEY] UPDATE/SHARE clause applying to this view. |
| 1680 | * |
| 1681 | * Note: we needn't explicitly consider any such clauses appearing in |
| 1682 | * ancestor query levels; their effects have already been pushed down to |
| 1683 | * here by markQueryForLocking, and will be reflected in "rc". |
| 1684 | */ |
| 1685 | rc = get_parse_rowmark(parsetree, rt_index); |
| 1686 | |
| 1687 | /* |
| 1688 | * Make a modifiable copy of the view query, and acquire needed locks on |
| 1689 | * the relations it mentions. Force at least RowShareLock for all such |
| 1690 | * rels if there's a FOR [KEY] UPDATE/SHARE clause affecting this view. |
| 1691 | */ |
| 1692 | rule_action = copyObject(linitial(rule->actions)); |
| 1693 | |
| 1694 | AcquireRewriteLocks(rule_action, true, (rc != NULL)); |
| 1695 | |
| 1696 | /* |
| 1697 | * If FOR [KEY] UPDATE/SHARE of view, mark all the contained tables as |
| 1698 | * implicit FOR [KEY] UPDATE/SHARE, the same as the parser would have done |
| 1699 | * if the view's subquery had been written out explicitly. |
| 1700 | */ |
| 1701 | if (rc != NULL) |
| 1702 | markQueryForLocking(rule_action, (Node *) rule_action->jointree, |
| 1703 | rc->strength, rc->waitPolicy, true); |
| 1704 | |
| 1705 | /* |
| 1706 | * Recursively expand any view references inside the view. |
| 1707 | * |
| 1708 | * Note: this must happen after markQueryForLocking. That way, any UPDATE |
| 1709 | * permission bits needed for sub-views are initially applied to their |
| 1710 | * RTE_RELATION RTEs by markQueryForLocking, and then transferred to their |
| 1711 | * OLD rangetable entries by the action below (in a recursive call of this |
| 1712 | * routine). |
| 1713 | */ |
| 1714 | rule_action = fireRIRrules(rule_action, activeRIRs); |
| 1715 | |
| 1716 | /* |
| 1717 | * Now, plug the view query in as a subselect, converting the relation's |
| 1718 | * original RTE to a subquery RTE. |
| 1719 | */ |
| 1720 | rte = rt_fetch(rt_index, parsetree->rtable); |
| 1721 | |
| 1722 | rte->rtekind = RTE_SUBQUERY; |
| 1723 | rte->subquery = rule_action; |
| 1724 | rte->security_barrier = RelationIsSecurityView(relation); |
| 1725 | /* Clear fields that should not be set in a subquery RTE */ |
| 1726 | rte->relid = InvalidOid; |
| 1727 | rte->relkind = 0; |
| 1728 | rte->rellockmode = 0; |
| 1729 | rte->tablesample = NULL; |
| 1730 | rte->inh = false; /* must not be set for a subquery */ |
| 1731 | |
| 1732 | /* |
| 1733 | * We move the view's permission check data down to its rangetable. The |
| 1734 | * checks will actually be done against the OLD entry therein. |
| 1735 | */ |
| 1736 | subrte = rt_fetch(PRS2_OLD_VARNO, rule_action->rtable); |
| 1737 | Assert(subrte->relid == relation->rd_id); |
| 1738 | subrte->requiredPerms = rte->requiredPerms; |
| 1739 | subrte->checkAsUser = rte->checkAsUser; |
| 1740 | subrte->selectedCols = rte->selectedCols; |
| 1741 | subrte->insertedCols = rte->insertedCols; |
| 1742 | subrte->updatedCols = rte->updatedCols; |
| 1743 | subrte->extraUpdatedCols = rte->extraUpdatedCols; |
| 1744 | |
| 1745 | rte->requiredPerms = 0; /* no permission check on subquery itself */ |
| 1746 | rte->checkAsUser = InvalidOid; |
| 1747 | rte->selectedCols = NULL; |
| 1748 | rte->insertedCols = NULL; |
| 1749 | rte->updatedCols = NULL; |
| 1750 | rte->extraUpdatedCols = NULL; |
| 1751 | |
| 1752 | return parsetree; |
| 1753 | } |
| 1754 | |
| 1755 | /* |
| 1756 | * Recursively mark all relations used by a view as FOR [KEY] UPDATE/SHARE. |
| 1757 | * |
| 1758 | * This may generate an invalid query, eg if some sub-query uses an |
| 1759 | * aggregate. We leave it to the planner to detect that. |
| 1760 | * |
| 1761 | * NB: this must agree with the parser's transformLockingClause() routine. |
| 1762 | * However, unlike the parser we have to be careful not to mark a view's |
| 1763 | * OLD and NEW rels for updating. The best way to handle that seems to be |
| 1764 | * to scan the jointree to determine which rels are used. |
| 1765 | */ |
| 1766 | static void |
| 1767 | markQueryForLocking(Query *qry, Node *jtnode, |
| 1768 | LockClauseStrength strength, LockWaitPolicy waitPolicy, |
| 1769 | bool pushedDown) |
| 1770 | { |
| 1771 | if (jtnode == NULL) |
| 1772 | return; |
| 1773 | if (IsA(jtnode, RangeTblRef)) |
| 1774 | { |
| 1775 | int rti = ((RangeTblRef *) jtnode)->rtindex; |
| 1776 | RangeTblEntry *rte = rt_fetch(rti, qry->rtable); |
| 1777 | |
| 1778 | if (rte->rtekind == RTE_RELATION) |
| 1779 | { |
| 1780 | applyLockingClause(qry, rti, strength, waitPolicy, pushedDown); |
| 1781 | rte->requiredPerms |= ACL_SELECT_FOR_UPDATE; |
| 1782 | } |
| 1783 | else if (rte->rtekind == RTE_SUBQUERY) |
| 1784 | { |
| 1785 | applyLockingClause(qry, rti, strength, waitPolicy, pushedDown); |
| 1786 | /* FOR UPDATE/SHARE of subquery is propagated to subquery's rels */ |
| 1787 | markQueryForLocking(rte->subquery, (Node *) rte->subquery->jointree, |
| 1788 | strength, waitPolicy, true); |
| 1789 | } |
| 1790 | /* other RTE types are unaffected by FOR UPDATE */ |
| 1791 | } |
| 1792 | else if (IsA(jtnode, FromExpr)) |
| 1793 | { |
| 1794 | FromExpr *f = (FromExpr *) jtnode; |
| 1795 | ListCell *l; |
| 1796 | |
| 1797 | foreach(l, f->fromlist) |
| 1798 | markQueryForLocking(qry, lfirst(l), strength, waitPolicy, pushedDown); |
| 1799 | } |
| 1800 | else if (IsA(jtnode, JoinExpr)) |
| 1801 | { |
| 1802 | JoinExpr *j = (JoinExpr *) jtnode; |
| 1803 | |
| 1804 | markQueryForLocking(qry, j->larg, strength, waitPolicy, pushedDown); |
| 1805 | markQueryForLocking(qry, j->rarg, strength, waitPolicy, pushedDown); |
| 1806 | } |
| 1807 | else |
| 1808 | elog(ERROR, "unrecognized node type: %d" , |
| 1809 | (int) nodeTag(jtnode)); |
| 1810 | } |
| 1811 | |
| 1812 | |
| 1813 | /* |
| 1814 | * fireRIRonSubLink - |
| 1815 | * Apply fireRIRrules() to each SubLink (subselect in expression) found |
| 1816 | * in the given tree. |
| 1817 | * |
| 1818 | * NOTE: although this has the form of a walker, we cheat and modify the |
| 1819 | * SubLink nodes in-place. It is caller's responsibility to ensure that |
| 1820 | * no unwanted side-effects occur! |
| 1821 | * |
| 1822 | * This is unlike most of the other routines that recurse into subselects, |
| 1823 | * because we must take control at the SubLink node in order to replace |
| 1824 | * the SubLink's subselect link with the possibly-rewritten subquery. |
| 1825 | */ |
| 1826 | static bool |
| 1827 | fireRIRonSubLink(Node *node, List *activeRIRs) |
| 1828 | { |
| 1829 | if (node == NULL) |
| 1830 | return false; |
| 1831 | if (IsA(node, SubLink)) |
| 1832 | { |
| 1833 | SubLink *sub = (SubLink *) node; |
| 1834 | |
| 1835 | /* Do what we came for */ |
| 1836 | sub->subselect = (Node *) fireRIRrules((Query *) sub->subselect, |
| 1837 | activeRIRs); |
| 1838 | /* Fall through to process lefthand args of SubLink */ |
| 1839 | } |
| 1840 | |
| 1841 | /* |
| 1842 | * Do NOT recurse into Query nodes, because fireRIRrules already processed |
| 1843 | * subselects of subselects for us. |
| 1844 | */ |
| 1845 | return expression_tree_walker(node, fireRIRonSubLink, |
| 1846 | (void *) activeRIRs); |
| 1847 | } |
| 1848 | |
| 1849 | |
| 1850 | /* |
| 1851 | * fireRIRrules - |
| 1852 | * Apply all RIR rules on each rangetable entry in the given query |
| 1853 | * |
| 1854 | * activeRIRs is a list of the OIDs of views we're already processing RIR |
| 1855 | * rules for, used to detect/reject recursion. |
| 1856 | */ |
| 1857 | static Query * |
| 1858 | fireRIRrules(Query *parsetree, List *activeRIRs) |
| 1859 | { |
| 1860 | int origResultRelation = parsetree->resultRelation; |
| 1861 | int rt_index; |
| 1862 | ListCell *lc; |
| 1863 | |
| 1864 | /* |
| 1865 | * don't try to convert this into a foreach loop, because rtable list can |
| 1866 | * get changed each time through... |
| 1867 | */ |
| 1868 | rt_index = 0; |
| 1869 | while (rt_index < list_length(parsetree->rtable)) |
| 1870 | { |
| 1871 | RangeTblEntry *rte; |
| 1872 | Relation rel; |
| 1873 | List *locks; |
| 1874 | RuleLock *rules; |
| 1875 | RewriteRule *rule; |
| 1876 | int i; |
| 1877 | |
| 1878 | ++rt_index; |
| 1879 | |
| 1880 | rte = rt_fetch(rt_index, parsetree->rtable); |
| 1881 | |
| 1882 | /* |
| 1883 | * A subquery RTE can't have associated rules, so there's nothing to |
| 1884 | * do to this level of the query, but we must recurse into the |
| 1885 | * subquery to expand any rule references in it. |
| 1886 | */ |
| 1887 | if (rte->rtekind == RTE_SUBQUERY) |
| 1888 | { |
| 1889 | rte->subquery = fireRIRrules(rte->subquery, activeRIRs); |
| 1890 | continue; |
| 1891 | } |
| 1892 | |
| 1893 | /* |
| 1894 | * Joins and other non-relation RTEs can be ignored completely. |
| 1895 | */ |
| 1896 | if (rte->rtekind != RTE_RELATION) |
| 1897 | continue; |
| 1898 | |
| 1899 | /* |
| 1900 | * Always ignore RIR rules for materialized views referenced in |
| 1901 | * queries. (This does not prevent refreshing MVs, since they aren't |
| 1902 | * referenced in their own query definitions.) |
| 1903 | * |
| 1904 | * Note: in the future we might want to allow MVs to be conditionally |
| 1905 | * expanded as if they were regular views, if they are not scannable. |
| 1906 | * In that case this test would need to be postponed till after we've |
| 1907 | * opened the rel, so that we could check its state. |
| 1908 | */ |
| 1909 | if (rte->relkind == RELKIND_MATVIEW) |
| 1910 | continue; |
| 1911 | |
| 1912 | /* |
| 1913 | * In INSERT ... ON CONFLICT, ignore the EXCLUDED pseudo-relation; |
| 1914 | * even if it points to a view, we needn't expand it, and should not |
| 1915 | * because we want the RTE to remain of RTE_RELATION type. Otherwise, |
| 1916 | * it would get changed to RTE_SUBQUERY type, which is an |
| 1917 | * untested/unsupported situation. |
| 1918 | */ |
| 1919 | if (parsetree->onConflict && |
| 1920 | rt_index == parsetree->onConflict->exclRelIndex) |
| 1921 | continue; |
| 1922 | |
| 1923 | /* |
| 1924 | * If the table is not referenced in the query, then we ignore it. |
| 1925 | * This prevents infinite expansion loop due to new rtable entries |
| 1926 | * inserted by expansion of a rule. A table is referenced if it is |
| 1927 | * part of the join set (a source table), or is referenced by any Var |
| 1928 | * nodes, or is the result table. |
| 1929 | */ |
| 1930 | if (rt_index != parsetree->resultRelation && |
| 1931 | !rangeTableEntry_used((Node *) parsetree, rt_index, 0)) |
| 1932 | continue; |
| 1933 | |
| 1934 | /* |
| 1935 | * Also, if this is a new result relation introduced by |
| 1936 | * ApplyRetrieveRule, we don't want to do anything more with it. |
| 1937 | */ |
| 1938 | if (rt_index == parsetree->resultRelation && |
| 1939 | rt_index != origResultRelation) |
| 1940 | continue; |
| 1941 | |
| 1942 | /* |
| 1943 | * We can use NoLock here since either the parser or |
| 1944 | * AcquireRewriteLocks should have locked the rel already. |
| 1945 | */ |
| 1946 | rel = table_open(rte->relid, NoLock); |
| 1947 | |
| 1948 | /* |
| 1949 | * Collect the RIR rules that we must apply |
| 1950 | */ |
| 1951 | rules = rel->rd_rules; |
| 1952 | if (rules != NULL) |
| 1953 | { |
| 1954 | locks = NIL; |
| 1955 | for (i = 0; i < rules->numLocks; i++) |
| 1956 | { |
| 1957 | rule = rules->rules[i]; |
| 1958 | if (rule->event != CMD_SELECT) |
| 1959 | continue; |
| 1960 | |
| 1961 | locks = lappend(locks, rule); |
| 1962 | } |
| 1963 | |
| 1964 | /* |
| 1965 | * If we found any, apply them --- but first check for recursion! |
| 1966 | */ |
| 1967 | if (locks != NIL) |
| 1968 | { |
| 1969 | ListCell *l; |
| 1970 | |
| 1971 | if (list_member_oid(activeRIRs, RelationGetRelid(rel))) |
| 1972 | ereport(ERROR, |
| 1973 | (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), |
| 1974 | errmsg("infinite recursion detected in rules for relation \"%s\"" , |
| 1975 | RelationGetRelationName(rel)))); |
| 1976 | activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs); |
| 1977 | |
| 1978 | foreach(l, locks) |
| 1979 | { |
| 1980 | rule = lfirst(l); |
| 1981 | |
| 1982 | parsetree = ApplyRetrieveRule(parsetree, |
| 1983 | rule, |
| 1984 | rt_index, |
| 1985 | rel, |
| 1986 | activeRIRs); |
| 1987 | } |
| 1988 | |
| 1989 | activeRIRs = list_delete_first(activeRIRs); |
| 1990 | } |
| 1991 | } |
| 1992 | |
| 1993 | table_close(rel, NoLock); |
| 1994 | } |
| 1995 | |
| 1996 | /* Recurse into subqueries in WITH */ |
| 1997 | foreach(lc, parsetree->cteList) |
| 1998 | { |
| 1999 | CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc); |
| 2000 | |
| 2001 | cte->ctequery = (Node *) |
| 2002 | fireRIRrules((Query *) cte->ctequery, activeRIRs); |
| 2003 | } |
| 2004 | |
| 2005 | /* |
| 2006 | * Recurse into sublink subqueries, too. But we already did the ones in |
| 2007 | * the rtable and cteList. |
| 2008 | */ |
| 2009 | if (parsetree->hasSubLinks) |
| 2010 | query_tree_walker(parsetree, fireRIRonSubLink, (void *) activeRIRs, |
| 2011 | QTW_IGNORE_RC_SUBQUERIES); |
| 2012 | |
| 2013 | /* |
| 2014 | * Apply any row level security policies. We do this last because it |
| 2015 | * requires special recursion detection if the new quals have sublink |
| 2016 | * subqueries, and if we did it in the loop above query_tree_walker would |
| 2017 | * then recurse into those quals a second time. |
| 2018 | */ |
| 2019 | rt_index = 0; |
| 2020 | foreach(lc, parsetree->rtable) |
| 2021 | { |
| 2022 | RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); |
| 2023 | Relation rel; |
| 2024 | List *securityQuals; |
| 2025 | List *withCheckOptions; |
| 2026 | bool hasRowSecurity; |
| 2027 | bool hasSubLinks; |
| 2028 | |
| 2029 | ++rt_index; |
| 2030 | |
| 2031 | /* Only normal relations can have RLS policies */ |
| 2032 | if (rte->rtekind != RTE_RELATION || |
| 2033 | (rte->relkind != RELKIND_RELATION && |
| 2034 | rte->relkind != RELKIND_PARTITIONED_TABLE)) |
| 2035 | continue; |
| 2036 | |
| 2037 | rel = table_open(rte->relid, NoLock); |
| 2038 | |
| 2039 | /* |
| 2040 | * Fetch any new security quals that must be applied to this RTE. |
| 2041 | */ |
| 2042 | get_row_security_policies(parsetree, rte, rt_index, |
| 2043 | &securityQuals, &withCheckOptions, |
| 2044 | &hasRowSecurity, &hasSubLinks); |
| 2045 | |
| 2046 | if (securityQuals != NIL || withCheckOptions != NIL) |
| 2047 | { |
| 2048 | if (hasSubLinks) |
| 2049 | { |
| 2050 | acquireLocksOnSubLinks_context context; |
| 2051 | |
| 2052 | /* |
| 2053 | * Recursively process the new quals, checking for infinite |
| 2054 | * recursion. |
| 2055 | */ |
| 2056 | if (list_member_oid(activeRIRs, RelationGetRelid(rel))) |
| 2057 | ereport(ERROR, |
| 2058 | (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), |
| 2059 | errmsg("infinite recursion detected in policy for relation \"%s\"" , |
| 2060 | RelationGetRelationName(rel)))); |
| 2061 | |
| 2062 | activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs); |
| 2063 | |
| 2064 | /* |
| 2065 | * get_row_security_policies just passed back securityQuals |
| 2066 | * and/or withCheckOptions, and there were SubLinks, make sure |
| 2067 | * we lock any relations which are referenced. |
| 2068 | * |
| 2069 | * These locks would normally be acquired by the parser, but |
| 2070 | * securityQuals and withCheckOptions are added post-parsing. |
| 2071 | */ |
| 2072 | context.for_execute = true; |
| 2073 | (void) acquireLocksOnSubLinks((Node *) securityQuals, &context); |
| 2074 | (void) acquireLocksOnSubLinks((Node *) withCheckOptions, |
| 2075 | &context); |
| 2076 | |
| 2077 | /* |
| 2078 | * Now that we have the locks on anything added by |
| 2079 | * get_row_security_policies, fire any RIR rules for them. |
| 2080 | */ |
| 2081 | expression_tree_walker((Node *) securityQuals, |
| 2082 | fireRIRonSubLink, (void *) activeRIRs); |
| 2083 | |
| 2084 | expression_tree_walker((Node *) withCheckOptions, |
| 2085 | fireRIRonSubLink, (void *) activeRIRs); |
| 2086 | |
| 2087 | activeRIRs = list_delete_first(activeRIRs); |
| 2088 | } |
| 2089 | |
| 2090 | /* |
| 2091 | * Add the new security barrier quals to the start of the RTE's |
| 2092 | * list so that they get applied before any existing barrier quals |
| 2093 | * (which would have come from a security-barrier view, and should |
| 2094 | * get lower priority than RLS conditions on the table itself). |
| 2095 | */ |
| 2096 | rte->securityQuals = list_concat(securityQuals, |
| 2097 | rte->securityQuals); |
| 2098 | |
| 2099 | parsetree->withCheckOptions = list_concat(withCheckOptions, |
| 2100 | parsetree->withCheckOptions); |
| 2101 | } |
| 2102 | |
| 2103 | /* |
| 2104 | * Make sure the query is marked correctly if row level security |
| 2105 | * applies, or if the new quals had sublinks. |
| 2106 | */ |
| 2107 | if (hasRowSecurity) |
| 2108 | parsetree->hasRowSecurity = true; |
| 2109 | if (hasSubLinks) |
| 2110 | parsetree->hasSubLinks = true; |
| 2111 | |
| 2112 | table_close(rel, NoLock); |
| 2113 | } |
| 2114 | |
| 2115 | return parsetree; |
| 2116 | } |
| 2117 | |
| 2118 | |
| 2119 | /* |
| 2120 | * Modify the given query by adding 'AND rule_qual IS NOT TRUE' to its |
| 2121 | * qualification. This is used to generate suitable "else clauses" for |
| 2122 | * conditional INSTEAD rules. (Unfortunately we must use "x IS NOT TRUE", |
| 2123 | * not just "NOT x" which the planner is much smarter about, else we will |
| 2124 | * do the wrong thing when the qual evaluates to NULL.) |
| 2125 | * |
| 2126 | * The rule_qual may contain references to OLD or NEW. OLD references are |
| 2127 | * replaced by references to the specified rt_index (the relation that the |
| 2128 | * rule applies to). NEW references are only possible for INSERT and UPDATE |
| 2129 | * queries on the relation itself, and so they should be replaced by copies |
| 2130 | * of the related entries in the query's own targetlist. |
| 2131 | */ |
| 2132 | static Query * |
| 2133 | CopyAndAddInvertedQual(Query *parsetree, |
| 2134 | Node *rule_qual, |
| 2135 | int rt_index, |
| 2136 | CmdType event) |
| 2137 | { |
| 2138 | /* Don't scribble on the passed qual (it's in the relcache!) */ |
| 2139 | Node *new_qual = copyObject(rule_qual); |
| 2140 | acquireLocksOnSubLinks_context context; |
| 2141 | |
| 2142 | context.for_execute = true; |
| 2143 | |
| 2144 | /* |
| 2145 | * In case there are subqueries in the qual, acquire necessary locks and |
| 2146 | * fix any deleted JOIN RTE entries. (This is somewhat redundant with |
| 2147 | * rewriteRuleAction, but not entirely ... consider restructuring so that |
| 2148 | * we only need to process the qual this way once.) |
| 2149 | */ |
| 2150 | (void) acquireLocksOnSubLinks(new_qual, &context); |
| 2151 | |
| 2152 | /* Fix references to OLD */ |
| 2153 | ChangeVarNodes(new_qual, PRS2_OLD_VARNO, rt_index, 0); |
| 2154 | /* Fix references to NEW */ |
| 2155 | if (event == CMD_INSERT || event == CMD_UPDATE) |
| 2156 | new_qual = ReplaceVarsFromTargetList(new_qual, |
| 2157 | PRS2_NEW_VARNO, |
| 2158 | 0, |
| 2159 | rt_fetch(rt_index, |
| 2160 | parsetree->rtable), |
| 2161 | parsetree->targetList, |
| 2162 | (event == CMD_UPDATE) ? |
| 2163 | REPLACEVARS_CHANGE_VARNO : |
| 2164 | REPLACEVARS_SUBSTITUTE_NULL, |
| 2165 | rt_index, |
| 2166 | &parsetree->hasSubLinks); |
| 2167 | /* And attach the fixed qual */ |
| 2168 | AddInvertedQual(parsetree, new_qual); |
| 2169 | |
| 2170 | return parsetree; |
| 2171 | } |
| 2172 | |
| 2173 | |
| 2174 | /* |
| 2175 | * fireRules - |
| 2176 | * Iterate through rule locks applying rules. |
| 2177 | * |
| 2178 | * Input arguments: |
| 2179 | * parsetree - original query |
| 2180 | * rt_index - RT index of result relation in original query |
| 2181 | * event - type of rule event |
| 2182 | * locks - list of rules to fire |
| 2183 | * Output arguments: |
| 2184 | * *instead_flag - set true if any unqualified INSTEAD rule is found |
| 2185 | * (must be initialized to false) |
| 2186 | * *returning_flag - set true if we rewrite RETURNING clause in any rule |
| 2187 | * (must be initialized to false) |
| 2188 | * *qual_product - filled with modified original query if any qualified |
| 2189 | * INSTEAD rule is found (must be initialized to NULL) |
| 2190 | * Return value: |
| 2191 | * list of rule actions adjusted for use with this query |
| 2192 | * |
| 2193 | * Qualified INSTEAD rules generate their action with the qualification |
| 2194 | * condition added. They also generate a modified version of the original |
| 2195 | * query with the negated qualification added, so that it will run only for |
| 2196 | * rows that the qualified action doesn't act on. (If there are multiple |
| 2197 | * qualified INSTEAD rules, we AND all the negated quals onto a single |
| 2198 | * modified original query.) We won't execute the original, unmodified |
| 2199 | * query if we find either qualified or unqualified INSTEAD rules. If |
| 2200 | * we find both, the modified original query is discarded too. |
| 2201 | */ |
| 2202 | static List * |
| 2203 | fireRules(Query *parsetree, |
| 2204 | int rt_index, |
| 2205 | CmdType event, |
| 2206 | List *locks, |
| 2207 | bool *instead_flag, |
| 2208 | bool *returning_flag, |
| 2209 | Query **qual_product) |
| 2210 | { |
| 2211 | List *results = NIL; |
| 2212 | ListCell *l; |
| 2213 | |
| 2214 | foreach(l, locks) |
| 2215 | { |
| 2216 | RewriteRule *rule_lock = (RewriteRule *) lfirst(l); |
| 2217 | Node *event_qual = rule_lock->qual; |
| 2218 | List *actions = rule_lock->actions; |
| 2219 | QuerySource qsrc; |
| 2220 | ListCell *r; |
| 2221 | |
| 2222 | /* Determine correct QuerySource value for actions */ |
| 2223 | if (rule_lock->isInstead) |
| 2224 | { |
| 2225 | if (event_qual != NULL) |
| 2226 | qsrc = QSRC_QUAL_INSTEAD_RULE; |
| 2227 | else |
| 2228 | { |
| 2229 | qsrc = QSRC_INSTEAD_RULE; |
| 2230 | *instead_flag = true; /* report unqualified INSTEAD */ |
| 2231 | } |
| 2232 | } |
| 2233 | else |
| 2234 | qsrc = QSRC_NON_INSTEAD_RULE; |
| 2235 | |
| 2236 | if (qsrc == QSRC_QUAL_INSTEAD_RULE) |
| 2237 | { |
| 2238 | /* |
| 2239 | * If there are INSTEAD rules with qualifications, the original |
| 2240 | * query is still performed. But all the negated rule |
| 2241 | * qualifications of the INSTEAD rules are added so it does its |
| 2242 | * actions only in cases where the rule quals of all INSTEAD rules |
| 2243 | * are false. Think of it as the default action in a case. We save |
| 2244 | * this in *qual_product so RewriteQuery() can add it to the query |
| 2245 | * list after we mangled it up enough. |
| 2246 | * |
| 2247 | * If we have already found an unqualified INSTEAD rule, then |
| 2248 | * *qual_product won't be used, so don't bother building it. |
| 2249 | */ |
| 2250 | if (!*instead_flag) |
| 2251 | { |
| 2252 | if (*qual_product == NULL) |
| 2253 | *qual_product = copyObject(parsetree); |
| 2254 | *qual_product = CopyAndAddInvertedQual(*qual_product, |
| 2255 | event_qual, |
| 2256 | rt_index, |
| 2257 | event); |
| 2258 | } |
| 2259 | } |
| 2260 | |
| 2261 | /* Now process the rule's actions and add them to the result list */ |
| 2262 | foreach(r, actions) |
| 2263 | { |
| 2264 | Query *rule_action = lfirst(r); |
| 2265 | |
| 2266 | if (rule_action->commandType == CMD_NOTHING) |
| 2267 | continue; |
| 2268 | |
| 2269 | rule_action = rewriteRuleAction(parsetree, rule_action, |
| 2270 | event_qual, rt_index, event, |
| 2271 | returning_flag); |
| 2272 | |
| 2273 | rule_action->querySource = qsrc; |
| 2274 | rule_action->canSetTag = false; /* might change later */ |
| 2275 | |
| 2276 | results = lappend(results, rule_action); |
| 2277 | } |
| 2278 | } |
| 2279 | |
| 2280 | return results; |
| 2281 | } |
| 2282 | |
| 2283 | |
| 2284 | /* |
| 2285 | * get_view_query - get the Query from a view's _RETURN rule. |
| 2286 | * |
| 2287 | * Caller should have verified that the relation is a view, and therefore |
| 2288 | * we should find an ON SELECT action. |
| 2289 | * |
| 2290 | * Note that the pointer returned is into the relcache and therefore must |
| 2291 | * be treated as read-only to the caller and not modified or scribbled on. |
| 2292 | */ |
| 2293 | Query * |
| 2294 | get_view_query(Relation view) |
| 2295 | { |
| 2296 | int i; |
| 2297 | |
| 2298 | Assert(view->rd_rel->relkind == RELKIND_VIEW); |
| 2299 | |
| 2300 | for (i = 0; i < view->rd_rules->numLocks; i++) |
| 2301 | { |
| 2302 | RewriteRule *rule = view->rd_rules->rules[i]; |
| 2303 | |
| 2304 | if (rule->event == CMD_SELECT) |
| 2305 | { |
| 2306 | /* A _RETURN rule should have only one action */ |
| 2307 | if (list_length(rule->actions) != 1) |
| 2308 | elog(ERROR, "invalid _RETURN rule action specification" ); |
| 2309 | |
| 2310 | return (Query *) linitial(rule->actions); |
| 2311 | } |
| 2312 | } |
| 2313 | |
| 2314 | elog(ERROR, "failed to find _RETURN rule for view" ); |
| 2315 | return NULL; /* keep compiler quiet */ |
| 2316 | } |
| 2317 | |
| 2318 | |
| 2319 | /* |
| 2320 | * view_has_instead_trigger - does view have an INSTEAD OF trigger for event? |
| 2321 | * |
| 2322 | * If it does, we don't want to treat it as auto-updatable. This test can't |
| 2323 | * be folded into view_query_is_auto_updatable because it's not an error |
| 2324 | * condition. |
| 2325 | */ |
| 2326 | static bool |
| 2327 | view_has_instead_trigger(Relation view, CmdType event) |
| 2328 | { |
| 2329 | TriggerDesc *trigDesc = view->trigdesc; |
| 2330 | |
| 2331 | switch (event) |
| 2332 | { |
| 2333 | case CMD_INSERT: |
| 2334 | if (trigDesc && trigDesc->trig_insert_instead_row) |
| 2335 | return true; |
| 2336 | break; |
| 2337 | case CMD_UPDATE: |
| 2338 | if (trigDesc && trigDesc->trig_update_instead_row) |
| 2339 | return true; |
| 2340 | break; |
| 2341 | case CMD_DELETE: |
| 2342 | if (trigDesc && trigDesc->trig_delete_instead_row) |
| 2343 | return true; |
| 2344 | break; |
| 2345 | default: |
| 2346 | elog(ERROR, "unrecognized CmdType: %d" , (int) event); |
| 2347 | break; |
| 2348 | } |
| 2349 | return false; |
| 2350 | } |
| 2351 | |
| 2352 | |
| 2353 | /* |
| 2354 | * view_col_is_auto_updatable - test whether the specified column of a view |
| 2355 | * is auto-updatable. Returns NULL (if the column can be updated) or a message |
| 2356 | * string giving the reason that it cannot be. |
| 2357 | * |
| 2358 | * The returned string has not been translated; if it is shown as an error |
| 2359 | * message, the caller should apply _() to translate it. |
| 2360 | * |
| 2361 | * Note that the checks performed here are local to this view. We do not check |
| 2362 | * whether the referenced column of the underlying base relation is updatable. |
| 2363 | */ |
| 2364 | static const char * |
| 2365 | view_col_is_auto_updatable(RangeTblRef *rtr, TargetEntry *tle) |
| 2366 | { |
| 2367 | Var *var = (Var *) tle->expr; |
| 2368 | |
| 2369 | /* |
| 2370 | * For now, the only updatable columns we support are those that are Vars |
| 2371 | * referring to user columns of the underlying base relation. |
| 2372 | * |
| 2373 | * The view targetlist may contain resjunk columns (e.g., a view defined |
| 2374 | * like "SELECT * FROM t ORDER BY a+b" is auto-updatable) but such columns |
| 2375 | * are not auto-updatable, and in fact should never appear in the outer |
| 2376 | * query's targetlist. |
| 2377 | */ |
| 2378 | if (tle->resjunk) |
| 2379 | return gettext_noop("Junk view columns are not updatable." ); |
| 2380 | |
| 2381 | if (!IsA(var, Var) || |
| 2382 | var->varno != rtr->rtindex || |
| 2383 | var->varlevelsup != 0) |
| 2384 | return gettext_noop("View columns that are not columns of their base relation are not updatable." ); |
| 2385 | |
| 2386 | if (var->varattno < 0) |
| 2387 | return gettext_noop("View columns that refer to system columns are not updatable." ); |
| 2388 | |
| 2389 | if (var->varattno == 0) |
| 2390 | return gettext_noop("View columns that return whole-row references are not updatable." ); |
| 2391 | |
| 2392 | return NULL; /* the view column is updatable */ |
| 2393 | } |
| 2394 | |
| 2395 | |
| 2396 | /* |
| 2397 | * view_query_is_auto_updatable - test whether the specified view definition |
| 2398 | * represents an auto-updatable view. Returns NULL (if the view can be updated) |
| 2399 | * or a message string giving the reason that it cannot be. |
| 2400 | |
| 2401 | * The returned string has not been translated; if it is shown as an error |
| 2402 | * message, the caller should apply _() to translate it. |
| 2403 | * |
| 2404 | * If check_cols is true, the view is required to have at least one updatable |
| 2405 | * column (necessary for INSERT/UPDATE). Otherwise the view's columns are not |
| 2406 | * checked for updatability. See also view_cols_are_auto_updatable. |
| 2407 | * |
| 2408 | * Note that the checks performed here are only based on the view definition. |
| 2409 | * We do not check whether any base relations referred to by the view are |
| 2410 | * updatable. |
| 2411 | */ |
| 2412 | const char * |
| 2413 | view_query_is_auto_updatable(Query *viewquery, bool check_cols) |
| 2414 | { |
| 2415 | RangeTblRef *rtr; |
| 2416 | RangeTblEntry *base_rte; |
| 2417 | |
| 2418 | /*---------- |
| 2419 | * Check if the view is simply updatable. According to SQL-92 this means: |
| 2420 | * - No DISTINCT clause. |
| 2421 | * - Each TLE is a column reference, and each column appears at most once. |
| 2422 | * - FROM contains exactly one base relation. |
| 2423 | * - No GROUP BY or HAVING clauses. |
| 2424 | * - No set operations (UNION, INTERSECT or EXCEPT). |
| 2425 | * - No sub-queries in the WHERE clause that reference the target table. |
| 2426 | * |
| 2427 | * We ignore that last restriction since it would be complex to enforce |
| 2428 | * and there isn't any actual benefit to disallowing sub-queries. (The |
| 2429 | * semantic issues that the standard is presumably concerned about don't |
| 2430 | * arise in Postgres, since any such sub-query will not see any updates |
| 2431 | * executed by the outer query anyway, thanks to MVCC snapshotting.) |
| 2432 | * |
| 2433 | * We also relax the second restriction by supporting part of SQL:1999 |
| 2434 | * feature T111, which allows for a mix of updatable and non-updatable |
| 2435 | * columns, provided that an INSERT or UPDATE doesn't attempt to assign to |
| 2436 | * a non-updatable column. |
| 2437 | * |
| 2438 | * In addition we impose these constraints, involving features that are |
| 2439 | * not part of SQL-92: |
| 2440 | * - No CTEs (WITH clauses). |
| 2441 | * - No OFFSET or LIMIT clauses (this matches a SQL:2008 restriction). |
| 2442 | * - No system columns (including whole-row references) in the tlist. |
| 2443 | * - No window functions in the tlist. |
| 2444 | * - No set-returning functions in the tlist. |
| 2445 | * |
| 2446 | * Note that we do these checks without recursively expanding the view. |
| 2447 | * If the base relation is a view, we'll recursively deal with it later. |
| 2448 | *---------- |
| 2449 | */ |
| 2450 | if (viewquery->distinctClause != NIL) |
| 2451 | return gettext_noop("Views containing DISTINCT are not automatically updatable." ); |
| 2452 | |
| 2453 | if (viewquery->groupClause != NIL || viewquery->groupingSets) |
| 2454 | return gettext_noop("Views containing GROUP BY are not automatically updatable." ); |
| 2455 | |
| 2456 | if (viewquery->havingQual != NULL) |
| 2457 | return gettext_noop("Views containing HAVING are not automatically updatable." ); |
| 2458 | |
| 2459 | if (viewquery->setOperations != NULL) |
| 2460 | return gettext_noop("Views containing UNION, INTERSECT, or EXCEPT are not automatically updatable." ); |
| 2461 | |
| 2462 | if (viewquery->cteList != NIL) |
| 2463 | return gettext_noop("Views containing WITH are not automatically updatable." ); |
| 2464 | |
| 2465 | if (viewquery->limitOffset != NULL || viewquery->limitCount != NULL) |
| 2466 | return gettext_noop("Views containing LIMIT or OFFSET are not automatically updatable." ); |
| 2467 | |
| 2468 | /* |
| 2469 | * We must not allow window functions or set returning functions in the |
| 2470 | * targetlist. Otherwise we might end up inserting them into the quals of |
| 2471 | * the main query. We must also check for aggregates in the targetlist in |
| 2472 | * case they appear without a GROUP BY. |
| 2473 | * |
| 2474 | * These restrictions ensure that each row of the view corresponds to a |
| 2475 | * unique row in the underlying base relation. |
| 2476 | */ |
| 2477 | if (viewquery->hasAggs) |
| 2478 | return gettext_noop("Views that return aggregate functions are not automatically updatable." ); |
| 2479 | |
| 2480 | if (viewquery->hasWindowFuncs) |
| 2481 | return gettext_noop("Views that return window functions are not automatically updatable." ); |
| 2482 | |
| 2483 | if (viewquery->hasTargetSRFs) |
| 2484 | return gettext_noop("Views that return set-returning functions are not automatically updatable." ); |
| 2485 | |
| 2486 | /* |
| 2487 | * The view query should select from a single base relation, which must be |
| 2488 | * a table or another view. |
| 2489 | */ |
| 2490 | if (list_length(viewquery->jointree->fromlist) != 1) |
| 2491 | return gettext_noop("Views that do not select from a single table or view are not automatically updatable." ); |
| 2492 | |
| 2493 | rtr = (RangeTblRef *) linitial(viewquery->jointree->fromlist); |
| 2494 | if (!IsA(rtr, RangeTblRef)) |
| 2495 | return gettext_noop("Views that do not select from a single table or view are not automatically updatable." ); |
| 2496 | |
| 2497 | base_rte = rt_fetch(rtr->rtindex, viewquery->rtable); |
| 2498 | if (base_rte->rtekind != RTE_RELATION || |
| 2499 | (base_rte->relkind != RELKIND_RELATION && |
| 2500 | base_rte->relkind != RELKIND_FOREIGN_TABLE && |
| 2501 | base_rte->relkind != RELKIND_VIEW && |
| 2502 | base_rte->relkind != RELKIND_PARTITIONED_TABLE)) |
| 2503 | return gettext_noop("Views that do not select from a single table or view are not automatically updatable." ); |
| 2504 | |
| 2505 | if (base_rte->tablesample) |
| 2506 | return gettext_noop("Views containing TABLESAMPLE are not automatically updatable." ); |
| 2507 | |
| 2508 | /* |
| 2509 | * Check that the view has at least one updatable column. This is required |
| 2510 | * for INSERT/UPDATE but not for DELETE. |
| 2511 | */ |
| 2512 | if (check_cols) |
| 2513 | { |
| 2514 | ListCell *cell; |
| 2515 | bool found; |
| 2516 | |
| 2517 | found = false; |
| 2518 | foreach(cell, viewquery->targetList) |
| 2519 | { |
| 2520 | TargetEntry *tle = (TargetEntry *) lfirst(cell); |
| 2521 | |
| 2522 | if (view_col_is_auto_updatable(rtr, tle) == NULL) |
| 2523 | { |
| 2524 | found = true; |
| 2525 | break; |
| 2526 | } |
| 2527 | } |
| 2528 | |
| 2529 | if (!found) |
| 2530 | return gettext_noop("Views that have no updatable columns are not automatically updatable." ); |
| 2531 | } |
| 2532 | |
| 2533 | return NULL; /* the view is updatable */ |
| 2534 | } |
| 2535 | |
| 2536 | |
| 2537 | /* |
| 2538 | * view_cols_are_auto_updatable - test whether all of the required columns of |
| 2539 | * an auto-updatable view are actually updatable. Returns NULL (if all the |
| 2540 | * required columns can be updated) or a message string giving the reason that |
| 2541 | * they cannot be. |
| 2542 | * |
| 2543 | * The returned string has not been translated; if it is shown as an error |
| 2544 | * message, the caller should apply _() to translate it. |
| 2545 | * |
| 2546 | * This should be used for INSERT/UPDATE to ensure that we don't attempt to |
| 2547 | * assign to any non-updatable columns. |
| 2548 | * |
| 2549 | * Additionally it may be used to retrieve the set of updatable columns in the |
| 2550 | * view, or if one or more of the required columns is not updatable, the name |
| 2551 | * of the first offending non-updatable column. |
| 2552 | * |
| 2553 | * The caller must have already verified that this is an auto-updatable view |
| 2554 | * using view_query_is_auto_updatable. |
| 2555 | * |
| 2556 | * Note that the checks performed here are only based on the view definition. |
| 2557 | * We do not check whether the referenced columns of the base relation are |
| 2558 | * updatable. |
| 2559 | */ |
| 2560 | static const char * |
| 2561 | view_cols_are_auto_updatable(Query *viewquery, |
| 2562 | Bitmapset *required_cols, |
| 2563 | Bitmapset **updatable_cols, |
| 2564 | char **non_updatable_col) |
| 2565 | { |
| 2566 | RangeTblRef *rtr; |
| 2567 | AttrNumber col; |
| 2568 | ListCell *cell; |
| 2569 | |
| 2570 | /* |
| 2571 | * The caller should have verified that this view is auto-updatable and so |
| 2572 | * there should be a single base relation. |
| 2573 | */ |
| 2574 | Assert(list_length(viewquery->jointree->fromlist) == 1); |
| 2575 | rtr = linitial_node(RangeTblRef, viewquery->jointree->fromlist); |
| 2576 | |
| 2577 | /* Initialize the optional return values */ |
| 2578 | if (updatable_cols != NULL) |
| 2579 | *updatable_cols = NULL; |
| 2580 | if (non_updatable_col != NULL) |
| 2581 | *non_updatable_col = NULL; |
| 2582 | |
| 2583 | /* Test each view column for updatability */ |
| 2584 | col = -FirstLowInvalidHeapAttributeNumber; |
| 2585 | foreach(cell, viewquery->targetList) |
| 2586 | { |
| 2587 | TargetEntry *tle = (TargetEntry *) lfirst(cell); |
| 2588 | const char *col_update_detail; |
| 2589 | |
| 2590 | col++; |
| 2591 | col_update_detail = view_col_is_auto_updatable(rtr, tle); |
| 2592 | |
| 2593 | if (col_update_detail == NULL) |
| 2594 | { |
| 2595 | /* The column is updatable */ |
| 2596 | if (updatable_cols != NULL) |
| 2597 | *updatable_cols = bms_add_member(*updatable_cols, col); |
| 2598 | } |
| 2599 | else if (bms_is_member(col, required_cols)) |
| 2600 | { |
| 2601 | /* The required column is not updatable */ |
| 2602 | if (non_updatable_col != NULL) |
| 2603 | *non_updatable_col = tle->resname; |
| 2604 | return col_update_detail; |
| 2605 | } |
| 2606 | } |
| 2607 | |
| 2608 | return NULL; /* all the required view columns are updatable */ |
| 2609 | } |
| 2610 | |
| 2611 | |
| 2612 | /* |
| 2613 | * relation_is_updatable - determine which update events the specified |
| 2614 | * relation supports. |
| 2615 | * |
| 2616 | * Note that views may contain a mix of updatable and non-updatable columns. |
| 2617 | * For a view to support INSERT/UPDATE it must have at least one updatable |
| 2618 | * column, but there is no such restriction for DELETE. If include_cols is |
| 2619 | * non-NULL, then only the specified columns are considered when testing for |
| 2620 | * updatability. |
| 2621 | * |
| 2622 | * This is used for the information_schema views, which have separate concepts |
| 2623 | * of "updatable" and "trigger updatable". A relation is "updatable" if it |
| 2624 | * can be updated without the need for triggers (either because it has a |
| 2625 | * suitable RULE, or because it is simple enough to be automatically updated). |
| 2626 | * A relation is "trigger updatable" if it has a suitable INSTEAD OF trigger. |
| 2627 | * The SQL standard regards this as not necessarily updatable, presumably |
| 2628 | * because there is no way of knowing what the trigger will actually do. |
| 2629 | * The information_schema views therefore call this function with |
| 2630 | * include_triggers = false. However, other callers might only care whether |
| 2631 | * data-modifying SQL will work, so they can pass include_triggers = true |
| 2632 | * to have trigger updatability included in the result. |
| 2633 | * |
| 2634 | * The return value is a bitmask of rule event numbers indicating which of |
| 2635 | * the INSERT, UPDATE and DELETE operations are supported. (We do it this way |
| 2636 | * so that we can test for UPDATE plus DELETE support in a single call.) |
| 2637 | */ |
| 2638 | int |
| 2639 | relation_is_updatable(Oid reloid, |
| 2640 | bool include_triggers, |
| 2641 | Bitmapset *include_cols) |
| 2642 | { |
| 2643 | int events = 0; |
| 2644 | Relation rel; |
| 2645 | RuleLock *rulelocks; |
| 2646 | |
| 2647 | #define ALL_EVENTS ((1 << CMD_INSERT) | (1 << CMD_UPDATE) | (1 << CMD_DELETE)) |
| 2648 | |
| 2649 | rel = try_relation_open(reloid, AccessShareLock); |
| 2650 | |
| 2651 | /* |
| 2652 | * If the relation doesn't exist, return zero rather than throwing an |
| 2653 | * error. This is helpful since scanning an information_schema view under |
| 2654 | * MVCC rules can result in referencing rels that have actually been |
| 2655 | * deleted already. |
| 2656 | */ |
| 2657 | if (rel == NULL) |
| 2658 | return 0; |
| 2659 | |
| 2660 | /* If the relation is a table, it is always updatable */ |
| 2661 | if (rel->rd_rel->relkind == RELKIND_RELATION || |
| 2662 | rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) |
| 2663 | { |
| 2664 | relation_close(rel, AccessShareLock); |
| 2665 | return ALL_EVENTS; |
| 2666 | } |
| 2667 | |
| 2668 | /* Look for unconditional DO INSTEAD rules, and note supported events */ |
| 2669 | rulelocks = rel->rd_rules; |
| 2670 | if (rulelocks != NULL) |
| 2671 | { |
| 2672 | int i; |
| 2673 | |
| 2674 | for (i = 0; i < rulelocks->numLocks; i++) |
| 2675 | { |
| 2676 | if (rulelocks->rules[i]->isInstead && |
| 2677 | rulelocks->rules[i]->qual == NULL) |
| 2678 | { |
| 2679 | events |= ((1 << rulelocks->rules[i]->event) & ALL_EVENTS); |
| 2680 | } |
| 2681 | } |
| 2682 | |
| 2683 | /* If we have rules for all events, we're done */ |
| 2684 | if (events == ALL_EVENTS) |
| 2685 | { |
| 2686 | relation_close(rel, AccessShareLock); |
| 2687 | return events; |
| 2688 | } |
| 2689 | } |
| 2690 | |
| 2691 | /* Similarly look for INSTEAD OF triggers, if they are to be included */ |
| 2692 | if (include_triggers) |
| 2693 | { |
| 2694 | TriggerDesc *trigDesc = rel->trigdesc; |
| 2695 | |
| 2696 | if (trigDesc) |
| 2697 | { |
| 2698 | if (trigDesc->trig_insert_instead_row) |
| 2699 | events |= (1 << CMD_INSERT); |
| 2700 | if (trigDesc->trig_update_instead_row) |
| 2701 | events |= (1 << CMD_UPDATE); |
| 2702 | if (trigDesc->trig_delete_instead_row) |
| 2703 | events |= (1 << CMD_DELETE); |
| 2704 | |
| 2705 | /* If we have triggers for all events, we're done */ |
| 2706 | if (events == ALL_EVENTS) |
| 2707 | { |
| 2708 | relation_close(rel, AccessShareLock); |
| 2709 | return events; |
| 2710 | } |
| 2711 | } |
| 2712 | } |
| 2713 | |
| 2714 | /* If this is a foreign table, check which update events it supports */ |
| 2715 | if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE) |
| 2716 | { |
| 2717 | FdwRoutine *fdwroutine = GetFdwRoutineForRelation(rel, false); |
| 2718 | |
| 2719 | if (fdwroutine->IsForeignRelUpdatable != NULL) |
| 2720 | events |= fdwroutine->IsForeignRelUpdatable(rel); |
| 2721 | else |
| 2722 | { |
| 2723 | /* Assume presence of executor functions is sufficient */ |
| 2724 | if (fdwroutine->ExecForeignInsert != NULL) |
| 2725 | events |= (1 << CMD_INSERT); |
| 2726 | if (fdwroutine->ExecForeignUpdate != NULL) |
| 2727 | events |= (1 << CMD_UPDATE); |
| 2728 | if (fdwroutine->ExecForeignDelete != NULL) |
| 2729 | events |= (1 << CMD_DELETE); |
| 2730 | } |
| 2731 | |
| 2732 | relation_close(rel, AccessShareLock); |
| 2733 | return events; |
| 2734 | } |
| 2735 | |
| 2736 | /* Check if this is an automatically updatable view */ |
| 2737 | if (rel->rd_rel->relkind == RELKIND_VIEW) |
| 2738 | { |
| 2739 | Query *viewquery = get_view_query(rel); |
| 2740 | |
| 2741 | if (view_query_is_auto_updatable(viewquery, false) == NULL) |
| 2742 | { |
| 2743 | Bitmapset *updatable_cols; |
| 2744 | int auto_events; |
| 2745 | RangeTblRef *rtr; |
| 2746 | RangeTblEntry *base_rte; |
| 2747 | Oid baseoid; |
| 2748 | |
| 2749 | /* |
| 2750 | * Determine which of the view's columns are updatable. If there |
| 2751 | * are none within the set of columns we are looking at, then the |
| 2752 | * view doesn't support INSERT/UPDATE, but it may still support |
| 2753 | * DELETE. |
| 2754 | */ |
| 2755 | view_cols_are_auto_updatable(viewquery, NULL, |
| 2756 | &updatable_cols, NULL); |
| 2757 | |
| 2758 | if (include_cols != NULL) |
| 2759 | updatable_cols = bms_int_members(updatable_cols, include_cols); |
| 2760 | |
| 2761 | if (bms_is_empty(updatable_cols)) |
| 2762 | auto_events = (1 << CMD_DELETE); /* May support DELETE */ |
| 2763 | else |
| 2764 | auto_events = ALL_EVENTS; /* May support all events */ |
| 2765 | |
| 2766 | /* |
| 2767 | * The base relation must also support these update commands. |
| 2768 | * Tables are always updatable, but for any other kind of base |
| 2769 | * relation we must do a recursive check limited to the columns |
| 2770 | * referenced by the locally updatable columns in this view. |
| 2771 | */ |
| 2772 | rtr = (RangeTblRef *) linitial(viewquery->jointree->fromlist); |
| 2773 | base_rte = rt_fetch(rtr->rtindex, viewquery->rtable); |
| 2774 | Assert(base_rte->rtekind == RTE_RELATION); |
| 2775 | |
| 2776 | if (base_rte->relkind != RELKIND_RELATION && |
| 2777 | base_rte->relkind != RELKIND_PARTITIONED_TABLE) |
| 2778 | { |
| 2779 | baseoid = base_rte->relid; |
| 2780 | include_cols = adjust_view_column_set(updatable_cols, |
| 2781 | viewquery->targetList); |
| 2782 | auto_events &= relation_is_updatable(baseoid, |
| 2783 | include_triggers, |
| 2784 | include_cols); |
| 2785 | } |
| 2786 | events |= auto_events; |
| 2787 | } |
| 2788 | } |
| 2789 | |
| 2790 | /* If we reach here, the relation may support some update commands */ |
| 2791 | relation_close(rel, AccessShareLock); |
| 2792 | return events; |
| 2793 | } |
| 2794 | |
| 2795 | |
| 2796 | /* |
| 2797 | * adjust_view_column_set - map a set of column numbers according to targetlist |
| 2798 | * |
| 2799 | * This is used with simply-updatable views to map column-permissions sets for |
| 2800 | * the view columns onto the matching columns in the underlying base relation. |
| 2801 | * The targetlist is expected to be a list of plain Vars of the underlying |
| 2802 | * relation (as per the checks above in view_query_is_auto_updatable). |
| 2803 | */ |
| 2804 | static Bitmapset * |
| 2805 | adjust_view_column_set(Bitmapset *cols, List *targetlist) |
| 2806 | { |
| 2807 | Bitmapset *result = NULL; |
| 2808 | int col; |
| 2809 | |
| 2810 | col = -1; |
| 2811 | while ((col = bms_next_member(cols, col)) >= 0) |
| 2812 | { |
| 2813 | /* bit numbers are offset by FirstLowInvalidHeapAttributeNumber */ |
| 2814 | AttrNumber attno = col + FirstLowInvalidHeapAttributeNumber; |
| 2815 | |
| 2816 | if (attno == InvalidAttrNumber) |
| 2817 | { |
| 2818 | /* |
| 2819 | * There's a whole-row reference to the view. For permissions |
| 2820 | * purposes, treat it as a reference to each column available from |
| 2821 | * the view. (We should *not* convert this to a whole-row |
| 2822 | * reference to the base relation, since the view may not touch |
| 2823 | * all columns of the base relation.) |
| 2824 | */ |
| 2825 | ListCell *lc; |
| 2826 | |
| 2827 | foreach(lc, targetlist) |
| 2828 | { |
| 2829 | TargetEntry *tle = lfirst_node(TargetEntry, lc); |
| 2830 | Var *var; |
| 2831 | |
| 2832 | if (tle->resjunk) |
| 2833 | continue; |
| 2834 | var = castNode(Var, tle->expr); |
| 2835 | result = bms_add_member(result, |
| 2836 | var->varattno - FirstLowInvalidHeapAttributeNumber); |
| 2837 | } |
| 2838 | } |
| 2839 | else |
| 2840 | { |
| 2841 | /* |
| 2842 | * Views do not have system columns, so we do not expect to see |
| 2843 | * any other system attnos here. If we do find one, the error |
| 2844 | * case will apply. |
| 2845 | */ |
| 2846 | TargetEntry *tle = get_tle_by_resno(targetlist, attno); |
| 2847 | |
| 2848 | if (tle != NULL && !tle->resjunk && IsA(tle->expr, Var)) |
| 2849 | { |
| 2850 | Var *var = (Var *) tle->expr; |
| 2851 | |
| 2852 | result = bms_add_member(result, |
| 2853 | var->varattno - FirstLowInvalidHeapAttributeNumber); |
| 2854 | } |
| 2855 | else |
| 2856 | elog(ERROR, "attribute number %d not found in view targetlist" , |
| 2857 | attno); |
| 2858 | } |
| 2859 | } |
| 2860 | |
| 2861 | return result; |
| 2862 | } |
| 2863 | |
| 2864 | |
| 2865 | /* |
| 2866 | * rewriteTargetView - |
| 2867 | * Attempt to rewrite a query where the target relation is a view, so that |
| 2868 | * the view's base relation becomes the target relation. |
| 2869 | * |
| 2870 | * Note that the base relation here may itself be a view, which may or may not |
| 2871 | * have INSTEAD OF triggers or rules to handle the update. That is handled by |
| 2872 | * the recursion in RewriteQuery. |
| 2873 | */ |
| 2874 | static Query * |
| 2875 | rewriteTargetView(Query *parsetree, Relation view) |
| 2876 | { |
| 2877 | Query *viewquery; |
| 2878 | const char *auto_update_detail; |
| 2879 | RangeTblRef *rtr; |
| 2880 | int base_rt_index; |
| 2881 | int new_rt_index; |
| 2882 | RangeTblEntry *base_rte; |
| 2883 | RangeTblEntry *view_rte; |
| 2884 | RangeTblEntry *new_rte; |
| 2885 | Relation base_rel; |
| 2886 | List *view_targetlist; |
| 2887 | ListCell *lc; |
| 2888 | |
| 2889 | /* |
| 2890 | * Get the Query from the view's ON SELECT rule. We're going to munge the |
| 2891 | * Query to change the view's base relation into the target relation, |
| 2892 | * along with various other changes along the way, so we need to make a |
| 2893 | * copy of it (get_view_query() returns a pointer into the relcache, so we |
| 2894 | * have to treat it as read-only). |
| 2895 | */ |
| 2896 | viewquery = copyObject(get_view_query(view)); |
| 2897 | |
| 2898 | /* The view must be updatable, else fail */ |
| 2899 | auto_update_detail = |
| 2900 | view_query_is_auto_updatable(viewquery, |
| 2901 | parsetree->commandType != CMD_DELETE); |
| 2902 | |
| 2903 | if (auto_update_detail) |
| 2904 | { |
| 2905 | /* messages here should match execMain.c's CheckValidResultRel */ |
| 2906 | switch (parsetree->commandType) |
| 2907 | { |
| 2908 | case CMD_INSERT: |
| 2909 | ereport(ERROR, |
| 2910 | (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
| 2911 | errmsg("cannot insert into view \"%s\"" , |
| 2912 | RelationGetRelationName(view)), |
| 2913 | errdetail_internal("%s" , _(auto_update_detail)), |
| 2914 | errhint("To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule." ))); |
| 2915 | break; |
| 2916 | case CMD_UPDATE: |
| 2917 | ereport(ERROR, |
| 2918 | (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
| 2919 | errmsg("cannot update view \"%s\"" , |
| 2920 | RelationGetRelationName(view)), |
| 2921 | errdetail_internal("%s" , _(auto_update_detail)), |
| 2922 | errhint("To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule." ))); |
| 2923 | break; |
| 2924 | case CMD_DELETE: |
| 2925 | ereport(ERROR, |
| 2926 | (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
| 2927 | errmsg("cannot delete from view \"%s\"" , |
| 2928 | RelationGetRelationName(view)), |
| 2929 | errdetail_internal("%s" , _(auto_update_detail)), |
| 2930 | errhint("To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule." ))); |
| 2931 | break; |
| 2932 | default: |
| 2933 | elog(ERROR, "unrecognized CmdType: %d" , |
| 2934 | (int) parsetree->commandType); |
| 2935 | break; |
| 2936 | } |
| 2937 | } |
| 2938 | |
| 2939 | /* |
| 2940 | * For INSERT/UPDATE the modified columns must all be updatable. Note that |
| 2941 | * we get the modified columns from the query's targetlist, not from the |
| 2942 | * result RTE's insertedCols and/or updatedCols set, since |
| 2943 | * rewriteTargetListIU may have added additional targetlist entries for |
| 2944 | * view defaults, and these must also be updatable. |
| 2945 | */ |
| 2946 | if (parsetree->commandType != CMD_DELETE) |
| 2947 | { |
| 2948 | Bitmapset *modified_cols = NULL; |
| 2949 | char *non_updatable_col; |
| 2950 | |
| 2951 | foreach(lc, parsetree->targetList) |
| 2952 | { |
| 2953 | TargetEntry *tle = (TargetEntry *) lfirst(lc); |
| 2954 | |
| 2955 | if (!tle->resjunk) |
| 2956 | modified_cols = bms_add_member(modified_cols, |
| 2957 | tle->resno - FirstLowInvalidHeapAttributeNumber); |
| 2958 | } |
| 2959 | |
| 2960 | if (parsetree->onConflict) |
| 2961 | { |
| 2962 | foreach(lc, parsetree->onConflict->onConflictSet) |
| 2963 | { |
| 2964 | TargetEntry *tle = (TargetEntry *) lfirst(lc); |
| 2965 | |
| 2966 | if (!tle->resjunk) |
| 2967 | modified_cols = bms_add_member(modified_cols, |
| 2968 | tle->resno - FirstLowInvalidHeapAttributeNumber); |
| 2969 | } |
| 2970 | } |
| 2971 | |
| 2972 | auto_update_detail = view_cols_are_auto_updatable(viewquery, |
| 2973 | modified_cols, |
| 2974 | NULL, |
| 2975 | &non_updatable_col); |
| 2976 | if (auto_update_detail) |
| 2977 | { |
| 2978 | /* |
| 2979 | * This is a different error, caused by an attempt to update a |
| 2980 | * non-updatable column in an otherwise updatable view. |
| 2981 | */ |
| 2982 | switch (parsetree->commandType) |
| 2983 | { |
| 2984 | case CMD_INSERT: |
| 2985 | ereport(ERROR, |
| 2986 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 2987 | errmsg("cannot insert into column \"%s\" of view \"%s\"" , |
| 2988 | non_updatable_col, |
| 2989 | RelationGetRelationName(view)), |
| 2990 | errdetail_internal("%s" , _(auto_update_detail)))); |
| 2991 | break; |
| 2992 | case CMD_UPDATE: |
| 2993 | ereport(ERROR, |
| 2994 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 2995 | errmsg("cannot update column \"%s\" of view \"%s\"" , |
| 2996 | non_updatable_col, |
| 2997 | RelationGetRelationName(view)), |
| 2998 | errdetail_internal("%s" , _(auto_update_detail)))); |
| 2999 | break; |
| 3000 | default: |
| 3001 | elog(ERROR, "unrecognized CmdType: %d" , |
| 3002 | (int) parsetree->commandType); |
| 3003 | break; |
| 3004 | } |
| 3005 | } |
| 3006 | } |
| 3007 | |
| 3008 | /* Locate RTE describing the view in the outer query */ |
| 3009 | view_rte = rt_fetch(parsetree->resultRelation, parsetree->rtable); |
| 3010 | |
| 3011 | /* |
| 3012 | * If we get here, view_query_is_auto_updatable() has verified that the |
| 3013 | * view contains a single base relation. |
| 3014 | */ |
| 3015 | Assert(list_length(viewquery->jointree->fromlist) == 1); |
| 3016 | rtr = linitial_node(RangeTblRef, viewquery->jointree->fromlist); |
| 3017 | |
| 3018 | base_rt_index = rtr->rtindex; |
| 3019 | base_rte = rt_fetch(base_rt_index, viewquery->rtable); |
| 3020 | Assert(base_rte->rtekind == RTE_RELATION); |
| 3021 | |
| 3022 | /* |
| 3023 | * Up to now, the base relation hasn't been touched at all in our query. |
| 3024 | * We need to acquire lock on it before we try to do anything with it. |
| 3025 | * (The subsequent recursive call of RewriteQuery will suppose that we |
| 3026 | * already have the right lock!) Since it will become the query target |
| 3027 | * relation, RowExclusiveLock is always the right thing. |
| 3028 | */ |
| 3029 | base_rel = table_open(base_rte->relid, RowExclusiveLock); |
| 3030 | |
| 3031 | /* |
| 3032 | * While we have the relation open, update the RTE's relkind, just in case |
| 3033 | * it changed since this view was made (cf. AcquireRewriteLocks). |
| 3034 | */ |
| 3035 | base_rte->relkind = base_rel->rd_rel->relkind; |
| 3036 | |
| 3037 | /* |
| 3038 | * If the view query contains any sublink subqueries then we need to also |
| 3039 | * acquire locks on any relations they refer to. We know that there won't |
| 3040 | * be any subqueries in the range table or CTEs, so we can skip those, as |
| 3041 | * in AcquireRewriteLocks. |
| 3042 | */ |
| 3043 | if (viewquery->hasSubLinks) |
| 3044 | { |
| 3045 | acquireLocksOnSubLinks_context context; |
| 3046 | |
| 3047 | context.for_execute = true; |
| 3048 | query_tree_walker(viewquery, acquireLocksOnSubLinks, &context, |
| 3049 | QTW_IGNORE_RC_SUBQUERIES); |
| 3050 | } |
| 3051 | |
| 3052 | /* |
| 3053 | * Create a new target RTE describing the base relation, and add it to the |
| 3054 | * outer query's rangetable. (What's happening in the next few steps is |
| 3055 | * very much like what the planner would do to "pull up" the view into the |
| 3056 | * outer query. Perhaps someday we should refactor things enough so that |
| 3057 | * we can share code with the planner.) |
| 3058 | * |
| 3059 | * Be sure to set rellockmode to the correct thing for the target table. |
| 3060 | * Since we copied the whole viewquery above, we can just scribble on |
| 3061 | * base_rte instead of copying it. |
| 3062 | */ |
| 3063 | new_rte = base_rte; |
| 3064 | new_rte->rellockmode = RowExclusiveLock; |
| 3065 | |
| 3066 | parsetree->rtable = lappend(parsetree->rtable, new_rte); |
| 3067 | new_rt_index = list_length(parsetree->rtable); |
| 3068 | |
| 3069 | /* |
| 3070 | * INSERTs never inherit. For UPDATE/DELETE, we use the view query's |
| 3071 | * inheritance flag for the base relation. |
| 3072 | */ |
| 3073 | if (parsetree->commandType == CMD_INSERT) |
| 3074 | new_rte->inh = false; |
| 3075 | |
| 3076 | /* |
| 3077 | * Adjust the view's targetlist Vars to reference the new target RTE, ie |
| 3078 | * make their varnos be new_rt_index instead of base_rt_index. There can |
| 3079 | * be no Vars for other rels in the tlist, so this is sufficient to pull |
| 3080 | * up the tlist expressions for use in the outer query. The tlist will |
| 3081 | * provide the replacement expressions used by ReplaceVarsFromTargetList |
| 3082 | * below. |
| 3083 | */ |
| 3084 | view_targetlist = viewquery->targetList; |
| 3085 | |
| 3086 | ChangeVarNodes((Node *) view_targetlist, |
| 3087 | base_rt_index, |
| 3088 | new_rt_index, |
| 3089 | 0); |
| 3090 | |
| 3091 | /* |
| 3092 | * Mark the new target RTE for the permissions checks that we want to |
| 3093 | * enforce against the view owner, as distinct from the query caller. At |
| 3094 | * the relation level, require the same INSERT/UPDATE/DELETE permissions |
| 3095 | * that the query caller needs against the view. We drop the ACL_SELECT |
| 3096 | * bit that is presumably in new_rte->requiredPerms initially. |
| 3097 | * |
| 3098 | * Note: the original view RTE remains in the query's rangetable list. |
| 3099 | * Although it will be unused in the query plan, we need it there so that |
| 3100 | * the executor still performs appropriate permissions checks for the |
| 3101 | * query caller's use of the view. |
| 3102 | */ |
| 3103 | new_rte->checkAsUser = view->rd_rel->relowner; |
| 3104 | new_rte->requiredPerms = view_rte->requiredPerms; |
| 3105 | |
| 3106 | /* |
| 3107 | * Now for the per-column permissions bits. |
| 3108 | * |
| 3109 | * Initially, new_rte contains selectedCols permission check bits for all |
| 3110 | * base-rel columns referenced by the view, but since the view is a SELECT |
| 3111 | * query its insertedCols/updatedCols is empty. We set insertedCols and |
| 3112 | * updatedCols to include all the columns the outer query is trying to |
| 3113 | * modify, adjusting the column numbers as needed. But we leave |
| 3114 | * selectedCols as-is, so the view owner must have read permission for all |
| 3115 | * columns used in the view definition, even if some of them are not read |
| 3116 | * by the outer query. We could try to limit selectedCols to only columns |
| 3117 | * used in the transformed query, but that does not correspond to what |
| 3118 | * happens in ordinary SELECT usage of a view: all referenced columns must |
| 3119 | * have read permission, even if optimization finds that some of them can |
| 3120 | * be discarded during query transformation. The flattening we're doing |
| 3121 | * here is an optional optimization, too. (If you are unpersuaded and |
| 3122 | * want to change this, note that applying adjust_view_column_set to |
| 3123 | * view_rte->selectedCols is clearly *not* the right answer, since that |
| 3124 | * neglects base-rel columns used in the view's WHERE quals.) |
| 3125 | * |
| 3126 | * This step needs the modified view targetlist, so we have to do things |
| 3127 | * in this order. |
| 3128 | */ |
| 3129 | Assert(bms_is_empty(new_rte->insertedCols) && |
| 3130 | bms_is_empty(new_rte->updatedCols)); |
| 3131 | |
| 3132 | new_rte->insertedCols = adjust_view_column_set(view_rte->insertedCols, |
| 3133 | view_targetlist); |
| 3134 | |
| 3135 | new_rte->updatedCols = adjust_view_column_set(view_rte->updatedCols, |
| 3136 | view_targetlist); |
| 3137 | |
| 3138 | /* |
| 3139 | * Move any security barrier quals from the view RTE onto the new target |
| 3140 | * RTE. Any such quals should now apply to the new target RTE and will |
| 3141 | * not reference the original view RTE in the rewritten query. |
| 3142 | */ |
| 3143 | new_rte->securityQuals = view_rte->securityQuals; |
| 3144 | view_rte->securityQuals = NIL; |
| 3145 | |
| 3146 | /* |
| 3147 | * Now update all Vars in the outer query that reference the view to |
| 3148 | * reference the appropriate column of the base relation instead. |
| 3149 | */ |
| 3150 | parsetree = (Query *) |
| 3151 | ReplaceVarsFromTargetList((Node *) parsetree, |
| 3152 | parsetree->resultRelation, |
| 3153 | 0, |
| 3154 | view_rte, |
| 3155 | view_targetlist, |
| 3156 | REPLACEVARS_REPORT_ERROR, |
| 3157 | 0, |
| 3158 | &parsetree->hasSubLinks); |
| 3159 | |
| 3160 | /* |
| 3161 | * Update all other RTI references in the query that point to the view |
| 3162 | * (for example, parsetree->resultRelation itself) to point to the new |
| 3163 | * base relation instead. Vars will not be affected since none of them |
| 3164 | * reference parsetree->resultRelation any longer. |
| 3165 | */ |
| 3166 | ChangeVarNodes((Node *) parsetree, |
| 3167 | parsetree->resultRelation, |
| 3168 | new_rt_index, |
| 3169 | 0); |
| 3170 | Assert(parsetree->resultRelation == new_rt_index); |
| 3171 | |
| 3172 | /* |
| 3173 | * For INSERT/UPDATE we must also update resnos in the targetlist to refer |
| 3174 | * to columns of the base relation, since those indicate the target |
| 3175 | * columns to be affected. |
| 3176 | * |
| 3177 | * Note that this destroys the resno ordering of the targetlist, but that |
| 3178 | * will be fixed when we recurse through rewriteQuery, which will invoke |
| 3179 | * rewriteTargetListIU again on the updated targetlist. |
| 3180 | */ |
| 3181 | if (parsetree->commandType != CMD_DELETE) |
| 3182 | { |
| 3183 | foreach(lc, parsetree->targetList) |
| 3184 | { |
| 3185 | TargetEntry *tle = (TargetEntry *) lfirst(lc); |
| 3186 | TargetEntry *view_tle; |
| 3187 | |
| 3188 | if (tle->resjunk) |
| 3189 | continue; |
| 3190 | |
| 3191 | view_tle = get_tle_by_resno(view_targetlist, tle->resno); |
| 3192 | if (view_tle != NULL && !view_tle->resjunk && IsA(view_tle->expr, Var)) |
| 3193 | tle->resno = ((Var *) view_tle->expr)->varattno; |
| 3194 | else |
| 3195 | elog(ERROR, "attribute number %d not found in view targetlist" , |
| 3196 | tle->resno); |
| 3197 | } |
| 3198 | } |
| 3199 | |
| 3200 | /* |
| 3201 | * For INSERT .. ON CONFLICT .. DO UPDATE, we must also update assorted |
| 3202 | * stuff in the onConflict data structure. |
| 3203 | */ |
| 3204 | if (parsetree->onConflict && |
| 3205 | parsetree->onConflict->action == ONCONFLICT_UPDATE) |
| 3206 | { |
| 3207 | Index old_exclRelIndex, |
| 3208 | new_exclRelIndex; |
| 3209 | RangeTblEntry *new_exclRte; |
| 3210 | List *tmp_tlist; |
| 3211 | |
| 3212 | /* |
| 3213 | * Like the INSERT/UPDATE code above, update the resnos in the |
| 3214 | * auxiliary UPDATE targetlist to refer to columns of the base |
| 3215 | * relation. |
| 3216 | */ |
| 3217 | foreach(lc, parsetree->onConflict->onConflictSet) |
| 3218 | { |
| 3219 | TargetEntry *tle = (TargetEntry *) lfirst(lc); |
| 3220 | TargetEntry *view_tle; |
| 3221 | |
| 3222 | if (tle->resjunk) |
| 3223 | continue; |
| 3224 | |
| 3225 | view_tle = get_tle_by_resno(view_targetlist, tle->resno); |
| 3226 | if (view_tle != NULL && !view_tle->resjunk && IsA(view_tle->expr, Var)) |
| 3227 | tle->resno = ((Var *) view_tle->expr)->varattno; |
| 3228 | else |
| 3229 | elog(ERROR, "attribute number %d not found in view targetlist" , |
| 3230 | tle->resno); |
| 3231 | } |
| 3232 | |
| 3233 | /* |
| 3234 | * Also, create a new RTE for the EXCLUDED pseudo-relation, using the |
| 3235 | * query's new base rel (which may well have a different column list |
| 3236 | * from the view, hence we need a new column alias list). This should |
| 3237 | * match transformOnConflictClause. In particular, note that the |
| 3238 | * relkind is set to composite to signal that we're not dealing with |
| 3239 | * an actual relation, and no permissions checks are wanted. |
| 3240 | */ |
| 3241 | old_exclRelIndex = parsetree->onConflict->exclRelIndex; |
| 3242 | |
| 3243 | new_exclRte = addRangeTableEntryForRelation(make_parsestate(NULL), |
| 3244 | base_rel, |
| 3245 | RowExclusiveLock, |
| 3246 | makeAlias("excluded" , NIL), |
| 3247 | false, false); |
| 3248 | new_exclRte->relkind = RELKIND_COMPOSITE_TYPE; |
| 3249 | new_exclRte->requiredPerms = 0; |
| 3250 | /* other permissions fields in new_exclRte are already empty */ |
| 3251 | |
| 3252 | parsetree->rtable = lappend(parsetree->rtable, new_exclRte); |
| 3253 | new_exclRelIndex = parsetree->onConflict->exclRelIndex = |
| 3254 | list_length(parsetree->rtable); |
| 3255 | |
| 3256 | /* |
| 3257 | * Replace the targetlist for the EXCLUDED pseudo-relation with a new |
| 3258 | * one, representing the columns from the new base relation. |
| 3259 | */ |
| 3260 | parsetree->onConflict->exclRelTlist = |
| 3261 | BuildOnConflictExcludedTargetlist(base_rel, new_exclRelIndex); |
| 3262 | |
| 3263 | /* |
| 3264 | * Update all Vars in the ON CONFLICT clause that refer to the old |
| 3265 | * EXCLUDED pseudo-relation. We want to use the column mappings |
| 3266 | * defined in the view targetlist, but we need the outputs to refer to |
| 3267 | * the new EXCLUDED pseudo-relation rather than the new target RTE. |
| 3268 | * Also notice that "EXCLUDED.*" will be expanded using the view's |
| 3269 | * rowtype, which seems correct. |
| 3270 | */ |
| 3271 | tmp_tlist = copyObject(view_targetlist); |
| 3272 | |
| 3273 | ChangeVarNodes((Node *) tmp_tlist, new_rt_index, |
| 3274 | new_exclRelIndex, 0); |
| 3275 | |
| 3276 | parsetree->onConflict = (OnConflictExpr *) |
| 3277 | ReplaceVarsFromTargetList((Node *) parsetree->onConflict, |
| 3278 | old_exclRelIndex, |
| 3279 | 0, |
| 3280 | view_rte, |
| 3281 | tmp_tlist, |
| 3282 | REPLACEVARS_REPORT_ERROR, |
| 3283 | 0, |
| 3284 | &parsetree->hasSubLinks); |
| 3285 | } |
| 3286 | |
| 3287 | /* |
| 3288 | * For UPDATE/DELETE, pull up any WHERE quals from the view. We know that |
| 3289 | * any Vars in the quals must reference the one base relation, so we need |
| 3290 | * only adjust their varnos to reference the new target (just the same as |
| 3291 | * we did with the view targetlist). |
| 3292 | * |
| 3293 | * If it's a security-barrier view, its WHERE quals must be applied before |
| 3294 | * quals from the outer query, so we attach them to the RTE as security |
| 3295 | * barrier quals rather than adding them to the main WHERE clause. |
| 3296 | * |
| 3297 | * For INSERT, the view's quals can be ignored in the main query. |
| 3298 | */ |
| 3299 | if (parsetree->commandType != CMD_INSERT && |
| 3300 | viewquery->jointree->quals != NULL) |
| 3301 | { |
| 3302 | Node *viewqual = (Node *) viewquery->jointree->quals; |
| 3303 | |
| 3304 | /* |
| 3305 | * Even though we copied viewquery already at the top of this |
| 3306 | * function, we must duplicate the viewqual again here, because we may |
| 3307 | * need to use the quals again below for a WithCheckOption clause. |
| 3308 | */ |
| 3309 | viewqual = copyObject(viewqual); |
| 3310 | |
| 3311 | ChangeVarNodes(viewqual, base_rt_index, new_rt_index, 0); |
| 3312 | |
| 3313 | if (RelationIsSecurityView(view)) |
| 3314 | { |
| 3315 | /* |
| 3316 | * The view's quals go in front of existing barrier quals: those |
| 3317 | * would have come from an outer level of security-barrier view, |
| 3318 | * and so must get evaluated later. |
| 3319 | * |
| 3320 | * Note: the parsetree has been mutated, so the new_rte pointer is |
| 3321 | * stale and needs to be re-computed. |
| 3322 | */ |
| 3323 | new_rte = rt_fetch(new_rt_index, parsetree->rtable); |
| 3324 | new_rte->securityQuals = lcons(viewqual, new_rte->securityQuals); |
| 3325 | |
| 3326 | /* |
| 3327 | * Do not set parsetree->hasRowSecurity, because these aren't RLS |
| 3328 | * conditions (they aren't affected by enabling/disabling RLS). |
| 3329 | */ |
| 3330 | |
| 3331 | /* |
| 3332 | * Make sure that the query is marked correctly if the added qual |
| 3333 | * has sublinks. |
| 3334 | */ |
| 3335 | if (!parsetree->hasSubLinks) |
| 3336 | parsetree->hasSubLinks = checkExprHasSubLink(viewqual); |
| 3337 | } |
| 3338 | else |
| 3339 | AddQual(parsetree, (Node *) viewqual); |
| 3340 | } |
| 3341 | |
| 3342 | /* |
| 3343 | * For INSERT/UPDATE, if the view has the WITH CHECK OPTION, or any parent |
| 3344 | * view specified WITH CASCADED CHECK OPTION, add the quals from the view |
| 3345 | * to the query's withCheckOptions list. |
| 3346 | */ |
| 3347 | if (parsetree->commandType != CMD_DELETE) |
| 3348 | { |
| 3349 | bool has_wco = RelationHasCheckOption(view); |
| 3350 | bool cascaded = RelationHasCascadedCheckOption(view); |
| 3351 | |
| 3352 | /* |
| 3353 | * If the parent view has a cascaded check option, treat this view as |
| 3354 | * if it also had a cascaded check option. |
| 3355 | * |
| 3356 | * New WithCheckOptions are added to the start of the list, so if |
| 3357 | * there is a cascaded check option, it will be the first item in the |
| 3358 | * list. |
| 3359 | */ |
| 3360 | if (parsetree->withCheckOptions != NIL) |
| 3361 | { |
| 3362 | WithCheckOption *parent_wco = |
| 3363 | (WithCheckOption *) linitial(parsetree->withCheckOptions); |
| 3364 | |
| 3365 | if (parent_wco->cascaded) |
| 3366 | { |
| 3367 | has_wco = true; |
| 3368 | cascaded = true; |
| 3369 | } |
| 3370 | } |
| 3371 | |
| 3372 | /* |
| 3373 | * Add the new WithCheckOption to the start of the list, so that |
| 3374 | * checks on inner views are run before checks on outer views, as |
| 3375 | * required by the SQL standard. |
| 3376 | * |
| 3377 | * If the new check is CASCADED, we need to add it even if this view |
| 3378 | * has no quals, since there may be quals on child views. A LOCAL |
| 3379 | * check can be omitted if this view has no quals. |
| 3380 | */ |
| 3381 | if (has_wco && (cascaded || viewquery->jointree->quals != NULL)) |
| 3382 | { |
| 3383 | WithCheckOption *wco; |
| 3384 | |
| 3385 | wco = makeNode(WithCheckOption); |
| 3386 | wco->kind = WCO_VIEW_CHECK; |
| 3387 | wco->relname = pstrdup(RelationGetRelationName(view)); |
| 3388 | wco->polname = NULL; |
| 3389 | wco->qual = NULL; |
| 3390 | wco->cascaded = cascaded; |
| 3391 | |
| 3392 | parsetree->withCheckOptions = lcons(wco, |
| 3393 | parsetree->withCheckOptions); |
| 3394 | |
| 3395 | if (viewquery->jointree->quals != NULL) |
| 3396 | { |
| 3397 | wco->qual = (Node *) viewquery->jointree->quals; |
| 3398 | ChangeVarNodes(wco->qual, base_rt_index, new_rt_index, 0); |
| 3399 | |
| 3400 | /* |
| 3401 | * Make sure that the query is marked correctly if the added |
| 3402 | * qual has sublinks. We can skip this check if the query is |
| 3403 | * already marked, or if the command is an UPDATE, in which |
| 3404 | * case the same qual will have already been added, and this |
| 3405 | * check will already have been done. |
| 3406 | */ |
| 3407 | if (!parsetree->hasSubLinks && |
| 3408 | parsetree->commandType != CMD_UPDATE) |
| 3409 | parsetree->hasSubLinks = checkExprHasSubLink(wco->qual); |
| 3410 | } |
| 3411 | } |
| 3412 | } |
| 3413 | |
| 3414 | table_close(base_rel, NoLock); |
| 3415 | |
| 3416 | return parsetree; |
| 3417 | } |
| 3418 | |
| 3419 | |
| 3420 | /* |
| 3421 | * RewriteQuery - |
| 3422 | * rewrites the query and apply the rules again on the queries rewritten |
| 3423 | * |
| 3424 | * rewrite_events is a list of open query-rewrite actions, so we can detect |
| 3425 | * infinite recursion. |
| 3426 | */ |
| 3427 | static List * |
| 3428 | RewriteQuery(Query *parsetree, List *rewrite_events) |
| 3429 | { |
| 3430 | CmdType event = parsetree->commandType; |
| 3431 | bool instead = false; |
| 3432 | bool returning = false; |
| 3433 | bool updatableview = false; |
| 3434 | Query *qual_product = NULL; |
| 3435 | List *rewritten = NIL; |
| 3436 | ListCell *lc1; |
| 3437 | |
| 3438 | /* |
| 3439 | * First, recursively process any insert/update/delete statements in WITH |
| 3440 | * clauses. (We have to do this first because the WITH clauses may get |
| 3441 | * copied into rule actions below.) |
| 3442 | */ |
| 3443 | foreach(lc1, parsetree->cteList) |
| 3444 | { |
| 3445 | CommonTableExpr *cte = lfirst_node(CommonTableExpr, lc1); |
| 3446 | Query *ctequery = castNode(Query, cte->ctequery); |
| 3447 | List *newstuff; |
| 3448 | |
| 3449 | if (ctequery->commandType == CMD_SELECT) |
| 3450 | continue; |
| 3451 | |
| 3452 | newstuff = RewriteQuery(ctequery, rewrite_events); |
| 3453 | |
| 3454 | /* |
| 3455 | * Currently we can only handle unconditional, single-statement DO |
| 3456 | * INSTEAD rules correctly; we have to get exactly one Query out of |
| 3457 | * the rewrite operation to stuff back into the CTE node. |
| 3458 | */ |
| 3459 | if (list_length(newstuff) == 1) |
| 3460 | { |
| 3461 | /* Push the single Query back into the CTE node */ |
| 3462 | ctequery = linitial_node(Query, newstuff); |
| 3463 | /* WITH queries should never be canSetTag */ |
| 3464 | Assert(!ctequery->canSetTag); |
| 3465 | cte->ctequery = (Node *) ctequery; |
| 3466 | } |
| 3467 | else if (newstuff == NIL) |
| 3468 | { |
| 3469 | ereport(ERROR, |
| 3470 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 3471 | errmsg("DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH" ))); |
| 3472 | } |
| 3473 | else |
| 3474 | { |
| 3475 | ListCell *lc2; |
| 3476 | |
| 3477 | /* examine queries to determine which error message to issue */ |
| 3478 | foreach(lc2, newstuff) |
| 3479 | { |
| 3480 | Query *q = (Query *) lfirst(lc2); |
| 3481 | |
| 3482 | if (q->querySource == QSRC_QUAL_INSTEAD_RULE) |
| 3483 | ereport(ERROR, |
| 3484 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 3485 | errmsg("conditional DO INSTEAD rules are not supported for data-modifying statements in WITH" ))); |
| 3486 | if (q->querySource == QSRC_NON_INSTEAD_RULE) |
| 3487 | ereport(ERROR, |
| 3488 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 3489 | errmsg("DO ALSO rules are not supported for data-modifying statements in WITH" ))); |
| 3490 | } |
| 3491 | |
| 3492 | ereport(ERROR, |
| 3493 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 3494 | errmsg("multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH" ))); |
| 3495 | } |
| 3496 | } |
| 3497 | |
| 3498 | /* |
| 3499 | * If the statement is an insert, update, or delete, adjust its targetlist |
| 3500 | * as needed, and then fire INSERT/UPDATE/DELETE rules on it. |
| 3501 | * |
| 3502 | * SELECT rules are handled later when we have all the queries that should |
| 3503 | * get executed. Also, utilities aren't rewritten at all (do we still |
| 3504 | * need that check?) |
| 3505 | */ |
| 3506 | if (event != CMD_SELECT && event != CMD_UTILITY) |
| 3507 | { |
| 3508 | int result_relation; |
| 3509 | RangeTblEntry *rt_entry; |
| 3510 | Relation rt_entry_relation; |
| 3511 | List *locks; |
| 3512 | List *product_queries; |
| 3513 | bool hasUpdate = false; |
| 3514 | int values_rte_index = 0; |
| 3515 | bool defaults_remaining = false; |
| 3516 | |
| 3517 | result_relation = parsetree->resultRelation; |
| 3518 | Assert(result_relation != 0); |
| 3519 | rt_entry = rt_fetch(result_relation, parsetree->rtable); |
| 3520 | Assert(rt_entry->rtekind == RTE_RELATION); |
| 3521 | |
| 3522 | /* |
| 3523 | * We can use NoLock here since either the parser or |
| 3524 | * AcquireRewriteLocks should have locked the rel already. |
| 3525 | */ |
| 3526 | rt_entry_relation = table_open(rt_entry->relid, NoLock); |
| 3527 | |
| 3528 | /* |
| 3529 | * Rewrite the targetlist as needed for the command type. |
| 3530 | */ |
| 3531 | if (event == CMD_INSERT) |
| 3532 | { |
| 3533 | RangeTblEntry *values_rte = NULL; |
| 3534 | |
| 3535 | /* |
| 3536 | * If it's an INSERT ... VALUES (...), (...), ... there will be a |
| 3537 | * single RTE for the VALUES targetlists. |
| 3538 | */ |
| 3539 | if (list_length(parsetree->jointree->fromlist) == 1) |
| 3540 | { |
| 3541 | RangeTblRef *rtr = (RangeTblRef *) linitial(parsetree->jointree->fromlist); |
| 3542 | |
| 3543 | if (IsA(rtr, RangeTblRef)) |
| 3544 | { |
| 3545 | RangeTblEntry *rte = rt_fetch(rtr->rtindex, |
| 3546 | parsetree->rtable); |
| 3547 | |
| 3548 | if (rte->rtekind == RTE_VALUES) |
| 3549 | { |
| 3550 | values_rte = rte; |
| 3551 | values_rte_index = rtr->rtindex; |
| 3552 | } |
| 3553 | } |
| 3554 | } |
| 3555 | |
| 3556 | if (values_rte) |
| 3557 | { |
| 3558 | /* Process the main targetlist ... */ |
| 3559 | parsetree->targetList = rewriteTargetListIU(parsetree->targetList, |
| 3560 | parsetree->commandType, |
| 3561 | parsetree->override, |
| 3562 | rt_entry_relation, |
| 3563 | parsetree->resultRelation); |
| 3564 | /* ... and the VALUES expression lists */ |
| 3565 | if (!rewriteValuesRTE(parsetree, values_rte, values_rte_index, |
| 3566 | rt_entry_relation, false)) |
| 3567 | defaults_remaining = true; |
| 3568 | } |
| 3569 | else |
| 3570 | { |
| 3571 | /* Process just the main targetlist */ |
| 3572 | parsetree->targetList = |
| 3573 | rewriteTargetListIU(parsetree->targetList, |
| 3574 | parsetree->commandType, |
| 3575 | parsetree->override, |
| 3576 | rt_entry_relation, |
| 3577 | parsetree->resultRelation); |
| 3578 | } |
| 3579 | |
| 3580 | if (parsetree->onConflict && |
| 3581 | parsetree->onConflict->action == ONCONFLICT_UPDATE) |
| 3582 | { |
| 3583 | parsetree->onConflict->onConflictSet = |
| 3584 | rewriteTargetListIU(parsetree->onConflict->onConflictSet, |
| 3585 | CMD_UPDATE, |
| 3586 | parsetree->override, |
| 3587 | rt_entry_relation, |
| 3588 | parsetree->resultRelation); |
| 3589 | } |
| 3590 | } |
| 3591 | else if (event == CMD_UPDATE) |
| 3592 | { |
| 3593 | parsetree->targetList = |
| 3594 | rewriteTargetListIU(parsetree->targetList, |
| 3595 | parsetree->commandType, |
| 3596 | parsetree->override, |
| 3597 | rt_entry_relation, |
| 3598 | parsetree->resultRelation); |
| 3599 | } |
| 3600 | else if (event == CMD_DELETE) |
| 3601 | { |
| 3602 | /* Nothing to do here */ |
| 3603 | } |
| 3604 | else |
| 3605 | elog(ERROR, "unrecognized commandType: %d" , (int) event); |
| 3606 | |
| 3607 | /* |
| 3608 | * Collect and apply the appropriate rules. |
| 3609 | */ |
| 3610 | locks = matchLocks(event, rt_entry_relation->rd_rules, |
| 3611 | result_relation, parsetree, &hasUpdate); |
| 3612 | |
| 3613 | product_queries = fireRules(parsetree, |
| 3614 | result_relation, |
| 3615 | event, |
| 3616 | locks, |
| 3617 | &instead, |
| 3618 | &returning, |
| 3619 | &qual_product); |
| 3620 | |
| 3621 | /* |
| 3622 | * If we have a VALUES RTE with any remaining untouched DEFAULT items, |
| 3623 | * and we got any product queries, finalize the VALUES RTE for each |
| 3624 | * product query (replacing the remaining DEFAULT items with NULLs). |
| 3625 | * We don't do this for the original query, because we know that it |
| 3626 | * must be an auto-insert on a view, and so should use the base |
| 3627 | * relation's defaults for any remaining DEFAULT items. |
| 3628 | */ |
| 3629 | if (defaults_remaining && product_queries != NIL) |
| 3630 | { |
| 3631 | ListCell *n; |
| 3632 | |
| 3633 | /* |
| 3634 | * Each product query has its own copy of the VALUES RTE at the |
| 3635 | * same index in the rangetable, so we must finalize each one. |
| 3636 | */ |
| 3637 | foreach(n, product_queries) |
| 3638 | { |
| 3639 | Query *pt = (Query *) lfirst(n); |
| 3640 | RangeTblEntry *values_rte = rt_fetch(values_rte_index, |
| 3641 | pt->rtable); |
| 3642 | |
| 3643 | rewriteValuesRTE(pt, values_rte, values_rte_index, |
| 3644 | rt_entry_relation, |
| 3645 | true); /* Force remaining defaults to NULL */ |
| 3646 | } |
| 3647 | } |
| 3648 | |
| 3649 | /* |
| 3650 | * If there were no INSTEAD rules, and the target relation is a view |
| 3651 | * without any INSTEAD OF triggers, see if the view can be |
| 3652 | * automatically updated. If so, we perform the necessary query |
| 3653 | * transformation here and add the resulting query to the |
| 3654 | * product_queries list, so that it gets recursively rewritten if |
| 3655 | * necessary. |
| 3656 | */ |
| 3657 | if (!instead && qual_product == NULL && |
| 3658 | rt_entry_relation->rd_rel->relkind == RELKIND_VIEW && |
| 3659 | !view_has_instead_trigger(rt_entry_relation, event)) |
| 3660 | { |
| 3661 | /* |
| 3662 | * This throws an error if the view can't be automatically |
| 3663 | * updated, but that's OK since the query would fail at runtime |
| 3664 | * anyway. |
| 3665 | */ |
| 3666 | parsetree = rewriteTargetView(parsetree, rt_entry_relation); |
| 3667 | |
| 3668 | /* |
| 3669 | * At this point product_queries contains any DO ALSO rule |
| 3670 | * actions. Add the rewritten query before or after those. This |
| 3671 | * must match the handling the original query would have gotten |
| 3672 | * below, if we allowed it to be included again. |
| 3673 | */ |
| 3674 | if (parsetree->commandType == CMD_INSERT) |
| 3675 | product_queries = lcons(parsetree, product_queries); |
| 3676 | else |
| 3677 | product_queries = lappend(product_queries, parsetree); |
| 3678 | |
| 3679 | /* |
| 3680 | * Set the "instead" flag, as if there had been an unqualified |
| 3681 | * INSTEAD, to prevent the original query from being included a |
| 3682 | * second time below. The transformation will have rewritten any |
| 3683 | * RETURNING list, so we can also set "returning" to forestall |
| 3684 | * throwing an error below. |
| 3685 | */ |
| 3686 | instead = true; |
| 3687 | returning = true; |
| 3688 | updatableview = true; |
| 3689 | } |
| 3690 | |
| 3691 | /* |
| 3692 | * If we got any product queries, recursively rewrite them --- but |
| 3693 | * first check for recursion! |
| 3694 | */ |
| 3695 | if (product_queries != NIL) |
| 3696 | { |
| 3697 | ListCell *n; |
| 3698 | rewrite_event *rev; |
| 3699 | |
| 3700 | foreach(n, rewrite_events) |
| 3701 | { |
| 3702 | rev = (rewrite_event *) lfirst(n); |
| 3703 | if (rev->relation == RelationGetRelid(rt_entry_relation) && |
| 3704 | rev->event == event) |
| 3705 | ereport(ERROR, |
| 3706 | (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), |
| 3707 | errmsg("infinite recursion detected in rules for relation \"%s\"" , |
| 3708 | RelationGetRelationName(rt_entry_relation)))); |
| 3709 | } |
| 3710 | |
| 3711 | rev = (rewrite_event *) palloc(sizeof(rewrite_event)); |
| 3712 | rev->relation = RelationGetRelid(rt_entry_relation); |
| 3713 | rev->event = event; |
| 3714 | rewrite_events = lcons(rev, rewrite_events); |
| 3715 | |
| 3716 | foreach(n, product_queries) |
| 3717 | { |
| 3718 | Query *pt = (Query *) lfirst(n); |
| 3719 | List *newstuff; |
| 3720 | |
| 3721 | newstuff = RewriteQuery(pt, rewrite_events); |
| 3722 | rewritten = list_concat(rewritten, newstuff); |
| 3723 | } |
| 3724 | |
| 3725 | rewrite_events = list_delete_first(rewrite_events); |
| 3726 | } |
| 3727 | |
| 3728 | /* |
| 3729 | * If there is an INSTEAD, and the original query has a RETURNING, we |
| 3730 | * have to have found a RETURNING in the rule(s), else fail. (Because |
| 3731 | * DefineQueryRewrite only allows RETURNING in unconditional INSTEAD |
| 3732 | * rules, there's no need to worry whether the substituted RETURNING |
| 3733 | * will actually be executed --- it must be.) |
| 3734 | */ |
| 3735 | if ((instead || qual_product != NULL) && |
| 3736 | parsetree->returningList && |
| 3737 | !returning) |
| 3738 | { |
| 3739 | switch (event) |
| 3740 | { |
| 3741 | case CMD_INSERT: |
| 3742 | ereport(ERROR, |
| 3743 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 3744 | errmsg("cannot perform INSERT RETURNING on relation \"%s\"" , |
| 3745 | RelationGetRelationName(rt_entry_relation)), |
| 3746 | errhint("You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause." ))); |
| 3747 | break; |
| 3748 | case CMD_UPDATE: |
| 3749 | ereport(ERROR, |
| 3750 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 3751 | errmsg("cannot perform UPDATE RETURNING on relation \"%s\"" , |
| 3752 | RelationGetRelationName(rt_entry_relation)), |
| 3753 | errhint("You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause." ))); |
| 3754 | break; |
| 3755 | case CMD_DELETE: |
| 3756 | ereport(ERROR, |
| 3757 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 3758 | errmsg("cannot perform DELETE RETURNING on relation \"%s\"" , |
| 3759 | RelationGetRelationName(rt_entry_relation)), |
| 3760 | errhint("You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause." ))); |
| 3761 | break; |
| 3762 | default: |
| 3763 | elog(ERROR, "unrecognized commandType: %d" , |
| 3764 | (int) event); |
| 3765 | break; |
| 3766 | } |
| 3767 | } |
| 3768 | |
| 3769 | /* |
| 3770 | * Updatable views are supported by ON CONFLICT, so don't prevent that |
| 3771 | * case from proceeding |
| 3772 | */ |
| 3773 | if (parsetree->onConflict && |
| 3774 | (product_queries != NIL || hasUpdate) && |
| 3775 | !updatableview) |
| 3776 | ereport(ERROR, |
| 3777 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 3778 | errmsg("INSERT with ON CONFLICT clause cannot be used with table that has INSERT or UPDATE rules" ))); |
| 3779 | |
| 3780 | table_close(rt_entry_relation, NoLock); |
| 3781 | } |
| 3782 | |
| 3783 | /* |
| 3784 | * For INSERTs, the original query is done first; for UPDATE/DELETE, it is |
| 3785 | * done last. This is needed because update and delete rule actions might |
| 3786 | * not do anything if they are invoked after the update or delete is |
| 3787 | * performed. The command counter increment between the query executions |
| 3788 | * makes the deleted (and maybe the updated) tuples disappear so the scans |
| 3789 | * for them in the rule actions cannot find them. |
| 3790 | * |
| 3791 | * If we found any unqualified INSTEAD, the original query is not done at |
| 3792 | * all, in any form. Otherwise, we add the modified form if qualified |
| 3793 | * INSTEADs were found, else the unmodified form. |
| 3794 | */ |
| 3795 | if (!instead) |
| 3796 | { |
| 3797 | if (parsetree->commandType == CMD_INSERT) |
| 3798 | { |
| 3799 | if (qual_product != NULL) |
| 3800 | rewritten = lcons(qual_product, rewritten); |
| 3801 | else |
| 3802 | rewritten = lcons(parsetree, rewritten); |
| 3803 | } |
| 3804 | else |
| 3805 | { |
| 3806 | if (qual_product != NULL) |
| 3807 | rewritten = lappend(rewritten, qual_product); |
| 3808 | else |
| 3809 | rewritten = lappend(rewritten, parsetree); |
| 3810 | } |
| 3811 | } |
| 3812 | |
| 3813 | /* |
| 3814 | * If the original query has a CTE list, and we generated more than one |
| 3815 | * non-utility result query, we have to fail because we'll have copied the |
| 3816 | * CTE list into each result query. That would break the expectation of |
| 3817 | * single evaluation of CTEs. This could possibly be fixed by |
| 3818 | * restructuring so that a CTE list can be shared across multiple Query |
| 3819 | * and PlannableStatement nodes. |
| 3820 | */ |
| 3821 | if (parsetree->cteList != NIL) |
| 3822 | { |
| 3823 | int qcount = 0; |
| 3824 | |
| 3825 | foreach(lc1, rewritten) |
| 3826 | { |
| 3827 | Query *q = (Query *) lfirst(lc1); |
| 3828 | |
| 3829 | if (q->commandType != CMD_UTILITY) |
| 3830 | qcount++; |
| 3831 | } |
| 3832 | if (qcount > 1) |
| 3833 | ereport(ERROR, |
| 3834 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 3835 | errmsg("WITH cannot be used in a query that is rewritten by rules into multiple queries" ))); |
| 3836 | } |
| 3837 | |
| 3838 | return rewritten; |
| 3839 | } |
| 3840 | |
| 3841 | |
| 3842 | /* |
| 3843 | * QueryRewrite - |
| 3844 | * Primary entry point to the query rewriter. |
| 3845 | * Rewrite one query via query rewrite system, possibly returning 0 |
| 3846 | * or many queries. |
| 3847 | * |
| 3848 | * NOTE: the parsetree must either have come straight from the parser, |
| 3849 | * or have been scanned by AcquireRewriteLocks to acquire suitable locks. |
| 3850 | */ |
| 3851 | List * |
| 3852 | QueryRewrite(Query *parsetree) |
| 3853 | { |
| 3854 | uint64 input_query_id = parsetree->queryId; |
| 3855 | List *querylist; |
| 3856 | List *results; |
| 3857 | ListCell *l; |
| 3858 | CmdType origCmdType; |
| 3859 | bool foundOriginalQuery; |
| 3860 | Query *lastInstead; |
| 3861 | |
| 3862 | /* |
| 3863 | * This function is only applied to top-level original queries |
| 3864 | */ |
| 3865 | Assert(parsetree->querySource == QSRC_ORIGINAL); |
| 3866 | Assert(parsetree->canSetTag); |
| 3867 | |
| 3868 | /* |
| 3869 | * Step 1 |
| 3870 | * |
| 3871 | * Apply all non-SELECT rules possibly getting 0 or many queries |
| 3872 | */ |
| 3873 | querylist = RewriteQuery(parsetree, NIL); |
| 3874 | |
| 3875 | /* |
| 3876 | * Step 2 |
| 3877 | * |
| 3878 | * Apply all the RIR rules on each query |
| 3879 | * |
| 3880 | * This is also a handy place to mark each query with the original queryId |
| 3881 | */ |
| 3882 | results = NIL; |
| 3883 | foreach(l, querylist) |
| 3884 | { |
| 3885 | Query *query = (Query *) lfirst(l); |
| 3886 | |
| 3887 | query = fireRIRrules(query, NIL); |
| 3888 | |
| 3889 | query->queryId = input_query_id; |
| 3890 | |
| 3891 | results = lappend(results, query); |
| 3892 | } |
| 3893 | |
| 3894 | /* |
| 3895 | * Step 3 |
| 3896 | * |
| 3897 | * Determine which, if any, of the resulting queries is supposed to set |
| 3898 | * the command-result tag; and update the canSetTag fields accordingly. |
| 3899 | * |
| 3900 | * If the original query is still in the list, it sets the command tag. |
| 3901 | * Otherwise, the last INSTEAD query of the same kind as the original is |
| 3902 | * allowed to set the tag. (Note these rules can leave us with no query |
| 3903 | * setting the tag. The tcop code has to cope with this by setting up a |
| 3904 | * default tag based on the original un-rewritten query.) |
| 3905 | * |
| 3906 | * The Asserts verify that at most one query in the result list is marked |
| 3907 | * canSetTag. If we aren't checking asserts, we can fall out of the loop |
| 3908 | * as soon as we find the original query. |
| 3909 | */ |
| 3910 | origCmdType = parsetree->commandType; |
| 3911 | foundOriginalQuery = false; |
| 3912 | lastInstead = NULL; |
| 3913 | |
| 3914 | foreach(l, results) |
| 3915 | { |
| 3916 | Query *query = (Query *) lfirst(l); |
| 3917 | |
| 3918 | if (query->querySource == QSRC_ORIGINAL) |
| 3919 | { |
| 3920 | Assert(query->canSetTag); |
| 3921 | Assert(!foundOriginalQuery); |
| 3922 | foundOriginalQuery = true; |
| 3923 | #ifndef USE_ASSERT_CHECKING |
| 3924 | break; |
| 3925 | #endif |
| 3926 | } |
| 3927 | else |
| 3928 | { |
| 3929 | Assert(!query->canSetTag); |
| 3930 | if (query->commandType == origCmdType && |
| 3931 | (query->querySource == QSRC_INSTEAD_RULE || |
| 3932 | query->querySource == QSRC_QUAL_INSTEAD_RULE)) |
| 3933 | lastInstead = query; |
| 3934 | } |
| 3935 | } |
| 3936 | |
| 3937 | if (!foundOriginalQuery && lastInstead != NULL) |
| 3938 | lastInstead->canSetTag = true; |
| 3939 | |
| 3940 | return results; |
| 3941 | } |
| 3942 | |