| 595 | |
| 596 | |
| 597 | void |
| 598 | ExecReScanSetOp(SetOpState *node) |
| 599 | { |
| 600 | ExecClearTuple(node->ps.ps_ResultTupleSlot); |
| 601 | node->setop_done = false; |
| 602 | node->numOutput = 0; |
| 603 | |
| 604 | if (((SetOp *) node->ps.plan)->strategy == SETOP_HASHED) |
| 605 | { |
| 606 | /* |
| 607 | * In the hashed case, if we haven't yet built the hash table then we |
| 608 | * can just return; nothing done yet, so nothing to undo. If subnode's |
| 609 | * chgParam is not NULL then it will be re-scanned by ExecProcNode, |
| 610 | * else no reason to re-scan it at all. |
| 611 | */ |
| 612 | if (!node->table_filled) |
| 613 | return; |
| 614 | |
| 615 | /* |
| 616 | * If we do have the hash table and the subplan does not have any |
| 617 | * parameter changes, then we can just rescan the existing hash table; |
| 618 | * no need to build it again. |
| 619 | */ |
| 620 | if (node->ps.lefttree->chgParam == NULL) |
| 621 | { |
| 622 | ResetTupleHashIterator(node->hashtable, &node->hashiter); |
| 623 | return; |
| 624 | } |
| 625 | } |
| 626 | |
| 627 | /* Release first tuple of group, if we have made a copy */ |
| 628 | if (node->grp_firstTuple != NULL) |
| 629 | { |
| 630 | heap_freetuple(node->grp_firstTuple); |
| 631 | node->grp_firstTuple = NULL; |
| 632 | } |
| 633 | |
| 634 | /* Release any hashtable storage */ |
| 635 | if (node->tableContext) |
| 636 | MemoryContextResetAndDeleteChildren(node->tableContext); |
| 637 | |
| 638 | /* And rebuild empty hashtable if needed */ |
| 639 | if (((SetOp *) node->ps.plan)->strategy == SETOP_HASHED) |
| 640 | { |
| 641 | ResetTupleHashTable(node->hashtable); |
| 642 | node->table_filled = false; |
| 643 | } |
| 644 | |
| 645 | /* |
| 646 | * if chgParam of subnode is not null then plan will be re-scanned by |
| 647 | * first ExecProcNode. |
| 648 | */ |
| 649 | if (node->ps.lefttree->chgParam == NULL) |
| 650 | ExecReScan(node->ps.lefttree); |
| 651 | } |
no test coverage detected