On 28-11-2021 08:22, Dmitry Yemanov wrote:
27.11.2021 17:28, Mark Rotteveel wrote:
Correction: it behaves as fetch_next (or fetch_prior) for the amount of rows that was fetched in the last fetch (or at least some number of rows buffered on the server).

I can understand needing to take into account the client-side buffer, but I don't think that I should take into account any rows that the server has buffered.

If you requested N rows from the server but now switching to the different fetch operation before getting all those rows, I expect the client to receive (and discard) the remaining part of the requested rows before sending the new opcode. This is what fbclient does currently.

I agree that the client should take into account the rows it received (and still has buffered), and the rows it asynchronously requested, but not yet received (or processed), but that isn't the case here. I requested 4 rows, and already received those 4 rows (request/response-style), but the subsequent fetch(es) with a different opcode return rows as if I used the initial (prior/next) opcode for the next four rows.

In other words, it looks as if Firebird when asked for 4 rows, will return 4 rows and *also* buffer 4 more *on the server*, and return those unconditionally on the next fetch.

For example, if I have a table with a lot of rows with a value from 1 .. N,

ABSOLUTE, position 10, returns [10]
NEXT, 5 rows, returns [11, 12, 13, 14, 15]
PRIOR 10 rows, returns [16, 17, 18, 19, 20, 19, 18, 17, 16, 15] (expected: [14, 13, 12, 11, 10, 9, 8, 7, 6, 5])

or

FIRST, returns [1]
NEXT, 4 rows returns [2, 3, 4, 5]
ABSOLUTE, position 20, returns [6] (expected: [20])
ABSOLUTE, position 20, returns [7] (expected: [20])
ABSOLUTE, position 20, returns [8] (expected: [20])
ABSOLUTE, position 20, returns [9] (expected: [20])
ABSOLUTE, position 20, returns [20]

or

ABSOLUTE, position 10, returns [10]
NEXT, 4 rows, returns [11, 12, 13, 14]
RELATIVE, position -2, returns [15] (expected: [12])
RELATIVE, position -1, returns [16] (expected: [11])
RELATIVE, position -1, returns [17] (expected: [10])
RELATIVE, position -1, returns [18] (expected: [9])
RELATIVE, position -1, returns [17] (expected: [8])

I think the client cannot be expected to also take into account some server buffer as well, especially because its size is unknowable. Even if it would normally be equal to the size of previous fetch, that is no guarantee: what if the previous fetch retrieved all but the last row?

It would also make the server-side buffering behaviour part of the server's public API, which I think is undesirable. What if in some cases it doesn't make sense to buffer, or what if it makes sense to buffer more rows, etc. You could no longer do that because the client has certain expectations.

BTW: As far as I can tell, the current code in interface.cpp doesn't work either: it swallows local buffered rows and the batches it requested, but not yet processed, then it tries to reposition the cursor using RELATIVE for that number of rows. This will not work, because the server will instead return the first buffered row instead of repositioning.

Mark
--
Mark Rotteveel


Firebird-Devel mailing list, web interface at 
https://lists.sourceforge.net/lists/listinfo/firebird-devel

Reply via email to