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
//! When a `HAVING` with no `GROUP BY` is a group over the whole table, and when
//! it is a statement to refuse.
//!
//! Invariant: **the grammar accepts every `HAVING`, and this decides which ones
//! are legal, in SQLite's own words.** The two used to disagree: `HAVING` was
//! read only inside the `GROUP BY` arm of `parse_select_core`, so
//! `SELECT count(*) AS n FROM t HAVING n > 0` - which the reference answers
//! with the count - stopped at `near "HAVING": syntax error` (task-2040). That
//! is the worst refusal available for it. Exit code 3 and the `unsupported`
//! status exist so a caller can tell "this engine has not built that" from
//! "your SQL is wrong", and a syntax error said the second about a statement
//! that is correct, which sends the caller rewording SQL that needs no
//! rewording. Deciding it here keeps the parser's job to shape and this one to
//! meaning, and keeps the sentence in one place.
use crateParseError;
use crateSpan;
/// Refuses a `HAVING` on a statement that does not aggregate.
///
/// **What makes a statement an aggregating one, for SQLite, is an aggregate
/// among the *result columns* and nothing else.** A `GROUP BY` makes one too.
/// An aggregate that appears only in the `HAVING`, or only in the `ORDER BY`,
/// does not, which is why the count is taken before the `HAVING` is bound
/// rather than read off the binder afterwards - by then `self.aggregates` holds
/// the ones the `HAVING` itself introduced. Measured against the pinned
/// `sqlite3` 3.53.4:
///
/// ```sql
/// SELECT count(*) AS n FROM t HAVING n > 0; -- 3
/// SELECT count(*) FROM t HAVING b > 0; -- 3
/// SELECT 1 FROM t HAVING count(*) > 0; -- HAVING clause on a non-aggregate query
/// SELECT 1 FROM t HAVING 1 ORDER BY count(*); -- HAVING clause on a non-aggregate query
/// ```
///
/// The failure is `ParseErrorKind::Refused`, not `Unsupported`: the reference
/// refuses these too, so no release of this engine will ever accept them, and
/// `unsupported` would tell a caller to wait for a feature that is not coming.
/// Its span is the default one, which `statements::refused` reads as
/// positionless - the reference reports this error with no offset, so its shell
/// prints the sentence and no caret art, and a span here would make two
/// transcripts differ over two lines of drawing rather than over an answer.
///
/// @param has_having - whether the statement carries a `HAVING` at all
/// @param group_terms - how many `GROUP BY` terms it has
/// @param aggregates_in_columns - how many aggregates its result columns asked for
pub