Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * execMain.c
4 : * top level executor interface routines
5 : *
6 : * INTERFACE ROUTINES
7 : * ExecutorStart()
8 : * ExecutorRun()
9 : * ExecutorFinish()
10 : * ExecutorEnd()
11 : *
12 : * These four procedures are the external interface to the executor.
13 : * In each case, the query descriptor is required as an argument.
14 : *
15 : * ExecutorStart must be called at the beginning of execution of any
16 : * query plan and ExecutorEnd must always be called at the end of
17 : * execution of a plan (unless it is aborted due to error).
18 : *
19 : * ExecutorRun accepts direction and count arguments that specify whether
20 : * the plan is to be executed forwards, backwards, and for how many tuples.
21 : * In some cases ExecutorRun may be called multiple times to process all
22 : * the tuples for a plan. It is also acceptable to stop short of executing
23 : * the whole plan (but only if it is a SELECT).
24 : *
25 : * ExecutorFinish must be called after the final ExecutorRun call and
26 : * before ExecutorEnd. This can be omitted only in case of EXPLAIN,
27 : * which should also omit ExecutorRun.
28 : *
29 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
30 : * Portions Copyright (c) 1994, Regents of the University of California
31 : *
32 : *
33 : * IDENTIFICATION
34 : * src/backend/executor/execMain.c
35 : *
36 : *-------------------------------------------------------------------------
37 : */
38 : #include "postgres.h"
39 :
40 : #include "access/htup_details.h"
41 : #include "access/sysattr.h"
42 : #include "access/transam.h"
43 : #include "access/xact.h"
44 : #include "catalog/namespace.h"
45 : #include "catalog/partition.h"
46 : #include "catalog/pg_inherits_fn.h"
47 : #include "catalog/pg_publication.h"
48 : #include "commands/matview.h"
49 : #include "commands/trigger.h"
50 : #include "executor/execdebug.h"
51 : #include "foreign/fdwapi.h"
52 : #include "mb/pg_wchar.h"
53 : #include "miscadmin.h"
54 : #include "optimizer/clauses.h"
55 : #include "parser/parsetree.h"
56 : #include "rewrite/rewriteManip.h"
57 : #include "storage/bufmgr.h"
58 : #include "storage/lmgr.h"
59 : #include "tcop/utility.h"
60 : #include "utils/acl.h"
61 : #include "utils/lsyscache.h"
62 : #include "utils/memutils.h"
63 : #include "utils/rls.h"
64 : #include "utils/ruleutils.h"
65 : #include "utils/snapmgr.h"
66 : #include "utils/tqual.h"
67 :
68 :
69 : /* Hooks for plugins to get control in ExecutorStart/Run/Finish/End */
70 : ExecutorStart_hook_type ExecutorStart_hook = NULL;
71 : ExecutorRun_hook_type ExecutorRun_hook = NULL;
72 : ExecutorFinish_hook_type ExecutorFinish_hook = NULL;
73 : ExecutorEnd_hook_type ExecutorEnd_hook = NULL;
74 :
75 : /* Hook for plugin to get control in ExecCheckRTPerms() */
76 : ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook = NULL;
77 :
78 : /* decls for local routines only used within this module */
79 : static void InitPlan(QueryDesc *queryDesc, int eflags);
80 : static void CheckValidRowMarkRel(Relation rel, RowMarkType markType);
81 : static void ExecPostprocessPlan(EState *estate);
82 : static void ExecEndPlan(PlanState *planstate, EState *estate);
83 : static void ExecutePlan(EState *estate, PlanState *planstate,
84 : bool use_parallel_mode,
85 : CmdType operation,
86 : bool sendTuples,
87 : uint64 numberTuples,
88 : ScanDirection direction,
89 : DestReceiver *dest,
90 : bool execute_once);
91 : static bool ExecCheckRTEPerms(RangeTblEntry *rte);
92 : static bool ExecCheckRTEPermsModified(Oid relOid, Oid userid,
93 : Bitmapset *modifiedCols,
94 : AclMode requiredPerms);
95 : static void ExecCheckXactReadOnly(PlannedStmt *plannedstmt);
96 : static char *ExecBuildSlotValueDescription(Oid reloid,
97 : TupleTableSlot *slot,
98 : TupleDesc tupdesc,
99 : Bitmapset *modifiedCols,
100 : int maxfieldlen);
101 : static char *ExecBuildSlotPartitionKeyDescription(Relation rel,
102 : Datum *values,
103 : bool *isnull,
104 : int maxfieldlen);
105 : static void EvalPlanQualStart(EPQState *epqstate, EState *parentestate,
106 : Plan *planTree);
107 : static void ExecPartitionCheck(ResultRelInfo *resultRelInfo,
108 : TupleTableSlot *slot, EState *estate);
109 :
110 : /*
111 : * Note that GetUpdatedColumns() also exists in commands/trigger.c. There does
112 : * not appear to be any good header to put it into, given the structures that
113 : * it uses, so we let them be duplicated. Be sure to update both if one needs
114 : * to be changed, however.
115 : */
116 : #define GetInsertedColumns(relinfo, estate) \
117 : (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->insertedCols)
118 : #define GetUpdatedColumns(relinfo, estate) \
119 : (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->updatedCols)
120 :
121 : /* end of local decls */
122 :
123 :
124 : /* ----------------------------------------------------------------
125 : * ExecutorStart
126 : *
127 : * This routine must be called at the beginning of any execution of any
128 : * query plan
129 : *
130 : * Takes a QueryDesc previously created by CreateQueryDesc (which is separate
131 : * only because some places use QueryDescs for utility commands). The tupDesc
132 : * field of the QueryDesc is filled in to describe the tuples that will be
133 : * returned, and the internal fields (estate and planstate) are set up.
134 : *
135 : * eflags contains flag bits as described in executor.h.
136 : *
137 : * NB: the CurrentMemoryContext when this is called will become the parent
138 : * of the per-query context used for this Executor invocation.
139 : *
140 : * We provide a function hook variable that lets loadable plugins
141 : * get control when ExecutorStart is called. Such a plugin would
142 : * normally call standard_ExecutorStart().
143 : *
144 : * ----------------------------------------------------------------
145 : */
146 : void
147 24667 : ExecutorStart(QueryDesc *queryDesc, int eflags)
148 : {
149 24667 : if (ExecutorStart_hook)
150 0 : (*ExecutorStart_hook) (queryDesc, eflags);
151 : else
152 24667 : standard_ExecutorStart(queryDesc, eflags);
153 24588 : }
154 :
155 : void
156 24667 : standard_ExecutorStart(QueryDesc *queryDesc, int eflags)
157 : {
158 : EState *estate;
159 : MemoryContext oldcontext;
160 :
161 : /* sanity checks: queryDesc must not be started already */
162 24667 : Assert(queryDesc != NULL);
163 24667 : Assert(queryDesc->estate == NULL);
164 :
165 : /*
166 : * If the transaction is read-only, we need to check if any writes are
167 : * planned to non-temporary tables. EXPLAIN is considered read-only.
168 : *
169 : * Don't allow writes in parallel mode. Supporting UPDATE and DELETE
170 : * would require (a) storing the combocid hash in shared memory, rather
171 : * than synchronizing it just once at the start of parallelism, and (b) an
172 : * alternative to heap_update()'s reliance on xmax for mutual exclusion.
173 : * INSERT may have no such troubles, but we forbid it to simplify the
174 : * checks.
175 : *
176 : * We have lower-level defenses in CommandCounterIncrement and elsewhere
177 : * against performing unsafe operations in parallel mode, but this gives a
178 : * more user-friendly error message.
179 : */
180 24798 : if ((XactReadOnly || IsInParallelMode()) &&
181 131 : !(eflags & EXEC_FLAG_EXPLAIN_ONLY))
182 131 : ExecCheckXactReadOnly(queryDesc->plannedstmt);
183 :
184 : /*
185 : * Build EState, switch into per-query memory context for startup.
186 : */
187 24665 : estate = CreateExecutorState();
188 24665 : queryDesc->estate = estate;
189 :
190 24665 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
191 :
192 : /*
193 : * Fill in external parameters, if any, from queryDesc; and allocate
194 : * workspace for internal parameters
195 : */
196 24665 : estate->es_param_list_info = queryDesc->params;
197 :
198 24665 : if (queryDesc->plannedstmt->nParamExec > 0)
199 8132 : estate->es_param_exec_vals = (ParamExecData *)
200 8132 : palloc0(queryDesc->plannedstmt->nParamExec * sizeof(ParamExecData));
201 :
202 24665 : estate->es_sourceText = queryDesc->sourceText;
203 :
204 : /*
205 : * Fill in the query environment, if any, from queryDesc.
206 : */
207 24665 : estate->es_queryEnv = queryDesc->queryEnv;
208 :
209 : /*
210 : * If non-read-only query, set the command ID to mark output tuples with
211 : */
212 24665 : switch (queryDesc->operation)
213 : {
214 : case CMD_SELECT:
215 :
216 : /*
217 : * SELECT FOR [KEY] UPDATE/SHARE and modifying CTEs need to mark
218 : * tuples
219 : */
220 39989 : if (queryDesc->plannedstmt->rowMarks != NIL ||
221 19811 : queryDesc->plannedstmt->hasModifyingCTE)
222 386 : estate->es_output_cid = GetCurrentCommandId(true);
223 :
224 : /*
225 : * A SELECT without modifying CTEs can't possibly queue triggers,
226 : * so force skip-triggers mode. This is just a marginal efficiency
227 : * hack, since AfterTriggerBeginQuery/AfterTriggerEndQuery aren't
228 : * all that expensive, but we might as well do it.
229 : */
230 20178 : if (!queryDesc->plannedstmt->hasModifyingCTE)
231 20159 : eflags |= EXEC_FLAG_SKIP_TRIGGERS;
232 20178 : break;
233 :
234 : case CMD_INSERT:
235 : case CMD_DELETE:
236 : case CMD_UPDATE:
237 4487 : estate->es_output_cid = GetCurrentCommandId(true);
238 4487 : break;
239 :
240 : default:
241 0 : elog(ERROR, "unrecognized operation code: %d",
242 : (int) queryDesc->operation);
243 : break;
244 : }
245 :
246 : /*
247 : * Copy other important information into the EState
248 : */
249 24665 : estate->es_snapshot = RegisterSnapshot(queryDesc->snapshot);
250 24665 : estate->es_crosscheck_snapshot = RegisterSnapshot(queryDesc->crosscheck_snapshot);
251 24665 : estate->es_top_eflags = eflags;
252 24665 : estate->es_instrument = queryDesc->instrument_options;
253 :
254 : /*
255 : * Initialize the plan state tree
256 : */
257 24665 : InitPlan(queryDesc, eflags);
258 :
259 : /*
260 : * Set up an AFTER-trigger statement context, unless told not to, or
261 : * unless it's EXPLAIN-only mode (when ExecutorFinish won't be called).
262 : */
263 24588 : if (!(eflags & (EXEC_FLAG_SKIP_TRIGGERS | EXEC_FLAG_EXPLAIN_ONLY)))
264 4371 : AfterTriggerBeginQuery();
265 :
266 24588 : MemoryContextSwitchTo(oldcontext);
267 24588 : }
268 :
269 : /* ----------------------------------------------------------------
270 : * ExecutorRun
271 : *
272 : * This is the main routine of the executor module. It accepts
273 : * the query descriptor from the traffic cop and executes the
274 : * query plan.
275 : *
276 : * ExecutorStart must have been called already.
277 : *
278 : * If direction is NoMovementScanDirection then nothing is done
279 : * except to start up/shut down the destination. Otherwise,
280 : * we retrieve up to 'count' tuples in the specified direction.
281 : *
282 : * Note: count = 0 is interpreted as no portal limit, i.e., run to
283 : * completion. Also note that the count limit is only applied to
284 : * retrieved tuples, not for instance to those inserted/updated/deleted
285 : * by a ModifyTable plan node.
286 : *
287 : * There is no return value, but output tuples (if any) are sent to
288 : * the destination receiver specified in the QueryDesc; and the number
289 : * of tuples processed at the top level can be found in
290 : * estate->es_processed.
291 : *
292 : * We provide a function hook variable that lets loadable plugins
293 : * get control when ExecutorRun is called. Such a plugin would
294 : * normally call standard_ExecutorRun().
295 : *
296 : * ----------------------------------------------------------------
297 : */
298 : void
299 24017 : ExecutorRun(QueryDesc *queryDesc,
300 : ScanDirection direction, uint64 count,
301 : bool execute_once)
302 : {
303 24017 : if (ExecutorRun_hook)
304 0 : (*ExecutorRun_hook) (queryDesc, direction, count, execute_once);
305 : else
306 24017 : standard_ExecutorRun(queryDesc, direction, count, execute_once);
307 20853 : }
308 :
309 : void
310 24017 : standard_ExecutorRun(QueryDesc *queryDesc,
311 : ScanDirection direction, uint64 count, bool execute_once)
312 : {
313 : EState *estate;
314 : CmdType operation;
315 : DestReceiver *dest;
316 : bool sendTuples;
317 : MemoryContext oldcontext;
318 :
319 : /* sanity checks */
320 24017 : Assert(queryDesc != NULL);
321 :
322 24017 : estate = queryDesc->estate;
323 :
324 24017 : Assert(estate != NULL);
325 24017 : Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));
326 :
327 : /*
328 : * Switch into per-query memory context
329 : */
330 24017 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
331 :
332 : /* Allow instrumentation of Executor overall runtime */
333 24017 : if (queryDesc->totaltime)
334 0 : InstrStartNode(queryDesc->totaltime);
335 :
336 : /*
337 : * extract information from the query descriptor and the query feature.
338 : */
339 24017 : operation = queryDesc->operation;
340 24017 : dest = queryDesc->dest;
341 :
342 : /*
343 : * startup tuple receiver, if we will be emitting tuples
344 : */
345 24017 : estate->es_processed = 0;
346 24017 : estate->es_lastoid = InvalidOid;
347 :
348 28411 : sendTuples = (operation == CMD_SELECT ||
349 4394 : queryDesc->plannedstmt->hasReturning);
350 :
351 24017 : if (sendTuples)
352 19840 : (*dest->rStartup) (dest, operation, queryDesc->tupDesc);
353 :
354 : /*
355 : * run plan
356 : */
357 24007 : if (!ScanDirectionIsNoMovement(direction))
358 : {
359 23779 : if (execute_once && queryDesc->already_executed)
360 0 : elog(ERROR, "can't re-execute query flagged for single execution");
361 23779 : queryDesc->already_executed = true;
362 :
363 47558 : ExecutePlan(estate,
364 : queryDesc->planstate,
365 23779 : queryDesc->plannedstmt->parallelModeNeeded,
366 : operation,
367 : sendTuples,
368 : count,
369 : direction,
370 : dest,
371 : execute_once);
372 : }
373 :
374 : /*
375 : * shutdown tuple receiver, if we started it
376 : */
377 20853 : if (sendTuples)
378 16920 : (*dest->rShutdown) (dest);
379 :
380 20853 : if (queryDesc->totaltime)
381 0 : InstrStopNode(queryDesc->totaltime, estate->es_processed);
382 :
383 20853 : MemoryContextSwitchTo(oldcontext);
384 20853 : }
385 :
386 : /* ----------------------------------------------------------------
387 : * ExecutorFinish
388 : *
389 : * This routine must be called after the last ExecutorRun call.
390 : * It performs cleanup such as firing AFTER triggers. It is
391 : * separate from ExecutorEnd because EXPLAIN ANALYZE needs to
392 : * include these actions in the total runtime.
393 : *
394 : * We provide a function hook variable that lets loadable plugins
395 : * get control when ExecutorFinish is called. Such a plugin would
396 : * normally call standard_ExecutorFinish().
397 : *
398 : * ----------------------------------------------------------------
399 : */
400 : void
401 20277 : ExecutorFinish(QueryDesc *queryDesc)
402 : {
403 20277 : if (ExecutorFinish_hook)
404 0 : (*ExecutorFinish_hook) (queryDesc);
405 : else
406 20277 : standard_ExecutorFinish(queryDesc);
407 20209 : }
408 :
409 : void
410 20277 : standard_ExecutorFinish(QueryDesc *queryDesc)
411 : {
412 : EState *estate;
413 : MemoryContext oldcontext;
414 :
415 : /* sanity checks */
416 20277 : Assert(queryDesc != NULL);
417 :
418 20277 : estate = queryDesc->estate;
419 :
420 20277 : Assert(estate != NULL);
421 20277 : Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));
422 :
423 : /* This should be run once and only once per Executor instance */
424 20277 : Assert(!estate->es_finished);
425 :
426 : /* Switch into per-query memory context */
427 20277 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
428 :
429 : /* Allow instrumentation of Executor overall runtime */
430 20277 : if (queryDesc->totaltime)
431 0 : InstrStartNode(queryDesc->totaltime);
432 :
433 : /* Run ModifyTable nodes to completion */
434 20277 : ExecPostprocessPlan(estate);
435 :
436 : /* Execute queued AFTER triggers, unless told not to */
437 20277 : if (!(estate->es_top_eflags & EXEC_FLAG_SKIP_TRIGGERS))
438 4117 : AfterTriggerEndQuery(estate);
439 :
440 20209 : if (queryDesc->totaltime)
441 0 : InstrStopNode(queryDesc->totaltime, 0);
442 :
443 20209 : MemoryContextSwitchTo(oldcontext);
444 :
445 20209 : estate->es_finished = true;
446 20209 : }
447 :
448 : /* ----------------------------------------------------------------
449 : * ExecutorEnd
450 : *
451 : * This routine must be called at the end of execution of any
452 : * query plan
453 : *
454 : * We provide a function hook variable that lets loadable plugins
455 : * get control when ExecutorEnd is called. Such a plugin would
456 : * normally call standard_ExecutorEnd().
457 : *
458 : * ----------------------------------------------------------------
459 : */
460 : void
461 21321 : ExecutorEnd(QueryDesc *queryDesc)
462 : {
463 21321 : if (ExecutorEnd_hook)
464 0 : (*ExecutorEnd_hook) (queryDesc);
465 : else
466 21321 : standard_ExecutorEnd(queryDesc);
467 21321 : }
468 :
469 : void
470 21321 : standard_ExecutorEnd(QueryDesc *queryDesc)
471 : {
472 : EState *estate;
473 : MemoryContext oldcontext;
474 :
475 : /* sanity checks */
476 21321 : Assert(queryDesc != NULL);
477 :
478 21321 : estate = queryDesc->estate;
479 :
480 21321 : Assert(estate != NULL);
481 :
482 : /*
483 : * Check that ExecutorFinish was called, unless in EXPLAIN-only mode. This
484 : * Assert is needed because ExecutorFinish is new as of 9.1, and callers
485 : * might forget to call it.
486 : */
487 21321 : Assert(estate->es_finished ||
488 : (estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY));
489 :
490 : /*
491 : * Switch into per-query memory context to run ExecEndPlan
492 : */
493 21321 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
494 :
495 21321 : ExecEndPlan(queryDesc->planstate, estate);
496 :
497 : /* do away with our snapshots */
498 21321 : UnregisterSnapshot(estate->es_snapshot);
499 21321 : UnregisterSnapshot(estate->es_crosscheck_snapshot);
500 :
501 : /*
502 : * Must switch out of context before destroying it
503 : */
504 21321 : MemoryContextSwitchTo(oldcontext);
505 :
506 : /*
507 : * Release EState and per-query memory context. This should release
508 : * everything the executor has allocated.
509 : */
510 21321 : FreeExecutorState(estate);
511 :
512 : /* Reset queryDesc fields that no longer point to anything */
513 21321 : queryDesc->tupDesc = NULL;
514 21321 : queryDesc->estate = NULL;
515 21321 : queryDesc->planstate = NULL;
516 21321 : queryDesc->totaltime = NULL;
517 21321 : }
518 :
519 : /* ----------------------------------------------------------------
520 : * ExecutorRewind
521 : *
522 : * This routine may be called on an open queryDesc to rewind it
523 : * to the start.
524 : * ----------------------------------------------------------------
525 : */
526 : void
527 14 : ExecutorRewind(QueryDesc *queryDesc)
528 : {
529 : EState *estate;
530 : MemoryContext oldcontext;
531 :
532 : /* sanity checks */
533 14 : Assert(queryDesc != NULL);
534 :
535 14 : estate = queryDesc->estate;
536 :
537 14 : Assert(estate != NULL);
538 :
539 : /* It's probably not sensible to rescan updating queries */
540 14 : Assert(queryDesc->operation == CMD_SELECT);
541 :
542 : /*
543 : * Switch into per-query memory context
544 : */
545 14 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
546 :
547 : /*
548 : * rescan plan
549 : */
550 14 : ExecReScan(queryDesc->planstate);
551 :
552 14 : MemoryContextSwitchTo(oldcontext);
553 14 : }
554 :
555 :
556 : /*
557 : * ExecCheckRTPerms
558 : * Check access permissions for all relations listed in a range table.
559 : *
560 : * Returns true if permissions are adequate. Otherwise, throws an appropriate
561 : * error if ereport_on_violation is true, or simply returns false otherwise.
562 : *
563 : * Note that this does NOT address row level security policies (aka: RLS). If
564 : * rows will be returned to the user as a result of this permission check
565 : * passing, then RLS also needs to be consulted (and check_enable_rls()).
566 : *
567 : * See rewrite/rowsecurity.c.
568 : */
569 : bool
570 24965 : ExecCheckRTPerms(List *rangeTable, bool ereport_on_violation)
571 : {
572 : ListCell *l;
573 24965 : bool result = true;
574 :
575 59802 : foreach(l, rangeTable)
576 : {
577 34924 : RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
578 :
579 34924 : result = ExecCheckRTEPerms(rte);
580 34924 : if (!result)
581 : {
582 87 : Assert(rte->rtekind == RTE_RELATION);
583 87 : if (ereport_on_violation)
584 87 : aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
585 87 : get_rel_name(rte->relid));
586 0 : return false;
587 : }
588 : }
589 :
590 24878 : if (ExecutorCheckPerms_hook)
591 0 : result = (*ExecutorCheckPerms_hook) (rangeTable,
592 : ereport_on_violation);
593 24878 : return result;
594 : }
595 :
596 : /*
597 : * ExecCheckRTEPerms
598 : * Check access permissions for a single RTE.
599 : */
600 : static bool
601 34924 : ExecCheckRTEPerms(RangeTblEntry *rte)
602 : {
603 : AclMode requiredPerms;
604 : AclMode relPerms;
605 : AclMode remainingPerms;
606 : Oid relOid;
607 : Oid userid;
608 :
609 : /*
610 : * Only plain-relation RTEs need to be checked here. Function RTEs are
611 : * checked when the function is prepared for execution. Join, subquery,
612 : * and special RTEs need no checks.
613 : */
614 34924 : if (rte->rtekind != RTE_RELATION)
615 8076 : return true;
616 :
617 : /*
618 : * No work if requiredPerms is empty.
619 : */
620 26848 : requiredPerms = rte->requiredPerms;
621 26848 : if (requiredPerms == 0)
622 2368 : return true;
623 :
624 24480 : relOid = rte->relid;
625 :
626 : /*
627 : * userid to check as: current user unless we have a setuid indication.
628 : *
629 : * Note: GetUserId() is presently fast enough that there's no harm in
630 : * calling it separately for each RTE. If that stops being true, we could
631 : * call it once in ExecCheckRTPerms and pass the userid down from there.
632 : * But for now, no need for the extra clutter.
633 : */
634 24480 : userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
635 :
636 : /*
637 : * We must have *all* the requiredPerms bits, but some of the bits can be
638 : * satisfied from column-level rather than relation-level permissions.
639 : * First, remove any bits that are satisfied by relation permissions.
640 : */
641 24480 : relPerms = pg_class_aclmask(relOid, userid, requiredPerms, ACLMASK_ALL);
642 24480 : remainingPerms = requiredPerms & ~relPerms;
643 24480 : if (remainingPerms != 0)
644 : {
645 136 : int col = -1;
646 :
647 : /*
648 : * If we lack any permissions that exist only as relation permissions,
649 : * we can fail straight away.
650 : */
651 136 : if (remainingPerms & ~(ACL_SELECT | ACL_INSERT | ACL_UPDATE))
652 8 : return false;
653 :
654 : /*
655 : * Check to see if we have the needed privileges at column level.
656 : *
657 : * Note: failures just report a table-level error; it would be nicer
658 : * to report a column-level error if we have some but not all of the
659 : * column privileges.
660 : */
661 128 : if (remainingPerms & ACL_SELECT)
662 : {
663 : /*
664 : * When the query doesn't explicitly reference any columns (for
665 : * example, SELECT COUNT(*) FROM table), allow the query if we
666 : * have SELECT on any column of the rel, as per SQL spec.
667 : */
668 86 : if (bms_is_empty(rte->selectedCols))
669 : {
670 5 : if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
671 : ACLMASK_ANY) != ACLCHECK_OK)
672 1 : return false;
673 : }
674 :
675 230 : while ((col = bms_next_member(rte->selectedCols, col)) >= 0)
676 : {
677 : /* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
678 106 : AttrNumber attno = col + FirstLowInvalidHeapAttributeNumber;
679 :
680 106 : if (attno == InvalidAttrNumber)
681 : {
682 : /* Whole-row reference, must have priv on all cols */
683 7 : if (pg_attribute_aclcheck_all(relOid, userid, ACL_SELECT,
684 : ACLMASK_ALL) != ACLCHECK_OK)
685 3 : return false;
686 : }
687 : else
688 : {
689 99 : if (pg_attribute_aclcheck(relOid, attno, userid,
690 : ACL_SELECT) != ACLCHECK_OK)
691 43 : return false;
692 : }
693 : }
694 : }
695 :
696 : /*
697 : * Basically the same for the mod columns, for both INSERT and UPDATE
698 : * privilege as specified by remainingPerms.
699 : */
700 81 : if (remainingPerms & ACL_INSERT && !ExecCheckRTEPermsModified(relOid,
701 : userid,
702 : rte->insertedCols,
703 : ACL_INSERT))
704 21 : return false;
705 :
706 60 : if (remainingPerms & ACL_UPDATE && !ExecCheckRTEPermsModified(relOid,
707 : userid,
708 : rte->updatedCols,
709 : ACL_UPDATE))
710 11 : return false;
711 : }
712 24393 : return true;
713 : }
714 :
715 : /*
716 : * ExecCheckRTEPermsModified
717 : * Check INSERT or UPDATE access permissions for a single RTE (these
718 : * are processed uniformly).
719 : */
720 : static bool
721 53 : ExecCheckRTEPermsModified(Oid relOid, Oid userid, Bitmapset *modifiedCols,
722 : AclMode requiredPerms)
723 : {
724 53 : int col = -1;
725 :
726 : /*
727 : * When the query doesn't explicitly update any columns, allow the query
728 : * if we have permission on any column of the rel. This is to handle
729 : * SELECT FOR UPDATE as well as possible corner cases in UPDATE.
730 : */
731 53 : if (bms_is_empty(modifiedCols))
732 : {
733 2 : if (pg_attribute_aclcheck_all(relOid, userid, requiredPerms,
734 : ACLMASK_ANY) != ACLCHECK_OK)
735 2 : return false;
736 : }
737 :
738 128 : while ((col = bms_next_member(modifiedCols, col)) >= 0)
739 : {
740 : /* bit #s are offset by FirstLowInvalidHeapAttributeNumber */
741 56 : AttrNumber attno = col + FirstLowInvalidHeapAttributeNumber;
742 :
743 56 : if (attno == InvalidAttrNumber)
744 : {
745 : /* whole-row reference can't happen here */
746 0 : elog(ERROR, "whole-row update is not implemented");
747 : }
748 : else
749 : {
750 56 : if (pg_attribute_aclcheck(relOid, attno, userid,
751 : requiredPerms) != ACLCHECK_OK)
752 30 : return false;
753 : }
754 : }
755 21 : return true;
756 : }
757 :
758 : /*
759 : * Check that the query does not imply any writes to non-temp tables;
760 : * unless we're in parallel mode, in which case don't even allow writes
761 : * to temp tables.
762 : *
763 : * Note: in a Hot Standby this would need to reject writes to temp
764 : * tables just as we do in parallel mode; but an HS standby can't have created
765 : * any temp tables in the first place, so no need to check that.
766 : */
767 : static void
768 131 : ExecCheckXactReadOnly(PlannedStmt *plannedstmt)
769 : {
770 : ListCell *l;
771 :
772 : /*
773 : * Fail if write permissions are requested in parallel mode for table
774 : * (temp or non-temp), otherwise fail for any non-temp table.
775 : */
776 456 : foreach(l, plannedstmt->rtable)
777 : {
778 327 : RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
779 :
780 327 : if (rte->rtekind != RTE_RELATION)
781 145 : continue;
782 :
783 182 : if ((rte->requiredPerms & (~ACL_SELECT)) == 0)
784 178 : continue;
785 :
786 4 : if (isTempNamespace(get_rel_namespace(rte->relid)))
787 2 : continue;
788 :
789 2 : PreventCommandIfReadOnly(CreateCommandTag((Node *) plannedstmt));
790 : }
791 :
792 129 : if (plannedstmt->commandType != CMD_SELECT || plannedstmt->hasModifyingCTE)
793 2 : PreventCommandIfParallelMode(CreateCommandTag((Node *) plannedstmt));
794 129 : }
795 :
796 :
797 : /* ----------------------------------------------------------------
798 : * InitPlan
799 : *
800 : * Initializes the query plan: open files, allocate storage
801 : * and start up the rule manager
802 : * ----------------------------------------------------------------
803 : */
804 : static void
805 24665 : InitPlan(QueryDesc *queryDesc, int eflags)
806 : {
807 24665 : CmdType operation = queryDesc->operation;
808 24665 : PlannedStmt *plannedstmt = queryDesc->plannedstmt;
809 24665 : Plan *plan = plannedstmt->planTree;
810 24665 : List *rangeTable = plannedstmt->rtable;
811 24665 : EState *estate = queryDesc->estate;
812 : PlanState *planstate;
813 : TupleDesc tupType;
814 : ListCell *l;
815 : int i;
816 :
817 : /*
818 : * Do permissions checks
819 : */
820 24665 : ExecCheckRTPerms(rangeTable, true);
821 :
822 : /*
823 : * initialize the node's execution state
824 : */
825 24593 : estate->es_range_table = rangeTable;
826 24593 : estate->es_plannedstmt = plannedstmt;
827 :
828 : /*
829 : * initialize result relation stuff, and open/lock the result rels.
830 : *
831 : * We must do this before initializing the plan tree, else we might try to
832 : * do a lock upgrade if a result rel is also a source rel.
833 : */
834 24593 : if (plannedstmt->resultRelations)
835 : {
836 4470 : List *resultRelations = plannedstmt->resultRelations;
837 4470 : int numResultRelations = list_length(resultRelations);
838 : ResultRelInfo *resultRelInfos;
839 : ResultRelInfo *resultRelInfo;
840 :
841 4470 : resultRelInfos = (ResultRelInfo *)
842 4470 : palloc(numResultRelations * sizeof(ResultRelInfo));
843 4470 : resultRelInfo = resultRelInfos;
844 9070 : foreach(l, resultRelations)
845 : {
846 4600 : Index resultRelationIndex = lfirst_int(l);
847 : Oid resultRelationOid;
848 : Relation resultRelation;
849 :
850 4600 : resultRelationOid = getrelid(resultRelationIndex, rangeTable);
851 4600 : resultRelation = heap_open(resultRelationOid, RowExclusiveLock);
852 :
853 4600 : InitResultRelInfo(resultRelInfo,
854 : resultRelation,
855 : resultRelationIndex,
856 : NULL,
857 : estate->es_instrument);
858 4600 : resultRelInfo++;
859 : }
860 4470 : estate->es_result_relations = resultRelInfos;
861 4470 : estate->es_num_result_relations = numResultRelations;
862 : /* es_result_relation_info is NULL except when within ModifyTable */
863 4470 : estate->es_result_relation_info = NULL;
864 :
865 : /*
866 : * In the partitioned result relation case, lock the non-leaf result
867 : * relations too. A subset of these are the roots of respective
868 : * partitioned tables, for which we also allocate ResulRelInfos.
869 : */
870 4470 : estate->es_root_result_relations = NULL;
871 4470 : estate->es_num_root_result_relations = 0;
872 4470 : if (plannedstmt->nonleafResultRelations)
873 : {
874 10 : int num_roots = list_length(plannedstmt->rootResultRelations);
875 :
876 : /*
877 : * Firstly, build ResultRelInfos for all the partitioned table
878 : * roots, because we will need them to fire the statement-level
879 : * triggers, if any.
880 : */
881 10 : resultRelInfos = (ResultRelInfo *)
882 10 : palloc(num_roots * sizeof(ResultRelInfo));
883 10 : resultRelInfo = resultRelInfos;
884 21 : foreach(l, plannedstmt->rootResultRelations)
885 : {
886 11 : Index resultRelIndex = lfirst_int(l);
887 : Oid resultRelOid;
888 : Relation resultRelDesc;
889 :
890 11 : resultRelOid = getrelid(resultRelIndex, rangeTable);
891 11 : resultRelDesc = heap_open(resultRelOid, RowExclusiveLock);
892 22 : InitResultRelInfo(resultRelInfo,
893 : resultRelDesc,
894 11 : lfirst_int(l),
895 : NULL,
896 : estate->es_instrument);
897 11 : resultRelInfo++;
898 : }
899 :
900 10 : estate->es_root_result_relations = resultRelInfos;
901 10 : estate->es_num_root_result_relations = num_roots;
902 :
903 : /* Simply lock the rest of them. */
904 21 : foreach(l, plannedstmt->nonleafResultRelations)
905 : {
906 11 : Index resultRelIndex = lfirst_int(l);
907 :
908 : /* We locked the roots above. */
909 11 : if (!list_member_int(plannedstmt->rootResultRelations,
910 : resultRelIndex))
911 0 : LockRelationOid(getrelid(resultRelIndex, rangeTable),
912 : RowExclusiveLock);
913 : }
914 : }
915 : }
916 : else
917 : {
918 : /*
919 : * if no result relation, then set state appropriately
920 : */
921 20123 : estate->es_result_relations = NULL;
922 20123 : estate->es_num_result_relations = 0;
923 20123 : estate->es_result_relation_info = NULL;
924 20123 : estate->es_root_result_relations = NULL;
925 20123 : estate->es_num_root_result_relations = 0;
926 : }
927 :
928 : /*
929 : * Similarly, we have to lock relations selected FOR [KEY] UPDATE/SHARE
930 : * before we initialize the plan tree, else we'd be risking lock upgrades.
931 : * While we are at it, build the ExecRowMark list. Any partitioned child
932 : * tables are ignored here (because isParent=true) and will be locked by
933 : * the first Append or MergeAppend node that references them. (Note that
934 : * the RowMarks corresponding to partitioned child tables are present in
935 : * the same list as the rest, i.e., plannedstmt->rowMarks.)
936 : */
937 24593 : estate->es_rowMarks = NIL;
938 25164 : foreach(l, plannedstmt->rowMarks)
939 : {
940 572 : PlanRowMark *rc = (PlanRowMark *) lfirst(l);
941 : Oid relid;
942 : Relation relation;
943 : ExecRowMark *erm;
944 :
945 : /* ignore "parent" rowmarks; they are irrelevant at runtime */
946 572 : if (rc->isParent)
947 16 : continue;
948 :
949 : /* get relation's OID (will produce InvalidOid if subquery) */
950 556 : relid = getrelid(rc->rti, rangeTable);
951 :
952 : /*
953 : * If you change the conditions under which rel locks are acquired
954 : * here, be sure to adjust ExecOpenScanRelation to match.
955 : */
956 556 : switch (rc->markType)
957 : {
958 : case ROW_MARK_EXCLUSIVE:
959 : case ROW_MARK_NOKEYEXCLUSIVE:
960 : case ROW_MARK_SHARE:
961 : case ROW_MARK_KEYSHARE:
962 377 : relation = heap_open(relid, RowShareLock);
963 377 : break;
964 : case ROW_MARK_REFERENCE:
965 157 : relation = heap_open(relid, AccessShareLock);
966 157 : break;
967 : case ROW_MARK_COPY:
968 : /* no physical table access is required */
969 22 : relation = NULL;
970 22 : break;
971 : default:
972 0 : elog(ERROR, "unrecognized markType: %d", rc->markType);
973 : relation = NULL; /* keep compiler quiet */
974 : break;
975 : }
976 :
977 : /* Check that relation is a legal target for marking */
978 556 : if (relation)
979 534 : CheckValidRowMarkRel(relation, rc->markType);
980 :
981 555 : erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
982 555 : erm->relation = relation;
983 555 : erm->relid = relid;
984 555 : erm->rti = rc->rti;
985 555 : erm->prti = rc->prti;
986 555 : erm->rowmarkId = rc->rowmarkId;
987 555 : erm->markType = rc->markType;
988 555 : erm->strength = rc->strength;
989 555 : erm->waitPolicy = rc->waitPolicy;
990 555 : erm->ermActive = false;
991 555 : ItemPointerSetInvalid(&(erm->curCtid));
992 555 : erm->ermExtra = NULL;
993 555 : estate->es_rowMarks = lappend(estate->es_rowMarks, erm);
994 : }
995 :
996 : /*
997 : * Initialize the executor's tuple table to empty.
998 : */
999 24592 : estate->es_tupleTable = NIL;
1000 24592 : estate->es_trig_tuple_slot = NULL;
1001 24592 : estate->es_trig_oldtup_slot = NULL;
1002 24592 : estate->es_trig_newtup_slot = NULL;
1003 :
1004 : /* mark EvalPlanQual not active */
1005 24592 : estate->es_epqTuple = NULL;
1006 24592 : estate->es_epqTupleSet = NULL;
1007 24592 : estate->es_epqScanDone = NULL;
1008 :
1009 : /*
1010 : * Initialize private state information for each SubPlan. We must do this
1011 : * before running ExecInitNode on the main query tree, since
1012 : * ExecInitSubPlan expects to be able to find these entries.
1013 : */
1014 24592 : Assert(estate->es_subplanstates == NIL);
1015 24592 : i = 1; /* subplan indices count from 1 */
1016 27816 : foreach(l, plannedstmt->subplans)
1017 : {
1018 3224 : Plan *subplan = (Plan *) lfirst(l);
1019 : PlanState *subplanstate;
1020 : int sp_eflags;
1021 :
1022 : /*
1023 : * A subplan will never need to do BACKWARD scan nor MARK/RESTORE. If
1024 : * it is a parameterless subplan (not initplan), we suggest that it be
1025 : * prepared to handle REWIND efficiently; otherwise there is no need.
1026 : */
1027 3224 : sp_eflags = eflags
1028 : & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA);
1029 3224 : if (bms_is_member(i, plannedstmt->rewindPlanIDs))
1030 2 : sp_eflags |= EXEC_FLAG_REWIND;
1031 :
1032 3224 : subplanstate = ExecInitNode(subplan, estate, sp_eflags);
1033 :
1034 3224 : estate->es_subplanstates = lappend(estate->es_subplanstates,
1035 : subplanstate);
1036 :
1037 3224 : i++;
1038 : }
1039 :
1040 : /*
1041 : * Initialize the private state information for all the nodes in the query
1042 : * tree. This opens files, allocates storage and leaves us ready to start
1043 : * processing tuples.
1044 : */
1045 24592 : planstate = ExecInitNode(plan, estate, eflags);
1046 :
1047 : /*
1048 : * Get the tuple descriptor describing the type of tuples to return.
1049 : */
1050 24588 : tupType = ExecGetResultType(planstate);
1051 :
1052 : /*
1053 : * Initialize the junk filter if needed. SELECT queries need a filter if
1054 : * there are any junk attrs in the top-level tlist.
1055 : */
1056 24588 : if (operation == CMD_SELECT)
1057 : {
1058 20136 : bool junk_filter_needed = false;
1059 : ListCell *tlist;
1060 :
1061 62250 : foreach(tlist, plan->targetlist)
1062 : {
1063 43105 : TargetEntry *tle = (TargetEntry *) lfirst(tlist);
1064 :
1065 43105 : if (tle->resjunk)
1066 : {
1067 991 : junk_filter_needed = true;
1068 991 : break;
1069 : }
1070 : }
1071 :
1072 20136 : if (junk_filter_needed)
1073 : {
1074 : JunkFilter *j;
1075 :
1076 1982 : j = ExecInitJunkFilter(planstate->plan->targetlist,
1077 991 : tupType->tdhasoid,
1078 : ExecInitExtraTupleSlot(estate));
1079 991 : estate->es_junkFilter = j;
1080 :
1081 : /* Want to return the cleaned tuple type */
1082 991 : tupType = j->jf_cleanTupType;
1083 : }
1084 : }
1085 :
1086 24588 : queryDesc->tupDesc = tupType;
1087 24588 : queryDesc->planstate = planstate;
1088 24588 : }
1089 :
1090 : /*
1091 : * Check that a proposed result relation is a legal target for the operation
1092 : *
1093 : * Generally the parser and/or planner should have noticed any such mistake
1094 : * already, but let's make sure.
1095 : *
1096 : * Note: when changing this function, you probably also need to look at
1097 : * CheckValidRowMarkRel.
1098 : */
1099 : void
1100 4832 : CheckValidResultRel(Relation resultRel, CmdType operation)
1101 : {
1102 4832 : TriggerDesc *trigDesc = resultRel->trigdesc;
1103 : FdwRoutine *fdwroutine;
1104 :
1105 4832 : switch (resultRel->rd_rel->relkind)
1106 : {
1107 : case RELKIND_RELATION:
1108 : case RELKIND_PARTITIONED_TABLE:
1109 4778 : CheckCmdReplicaIdentity(resultRel, operation);
1110 4778 : break;
1111 : case RELKIND_SEQUENCE:
1112 0 : ereport(ERROR,
1113 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1114 : errmsg("cannot change sequence \"%s\"",
1115 : RelationGetRelationName(resultRel))));
1116 : break;
1117 : case RELKIND_TOASTVALUE:
1118 0 : ereport(ERROR,
1119 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1120 : errmsg("cannot change TOAST relation \"%s\"",
1121 : RelationGetRelationName(resultRel))));
1122 : break;
1123 : case RELKIND_VIEW:
1124 :
1125 : /*
1126 : * Okay only if there's a suitable INSTEAD OF trigger. Messages
1127 : * here should match rewriteHandler.c's rewriteTargetView, except
1128 : * that we omit errdetail because we haven't got the information
1129 : * handy (and given that we really shouldn't get here anyway, it's
1130 : * not worth great exertion to get).
1131 : */
1132 44 : switch (operation)
1133 : {
1134 : case CMD_INSERT:
1135 14 : if (!trigDesc || !trigDesc->trig_insert_instead_row)
1136 0 : ereport(ERROR,
1137 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1138 : errmsg("cannot insert into view \"%s\"",
1139 : RelationGetRelationName(resultRel)),
1140 : errhint("To enable inserting into the view, provide an INSTEAD OF INSERT trigger or an unconditional ON INSERT DO INSTEAD rule.")));
1141 14 : break;
1142 : case CMD_UPDATE:
1143 22 : if (!trigDesc || !trigDesc->trig_update_instead_row)
1144 0 : ereport(ERROR,
1145 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1146 : errmsg("cannot update view \"%s\"",
1147 : RelationGetRelationName(resultRel)),
1148 : errhint("To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.")));
1149 22 : break;
1150 : case CMD_DELETE:
1151 8 : if (!trigDesc || !trigDesc->trig_delete_instead_row)
1152 0 : ereport(ERROR,
1153 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1154 : errmsg("cannot delete from view \"%s\"",
1155 : RelationGetRelationName(resultRel)),
1156 : errhint("To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.")));
1157 8 : break;
1158 : default:
1159 0 : elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1160 : break;
1161 : }
1162 44 : break;
1163 : case RELKIND_MATVIEW:
1164 10 : if (!MatViewIncrementalMaintenanceIsEnabled())
1165 0 : ereport(ERROR,
1166 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1167 : errmsg("cannot change materialized view \"%s\"",
1168 : RelationGetRelationName(resultRel))));
1169 10 : break;
1170 : case RELKIND_FOREIGN_TABLE:
1171 : /* Okay only if the FDW supports it */
1172 0 : fdwroutine = GetFdwRoutineForRelation(resultRel, false);
1173 0 : switch (operation)
1174 : {
1175 : case CMD_INSERT:
1176 0 : if (fdwroutine->ExecForeignInsert == NULL)
1177 0 : ereport(ERROR,
1178 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1179 : errmsg("cannot insert into foreign table \"%s\"",
1180 : RelationGetRelationName(resultRel))));
1181 0 : if (fdwroutine->IsForeignRelUpdatable != NULL &&
1182 0 : (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_INSERT)) == 0)
1183 0 : ereport(ERROR,
1184 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1185 : errmsg("foreign table \"%s\" does not allow inserts",
1186 : RelationGetRelationName(resultRel))));
1187 0 : break;
1188 : case CMD_UPDATE:
1189 0 : if (fdwroutine->ExecForeignUpdate == NULL)
1190 0 : ereport(ERROR,
1191 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1192 : errmsg("cannot update foreign table \"%s\"",
1193 : RelationGetRelationName(resultRel))));
1194 0 : if (fdwroutine->IsForeignRelUpdatable != NULL &&
1195 0 : (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_UPDATE)) == 0)
1196 0 : ereport(ERROR,
1197 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1198 : errmsg("foreign table \"%s\" does not allow updates",
1199 : RelationGetRelationName(resultRel))));
1200 0 : break;
1201 : case CMD_DELETE:
1202 0 : if (fdwroutine->ExecForeignDelete == NULL)
1203 0 : ereport(ERROR,
1204 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1205 : errmsg("cannot delete from foreign table \"%s\"",
1206 : RelationGetRelationName(resultRel))));
1207 0 : if (fdwroutine->IsForeignRelUpdatable != NULL &&
1208 0 : (fdwroutine->IsForeignRelUpdatable(resultRel) & (1 << CMD_DELETE)) == 0)
1209 0 : ereport(ERROR,
1210 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1211 : errmsg("foreign table \"%s\" does not allow deletes",
1212 : RelationGetRelationName(resultRel))));
1213 0 : break;
1214 : default:
1215 0 : elog(ERROR, "unrecognized CmdType: %d", (int) operation);
1216 : break;
1217 : }
1218 0 : break;
1219 : default:
1220 0 : ereport(ERROR,
1221 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1222 : errmsg("cannot change relation \"%s\"",
1223 : RelationGetRelationName(resultRel))));
1224 : break;
1225 : }
1226 4832 : }
1227 :
1228 : /*
1229 : * Check that a proposed rowmark target relation is a legal target
1230 : *
1231 : * In most cases parser and/or planner should have noticed this already, but
1232 : * they don't cover all cases.
1233 : */
1234 : static void
1235 534 : CheckValidRowMarkRel(Relation rel, RowMarkType markType)
1236 : {
1237 : FdwRoutine *fdwroutine;
1238 :
1239 534 : switch (rel->rd_rel->relkind)
1240 : {
1241 : case RELKIND_RELATION:
1242 : case RELKIND_PARTITIONED_TABLE:
1243 : /* OK */
1244 532 : break;
1245 : case RELKIND_SEQUENCE:
1246 : /* Must disallow this because we don't vacuum sequences */
1247 0 : ereport(ERROR,
1248 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1249 : errmsg("cannot lock rows in sequence \"%s\"",
1250 : RelationGetRelationName(rel))));
1251 : break;
1252 : case RELKIND_TOASTVALUE:
1253 : /* We could allow this, but there seems no good reason to */
1254 0 : ereport(ERROR,
1255 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1256 : errmsg("cannot lock rows in TOAST relation \"%s\"",
1257 : RelationGetRelationName(rel))));
1258 : break;
1259 : case RELKIND_VIEW:
1260 : /* Should not get here; planner should have expanded the view */
1261 0 : ereport(ERROR,
1262 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1263 : errmsg("cannot lock rows in view \"%s\"",
1264 : RelationGetRelationName(rel))));
1265 : break;
1266 : case RELKIND_MATVIEW:
1267 : /* Allow referencing a matview, but not actual locking clauses */
1268 2 : if (markType != ROW_MARK_REFERENCE)
1269 1 : ereport(ERROR,
1270 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1271 : errmsg("cannot lock rows in materialized view \"%s\"",
1272 : RelationGetRelationName(rel))));
1273 1 : break;
1274 : case RELKIND_FOREIGN_TABLE:
1275 : /* Okay only if the FDW supports it */
1276 0 : fdwroutine = GetFdwRoutineForRelation(rel, false);
1277 0 : if (fdwroutine->RefetchForeignRow == NULL)
1278 0 : ereport(ERROR,
1279 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1280 : errmsg("cannot lock rows in foreign table \"%s\"",
1281 : RelationGetRelationName(rel))));
1282 0 : break;
1283 : default:
1284 0 : ereport(ERROR,
1285 : (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1286 : errmsg("cannot lock rows in relation \"%s\"",
1287 : RelationGetRelationName(rel))));
1288 : break;
1289 : }
1290 533 : }
1291 :
1292 : /*
1293 : * Initialize ResultRelInfo data for one result relation
1294 : *
1295 : * Caution: before Postgres 9.1, this function included the relkind checking
1296 : * that's now in CheckValidResultRel, and it also did ExecOpenIndices if
1297 : * appropriate. Be sure callers cover those needs.
1298 : */
1299 : void
1300 5079 : InitResultRelInfo(ResultRelInfo *resultRelInfo,
1301 : Relation resultRelationDesc,
1302 : Index resultRelationIndex,
1303 : Relation partition_root,
1304 : int instrument_options)
1305 : {
1306 5079 : List *partition_check = NIL;
1307 :
1308 5079 : MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
1309 5079 : resultRelInfo->type = T_ResultRelInfo;
1310 5079 : resultRelInfo->ri_RangeTableIndex = resultRelationIndex;
1311 5079 : resultRelInfo->ri_RelationDesc = resultRelationDesc;
1312 5079 : resultRelInfo->ri_NumIndices = 0;
1313 5079 : resultRelInfo->ri_IndexRelationDescs = NULL;
1314 5079 : resultRelInfo->ri_IndexRelationInfo = NULL;
1315 : /* make a copy so as not to depend on relcache info not changing... */
1316 5079 : resultRelInfo->ri_TrigDesc = CopyTriggerDesc(resultRelationDesc->trigdesc);
1317 5079 : if (resultRelInfo->ri_TrigDesc)
1318 : {
1319 1119 : int n = resultRelInfo->ri_TrigDesc->numtriggers;
1320 :
1321 1119 : resultRelInfo->ri_TrigFunctions = (FmgrInfo *)
1322 1119 : palloc0(n * sizeof(FmgrInfo));
1323 1119 : resultRelInfo->ri_TrigWhenExprs = (ExprState **)
1324 1119 : palloc0(n * sizeof(ExprState *));
1325 1119 : if (instrument_options)
1326 0 : resultRelInfo->ri_TrigInstrument = InstrAlloc(n, instrument_options);
1327 : }
1328 : else
1329 : {
1330 3960 : resultRelInfo->ri_TrigFunctions = NULL;
1331 3960 : resultRelInfo->ri_TrigWhenExprs = NULL;
1332 3960 : resultRelInfo->ri_TrigInstrument = NULL;
1333 : }
1334 5079 : if (resultRelationDesc->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1335 0 : resultRelInfo->ri_FdwRoutine = GetFdwRoutineForRelation(resultRelationDesc, true);
1336 : else
1337 5079 : resultRelInfo->ri_FdwRoutine = NULL;
1338 5079 : resultRelInfo->ri_FdwState = NULL;
1339 5079 : resultRelInfo->ri_usesFdwDirectModify = false;
1340 5079 : resultRelInfo->ri_ConstraintExprs = NULL;
1341 5079 : resultRelInfo->ri_junkFilter = NULL;
1342 5079 : resultRelInfo->ri_projectReturning = NULL;
1343 :
1344 : /*
1345 : * Partition constraint, which also includes the partition constraint of
1346 : * all the ancestors that are partitions. Note that it will be checked
1347 : * even in the case of tuple-routing where this table is the target leaf
1348 : * partition, if there any BR triggers defined on the table. Although
1349 : * tuple-routing implicitly preserves the partition constraint of the
1350 : * target partition for a given row, the BR triggers may change the row
1351 : * such that the constraint is no longer satisfied, which we must fail for
1352 : * by checking it explicitly.
1353 : *
1354 : * If this is a partitioned table, the partition constraint (if any) of a
1355 : * given row will be checked just before performing tuple-routing.
1356 : */
1357 5079 : partition_check = RelationGetPartitionQual(resultRelationDesc);
1358 :
1359 5079 : resultRelInfo->ri_PartitionCheck = partition_check;
1360 5079 : resultRelInfo->ri_PartitionRoot = partition_root;
1361 5079 : }
1362 :
1363 : /*
1364 : * ExecGetTriggerResultRel
1365 : *
1366 : * Get a ResultRelInfo for a trigger target relation. Most of the time,
1367 : * triggers are fired on one of the result relations of the query, and so
1368 : * we can just return a member of the es_result_relations array, the
1369 : * es_root_result_relations array (if any), or the es_leaf_result_relations
1370 : * list (if any). (Note: in self-join situations there might be multiple
1371 : * members with the same OID; if so it doesn't matter which one we pick.)
1372 : * However, it is sometimes necessary to fire triggers on other relations;
1373 : * this happens mainly when an RI update trigger queues additional triggers
1374 : * on other relations, which will be processed in the context of the outer
1375 : * query. For efficiency's sake, we want to have a ResultRelInfo for those
1376 : * triggers too; that can avoid repeated re-opening of the relation. (It
1377 : * also provides a way for EXPLAIN ANALYZE to report the runtimes of such
1378 : * triggers.) So we make additional ResultRelInfo's as needed, and save them
1379 : * in es_trig_target_relations.
1380 : */
1381 : ResultRelInfo *
1382 663 : ExecGetTriggerResultRel(EState *estate, Oid relid)
1383 : {
1384 : ResultRelInfo *rInfo;
1385 : int nr;
1386 : ListCell *l;
1387 : Relation rel;
1388 : MemoryContext oldcontext;
1389 :
1390 : /* First, search through the query result relations */
1391 663 : rInfo = estate->es_result_relations;
1392 663 : nr = estate->es_num_result_relations;
1393 1363 : while (nr > 0)
1394 : {
1395 655 : if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1396 618 : return rInfo;
1397 37 : rInfo++;
1398 37 : nr--;
1399 : }
1400 : /* Second, search through the root result relations, if any */
1401 45 : rInfo = estate->es_root_result_relations;
1402 45 : nr = estate->es_num_root_result_relations;
1403 91 : while (nr > 0)
1404 : {
1405 7 : if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1406 6 : return rInfo;
1407 1 : rInfo++;
1408 1 : nr--;
1409 : }
1410 : /* Third, search through the leaf result relations, if any */
1411 41 : foreach(l, estate->es_leaf_result_relations)
1412 : {
1413 4 : rInfo = (ResultRelInfo *) lfirst(l);
1414 4 : if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1415 2 : return rInfo;
1416 : }
1417 : /* Nope, but maybe we already made an extra ResultRelInfo for it */
1418 37 : foreach(l, estate->es_trig_target_relations)
1419 : {
1420 0 : rInfo = (ResultRelInfo *) lfirst(l);
1421 0 : if (RelationGetRelid(rInfo->ri_RelationDesc) == relid)
1422 0 : return rInfo;
1423 : }
1424 : /* Nope, so we need a new one */
1425 :
1426 : /*
1427 : * Open the target relation's relcache entry. We assume that an
1428 : * appropriate lock is still held by the backend from whenever the trigger
1429 : * event got queued, so we need take no new lock here. Also, we need not
1430 : * recheck the relkind, so no need for CheckValidResultRel.
1431 : */
1432 37 : rel = heap_open(relid, NoLock);
1433 :
1434 : /*
1435 : * Make the new entry in the right context.
1436 : */
1437 37 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
1438 37 : rInfo = makeNode(ResultRelInfo);
1439 37 : InitResultRelInfo(rInfo,
1440 : rel,
1441 : 0, /* dummy rangetable index */
1442 : NULL,
1443 : estate->es_instrument);
1444 37 : estate->es_trig_target_relations =
1445 37 : lappend(estate->es_trig_target_relations, rInfo);
1446 37 : MemoryContextSwitchTo(oldcontext);
1447 :
1448 : /*
1449 : * Currently, we don't need any index information in ResultRelInfos used
1450 : * only for triggers, so no need to call ExecOpenIndices.
1451 : */
1452 :
1453 37 : return rInfo;
1454 : }
1455 :
1456 : /*
1457 : * Close any relations that have been opened by ExecGetTriggerResultRel().
1458 : */
1459 : void
1460 21422 : ExecCleanUpTriggerState(EState *estate)
1461 : {
1462 : ListCell *l;
1463 :
1464 21442 : foreach(l, estate->es_trig_target_relations)
1465 : {
1466 20 : ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
1467 :
1468 : /* Close indices and then the relation itself */
1469 20 : ExecCloseIndices(resultRelInfo);
1470 20 : heap_close(resultRelInfo->ri_RelationDesc, NoLock);
1471 : }
1472 21422 : }
1473 :
1474 : /*
1475 : * ExecContextForcesOids
1476 : *
1477 : * This is pretty grotty: when doing INSERT, UPDATE, or CREATE TABLE AS,
1478 : * we need to ensure that result tuples have space for an OID iff they are
1479 : * going to be stored into a relation that has OIDs. In other contexts
1480 : * we are free to choose whether to leave space for OIDs in result tuples
1481 : * (we generally don't want to, but we do if a physical-tlist optimization
1482 : * is possible). This routine checks the plan context and returns TRUE if the
1483 : * choice is forced, FALSE if the choice is not forced. In the TRUE case,
1484 : * *hasoids is set to the required value.
1485 : *
1486 : * One reason this is ugly is that all plan nodes in the plan tree will emit
1487 : * tuples with space for an OID, though we really only need the topmost node
1488 : * to do so. However, node types like Sort don't project new tuples but just
1489 : * return their inputs, and in those cases the requirement propagates down
1490 : * to the input node. Eventually we might make this code smart enough to
1491 : * recognize how far down the requirement really goes, but for now we just
1492 : * make all plan nodes do the same thing if the top level forces the choice.
1493 : *
1494 : * We assume that if we are generating tuples for INSERT or UPDATE,
1495 : * estate->es_result_relation_info is already set up to describe the target
1496 : * relation. Note that in an UPDATE that spans an inheritance tree, some of
1497 : * the target relations may have OIDs and some not. We have to make the
1498 : * decisions on a per-relation basis as we initialize each of the subplans of
1499 : * the ModifyTable node, so ModifyTable has to set es_result_relation_info
1500 : * while initializing each subplan.
1501 : *
1502 : * CREATE TABLE AS is even uglier, because we don't have the target relation's
1503 : * descriptor available when this code runs; we have to look aside at the
1504 : * flags passed to ExecutorStart().
1505 : */
1506 : bool
1507 54647 : ExecContextForcesOids(PlanState *planstate, bool *hasoids)
1508 : {
1509 54647 : ResultRelInfo *ri = planstate->state->es_result_relation_info;
1510 :
1511 54647 : if (ri != NULL)
1512 : {
1513 5670 : Relation rel = ri->ri_RelationDesc;
1514 :
1515 5670 : if (rel != NULL)
1516 : {
1517 5670 : *hasoids = rel->rd_rel->relhasoids;
1518 5670 : return true;
1519 : }
1520 : }
1521 :
1522 48977 : if (planstate->state->es_top_eflags & EXEC_FLAG_WITH_OIDS)
1523 : {
1524 2 : *hasoids = true;
1525 2 : return true;
1526 : }
1527 48975 : if (planstate->state->es_top_eflags & EXEC_FLAG_WITHOUT_OIDS)
1528 : {
1529 294 : *hasoids = false;
1530 294 : return true;
1531 : }
1532 :
1533 48681 : return false;
1534 : }
1535 :
1536 : /* ----------------------------------------------------------------
1537 : * ExecPostprocessPlan
1538 : *
1539 : * Give plan nodes a final chance to execute before shutdown
1540 : * ----------------------------------------------------------------
1541 : */
1542 : static void
1543 20277 : ExecPostprocessPlan(EState *estate)
1544 : {
1545 : ListCell *lc;
1546 :
1547 : /*
1548 : * Make sure nodes run forward.
1549 : */
1550 20277 : estate->es_direction = ForwardScanDirection;
1551 :
1552 : /*
1553 : * Run any secondary ModifyTable nodes to completion, in case the main
1554 : * query did not fetch all rows from them. (We do this to ensure that
1555 : * such nodes have predictable results.)
1556 : */
1557 20394 : foreach(lc, estate->es_auxmodifytables)
1558 : {
1559 117 : PlanState *ps = (PlanState *) lfirst(lc);
1560 :
1561 : for (;;)
1562 : {
1563 : TupleTableSlot *slot;
1564 :
1565 : /* Reset the per-output-tuple exprcontext each time */
1566 140 : ResetPerTupleExprContext(estate);
1567 :
1568 140 : slot = ExecProcNode(ps);
1569 :
1570 140 : if (TupIsNull(slot))
1571 : break;
1572 23 : }
1573 : }
1574 20277 : }
1575 :
1576 : /* ----------------------------------------------------------------
1577 : * ExecEndPlan
1578 : *
1579 : * Cleans up the query plan -- closes files and frees up storage
1580 : *
1581 : * NOTE: we are no longer very worried about freeing storage per se
1582 : * in this code; FreeExecutorState should be guaranteed to release all
1583 : * memory that needs to be released. What we are worried about doing
1584 : * is closing relations and dropping buffer pins. Thus, for example,
1585 : * tuple tables must be cleared or dropped to ensure pins are released.
1586 : * ----------------------------------------------------------------
1587 : */
1588 : static void
1589 21321 : ExecEndPlan(PlanState *planstate, EState *estate)
1590 : {
1591 : ResultRelInfo *resultRelInfo;
1592 : int i;
1593 : ListCell *l;
1594 :
1595 : /*
1596 : * shut down the node-type-specific query processing
1597 : */
1598 21321 : ExecEndNode(planstate);
1599 :
1600 : /*
1601 : * for subplans too
1602 : */
1603 24490 : foreach(l, estate->es_subplanstates)
1604 : {
1605 3169 : PlanState *subplanstate = (PlanState *) lfirst(l);
1606 :
1607 3169 : ExecEndNode(subplanstate);
1608 : }
1609 :
1610 : /*
1611 : * destroy the executor's tuple table. Actually we only care about
1612 : * releasing buffer pins and tupdesc refcounts; there's no need to pfree
1613 : * the TupleTableSlots, since the containing memory context is about to go
1614 : * away anyway.
1615 : */
1616 21321 : ExecResetTupleTable(estate->es_tupleTable, false);
1617 :
1618 : /*
1619 : * close the result relation(s) if any, but hold locks until xact commit.
1620 : */
1621 21321 : resultRelInfo = estate->es_result_relations;
1622 25589 : for (i = estate->es_num_result_relations; i > 0; i--)
1623 : {
1624 : /* Close indices and then the relation itself */
1625 4268 : ExecCloseIndices(resultRelInfo);
1626 4268 : heap_close(resultRelInfo->ri_RelationDesc, NoLock);
1627 4268 : resultRelInfo++;
1628 : }
1629 :
1630 : /* Close the root target relation(s). */
1631 21321 : resultRelInfo = estate->es_root_result_relations;
1632 21331 : for (i = estate->es_num_root_result_relations; i > 0; i--)
1633 : {
1634 10 : heap_close(resultRelInfo->ri_RelationDesc, NoLock);
1635 10 : resultRelInfo++;
1636 : }
1637 :
1638 : /* likewise close any trigger target relations */
1639 21321 : ExecCleanUpTriggerState(estate);
1640 :
1641 : /*
1642 : * close any relations selected FOR [KEY] UPDATE/SHARE, again keeping
1643 : * locks
1644 : */
1645 21862 : foreach(l, estate->es_rowMarks)
1646 : {
1647 541 : ExecRowMark *erm = (ExecRowMark *) lfirst(l);
1648 :
1649 541 : if (erm->relation)
1650 519 : heap_close(erm->relation, NoLock);
1651 : }
1652 21321 : }
1653 :
1654 : /* ----------------------------------------------------------------
1655 : * ExecutePlan
1656 : *
1657 : * Processes the query plan until we have retrieved 'numberTuples' tuples,
1658 : * moving in the specified direction.
1659 : *
1660 : * Runs to completion if numberTuples is 0
1661 : *
1662 : * Note: the ctid attribute is a 'junk' attribute that is removed before the
1663 : * user can see it
1664 : * ----------------------------------------------------------------
1665 : */
1666 : static void
1667 23779 : ExecutePlan(EState *estate,
1668 : PlanState *planstate,
1669 : bool use_parallel_mode,
1670 : CmdType operation,
1671 : bool sendTuples,
1672 : uint64 numberTuples,
1673 : ScanDirection direction,
1674 : DestReceiver *dest,
1675 : bool execute_once)
1676 : {
1677 : TupleTableSlot *slot;
1678 : uint64 current_tuple_count;
1679 :
1680 : /*
1681 : * initialize local variables
1682 : */
1683 23779 : current_tuple_count = 0;
1684 :
1685 : /*
1686 : * Set the direction.
1687 : */
1688 23779 : estate->es_direction = direction;
1689 :
1690 : /*
1691 : * If the plan might potentially be executed multiple times, we must force
1692 : * it to run without parallelism, because we might exit early. Also
1693 : * disable parallelism when writing into a relation, because no database
1694 : * changes are allowed in parallel mode.
1695 : */
1696 23779 : if (!execute_once || dest->mydest == DestIntoRel)
1697 1262 : use_parallel_mode = false;
1698 :
1699 23779 : if (use_parallel_mode)
1700 17 : EnterParallelMode();
1701 :
1702 : /*
1703 : * Loop until we've processed the proper number of tuples from the plan.
1704 : */
1705 : for (;;)
1706 : {
1707 : /* Reset the per-output-tuple exprcontext */
1708 186065 : ResetPerTupleExprContext(estate);
1709 :
1710 : /*
1711 : * Execute the plan and obtain a tuple
1712 : */
1713 186065 : slot = ExecProcNode(planstate);
1714 :
1715 : /*
1716 : * if the tuple is null, then we assume there is nothing more to
1717 : * process so we just end the loop...
1718 : */
1719 182911 : if (TupIsNull(slot))
1720 : {
1721 : /* Allow nodes to release or shut down resources. */
1722 17704 : (void) ExecShutdownNode(planstate);
1723 17704 : break;
1724 : }
1725 :
1726 : /*
1727 : * If we have a junk filter, then project a new tuple with the junk
1728 : * removed.
1729 : *
1730 : * Store this new "clean" tuple in the junkfilter's resultSlot.
1731 : * (Formerly, we stored it back over the "dirty" tuple, which is WRONG
1732 : * because that tuple slot has the wrong descriptor.)
1733 : */
1734 165207 : if (estate->es_junkFilter != NULL)
1735 2786 : slot = ExecFilterJunk(estate->es_junkFilter, slot);
1736 :
1737 : /*
1738 : * If we are supposed to send the tuple somewhere, do so. (In
1739 : * practice, this is probably always the case at this point.)
1740 : */
1741 165207 : if (sendTuples)
1742 : {
1743 : /*
1744 : * If we are not able to send the tuple, we assume the destination
1745 : * has closed and no more tuples can be sent. If that's the case,
1746 : * end the loop.
1747 : */
1748 165207 : if (!((*dest->receiveSlot) (slot, dest)))
1749 0 : break;
1750 : }
1751 :
1752 : /*
1753 : * Count tuples processed, if this is a SELECT. (For other operation
1754 : * types, the ModifyTable plan node must count the appropriate
1755 : * events.)
1756 : */
1757 165207 : if (operation == CMD_SELECT)
1758 164885 : (estate->es_processed)++;
1759 :
1760 : /*
1761 : * check our tuple count.. if we've processed the proper number then
1762 : * quit, else loop again and process more tuples. Zero numberTuples
1763 : * means no limit.
1764 : */
1765 165207 : current_tuple_count++;
1766 165207 : if (numberTuples && numberTuples == current_tuple_count)
1767 : {
1768 : /* Allow nodes to release or shut down resources. */
1769 2921 : (void) ExecShutdownNode(planstate);
1770 2921 : break;
1771 : }
1772 162286 : }
1773 :
1774 20625 : if (use_parallel_mode)
1775 16 : ExitParallelMode();
1776 20625 : }
1777 :
1778 :
1779 : /*
1780 : * ExecRelCheck --- check that tuple meets constraints for result relation
1781 : *
1782 : * Returns NULL if OK, else name of failed check constraint
1783 : */
1784 : static const char *
1785 191 : ExecRelCheck(ResultRelInfo *resultRelInfo,
1786 : TupleTableSlot *slot, EState *estate)
1787 : {
1788 191 : Relation rel = resultRelInfo->ri_RelationDesc;
1789 191 : int ncheck = rel->rd_att->constr->num_check;
1790 191 : ConstrCheck *check = rel->rd_att->constr->check;
1791 : ExprContext *econtext;
1792 : MemoryContext oldContext;
1793 : int i;
1794 :
1795 : /*
1796 : * If first time through for this result relation, build expression
1797 : * nodetrees for rel's constraint expressions. Keep them in the per-query
1798 : * memory context so they'll survive throughout the query.
1799 : */
1800 191 : if (resultRelInfo->ri_ConstraintExprs == NULL)
1801 : {
1802 112 : oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
1803 112 : resultRelInfo->ri_ConstraintExprs =
1804 112 : (ExprState **) palloc(ncheck * sizeof(ExprState *));
1805 260 : for (i = 0; i < ncheck; i++)
1806 : {
1807 : Expr *checkconstr;
1808 :
1809 148 : checkconstr = stringToNode(check[i].ccbin);
1810 296 : resultRelInfo->ri_ConstraintExprs[i] =
1811 148 : ExecPrepareExpr(checkconstr, estate);
1812 : }
1813 112 : MemoryContextSwitchTo(oldContext);
1814 : }
1815 :
1816 : /*
1817 : * We will use the EState's per-tuple context for evaluating constraint
1818 : * expressions (creating it if it's not already there).
1819 : */
1820 191 : econtext = GetPerTupleExprContext(estate);
1821 :
1822 : /* Arrange for econtext's scan tuple to be the tuple under test */
1823 191 : econtext->ecxt_scantuple = slot;
1824 :
1825 : /* And evaluate the constraints */
1826 412 : for (i = 0; i < ncheck; i++)
1827 : {
1828 271 : ExprState *checkconstr = resultRelInfo->ri_ConstraintExprs[i];
1829 :
1830 : /*
1831 : * NOTE: SQL specifies that a NULL result from a constraint expression
1832 : * is not to be treated as a failure. Therefore, use ExecCheck not
1833 : * ExecQual.
1834 : */
1835 271 : if (!ExecCheck(checkconstr, econtext))
1836 50 : return check[i].ccname;
1837 : }
1838 :
1839 : /* NULL result means no error */
1840 141 : return NULL;
1841 : }
1842 :
1843 : /*
1844 : * ExecPartitionCheck --- check that tuple meets the partition constraint.
1845 : */
1846 : static void
1847 107 : ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
1848 : EState *estate)
1849 : {
1850 107 : Relation rel = resultRelInfo->ri_RelationDesc;
1851 107 : TupleDesc tupdesc = RelationGetDescr(rel);
1852 : Bitmapset *modifiedCols;
1853 : Bitmapset *insertedCols;
1854 : Bitmapset *updatedCols;
1855 : ExprContext *econtext;
1856 :
1857 : /*
1858 : * If first time through, build expression state tree for the partition
1859 : * check expression. Keep it in the per-query memory context so they'll
1860 : * survive throughout the query.
1861 : */
1862 107 : if (resultRelInfo->ri_PartitionCheckExpr == NULL)
1863 : {
1864 72 : List *qual = resultRelInfo->ri_PartitionCheck;
1865 :
1866 72 : resultRelInfo->ri_PartitionCheckExpr = ExecPrepareCheck(qual, estate);
1867 : }
1868 :
1869 : /*
1870 : * We will use the EState's per-tuple context for evaluating constraint
1871 : * expressions (creating it if it's not already there).
1872 : */
1873 107 : econtext = GetPerTupleExprContext(estate);
1874 :
1875 : /* Arrange for econtext's scan tuple to be the tuple under test */
1876 107 : econtext->ecxt_scantuple = slot;
1877 :
1878 : /*
1879 : * As in case of the catalogued constraints, we treat a NULL result as
1880 : * success here, not a failure.
1881 : */
1882 107 : if (!ExecCheck(resultRelInfo->ri_PartitionCheckExpr, econtext))
1883 : {
1884 : char *val_desc;
1885 20 : Relation orig_rel = rel;
1886 :
1887 : /* See the comment above. */
1888 20 : if (resultRelInfo->ri_PartitionRoot)
1889 : {
1890 3 : HeapTuple tuple = ExecFetchSlotTuple(slot);
1891 3 : TupleDesc old_tupdesc = RelationGetDescr(rel);
1892 : TupleConversionMap *map;
1893 :
1894 3 : rel = resultRelInfo->ri_PartitionRoot;
1895 3 : tupdesc = RelationGetDescr(rel);
1896 : /* a reverse map */
1897 3 : map = convert_tuples_by_name(old_tupdesc, tupdesc,
1898 : gettext_noop("could not convert row type"));
1899 3 : if (map != NULL)
1900 : {
1901 1 : tuple = do_convert_tuple(tuple, map);
1902 1 : ExecSetSlotDescriptor(slot, tupdesc);
1903 1 : ExecStoreTuple(tuple, slot, InvalidBuffer, false);
1904 : }
1905 : }
1906 :
1907 20 : insertedCols = GetInsertedColumns(resultRelInfo, estate);
1908 20 : updatedCols = GetUpdatedColumns(resultRelInfo, estate);
1909 20 : modifiedCols = bms_union(insertedCols, updatedCols);
1910 20 : val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
1911 : slot,
1912 : tupdesc,
1913 : modifiedCols,
1914 : 64);
1915 20 : ereport(ERROR,
1916 : (errcode(ERRCODE_CHECK_VIOLATION),
1917 : errmsg("new row for relation \"%s\" violates partition constraint",
1918 : RelationGetRelationName(orig_rel)),
1919 : val_desc ? errdetail("Failing row contains %s.", val_desc) : 0));
1920 : }
1921 87 : }
1922 :
1923 : /*
1924 : * ExecConstraints - check constraints of the tuple in 'slot'
1925 : *
1926 : * This checks the traditional NOT NULL and check constraints, as well as
1927 : * the partition constraint, if any.
1928 : *
1929 : * Note: 'slot' contains the tuple to check the constraints of, which may
1930 : * have been converted from the original input tuple after tuple routing.
1931 : * 'resultRelInfo' is the original result relation, before tuple routing.
1932 : */
1933 : void
1934 35641 : ExecConstraints(ResultRelInfo *resultRelInfo,
1935 : TupleTableSlot *slot, EState *estate)
1936 : {
1937 35641 : Relation rel = resultRelInfo->ri_RelationDesc;
1938 35641 : TupleDesc tupdesc = RelationGetDescr(rel);
1939 35641 : TupleConstr *constr = tupdesc->constr;
1940 : Bitmapset *modifiedCols;
1941 : Bitmapset *insertedCols;
1942 : Bitmapset *updatedCols;
1943 :
1944 35641 : Assert(constr || resultRelInfo->ri_PartitionCheck);
1945 :
1946 35641 : if (constr && constr->has_not_null)
1947 : {
1948 35294 : int natts = tupdesc->natts;
1949 : int attrChk;
1950 :
1951 167528 : for (attrChk = 1; attrChk <= natts; attrChk++)
1952 : {
1953 132260 : Form_pg_attribute att = TupleDescAttr(tupdesc, attrChk - 1);
1954 :
1955 132260 : if (att->attnotnull && slot_attisnull(slot, attrChk))
1956 : {
1957 : char *val_desc;
1958 26 : Relation orig_rel = rel;
1959 26 : TupleDesc orig_tupdesc = RelationGetDescr(rel);
1960 :
1961 : /*
1962 : * If the tuple has been routed, it's been converted to the
1963 : * partition's rowtype, which might differ from the root
1964 : * table's. We must convert it back to the root table's
1965 : * rowtype so that val_desc shown error message matches the
1966 : * input tuple.
1967 : */
1968 26 : if (resultRelInfo->ri_PartitionRoot)
1969 : {
1970 0 : HeapTuple tuple = ExecFetchSlotTuple(slot);
1971 : TupleConversionMap *map;
1972 :
1973 0 : rel = resultRelInfo->ri_PartitionRoot;
1974 0 : tupdesc = RelationGetDescr(rel);
1975 : /* a reverse map */
1976 0 : map = convert_tuples_by_name(orig_tupdesc, tupdesc,
1977 : gettext_noop("could not convert row type"));
1978 0 : if (map != NULL)
1979 : {
1980 0 : tuple = do_convert_tuple(tuple, map);
1981 0 : ExecSetSlotDescriptor(slot, tupdesc);
1982 0 : ExecStoreTuple(tuple, slot, InvalidBuffer, false);
1983 : }
1984 : }
1985 :
1986 26 : insertedCols = GetInsertedColumns(resultRelInfo, estate);
1987 26 : updatedCols = GetUpdatedColumns(resultRelInfo, estate);
1988 26 : modifiedCols = bms_union(insertedCols, updatedCols);
1989 26 : val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
1990 : slot,
1991 : tupdesc,
1992 : modifiedCols,
1993 : 64);
1994 :
1995 26 : ereport(ERROR,
1996 : (errcode(ERRCODE_NOT_NULL_VIOLATION),
1997 : errmsg("null value in column \"%s\" violates not-null constraint",
1998 : NameStr(att->attname)),
1999 : val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2000 : errtablecol(orig_rel, attrChk)));
2001 : }
2002 : }
2003 : }
2004 :
2005 35615 : if (constr && constr->num_check > 0)
2006 : {
2007 : const char *failed;
2008 :
2009 191 : if ((failed = ExecRelCheck(resultRelInfo, slot, estate)) != NULL)
2010 : {
2011 : char *val_desc;
2012 50 : Relation orig_rel = rel;
2013 :
2014 : /* See the comment above. */
2015 50 : if (resultRelInfo->ri_PartitionRoot)
2016 : {
2017 2 : HeapTuple tuple = ExecFetchSlotTuple(slot);
2018 2 : TupleDesc old_tupdesc = RelationGetDescr(rel);
2019 : TupleConversionMap *map;
2020 :
2021 2 : rel = resultRelInfo->ri_PartitionRoot;
2022 2 : tupdesc = RelationGetDescr(rel);
2023 : /* a reverse map */
2024 2 : map = convert_tuples_by_name(old_tupdesc, tupdesc,
2025 : gettext_noop("could not convert row type"));
2026 2 : if (map != NULL)
2027 : {
2028 2 : tuple = do_convert_tuple(tuple, map);
2029 2 : ExecSetSlotDescriptor(slot, tupdesc);
2030 2 : ExecStoreTuple(tuple, slot, InvalidBuffer, false);
2031 : }
2032 : }
2033 :
2034 50 : insertedCols = GetInsertedColumns(resultRelInfo, estate);
2035 50 : updatedCols = GetUpdatedColumns(resultRelInfo, estate);
2036 50 : modifiedCols = bms_union(insertedCols, updatedCols);
2037 50 : val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
2038 : slot,
2039 : tupdesc,
2040 : modifiedCols,
2041 : 64);
2042 50 : ereport(ERROR,
2043 : (errcode(ERRCODE_CHECK_VIOLATION),
2044 : errmsg("new row for relation \"%s\" violates check constraint \"%s\"",
2045 : RelationGetRelationName(orig_rel), failed),
2046 : val_desc ? errdetail("Failing row contains %s.", val_desc) : 0,
2047 : errtableconstraint(orig_rel, failed)));
2048 : }
2049 : }
2050 :
2051 35565 : if (resultRelInfo->ri_PartitionCheck)
2052 103 : ExecPartitionCheck(resultRelInfo, slot, estate);
2053 35546 : }
2054 :
2055 :
2056 : /*
2057 : * ExecWithCheckOptions -- check that tuple satisfies any WITH CHECK OPTIONs
2058 : * of the specified kind.
2059 : *
2060 : * Note that this needs to be called multiple times to ensure that all kinds of
2061 : * WITH CHECK OPTIONs are handled (both those from views which have the WITH
2062 : * CHECK OPTION set and from row level security policies). See ExecInsert()
2063 : * and ExecUpdate().
2064 : */
2065 : void
2066 241 : ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
2067 : TupleTableSlot *slot, EState *estate)
2068 : {
2069 241 : Relation rel = resultRelInfo->ri_RelationDesc;
2070 241 : TupleDesc tupdesc = RelationGetDescr(rel);
2071 : ExprContext *econtext;
2072 : ListCell *l1,
2073 : *l2;
2074 :
2075 : /*
2076 : * We will use the EState's per-tuple context for evaluating constraint
2077 : * expressions (creating it if it's not already there).
2078 : */
2079 241 : econtext = GetPerTupleExprContext(estate);
2080 :
2081 : /* Arrange for econtext's scan tuple to be the tuple under test */
2082 241 : econtext->ecxt_scantuple = slot;
2083 :
2084 : /* Check each of the constraints */
2085 507 : forboth(l1, resultRelInfo->ri_WithCheckOptions,
2086 : l2, resultRelInfo->ri_WithCheckOptionExprs)
2087 : {
2088 321 : WithCheckOption *wco = (WithCheckOption *) lfirst(l1);
2089 321 : ExprState *wcoExpr = (ExprState *) lfirst(l2);
2090 :
2091 : /*
2092 : * Skip any WCOs which are not the kind we are looking for at this
2093 : * time.
2094 : */
2095 321 : if (wco->kind != kind)
2096 160 : continue;
2097 :
2098 : /*
2099 : * WITH CHECK OPTION checks are intended to ensure that the new tuple
2100 : * is visible (in the case of a view) or that it passes the
2101 : * 'with-check' policy (in the case of row security). If the qual
2102 : * evaluates to NULL or FALSE, then the new tuple won't be included in
2103 : * the view or doesn't pass the 'with-check' policy for the table.
2104 : */
2105 161 : if (!ExecQual(wcoExpr, econtext))
2106 : {
2107 : char *val_desc;
2108 : Bitmapset *modifiedCols;
2109 : Bitmapset *insertedCols;
2110 : Bitmapset *updatedCols;
2111 :
2112 55 : switch (wco->kind)
2113 : {
2114 : /*
2115 : * For WITH CHECK OPTIONs coming from views, we might be
2116 : * able to provide the details on the row, depending on
2117 : * the permissions on the relation (that is, if the user
2118 : * could view it directly anyway). For RLS violations, we
2119 : * don't include the data since we don't know if the user
2120 : * should be able to view the tuple as that depends on the
2121 : * USING policy.
2122 : */
2123 : case WCO_VIEW_CHECK:
2124 : /* See the comment in ExecConstraints(). */
2125 29 : if (resultRelInfo->ri_PartitionRoot)
2126 : {
2127 3 : HeapTuple tuple = ExecFetchSlotTuple(slot);
2128 3 : TupleDesc old_tupdesc = RelationGetDescr(rel);
2129 : TupleConversionMap *map;
2130 :
2131 3 : rel = resultRelInfo->ri_PartitionRoot;
2132 3 : tupdesc = RelationGetDescr(rel);
2133 : /* a reverse map */
2134 3 : map = convert_tuples_by_name(old_tupdesc, tupdesc,
2135 : gettext_noop("could not convert row type"));
2136 3 : if (map != NULL)
2137 : {
2138 2 : tuple = do_convert_tuple(tuple, map);
2139 2 : ExecSetSlotDescriptor(slot, tupdesc);
2140 2 : ExecStoreTuple(tuple, slot, InvalidBuffer, false);
2141 : }
2142 : }
2143 :
2144 29 : insertedCols = GetInsertedColumns(resultRelInfo, estate);
2145 29 : updatedCols = GetUpdatedColumns(resultRelInfo, estate);
2146 29 : modifiedCols = bms_union(insertedCols, updatedCols);
2147 29 : val_desc = ExecBuildSlotValueDescription(RelationGetRelid(rel),
2148 : slot,
2149 : tupdesc,
2150 : modifiedCols,
2151 : 64);
2152 :
2153 29 : ereport(ERROR,
2154 : (errcode(ERRCODE_WITH_CHECK_OPTION_VIOLATION),
2155 : errmsg("new row violates check option for view \"%s\"",
2156 : wco->relname),
2157 : val_desc ? errdetail("Failing row contains %s.",
2158 : val_desc) : 0));
2159 : break;
2160 : case WCO_RLS_INSERT_CHECK:
2161 : case WCO_RLS_UPDATE_CHECK:
2162 22 : if (wco->polname != NULL)
2163 5 : ereport(ERROR,
2164 : (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2165 : errmsg("new row violates row-level security policy \"%s\" for table \"%s\"",
2166 : wco->polname, wco->relname)));
2167 : else
2168 17 : ereport(ERROR,
2169 : (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2170 : errmsg("new row violates row-level security policy for table \"%s\"",
2171 : wco->relname)));
2172 : break;
2173 : case WCO_RLS_CONFLICT_CHECK:
2174 4 : if (wco->polname != NULL)
2175 0 : ereport(ERROR,
2176 : (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2177 : errmsg("new row violates row-level security policy \"%s\" (USING expression) for table \"%s\"",
2178 : wco->polname, wco->relname)));
2179 : else
2180 4 : ereport(ERROR,
2181 : (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2182 : errmsg("new row violates row-level security policy (USING expression) for table \"%s\"",
2183 : wco->relname)));
2184 : break;
2185 : default:
2186 0 : elog(ERROR, "unrecognized WCO kind: %u", wco->kind);
2187 : break;
2188 : }
2189 : }
2190 : }
2191 186 : }
2192 :
2193 : /*
2194 : * ExecBuildSlotValueDescription -- construct a string representing a tuple
2195 : *
2196 : * This is intentionally very similar to BuildIndexValueDescription, but
2197 : * unlike that function, we truncate long field values (to at most maxfieldlen
2198 : * bytes). That seems necessary here since heap field values could be very
2199 : * long, whereas index entries typically aren't so wide.
2200 : *
2201 : * Also, unlike the case with index entries, we need to be prepared to ignore
2202 : * dropped columns. We used to use the slot's tuple descriptor to decode the
2203 : * data, but the slot's descriptor doesn't identify dropped columns, so we
2204 : * now need to be passed the relation's descriptor.
2205 : *
2206 : * Note that, like BuildIndexValueDescription, if the user does not have
2207 : * permission to view any of the columns involved, a NULL is returned. Unlike
2208 : * BuildIndexValueDescription, if the user has access to view a subset of the
2209 : * column involved, that subset will be returned with a key identifying which
2210 : * columns they are.
2211 : */
2212 : static char *
2213 125 : ExecBuildSlotValueDescription(Oid reloid,
2214 : TupleTableSlot *slot,
2215 : TupleDesc tupdesc,
2216 : Bitmapset *modifiedCols,
2217 : int maxfieldlen)
2218 : {
2219 : StringInfoData buf;
2220 : StringInfoData collist;
2221 125 : bool write_comma = false;
2222 125 : bool write_comma_collist = false;
2223 : int i;
2224 : AclResult aclresult;
2225 125 : bool table_perm = false;
2226 125 : bool any_perm = false;
2227 :
2228 : /*
2229 : * Check if RLS is enabled and should be active for the relation; if so,
2230 : * then don't return anything. Otherwise, go through normal permission
2231 : * checks.
2232 : */
2233 125 : if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED)
2234 0 : return NULL;
2235 :
2236 125 : initStringInfo(&buf);
2237 :
2238 125 : appendStringInfoChar(&buf, '(');
2239 :
2240 : /*
2241 : * Check if the user has permissions to see the row. Table-level SELECT
2242 : * allows access to all columns. If the user does not have table-level
2243 : * SELECT then we check each column and include those the user has SELECT
2244 : * rights on. Additionally, we always include columns the user provided
2245 : * data for.
2246 : */
2247 125 : aclresult = pg_class_aclcheck(reloid, GetUserId(), ACL_SELECT);
2248 125 : if (aclresult != ACLCHECK_OK)
2249 : {
2250 : /* Set up the buffer for the column list */
2251 5 : initStringInfo(&collist);
2252 5 : appendStringInfoChar(&collist, '(');
2253 : }
2254 : else
2255 120 : table_perm = any_perm = true;
2256 :
2257 : /* Make sure the tuple is fully deconstructed */
2258 125 : slot_getallattrs(slot);
2259 :
2260 420 : for (i = 0; i < tupdesc->natts; i++)
2261 : {
2262 295 : bool column_perm = false;
2263 : char *val;
2264 : int vallen;
2265 295 : Form_pg_attribute att = TupleDescAttr(tupdesc, i);
2266 :
2267 : /* ignore dropped columns */
2268 295 : if (att->attisdropped)
2269 2 : continue;
2270 :
2271 293 : if (!table_perm)
2272 : {
2273 : /*
2274 : * No table-level SELECT, so need to make sure they either have
2275 : * SELECT rights on the column or that they have provided the data
2276 : * for the column. If not, omit this column from the error
2277 : * message.
2278 : */
2279 14 : aclresult = pg_attribute_aclcheck(reloid, att->attnum,
2280 : GetUserId(), ACL_SELECT);
2281 14 : if (bms_is_member(att->attnum - FirstLowInvalidHeapAttributeNumber,
2282 7 : modifiedCols) || aclresult == ACLCHECK_OK)
2283 : {
2284 9 : column_perm = any_perm = true;
2285 :
2286 9 : if (write_comma_collist)
2287 4 : appendStringInfoString(&collist, ", ");
2288 : else
2289 5 : write_comma_collist = true;
2290 :
2291 9 : appendStringInfoString(&collist, NameStr(att->attname));
2292 : }
2293 : }
2294 :
2295 293 : if (table_perm || column_perm)
2296 : {
2297 288 : if (slot->tts_isnull[i])
2298 52 : val = "null";
2299 : else
2300 : {
2301 : Oid foutoid;
2302 : bool typisvarlena;
2303 :
2304 236 : getTypeOutputInfo(att->atttypid,
2305 : &foutoid, &typisvarlena);
2306 236 : val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
2307 : }
2308 :
2309 288 : if (write_comma)
2310 163 : appendStringInfoString(&buf, ", ");
2311 : else
2312 125 : write_comma = true;
2313 :
2314 : /* truncate if needed */
2315 288 : vallen = strlen(val);
2316 288 : if (vallen <= maxfieldlen)
2317 288 : appendStringInfoString(&buf, val);
2318 : else
2319 : {
2320 0 : vallen = pg_mbcliplen(val, vallen, maxfieldlen);
2321 0 : appendBinaryStringInfo(&buf, val, vallen);
2322 0 : appendStringInfoString(&buf, "...");
2323 : }
2324 : }
2325 : }
2326 :
2327 : /* If we end up with zero columns being returned, then return NULL. */
2328 125 : if (!any_perm)
2329 0 : return NULL;
2330 :
2331 125 : appendStringInfoChar(&buf, ')');
2332 :
2333 125 : if (!table_perm)
2334 : {
2335 5 : appendStringInfoString(&collist, ") = ");
2336 5 : appendStringInfoString(&collist, buf.data);
2337 :
2338 5 : return collist.data;
2339 : }
2340 :
2341 120 : return buf.data;
2342 : }
2343 :
2344 :
2345 : /*
2346 : * ExecUpdateLockMode -- find the appropriate UPDATE tuple lock mode for a
2347 : * given ResultRelInfo
2348 : */
2349 : LockTupleMode
2350 277 : ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo)
2351 : {
2352 : Bitmapset *keyCols;
2353 : Bitmapset *updatedCols;
2354 :
2355 : /*
2356 : * Compute lock mode to use. If columns that are part of the key have not
2357 : * been modified, then we can use a weaker lock, allowing for better
2358 : * concurrency.
2359 : */
2360 277 : updatedCols = GetUpdatedColumns(relinfo, estate);
2361 277 : keyCols = RelationGetIndexAttrBitmap(relinfo->ri_RelationDesc,
2362 : INDEX_ATTR_BITMAP_KEY);
2363 :
2364 277 : if (bms_overlap(keyCols, updatedCols))
2365 16 : return LockTupleExclusive;
2366 :
2367 261 : return LockTupleNoKeyExclusive;
2368 : }
2369 :
2370 : /*
2371 : * ExecFindRowMark -- find the ExecRowMark struct for given rangetable index
2372 : *
2373 : * If no such struct, either return NULL or throw error depending on missing_ok
2374 : */
2375 : ExecRowMark *
2376 18605 : ExecFindRowMark(EState *estate, Index rti, bool missing_ok)
2377 : {
2378 : ListCell *lc;
2379 :
2380 18965 : foreach(lc, estate->es_rowMarks)
2381 : {
2382 1463 : ExecRowMark *erm = (ExecRowMark *) lfirst(lc);
2383 :
2384 1463 : if (erm->rti == rti)
2385 1103 : return erm;
2386 : }
2387 17502 : if (!missing_ok)
2388 0 : elog(ERROR, "failed to find ExecRowMark for rangetable index %u", rti);
2389 17502 : return NULL;
2390 : }
2391 :
2392 : /*
2393 : * ExecBuildAuxRowMark -- create an ExecAuxRowMark struct
2394 : *
2395 : * Inputs are the underlying ExecRowMark struct and the targetlist of the
2396 : * input plan node (not planstate node!). We need the latter to find out
2397 : * the column numbers of the resjunk columns.
2398 : */
2399 : ExecAuxRowMark *
2400 600 : ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
2401 : {
2402 600 : ExecAuxRowMark *aerm = (ExecAuxRowMark *) palloc0(sizeof(ExecAuxRowMark));
2403 : char resname[32];
2404 :
2405 600 : aerm->rowmark = erm;
2406 :
2407 : /* Look up the resjunk columns associated with this rowmark */
2408 600 : if (erm->markType != ROW_MARK_COPY)
2409 : {
2410 : /* need ctid for all methods other than COPY */
2411 553 : snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
2412 553 : aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2413 : resname);
2414 553 : if (!AttributeNumberIsValid(aerm->ctidAttNo))
2415 0 : elog(ERROR, "could not find junk %s column", resname);
2416 : }
2417 : else
2418 : {
2419 : /* need wholerow if COPY */
2420 47 : snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
2421 47 : aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
2422 : resname);
2423 47 : if (!AttributeNumberIsValid(aerm->wholeAttNo))
2424 0 : elog(ERROR, "could not find junk %s column", resname);
2425 : }
2426 :
2427 : /* if child rel, need tableoid */
2428 600 : if (erm->rti != erm->prti)
2429 : {
2430 56 : snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
2431 56 : aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
2432 : resname);
2433 56 : if (!AttributeNumberIsValid(aerm->toidAttNo))
2434 0 : elog(ERROR, "could not find junk %s column", resname);
2435 : }
2436 :
2437 600 : return aerm;
2438 : }
2439 :
2440 :
2441 : /*
2442 : * EvalPlanQual logic --- recheck modified tuple(s) to see if we want to
2443 : * process the updated version under READ COMMITTED rules.
2444 : *
2445 : * See backend/executor/README for some info about how this works.
2446 : */
2447 :
2448 :
2449 : /*
2450 : * Check a modified tuple to see if we want to process its updated version
2451 : * under READ COMMITTED rules.
2452 : *
2453 : * estate - outer executor state data
2454 : * epqstate - state for EvalPlanQual rechecking
2455 : * relation - table containing tuple
2456 : * rti - rangetable index of table containing tuple
2457 : * lockmode - requested tuple lock mode
2458 : * *tid - t_ctid from the outdated tuple (ie, next updated version)
2459 : * priorXmax - t_xmax from the outdated tuple
2460 : *
2461 : * *tid is also an output parameter: it's modified to hold the TID of the
2462 : * latest version of the tuple (note this may be changed even on failure)
2463 : *
2464 : * Returns a slot containing the new candidate update/delete tuple, or
2465 : * NULL if we determine we shouldn't process the row.
2466 : *
2467 : * Note: properly, lockmode should be declared as enum LockTupleMode,
2468 : * but we use "int" to avoid having to include heapam.h in executor.h.
2469 : */
2470 : TupleTableSlot *
2471 0 : EvalPlanQual(EState *estate, EPQState *epqstate,
2472 : Relation relation, Index rti, int lockmode,
2473 : ItemPointer tid, TransactionId priorXmax)
2474 : {
2475 : TupleTableSlot *slot;
2476 : HeapTuple copyTuple;
2477 :
2478 0 : Assert(rti > 0);
2479 :
2480 : /*
2481 : * Get and lock the updated version of the row; if fail, return NULL.
2482 : */
2483 0 : copyTuple = EvalPlanQualFetch(estate, relation, lockmode, LockWaitBlock,
2484 : tid, priorXmax);
2485 :
2486 0 : if (copyTuple == NULL)
2487 0 : return NULL;
2488 :
2489 : /*
2490 : * For UPDATE/DELETE we have to return tid of actual row we're executing
2491 : * PQ for.
2492 : */
2493 0 : *tid = copyTuple->t_self;
2494 :
2495 : /*
2496 : * Need to run a recheck subquery. Initialize or reinitialize EPQ state.
2497 : */
2498 0 : EvalPlanQualBegin(epqstate, estate);
2499 :
2500 : /*
2501 : * Free old test tuple, if any, and store new tuple where relation's scan
2502 : * node will see it
2503 : */
2504 0 : EvalPlanQualSetTuple(epqstate, rti, copyTuple);
2505 :
2506 : /*
2507 : * Fetch any non-locked source rows
2508 : */
2509 0 : EvalPlanQualFetchRowMarks(epqstate);
2510 :
2511 : /*
2512 : * Run the EPQ query. We assume it will return at most one tuple.
2513 : */
2514 0 : slot = EvalPlanQualNext(epqstate);
2515 :
2516 : /*
2517 : * If we got a tuple, force the slot to materialize the tuple so that it
2518 : * is not dependent on any local state in the EPQ query (in particular,
2519 : * it's highly likely that the slot contains references to any pass-by-ref
2520 : * datums that may be present in copyTuple). As with the next step, this
2521 : * is to guard against early re-use of the EPQ query.
2522 : */
2523 0 : if (!TupIsNull(slot))
2524 0 : (void) ExecMaterializeSlot(slot);
2525 :
2526 : /*
2527 : * Clear out the test tuple. This is needed in case the EPQ query is
2528 : * re-used to test a tuple for a different relation. (Not clear that can
2529 : * really happen, but let's be safe.)
2530 : */
2531 0 : EvalPlanQualSetTuple(epqstate, rti, NULL);
2532 :
2533 0 : return slot;
2534 : }
2535 :
2536 : /*
2537 : * Fetch a copy of the newest version of an outdated tuple
2538 : *
2539 : * estate - executor state data
2540 : * relation - table containing tuple
2541 : * lockmode - requested tuple lock mode
2542 : * wait_policy - requested lock wait policy
2543 : * *tid - t_ctid from the outdated tuple (ie, next updated version)
2544 : * priorXmax - t_xmax from the outdated tuple
2545 : *
2546 : * Returns a palloc'd copy of the newest tuple version, or NULL if we find
2547 : * that there is no newest version (ie, the row was deleted not updated).
2548 : * We also return NULL if the tuple is locked and the wait policy is to skip
2549 : * such tuples.
2550 : *
2551 : * If successful, we have locked the newest tuple version, so caller does not
2552 : * need to worry about it changing anymore.
2553 : *
2554 : * Note: properly, lockmode should be declared as enum LockTupleMode,
2555 : * but we use "int" to avoid having to include heapam.h in executor.h.
2556 : */
2557 : HeapTuple
2558 0 : EvalPlanQualFetch(EState *estate, Relation relation, int lockmode,
2559 : LockWaitPolicy wait_policy,
2560 : ItemPointer tid, TransactionId priorXmax)
2561 : {
2562 0 : HeapTuple copyTuple = NULL;
2563 : HeapTupleData tuple;
2564 : SnapshotData SnapshotDirty;
2565 :
2566 : /*
2567 : * fetch target tuple
2568 : *
2569 : * Loop here to deal with updated or busy tuples
2570 : */
2571 0 : InitDirtySnapshot(SnapshotDirty);
2572 0 : tuple.t_self = *tid;
2573 : for (;;)
2574 : {
2575 : Buffer buffer;
2576 :
2577 0 : if (heap_fetch(relation, &SnapshotDirty, &tuple, &buffer, true, NULL))
2578 : {
2579 : HTSU_Result test;
2580 : HeapUpdateFailureData hufd;
2581 :
2582 : /*
2583 : * If xmin isn't what we're expecting, the slot must have been
2584 : * recycled and reused for an unrelated tuple. This implies that
2585 : * the latest version of the row was deleted, so we need do
2586 : * nothing. (Should be safe to examine xmin without getting
2587 : * buffer's content lock. We assume reading a TransactionId to be
2588 : * atomic, and Xmin never changes in an existing tuple, except to
2589 : * invalid or frozen, and neither of those can match priorXmax.)
2590 : */
2591 0 : if (!TransactionIdEquals(HeapTupleHeaderGetXmin(tuple.t_data),
2592 : priorXmax))
2593 : {
2594 0 : ReleaseBuffer(buffer);
2595 0 : return NULL;
2596 : }
2597 :
2598 : /* otherwise xmin should not be dirty... */
2599 0 : if (TransactionIdIsValid(SnapshotDirty.xmin))
2600 0 : elog(ERROR, "t_xmin is uncommitted in tuple to be updated");
2601 :
2602 : /*
2603 : * If tuple is being updated by other transaction then we have to
2604 : * wait for its commit/abort, or die trying.
2605 : */
2606 0 : if (TransactionIdIsValid(SnapshotDirty.xmax))
2607 : {
2608 0 : ReleaseBuffer(buffer);
2609 0 : switch (wait_policy)
2610 : {
2611 : case LockWaitBlock:
2612 0 : XactLockTableWait(SnapshotDirty.xmax,
2613 : relation, &tuple.t_self,
2614 : XLTW_FetchUpdated);
2615 0 : break;
2616 : case LockWaitSkip:
2617 0 : if (!ConditionalXactLockTableWait(SnapshotDirty.xmax))
2618 0 : return NULL; /* skip instead of waiting */
2619 0 : break;
2620 : case LockWaitError:
2621 0 : if (!ConditionalXactLockTableWait(SnapshotDirty.xmax))
2622 0 : ereport(ERROR,
2623 : (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
2624 : errmsg("could not obtain lock on row in relation \"%s\"",
2625 : RelationGetRelationName(relation))));
2626 0 : break;
2627 : }
2628 0 : continue; /* loop back to repeat heap_fetch */
2629 : }
2630 :
2631 : /*
2632 : * If tuple was inserted by our own transaction, we have to check
2633 : * cmin against es_output_cid: cmin >= current CID means our
2634 : * command cannot see the tuple, so we should ignore it. Otherwise
2635 : * heap_lock_tuple() will throw an error, and so would any later
2636 : * attempt to update or delete the tuple. (We need not check cmax
2637 : * because HeapTupleSatisfiesDirty will consider a tuple deleted
2638 : * by our transaction dead, regardless of cmax.) We just checked
2639 : * that priorXmax == xmin, so we can test that variable instead of
2640 : * doing HeapTupleHeaderGetXmin again.
2641 : */
2642 0 : if (TransactionIdIsCurrentTransactionId(priorXmax) &&
2643 0 : HeapTupleHeaderGetCmin(tuple.t_data) >= estate->es_output_cid)
2644 : {
2645 0 : ReleaseBuffer(buffer);
2646 0 : return NULL;
2647 : }
2648 :
2649 : /*
2650 : * This is a live tuple, so now try to lock it.
2651 : */
2652 0 : test = heap_lock_tuple(relation, &tuple,
2653 : estate->es_output_cid,
2654 : lockmode, wait_policy,
2655 : false, &buffer, &hufd);
2656 : /* We now have two pins on the buffer, get rid of one */
2657 0 : ReleaseBuffer(buffer);
2658 :
2659 0 : switch (test)
2660 : {
2661 : case HeapTupleSelfUpdated:
2662 :
2663 : /*
2664 : * The target tuple was already updated or deleted by the
2665 : * current command, or by a later command in the current
2666 : * transaction. We *must* ignore the tuple in the former
2667 : * case, so as to avoid the "Halloween problem" of
2668 : * repeated update attempts. In the latter case it might
2669 : * be sensible to fetch the updated tuple instead, but
2670 : * doing so would require changing heap_update and
2671 : * heap_delete to not complain about updating "invisible"
2672 : * tuples, which seems pretty scary (heap_lock_tuple will
2673 : * not complain, but few callers expect
2674 : * HeapTupleInvisible, and we're not one of them). So for
2675 : * now, treat the tuple as deleted and do not process.
2676 : */
2677 0 : ReleaseBuffer(buffer);
2678 0 : return NULL;
2679 :
2680 : case HeapTupleMayBeUpdated:
2681 : /* successfully locked */
2682 0 : break;
2683 :
2684 : case HeapTupleUpdated:
2685 0 : ReleaseBuffer(buffer);
2686 0 : if (IsolationUsesXactSnapshot())
2687 0 : ereport(ERROR,
2688 : (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
2689 : errmsg("could not serialize access due to concurrent update")));
2690 :
2691 : /* Should not encounter speculative tuple on recheck */
2692 0 : Assert(!HeapTupleHeaderIsSpeculative(tuple.t_data));
2693 0 : if (!ItemPointerEquals(&hufd.ctid, &tuple.t_self))
2694 : {
2695 : /* it was updated, so look at the updated version */
2696 0 : tuple.t_self = hufd.ctid;
2697 : /* updated row should have xmin matching this xmax */
2698 0 : priorXmax = hufd.xmax;
2699 0 : continue;
2700 : }
2701 : /* tuple was deleted, so give up */
2702 0 : return NULL;
2703 :
2704 : case HeapTupleWouldBlock:
2705 0 : ReleaseBuffer(buffer);
2706 0 : return NULL;
2707 :
2708 : case HeapTupleInvisible:
2709 0 : elog(ERROR, "attempted to lock invisible tuple");
2710 :
2711 : default:
2712 0 : ReleaseBuffer(buffer);
2713 0 : elog(ERROR, "unrecognized heap_lock_tuple status: %u",
2714 : test);
2715 : return NULL; /* keep compiler quiet */
2716 : }
2717 :
2718 : /*
2719 : * We got tuple - now copy it for use by recheck query.
2720 : */
2721 0 : copyTuple = heap_copytuple(&tuple);
2722 0 : ReleaseBuffer(buffer);
2723 0 : break;
2724 : }
2725 :
2726 : /*
2727 : * If the referenced slot was actually empty, the latest version of
2728 : * the row must have been deleted, so we need do nothing.
2729 : */
2730 0 : if (tuple.t_data == NULL)
2731 : {
2732 0 : ReleaseBuffer(buffer);
2733 0 : return NULL;
2734 : }
2735 :
2736 : /*
2737 : * As above, if xmin isn't what we're expecting, do nothing.
2738 : */
2739 0 : if (!TransactionIdEquals(HeapTupleHeaderGetXmin(tuple.t_data),
2740 : priorXmax))
2741 : {
2742 0 : ReleaseBuffer(buffer);
2743 0 : return NULL;
2744 : }
2745 :
2746 : /*
2747 : * If we get here, the tuple was found but failed SnapshotDirty.
2748 : * Assuming the xmin is either a committed xact or our own xact (as it
2749 : * certainly should be if we're trying to modify the tuple), this must
2750 : * mean that the row was updated or deleted by either a committed xact
2751 : * or our own xact. If it was deleted, we can ignore it; if it was
2752 : * updated then chain up to the next version and repeat the whole
2753 : * process.
2754 : *
2755 : * As above, it should be safe to examine xmax and t_ctid without the
2756 : * buffer content lock, because they can't be changing.
2757 : */
2758 0 : if (ItemPointerEquals(&tuple.t_self, &tuple.t_data->t_ctid))
2759 : {
2760 : /* deleted, so forget about it */
2761 0 : ReleaseBuffer(buffer);
2762 0 : return NULL;
2763 : }
2764 :
2765 : /* updated, so look at the updated row */
2766 0 : tuple.t_self = tuple.t_data->t_ctid;
2767 : /* updated row should have xmin matching this xmax */
2768 0 : priorXmax = HeapTupleHeaderGetUpdateXid(tuple.t_data);
2769 0 : ReleaseBuffer(buffer);
2770 : /* loop back to fetch next in chain */
2771 0 : }
2772 :
2773 : /*
2774 : * Return the copied tuple
2775 : */
2776 0 : return copyTuple;
2777 : }
2778 :
2779 : /*
2780 : * EvalPlanQualInit -- initialize during creation of a plan state node
2781 : * that might need to invoke EPQ processing.
2782 : *
2783 : * Note: subplan/auxrowmarks can be NULL/NIL if they will be set later
2784 : * with EvalPlanQualSetPlan.
2785 : */
2786 : void
2787 4847 : EvalPlanQualInit(EPQState *epqstate, EState *estate,
2788 : Plan *subplan, List *auxrowmarks, int epqParam)
2789 : {
2790 : /* Mark the EPQ state inactive */
2791 4847 : epqstate->estate = NULL;
2792 4847 : epqstate->planstate = NULL;
2793 4847 : epqstate->origslot = NULL;
2794 : /* ... and remember data that EvalPlanQualBegin will need */
2795 4847 : epqstate->plan = subplan;
2796 4847 : epqstate->arowMarks = auxrowmarks;
2797 4847 : epqstate->epqParam = epqParam;
2798 4847 : }
2799 :
2800 : /*
2801 : * EvalPlanQualSetPlan -- set or change subplan of an EPQState.
2802 : *
2803 : * We need this so that ModifyTable can deal with multiple subplans.
2804 : */
2805 : void
2806 4575 : EvalPlanQualSetPlan(EPQState *epqstate, Plan *subplan, List *auxrowmarks)
2807 : {
2808 : /* If we have a live EPQ query, shut it down */
2809 4575 : EvalPlanQualEnd(epqstate);
2810 : /* And set/change the plan pointer */
2811 4575 : epqstate->plan = subplan;
2812 : /* The rowmarks depend on the plan, too */
2813 4575 : epqstate->arowMarks = auxrowmarks;
2814 4575 : }
2815 :
2816 : /*
2817 : * Install one test tuple into EPQ state, or clear test tuple if tuple == NULL
2818 : *
2819 : * NB: passed tuple must be palloc'd; it may get freed later
2820 : */
2821 : void
2822 0 : EvalPlanQualSetTuple(EPQState *epqstate, Index rti, HeapTuple tuple)
2823 : {
2824 0 : EState *estate = epqstate->estate;
2825 :
2826 0 : Assert(rti > 0);
2827 :
2828 : /*
2829 : * free old test tuple, if any, and store new tuple where relation's scan
2830 : * node will see it
2831 : */
2832 0 : if (estate->es_epqTuple[rti - 1] != NULL)
2833 0 : heap_freetuple(estate->es_epqTuple[rti - 1]);
2834 0 : estate->es_epqTuple[rti - 1] = tuple;
2835 0 : estate->es_epqTupleSet[rti - 1] = true;
2836 0 : }
2837 :
2838 : /*
2839 : * Fetch back the current test tuple (if any) for the specified RTI
2840 : */
2841 : HeapTuple
2842 0 : EvalPlanQualGetTuple(EPQState *epqstate, Index rti)
2843 : {
2844 0 : EState *estate = epqstate->estate;
2845 :
2846 0 : Assert(rti > 0);
2847 :
2848 0 : return estate->es_epqTuple[rti - 1];
2849 : }
2850 :
2851 : /*
2852 : * Fetch the current row values for any non-locked relations that need
2853 : * to be scanned by an EvalPlanQual operation. origslot must have been set
2854 : * to contain the current result row (top-level row) that we need to recheck.
2855 : */
2856 : void
2857 0 : EvalPlanQualFetchRowMarks(EPQState *epqstate)
2858 : {
2859 : ListCell *l;
2860 :
2861 0 : Assert(epqstate->origslot != NULL);
2862 :
2863 0 : foreach(l, epqstate->arowMarks)
2864 : {
2865 0 : ExecAuxRowMark *aerm = (ExecAuxRowMark *) lfirst(l);
2866 0 : ExecRowMark *erm = aerm->rowmark;
2867 : Datum datum;
2868 : bool isNull;
2869 : HeapTupleData tuple;
2870 :
2871 0 : if (RowMarkRequiresRowShareLock(erm->markType))
2872 0 : elog(ERROR, "EvalPlanQual doesn't support locking rowmarks");
2873 :
2874 : /* clear any leftover test tuple for this rel */
2875 0 : EvalPlanQualSetTuple(epqstate, erm->rti, NULL);
2876 :
2877 : /* if child rel, must check whether it produced this row */
2878 0 : if (erm->rti != erm->prti)
2879 : {
2880 : Oid tableoid;
2881 :
2882 0 : datum = ExecGetJunkAttribute(epqstate->origslot,
2883 0 : aerm->toidAttNo,
2884 : &isNull);
2885 : /* non-locked rels could be on the inside of outer joins */
2886 0 : if (isNull)
2887 0 : continue;
2888 0 : tableoid = DatumGetObjectId(datum);
2889 :
2890 0 : Assert(OidIsValid(erm->relid));
2891 0 : if (tableoid != erm->relid)
2892 : {
2893 : /* this child is inactive right now */
2894 0 : continue;
2895 : }
2896 : }
2897 :
2898 0 : if (erm->markType == ROW_MARK_REFERENCE)
2899 : {
2900 : HeapTuple copyTuple;
2901 :
2902 0 : Assert(erm->relation != NULL);
2903 :
2904 : /* fetch the tuple's ctid */
2905 0 : datum = ExecGetJunkAttribute(epqstate->origslot,
2906 0 : aerm->ctidAttNo,
2907 : &isNull);
2908 : /* non-locked rels could be on the inside of outer joins */
2909 0 : if (isNull)
2910 0 : continue;
2911 :
2912 : /* fetch requests on foreign tables must be passed to their FDW */
2913 0 : if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2914 : {
2915 : FdwRoutine *fdwroutine;
2916 0 : bool updated = false;
2917 :
2918 0 : fdwroutine = GetFdwRoutineForRelation(erm->relation, false);
2919 : /* this should have been checked already, but let's be safe */
2920 0 : if (fdwroutine->RefetchForeignRow == NULL)
2921 0 : ereport(ERROR,
2922 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2923 : errmsg("cannot lock rows in foreign table \"%s\"",
2924 : RelationGetRelationName(erm->relation))));
2925 0 : copyTuple = fdwroutine->RefetchForeignRow(epqstate->estate,
2926 : erm,
2927 : datum,
2928 : &updated);
2929 0 : if (copyTuple == NULL)
2930 0 : elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2931 :
2932 : /*
2933 : * Ideally we'd insist on updated == false here, but that
2934 : * assumes that FDWs can track that exactly, which they might
2935 : * not be able to. So just ignore the flag.
2936 : */
2937 : }
2938 : else
2939 : {
2940 : /* ordinary table, fetch the tuple */
2941 : Buffer buffer;
2942 :
2943 0 : tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
2944 0 : if (!heap_fetch(erm->relation, SnapshotAny, &tuple, &buffer,
2945 : false, NULL))
2946 0 : elog(ERROR, "failed to fetch tuple for EvalPlanQual recheck");
2947 :
2948 : /* successful, copy tuple */
2949 0 : copyTuple = heap_copytuple(&tuple);
2950 0 : ReleaseBuffer(buffer);
2951 : }
2952 :
2953 : /* store tuple */
2954 0 : EvalPlanQualSetTuple(epqstate, erm->rti, copyTuple);
2955 : }
2956 : else
2957 : {
2958 : HeapTupleHeader td;
2959 :
2960 0 : Assert(erm->markType == ROW_MARK_COPY);
2961 :
2962 : /* fetch the whole-row Var for the relation */
2963 0 : datum = ExecGetJunkAttribute(epqstate->origslot,
2964 0 : aerm->wholeAttNo,
2965 : &isNull);
2966 : /* non-locked rels could be on the inside of outer joins */
2967 0 : if (isNull)
2968 0 : continue;
2969 0 : td = DatumGetHeapTupleHeader(datum);
2970 :
2971 : /* build a temporary HeapTuple control structure */
2972 0 : tuple.t_len = HeapTupleHeaderGetDatumLength(td);
2973 0 : tuple.t_data = td;
2974 : /* relation might be a foreign table, if so provide tableoid */
2975 0 : tuple.t_tableOid = erm->relid;
2976 : /* also copy t_ctid in case there's valid data there */
2977 0 : tuple.t_self = td->t_ctid;
2978 :
2979 : /* copy and store tuple */
2980 0 : EvalPlanQualSetTuple(epqstate, erm->rti,
2981 : heap_copytuple(&tuple));
2982 : }
2983 : }
2984 0 : }
2985 :
2986 : /*
2987 : * Fetch the next row (if any) from EvalPlanQual testing
2988 : *
2989 : * (In practice, there should never be more than one row...)
2990 : */
2991 : TupleTableSlot *
2992 0 : EvalPlanQualNext(EPQState *epqstate)
2993 : {
2994 : MemoryContext oldcontext;
2995 : TupleTableSlot *slot;
2996 :
2997 0 : oldcontext = MemoryContextSwitchTo(epqstate->estate->es_query_cxt);
2998 0 : slot = ExecProcNode(epqstate->planstate);
2999 0 : MemoryContextSwitchTo(oldcontext);
3000 :
3001 0 : return slot;
3002 : }
3003 :
3004 : /*
3005 : * Initialize or reset an EvalPlanQual state tree
3006 : */
3007 : void
3008 0 : EvalPlanQualBegin(EPQState *epqstate, EState *parentestate)
3009 : {
3010 0 : EState *estate = epqstate->estate;
3011 :
3012 0 : if (estate == NULL)
3013 : {
3014 : /* First time through, so create a child EState */
3015 0 : EvalPlanQualStart(epqstate, parentestate, epqstate->plan);
3016 : }
3017 : else
3018 : {
3019 : /*
3020 : * We already have a suitable child EPQ tree, so just reset it.
3021 : */
3022 0 : int rtsize = list_length(parentestate->es_range_table);
3023 0 : PlanState *planstate = epqstate->planstate;
3024 :
3025 0 : MemSet(estate->es_epqScanDone, 0, rtsize * sizeof(bool));
3026 :
3027 : /* Recopy current values of parent parameters */
3028 0 : if (parentestate->es_plannedstmt->nParamExec > 0)
3029 : {
3030 0 : int i = parentestate->es_plannedstmt->nParamExec;
3031 :
3032 0 : while (--i >= 0)
3033 : {
3034 : /* copy value if any, but not execPlan link */
3035 0 : estate->es_param_exec_vals[i].value =
3036 0 : parentestate->es_param_exec_vals[i].value;
3037 0 : estate->es_param_exec_vals[i].isnull =
3038 0 : parentestate->es_param_exec_vals[i].isnull;
3039 : }
3040 : }
3041 :
3042 : /*
3043 : * Mark child plan tree as needing rescan at all scan nodes. The
3044 : * first ExecProcNode will take care of actually doing the rescan.
3045 : */
3046 0 : planstate->chgParam = bms_add_member(planstate->chgParam,
3047 : epqstate->epqParam);
3048 : }
3049 0 : }
3050 :
3051 : /*
3052 : * Start execution of an EvalPlanQual plan tree.
3053 : *
3054 : * This is a cut-down version of ExecutorStart(): we copy some state from
3055 : * the top-level estate rather than initializing it fresh.
3056 : */
3057 : static void
3058 0 : EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
3059 : {
3060 : EState *estate;
3061 : int rtsize;
3062 : MemoryContext oldcontext;
3063 : ListCell *l;
3064 :
3065 0 : rtsize = list_length(parentestate->es_range_table);
3066 :
3067 0 : epqstate->estate = estate = CreateExecutorState();
3068 :
3069 0 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3070 :
3071 : /*
3072 : * Child EPQ EStates share the parent's copy of unchanging state such as
3073 : * the snapshot, rangetable, result-rel info, and external Param info.
3074 : * They need their own copies of local state, including a tuple table,
3075 : * es_param_exec_vals, etc.
3076 : *
3077 : * The ResultRelInfo array management is trickier than it looks. We
3078 : * create a fresh array for the child but copy all the content from the
3079 : * parent. This is because it's okay for the child to share any
3080 : * per-relation state the parent has already created --- but if the child
3081 : * sets up any ResultRelInfo fields, such as its own junkfilter, that
3082 : * state must *not* propagate back to the parent. (For one thing, the
3083 : * pointed-to data is in a memory context that won't last long enough.)
3084 : */
3085 0 : estate->es_direction = ForwardScanDirection;
3086 0 : estate->es_snapshot = parentestate->es_snapshot;
3087 0 : estate->es_crosscheck_snapshot = parentestate->es_crosscheck_snapshot;
3088 0 : estate->es_range_table = parentestate->es_range_table;
3089 0 : estate->es_plannedstmt = parentestate->es_plannedstmt;
3090 0 : estate->es_junkFilter = parentestate->es_junkFilter;
3091 0 : estate->es_output_cid = parentestate->es_output_cid;
3092 0 : if (parentestate->es_num_result_relations > 0)
3093 : {
3094 0 : int numResultRelations = parentestate->es_num_result_relations;
3095 : ResultRelInfo *resultRelInfos;
3096 :
3097 0 : resultRelInfos = (ResultRelInfo *)
3098 0 : palloc(numResultRelations * sizeof(ResultRelInfo));
3099 0 : memcpy(resultRelInfos, parentestate->es_result_relations,
3100 : numResultRelations * sizeof(ResultRelInfo));
3101 0 : estate->es_result_relations = resultRelInfos;
3102 0 : estate->es_num_result_relations = numResultRelations;
3103 : }
3104 : /* es_result_relation_info must NOT be copied */
3105 : /* es_trig_target_relations must NOT be copied */
3106 0 : estate->es_rowMarks = parentestate->es_rowMarks;
3107 0 : estate->es_top_eflags = parentestate->es_top_eflags;
3108 0 : estate->es_instrument = parentestate->es_instrument;
3109 : /* es_auxmodifytables must NOT be copied */
3110 :
3111 : /*
3112 : * The external param list is simply shared from parent. The internal
3113 : * param workspace has to be local state, but we copy the initial values
3114 : * from the parent, so as to have access to any param values that were
3115 : * already set from other parts of the parent's plan tree.
3116 : */
3117 0 : estate->es_param_list_info = parentestate->es_param_list_info;
3118 0 : if (parentestate->es_plannedstmt->nParamExec > 0)
3119 : {
3120 0 : int i = parentestate->es_plannedstmt->nParamExec;
3121 :
3122 0 : estate->es_param_exec_vals = (ParamExecData *)
3123 0 : palloc0(i * sizeof(ParamExecData));
3124 0 : while (--i >= 0)
3125 : {
3126 : /* copy value if any, but not execPlan link */
3127 0 : estate->es_param_exec_vals[i].value =
3128 0 : parentestate->es_param_exec_vals[i].value;
3129 0 : estate->es_param_exec_vals[i].isnull =
3130 0 : parentestate->es_param_exec_vals[i].isnull;
3131 : }
3132 : }
3133 :
3134 : /*
3135 : * Each EState must have its own es_epqScanDone state, but if we have
3136 : * nested EPQ checks they should share es_epqTuple arrays. This allows
3137 : * sub-rechecks to inherit the values being examined by an outer recheck.
3138 : */
3139 0 : estate->es_epqScanDone = (bool *) palloc0(rtsize * sizeof(bool));
3140 0 : if (parentestate->es_epqTuple != NULL)
3141 : {
3142 0 : estate->es_epqTuple = parentestate->es_epqTuple;
3143 0 : estate->es_epqTupleSet = parentestate->es_epqTupleSet;
3144 : }
3145 : else
3146 : {
3147 0 : estate->es_epqTuple = (HeapTuple *)
3148 0 : palloc0(rtsize * sizeof(HeapTuple));
3149 0 : estate->es_epqTupleSet = (bool *)
3150 0 : palloc0(rtsize * sizeof(bool));
3151 : }
3152 :
3153 : /*
3154 : * Each estate also has its own tuple table.
3155 : */
3156 0 : estate->es_tupleTable = NIL;
3157 :
3158 : /*
3159 : * Initialize private state information for each SubPlan. We must do this
3160 : * before running ExecInitNode on the main query tree, since
3161 : * ExecInitSubPlan expects to be able to find these entries. Some of the
3162 : * SubPlans might not be used in the part of the plan tree we intend to
3163 : * run, but since it's not easy to tell which, we just initialize them
3164 : * all.
3165 : */
3166 0 : Assert(estate->es_subplanstates == NIL);
3167 0 : foreach(l, parentestate->es_plannedstmt->subplans)
3168 : {
3169 0 : Plan *subplan = (Plan *) lfirst(l);
3170 : PlanState *subplanstate;
3171 :
3172 0 : subplanstate = ExecInitNode(subplan, estate, 0);
3173 0 : estate->es_subplanstates = lappend(estate->es_subplanstates,
3174 : subplanstate);
3175 : }
3176 :
3177 : /*
3178 : * Initialize the private state information for all the nodes in the part
3179 : * of the plan tree we need to run. This opens files, allocates storage
3180 : * and leaves us ready to start processing tuples.
3181 : */
3182 0 : epqstate->planstate = ExecInitNode(planTree, estate, 0);
3183 :
3184 0 : MemoryContextSwitchTo(oldcontext);
3185 0 : }
3186 :
3187 : /*
3188 : * EvalPlanQualEnd -- shut down at termination of parent plan state node,
3189 : * or if we are done with the current EPQ child.
3190 : *
3191 : * This is a cut-down version of ExecutorEnd(); basically we want to do most
3192 : * of the normal cleanup, but *not* close result relations (which we are
3193 : * just sharing from the outer query). We do, however, have to close any
3194 : * trigger target relations that got opened, since those are not shared.
3195 : * (There probably shouldn't be any of the latter, but just in case...)
3196 : */
3197 : void
3198 9095 : EvalPlanQualEnd(EPQState *epqstate)
3199 : {
3200 9095 : EState *estate = epqstate->estate;
3201 : MemoryContext oldcontext;
3202 : ListCell *l;
3203 :
3204 9095 : if (estate == NULL)
3205 18190 : return; /* idle, so nothing to do */
3206 :
3207 0 : oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
3208 :
3209 0 : ExecEndNode(epqstate->planstate);
3210 :
3211 0 : foreach(l, estate->es_subplanstates)
3212 : {
3213 0 : PlanState *subplanstate = (PlanState *) lfirst(l);
3214 :
3215 0 : ExecEndNode(subplanstate);
3216 : }
3217 :
3218 : /* throw away the per-estate tuple table */
3219 0 : ExecResetTupleTable(estate->es_tupleTable, false);
3220 :
3221 : /* close any trigger target relations attached to this EState */
3222 0 : ExecCleanUpTriggerState(estate);
3223 :
3224 0 : MemoryContextSwitchTo(oldcontext);
3225 :
3226 0 : FreeExecutorState(estate);
3227 :
3228 : /* Mark EPQState idle */
3229 0 : epqstate->estate = NULL;
3230 0 : epqstate->planstate = NULL;
3231 0 : epqstate->origslot = NULL;
3232 : }
3233 :
3234 : /*
3235 : * ExecSetupPartitionTupleRouting - set up information needed during
3236 : * tuple routing for partitioned tables
3237 : *
3238 : * Output arguments:
3239 : * 'pd' receives an array of PartitionDispatch objects with one entry for
3240 : * every partitioned table in the partition tree
3241 : * 'partitions' receives an array of ResultRelInfo objects with one entry for
3242 : * every leaf partition in the partition tree
3243 : * 'tup_conv_maps' receives an array of TupleConversionMap objects with one
3244 : * entry for every leaf partition (required to convert input tuple based
3245 : * on the root table's rowtype to a leaf partition's rowtype after tuple
3246 : * routing is done)
3247 : * 'partition_tuple_slot' receives a standalone TupleTableSlot to be used
3248 : * to manipulate any given leaf partition's rowtype after that partition
3249 : * is chosen by tuple-routing.
3250 : * 'num_parted' receives the number of partitioned tables in the partition
3251 : * tree (= the number of entries in the 'pd' output array)
3252 : * 'num_partitions' receives the number of leaf partitions in the partition
3253 : * tree (= the number of entries in the 'partitions' and 'tup_conv_maps'
3254 : * output arrays
3255 : *
3256 : * Note that all the relations in the partition tree are locked using the
3257 : * RowExclusiveLock mode upon return from this function.
3258 : */
3259 : void
3260 69 : ExecSetupPartitionTupleRouting(Relation rel,
3261 : Index resultRTindex,
3262 : EState *estate,
3263 : PartitionDispatch **pd,
3264 : ResultRelInfo **partitions,
3265 : TupleConversionMap ***tup_conv_maps,
3266 : TupleTableSlot **partition_tuple_slot,
3267 : int *num_parted, int *num_partitions)
3268 : {
3269 69 : TupleDesc tupDesc = RelationGetDescr(rel);
3270 : List *leaf_parts;
3271 : ListCell *cell;
3272 : int i;
3273 : ResultRelInfo *leaf_part_rri;
3274 :
3275 : /*
3276 : * Get the information about the partition tree after locking all the
3277 : * partitions.
3278 : */
3279 69 : (void) find_all_inheritors(RelationGetRelid(rel), RowExclusiveLock, NULL);
3280 69 : *pd = RelationGetPartitionDispatchInfo(rel, num_parted, &leaf_parts);
3281 69 : *num_partitions = list_length(leaf_parts);
3282 69 : *partitions = (ResultRelInfo *) palloc(*num_partitions *
3283 : sizeof(ResultRelInfo));
3284 69 : *tup_conv_maps = (TupleConversionMap **) palloc0(*num_partitions *
3285 : sizeof(TupleConversionMap *));
3286 :
3287 : /*
3288 : * Initialize an empty slot that will be used to manipulate tuples of any
3289 : * given partition's rowtype. It is attached to the caller-specified node
3290 : * (such as ModifyTableState) and released when the node finishes
3291 : * processing.
3292 : */
3293 69 : *partition_tuple_slot = MakeTupleTableSlot();
3294 :
3295 69 : leaf_part_rri = *partitions;
3296 69 : i = 0;
3297 301 : foreach(cell, leaf_parts)
3298 : {
3299 : Relation partrel;
3300 : TupleDesc part_tupdesc;
3301 :
3302 : /*
3303 : * We locked all the partitions above including the leaf partitions.
3304 : * Note that each of the relations in *partitions are eventually
3305 : * closed by the caller.
3306 : */
3307 232 : partrel = heap_open(lfirst_oid(cell), NoLock);
3308 232 : part_tupdesc = RelationGetDescr(partrel);
3309 :
3310 : /*
3311 : * Verify result relation is a valid target for the current operation.
3312 : */
3313 232 : CheckValidResultRel(partrel, CMD_INSERT);
3314 :
3315 : /*
3316 : * Save a tuple conversion map to convert a tuple routed to this
3317 : * partition from the parent's type to the partition's.
3318 : */
3319 232 : (*tup_conv_maps)[i] = convert_tuples_by_name(tupDesc, part_tupdesc,
3320 : gettext_noop("could not convert row type"));
3321 :
3322 232 : InitResultRelInfo(leaf_part_rri,
3323 : partrel,
3324 : resultRTindex,
3325 : rel,
3326 : estate->es_instrument);
3327 :
3328 232 : estate->es_leaf_result_relations =
3329 232 : lappend(estate->es_leaf_result_relations, leaf_part_rri);
3330 :
3331 : /*
3332 : * Open partition indices (remember we do not support ON CONFLICT in
3333 : * case of partitioned tables, so we do not need support information
3334 : * for speculative insertion)
3335 : */
3336 233 : if (leaf_part_rri->ri_RelationDesc->rd_rel->relhasindex &&
3337 1 : leaf_part_rri->ri_IndexRelationDescs == NULL)
3338 1 : ExecOpenIndices(leaf_part_rri, false);
3339 :
3340 232 : leaf_part_rri++;
3341 232 : i++;
3342 : }
3343 69 : }
3344 :
3345 : /*
3346 : * ExecFindPartition -- Find a leaf partition in the partition tree rooted
3347 : * at parent, for the heap tuple contained in *slot
3348 : *
3349 : * estate must be non-NULL; we'll need it to compute any expressions in the
3350 : * partition key(s)
3351 : *
3352 : * If no leaf partition is found, this routine errors out with the appropriate
3353 : * error message, else it returns the leaf partition sequence number returned
3354 : * by get_partition_for_tuple() unchanged.
3355 : */
3356 : int
3357 178 : ExecFindPartition(ResultRelInfo *resultRelInfo, PartitionDispatch *pd,
3358 : TupleTableSlot *slot, EState *estate)
3359 : {
3360 : int result;
3361 : PartitionDispatchData *failed_at;
3362 : TupleTableSlot *failed_slot;
3363 :
3364 : /*
3365 : * First check the root table's partition constraint, if any. No point in
3366 : * routing the tuple if it doesn't belong in the root table itself.
3367 : */
3368 178 : if (resultRelInfo->ri_PartitionCheck)
3369 4 : ExecPartitionCheck(resultRelInfo, slot, estate);
3370 :
3371 177 : result = get_partition_for_tuple(pd, slot, estate,
3372 : &failed_at, &failed_slot);
3373 177 : if (result < 0)
3374 : {
3375 : Relation failed_rel;
3376 : Datum key_values[PARTITION_MAX_KEYS];
3377 : bool key_isnull[PARTITION_MAX_KEYS];
3378 : char *val_desc;
3379 11 : ExprContext *ecxt = GetPerTupleExprContext(estate);
3380 :
3381 11 : failed_rel = failed_at->reldesc;
3382 11 : ecxt->ecxt_scantuple = failed_slot;
3383 11 : FormPartitionKeyDatum(failed_at, failed_slot, estate,
3384 : key_values, key_isnull);
3385 11 : val_desc = ExecBuildSlotPartitionKeyDescription(failed_rel,
3386 : key_values,
3387 : key_isnull,
3388 : 64);
3389 11 : Assert(OidIsValid(RelationGetRelid(failed_rel)));
3390 11 : ereport(ERROR,
3391 : (errcode(ERRCODE_CHECK_VIOLATION),
3392 : errmsg("no partition of relation \"%s\" found for row",
3393 : RelationGetRelationName(failed_rel)),
3394 : val_desc ? errdetail("Partition key of the failing row contains %s.", val_desc) : 0));
3395 : }
3396 :
3397 166 : return result;
3398 : }
3399 :
3400 : /*
3401 : * BuildSlotPartitionKeyDescription
3402 : *
3403 : * This works very much like BuildIndexValueDescription() and is currently
3404 : * used for building error messages when ExecFindPartition() fails to find
3405 : * partition for a row.
3406 : */
3407 : static char *
3408 11 : ExecBuildSlotPartitionKeyDescription(Relation rel,
3409 : Datum *values,
3410 : bool *isnull,
3411 : int maxfieldlen)
3412 : {
3413 : StringInfoData buf;
3414 11 : PartitionKey key = RelationGetPartitionKey(rel);
3415 11 : int partnatts = get_partition_natts(key);
3416 : int i;
3417 11 : Oid relid = RelationGetRelid(rel);
3418 : AclResult aclresult;
3419 :
3420 11 : if (check_enable_rls(relid, InvalidOid, true) == RLS_ENABLED)
3421 0 : return NULL;
3422 :
3423 : /* If the user has table-level access, just go build the description. */
3424 11 : aclresult = pg_class_aclcheck(relid, GetUserId(), ACL_SELECT);
3425 11 : if (aclresult != ACLCHECK_OK)
3426 : {
3427 : /*
3428 : * Step through the columns of the partition key and make sure the
3429 : * user has SELECT rights on all of them.
3430 : */
3431 4 : for (i = 0; i < partnatts; i++)
3432 : {
3433 3 : AttrNumber attnum = get_partition_col_attnum(key, i);
3434 :
3435 : /*
3436 : * If this partition key column is an expression, we return no
3437 : * detail rather than try to figure out what column(s) the
3438 : * expression includes and if the user has SELECT rights on them.
3439 : */
3440 5 : if (attnum == InvalidAttrNumber ||
3441 2 : pg_attribute_aclcheck(relid, attnum, GetUserId(),
3442 : ACL_SELECT) != ACLCHECK_OK)
3443 2 : return NULL;
3444 : }
3445 : }
3446 :
3447 9 : initStringInfo(&buf);
3448 9 : appendStringInfo(&buf, "(%s) = (",
3449 : pg_get_partkeydef_columns(relid, true));
3450 :
3451 23 : for (i = 0; i < partnatts; i++)
3452 : {
3453 : char *val;
3454 : int vallen;
3455 :
3456 14 : if (isnull[i])
3457 2 : val = "null";
3458 : else
3459 : {
3460 : Oid foutoid;
3461 : bool typisvarlena;
3462 :
3463 12 : getTypeOutputInfo(get_partition_col_typid(key, i),
3464 : &foutoid, &typisvarlena);
3465 12 : val = OidOutputFunctionCall(foutoid, values[i]);
3466 : }
3467 :
3468 14 : if (i > 0)
3469 5 : appendStringInfoString(&buf, ", ");
3470 :
3471 : /* truncate if needed */
3472 14 : vallen = strlen(val);
3473 14 : if (vallen <= maxfieldlen)
3474 14 : appendStringInfoString(&buf, val);
3475 : else
3476 : {
3477 0 : vallen = pg_mbcliplen(val, vallen, maxfieldlen);
3478 0 : appendBinaryStringInfo(&buf, val, vallen);
3479 0 : appendStringInfoString(&buf, "...");
3480 : }
3481 : }
3482 :
3483 9 : appendStringInfoChar(&buf, ')');
3484 :
3485 9 : return buf.data;
3486 : }
|