Skip to main content

inillucent_sql/
ast.rs

1//! The arena-backed abstract syntax tree.
2//!
3//! Invariant: a node is an index into an arena, never a box, so an adversarial
4//! nesting depth costs one vector push per node and a walker can be iterative.
5//! Every node carries the span it was parsed from, and no node has been
6//! normalised: `NOT IN`, `IS NOT DISTINCT FROM` and an implicit alias are all
7//! distinct nodes rather than reconstructions, because a diagnostic that has to
8//! guess what the user wrote points at the wrong place.
9//!
10//! Identifiers are interned once per parse. The interned form keeps the
11//! original spelling *and* an ASCII-folded lookup key, because SQL name
12//! resolution is case-insensitive while `sqlite_schema` records the spelling
13//! the user chose.
14
15use crate::lexer::{QuoteForm, Span};
16
17/// An identifier, interned per parse.
18#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct NameId(pub u32);
20
21/// An expression node.
22#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
23pub struct ExprId(pub u32);
24
25/// A compound SELECT.
26#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
27pub struct SelectId(pub u32);
28
29/// One arm of a compound SELECT.
30#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
31pub struct SelectCoreId(pub u32);
32
33/// A FROM term.
34#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
35pub struct FromTermId(pub u32);
36
37/// A window definition.
38#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
39pub struct WindowId(pub u32);
40
41/// An interned identifier: what was written and what it matches.
42#[derive(Clone, Debug, PartialEq, Eq)]
43pub struct Name {
44    /// The identifier exactly as written, with quoting removed.
45    pub text: Vec<u8>,
46    /// The ASCII-folded key names are compared by.
47    pub folded: Vec<u8>,
48    /// How it was quoted, which decides whether it may become a string.
49    pub quote: QuoteForm,
50    /// Where it came from.
51    pub span: Span,
52}
53
54impl Name {
55    /// Returns the written spelling as text, for diagnostics and schema SQL.
56    pub fn as_str(&self) -> &str {
57        core::str::from_utf8(&self.text).unwrap_or("")
58    }
59}
60
61/// A literal value, kept as the bytes it was written as.
62#[derive(Clone, Debug, PartialEq, Eq)]
63pub enum Literal {
64    /// `NULL`.
65    Null,
66    /// `TRUE` or `FALSE`, which SQLite treats as 1 and 0.
67    Boolean(bool),
68    /// An integer literal, as written.
69    Integer(Vec<u8>),
70    /// A floating-point literal, as written.
71    Float(Vec<u8>),
72    /// A string literal, unescaped.
73    String(Vec<u8>),
74    /// A blob literal, decoded.
75    Blob(Vec<u8>),
76    /// `CURRENT_DATE`, `CURRENT_TIME` or `CURRENT_TIMESTAMP`.
77    CurrentDate,
78    /// `CURRENT_TIME`.
79    CurrentTime,
80    /// `CURRENT_TIMESTAMP`.
81    CurrentTimestamp,
82}
83
84/// A unary operator.
85#[derive(Clone, Copy, Debug, PartialEq, Eq)]
86pub enum UnaryOp {
87    /// `-x`
88    Negate,
89    /// `+x`, which SQLite keeps as a no-op that still forces evaluation.
90    Identity,
91    /// `~x`
92    BitNot,
93    /// `NOT x`
94    Not,
95}
96
97/// A binary operator.
98#[derive(Clone, Copy, Debug, PartialEq, Eq)]
99pub enum BinaryOp {
100    /// `OR`
101    Or,
102    /// `AND`
103    And,
104    /// `=`
105    Equal,
106    /// `<>`
107    NotEqual,
108    /// `<`
109    Less,
110    /// `<=`
111    LessEqual,
112    /// `>`
113    Greater,
114    /// `>=`
115    GreaterEqual,
116    /// `+`
117    Add,
118    /// `-`
119    Subtract,
120    /// `*`
121    Multiply,
122    /// `/`
123    Divide,
124    /// `%`
125    Modulo,
126    /// `||`
127    Concat,
128    /// `&`
129    BitAnd,
130    /// `|`
131    BitOr,
132    /// `<<`
133    ShiftLeft,
134    /// `>>`
135    ShiftRight,
136    /// `->`
137    Extract,
138    /// `->>`
139    ExtractText,
140    /// `MATCH`
141    Match,
142    /// `REGEXP`
143    Regexp,
144    /// `<->`
145    L2Distance,
146    /// `<=>`
147    CosineDistance,
148    /// `<#>`
149    NegativeInnerProduct,
150    /// `<+>`
151    L1Distance,
152    /// `<~>`
153    HammingDistance,
154    /// `<%>`
155    JaccardDistance,
156}
157
158/// Which pattern operator was written.
159#[derive(Clone, Copy, Debug, PartialEq, Eq)]
160pub enum PatternOp {
161    /// `LIKE`
162    Like,
163    /// `GLOB`
164    Glob,
165    /// `REGEXP`
166    Regexp,
167    /// `MATCH`
168    Match,
169}
170
171/// The right-hand side of `IN`.
172#[derive(Clone, Debug, PartialEq, Eq)]
173pub enum InRhs {
174    /// `IN (1, 2, 3)`, including the empty list.
175    List(Vec<ExprId>),
176    /// `IN (SELECT ...)`.
177    Select(SelectId),
178    /// `IN table` or `IN schema.table`.
179    Table {
180        /// The schema qualifier, when written.
181        database: Option<NameId>,
182        /// The table or table-valued function name.
183        table: NameId,
184        /// Arguments, when the name is a table-valued function.
185        arguments: Option<Vec<ExprId>>,
186    },
187}
188
189/// A `RAISE()` action inside a trigger body.
190#[derive(Clone, Copy, Debug, PartialEq, Eq)]
191pub enum RaiseAction {
192    /// `RAISE(IGNORE)`
193    Ignore,
194    /// `RAISE(ROLLBACK, msg)`
195    Rollback,
196    /// `RAISE(ABORT, msg)`
197    Abort,
198    /// `RAISE(FAIL, msg)`
199    Fail,
200}
201
202/// An expression, in the shape it was written.
203#[derive(Clone, Debug, PartialEq, Eq)]
204pub enum Expr {
205    /// A literal.
206    Literal(Literal),
207    /// A bound parameter.
208    Parameter {
209        /// The one-based parameter index assigned at parse time.
210        index: u32,
211        /// The written name, for `:name` style parameters.
212        name: Option<NameId>,
213    },
214    /// A column reference, with as much qualification as was written.
215    Column {
216        /// The schema qualifier.
217        database: Option<NameId>,
218        /// The table qualifier or alias.
219        table: Option<NameId>,
220        /// The column name.
221        column: NameId,
222    },
223    /// `*` or `table.*`, legal only where the grammar allows it.
224    Star {
225        /// The table qualifier, when written.
226        table: Option<NameId>,
227    },
228    /// A unary operator applied to one operand.
229    Unary {
230        /// Which operator.
231        op: UnaryOp,
232        /// The operand.
233        operand: ExprId,
234    },
235    /// A binary operator applied to two operands.
236    Binary {
237        /// Which operator.
238        op: BinaryOp,
239        /// The left operand.
240        left: ExprId,
241        /// The right operand.
242        right: ExprId,
243    },
244    /// `expr COLLATE name`.
245    Collate {
246        /// The operand.
247        operand: ExprId,
248        /// The collation name.
249        collation: NameId,
250    },
251    /// `CAST(expr AS type)`.
252    Cast {
253        /// The operand.
254        operand: ExprId,
255        /// The declared type, as written.
256        declared: NameId,
257    },
258    /// `expr [NOT] LIKE|GLOB|REGEXP|MATCH pattern [ESCAPE expr]`.
259    Pattern {
260        /// Whether `NOT` was written.
261        negated: bool,
262        /// Which operator.
263        op: PatternOp,
264        /// The value being matched.
265        operand: ExprId,
266        /// The pattern.
267        pattern: ExprId,
268        /// The `ESCAPE` argument, when written.
269        escape: Option<ExprId>,
270    },
271    /// `expr [NOT] BETWEEN low AND high`.
272    Between {
273        /// Whether `NOT` was written.
274        negated: bool,
275        /// The value being tested.
276        operand: ExprId,
277        /// The lower bound.
278        low: ExprId,
279        /// The upper bound.
280        high: ExprId,
281    },
282    /// `expr [NOT] IN rhs`.
283    In {
284        /// Whether `NOT` was written.
285        negated: bool,
286        /// The value being tested.
287        operand: ExprId,
288        /// What it is tested against.
289        rhs: InRhs,
290    },
291    /// `expr ISNULL` / `expr NOTNULL` / `expr IS [NOT] NULL`.
292    IsNull {
293        /// Whether the test is for not-null.
294        negated: bool,
295        /// The operand.
296        operand: ExprId,
297    },
298    /// `left IS [NOT] [DISTINCT FROM] right`.
299    Is {
300        /// Whether `NOT` was written.
301        negated: bool,
302        /// Whether the `DISTINCT FROM` spelling was used.
303        distinct_from: bool,
304        /// The left operand.
305        left: ExprId,
306        /// The right operand.
307        right: ExprId,
308    },
309    /// `CASE [operand] WHEN ... THEN ... [ELSE ...] END`.
310    Case {
311        /// The base operand, when the form has one.
312        operand: Option<ExprId>,
313        /// The `WHEN`/`THEN` pairs, in written order.
314        branches: Vec<(ExprId, ExprId)>,
315        /// The `ELSE` arm.
316        otherwise: Option<ExprId>,
317    },
318    /// A function call, aggregate or scalar or window.
319    Function {
320        /// The function name.
321        name: NameId,
322        /// Whether `DISTINCT` was written.
323        distinct: bool,
324        /// The arguments, or `None` for `count(*)`.
325        arguments: Option<Vec<ExprId>>,
326        /// An `ORDER BY` inside the argument list.
327        order_by: Vec<OrderTerm>,
328        /// A `FILTER (WHERE ...)` clause.
329        filter: Option<ExprId>,
330        /// An `OVER` clause.
331        over: Option<WindowId>,
332    },
333    /// `[NOT] EXISTS (SELECT ...)`.
334    Exists {
335        /// Whether `NOT` was written.
336        negated: bool,
337        /// The subquery.
338        select: SelectId,
339    },
340    /// A scalar subquery.
341    Subquery(SelectId),
342    /// A parenthesised list of two or more expressions.
343    RowValue(Vec<ExprId>),
344    /// `RAISE(...)`, legal only inside a trigger body.
345    Raise {
346        /// Which action.
347        action: RaiseAction,
348        /// The message, when the action takes one.
349        message: Option<Vec<u8>>,
350    },
351}
352
353/// Ascending or descending.
354#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
355pub enum SortOrder {
356    /// `ASC`, the default.
357    #[default]
358    Ascending,
359    /// `DESC`.
360    Descending,
361}
362
363/// Where NULLs sort, when written explicitly.
364#[derive(Clone, Copy, Debug, PartialEq, Eq)]
365pub enum NullOrder {
366    /// `NULLS FIRST`.
367    First,
368    /// `NULLS LAST`.
369    Last,
370}
371
372/// One term of an `ORDER BY`.
373#[derive(Clone, Copy, Debug, PartialEq, Eq)]
374pub struct OrderTerm {
375    /// The expression, which may be an ordinal or an alias.
376    pub expr: ExprId,
377    /// The written or defaulted direction.
378    pub order: SortOrder,
379    /// The written null ordering, when there was one.
380    pub nulls: Option<NullOrder>,
381}
382
383/// One result column of a SELECT.
384#[derive(Clone, Debug, PartialEq, Eq)]
385pub struct ResultColumn {
386    /// The expression, which may be `*` or `table.*`.
387    pub expr: ExprId,
388    /// The alias, when one was written.
389    pub alias: Option<NameId>,
390    /// Whether the alias was written with `AS`.
391    pub alias_was_explicit: bool,
392    /// The span of the whole result column.
393    pub span: Span,
394}
395
396/// Which join was written.
397#[derive(Clone, Copy, Debug, PartialEq, Eq)]
398pub enum JoinKind {
399    /// A comma, which is a cross join that may still be reordered.
400    Comma,
401    /// `[INNER] JOIN`.
402    Inner,
403    /// `CROSS JOIN`, which SQLite refuses to reorder.
404    Cross,
405    /// `LEFT [OUTER] JOIN`.
406    Left,
407    /// `RIGHT [OUTER] JOIN`.
408    Right,
409    /// `FULL [OUTER] JOIN`.
410    Full,
411}
412
413/// The `ON` or `USING` constraint of a join.
414#[derive(Clone, Debug, PartialEq, Eq)]
415pub enum JoinConstraint {
416    /// No constraint was written.
417    None,
418    /// `ON expr`.
419    On(ExprId),
420    /// `USING (a, b)`.
421    Using(Vec<NameId>),
422}
423
424/// How a FROM term names its rows.
425#[derive(Clone, Debug, PartialEq, Eq)]
426pub enum FromSource {
427    /// A table, view or table-valued function.
428    Table {
429        /// The schema qualifier.
430        database: Option<NameId>,
431        /// The object name.
432        name: NameId,
433        /// Arguments, when it is a table-valued function.
434        arguments: Option<Vec<ExprId>>,
435        /// `INDEXED BY name`, or `NOT INDEXED`.
436        indexed_by: IndexHint,
437    },
438    /// A subquery.
439    Subquery(SelectId),
440    /// A parenthesised join, which is one term to whatever contains it.
441    Join(Vec<FromTermId>),
442}
443
444/// An `INDEXED BY` hint.
445#[derive(Clone, Copy, Debug, PartialEq, Eq)]
446pub enum IndexHint {
447    /// Nothing was written.
448    None,
449    /// `NOT INDEXED`.
450    NotIndexed,
451    /// `INDEXED BY name`.
452    IndexedBy(NameId),
453}
454
455/// One term of a FROM clause, with the join that attached it.
456#[derive(Clone, Debug, PartialEq, Eq)]
457pub struct FromTerm {
458    /// Where the rows come from.
459    pub source: FromSource,
460    /// The alias, when one was written.
461    pub alias: Option<NameId>,
462    /// The join that attaches this term to the one before it.
463    pub join: JoinKind,
464    /// Whether `NATURAL` was written.
465    pub natural: bool,
466    /// The `ON` or `USING` constraint.
467    pub constraint: JoinConstraint,
468    /// The span of the whole term.
469    pub span: Span,
470}
471
472/// A window frame's unit.
473#[derive(Clone, Copy, Debug, PartialEq, Eq)]
474pub enum FrameUnit {
475    /// `ROWS`.
476    Rows,
477    /// `RANGE`.
478    Range,
479    /// `GROUPS`.
480    Groups,
481}
482
483/// One end of a window frame.
484#[derive(Clone, Copy, Debug, PartialEq, Eq)]
485pub enum FrameBound {
486    /// `UNBOUNDED PRECEDING`.
487    UnboundedPreceding,
488    /// `expr PRECEDING`.
489    Preceding(ExprId),
490    /// `CURRENT ROW`.
491    CurrentRow,
492    /// `expr FOLLOWING`.
493    Following(ExprId),
494    /// `UNBOUNDED FOLLOWING`.
495    UnboundedFollowing,
496}
497
498/// A frame's `EXCLUDE` clause.
499#[derive(Clone, Copy, Debug, PartialEq, Eq)]
500pub enum FrameExclude {
501    /// `EXCLUDE NO OTHERS`, the default.
502    NoOthers,
503    /// `EXCLUDE CURRENT ROW`.
504    CurrentRow,
505    /// `EXCLUDE GROUP`.
506    Group,
507    /// `EXCLUDE TIES`.
508    Ties,
509}
510
511/// A window definition, named or inline.
512#[derive(Clone, Debug, PartialEq, Eq)]
513pub struct Window {
514    /// The window this one inherits from, when written.
515    pub base: Option<NameId>,
516    /// `PARTITION BY`.
517    pub partition_by: Vec<ExprId>,
518    /// `ORDER BY`.
519    pub order_by: Vec<OrderTerm>,
520    /// The frame unit, when a frame was written.
521    pub unit: Option<FrameUnit>,
522    /// The frame start.
523    pub start: Option<FrameBound>,
524    /// The frame end.
525    pub end: Option<FrameBound>,
526    /// The `EXCLUDE` clause.
527    pub exclude: FrameExclude,
528    /// The span of the definition.
529    pub span: Span,
530}
531
532/// The rows of one arm of a compound SELECT.
533#[derive(Clone, Debug, PartialEq, Eq)]
534pub enum SelectBody {
535    /// `SELECT ...`.
536    Select {
537        /// Whether `DISTINCT` was written.
538        distinct: bool,
539        /// Whether `ALL` was written.
540        all: bool,
541        /// The result columns.
542        columns: Vec<ResultColumn>,
543        /// The FROM terms, in written order.
544        from: Vec<FromTermId>,
545        /// The WHERE clause.
546        filter: Option<ExprId>,
547        /// The GROUP BY terms.
548        group_by: Vec<ExprId>,
549        /// The HAVING clause.
550        having: Option<ExprId>,
551        /// Named windows.
552        windows: Vec<(NameId, WindowId)>,
553    },
554    /// `VALUES (...), (...)`.
555    Values(Vec<Vec<ExprId>>),
556}
557
558/// One arm of a compound SELECT.
559#[derive(Clone, Debug, PartialEq, Eq)]
560pub struct SelectCore {
561    /// What the arm produces.
562    pub body: SelectBody,
563    /// The span of the arm.
564    pub span: Span,
565}
566
567/// A compound operator.
568#[derive(Clone, Copy, Debug, PartialEq, Eq)]
569pub enum CompoundOp {
570    /// `UNION`.
571    Union,
572    /// `UNION ALL`.
573    UnionAll,
574    /// `INTERSECT`.
575    Intersect,
576    /// `EXCEPT`.
577    Except,
578}
579
580/// A common table expression.
581#[derive(Clone, Debug, PartialEq, Eq)]
582pub struct CommonTableExpr {
583    /// The name it is bound to.
584    pub name: NameId,
585    /// The explicit column list, when written.
586    pub columns: Vec<NameId>,
587    /// `MATERIALIZED` or `NOT MATERIALIZED`, when written.
588    pub materialized: Option<bool>,
589    /// The query.
590    pub select: SelectId,
591}
592
593/// A `WITH` prefix.
594#[derive(Clone, Debug, PartialEq, Eq, Default)]
595pub struct With {
596    /// Whether `RECURSIVE` was written.
597    pub recursive: bool,
598    /// The CTEs, in written order.
599    pub ctes: Vec<CommonTableExpr>,
600}
601
602/// A complete SELECT: a `WITH` prefix, compound arms, and the tail clauses.
603#[derive(Clone, Debug, PartialEq, Eq)]
604pub struct Select {
605    /// The `WITH` prefix.
606    pub with: With,
607    /// The first arm.
608    pub first: SelectCoreId,
609    /// Later arms, each with the operator that joined it.
610    pub compounds: Vec<(CompoundOp, SelectCoreId)>,
611    /// The `ORDER BY`, which belongs to the whole compound.
612    pub order_by: Vec<OrderTerm>,
613    /// The `LIMIT` expression.
614    pub limit: Option<ExprId>,
615    /// The `OFFSET` expression.
616    pub offset: Option<ExprId>,
617    /// The span of the whole statement.
618    pub span: Span,
619}
620
621/// A conflict-resolution algorithm.
622#[derive(Clone, Copy, Debug, PartialEq, Eq)]
623pub enum ConflictAction {
624    /// `ROLLBACK`.
625    Rollback,
626    /// `ABORT`, the default.
627    Abort,
628    /// `FAIL`.
629    Fail,
630    /// `IGNORE`.
631    Ignore,
632    /// `REPLACE`.
633    Replace,
634}
635
636/// A column constraint, in written order.
637#[derive(Clone, Debug, PartialEq, Eq)]
638pub enum ColumnConstraint {
639    /// `PRIMARY KEY [ASC|DESC] [conflict] [AUTOINCREMENT]`.
640    PrimaryKey {
641        /// The written direction.
642        order: SortOrder,
643        /// The conflict clause.
644        on_conflict: Option<ConflictAction>,
645        /// Whether `AUTOINCREMENT` was written.
646        autoincrement: bool,
647    },
648    /// `NOT NULL [conflict]`.
649    NotNull(Option<ConflictAction>),
650    /// `NULL`, which SQLite accepts and ignores.
651    Null,
652    /// `UNIQUE [conflict]`.
653    Unique(Option<ConflictAction>),
654    /// `CHECK (expr)`.
655    ///
656    /// **No conflict clause**, which is SQLite's grammar and not an omission:
657    /// `ccons ::= CHECK LP expr RP` has no `onconf`, so
658    /// `b INTEGER CHECK(b < 9) ON CONFLICT IGNORE` is a syntax error there and
659    /// has to be one here. Only a *table*-level `CHECK` takes the clause - see
660    /// [`TableConstraint::Check`].
661    Check(ExprId),
662    /// `DEFAULT expr`.
663    Default(ExprId),
664    /// `COLLATE name`.
665    Collate(NameId),
666    /// `REFERENCES ...`.
667    References(ForeignKeyClause),
668    /// `GENERATED ALWAYS AS (expr) [STORED|VIRTUAL]`.
669    Generated {
670        /// The generating expression.
671        expr: ExprId,
672        /// Whether `STORED` was written.
673        stored: bool,
674    },
675}
676
677/// A foreign-key clause, on a column or on a table.
678#[derive(Clone, Debug, PartialEq, Eq)]
679pub struct ForeignKeyClause {
680    /// The parent table.
681    pub table: NameId,
682    /// The parent columns, when written.
683    pub columns: Vec<NameId>,
684    /// The `ON DELETE`/`ON UPDATE`/`MATCH` clauses, as written.
685    pub actions: Vec<ForeignKeyAction>,
686    /// Whether the constraint is deferrable.
687    pub deferrable: Option<bool>,
688    /// Whether it is initially deferred.
689    pub initially_deferred: bool,
690}
691
692/// One `ON DELETE`, `ON UPDATE` or `MATCH` clause.
693#[derive(Clone, Copy, Debug, PartialEq, Eq)]
694pub enum ForeignKeyAction {
695    /// `ON DELETE <action>`.
696    OnDelete(ReferentialAction),
697    /// `ON UPDATE <action>`.
698    OnUpdate(ReferentialAction),
699    /// `MATCH name`.
700    Match(NameId),
701}
702
703/// What a referential action does.
704#[derive(Clone, Copy, Debug, PartialEq, Eq)]
705pub enum ReferentialAction {
706    /// `SET NULL`.
707    SetNull,
708    /// `SET DEFAULT`.
709    SetDefault,
710    /// `CASCADE`.
711    Cascade,
712    /// `RESTRICT`.
713    Restrict,
714    /// `NO ACTION`.
715    NoAction,
716}
717
718/// One column of a `CREATE TABLE`.
719#[derive(Clone, Debug, PartialEq, Eq)]
720pub struct ColumnDef {
721    /// The column name.
722    pub name: NameId,
723    /// The declared type, exactly as written, when there was one.
724    pub declared_type: Option<Vec<u8>>,
725    /// The constraints, in written order, each with its optional name.
726    pub constraints: Vec<(Option<NameId>, ColumnConstraint)>,
727    /// The span of the definition.
728    pub span: Span,
729}
730
731/// One indexed column of a table constraint or an index.
732#[derive(Clone, Copy, Debug, PartialEq, Eq)]
733pub struct IndexedColumn {
734    /// The key expression, which may be a bare column.
735    pub expr: ExprId,
736    /// An explicit collation.
737    pub collation: Option<NameId>,
738    /// The direction.
739    pub order: SortOrder,
740}
741
742/// A table-level constraint.
743#[derive(Clone, Debug, PartialEq, Eq)]
744pub enum TableConstraint {
745    /// `PRIMARY KEY (...)`.
746    PrimaryKey {
747        /// The key columns.
748        columns: Vec<IndexedColumn>,
749        /// The conflict clause.
750        on_conflict: Option<ConflictAction>,
751        /// Whether `AUTOINCREMENT` was written.
752        autoincrement: bool,
753    },
754    /// `UNIQUE (...)`.
755    Unique {
756        /// The key columns.
757        columns: Vec<IndexedColumn>,
758        /// The conflict clause.
759        on_conflict: Option<ConflictAction>,
760    },
761    /// `CHECK (expr) [conflict]`.
762    ///
763    /// **Parsed and then ignored, which is what SQLite does with it.**
764    /// `tcons ::= CHECK LP expr RP onconf` accepts the clause and
765    /// `sqlite3AddCheckConstraint` never reads it, so
766    /// `CONSTRAINT small CHECK(b < 9) ON CONFLICT FAIL` behaves exactly as
767    /// `ABORT`: measured against the pinned 3.53.4, an `INSERT` of three rows
768    /// whose second fails keeps none of them.
769    ///
770    /// It is in the tree rather than discarded at the token because the table's
771    /// `CREATE` text is stored and re-parsed on every open, so the grammar has
772    /// to accept everything the text can hold. Not accepting it did not cost
773    /// one statement a clause - it made the `CREATE TABLE` a parse error, and
774    /// every statement after it said `no such table`.
775    Check {
776        /// The predicate.
777        expr: ExprId,
778        /// The conflict clause, accepted and not acted on.
779        on_conflict: Option<ConflictAction>,
780    },
781    /// `FOREIGN KEY (...) REFERENCES ...`.
782    ForeignKey {
783        /// The child columns.
784        columns: Vec<NameId>,
785        /// The parent reference.
786        clause: ForeignKeyClause,
787    },
788}
789
790/// The body of a `CREATE TABLE`.
791#[derive(Clone, Debug, PartialEq, Eq)]
792pub enum CreateTableBody {
793    /// A column list.
794    Columns {
795        /// The columns, in written order.
796        columns: Vec<ColumnDef>,
797        /// The table constraints, in written order, each with its name.
798        constraints: Vec<(Option<NameId>, TableConstraint)>,
799        /// Whether `WITHOUT ROWID` was written.
800        without_rowid: bool,
801        /// Whether `STRICT` was written.
802        strict: bool,
803    },
804    /// `CREATE TABLE ... AS SELECT ...`.
805    AsSelect(SelectId),
806}
807
808/// An `UPSERT` clause.
809#[derive(Clone, Debug, PartialEq, Eq)]
810pub struct Upsert {
811    /// The conflict target columns, when written.
812    pub target: Vec<IndexedColumn>,
813    /// The conflict target's `WHERE`.
814    pub target_filter: Option<ExprId>,
815    /// The `DO UPDATE SET` assignments, empty for `DO NOTHING`.
816    pub assignments: Vec<(Vec<NameId>, ExprId)>,
817    /// Whether the action is `DO UPDATE`.
818    pub do_update: bool,
819    /// The `DO UPDATE`'s `WHERE`.
820    pub filter: Option<ExprId>,
821}
822
823/// What an INSERT inserts.
824#[derive(Clone, Debug, PartialEq, Eq)]
825pub enum InsertSource {
826    /// `VALUES`, or any SELECT.
827    Select(SelectId),
828    /// `DEFAULT VALUES`.
829    DefaultValues,
830}
831
832/// An `INSERT` statement.
833#[derive(Clone, Debug, PartialEq, Eq)]
834pub struct Insert {
835    /// The `WITH` prefix.
836    pub with: With,
837    /// The conflict algorithm from `INSERT OR ...` or `REPLACE`.
838    pub on_conflict: Option<ConflictAction>,
839    /// The schema qualifier.
840    pub database: Option<NameId>,
841    /// The target table.
842    pub table: NameId,
843    /// The table alias.
844    pub alias: Option<NameId>,
845    /// The column list, when written.
846    pub columns: Vec<NameId>,
847    /// The rows.
848    pub source: InsertSource,
849    /// The `ON CONFLICT` clauses, in written order.
850    pub upserts: Vec<Upsert>,
851    /// The `RETURNING` columns.
852    pub returning: Vec<ResultColumn>,
853}
854
855/// An `UPDATE` statement.
856#[derive(Clone, Debug, PartialEq, Eq)]
857pub struct Update {
858    /// The `WITH` prefix.
859    pub with: With,
860    /// The conflict algorithm from `UPDATE OR ...`.
861    pub on_conflict: Option<ConflictAction>,
862    /// The target term, which carries its own alias and index hint.
863    pub target: FromTermId,
864    /// The `SET` assignments; a group of names is the `(a, b) = ...` form.
865    pub assignments: Vec<(Vec<NameId>, ExprId)>,
866    /// An `UPDATE ... FROM` clause.
867    pub from: Vec<FromTermId>,
868    /// The `WHERE` clause.
869    pub filter: Option<ExprId>,
870    /// The `RETURNING` columns.
871    pub returning: Vec<ResultColumn>,
872    /// The `ORDER BY`, which SQLite allows with `LIMIT`.
873    pub order_by: Vec<OrderTerm>,
874    /// The `LIMIT`.
875    pub limit: Option<ExprId>,
876    /// The `OFFSET`.
877    pub offset: Option<ExprId>,
878    /// Where the clause the reference build has no grammar for was written.
879    ///
880    /// `ORDER BY` and `LIMIT` on a `DELETE` or an `UPDATE` are a compile-time
881    /// option in SQLite, and the pinned build is not compiled with it - so the
882    /// reference answers `near "ORDER": syntax error` and points at the word.
883    /// The syntax register requires these to *parse* here, so the refusal is
884    /// the binder's; it needs the position to be able to point at the same
885    /// word, and this is where the parser leaves it.
886    pub limited_at: Option<(Limited, crate::lexer::Span)>,
887}
888
889/// Which of the two words a limited `DELETE` or `UPDATE` was written with.
890///
891/// The reference names the first one it cannot parse, so a statement carrying
892/// both reports `ORDER` and one carrying only a `LIMIT` reports `LIMIT`.
893#[derive(Clone, Copy, Debug, PartialEq, Eq)]
894pub enum Limited {
895    /// `ORDER BY`.
896    OrderBy,
897    /// `LIMIT`.
898    Limit,
899}
900
901impl Limited {
902    /// Returns the word the refusal quotes.
903    pub fn word(self) -> &'static str {
904        match self {
905            Limited::OrderBy => "ORDER",
906            Limited::Limit => "LIMIT",
907        }
908    }
909}
910
911/// A `DELETE` statement.
912#[derive(Clone, Debug, PartialEq, Eq)]
913pub struct Delete {
914    /// The `WITH` prefix.
915    pub with: With,
916    /// The target term.
917    pub target: FromTermId,
918    /// The `WHERE` clause.
919    pub filter: Option<ExprId>,
920    /// The `RETURNING` columns.
921    pub returning: Vec<ResultColumn>,
922    /// The `ORDER BY`.
923    pub order_by: Vec<OrderTerm>,
924    /// The `LIMIT`.
925    pub limit: Option<ExprId>,
926    /// The `OFFSET`.
927    pub offset: Option<ExprId>,
928    /// Where the clause the reference build has no grammar for was written.
929    ///
930    /// `ORDER BY` and `LIMIT` on a `DELETE` or an `UPDATE` are a compile-time
931    /// option in SQLite, and the pinned build is not compiled with it - so the
932    /// reference answers `near "ORDER": syntax error` and points at the word.
933    /// The syntax register requires these to *parse* here, so the refusal is
934    /// the binder's; it needs the position to be able to point at the same
935    /// word, and this is where the parser leaves it.
936    pub limited_at: Option<(Limited, crate::lexer::Span)>,
937}
938
939/// Which kind of object a `DROP` names.
940#[derive(Clone, Copy, Debug, PartialEq, Eq)]
941pub enum ObjectKind {
942    /// A table.
943    Table,
944    /// An index.
945    Index,
946    /// A view.
947    View,
948    /// A trigger.
949    Trigger,
950}
951
952/// What an `ALTER TABLE` does.
953#[derive(Clone, Debug, PartialEq, Eq)]
954pub enum AlterAction {
955    /// `RENAME TO name`.
956    RenameTo(NameId),
957    /// `RENAME [COLUMN] a TO b`.
958    RenameColumn {
959        /// The current name.
960        from: NameId,
961        /// The new name.
962        to: NameId,
963    },
964    /// `ADD [COLUMN] def`.
965    AddColumn(ColumnDef),
966    /// `DROP [COLUMN] name`.
967    DropColumn(NameId),
968}
969
970/// When a trigger fires.
971#[derive(Clone, Copy, Debug, PartialEq, Eq)]
972pub enum TriggerTime {
973    /// `BEFORE`.
974    Before,
975    /// `AFTER`.
976    After,
977    /// `INSTEAD OF`.
978    InsteadOf,
979}
980
981/// What a trigger fires on.
982#[derive(Clone, Debug, PartialEq, Eq)]
983pub enum TriggerEvent {
984    /// `DELETE`.
985    Delete,
986    /// `INSERT`.
987    Insert,
988    /// `UPDATE [OF a, b]`.
989    Update(Vec<NameId>),
990}
991
992/// A `PRAGMA` argument.
993#[derive(Clone, Debug, PartialEq, Eq)]
994pub enum PragmaValue {
995    /// Nothing was written.
996    None,
997    /// `= value` or `(value)`.
998    Value(ExprId),
999    /// `(name)`, which is a bare word rather than an expression.
1000    Name(NameId),
1001}
1002
1003/// A parsed statement.
1004#[derive(Clone, Debug, PartialEq, Eq)]
1005pub enum Statement {
1006    /// An empty statement, which SQLite compiles to nothing.
1007    Empty,
1008    /// `SELECT` or `VALUES`.
1009    Select(SelectId),
1010    /// `INSERT` or `REPLACE`.
1011    Insert(Box<Insert>),
1012    /// `UPDATE`.
1013    Update(Box<Update>),
1014    /// `DELETE`.
1015    Delete(Box<Delete>),
1016    /// `CREATE TABLE`.
1017    CreateTable {
1018        /// Whether `TEMP` was written.
1019        temporary: bool,
1020        /// Whether `IF NOT EXISTS` was written.
1021        if_not_exists: bool,
1022        /// The schema qualifier.
1023        database: Option<NameId>,
1024        /// The table name.
1025        name: NameId,
1026        /// The body.
1027        body: CreateTableBody,
1028    },
1029    /// `CREATE INDEX`.
1030    CreateIndex {
1031        /// Whether `UNIQUE` was written.
1032        unique: bool,
1033        /// Whether `IF NOT EXISTS` was written.
1034        if_not_exists: bool,
1035        /// The schema qualifier.
1036        database: Option<NameId>,
1037        /// The index name.
1038        name: NameId,
1039        /// The table it indexes.
1040        table: NameId,
1041        /// The module named by `USING`, when one was.
1042        ///
1043        /// SQLite has no `USING` on `CREATE INDEX`; PostgreSQL does, and it is
1044        /// how pgvector spells `USING hnsw`. This engine borrows the spelling
1045        /// for the same purpose: an index whose structure is not a b-tree.
1046        /// A plain `CREATE INDEX` leaves it `None` and nothing
1047        /// downstream changes.
1048        using: Option<NameId>,
1049        /// The key columns.
1050        columns: Vec<IndexedColumn>,
1051        /// The storage parameters `WITH ( ... )` named, as written.
1052        ///
1053        /// `m = 16`, `ef_construction = 64` and the rest: raw `name = value`
1054        /// slices, in the order they were written, for the structure named by
1055        /// `using` to read. Empty for a plain `CREATE INDEX`, which has no
1056        /// structure to read them.
1057        settings: Vec<Vec<u8>>,
1058        /// The partial-index predicate.
1059        filter: Option<ExprId>,
1060    },
1061    /// `CREATE VIEW`.
1062    CreateView {
1063        /// Whether `TEMP` was written.
1064        temporary: bool,
1065        /// Whether `IF NOT EXISTS` was written.
1066        if_not_exists: bool,
1067        /// The schema qualifier.
1068        database: Option<NameId>,
1069        /// The view name.
1070        name: NameId,
1071        /// The explicit column list.
1072        columns: Vec<NameId>,
1073        /// The query.
1074        select: SelectId,
1075    },
1076    /// `CREATE TRIGGER`.
1077    CreateTrigger {
1078        /// Whether `TEMP` was written.
1079        temporary: bool,
1080        /// Whether `IF NOT EXISTS` was written.
1081        if_not_exists: bool,
1082        /// The schema qualifier.
1083        database: Option<NameId>,
1084        /// The trigger name.
1085        name: NameId,
1086        /// When it fires.
1087        time: Option<TriggerTime>,
1088        /// What it fires on.
1089        event: TriggerEvent,
1090        /// The table it is attached to.
1091        table: NameId,
1092        /// Whether `FOR EACH ROW` was written.
1093        for_each_row: bool,
1094        /// The `WHEN` guard.
1095        when: Option<ExprId>,
1096        /// The body statements, in written order.
1097        body: Vec<Statement>,
1098    },
1099    /// `CREATE VIRTUAL TABLE`.
1100    CreateVirtualTable {
1101        /// Whether `IF NOT EXISTS` was written.
1102        if_not_exists: bool,
1103        /// The schema qualifier.
1104        database: Option<NameId>,
1105        /// The table name.
1106        name: NameId,
1107        /// The module name.
1108        module: NameId,
1109        /// The module arguments, as written source slices.
1110        arguments: Vec<Vec<u8>>,
1111    },
1112    /// `DROP TABLE|INDEX|VIEW|TRIGGER`.
1113    Drop {
1114        /// Which kind of object.
1115        kind: ObjectKind,
1116        /// Whether `IF EXISTS` was written.
1117        if_exists: bool,
1118        /// The schema qualifier.
1119        database: Option<NameId>,
1120        /// The object name.
1121        name: NameId,
1122    },
1123    /// `ALTER TABLE`.
1124    AlterTable {
1125        /// The schema qualifier.
1126        database: Option<NameId>,
1127        /// The table name.
1128        table: NameId,
1129        /// What to do to it.
1130        action: AlterAction,
1131    },
1132    /// `BEGIN`.
1133    Begin {
1134        /// `DEFERRED`, `IMMEDIATE` or `EXCLUSIVE`, when written.
1135        behaviour: Option<TransactionBehaviour>,
1136    },
1137    /// `COMMIT` or `END`.
1138    Commit,
1139    /// `ROLLBACK [TO savepoint]`.
1140    Rollback {
1141        /// The savepoint to roll back to.
1142        savepoint: Option<NameId>,
1143    },
1144    /// `SAVEPOINT name`.
1145    Savepoint(NameId),
1146    /// `RELEASE [SAVEPOINT] name`.
1147    Release(NameId),
1148    /// `PRAGMA`.
1149    Pragma {
1150        /// The schema qualifier.
1151        database: Option<NameId>,
1152        /// The pragma name.
1153        name: NameId,
1154        /// The argument.
1155        value: PragmaValue,
1156    },
1157    /// `ATTACH`.
1158    Attach {
1159        /// The file expression.
1160        file: ExprId,
1161        /// The schema name expression.
1162        schema: ExprId,
1163        /// The `KEY` expression.
1164        key: Option<ExprId>,
1165    },
1166    /// `DETACH`.
1167    Detach {
1168        /// The schema name expression.
1169        schema: ExprId,
1170    },
1171    /// `VACUUM`.
1172    Vacuum {
1173        /// The schema to vacuum.
1174        database: Option<NameId>,
1175        /// The `INTO` target.
1176        into: Option<ExprId>,
1177    },
1178    /// `ANALYZE`.
1179    Analyze {
1180        /// The schema qualifier.
1181        database: Option<NameId>,
1182        /// The object to analyze.
1183        name: Option<NameId>,
1184    },
1185    /// `REINDEX`.
1186    Reindex {
1187        /// The schema qualifier.
1188        database: Option<NameId>,
1189        /// The collation, table or index to reindex.
1190        name: Option<NameId>,
1191    },
1192    /// `EXPLAIN` or `EXPLAIN QUERY PLAN`.
1193    Explain {
1194        /// Whether `QUERY PLAN` was written.
1195        query_plan: bool,
1196        /// The statement being explained.
1197        inner: Box<Statement>,
1198    },
1199}
1200
1201/// The behaviour of a `BEGIN`.
1202#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1203pub enum TransactionBehaviour {
1204    /// `DEFERRED`.
1205    Deferred,
1206    /// `IMMEDIATE`.
1207    Immediate,
1208    /// `EXCLUSIVE`.
1209    Exclusive,
1210}
1211
1212/// How many name buffers [`Ast::clear`] keeps for the next parse to fill.
1213///
1214/// **Because `clear` empties `names`, which drops each `Name`'s two `Vec<u8>`
1215/// (task-2039).** The arena keeps its *vectors'* capacity across a clear and
1216/// not its *entries'*, so a connection re-compiling the same statement paid
1217/// two allocations per distinct name for ever. A statement names a handful of
1218/// things, so a short list of buffers covers the repeating case; a statement
1219/// that names hundreds gives the surplus back to the allocator rather than
1220/// holding it on a connection that will never name that many again.
1221const SPARE_NAME_BUFFERS: usize = 64;
1222
1223/// The largest name buffer [`Ast::clear`] keeps, in bytes of capacity.
1224///
1225/// A held buffer is memory the connection does not give back, so a long name -
1226/// a generated column alias, a quoted sentence - is dropped rather than kept.
1227/// With [`SPARE_NAME_BUFFERS`] this bounds what one arena holds between parses
1228/// at about 8 KiB.
1229const SPARE_NAME_CAPACITY: usize = 128;
1230
1231/// Which names share one hash of their spelling and quote form.
1232///
1233/// **A collision must not hand back the wrong `NameId`.** `NameId` equality is
1234/// read as "the same name" - the binder resolves a column reference by
1235/// comparing ids - so storing one index per hash and overwriting on collision
1236/// would silently make two different identifiers the same name. Every
1237/// candidate is compared against `Ast::names` before it is returned, and a
1238/// hash shared by two different spellings keeps both.
1239///
1240/// The single case is inline rather than a one-element `Vec` because that
1241/// `Vec` would be an allocation per distinct name, which is most of what
1242/// task-2039 removed. `Several` allocates, and needs a 64-bit collision to be
1243/// reached at all.
1244#[derive(Clone, Debug, PartialEq, Eq)]
1245enum Interned {
1246    /// The only name whose spelling and quote form hash to this value.
1247    One(u32),
1248    /// Two or more names that hashed the same, in the order they were interned.
1249    Several(Vec<u32>),
1250}
1251
1252/// The arena every node of one parse lives in.
1253#[derive(Clone, Debug, Default, Eq)]
1254pub struct Ast {
1255    names: Vec<Name>,
1256    /// Where a name already is, so `intern` is a lookup rather than a scan.
1257    ///
1258    /// **`intern` was a linear scan of every name interned so far, so N
1259    /// distinct identifiers cost N-squared comparisons (task-1932, H8).** The
1260    /// `SqlLength` default is 1 GiB, so a statement naming two hundred thousand
1261    /// distinct columns is well inside what the parser accepts and was
1262    /// quadratic to parse.
1263    ///
1264    /// **The key is a hash of the name and not the name itself (task-2039).**
1265    /// Owning `(folded, quote, text)` meant every lookup had to build an owned
1266    /// key to look up *with*, and finding the name already there still cost the
1267    /// folded copy plus two more from `key.clone()` on the way in - four
1268    /// allocations per distinct name, twelve of the ninety-three a compile of
1269    /// `SELECT a FROM t WHERE id = ?1` made. Hashing the bytes where they are
1270    /// and comparing the candidates against `names`, which already holds the
1271    /// spelling and the quote form, makes a hit free and leaves a miss paying
1272    /// only for what it stores.
1273    ///
1274    /// The hash comes from the map's own [`std::collections::hash_map::RandomState`],
1275    /// which is seeded per arena. That matters rather than being tidy: the
1276    /// parser accepts `Limit::Column * 64` distinct identifiers - 128,000 under
1277    /// the defaults - so a fixed hash an attacker could invert would let a
1278    /// statement drive every name into one `Several` and restore the quadratic
1279    /// parse this map exists to prevent.
1280    interned: std::collections::HashMap<u64, Interned>,
1281    /// Name byte buffers a previous parse used, waiting to be filled again.
1282    ///
1283    /// See [`SPARE_NAME_BUFFERS`]. Empty on a fresh arena, so the first parse
1284    /// pays what it always did and every parse after it does not.
1285    spare: Vec<Vec<u8>>,
1286    exprs: Vec<Expr>,
1287    expr_spans: Vec<Span>,
1288    /// How deep each expression's own subtree is, one entry per node.
1289    ///
1290    /// **`Limit::ExprDepth` was declared in `compat/limits.toml` and enforced
1291    /// nowhere (task-1932, H8).** The parser charges `Limit::ParserDepth` in
1292    /// `enter`/`leave`, which counts recursion, and the two are different
1293    /// measurements: a flat chain `a1 = 1 AND a2 = 2 AND ...` enters and leaves
1294    /// `parse_expr_bp` once per term, so the recursion counter never
1295    /// accumulates, while the tree grows one level per term with nothing
1296    /// counting it. SQLite refuses at depth 1000. A tree that deep is accepted
1297    /// here and then walked recursively by the binder, the planner and the
1298    /// executor, each of which overflows the stack at some depth nobody
1299    /// measured.
1300    ///
1301    /// A node's depth is one more than the deepest of its children, and a child
1302    /// is always already in the arena when its parent is added, so this is one
1303    /// pass over the child ids at `add_expr` rather than a walk.
1304    expr_depths: Vec<u32>,
1305    /// The deepest expression tree in the arena.
1306    max_expr_depth: u32,
1307    selects: Vec<Select>,
1308    cores: Vec<SelectCore>,
1309    from_terms: Vec<FromTerm>,
1310    windows: Vec<Window>,
1311    bytes: usize,
1312}
1313
1314/// Two arenas are equal when they hold the same nodes.
1315///
1316/// **Hand-written rather than derived, because `interned` and `spare` are not
1317/// content (task-2039).** `interned` is an index over `names` keyed by a hash
1318/// the arena seeds for itself, so two arenas parsed from the same text hold
1319/// the same names under different keys; `spare` is buffers the allocator has
1320/// not been given back yet, which the next parse may or may not use. Comparing
1321/// either would report two identical parses as different. The fields are
1322/// destructured by name and none is skipped with `..`, so a field added later
1323/// fails to compile here rather than being silently left out of equality.
1324impl PartialEq for Ast {
1325    /// @param other - the arena to compare against
1326    fn eq(&self, other: &Ast) -> bool {
1327        let Ast {
1328            names,
1329            interned: _,
1330            spare: _,
1331            exprs,
1332            expr_spans,
1333            expr_depths,
1334            max_expr_depth,
1335            selects,
1336            cores,
1337            from_terms,
1338            windows,
1339            bytes,
1340        } = self;
1341        *names == other.names
1342            && *exprs == other.exprs
1343            && *expr_spans == other.expr_spans
1344            && *expr_depths == other.expr_depths
1345            && *max_expr_depth == other.max_expr_depth
1346            && *selects == other.selects
1347            && *cores == other.cores
1348            && *from_terms == other.from_terms
1349            && *windows == other.windows
1350            && *bytes == other.bytes
1351    }
1352}
1353
1354impl Ast {
1355    /// Returns an empty arena.
1356    pub fn new() -> Ast {
1357        Ast::default()
1358    }
1359
1360    /// Empties the arena, keeping the memory it has already taken.
1361    ///
1362    /// **So that a second statement costs no allocations.** Every one of these
1363    /// vectors is empty at `Ast::new` and grows on its first push, so parsing
1364    /// `SELECT 1` takes half a dozen trips to the allocator - about 270 ns of a
1365    /// 1,337 ns prepare on this platform's CRT heap. A parser handed a cleared
1366    /// arena pushes into capacity that is already there.
1367    ///
1368    /// It is a `clear` rather than a `new` for exactly that reason, and the
1369    /// names are cleared with everything else: `intern` returns an existing id
1370    /// for equal text, so a name left behind from the previous statement would
1371    /// be a live id in the next one's arena.
1372    ///
1373    /// **The names keep their byte buffers even though the names go
1374    /// (task-2039).** Clearing `names` drops every `Name`, and a `Name` owns
1375    /// two `Vec<u8>` - so the vector's capacity survived a clear and the two
1376    /// allocations behind each entry in it did not, and a connection
1377    /// re-compiling one statement went back to the allocator twice per
1378    /// distinct name for ever. The buffers go on `spare` instead and `intern`
1379    /// fills them again. [`SPARE_NAME_BUFFERS`] is what bounds the list.
1380    pub fn clear(&mut self) {
1381        self.recycle_names();
1382        self.interned.clear();
1383        self.exprs.clear();
1384        self.expr_spans.clear();
1385        self.expr_depths.clear();
1386        self.max_expr_depth = 0;
1387        self.selects.clear();
1388        self.cores.clear();
1389        self.from_terms.clear();
1390        self.windows.clear();
1391        self.bytes = 0;
1392    }
1393
1394    /// Returns the number of arena bytes charged so far.
1395    ///
1396    /// This is what the `max_ast_bytes` limit is charged against. It counts the
1397    /// node structures rather than the source, because the source is borrowed.
1398    pub fn charged_bytes(&self) -> usize {
1399        self.bytes
1400    }
1401
1402    /// Interns an identifier, returning the id of an equal existing entry when
1403    /// there is one.
1404    ///
1405    /// **A map rather than a scan (task-1932, H8).** This walked every name
1406    /// interned so far and compared three fields against each, so a statement
1407    /// naming N distinct identifiers cost N-squared comparisons - and the
1408    /// `SqlLength` default is 1 GiB, which leaves room for hundreds of
1409    /// thousands of them. The key is exactly what the scan compared, so the
1410    /// answer is the same one and only the cost changed.
1411    ///
1412    /// The count is charged against `Limit::Column` for the same reason the
1413    /// depth is charged below: a bound that exists in `compat/limits.toml` and
1414    /// is enforced nowhere is not a bound. It is generous - a name is a column,
1415    /// a table, an alias, a function or a collation, so one statement
1416    /// legitimately interns more names than any one table has columns - and it
1417    /// is a ceiling on an arena that has to fit in memory rather than a
1418    /// statement about the schema.
1419    pub fn intern(&mut self, text: Vec<u8>, quote: QuoteForm, span: Span) -> NameId {
1420        let id = self.intern_bytes(&text, quote, span);
1421        Ast::keep_buffer(&mut self.spare, text);
1422        id
1423    }
1424
1425    /// Interns an identifier the caller does not own, returning the id of an
1426    /// equal existing entry when there is one.
1427    ///
1428    /// **The entry point that allocates nothing on a hit (task-2039).** The
1429    /// owned form above had to exist before the lookup could happen, so the
1430    /// parser called `identifier_text(..).into_owned()` on every identifier
1431    /// token whether or not the name was already interned - and `intern` then
1432    /// folded a copy and cloned the key, four allocations for a name the arena
1433    /// already held. This hashes the bytes where the source already has them.
1434    ///
1435    /// A miss allocates what it stores and nothing else: the spelling and the
1436    /// folded key, each taken from `spare` when a previous parse left one
1437    /// there.
1438    ///
1439    /// @param text - the identifier as written, with quoting already undone
1440    /// @param quote - how it was quoted, which decides whether it may become a
1441    ///   string
1442    /// @param span - where this occurrence came from
1443    pub fn intern_bytes(&mut self, text: &[u8], quote: QuoteForm, span: Span) -> NameId {
1444        let hash = self.hash_of(text, quote);
1445        if let Some(index) = self.find_interned(hash, text, quote) {
1446            return NameId(index);
1447        }
1448        let mut folded = Ast::take_buffer(&mut self.spare);
1449        folded.extend(text.iter().map(|byte| byte.to_ascii_lowercase()));
1450        let mut spelling = Ast::take_buffer(&mut self.spare);
1451        spelling.extend_from_slice(text);
1452        self.bytes = self.bytes.saturating_add(
1453            spelling
1454                .len()
1455                .saturating_add(folded.len())
1456                .saturating_add(32),
1457        );
1458        let index = self.names.len() as u32;
1459        self.names.push(Name {
1460            text: spelling,
1461            folded,
1462            quote,
1463            span,
1464        });
1465        self.remember_interned(hash, index);
1466        NameId(index)
1467    }
1468
1469    /// Returns the hash an identifier is filed under.
1470    ///
1471    /// The map's own hasher, so the seed belongs to this arena and no caller
1472    /// can choose names that collide. The folded key is not part of the hash:
1473    /// folding is a function of the spelling, so two identifiers written the
1474    /// same way and quoted the same way always fold the same, and no name is
1475    /// ever filed apart from itself.
1476    ///
1477    /// @param text - the identifier as written
1478    /// @param quote - how it was quoted
1479    fn hash_of(&self, text: &[u8], quote: QuoteForm) -> u64 {
1480        use std::hash::BuildHasher;
1481        self.interned.hasher().hash_one((text, quote))
1482    }
1483
1484    /// Returns the index of an interned name equal to this one, when there is
1485    /// one.
1486    ///
1487    /// Every candidate filed under the hash is compared against what `names`
1488    /// already holds, so a hash two different identifiers share returns the
1489    /// right one rather than whichever was stored last.
1490    ///
1491    /// @param hash - what [`Ast::hash_of`] returned for the identifier
1492    /// @param text - the identifier as written
1493    /// @param quote - how it was quoted
1494    fn find_interned(&self, hash: u64, text: &[u8], quote: QuoteForm) -> Option<u32> {
1495        let candidates: &[u32] = match self.interned.get(&hash)? {
1496            Interned::One(index) => core::slice::from_ref(index),
1497            Interned::Several(indexes) => indexes.as_slice(),
1498        };
1499        candidates.iter().copied().find(|index| {
1500            self.names
1501                .get(*index as usize)
1502                .is_some_and(|name| name.quote == quote && name.text == text)
1503        })
1504    }
1505
1506    /// Files a newly interned name under its hash.
1507    ///
1508    /// @param hash - what [`Ast::hash_of`] returned for the identifier
1509    /// @param index - where the name was pushed in `names`
1510    fn remember_interned(&mut self, hash: u64, index: u32) {
1511        use std::collections::hash_map::Entry;
1512        match self.interned.entry(hash) {
1513            Entry::Vacant(slot) => {
1514                slot.insert(Interned::One(index));
1515            }
1516            Entry::Occupied(mut slot) => match slot.get_mut() {
1517                Interned::Several(indexes) => indexes.push(index),
1518                Interned::One(first) => {
1519                    let first = *first;
1520                    slot.insert(Interned::Several(vec![first, index]));
1521                }
1522            },
1523        }
1524    }
1525
1526    /// Moves every name's byte buffers onto the free list and empties `names`.
1527    ///
1528    /// [`Ast::clear`] is the only caller, and its comment carries the argument.
1529    ///
1530    /// **Drained rather than taken.** `core::mem::take` on `self.names` leaves
1531    /// a `Vec` with no capacity behind, which hands the allocator back the one
1532    /// thing `clear` exists to keep - and cost a 256-byte `RawVec<Name>` regrow
1533    /// on every warm compile while this function was written that way. The
1534    /// free list and the names are separate fields, so the drain and the pushes
1535    /// borrow disjointly and neither has to be given up.
1536    fn recycle_names(&mut self) {
1537        let spare = &mut self.spare;
1538        for name in self.names.drain(..) {
1539            Ast::keep_buffer(spare, name.text);
1540            Ast::keep_buffer(spare, name.folded);
1541        }
1542    }
1543
1544    /// Keeps one byte buffer for the next parse, or gives it back.
1545    ///
1546    /// A buffer with no capacity never allocated, so keeping it would fill the
1547    /// list with entries that save nothing.
1548    ///
1549    /// @param spare - the free list to put it on
1550    /// @param buffer - the buffer nothing holds any more
1551    fn keep_buffer(spare: &mut Vec<Vec<u8>>, mut buffer: Vec<u8>) {
1552        if spare.len() >= SPARE_NAME_BUFFERS
1553            || buffer.capacity() == 0
1554            || buffer.capacity() > SPARE_NAME_CAPACITY
1555        {
1556            return;
1557        }
1558        buffer.clear();
1559        spare.push(buffer);
1560    }
1561
1562    /// Returns an empty byte buffer, reusing one a previous parse left.
1563    ///
1564    /// The buffer may be shorter than what is about to go into it, in which
1565    /// case filling it reallocates - which is the one allocation a fresh `Vec`
1566    /// would have made anyway, so a spare that is too small costs nothing over
1567    /// having no spare at all.
1568    ///
1569    /// @param spare - the free list to take from
1570    fn take_buffer(spare: &mut Vec<Vec<u8>>) -> Vec<u8> {
1571        spare.pop().unwrap_or_default()
1572    }
1573
1574    /// Returns how many distinct identifiers have been interned.
1575    pub fn name_count(&self) -> usize {
1576        self.names.len()
1577    }
1578
1579    /// Returns the depth of the deepest expression tree in the arena.
1580    ///
1581    /// What `Limit::ExprDepth` is charged against. See `expr_depths`.
1582    pub fn max_expr_depth(&self) -> u32 {
1583        self.max_expr_depth
1584    }
1585
1586    /// Returns how deep one expression's own subtree is.
1587    ///
1588    /// @param id - the node
1589    pub fn expr_depth(&self, id: ExprId) -> u32 {
1590        self.expr_depths.get(id.0 as usize).copied().unwrap_or(0)
1591    }
1592
1593    /// Returns an interned name.
1594    pub fn name(&self, id: NameId) -> Option<&Name> {
1595        self.names.get(id.0 as usize)
1596    }
1597
1598    /// Returns the folded key of an interned name, or an empty slice.
1599    pub fn folded(&self, id: NameId) -> &[u8] {
1600        self.names.get(id.0 as usize).map_or(&[], |n| &n.folded)
1601    }
1602
1603    /// Returns the written spelling of an interned name, or an empty slice.
1604    pub fn text(&self, id: NameId) -> &[u8] {
1605        self.names.get(id.0 as usize).map_or(&[], |n| &n.text)
1606    }
1607
1608    /// Adds an expression node.
1609    pub fn add_expr(&mut self, expr: Expr, span: Span) -> ExprId {
1610        self.bytes = self
1611            .bytes
1612            .saturating_add(core::mem::size_of::<Expr>().saturating_add(8));
1613        let depth = self.depth_of(&expr);
1614        self.max_expr_depth = self.max_expr_depth.max(depth);
1615        self.exprs.push(expr);
1616        self.expr_spans.push(span);
1617        self.expr_depths.push(depth);
1618        ExprId(self.exprs.len().saturating_sub(1) as u32)
1619    }
1620
1621    /// Returns how deep a node about to be added is.
1622    ///
1623    /// One more than the deepest of its children. Every child is already in the
1624    /// arena - the parser builds bottom up - so this reads their recorded
1625    /// depths rather than walking them, which is what keeps `add_expr` the
1626    /// constant-time push it was.
1627    ///
1628    /// A subquery's depth is one: the `SELECT` it names has an expression arena
1629    /// of its own and its own `max_expr_depth`, and charging the outer tree for
1630    /// the inner one would refuse a shallow expression that happens to contain
1631    /// a deep query rather than the deep query itself.
1632    ///
1633    /// @param expr - the node
1634    fn depth_of(&self, expr: &Expr) -> u32 {
1635        let deepest = |ids: &[ExprId]| -> u32 {
1636            ids.iter().map(|id| self.expr_depth(*id)).max().unwrap_or(0)
1637        };
1638        let children = match expr {
1639            Expr::Literal(_)
1640            | Expr::Parameter { .. }
1641            | Expr::Column { .. }
1642            | Expr::Star { .. }
1643            | Expr::Exists { .. }
1644            | Expr::Subquery(_)
1645            | Expr::Raise { .. } => 0,
1646            Expr::Unary { operand, .. }
1647            | Expr::Collate { operand, .. }
1648            | Expr::Cast { operand, .. }
1649            | Expr::IsNull { operand, .. } => self.expr_depth(*operand),
1650            Expr::Binary { left, right, .. } | Expr::Is { left, right, .. } => {
1651                self.expr_depth(*left).max(self.expr_depth(*right))
1652            }
1653            Expr::Pattern {
1654                operand,
1655                pattern,
1656                escape,
1657                ..
1658            } => self
1659                .expr_depth(*operand)
1660                .max(self.expr_depth(*pattern))
1661                .max(escape.map(|id| self.expr_depth(id)).unwrap_or(0)),
1662            Expr::Between {
1663                operand, low, high, ..
1664            } => self
1665                .expr_depth(*operand)
1666                .max(self.expr_depth(*low))
1667                .max(self.expr_depth(*high)),
1668            Expr::In { operand, rhs, .. } => {
1669                let right = match rhs {
1670                    InRhs::List(ids) => deepest(ids),
1671                    InRhs::Select(_) => 0,
1672                    InRhs::Table { arguments, .. } => {
1673                        arguments.as_deref().map(deepest).unwrap_or(0)
1674                    }
1675                };
1676                self.expr_depth(*operand).max(right)
1677            }
1678            Expr::Case {
1679                operand,
1680                branches,
1681                otherwise,
1682            } => {
1683                let mut deep = operand.map(|id| self.expr_depth(id)).unwrap_or(0);
1684                for (when, then) in branches {
1685                    deep = deep.max(self.expr_depth(*when)).max(self.expr_depth(*then));
1686                }
1687                deep.max(otherwise.map(|id| self.expr_depth(id)).unwrap_or(0))
1688            }
1689            Expr::Function {
1690                arguments, filter, ..
1691            } => arguments
1692                .as_deref()
1693                .map(deepest)
1694                .unwrap_or(0)
1695                .max(filter.map(|id| self.expr_depth(id)).unwrap_or(0)),
1696            Expr::RowValue(ids) => deepest(ids),
1697        };
1698        children.saturating_add(1)
1699    }
1700
1701    /// Returns an expression node.
1702    pub fn expr(&self, id: ExprId) -> Option<&Expr> {
1703        self.exprs.get(id.0 as usize)
1704    }
1705
1706    /// Returns the span an expression was parsed from.
1707    pub fn expr_span(&self, id: ExprId) -> Span {
1708        self.expr_spans
1709            .get(id.0 as usize)
1710            .copied()
1711            .unwrap_or_default()
1712    }
1713
1714    /// Returns the number of expression nodes in the arena.
1715    pub fn expr_count(&self) -> usize {
1716        self.exprs.len()
1717    }
1718
1719    /// Adds a compound SELECT.
1720    pub fn add_select(&mut self, select: Select) -> SelectId {
1721        self.bytes = self
1722            .bytes
1723            .saturating_add(core::mem::size_of::<Select>().saturating_add(32));
1724        self.selects.push(select);
1725        SelectId(self.selects.len().saturating_sub(1) as u32)
1726    }
1727
1728    /// Returns a compound SELECT.
1729    pub fn select(&self, id: SelectId) -> Option<&Select> {
1730        self.selects.get(id.0 as usize)
1731    }
1732
1733    /// Adds one arm of a compound SELECT.
1734    pub fn add_core(&mut self, core: SelectCore) -> SelectCoreId {
1735        self.bytes = self
1736            .bytes
1737            .saturating_add(core::mem::size_of::<SelectCore>().saturating_add(64));
1738        self.cores.push(core);
1739        SelectCoreId(self.cores.len().saturating_sub(1) as u32)
1740    }
1741
1742    /// Returns one arm of a compound SELECT.
1743    pub fn core(&self, id: SelectCoreId) -> Option<&SelectCore> {
1744        self.cores.get(id.0 as usize)
1745    }
1746
1747    /// Adds a FROM term.
1748    pub fn add_from_term(&mut self, term: FromTerm) -> FromTermId {
1749        self.bytes = self
1750            .bytes
1751            .saturating_add(core::mem::size_of::<FromTerm>().saturating_add(32));
1752        self.from_terms.push(term);
1753        FromTermId(self.from_terms.len().saturating_sub(1) as u32)
1754    }
1755
1756    /// Returns a FROM term.
1757    pub fn from_term(&self, id: FromTermId) -> Option<&FromTerm> {
1758        self.from_terms.get(id.0 as usize)
1759    }
1760
1761    /// Returns a FROM term for modification.
1762    ///
1763    /// A join's `ON` or `USING` clause follows the table it constrains, so the
1764    /// term is stored first and its constraint attached once the parser has
1765    /// read it. Building the term out of order instead would mean holding a
1766    /// half-built node across a recursive parse.
1767    pub fn from_term_mut(&mut self, id: FromTermId) -> Option<&mut FromTerm> {
1768        self.from_terms.get_mut(id.0 as usize)
1769    }
1770
1771    /// Adds a window definition.
1772    pub fn add_window(&mut self, window: Window) -> WindowId {
1773        self.bytes = self
1774            .bytes
1775            .saturating_add(core::mem::size_of::<Window>().saturating_add(32));
1776        self.windows.push(window);
1777        WindowId(self.windows.len().saturating_sub(1) as u32)
1778    }
1779
1780    /// Returns a window definition.
1781    pub fn window(&self, id: WindowId) -> Option<&Window> {
1782        self.windows.get(id.0 as usize)
1783    }
1784}
1785
1786#[cfg(test)]
1787mod tests {
1788    use super::*;
1789
1790    /// Interning is by folded key *and* spelling, so `a` and `A` are two
1791    /// entries that compare equal by key rather than one entry that has
1792    /// forgotten which spelling reached it.
1793    #[test]
1794    fn interning_keeps_the_spelling_and_folds_the_key() {
1795        let mut ast = Ast::new();
1796        let lower = ast.intern(b"abc".to_vec(), QuoteForm::Bare, Span::default());
1797        let upper = ast.intern(b"ABC".to_vec(), QuoteForm::Bare, Span::default());
1798        let again = ast.intern(b"abc".to_vec(), QuoteForm::Bare, Span::default());
1799        assert_eq!(lower, again);
1800        assert_ne!(lower, upper);
1801        assert_eq!(ast.folded(lower), ast.folded(upper));
1802        assert_eq!(ast.text(upper), b"ABC");
1803    }
1804
1805    /// Every node id resolves, and an id from another arena does not panic.
1806    #[test]
1807    fn an_unknown_id_returns_none_rather_than_panicking() {
1808        let ast = Ast::new();
1809        assert!(ast.expr(ExprId(7)).is_none());
1810        assert!(ast.select(SelectId(7)).is_none());
1811        assert!(ast.name(NameId(7)).is_none());
1812        assert_eq!(ast.expr_span(ExprId(7)), Span::default());
1813    }
1814
1815    /// The charge grows with the arena, which is what the limit is checked
1816    /// against before a deep parse allocates.
1817    #[test]
1818    fn the_arena_charges_for_what_it_holds() {
1819        let mut ast = Ast::new();
1820        let before = ast.charged_bytes();
1821        ast.add_expr(Expr::Literal(Literal::Null), Span::default());
1822        assert!(ast.charged_bytes() > before);
1823    }
1824
1825    /// The same name written twice is one entry however it arrives, so the
1826    /// borrowed entry point and the owned one agree.
1827    #[test]
1828    fn the_borrowed_and_owned_entry_points_intern_the_same_name() {
1829        let mut ast = Ast::new();
1830        let owned = ast.intern(b"col".to_vec(), QuoteForm::Bare, Span::default());
1831        let borrowed = ast.intern_bytes(b"col", QuoteForm::Bare, Span::default());
1832        assert_eq!(owned, borrowed);
1833        assert_eq!(ast.name_count(), 1);
1834        assert_eq!(ast.text(owned), b"col");
1835        assert_eq!(ast.folded(owned), b"col");
1836    }
1837
1838    /// The quote form is part of what makes a name, so `x` and `"x"` are two
1839    /// entries even though they spell the same word.
1840    #[test]
1841    fn the_quote_form_separates_two_names_that_spell_the_same_word() {
1842        let mut ast = Ast::new();
1843        let bare = ast.intern_bytes(b"x", QuoteForm::Bare, Span::default());
1844        let quoted = ast.intern_bytes(b"x", QuoteForm::Double, Span::default());
1845        assert_ne!(bare, quoted);
1846        assert_eq!(ast.name_count(), 2);
1847        assert_eq!(
1848            ast.intern_bytes(b"x", QuoteForm::Bare, Span::default()),
1849            bare
1850        );
1851        assert_eq!(
1852            ast.intern_bytes(b"x", QuoteForm::Double, Span::default()),
1853            quoted
1854        );
1855    }
1856
1857    /// A name filed under another name's hash gets its own id.
1858    ///
1859    /// **The failure the map is keyed on a hash to avoid (task-2039).** A map
1860    /// that stored one index per hash and trusted it would answer `gamma` with
1861    /// `alpha`'s id here, and `NameId` equality is read as "the same name" -
1862    /// the binder resolves a column reference by comparing ids - so two
1863    /// different identifiers becoming one id is a wrong query rather than a
1864    /// slow one. A 64-bit collision cannot be produced by interning names, so
1865    /// the collision is filed by hand: `remember_interned` is exactly what
1866    /// `intern_bytes` calls, with the hash of a different name.
1867    #[test]
1868    fn a_name_filed_under_another_names_hash_gets_its_own_id() {
1869        let mut ast = Ast::new();
1870        let alpha = ast.intern_bytes(b"alpha", QuoteForm::Bare, Span::default());
1871        let stolen = ast.hash_of(b"gamma", QuoteForm::Bare);
1872        ast.remember_interned(stolen, alpha.0);
1873
1874        let gamma = ast.intern_bytes(b"gamma", QuoteForm::Bare, Span::default());
1875        assert_ne!(gamma, alpha);
1876        assert_eq!(ast.text(gamma), b"gamma");
1877        assert_eq!(ast.text(alpha), b"alpha");
1878
1879        // And both are still found, from the one slot that now holds both.
1880        assert_eq!(
1881            ast.intern_bytes(b"gamma", QuoteForm::Bare, Span::default()),
1882            gamma
1883        );
1884        assert_eq!(
1885            ast.intern_bytes(b"alpha", QuoteForm::Bare, Span::default()),
1886            alpha
1887        );
1888        assert_eq!(ast.name_count(), 2);
1889    }
1890
1891    /// Two hundred names all reach their own id and find it again.
1892    ///
1893    /// The map is keyed on a hash now, so "every name is distinct" is a claim
1894    /// about the candidate comparison rather than about the map, and a scan of
1895    /// a real number of names is what checks it.
1896    #[test]
1897    fn many_names_each_keep_their_own_id() {
1898        let mut ast = Ast::new();
1899        let spellings: Vec<Vec<u8>> = (0..200)
1900            .map(|nth| format!("column_{nth}").into_bytes())
1901            .collect();
1902        let ids: Vec<NameId> = spellings
1903            .iter()
1904            .map(|text| ast.intern_bytes(text, QuoteForm::Bare, Span::default()))
1905            .collect();
1906        assert_eq!(ast.name_count(), 200);
1907        for (text, id) in spellings.iter().zip(&ids) {
1908            assert_eq!(
1909                ast.intern_bytes(text, QuoteForm::Bare, Span::default()),
1910                *id
1911            );
1912            assert_eq!(ast.text(*id), text.as_slice());
1913        }
1914        let mut sorted = ids.clone();
1915        sorted.sort_unstable();
1916        sorted.dedup();
1917        assert_eq!(sorted.len(), 200);
1918    }
1919
1920    /// `clear` keeps the names' byte buffers and the names vector's capacity.
1921    ///
1922    /// **Both halves, because losing either one costs an allocation per warm
1923    /// compile (task-2039).** The buffers are what a second parse of the same
1924    /// statement fills instead of asking the allocator; the vector's capacity
1925    /// is what `clear` existed to keep in the first place, and a `clear` that
1926    /// moved the names out by `core::mem::take` silently gave it back.
1927    #[test]
1928    fn clearing_keeps_the_name_buffers_and_the_names_capacity() {
1929        let mut ast = Ast::new();
1930        for nth in 0..4u32 {
1931            ast.intern_bytes(
1932                format!("c{nth}").as_bytes(),
1933                QuoteForm::Bare,
1934                Span::default(),
1935            );
1936        }
1937        let capacity = ast.names.capacity();
1938        assert!(capacity >= 4);
1939
1940        ast.clear();
1941        assert_eq!(ast.name_count(), 0);
1942        assert_eq!(ast.names.capacity(), capacity);
1943        // Two buffers a name: the spelling and the folded key.
1944        assert_eq!(ast.spare.len(), 8);
1945        assert!(ast.spare.iter().all(|buffer| buffer.is_empty()));
1946
1947        // And the next parse takes them back rather than allocating.
1948        for nth in 0..4u32 {
1949            ast.intern_bytes(
1950                format!("c{nth}").as_bytes(),
1951                QuoteForm::Bare,
1952                Span::default(),
1953            );
1954        }
1955        assert_eq!(ast.spare.len(), 0);
1956        assert_eq!(ast.name_count(), 4);
1957        assert_eq!(ast.text(NameId(2)), b"c2");
1958    }
1959
1960    /// The free list is bounded, so a statement naming thousands of things
1961    /// does not leave the connection holding them.
1962    #[test]
1963    fn the_free_list_does_not_grow_without_bound() {
1964        let mut ast = Ast::new();
1965        for nth in 0..2_000u32 {
1966            ast.intern_bytes(
1967                format!("column_{nth}").as_bytes(),
1968                QuoteForm::Bare,
1969                Span::default(),
1970            );
1971        }
1972        ast.clear();
1973        assert_eq!(ast.spare.len(), SPARE_NAME_BUFFERS);
1974
1975        // A name longer than a buffer worth keeping is dropped rather than
1976        // held, so one enormous alias does not pin its bytes for ever.
1977        let mut ast = Ast::new();
1978        let long = vec![b'z'; SPARE_NAME_CAPACITY.saturating_add(1)];
1979        ast.intern_bytes(&long, QuoteForm::Bare, Span::default());
1980        ast.clear();
1981        assert_eq!(ast.spare.len(), 0);
1982    }
1983
1984    /// Two arenas holding the same nodes are equal, and the index behind them
1985    /// is not part of that.
1986    ///
1987    /// `Ast` compares by hand because `interned` is keyed on a hash each arena
1988    /// seeds for itself, so a derived comparison would report two identical
1989    /// parses as different (task-2039).
1990    #[test]
1991    fn two_arenas_holding_the_same_names_are_equal() {
1992        let mut one = Ast::new();
1993        let mut two = Ast::new();
1994        for text in [b"alpha".as_slice(), b"beta".as_slice()] {
1995            one.intern_bytes(text, QuoteForm::Bare, Span::default());
1996            two.intern_bytes(text, QuoteForm::Bare, Span::default());
1997        }
1998        assert_eq!(one, two);
1999
2000        two.intern_bytes(b"gamma", QuoteForm::Bare, Span::default());
2001        assert_ne!(one, two);
2002    }
2003}