* markTargetListOrigin() * If 'var' is a Var of a plain relation, mark 'tle' with its origin * * levelsup is an extra offset to interpret the Var's varlevelsup correctly. * * Note that we do not drill down into views, but report the view as the * column owner. There's also no need to drill down into joins: if we see * a join alias Var, it must be a merged JOIN USING column (or possibly a
| 342 | * so we don't report it. |
| 343 | */ |
| 344 | static void |
| 345 | markTargetListOrigin(ParseState *pstate, TargetEntry *tle, |
| 346 | Var *var, int levelsup) |
| 347 | { |
| 348 | int netlevelsup; |
| 349 | RangeTblEntry *rte; |
| 350 | AttrNumber attnum; |
| 351 | |
| 352 | if (var == NULL || !IsA(var, Var)) |
| 353 | return; |
| 354 | netlevelsup = var->varlevelsup + levelsup; |
| 355 | rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup); |
| 356 | attnum = var->varattno; |
| 357 | |
| 358 | switch (rte->rtekind) |
| 359 | { |
| 360 | case RTE_RELATION: |
| 361 | /* It's a table or view, report it */ |
| 362 | tle->resorigtbl = rte->relid; |
| 363 | tle->resorigcol = attnum; |
| 364 | break; |
| 365 | case RTE_SUBQUERY: |
| 366 | /* Subselect-in-FROM: copy up from the subselect */ |
| 367 | if (attnum != InvalidAttrNumber) |
| 368 | { |
| 369 | TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList, |
| 370 | attnum); |
| 371 | |
| 372 | if (ste == NULL || ste->resjunk) |
| 373 | elog(ERROR, "subquery %s does not have attribute %d", |
| 374 | rte->eref->aliasname, attnum); |
| 375 | tle->resorigtbl = ste->resorigtbl; |
| 376 | tle->resorigcol = ste->resorigcol; |
| 377 | } |
| 378 | break; |
| 379 | case RTE_JOIN: |
| 380 | case RTE_FUNCTION: |
| 381 | case RTE_VALUES: |
| 382 | case RTE_TABLEFUNC: |
| 383 | case RTE_NAMEDTUPLESTORE: |
| 384 | case RTE_RESULT: |
| 385 | case RTE_VOID: |
| 386 | case RTE_TABLEFUNCTION: |
| 387 | /* not a simple relation, leave it unmarked */ |
| 388 | break; |
| 389 | case RTE_CTE: |
| 390 | |
| 391 | /* |
| 392 | * CTE reference: copy up from the subquery, if possible. If the |
| 393 | * RTE is a recursive self-reference then we can't do anything |
| 394 | * because we haven't finished analyzing it yet. However, it's no |
| 395 | * big loss because we must be down inside the recursive term of a |
| 396 | * recursive CTE, and so any markings on the current targetlist |
| 397 | * are not going to affect the results anyway. |
| 398 | */ |
| 399 | if (attnum != InvalidAttrNumber && !rte->self_reference) |
| 400 | { |
| 401 | CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup); |
no test coverage detected