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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//! The four assertions the MySQL grammar walk uses, and why there are four.
//!
//! [`check`] is [`assert_sql`] and is what every case should use: it runs the
//! `sqlparser` grammar tier, a real MySQL 8.4 when one is compiled in
//! (`--features live-docker`), and the whitespace-normalised comparison against the
//! string written in the test.
//!
//! The other three exist because **for MySQL the two tiers disagree, in both
//! directions**, and neither disagreement should be settled by weakening the SQL.
//!
//! * [`check_without_grammar`] drops the grammar tier for a construct `sqlparser`
//! rejects and the manual and the server both accept. `sqlparser` is a generic
//! parser wearing a MySQL hat, not MySQL's grammar; each call names the construct
//! so the list of false negatives is readable from the tests. It *asserts* the
//! disagreement is still real, so a stricter parser turns these back into
//! ordinary cases rather than leaving a silent hole.
//! * [`check_without_engine`] drops the engine tier for SQL that is syntactically
//! right and semantically impossible against the shared schema — in practice only
//! `PARTITION`, because MySQL cannot partition a table that participates in a
//! foreign key and every table in `tests/schema/mysql.sql` does.
//! * [`check_shape_only`] is the unhappy intersection: a construct `sqlparser`
//! rejects *and* the shared schema cannot satisfy, so only the string comparison
//! is left. Three cases need it, all of them `PARTITION` in a statement whose
//! `PARTITION` `sqlparser` also cannot parse. Their expected strings come from the
//! manual alone, and each one names the two reasons.
//!
//! All of them still assert the intended string, which is the part that says "this
//! is the SQL we meant" and the part no parser can answer.
//!
//! **A run with no judge announces itself.** On a plain `cargo test` there is no
//! engine, so a [`check_without_grammar`] case has nothing vouching for its SQL at
//! all, and a [`check_shape_only`] case never does on any build. Both write a
//! `SKIPPED (no judge)` line to stderr — past libtest's capture, so it is visible
//! without `--nocapture` — naming the case's file and line, instead of passing as
//! silently as a fully judged one. [`check_without_engine`] stays quiet: its
//! grammar tier does run.
//!
//! **Where the expected strings come from.** Each is derived from the statement's
//! production in the MySQL 8.4 reference manual — cited in the test where the shape
//! is not obvious — or from bob's rendering of the same construct where bob has one,
//! plus the rendering rules `keelson_core::clause` documents: a clause writes its own
//! keyword, an absent clause writes nothing at all, and every operator from the chain
//! parenthesises its own result exactly once. None was produced by running the
//! builder and pasting the output.
//!
//! **Every table and column named is in `tests/schema/mysql.sql`.** That is what lets
//! the engine tier resolve names, which is where the sharp failures are.
use ;
use ;
/// Whether this build reaches a real MySQL.
/// Announce visibly that a case ran with no judge vouching for its SQL.
///
/// The weakened assertions below drop the `sqlparser` tier on purpose, which
/// leaves the engine as the only judge — and on a plain `cargo test` there is no
/// engine. `eprintln!` is captured and discarded for a passing test, so a message
/// through it is silence in exactly the situation this exists for; writing to the
/// stderr handle directly bypasses libtest's capture. `#[track_caller]` all the
/// way down makes the message name the test's own file and line.
/// Build, then run every check this build can: grammar, engine, and intent.
pub
/// [`check`] without the grammar tier, for a construct `sqlparser` gets wrong.
///
/// `construct` names what it cannot parse; it appears in the panic message so a
/// failure here is never mistaken for the skipped check.
pub
/// [`check`] without the engine tier, for SQL the shared schema cannot satisfy.
///
/// `reason` says why the server cannot be asked.
pub
/// The string comparison alone, for the cases where neither judge can be asked.
///
/// `construct` names what `sqlparser` cannot parse and `reason` why the server
/// cannot be asked either. The grammar half of the disagreement is still asserted,
/// so this weakens to [`check_without_engine`] the moment `sqlparser` improves.
///
/// **This is the weakest assertion in the file.** Use it only when the alternative
/// is not testing the construct at all, and derive `expected` from the manual.
pub