Bug #10806
Presort queries can sometimes dynamically find records created after opening the query
0%
History
#1 Updated by Alexandru Lungu 11 months ago
Part of #10737, I discovered that BY clause index overlapping resolution is influenced by WHERE clause. This happens for any kind of query.
For presort however, the regression tests shown that FWD trunk doesn't properly find new records after OPEN QUERY, which apparently is possible. The scenario is rather limited in the sense that it happens only if the BY clauses partially overlap an index, but the WHERE clause ensures that this is enough (with equality checks on leading components).
I committed testcases/1813 with tests/query/index/ByAndWherePresortTestCases.cls. Check with tests/query/index/ByAndWherePreselectTestCases.cls for non-presort cases that work fine in trunk.
#4 Updated by Artur Școlnic 5 days ago
- Assignee set to Artur Școlnic
- Status changed from New to WIP
#5 Updated by Artur Școlnic 5 days ago
- Status changed from WIP to Review
- reviewer Alexandru Lungu added
Summary¶
A presort query took a fixed, preselected snapshot of its results, so records created or changed after the query opened were never seen. This makes PresortQuery change-sensitive by inheriting AdaptiveQuery instead of PreselectQuery, so it can switch to dynamic retrieval when the session holds pending changes.
Three files, +91/-10.
The change¶
PresortQuery now extends AdaptiveQuery. Its createResults override became createHighLevelResults (see below), assembleOrderByClause was split so the body keeps its checked exception while the override matches AdaptiveQuery's signature, and executeQuery now asks for a preselected result set explicitly on the template-rowid path.
AdaptiveQuery gained one hook, createHighLevelResults, called from createResults in place of the inline super.createResults(adapter). The default implementation is exactly what it replaced, so AdaptiveFind and every other caller are unaffected; PresortQuery is the only override.
PreselectQuery gained executePreselected, split out of executeQuery, so a subclass whose parent executes lazily can still ask for a fully materialised result set. Java offers no way to reach a grandparent implementation directly.
Why the results wrapper moved¶
This is the part worth a close look. SortedResults materialises and sorts in its constructor and never re-reads its delegate. Building it per delegate change meant that once the query went dynamic, every next() rebuilt the presorted view over a cursor that had already moved, and rows were lost. Building it once per open, over the adapter rather than the delegate, is what AdaptiveQuery already does for its own results; the hook simply lets a subclass participate in that.
The wrapper is cached for the life of an open, and cleared on re-open through open() -> close() -> cleanup().
Testing¶
Patterns covered, in FWD and against an OpenEdge reference where the semantics were in question:
- an uncommitted CREATE that matches the predicate, read from another buffer
- an uncommitted UPDATE that moves a row into or out of the predicate
- a pending change to a field the query SORTS on, and to a field it BREAKS on, where the row still matches the predicate so only its position and group can be wrong
- re-opening a presort statement, which must rebuild the presorted set rather than replay the previous open
- an existing corpus of BY/WHERE index-selection queries in both presort and preselect shapes, as a regression guard
| Suite | Trunk | With change |
|---|---|---|
| Presort visibility (45 tests) | 24 pass / 21 fail | 44 pass / 1 fail |
| BY/WHERE index selection (368 tests) | 351 pass / 17 fail | 351 pass / 17 fail |
The one remaining failure in the first suite fails on trunk as well and is out of scope here. The BY/WHERE failing-method set is identical to trunk, method for method. One test was added for the re-open case and passes, bringing that suite to 46.
Alex, please review the first iteration of the implementation in 10806a.
#6 Updated by Artur Școlnic 2 days ago
- Status changed from Review to WIP
Will do a few more rounds of self review and generate more tests.
#7 Updated by Artur Școlnic about 12 hours ago
I keep finding failing testcases and fixing them, will post here when there are no issues to be solved.