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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! Which collation a comparison, a sort or a grouping uses, and where an
//! explicit `COLLATE` comes from.
//!
//! Invariant: **every collation the binder decides comes from the rules in
//! this file, and they are SQLite's `sqlite3ExprCollSeq` and
//! `sqlite3BinaryCompareCollSeq`, graded against the pinned 3.53.4 shell.**
//! The executor's `expression_collation` used to be a second copy of them
//! that looked only at the top node, and the binder's own two helpers did the
//! same, so an explicit `COLLATE` inside an operand of `||` reached neither a
//! comparison nor a `GROUP BY` (task-2089). One copy, here, is what keeps a
//! comparison, an `ORDER BY`, a `DISTINCT` and a `PARTITION BY` agreeing
//! about which values are equal. The cases that grade these rules are
//! `crates/inillucent-compat/tests/corpora/differential-part8/task2089.cases`.
use Collation;
use BoundExpr;
use crateUnaryOp;
/// Returns the collation a result column compares with.
///
/// `DISTINCT` and `GROUP BY` compare result values, and a NOCASE column makes
/// `blue` and `Blue` the same value for both. Comparing them with BINARY
/// instead returns more rows than SQLite does, which looks like a duplicate
/// rather than like a bug.
/// Wraps an expression in the collation an explicit `COLLATE` names.
///
/// **A `COLLATE` above a comparison does not reach the comparison (task-1979,
/// F5).** `a = b COLLATE NOCASE` parses as `a = (b COLLATE NOCASE)`, because
/// `COLLATE` binds tighter than `=`, and the comparison then reads NOCASE off
/// its own right operand through [`comparison_rules`]. `(a = b) COLLATE
/// NOCASE` is the other tree: the comparison is finished and NOCASE applies to
/// the integer it produced, where a text collation does nothing. This function
/// used to stamp the collation onto a `BoundExpr::Compare` it was handed, which
/// made the two trees answer the same and made the outer name win over the
/// inner one: measured against 3.53.4, `SELECT ('B'<'a') COLLATE NOCASE`
/// answered 0 where SQLite answers 1, and
/// `SELECT ('a' = 'A' COLLATE NOCASE) COLLATE BINARY` answered 0 where SQLite
/// answers 1 because the inner NOCASE is the comparison's and the outer BINARY
/// is the result's.
///
/// The wrapper is what carries the collation onward: [`comparison_rules`] asks
/// an operand for its [`BoundExpr::explicit_collation`], so a `COLLATE` on a
/// literal still reaches the comparison that uses it.
///
/// @param expr - the operand the `COLLATE` was written on
/// @param collation - the collation it names
pub