On 9/6/16 12:00 PM, Tom Lane wrote:
On the other hand, if eof_cte is true, then what happened on the last call is that we tried to fetch forwards, reached EOF on the underlying query, and returned NULL. In that case, a backwards fetch *should* produce the last row in the tuplestore.
Patch attached. -- Jim Nasby, Data Architect, Blue Treble Consulting, Austin TX Experts in Analytics, Data Architecture and PostgreSQL Data in Trouble? Get it in Treble! http://BlueTreble.com 855-TREBLE2 (855-873-2532) mobile: 512-569-9461
diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c index 3c2f684..64248cb 100644 --- a/src/backend/executor/nodeCtescan.c +++ b/src/backend/executor/nodeCtescan.c @@ -53,8 +53,21 @@ CteScanNext(CteScanState *node) */ eof_tuplestore = tuplestore_ateof(tuplestorestate); + /* + * Before fetching, we need to handle a special case: when reversing + * direction at the end of the tuplestore, the next + * tuplestore_gettupleslot() call will return the last tuple. But since + * that tuple was just seen, we want to move past it. This is necessary + * because the tuplestore get routines always move the current pointer, + * unless they hit the end (or beginning) of the store. + */ if (!forward && eof_tuplestore) { + /* + * However, once we hit the end of the underlying node any call while + * at the end of the tuplestore will return NULL. In that case, we DO + * want to return the last row in the tuplestore. + */ if (!node->leader->eof_cte) { /* diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 9ab03f3..197b91b 100644 --- a/src/backend/executor/nodeMaterial.c +++ b/src/backend/executor/nodeMaterial.c @@ -82,16 +82,23 @@ ExecMaterial(MaterialState *node) eof_tuplestore = (tuplestorestate == NULL) || tuplestore_ateof(tuplestorestate); + /* + * Before fetching, we need to handle a special case: when reversing + * direction at the end of the tuplestore, the next + * tuplestore_gettupleslot() call will return the last tuple. But since + * that tuple was just seen, we want to move past it. This is necessary + * because the tuplestore get routines always move the current pointer, + * unless they hit the end (or beginning) of the store. + */ if (!forward && eof_tuplestore) { + /* + * However, once we hit the end of the underlying node any call while + * at the end of the tuplestore will return NULL. In that case, we DO + * want to return the last row in the tuplestore. + */ if (!node->eof_underlying) { - /* - * When reversing direction at tuplestore EOF, the first - * gettupleslot call will fetch the last-added tuple; but we want - * to return the one before that, if possible. So do an extra - * fetch. - */ if (!tuplestore_advance(tuplestorestate, forward)) return NULL; /* the tuplestore must be empty */ }
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers