---------------------------------------------------------------- * ExecUnique * ---------------------------------------------------------------- */
| 45 | * ---------------------------------------------------------------- |
| 46 | */ |
| 47 | static TupleTableSlot * /* return: a tuple or NULL */ |
| 48 | ExecUnique(PlanState *pstate) |
| 49 | { |
| 50 | UniqueState *node = castNode(UniqueState, pstate); |
| 51 | ExprContext *econtext = node->ps.ps_ExprContext; |
| 52 | TupleTableSlot *resultTupleSlot; |
| 53 | TupleTableSlot *slot; |
| 54 | PlanState *outerPlan; |
| 55 | |
| 56 | CHECK_FOR_INTERRUPTS(); |
| 57 | |
| 58 | /* |
| 59 | * get information from the node |
| 60 | */ |
| 61 | outerPlan = outerPlanState(node); |
| 62 | resultTupleSlot = node->ps.ps_ResultTupleSlot; |
| 63 | |
| 64 | /* |
| 65 | * now loop, returning only non-duplicate tuples. We assume that the |
| 66 | * tuples arrive in sorted order so we can detect duplicates easily. The |
| 67 | * first tuple of each group is returned. |
| 68 | */ |
| 69 | for (;;) |
| 70 | { |
| 71 | /* |
| 72 | * fetch a tuple from the outer subplan |
| 73 | */ |
| 74 | slot = ExecProcNode(outerPlan); |
| 75 | if (TupIsNull(slot)) |
| 76 | { |
| 77 | /* end of subplan, so we're done */ |
| 78 | ExecClearTuple(resultTupleSlot); |
| 79 | return NULL; |
| 80 | } |
| 81 | |
| 82 | /* |
| 83 | * Always return the first tuple from the subplan. |
| 84 | */ |
| 85 | if (TupIsNull(resultTupleSlot)) |
| 86 | break; |
| 87 | |
| 88 | /* |
| 89 | * Else test if the new tuple and the previously returned tuple match. |
| 90 | * If so then we loop back and fetch another new tuple from the |
| 91 | * subplan. |
| 92 | */ |
| 93 | econtext->ecxt_innertuple = slot; |
| 94 | econtext->ecxt_outertuple = resultTupleSlot; |
| 95 | if (!ExecQualAndReset(node->eqfunction, econtext)) |
| 96 | break; |
| 97 | } |
| 98 | |
| 99 | /* |
| 100 | * We have a new tuple different from the previous saved tuple (if any). |
| 101 | * Save it and return it. We must copy it because the source subplan |
| 102 | * won't guarantee that this source tuple is still accessible after |
| 103 | * fetching the next source tuple. |
| 104 | */ |
nothing calls this directly
no test coverage detected