1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! What `PRAGMA reverse_unordered_selects` turns around.
//!
//! Invariant: **a query with no `ORDER BY` returns its rows in the reverse of
//! the order it returns them in with the pragma off, wherever SQLite would**,
//! and a query the pragma cannot reverse in SQLite is left alone.
use *;
/// Returns whether `PRAGMA reverse_unordered_selects` makes the outer scan run
/// backwards.
///
/// SQLite reverses every scan whose direction nothing asks for. This reverses
/// the outermost term of a query with no `ORDER BY`, no `GROUP BY` and no
/// `DISTINCT` (a plain aggregate such as `group_concat(a)` is included, because
/// the order the rows reach it in is visible), which is the order the rows leave in when the inner terms are
/// seeks that find one row each. A statement that sorts anyway, or whose outer
/// term is not a scan of a table or an index, is left alone.
///
/// @param select - the bound statement
/// @param sources - the planned FROM terms
/// @param levers - the optimizations that were on when the plan was chosen
pub
/// Returns whether `PRAGMA reverse_unordered_selects` turns the whole joined row
/// stream around.
///
/// SQLite runs every loop of a query with no `ORDER BY` backwards: the outer
/// scan, each inner join term, the inner side of a `LEFT JOIN`, and the values
/// of an `IN` list, which it walks from the largest. Reversing only the outer
/// scan left the rows each outer row joined to in forward order, so `SELECT *
/// FROM a, b WHERE b.aid = a.id` disagreed with SQLite on every outer row with
/// more than one match. A nested loop whose every level runs backwards
/// produces the forward rows in reverse, so the executor reverses the joined
/// rows instead.
///
/// That holds only when every term is a loop SQLite can run backwards. It
/// cannot reverse a virtual table, a subquery it reads as a co-routine, or the
/// queue of a recursive CTE, so a query with one of those keeps the outer scan
/// rule in `reverses_unordered_scan`. A `GROUP BY` or `DISTINCT` is answered
/// in key order by SQLite, so neither is reversed. Each arm of a compound is
/// planned on its own and reverses its own rows, which is what SQLite does for
/// `UNION ALL`.
///
/// @param select - the bound statement
/// @param sources - the planned FROM terms
/// @param levers - the optimizations that were on when the plan was chosen
pub