* setTargetTable * Add the target relation of INSERT/UPDATE/DELETE to the range table, * and make the special links to it in the ParseState. * * We also open the target relation and acquire a write lock on it. * This must be done before processing the FROM list, in case the target * is also mentioned as a source relation --- we want to be sure to grab * the write lock before any
| 259 | * Returns the rangetable index of the target relation. |
| 260 | */ |
| 261 | int |
| 262 | setTargetTable(ParseState *pstate, RangeVar *relation, |
| 263 | bool inh, bool alsoSource, AclMode requiredPerms) |
| 264 | { |
| 265 | ParseCallbackState pcbstate; |
| 266 | ParseNamespaceItem *nsitem; |
| 267 | bool lockUpgraded = false; |
| 268 | LOCKMODE lockmode; |
| 269 | |
| 270 | /* |
| 271 | * ENRs hide tables of the same name, so we need to check for them first. |
| 272 | * In contrast, CTEs don't hide tables (for this purpose). |
| 273 | */ |
| 274 | if (relation->schemaname == NULL && |
| 275 | scanNameSpaceForENR(pstate, relation->relname)) |
| 276 | ereport(ERROR, |
| 277 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 278 | errmsg("relation \"%s\" cannot be the target of a modifying statement", |
| 279 | relation->relname))); |
| 280 | |
| 281 | /* Close old target; this could only happen for multi-action rules */ |
| 282 | if (pstate->p_target_relation != NULL) |
| 283 | table_close(pstate->p_target_relation, NoLock); |
| 284 | |
| 285 | /* |
| 286 | * Open target rel and grab suitable lock (which we will hold till end of |
| 287 | * transaction). |
| 288 | * |
| 289 | * free_parsestate() will eventually do the corresponding table_close(), |
| 290 | * but *not* release the lock. |
| 291 | * |
| 292 | * CDB: Acquire ExclusiveLock if it is a distributed relation and we are |
| 293 | * doing UPDATE or DELETE activity or `insert on conflict do update`. |
| 294 | * |
| 295 | * We should use heap_openrv instead of parserOpenTable for inserts because |
| 296 | * parserOpenTable upgrades the lock to Exclusive mode for distributed |
| 297 | * tables. |
| 298 | * |
| 299 | * Cloudberry specific behavior: |
| 300 | * Statement `insert on conflict do update` should be considered |
| 301 | * like update when deducting lockmode. See github issue: |
| 302 | * https://github.com/greenplum-db/gpdb/issues/9449 |
| 303 | */ |
| 304 | if (pstate->p_is_insert && !pstate->p_is_on_conflict_update) |
| 305 | { |
| 306 | setup_parser_errposition_callback(&pcbstate, pstate, relation->location); |
| 307 | pstate->p_target_relation = heap_openrv(relation, RowExclusiveLock); |
| 308 | cancel_parser_errposition_callback(&pcbstate); |
| 309 | } |
| 310 | else |
| 311 | { |
| 312 | pstate->p_target_relation = parserOpenTable(pstate, relation, RowExclusiveLock, &lockUpgraded); |
| 313 | } |
| 314 | |
| 315 | lockmode = lockUpgraded ? ExclusiveLock : RowExclusiveLock; |
| 316 | |
| 317 | if (Gp_role == GP_ROLE_DISPATCH && |
| 318 | pstate->p_is_insert && |
no test coverage detected