* expandRecordVariable * Get the tuple descriptor for a Var of type RECORD, if possible. * * Since no actual table or view column is allowed to have type RECORD, such * a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We * drill down to find the ultimate defining expression and attempt to infer * the tupdesc from it. We ereport if we can't determine the tupdesc. * * l
| 1510 | * levelsup is an extra offset to interpret the Var's varlevelsup correctly. |
| 1511 | */ |
| 1512 | TupleDesc |
| 1513 | expandRecordVariable(ParseState *pstate, Var *var, int levelsup) |
| 1514 | { |
| 1515 | TupleDesc tupleDesc; |
| 1516 | int netlevelsup; |
| 1517 | RangeTblEntry *rte; |
| 1518 | AttrNumber attnum; |
| 1519 | Node *expr; |
| 1520 | |
| 1521 | /* Check my caller didn't mess up */ |
| 1522 | Assert(IsA(var, Var)); |
| 1523 | Assert(var->vartype == RECORDOID); |
| 1524 | |
| 1525 | /* |
| 1526 | * Note: it's tempting to use GetNSItemByRangeTablePosn here so that we |
| 1527 | * can use expandNSItemVars instead of expandRTE; but that does not work |
| 1528 | * for some of the recursion cases below, where we have consed up a |
| 1529 | * ParseState that lacks p_namespace data. |
| 1530 | */ |
| 1531 | netlevelsup = var->varlevelsup + levelsup; |
| 1532 | rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup); |
| 1533 | attnum = var->varattno; |
| 1534 | |
| 1535 | if (attnum == InvalidAttrNumber) |
| 1536 | { |
| 1537 | /* Whole-row reference to an RTE, so expand the known fields */ |
| 1538 | List *names, |
| 1539 | *vars; |
| 1540 | ListCell *lname, |
| 1541 | *lvar; |
| 1542 | int i; |
| 1543 | |
| 1544 | expandRTE(rte, var->varno, 0, var->location, false, |
| 1545 | &names, &vars); |
| 1546 | |
| 1547 | tupleDesc = CreateTemplateTupleDesc(list_length(vars)); |
| 1548 | i = 1; |
| 1549 | forboth(lname, names, lvar, vars) |
| 1550 | { |
| 1551 | char *label = strVal(lfirst(lname)); |
| 1552 | Node *varnode = (Node *) lfirst(lvar); |
| 1553 | |
| 1554 | TupleDescInitEntry(tupleDesc, i, |
| 1555 | label, |
| 1556 | exprType(varnode), |
| 1557 | exprTypmod(varnode), |
| 1558 | 0); |
| 1559 | TupleDescInitEntryCollation(tupleDesc, i, |
| 1560 | exprCollation(varnode)); |
| 1561 | i++; |
| 1562 | } |
| 1563 | Assert(lname == NULL && lvar == NULL); /* lists same length? */ |
| 1564 | |
| 1565 | return tupleDesc; |
| 1566 | } |
| 1567 | |
| 1568 | expr = (Node *) var; /* default if we can't drill down */ |
| 1569 |
no test coverage detected