* window_gettupleslot * Fetch the pos'th tuple of the current partition into the slot, * using the winobj's read pointer * * Returns true if successful, false if no such row */
| 3327 | * Returns true if successful, false if no such row |
| 3328 | */ |
| 3329 | static bool |
| 3330 | window_gettupleslot(WindowObject winobj, int64 pos, TupleTableSlot *slot) |
| 3331 | { |
| 3332 | WindowAggState *winstate = winobj->winstate; |
| 3333 | MemoryContext oldcontext; |
| 3334 | |
| 3335 | /* often called repeatedly in a row */ |
| 3336 | CHECK_FOR_INTERRUPTS(); |
| 3337 | |
| 3338 | /* Don't allow passing -1 to spool_tuples here */ |
| 3339 | if (pos < 0) |
| 3340 | return false; |
| 3341 | |
| 3342 | /* If necessary, fetch the tuple into the spool */ |
| 3343 | spool_tuples(winstate, pos); |
| 3344 | |
| 3345 | if (pos >= winstate->spooled_rows) |
| 3346 | return false; |
| 3347 | |
| 3348 | if (pos < winobj->markpos) |
| 3349 | elog(ERROR, "cannot fetch row before WindowObject's mark position"); |
| 3350 | |
| 3351 | oldcontext = MemoryContextSwitchTo(winstate->ss.ps.ps_ExprContext->ecxt_per_query_memory); |
| 3352 | |
| 3353 | tuplestore_select_read_pointer(winstate->buffer, winobj->readptr); |
| 3354 | |
| 3355 | /* |
| 3356 | * Advance or rewind until we are within one tuple of the one we want. |
| 3357 | */ |
| 3358 | if (winobj->seekpos < pos - 1) |
| 3359 | { |
| 3360 | if (!tuplestore_skiptuples(winstate->buffer, |
| 3361 | pos - 1 - winobj->seekpos, |
| 3362 | true)) |
| 3363 | elog(ERROR, "unexpected end of tuplestore"); |
| 3364 | winobj->seekpos = pos - 1; |
| 3365 | } |
| 3366 | else if (winobj->seekpos > pos + 1) |
| 3367 | { |
| 3368 | if (!tuplestore_skiptuples(winstate->buffer, |
| 3369 | winobj->seekpos - (pos + 1), |
| 3370 | false)) |
| 3371 | elog(ERROR, "unexpected end of tuplestore"); |
| 3372 | winobj->seekpos = pos + 1; |
| 3373 | } |
| 3374 | else if (winobj->seekpos == pos) |
| 3375 | { |
| 3376 | /* |
| 3377 | * There's no API to refetch the tuple at the current position. We |
| 3378 | * have to move one tuple forward, and then one backward. (We don't |
| 3379 | * do it the other way because we might try to fetch the row before |
| 3380 | * our mark, which isn't allowed.) XXX this case could stand to be |
| 3381 | * optimized. |
| 3382 | */ |
| 3383 | tuplestore_advance(winstate->buffer, true); |
| 3384 | winobj->seekpos++; |
| 3385 | } |
| 3386 |
no test coverage detected