| Line | Hits | Source | Commit |
| 1525 |
- |
expandRecordVariable(ParseState *pstate, Var *var, int levelsup) |
- |
| 1526 |
- |
{ |
- |
| 1527 |
- |
TupleDesc tupleDesc; |
- |
| 1528 |
- |
int netlevelsup; |
- |
| 1529 |
- |
RangeTblEntry *rte; |
- |
| 1530 |
- |
AttrNumber attnum; |
- |
| 1531 |
- |
Node *expr; |
- |
| 1532 |
- |
|
- |
| 1533 |
- |
/* Check my caller didn't mess up */ |
- |
| 1534 |
- |
Assert(IsA(var, Var)); |
- |
| 1535 |
- |
Assert(var->vartype == RECORDOID); |
- |
| 1536 |
- |
|
- |
| 1537 |
- |
/* |
- |
| 1538 |
- |
* Note: it's tempting to use GetNSItemByRangeTablePosn here so that we |
- |
| 1539 |
- |
* can use expandNSItemVars instead of expandRTE; but that does not work |
- |
| 1540 |
- |
* for some of the recursion cases below, where we have consed up a |
- |
| 1541 |
- |
* ParseState that lacks p_namespace data. |
- |
| 1542 |
- |
*/ |
- |
| 1543 |
- |
netlevelsup = var->varlevelsup + levelsup; |
- |
| 1544 |
- |
rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup); |
- |
| 1545 |
- |
attnum = var->varattno; |
- |
| 1546 |
- |
|
- |
| 1547 |
- |
if (attnum == InvalidAttrNumber) |
- |
| 1548 |
- |
{ |
- |
| 1549 |
- |
/* Whole-row reference to an RTE, so expand the known fields */ |
- |
| 1550 |
- |
List *names, |
- |
| 1551 |
- |
*vars; |
- |
| 1552 |
- |
ListCell *lname, |
- |
| 1553 |
- |
*lvar; |
- |
| 1554 |
- |
int i; |
- |
| 1555 |
- |
|
- |
| 1556 |
- |
expandRTE(rte, var->varno, 0, var->varreturningtype, |
- |
| 1557 |
- |
var->location, false, &names, &vars); |
- |
| 1558 |
- |
|
- |
| 1559 |
- |
tupleDesc = CreateTemplateTupleDesc(list_length(vars)); |
- |
| 1560 |
- |
i = 1; |
- |
| 1561 |
- |
forboth(lname, names, lvar, vars) |
- |
| 1562 |
- |
{ |
- |
| 1563 |
- |
char *label = strVal(lfirst(lname)); |
- |
| 1564 |
- |
Node *varnode = (Node *) lfirst(lvar); |
- |
| 1565 |
- |
|
- |
| 1566 |
- |
TupleDescInitEntry(tupleDesc, i, |
- |
| 1567 |
- |
label, |
- |
| 1568 |
- |
exprType(varnode), |
- |
| 1569 |
- |
exprTypmod(varnode), |
- |
| 1570 |
- |
0); |
- |
| 1571 |
- |
TupleDescInitEntryCollation(tupleDesc, i, |
- |
| 1572 |
- |
exprCollation(varnode)); |
- |
| 1573 |
- |
i++; |
- |
| 1574 |
- |
} |
- |
| 1575 |
- |
Assert(lname == NULL && lvar == NULL); /* lists same length? */ |
- |
| 1576 |
- |
|
- |
| 1577 |
- |
return tupleDesc; |
- |
| 1578 |
- |
} |
- |
| 1579 |
- |
|
- |
| 1580 |
- |
expr = (Node *) var; /* default if we can't drill down */ |
- |
| 1581 |
- |
|
- |
| 1582 |
- |
switch (rte->rtekind) |
- |
| 1583 |
- |
{ |
- |
| 1584 |
- |
case RTE_RELATION: |
- |
| 1585 |
- |
case RTE_VALUES: |
- |
| 1586 |
- |
case RTE_NAMEDTUPLESTORE: |
- |
| 1587 |
- |
case RTE_GRAPH_TABLE: |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 1588 |
- |
case RTE_RESULT: |
- |
| 1589 |
- |
|
- |
| 1590 |
- |
/* |
- |
| 1591 |
- |
* This case should not occur: a column of a table, values list, |
- |
| 1592 |
- |
* or ENR shouldn't have type RECORD. Fall through and fail (most |
- |
| 1593 |
- |
* likely) at the bottom. |
- |
| 1594 |
- |
*/ |
- |
| 1595 |
- |
break; |
- |
| 1596 |
- |
case RTE_SUBQUERY: |
- |
| 1597 |
- |
{ |
- |
| 1598 |
- |
/* Subselect-in-FROM: examine sub-select's output expr */ |
- |
| 1599 |
- |
TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList, |
- |
| 1600 |
- |
attnum); |
- |
| 1601 |
- |
|
- |
| 1602 |
- |
if (ste == NULL || ste->resjunk) |
- |
| 1603 |
- |
elog(ERROR, "subquery %s does not have attribute %d", |
- |
| 1604 |
- |
rte->eref->aliasname, attnum); |
- |
| 1605 |
- |
expr = (Node *) ste->expr; |
- |
| 1606 |
- |
if (IsA(expr, Var)) |
- |
| 1607 |
- |
{ |
- |
| 1608 |
- |
/* |
- |
| 1609 |
- |
* Recurse into the sub-select to see what its Var refers |
- |
| 1610 |
- |
* to. We have to build an additional level of ParseState |
- |
| 1611 |
- |
* to keep in step with varlevelsup in the subselect; |
- |
| 1612 |
- |
* furthermore, the subquery RTE might be from an outer |
- |
| 1613 |
- |
* query level, in which case the ParseState for the |
- |
| 1614 |
- |
* subselect must have that outer level as parent. |
- |
| 1615 |
- |
*/ |
- |
| 1616 |
- |
ParseState mypstate = {0}; |
- |
| 1617 |
- |
Index levelsup; |
- |
| 1618 |
- |
|
- |
| 1619 |
- |
/* this loop must work, since GetRTEByRangeTablePosn did */ |
- |
| 1620 |
- |
for (levelsup = 0; levelsup < netlevelsup; levelsup++) |
- |
| 1621 |
- |
pstate = pstate->parentParseState; |
- |
| 1622 |
- |
mypstate.parentParseState = pstate; |
- |
| 1623 |
- |
mypstate.p_rtable = rte->subquery->rtable; |
- |
| 1624 |
- |
/* don't bother filling the rest of the fake pstate */ |
- |
| 1625 |
- |
|
- |
| 1626 |
- |
return expandRecordVariable(&mypstate, (Var *) expr, 0); |
- |
| 1627 |
- |
} |
- |
| 1628 |
- |
/* else fall through to inspect the expression */ |
- |
| 1629 |
- |
} |
- |
| 1630 |
- |
break; |
- |
| 1631 |
- |
case RTE_JOIN: |
- |
| 1632 |
- |
/* Join RTE --- recursively inspect the alias variable */ |
- |
| 1633 |
- |
Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars)); |
- |
| 1634 |
- |
expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1); |
- |
| 1635 |
- |
Assert(expr != NULL); |
- |
| 1636 |
- |
/* We intentionally don't strip implicit coercions here */ |
- |
| 1637 |
- |
if (IsA(expr, Var)) |
- |
| 1638 |
- |
return expandRecordVariable(pstate, (Var *) expr, netlevelsup); |
- |
| 1639 |
- |
/* else fall through to inspect the expression */ |
- |
| 1640 |
- |
break; |
- |
| 1641 |
- |
case RTE_FUNCTION: |
- |
| 1642 |
- |
|
- |
| 1643 |
- |
/* |
- |
| 1644 |
- |
* We couldn't get here unless a function is declared with one of |
- |
| 1645 |
- |
* its result columns as RECORD, which is not allowed. |
- |
| 1646 |
- |
*/ |
- |
| 1647 |
- |
break; |
- |
| 1648 |
- |
case RTE_TABLEFUNC: |
- |
| 1649 |
- |
|
- |
| 1650 |
- |
/* |
- |
| 1651 |
- |
* Table function cannot have columns with RECORD type. |
- |
| 1652 |
- |
*/ |
- |
| 1653 |
- |
break; |
- |
| 1654 |
- |
case RTE_CTE: |
- |
| 1655 |
- |
/* CTE reference: examine subquery's output expr */ |
- |
| 1656 |
- |
if (!rte->self_reference) |
- |
| 1657 |
- |
{ |
- |
| 1658 |
- |
CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup); |
- |
| 1659 |
- |
TargetEntry *ste; |
- |
| 1660 |
- |
|
- |
| 1661 |
- |
ste = get_tle_by_resno(GetCTETargetList(cte), attnum); |
- |
| 1662 |
- |
if (ste == NULL || ste->resjunk) |
- |
| 1663 |
- |
elog(ERROR, "CTE %s does not have attribute %d", |
- |
| 1664 |
- |
rte->eref->aliasname, attnum); |
- |
| 1665 |
- |
expr = (Node *) ste->expr; |
- |
| 1666 |
- |
if (IsA(expr, Var)) |
- |
| 1667 |
- |
{ |
- |
| 1668 |
- |
/* |
- |
| 1669 |
- |
* Recurse into the CTE to see what its Var refers to. We |
- |
| 1670 |
- |
* have to build an additional level of ParseState to keep |
- |
| 1671 |
- |
* in step with varlevelsup in the CTE; furthermore it |
- |
| 1672 |
- |
* could be an outer CTE (compare SUBQUERY case above). |
- |
| 1673 |
- |
*/ |
- |
| 1674 |
- |
ParseState mypstate = {0}; |
- |
| 1675 |
- |
Index levelsup; |
- |
| 1676 |
- |
|
- |
| 1677 |
- |
/* this loop must work, since GetCTEForRTE did */ |
- |
| 1678 |
- |
for (levelsup = 0; |
- |
| 1679 |
- |
levelsup < rte->ctelevelsup + netlevelsup; |
- |
| 1680 |
- |
levelsup++) |
- |
| 1681 |
- |
pstate = pstate->parentParseState; |
- |
| 1682 |
- |
mypstate.parentParseState = pstate; |
- |
| 1683 |
- |
mypstate.p_rtable = ((Query *) cte->ctequery)->rtable; |
- |
| 1684 |
- |
/* don't bother filling the rest of the fake pstate */ |
- |
| 1685 |
- |
|
- |
| 1686 |
- |
return expandRecordVariable(&mypstate, (Var *) expr, 0); |
- |
| 1687 |
- |
} |
- |
| 1688 |
- |
/* else fall through to inspect the expression */ |
- |
| 1689 |
- |
} |
- |
| 1690 |
- |
break; |
- |
| 1691 |
- |
case RTE_GROUP: |
- |
| 1692 |
- |
|
- |
| 1693 |
- |
/* |
- |
| 1694 |
- |
* We couldn't get here: the RTE_GROUP RTE has not been added. |
- |
| 1695 |
- |
*/ |
- |
| 1696 |
- |
break; |
- |
| 1697 |
- |
} |
- |
| 1698 |
- |
|
- |
| 1699 |
- |
/* |
- |
| 1700 |
- |
* We now have an expression we can't expand any more, so see if |
- |
| 1701 |
- |
* get_expr_result_tupdesc() can do anything with it. |
- |
| 1702 |
- |
*/ |
- |
| 1703 |
- |
return get_expr_result_tupdesc(expr, false); |
- |
| 1704 |
- |
} |
- |