* searchRangeTableForRel * See if any RangeTblEntry could possibly match the RangeVar. * If so, return a pointer to the RangeTblEntry; else return NULL. * * This is different from refnameNamespaceItem in that it considers every * entry in the ParseState's rangetable(s), not only those that are currently * visible in the p_namespace list(s). This behavior is invalid per the SQL * spec,
| 339 | * and matches on alias. |
| 340 | */ |
| 341 | static RangeTblEntry * |
| 342 | searchRangeTableForRel(ParseState *pstate, RangeVar *relation) |
| 343 | { |
| 344 | const char *refname = relation->relname; |
| 345 | Oid relId = InvalidOid; |
| 346 | CommonTableExpr *cte = NULL; |
| 347 | bool isenr = false; |
| 348 | Index ctelevelsup = 0; |
| 349 | Index levelsup; |
| 350 | |
| 351 | /* |
| 352 | * If it's an unqualified name, check for possible CTE matches. A CTE |
| 353 | * hides any real relation matches. If no CTE, look for a matching |
| 354 | * relation. |
| 355 | * |
| 356 | * NB: It's not critical that RangeVarGetRelid return the correct answer |
| 357 | * here in the face of concurrent DDL. If it doesn't, the worst case |
| 358 | * scenario is a less-clear error message. Also, the tables involved in |
| 359 | * the query are already locked, which reduces the number of cases in |
| 360 | * which surprising behavior can occur. So we do the name lookup |
| 361 | * unlocked. |
| 362 | */ |
| 363 | if (!relation->schemaname) |
| 364 | { |
| 365 | cte = scanNameSpaceForCTE(pstate, refname, &ctelevelsup); |
| 366 | if (!cte) |
| 367 | isenr = scanNameSpaceForENR(pstate, refname); |
| 368 | } |
| 369 | |
| 370 | if (!cte && !isenr) |
| 371 | relId = RangeVarGetRelid(relation, NoLock, true); |
| 372 | |
| 373 | /* Now look for RTEs matching either the relation/CTE/ENR or the alias */ |
| 374 | for (levelsup = 0; |
| 375 | pstate != NULL; |
| 376 | pstate = pstate->parentParseState, levelsup++) |
| 377 | { |
| 378 | ListCell *l; |
| 379 | |
| 380 | foreach(l, pstate->p_rtable) |
| 381 | { |
| 382 | RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); |
| 383 | |
| 384 | if (rte->rtekind == RTE_RELATION && |
| 385 | OidIsValid(relId) && |
| 386 | rte->relid == relId) |
| 387 | return rte; |
| 388 | if (rte->rtekind == RTE_CTE && |
| 389 | cte != NULL && |
| 390 | rte->ctelevelsup + levelsup == ctelevelsup && |
| 391 | strcmp(rte->ctename, refname) == 0) |
| 392 | return rte; |
| 393 | if (rte->rtekind == RTE_NAMEDTUPLESTORE && |
| 394 | isenr && |
| 395 | strcmp(rte->enrname, refname) == 0) |
| 396 | return rte; |
| 397 | |
| 398 | if (rte->eref != NULL && |
no test coverage detected