* ExpandRowReference() * Transforms foo.* into a list of expressions or targetlist entries. * * This handles the case where foo is an arbitrary expression of composite * type. */
| 1415 | * type. |
| 1416 | */ |
| 1417 | static List * |
| 1418 | ExpandRowReference(ParseState *pstate, Node *expr, |
| 1419 | bool make_target_entry) |
| 1420 | { |
| 1421 | List *result = NIL; |
| 1422 | TupleDesc tupleDesc; |
| 1423 | int numAttrs; |
| 1424 | int i; |
| 1425 | |
| 1426 | /* |
| 1427 | * If the rowtype expression is a whole-row Var, we can expand the fields |
| 1428 | * as simple Vars. Note: if the RTE is a relation, this case leaves us |
| 1429 | * with the RTE's selectedCols bitmap showing the whole row as needing |
| 1430 | * select permission, as well as the individual columns. However, we can |
| 1431 | * only get here for weird notations like (table.*).*, so it's not worth |
| 1432 | * trying to clean up --- arguably, the permissions marking is correct |
| 1433 | * anyway for such cases. |
| 1434 | */ |
| 1435 | if (IsA(expr, Var) && |
| 1436 | ((Var *) expr)->varattno == InvalidAttrNumber) |
| 1437 | { |
| 1438 | Var *var = (Var *) expr; |
| 1439 | ParseNamespaceItem *nsitem; |
| 1440 | |
| 1441 | nsitem = GetNSItemByRangeTablePosn(pstate, var->varno, var->varlevelsup); |
| 1442 | return ExpandSingleTable(pstate, nsitem, var->varlevelsup, var->location, make_target_entry); |
| 1443 | } |
| 1444 | |
| 1445 | /* |
| 1446 | * Otherwise we have to do it the hard way. Our current implementation is |
| 1447 | * to generate multiple copies of the expression and do FieldSelects. |
| 1448 | * (This can be pretty inefficient if the expression involves nontrivial |
| 1449 | * computation :-(.) |
| 1450 | * |
| 1451 | * Verify it's a composite type, and get the tupdesc. |
| 1452 | * get_expr_result_tupdesc() handles this conveniently. |
| 1453 | * |
| 1454 | * If it's a Var of type RECORD, we have to work even harder: we have to |
| 1455 | * find what the Var refers to, and pass that to get_expr_result_tupdesc. |
| 1456 | * That task is handled by expandRecordVariable(). |
| 1457 | */ |
| 1458 | if (IsA(expr, Var) && |
| 1459 | ((Var *) expr)->vartype == RECORDOID) |
| 1460 | tupleDesc = expandRecordVariable(pstate, (Var *) expr, 0); |
| 1461 | else |
| 1462 | tupleDesc = get_expr_result_tupdesc(expr, false); |
| 1463 | Assert(tupleDesc); |
| 1464 | |
| 1465 | /* Generate a list of references to the individual fields */ |
| 1466 | numAttrs = tupleDesc->natts; |
| 1467 | for (i = 0; i < numAttrs; i++) |
| 1468 | { |
| 1469 | Form_pg_attribute att = TupleDescAttr(tupleDesc, i); |
| 1470 | FieldSelect *fselect; |
| 1471 | |
| 1472 | if (att->attisdropped) |
| 1473 | continue; |
| 1474 |
no test coverage detected