| 1452 | } |
| 1453 | |
| 1454 | static Node * |
| 1455 | transformMultiAssignRef(ParseState *pstate, MultiAssignRef *maref) |
| 1456 | { |
| 1457 | SubLink *sublink; |
| 1458 | RowExpr *rexpr; |
| 1459 | Query *qtree; |
| 1460 | TargetEntry *tle; |
| 1461 | |
| 1462 | /* We should only see this in first-stage processing of UPDATE tlists */ |
| 1463 | Assert(pstate->p_expr_kind == EXPR_KIND_UPDATE_SOURCE); |
| 1464 | |
| 1465 | /* We only need to transform the source if this is the first column */ |
| 1466 | if (maref->colno == 1) |
| 1467 | { |
| 1468 | /* |
| 1469 | * For now, we only allow EXPR SubLinks and RowExprs as the source of |
| 1470 | * an UPDATE multiassignment. This is sufficient to cover interesting |
| 1471 | * cases; at worst, someone would have to write (SELECT * FROM expr) |
| 1472 | * to expand a composite-returning expression of another form. |
| 1473 | */ |
| 1474 | if (IsA(maref->source, SubLink) && |
| 1475 | ((SubLink *) maref->source)->subLinkType == EXPR_SUBLINK) |
| 1476 | { |
| 1477 | /* Relabel it as a MULTIEXPR_SUBLINK */ |
| 1478 | sublink = (SubLink *) maref->source; |
| 1479 | sublink->subLinkType = MULTIEXPR_SUBLINK; |
| 1480 | /* And transform it */ |
| 1481 | sublink = (SubLink *) transformExprRecurse(pstate, |
| 1482 | (Node *) sublink); |
| 1483 | |
| 1484 | qtree = castNode(Query, sublink->subselect); |
| 1485 | |
| 1486 | /* Check subquery returns required number of columns */ |
| 1487 | if (count_nonjunk_tlist_entries(qtree->targetList) != maref->ncolumns) |
| 1488 | ereport(ERROR, |
| 1489 | (errcode(ERRCODE_SYNTAX_ERROR), |
| 1490 | errmsg("number of columns does not match number of values"), |
| 1491 | parser_errposition(pstate, sublink->location))); |
| 1492 | |
| 1493 | /* |
| 1494 | * Build a resjunk tlist item containing the MULTIEXPR SubLink, |
| 1495 | * and add it to pstate->p_multiassign_exprs, whence it will later |
| 1496 | * get appended to the completed targetlist. We needn't worry |
| 1497 | * about selecting a resno for it; transformUpdateStmt will do |
| 1498 | * that. |
| 1499 | */ |
| 1500 | tle = makeTargetEntry((Expr *) sublink, 0, NULL, true); |
| 1501 | pstate->p_multiassign_exprs = lappend(pstate->p_multiassign_exprs, |
| 1502 | tle); |
| 1503 | |
| 1504 | /* |
| 1505 | * Assign a unique-within-this-targetlist ID to the MULTIEXPR |
| 1506 | * SubLink. We can just use its position in the |
| 1507 | * p_multiassign_exprs list. |
| 1508 | */ |
| 1509 | sublink->subLinkId = list_length(pstate->p_multiassign_exprs); |
| 1510 | } |
| 1511 | else if (IsA(maref->source, RowExpr)) |
no test coverage detected