Bug #10026
A multi-table AdaptiveQuery running off-end is still updating the cursor
0%
History
#1 Updated by Alexandru Lungu about 1 year ago
- File 10026.patch
added - Assignee set to Stefanel Pezamosca
From #10000:
First and foremost, there is Eduard's change in trunk rev. 15701 where buffers from components 2 onward are not released on off-end. This is a correct fix from #9538.
- However, this exposes a limitation in AdaptiveQuery where the
cursor.addResultFirst(getCurrentIds());is called unconditionally. It should have checked whether the query actually run off-end and then callcursor.addResultFirst(null);. [...] we need a better synchronization between results and cursor: the cursor is empty when the results are empty and cursor has records when the results actually fetched something.
I am attaching my attempt.
This covers the example in #9538-69 - but scrolling variant. Debug it and check that after running off-end, the row is also added to the cursor instead of null to signal last entry.
With my attempt, FIND CURRENT becomes broken, because not updating the cursor will let is eventually empty. A FIND CURRENT on an example like #10000-34 will yield an error.
- Extend the FIND CURRENT test-case suite to cover: scrolling, non-scrolling queries + browsed queries + multi-table queries (with optimized components or not).
- run some nexts and run FIND CURRENT.
- run some nexts and then some prevs + run FIND CURRENT (the buffers should have been loaded by
loadByValuenow). - etc.
- Check if there are other places where the query should decide whether updating the cursor with ids or null is right. There may be other places apart from the ones in my patch.
- Fix GET CURRENT to work even if that component didn't find anything. It is possible to have a record loaded using
loadByValues, but the results and cursor still be empty (and the query off-end). Maybe calling the CURRENT fromCompoundQueryshould by-pass such checks. The CURRENT solely relies on buffer contents, so it is irrelevant if the query is off-end. - Extra: please check in OE what happens if buffers are loaded with something else before a CURRENT. Will the CURRENT honor whatever is already loaded or reload the queries with the last entries found?
Mind that some symptoms of this issue were seen in #10000 and fixed properly. However, this issue has the potential to generate logical mismatches which may be hard to understand with the debugger.
#2 Updated by Stefanel Pezamosca about 1 year ago
- Status changed from New to WIP
#3 Updated by Stefanel Pezamosca about 1 year ago
Alexandru Lungu wrote:
- Extra: please check in OE what happens if buffers are loaded with something else before a CURRENT. Will the CURRENT honor whatever is already loaded or reload the queries with the last entries found?
I have observed that for a scrolling query. GET-CURRENT will load previously found records by the query. For non-scrolling case the CURRENT will honor the already loaded records.
Fix GET CURRENT to work even if that component didn't find anything. It is possible to have a record loaded using loadByValues, but the results and cursor still be empty (and the query off-end). Maybe calling the CURRENT from CompoundQuery should by-pass such checks. The CURRENT solely relies on buffer contents, so it is irrelevant if the query is off-end.
Do you have an example/testcase that shows this? At the moment I don't understand how this case should look like such that GET CURRENT would not work.
#4 Updated by Alexandru Lungu about 1 year ago
Do you have an example/testcase that shows this? At the moment I don't understand how this case should look like such that GET CURRENT would not work.
I get provide some pseudo-code:
- Run a compound query with no optimized components EACH/EACH. The results found should be (1, 2), (1, 3), (2, 3) (so a x < y condition should do the trick).
- Go through all rows with next till off-end (including off-end).
- The first AQ is at record 3; the second AQ has no records
- Run
get first. This will callloadByValuesand runloadon both queries with (1) and (2).- Thus, the first AQ is re-positioned to row 1. Second AQ is not re-positioned .... its buffer is simply loaded with 2.
- Run
get current. First AQ will reload row 1. Second AQ will reload the buffer; however, a call togetRowfrom CompoundQuery will end up inAQ.getRowthat checks whether it has any results. It doesn't ... so this fails.
I fixed this in #10000 by not calling getRow for scrolling queries (that are prone to loadByValues), but rather take input from buffers directly to bypass the checking whether the query has results. It doesn't ... but it was loaded with loadByValues previously.
#6 Updated by Stefanel Pezamosca about 1 year ago
I made a testcase: See testcase
The output in OE is:(1,2) (1,3) (2,3) (?,?) (1,2) (1,2) (3,3) (3,3) ======Scrolling====== (1,2) (1,3) (2,3) (?,?) (1,2) (1,2) (3,3) Warning: A buffer in query qh_scroll contains a different record than the current query result list entry. (4108) Warning: A buffer in query qh_scroll contains a different record than the current query result list entry. (4108) (1,2)The output in FWD is this:
(1,2) (1,3) (2,3) (?,?) (1,2) (1,2) (3,3) (3,3) ======Scrolling====== (1,2) (1,3) (2,3) (?,?) (1,2) No query record is available. (4114) (1,2) (3,3) (3,3)There are clearly some differences that should be fixed.
#7 Updated by Stefanel Pezamosca 12 months ago
I made some more experiments related with Scrolling/Non-Scrolling Queries.
For this testcase: Scrolling & Non-Scrolling Query testcase
I also found some relevant tests in
xfer/testcases/abl/tests/query/adaptive/ that I could look into, as currently there are some failures. I'm currently investigating and experimenting with some changes.