1 /*------------------------------------------------------------------------- 2 * 3 * execCurrent.c 4 * executor support for WHERE CURRENT OF cursor 5 * 6 * Portions Copyright (c) 1996-2019, 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/genam.h" 16 #include "access/relscan.h" 17 #include "access/sysattr.h" 18 #include "catalog/pg_type.h" 19 #include "executor/executor.h" 20 #include "utils/builtins.h" 21 #include "utils/lsyscache.h" 22 #include "utils/portal.h" 23 #include "utils/rel.h" 24 25 26 static char *fetch_cursor_param_value(ExprContext *econtext, int paramId); 27 static ScanState *search_plan_tree(PlanState *node, Oid table_oid, 28 bool *pending_rescan); 29 30 31 /* 32 * execCurrentOf 33 * 34 * Given a CURRENT OF expression and the OID of a table, determine which row 35 * of the table is currently being scanned by the cursor named by CURRENT OF, 36 * and return the row's TID into *current_tid. 37 * 38 * Returns true if a row was identified. Returns false if the cursor is valid 39 * for the table but is not currently scanning a row of the table (this is a 40 * legal situation in inheritance cases). Raises error if cursor is not a 41 * valid updatable scan of the specified table. 42 */ 43 bool 44 execCurrentOf(CurrentOfExpr *cexpr, 45 ExprContext *econtext, 46 Oid table_oid, 47 ItemPointer current_tid) 48 { 49 char *cursor_name; 50 char *table_name; 51 Portal portal; 52 QueryDesc *queryDesc; 53 54 /* Get the cursor name --- may have to look up a parameter reference */ 55 if (cexpr->cursor_name) 56 cursor_name = cexpr->cursor_name; 57 else 58 cursor_name = fetch_cursor_param_value(econtext, cexpr->cursor_param); 59 60 /* Fetch table name for possible use in error messages */ 61 table_name = get_rel_name(table_oid); 62 if (table_name == NULL) 63 elog(ERROR, "cache lookup failed for relation %u", table_oid); 64 65 /* Find the cursor's portal */ 66 portal = GetPortalByName(cursor_name); 67 if (!PortalIsValid(portal)) 68 ereport(ERROR, 69 (errcode(ERRCODE_UNDEFINED_CURSOR), 70 errmsg("cursor \"%s\" does not exist", cursor_name))); 71 72 /* 73 * We have to watch out for non-SELECT queries as well as held cursors, 74 * both of which may have null queryDesc. 75 */ 76 if (portal->strategy != PORTAL_ONE_SELECT) 77 ereport(ERROR, 78 (errcode(ERRCODE_INVALID_CURSOR_STATE), 79 errmsg("cursor \"%s\" is not a SELECT query", 80 cursor_name))); 81 queryDesc = portal->queryDesc; 82 if (queryDesc == NULL || queryDesc->estate == NULL) 83 ereport(ERROR, 84 (errcode(ERRCODE_INVALID_CURSOR_STATE), 85 errmsg("cursor \"%s\" is held from a previous transaction", 86 cursor_name))); 87 88 /* 89 * We have two different strategies depending on whether the cursor uses 90 * FOR UPDATE/SHARE or not. The reason for supporting both is that the 91 * FOR UPDATE code is able to identify a target table in many cases where 92 * the other code can't, while the non-FOR-UPDATE case allows use of WHERE 93 * CURRENT OF with an insensitive cursor. 94 */ 95 if (queryDesc->estate->es_rowmarks) 96 { 97 ExecRowMark *erm; 98 Index i; 99 100 /* 101 * Here, the query must have exactly one FOR UPDATE/SHARE reference to 102 * the target table, and we dig the ctid info out of that. 103 */ 104 erm = NULL; 105 for (i = 0; i < queryDesc->estate->es_range_table_size; i++) 106 { 107 ExecRowMark *thiserm = queryDesc->estate->es_rowmarks[i]; 108 109 if (thiserm == NULL || 110 !RowMarkRequiresRowShareLock(thiserm->markType)) 111 continue; /* ignore non-FOR UPDATE/SHARE items */ 112 113 if (thiserm->relid == table_oid) 114 { 115 if (erm) 116 ereport(ERROR, 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) 125 ereport(ERROR, 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 * The cursor must have a current result row: per the SQL spec, it's 132 * an error if not. 133 */ 134 if (portal->atStart || portal->atEnd) 135 ereport(ERROR, 136 (errcode(ERRCODE_INVALID_CURSOR_STATE), 137 errmsg("cursor \"%s\" is not positioned on a row", 138 cursor_name))); 139 140 /* Return the currently scanned TID, if there is one */ 141 if (ItemPointerIsValid(&(erm->curCtid))) 142 { 143 *current_tid = erm->curCtid; 144 return true; 145 } 146 147 /* 148 * This table didn't produce the cursor's current row; some other 149 * inheritance child of the same parent must have. Signal caller to 150 * do nothing on this table. 151 */ 152 return false; 153 } 154 else 155 { 156 /* 157 * Without FOR UPDATE, we dig through the cursor's plan to find the 158 * scan node. Fail if it's not there or buried underneath 159 * aggregation. 160 */ 161 ScanState *scanstate; 162 bool pending_rescan = false; 163 164 scanstate = search_plan_tree(queryDesc->planstate, table_oid, 165 &pending_rescan); 166 if (!scanstate) 167 ereport(ERROR, 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 * The cursor must have a current result row: per the SQL spec, it's 174 * an error if not. We test this at the top level, rather than at the 175 * scan node level, because in inheritance cases any one table scan 176 * could easily not be on a row. We want to return false, not raise 177 * error, if the passed-in table OID is for one of the inactive scans. 178 */ 179 if (portal->atStart || portal->atEnd) 180 ereport(ERROR, 181 (errcode(ERRCODE_INVALID_CURSOR_STATE), 182 errmsg("cursor \"%s\" is not positioned on a row", 183 cursor_name))); 184 185 /* 186 * Now OK to return false if we found an inactive scan. It is 187 * inactive either if it's not positioned on a row, or there's a 188 * rescan pending for it. 189 */ 190 if (TupIsNull(scanstate->ss_ScanTupleSlot) || pending_rescan) 191 return false; 192 193 /* 194 * Extract TID of the scan's current row. The mechanism for this is 195 * in principle scan-type-dependent, but for most scan types, we can 196 * just dig the TID out of the physical scan tuple. 197 */ 198 if (IsA(scanstate, IndexOnlyScanState)) 199 { 200 /* 201 * For IndexOnlyScan, the tuple stored in ss_ScanTupleSlot may be 202 * a virtual tuple that does not have the ctid column, so we have 203 * to get the TID from xs_ctup.t_self. 204 */ 205 IndexScanDesc scan = ((IndexOnlyScanState *) scanstate)->ioss_ScanDesc; 206 207 *current_tid = scan->xs_heaptid; 208 } 209 else 210 { 211 /* 212 * Default case: try to fetch TID from the scan node's current 213 * tuple. As an extra cross-check, verify tableoid in the current 214 * tuple. If the scan hasn't provided a physical tuple, we have 215 * to fail. 216 */ 217 Datum ldatum; 218 bool lisnull; 219 ItemPointer tuple_tid; 220 221 #ifdef USE_ASSERT_CHECKING 222 ldatum = slot_getsysattr(scanstate->ss_ScanTupleSlot, 223 TableOidAttributeNumber, 224 &lisnull); 225 if (lisnull) 226 ereport(ERROR, 227 (errcode(ERRCODE_INVALID_CURSOR_STATE), 228 errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"", 229 cursor_name, table_name))); 230 Assert(DatumGetObjectId(ldatum) == table_oid); 231 #endif 232 233 ldatum = slot_getsysattr(scanstate->ss_ScanTupleSlot, 234 SelfItemPointerAttributeNumber, 235 &lisnull); 236 if (lisnull) 237 ereport(ERROR, 238 (errcode(ERRCODE_INVALID_CURSOR_STATE), 239 errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"", 240 cursor_name, table_name))); 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 * 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 * 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