PostgreSQL Source Code: src/backend/executor/execCurrent.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
14
24
25
28 bool *pending_rescan);
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43bool
46 Oid table_oid,
48{
49 char *cursor_name;
50 char *table_name;
53
54
57 else
59
60
62 if (table_name == NULL)
63 elog(ERROR, "cache lookup failed for relation %u", table_oid);
64
65
69 (errcode(ERRCODE_UNDEFINED_CURSOR),
70 errmsg("cursor \"%s\" does not exist", cursor_name)));
71
72
73
74
75
78 (errcode(ERRCODE_INVALID_CURSOR_STATE),
79 errmsg("cursor \"%s\" is not a SELECT query",
80 cursor_name)));
82 if (queryDesc == NULL || queryDesc->estate == NULL)
84 (errcode(ERRCODE_INVALID_CURSOR_STATE),
85 errmsg("cursor \"%s\" is held from a previous transaction",
86 cursor_name)));
87
88
89
90
91
92
93
94
96 {
99
100
101
102
103
104 erm = NULL;
106 {
108
109 if (thiserm == NULL ||
111 continue;
112
113 if (thiserm->relid == table_oid)
114 {
115 if (erm)
117 (errcode(ERRCODE_INVALID_CURSOR_STATE),
118 errmsg("cursor \"%s\" has multiple FOR UPDATE/SHARE references to table \"%s\"",
119 cursor_name, table_name)));
120 erm = thiserm;
121 }
122 }
123
124 if (erm == NULL)
126 (errcode(ERRCODE_INVALID_CURSOR_STATE),
127 errmsg("cursor \"%s\" does not have a FOR UPDATE/SHARE reference to table \"%s\"",
128 cursor_name, table_name)));
129
130
131
132
133
136 (errcode(ERRCODE_INVALID_CURSOR_STATE),
137 errmsg("cursor \"%s\" is not positioned on a row",
138 cursor_name)));
139
140
142 {
143 *current_tid = erm->curCtid;
144 return true;
145 }
146
147
148
149
150
151
152 return false;
153 }
154 else
155 {
156
157
158
159
160
162 bool pending_rescan = false;
163
165 &pending_rescan);
166 if (!scanstate)
168 (errcode(ERRCODE_INVALID_CURSOR_STATE),
169 errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
170 cursor_name, table_name)));
171
172
173
174
175
176
177
178
181 (errcode(ERRCODE_INVALID_CURSOR_STATE),
182 errmsg("cursor \"%s\" is not positioned on a row",
183 cursor_name)));
184
185
186
187
188
189
191 return false;
192
193
194
195
196
197
199 {
200
201
202
203
204
206
208 }
209 else
210 {
211
212
213
214
215
216
218 bool lisnull;
220
221#ifdef USE_ASSERT_CHECKING
224 &lisnull);
225 if (lisnull)
227 (errcode(ERRCODE_INVALID_CURSOR_STATE),
228 errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
229 cursor_name, table_name)));
231#endif
232
235 &lisnull);
236 if (lisnull)
238 (errcode(ERRCODE_INVALID_CURSOR_STATE),
239 errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
240 cursor_name, table_name)));
242
243 *current_tid = *tuple_tid;
244 }
245
247
248 return true;
249 }
250}
251
252
253
254
255
256
257static char *
259{
261
262 if (paramInfo &&
263 paramId > 0 && paramId <= paramInfo->numParams)
264 {
267
268
270 prm = paramInfo->paramFetch(paramInfo, paramId, false, &prmdata);
271 else
272 prm = ¶mInfo->params[paramId - 1];
273
275 {
276
277 if (prm->ptype != REFCURSOROID)
279 (errcode(ERRCODE_DATATYPE_MISMATCH),
280 errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
281 paramId,
284
285
287 }
288 }
289
291 (errcode(ERRCODE_UNDEFINED_OBJECT),
292 errmsg("no value found for parameter %d", paramId)));
293 return NULL;
294}
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
315 bool *pending_rescan)
316{
318
319 if (node == NULL)
320 return NULL;
322 {
323
324
325
326
327
328
329
330
331
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_TidRangeScanState:
340 case T_ForeignScanState:
341 case T_CustomScanState:
342 {
344
347 result = sstate;
348 break;
349 }
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373 case T_AppendState:
374 {
376 int i;
377
379 {
381 table_oid,
382 pending_rescan);
383
384 if (!elem)
385 continue;
386 if (result)
387 return NULL;
388 result = elem;
389 }
390 break;
391 }
392
393
394
395
396
397 case T_ResultState:
398 case T_LimitState:
400 table_oid,
401 pending_rescan);
402 break;
403
404
405
406
407 case T_SubqueryScanState:
409 table_oid,
410 pending_rescan);
411 break;
412
413 default:
414
415 break;
416 }
417
418
419
420
421
422 if (result && node->chgParam != NULL)
423 *pending_rescan = true;
424
425 return result;
426}
#define TextDatumGetCString(d)
#define OidIsValid(objectId)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
static ScanState * search_plan_tree(PlanState *node, Oid table_oid, bool *pending_rescan)
static char * fetch_cursor_param_value(ExprContext *econtext, int paramId)
bool execCurrentOf(CurrentOfExpr *cexpr, ExprContext *econtext, Oid table_oid, ItemPointer current_tid)
#define outerPlanState(node)
char * format_type_be(Oid type_oid)
Assert(PointerIsAligned(start, uint64))
ItemPointerData * ItemPointer
static bool ItemPointerIsValid(const ItemPointerData *pointer)
char * get_rel_name(Oid relid)
#define IsA(nodeptr, _type_)
#define RowMarkRequiresRowShareLock(marktype)
Portal GetPortalByName(const char *name)
static Oid DatumGetObjectId(Datum X)
static Pointer DatumGetPointer(Datum X)
#define RelationGetRelid(relation)
struct ExecRowMark ** es_rowmarks
Index es_range_table_size
ParamListInfo ecxt_param_list_info
ItemPointerData xs_heaptid
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
ParamFetchHook paramFetch
Relation ss_currentRelation
TupleTableSlot * ss_ScanTupleSlot
#define TableOidAttributeNumber
#define SelfItemPointerAttributeNumber
static Datum slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)