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