* Open a table during parse analysis * * This is essentially just the same as table_openrv(), except that it caters * to some parser-specific error reporting needs, notably that it arranges * to include the RangeVar's parse location in any resulting error. * * Note: properly, lockmode should be declared LOCKMODE not int, but that * would require importing storage/lock.h into parse_relation.
| 1367 | * LOCKMODE is typedef'd as int anyway, that seems like overkill. |
| 1368 | */ |
| 1369 | Relation |
| 1370 | parserOpenTable(ParseState *pstate, const RangeVar *relation, |
| 1371 | int lockmode, bool *lockUpgraded) |
| 1372 | { |
| 1373 | Relation rel; |
| 1374 | ParseCallbackState pcbstate; |
| 1375 | Oid relid; |
| 1376 | |
| 1377 | setup_parser_errposition_callback(&pcbstate, pstate, relation->location); |
| 1378 | |
| 1379 | /* Look up the appropriate relation using namespace search */ |
| 1380 | relid = RangeVarGetRelid(relation, NoLock, true); |
| 1381 | /* |
| 1382 | * CdbTryOpenTable might return NULL (for example, if the table |
| 1383 | * is dropped by another transaction). Every time we invoke function |
| 1384 | * CdbTryOpenTable, we should check if the return value is NULL. |
| 1385 | */ |
| 1386 | rel = CdbTryOpenTable(relid, lockmode, lockUpgraded); |
| 1387 | |
| 1388 | if (!RelationIsValid(rel)) |
| 1389 | { |
| 1390 | if (relation->schemaname) |
| 1391 | ereport(ERROR, |
| 1392 | (errcode(ERRCODE_UNDEFINED_TABLE), |
| 1393 | errmsg("relation \"%s.%s\" does not exist", |
| 1394 | relation->schemaname, relation->relname))); |
| 1395 | else |
| 1396 | { |
| 1397 | /* |
| 1398 | * An unqualified name might have been meant as a reference to |
| 1399 | * some not-yet-in-scope CTE. The bare "does not exist" message |
| 1400 | * has proven remarkably unhelpful for figuring out such problems, |
| 1401 | * so we take pains to offer a specific hint. |
| 1402 | */ |
| 1403 | if (isFutureCTE(pstate, relation->relname)) |
| 1404 | ereport(ERROR, |
| 1405 | (errcode(ERRCODE_UNDEFINED_TABLE), |
| 1406 | errmsg("relation \"%s\" does not exist", |
| 1407 | relation->relname), |
| 1408 | errdetail("There is a WITH item named \"%s\", but it cannot be referenced from this part of the query.", |
| 1409 | relation->relname), |
| 1410 | errhint("Use WITH RECURSIVE, or re-order the WITH items to remove forward references."))); |
| 1411 | else |
| 1412 | ereport(ERROR, |
| 1413 | (errcode(ERRCODE_UNDEFINED_TABLE), |
| 1414 | errmsg("relation \"%s\" does not exist", |
| 1415 | relation->relname))); |
| 1416 | } |
| 1417 | } |
| 1418 | |
| 1419 | cancel_parser_errposition_callback(&pcbstate); |
| 1420 | return rel; |
| 1421 | } |
| 1422 | |
| 1423 | /* |
| 1424 | * Add an entry for a relation to the pstate's range table (p_rtable). |
no test coverage detected