Common recursive CTE looks like:
WITH RECURSIVE
cte AS (
SELECT 1 id
UNION ALL
SELECT id + 1 FROM cte WHERE id < 1000
)
SELECT COUNT(*) FROM cte;
This form is well-described in Reference Manual.
But the same output can be produced while using another synthactic form of the CTE:
WITH RECURSIVE
cte AS (
SELECT 1 id
UNION ALL
SELECT id + 1 FROM cte LIMIT 1000
)
SELECT COUNT(*) FROM cte;
This alternative form is not described in RM. Moreover, it does not match the next part of the description in RM:
Each iteration of the recursive part operates only on the rows produced by the previous iteration. If the recursive part has multiple query blocks, iterations of each query block are scheduled in unspecified order, and each query block operates on rows that have been produced either by its previous iteration or by other query blocks since that previous iteration's end.
Each iteration of the recursive part produces one row. There is nothing in the recursive part that would lead to the fact that a new row will NOT be created at the next step of the recursion.
But the recursion nevertheless ends, and the total number of rows corresponds to the LIMIT value.
How does recursive CTE work in such a syntactic form?
UPDATE - copied from the comments.
Reason is that LIMIT applies to the UNION statement, not to the single queries (unless you use parentheses). – lemon
It seems obvious. But I can't find where RM describes that the whole, combined, result is being investigated.
And one more thing - if the CTE recursion stops, then the 1001st row is generated, which is then discarded using LIMIT, this does not lead to new rows and stops the recursion.. but I can't find the reason why exactly the row that is created on the most last iteration is discarded using LIMIT deterministically.