Repository navigation
fix(query): compare two lists in dictionary order - #4956
Conversation
|
This PR has potential conflicts with the following other open pull requests which modify the same files:
|
Tracking
Standard development
CI Testing Labels
Documentation checklist
|
|
On the index side, A composite index needed the reading per property rather than on the leading one On-disk storage read only the band out of the range, so a list bound answered Two tests carry the weight.
Both sweeps agree on where that mechanism pays, and it is later than the seek That rule is not introduced here and nothing regresses by it. It governs the Two things follow for this change rather than for that rule. A list bound |
d3faed5 to
7484bab
Compare
A scan standing in for a filter can re-read an entry the band it walks cannot separate, which is how the search-term predicates already work. The predicate was kept for the leading property alone, so a bound on a trailing property was left to a filter that the index-lookup rewrite had already removed. Each indexed property now carries its own. A rejection names the property whose predicate raised it, and the scan seeks past every entry sharing the values that predicate read: those entries are held in one run whichever property it was, since the index orders on them ahead of everything beyond. A chunked scan steps instead, because a seek would pass a node another thread has marked and knows nothing of the chunk end.
Two lists are placed in the dictionary order the specification gives: elements pairwise from the start, a shorter list first where the two agree up to its end, and nothing decided where placing them reaches a null. That leaves [1] < [1, null] decided, because no element meets the null, while [1, 2] >= [1, null] is not. A band cannot separate the rows that follow from the rows a filter drops, and the filter is gone by the time the scan runs, so a list bound is read by the scan instead: every row carrying the property is handed to the same comparison the filter would have made. On-disk storage fences by a band alone, so it reads the bound over what the band gathered, which costs it a second pass.
7484bab to
2df9d08
Compare
…x predicates Rewrite the comments added by this branch to name the mechanism directly. Move AdvanceOutcome and Advance above the AdvanceUntilValid_ comment they had separated from its function. Merge case List into the true group of ValidFor, which clang-tidy flagged as a cloned branch.
…e scans A list bound reaches the scan as an IS NOT NULL range with a value predicate, and the planner has already dropped its filter. The global vertex property index read only the bounds, so a list bound returned every vertex carrying the property. The index now takes a PropertyValueRange and checks its predicate per entry, as the edge indexes do; ScanAllByVertexProperty and ScanParallelByVertexProperty pass the range when it carries a predicate. The parallel edge scans passed no range on the IS NOT NULL branch and now pass it. On-disk storage in edge import mode reads from its own cache and aborted on any range carrying a predicate, CONTAINS included. The cache now takes the whole range, and its in-memory index applies the predicate.
The specification counts a NaN incomparable, and a pair of lists that compares an incomparable element pair is itself incomparable, so all four ordered comparisons answer Null. They answered false, reading the NaN as unordered the way a scalar comparison does. A scalar NaN still compares false. Adds gql_behave scenarios for list comparison, each list-bound query run with no index, a label-property, composite, global and edge index.
The cache keeps the vertices a scan loads into it, but their deltas belong to the loading transaction, and only a transaction that commits is handed to the cache to outlive its accessor. A scan from a later transaction walks deltas the loading one has already released. Both edge import mode scans now share an accessor. The second still reads the cache rather than reloading it, so it covers the same ground.
|



Two lists are placed in the dictionary order the specification gives: elements
pairwise from the start, settling on the first that differs, and a shorter list
first where the two agree up to its end. Where placing them reaches a null
nothing is decided, so all four ordered comparisons answer Null. That leaves
[1] < [1, 0] and [1] < [1, null] both true, the second because no element ever
meets the null, while [1, 2] >= [1, null] is undecided.
No band separates the rows such a comparison keeps from the rows it drops when a
list is the bound, and the filter a scan stands in for is gone from the plan by
then, so the scan reads the bound itself over every row carrying the property.
Each indexed property carries its own reading, and a rejection passes every
entry sharing the values that reading looked at, which the index holds in one
run. On-disk storage fences by a band alone, so it reads the bound over what the
band gathered and pays for a second pass.