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