* Read tuples from the outer node, up to and including position 'pos', and * store them into the tuplestore. If pos is -1, reads the whole partition. */
| 1498 | * store them into the tuplestore. If pos is -1, reads the whole partition. |
| 1499 | */ |
| 1500 | static void |
| 1501 | spool_tuples(WindowAggState *winstate, int64 pos) |
| 1502 | { |
| 1503 | WindowAgg *node = (WindowAgg *) winstate->ss.ps.plan; |
| 1504 | PlanState *outerPlan; |
| 1505 | TupleTableSlot *outerslot; |
| 1506 | MemoryContext oldcontext; |
| 1507 | |
| 1508 | if (!winstate->buffer) |
| 1509 | return; /* just a safety check */ |
| 1510 | if (winstate->partition_spooled) |
| 1511 | return; /* whole partition done already */ |
| 1512 | |
| 1513 | /* |
| 1514 | * If the tuplestore has spilled to disk, alternate reading and writing |
| 1515 | * becomes quite expensive due to frequent buffer flushes. It's cheaper |
| 1516 | * to force the entire partition to get spooled in one go. |
| 1517 | * |
| 1518 | * XXX this is a horrid kluge --- it'd be better to fix the performance |
| 1519 | * problem inside tuplestore. FIXME |
| 1520 | */ |
| 1521 | if (!tuplestore_in_memory(winstate->buffer)) |
| 1522 | pos = -1; |
| 1523 | |
| 1524 | outerPlan = outerPlanState(winstate); |
| 1525 | |
| 1526 | /* Must be in query context to call outerplan */ |
| 1527 | oldcontext = MemoryContextSwitchTo(winstate->ss.ps.ps_ExprContext->ecxt_per_query_memory); |
| 1528 | |
| 1529 | while (winstate->spooled_rows <= pos || pos == -1) |
| 1530 | { |
| 1531 | outerslot = ExecProcNode(outerPlan); |
| 1532 | if (TupIsNull(outerslot)) |
| 1533 | { |
| 1534 | /* reached the end of the last partition */ |
| 1535 | winstate->partition_spooled = true; |
| 1536 | winstate->more_partitions = false; |
| 1537 | break; |
| 1538 | } |
| 1539 | |
| 1540 | if (node->partNumCols > 0) |
| 1541 | { |
| 1542 | ExprContext *econtext = winstate->tmpcontext; |
| 1543 | |
| 1544 | econtext->ecxt_innertuple = winstate->first_part_slot; |
| 1545 | econtext->ecxt_outertuple = outerslot; |
| 1546 | |
| 1547 | /* Check if this tuple still belongs to the current partition */ |
| 1548 | if (!ExecQualAndReset(winstate->partEqfunction, econtext)) |
| 1549 | { |
| 1550 | /* |
| 1551 | * end of partition; copy the tuple for the next cycle. |
| 1552 | */ |
| 1553 | ExecCopySlot(winstate->first_part_slot, outerslot); |
| 1554 | winstate->partition_spooled = true; |
| 1555 | winstate->more_partitions = true; |
| 1556 | break; |
| 1557 | } |
no test coverage detected