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 */ }