1 /*-------------------------------------------------------------------------
2 *
3 * execCurrent.c
4 * executor support for WHERE CURRENT OF cursor
5 *
6 * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 * src/backend/executor/execCurrent.c
10 *
11 *-------------------------------------------------------------------------
12 */
13 #include "postgres.h"
14
15 #include "access/relscan.h"
16 #include "access/sysattr.h"
17 #include "catalog/pg_type.h"
18 #include "executor/executor.h"
19 #include "utils/builtins.h"
20 #include "utils/lsyscache.h"
21 #include "utils/portal.h"
22 #include "utils/rel.h"
23
24
25 static char *fetch_cursor_param_value(ExprContext *econtext, int paramId);
26 static ScanState *search_plan_tree(PlanState *node, Oid table_oid,
27 bool *pending_rescan);
28
29
30 /*
31 * execCurrentOf
32 *
33 * Given a CURRENT OF expression and the OID of a table, determine which row
34 * of the table is currently being scanned by the cursor named by CURRENT OF,
35 * and return the row's TID into *current_tid.
36 *
37 * Returns true if a row was identified. Returns false if the cursor is valid
38 * for the table but is not currently scanning a row of the table (this is a
39 * legal situation in inheritance cases). Raises error if cursor is not a
40 * valid updatable scan of the specified table.
41 */
42 bool
execCurrentOf(CurrentOfExpr * cexpr,ExprContext * econtext,Oid table_oid,ItemPointer current_tid)43 execCurrentOf(CurrentOfExpr *cexpr,
44 ExprContext *econtext,
45 Oid table_oid,
46 ItemPointer current_tid)
47 {
48 char *cursor_name;
49 char *table_name;
50 Portal portal;
51 QueryDesc *queryDesc;
52
53 /* Get the cursor name --- may have to look up a parameter reference */
54 if (cexpr->cursor_name)
55 cursor_name = cexpr->cursor_name;
56 else
57 cursor_name = fetch_cursor_param_value(econtext, cexpr->cursor_param);
58
59 /* Fetch table name for possible use in error messages */
60 table_name = get_rel_name(table_oid);
61 if (table_name == NULL)
62 elog(ERROR, "cache lookup failed for relation %u", table_oid);
63
64 /* Find the cursor's portal */
65 portal = GetPortalByName(cursor_name);
66 if (!PortalIsValid(portal))
67 ereport(ERROR,
68 (errcode(ERRCODE_UNDEFINED_CURSOR),
69 errmsg("cursor \"%s\" does not exist", cursor_name)));
70
71 /*
72 * We have to watch out for non-SELECT queries as well as held cursors,
73 * both of which may have null queryDesc.
74 */
75 if (portal->strategy != PORTAL_ONE_SELECT)
76 ereport(ERROR,
77 (errcode(ERRCODE_INVALID_CURSOR_STATE),
78 errmsg("cursor \"%s\" is not a SELECT query",
79 cursor_name)));
80 queryDesc = portal->queryDesc;
81 if (queryDesc == NULL || queryDesc->estate == NULL)
82 ereport(ERROR,
83 (errcode(ERRCODE_INVALID_CURSOR_STATE),
84 errmsg("cursor \"%s\" is held from a previous transaction",
85 cursor_name)));
86
87 /*
88 * We have two different strategies depending on whether the cursor uses
89 * FOR UPDATE/SHARE or not. The reason for supporting both is that the
90 * FOR UPDATE code is able to identify a target table in many cases where
91 * the other code can't, while the non-FOR-UPDATE case allows use of WHERE
92 * CURRENT OF with an insensitive cursor.
93 */
94 if (queryDesc->estate->es_rowMarks)
95 {
96 ExecRowMark *erm;
97 ListCell *lc;
98
99 /*
100 * Here, the query must have exactly one FOR UPDATE/SHARE reference to
101 * the target table, and we dig the ctid info out of that.
102 */
103 erm = NULL;
104 foreach(lc, queryDesc->estate->es_rowMarks)
105 {
106 ExecRowMark *thiserm = (ExecRowMark *) lfirst(lc);
107
108 if (!RowMarkRequiresRowShareLock(thiserm->markType))
109 continue; /* ignore non-FOR UPDATE/SHARE items */
110
111 if (thiserm->relid == table_oid)
112 {
113 if (erm)
114 ereport(ERROR,
115 (errcode(ERRCODE_INVALID_CURSOR_STATE),
116 errmsg("cursor \"%s\" has multiple FOR UPDATE/SHARE references to table \"%s\"",
117 cursor_name, table_name)));
118 erm = thiserm;
119 }
120 }
121
122 if (erm == NULL)
123 ereport(ERROR,
124 (errcode(ERRCODE_INVALID_CURSOR_STATE),
125 errmsg("cursor \"%s\" does not have a FOR UPDATE/SHARE reference to table \"%s\"",
126 cursor_name, table_name)));
127
128 /*
129 * The cursor must have a current result row: per the SQL spec, it's
130 * an error if not.
131 */
132 if (portal->atStart || portal->atEnd)
133 ereport(ERROR,
134 (errcode(ERRCODE_INVALID_CURSOR_STATE),
135 errmsg("cursor \"%s\" is not positioned on a row",
136 cursor_name)));
137
138 /* Return the currently scanned TID, if there is one */
139 if (ItemPointerIsValid(&(erm->curCtid)))
140 {
141 *current_tid = erm->curCtid;
142 return true;
143 }
144
145 /*
146 * This table didn't produce the cursor's current row; some other
147 * inheritance child of the same parent must have. Signal caller to
148 * do nothing on this table.
149 */
150 return false;
151 }
152 else
153 {
154 /*
155 * Without FOR UPDATE, we dig through the cursor's plan to find the
156 * scan node. Fail if it's not there or buried underneath
157 * aggregation.
158 */
159 ScanState *scanstate;
160 bool pending_rescan = false;
161
162 scanstate = search_plan_tree(queryDesc->planstate, table_oid,
163 &pending_rescan);
164 if (!scanstate)
165 ereport(ERROR,
166 (errcode(ERRCODE_INVALID_CURSOR_STATE),
167 errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
168 cursor_name, table_name)));
169
170 /*
171 * The cursor must have a current result row: per the SQL spec, it's
172 * an error if not. We test this at the top level, rather than at the
173 * scan node level, because in inheritance cases any one table scan
174 * could easily not be on a row. We want to return false, not raise
175 * error, if the passed-in table OID is for one of the inactive scans.
176 */
177 if (portal->atStart || portal->atEnd)
178 ereport(ERROR,
179 (errcode(ERRCODE_INVALID_CURSOR_STATE),
180 errmsg("cursor \"%s\" is not positioned on a row",
181 cursor_name)));
182
183 /*
184 * Now OK to return false if we found an inactive scan. It is
185 * inactive either if it's not positioned on a row, or there's a
186 * rescan pending for it.
187 */
188 if (TupIsNull(scanstate->ss_ScanTupleSlot) || pending_rescan)
189 return false;
190
191 /*
192 * Extract TID of the scan's current row. The mechanism for this is
193 * in principle scan-type-dependent, but for most scan types, we can
194 * just dig the TID out of the physical scan tuple.
195 */
196 if (IsA(scanstate, IndexOnlyScanState))
197 {
198 /*
199 * For IndexOnlyScan, the tuple stored in ss_ScanTupleSlot may be
200 * a virtual tuple that does not have the ctid column, so we have
201 * to get the TID from xs_ctup.t_self.
202 */
203 IndexScanDesc scan = ((IndexOnlyScanState *) scanstate)->ioss_ScanDesc;
204
205 *current_tid = scan->xs_ctup.t_self;
206 }
207 else
208 {
209 /*
210 * Default case: try to fetch TID from the scan node's current
211 * tuple. As an extra cross-check, verify tableoid in the current
212 * tuple. If the scan hasn't provided a physical tuple, we have
213 * to fail.
214 */
215 Datum ldatum;
216 bool lisnull;
217 ItemPointer tuple_tid;
218
219 #ifdef USE_ASSERT_CHECKING
220 if (!slot_getsysattr(scanstate->ss_ScanTupleSlot,
221 TableOidAttributeNumber,
222 &ldatum,
223 &lisnull))
224 ereport(ERROR,
225 (errcode(ERRCODE_INVALID_CURSOR_STATE),
226 errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
227 cursor_name, table_name)));
228 Assert(!lisnull);
229 Assert(DatumGetObjectId(ldatum) == table_oid);
230 #endif
231
232 if (!slot_getsysattr(scanstate->ss_ScanTupleSlot,
233 SelfItemPointerAttributeNumber,
234 &ldatum,
235 &lisnull))
236 ereport(ERROR,
237 (errcode(ERRCODE_INVALID_CURSOR_STATE),
238 errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
239 cursor_name, table_name)));
240 Assert(!lisnull);
241 tuple_tid = (ItemPointer) DatumGetPointer(ldatum);
242
243 *current_tid = *tuple_tid;
244 }
245
246 Assert(ItemPointerIsValid(current_tid));
247
248 return true;
249 }
250 }
251
252 /*
253 * fetch_cursor_param_value
254 *
255 * Fetch the string value of a param, verifying it is of type REFCURSOR.
256 */
257 static char *
fetch_cursor_param_value(ExprContext * econtext,int paramId)258 fetch_cursor_param_value(ExprContext *econtext, int paramId)
259 {
260 ParamListInfo paramInfo = econtext->ecxt_param_list_info;
261
262 if (paramInfo &&
263 paramId > 0 && paramId <= paramInfo->numParams)
264 {
265 ParamExternData *prm;
266 ParamExternData prmdata;
267
268 /* give hook a chance in case parameter is dynamic */
269 if (paramInfo->paramFetch != NULL)
270 prm = paramInfo->paramFetch(paramInfo, paramId, false, &prmdata);
271 else
272 prm = ¶mInfo->params[paramId - 1];
273
274 if (OidIsValid(prm->ptype) && !prm->isnull)
275 {
276 /* safety check in case hook did something unexpected */
277 if (prm->ptype != REFCURSOROID)
278 ereport(ERROR,
279 (errcode(ERRCODE_DATATYPE_MISMATCH),
280 errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
281 paramId,
282 format_type_be(prm->ptype),
283 format_type_be(REFCURSOROID))));
284
285 /* We know that refcursor uses text's I/O routines */
286 return TextDatumGetCString(prm->value);
287 }
288 }
289
290 ereport(ERROR,
291 (errcode(ERRCODE_UNDEFINED_OBJECT),
292 errmsg("no value found for parameter %d", paramId)));
293 return NULL;
294 }
295
296 /*
297 * search_plan_tree
298 *
299 * Search through a PlanState tree for a scan node on the specified table.
300 * Return NULL if not found or multiple candidates.
301 *
302 * CAUTION: this function is not charged simply with finding some candidate
303 * scan, but with ensuring that that scan returned the plan tree's current
304 * output row. That's why we must reject multiple-match cases.
305 *
306 * If a candidate is found, set *pending_rescan to true if that candidate
307 * or any node above it has a pending rescan action, i.e. chgParam != NULL.
308 * That indicates that we shouldn't consider the node to be positioned on a
309 * valid tuple, even if its own state would indicate that it is. (Caller
310 * must initialize *pending_rescan to false, and should not trust its state
311 * if multiple candidates are found.)
312 */
313 static ScanState *
search_plan_tree(PlanState * node,Oid table_oid,bool * pending_rescan)314 search_plan_tree(PlanState *node, Oid table_oid,
315 bool *pending_rescan)
316 {
317 ScanState *result = NULL;
318
319 if (node == NULL)
320 return NULL;
321 switch (nodeTag(node))
322 {
323 /*
324 * Relation scan nodes can all be treated alike: check to see if
325 * they are scanning the specified table.
326 *
327 * ForeignScan and CustomScan might not have a currentRelation, in
328 * which case we just ignore them. (We dare not descend to any
329 * child plan nodes they might have, since we do not know the
330 * relationship of such a node's current output tuple to the
331 * children's current outputs.)
332 */
333 case T_SeqScanState:
334 case T_SampleScanState:
335 case T_IndexScanState:
336 case T_IndexOnlyScanState:
337 case T_BitmapHeapScanState:
338 case T_TidScanState:
339 case T_ForeignScanState:
340 case T_CustomScanState:
341 {
342 ScanState *sstate = (ScanState *) node;
343
344 if (sstate->ss_currentRelation &&
345 RelationGetRelid(sstate->ss_currentRelation) == table_oid)
346 result = sstate;
347 break;
348 }
349
350 /*
351 * For Append, we can check each input node. It is safe to
352 * descend to the inputs because only the input that resulted in
353 * the Append's current output node could be positioned on a tuple
354 * at all; the other inputs are either at EOF or not yet started.
355 * Hence, if the desired table is scanned by some
356 * currently-inactive input node, we will find that node but then
357 * our caller will realize that it didn't emit the tuple of
358 * interest.
359 *
360 * We do need to watch out for multiple matches (possible if
361 * Append was from UNION ALL rather than an inheritance tree).
362 *
363 * Note: we can NOT descend through MergeAppend similarly, since
364 * its inputs are likely all active, and we don't know which one
365 * returned the current output tuple. (Perhaps that could be
366 * fixed if we were to let this code know more about MergeAppend's
367 * internal state, but it does not seem worth the trouble. Users
368 * should not expect plans for ORDER BY queries to be considered
369 * simply-updatable, since they won't be if the sorting is
370 * implemented by a Sort node.)
371 */
372 case T_AppendState:
373 {
374 AppendState *astate = (AppendState *) node;
375 int i;
376
377 for (i = 0; i < astate->as_nplans; i++)
378 {
379 ScanState *elem = search_plan_tree(astate->appendplans[i],
380 table_oid,
381 pending_rescan);
382
383 if (!elem)
384 continue;
385 if (result)
386 return NULL; /* multiple matches */
387 result = elem;
388 }
389 break;
390 }
391
392 /*
393 * Result and Limit can be descended through (these are safe
394 * because they always return their input's current row)
395 */
396 case T_ResultState:
397 case T_LimitState:
398 result = search_plan_tree(node->lefttree,
399 table_oid,
400 pending_rescan);
401 break;
402
403 /*
404 * SubqueryScan too, but it keeps the child in a different place
405 */
406 case T_SubqueryScanState:
407 result = search_plan_tree(((SubqueryScanState *) node)->subplan,
408 table_oid,
409 pending_rescan);
410 break;
411
412 default:
413 /* Otherwise, assume we can't descend through it */
414 break;
415 }
416
417 /*
418 * If we found a candidate at or below this node, then this node's
419 * chgParam indicates a pending rescan that will affect the candidate.
420 */
421 if (result && node->chgParam != NULL)
422 *pending_rescan = true;
423
424 return result;
425 }
426