1#[cfg(feature = "extra_checks")]
3pub mod check;
4pub mod fmt;
5
6use std::num::ParseIntError;
7use std::ops::Deref;
8use std::str::{self, Bytes, FromStr};
9
10#[cfg(feature = "extra_checks")]
11use check::ColumnCount;
12use fmt::TokenStream;
13use indexmap::{IndexMap, IndexSet};
14
15use crate::custom_err;
16use crate::dialect::TokenType::{self, *};
17use crate::dialect::{from_token, is_identifier, Token};
18use crate::parser::{parse::YYCODETYPE, ParserError};
19
20#[derive(Default)]
22pub struct ParameterInfo {
23 pub count: u16,
25 pub names: IndexSet<String>,
27}
28
29impl TokenStream for ParameterInfo {
31 type Error = ParseIntError;
32
33 fn append(&mut self, ty: TokenType, value: Option<&str>) -> Result<(), Self::Error> {
34 if ty == TK_VARIABLE {
35 if let Some(variable) = value {
36 if variable == "?" {
37 self.count = self.count.saturating_add(1);
38 } else if variable.as_bytes()[0] == b'?' {
39 let n = u16::from_str(&variable[1..])?;
40 if n > self.count {
41 self.count = n;
42 }
43 } else if self.names.insert(variable.to_owned()) {
44 self.count = self.count.saturating_add(1);
45 }
46 }
47 }
48 Ok(())
49 }
50}
51
52#[derive(Clone, Debug, PartialEq, Eq)]
55pub enum Cmd {
56 Explain(Stmt),
58 ExplainQueryPlan(Stmt),
60 Stmt(Stmt),
62}
63
64pub(crate) enum ExplainKind {
65 Explain,
66 QueryPlan,
67}
68
69#[derive(Clone, Debug, PartialEq, Eq)]
72pub enum Stmt {
73 AlterTable(QualifiedName, AlterTableBody),
75 Analyze(Option<QualifiedName>),
77 Attach {
79 expr: Expr,
82 db_name: Expr,
84 key: Option<Expr>,
86 },
87 Begin(Option<TransactionType>, Option<Name>),
89 Commit(Option<Name>), CreateIndex {
93 unique: bool,
95 if_not_exists: bool,
97 idx_name: QualifiedName,
99 tbl_name: Name,
101 columns: Vec<SortedColumn>,
103 where_clause: Option<Expr>,
105 },
106 CreateTable {
108 temporary: bool, if_not_exists: bool,
112 tbl_name: QualifiedName,
114 body: CreateTableBody,
116 },
117 CreateTrigger {
119 temporary: bool,
121 if_not_exists: bool,
123 trigger_name: QualifiedName,
125 time: Option<TriggerTime>,
127 event: TriggerEvent,
129 tbl_name: QualifiedName,
131 for_each_row: bool,
133 when_clause: Option<Expr>,
135 commands: Vec<TriggerCmd>,
137 },
138 CreateView {
140 temporary: bool,
142 if_not_exists: bool,
144 view_name: QualifiedName,
146 columns: Option<Vec<IndexedColumn>>, select: Box<Select>,
150 },
151 CreateVirtualTable {
153 if_not_exists: bool,
155 tbl_name: QualifiedName,
157 module_name: Name,
159 args: Option<Vec<Box<str>>>,
161 },
162 Delete {
164 with: Option<With>, tbl_name: QualifiedName,
168 indexed: Option<Indexed>,
170 where_clause: Option<Expr>,
172 returning: Option<Vec<ResultColumn>>,
174 order_by: Option<Vec<SortedColumn>>,
176 limit: Option<Limit>,
178 },
179 Detach(Expr), DropIndex {
183 if_exists: bool,
185 idx_name: QualifiedName,
187 },
188 DropTable {
190 if_exists: bool,
192 tbl_name: QualifiedName,
194 },
195 DropTrigger {
197 if_exists: bool,
199 trigger_name: QualifiedName,
201 },
202 DropView {
204 if_exists: bool,
206 view_name: QualifiedName,
208 },
209 Insert {
211 with: Option<With>, or_conflict: Option<ResolveType>, tbl_name: QualifiedName,
217 columns: Option<DistinctNames>,
219 body: InsertBody,
221 returning: Option<Vec<ResultColumn>>,
223 },
224 Pragma(QualifiedName, Option<PragmaBody>),
226 Reindex {
228 obj_name: Option<QualifiedName>,
230 },
231 Release(Name), Rollback {
235 tx_name: Option<Name>,
237 savepoint_name: Option<Name>, },
240 Savepoint(Name),
242 Select(Box<Select>),
244 Update {
246 with: Option<With>, or_conflict: Option<ResolveType>,
250 tbl_name: QualifiedName,
252 indexed: Option<Indexed>,
254 sets: Vec<Set>, from: Option<FromClause>,
258 where_clause: Option<Expr>,
260 returning: Option<Vec<ResultColumn>>,
262 order_by: Option<Vec<SortedColumn>>,
264 limit: Option<Limit>,
266 },
267 Vacuum(Option<Name>, Option<Expr>),
269}
270
271impl Stmt {
272 pub fn create_index(
274 unique: bool,
275 if_not_exists: bool,
276 idx_name: QualifiedName,
277 tbl_name: Name,
278 columns: Vec<SortedColumn>,
279 where_clause: Option<Expr>,
280 ) -> Result<Self, ParserError> {
281 has_explicit_nulls(&columns)?;
282 Ok(Self::CreateIndex {
283 unique,
284 if_not_exists,
285 idx_name,
286 tbl_name,
287 columns,
288 where_clause,
289 })
290 }
291 #[allow(clippy::too_many_arguments)]
293 pub fn update(
294 with: Option<With>,
295 or_conflict: Option<ResolveType>,
296 tbl_name: QualifiedName,
297 indexed: Option<Indexed>,
298 sets: Vec<Set>, from: Option<FromClause>,
300 where_clause: Option<Expr>,
301 returning: Option<Vec<ResultColumn>>,
302 order_by: Option<Vec<SortedColumn>>,
303 limit: Option<Limit>,
304 ) -> Result<Self, ParserError> {
305 #[cfg(feature = "extra_checks")]
306 if let Some(FromClause {
307 select: Some(ref select),
308 ref joins,
309 ..
310 }) = from
311 {
312 if matches!(select.as_ref(),
313 SelectTable::Table(qn, _, _) | SelectTable::TableCall(qn, _, _)
314 if *qn == tbl_name)
315 || joins.as_ref().is_some_and(|js| js.iter().any(|j|
316 matches!(j.table, SelectTable::Table(ref qn, _, _) | SelectTable::TableCall(ref qn, _, _)
317 if *qn == tbl_name)))
318 {
319 return Err(custom_err!(
320 "target object/alias may not appear in FROM clause",
321 ));
322 }
323 }
324 #[cfg(feature = "extra_checks")]
325 if order_by.is_some() && limit.is_none() {
326 return Err(custom_err!("ORDER BY without LIMIT on UPDATE"));
327 }
328 Ok(Self::Update {
329 with,
330 or_conflict,
331 tbl_name,
332 indexed,
333 sets,
334 from,
335 where_clause,
336 returning,
337 order_by,
338 limit,
339 })
340 }
341}
342
343#[derive(Clone, Debug, PartialEq, Eq)]
346pub enum Expr {
347 Between {
349 lhs: Box<Expr>,
351 not: bool,
353 start: Box<Expr>,
355 end: Box<Expr>,
357 },
358 Binary(Box<Expr>, Operator, Box<Expr>),
360 Case {
362 base: Option<Box<Expr>>,
364 when_then_pairs: Vec<(Expr, Expr)>,
366 else_expr: Option<Box<Expr>>,
368 },
369 Cast {
371 expr: Box<Expr>,
373 type_name: Option<Type>,
375 },
376 Collate(Box<Expr>, Box<str>),
378 DoublyQualified(Name, Name, Name),
380 Exists(Box<Select>),
382 FunctionCall {
384 name: Id,
386 distinctness: Option<Distinctness>,
388 args: Option<Vec<Expr>>,
390 order_by: Option<FunctionCallOrder>,
392 filter_over: Option<FunctionTail>,
394 },
395 FunctionCallStar {
397 name: Id,
399 filter_over: Option<FunctionTail>,
401 },
402 Id(Id),
404 InList {
406 lhs: Box<Expr>,
408 not: bool,
410 rhs: Option<Vec<Expr>>,
412 },
413 InSelect {
415 lhs: Box<Expr>,
417 not: bool,
419 rhs: Box<Select>,
421 },
422 InTable {
424 lhs: Box<Expr>,
426 not: bool,
428 rhs: QualifiedName,
430 args: Option<Vec<Expr>>,
432 },
433 IsNull(Box<Expr>),
435 Like {
437 lhs: Box<Expr>,
439 not: bool,
441 op: LikeOperator,
443 rhs: Box<Expr>,
445 escape: Option<Box<Expr>>,
447 },
448 Literal(Literal),
450 Name(Name),
452 NotNull(Box<Expr>),
454 Parenthesized(Vec<Expr>),
456 Qualified(Name, Name),
458 Raise(ResolveType, Option<Box<Expr>>),
460 Subquery(Box<Select>),
462 Unary(UnaryOperator, Box<Expr>),
464 Variable(Box<str>),
466}
467
468#[derive(Clone, Debug, PartialEq, Eq)]
470pub enum FunctionCallOrder {
471 SortList(Vec<SortedColumn>),
473 #[cfg(feature = "SQLITE_ENABLE_ORDERED_SET_AGGREGATES")]
475 WithinGroup(Box<Expr>),
476}
477
478impl FunctionCallOrder {
479 #[cfg(feature = "SQLITE_ENABLE_ORDERED_SET_AGGREGATES")]
481 pub fn within_group(expr: Expr) -> Self {
482 Self::WithinGroup(Box::new(expr))
483 }
484}
485
486impl Expr {
487 pub fn parenthesized(x: Self) -> Self {
489 Self::Parenthesized(vec![x])
490 }
491 pub fn id(xt: YYCODETYPE, x: Token) -> Self {
493 Self::Id(Id::from_token(xt, x))
494 }
495 pub fn collate(x: Self, ct: YYCODETYPE, c: Token) -> Self {
497 Self::Collate(Box::new(x), from_token(ct, c))
498 }
499 pub fn cast(x: Self, type_name: Option<Type>) -> Self {
501 Self::Cast {
502 expr: Box::new(x),
503 type_name,
504 }
505 }
506 pub fn binary(left: Self, op: YYCODETYPE, right: Self) -> Self {
508 Self::Binary(Box::new(left), Operator::from(op), Box::new(right))
509 }
510 pub fn ptr(left: Self, op: Token, right: Self) -> Self {
512 let mut ptr = Operator::ArrowRight;
513 if op.1 == b"->>" {
514 ptr = Operator::ArrowRightShift;
515 }
516 Self::Binary(Box::new(left), ptr, Box::new(right))
517 }
518 pub fn like(lhs: Self, not: bool, op: LikeOperator, rhs: Self, escape: Option<Self>) -> Self {
520 Self::Like {
521 lhs: Box::new(lhs),
522 not,
523 op,
524 rhs: Box::new(rhs),
525 escape: escape.map(Box::new),
526 }
527 }
528 pub fn not_null(x: Self, op: YYCODETYPE) -> Self {
530 if op == TK_ISNULL as YYCODETYPE {
531 Self::IsNull(Box::new(x))
532 } else if op == TK_NOTNULL as YYCODETYPE {
533 Self::NotNull(Box::new(x))
534 } else {
535 unreachable!()
536 }
537 }
538 pub fn unary(op: UnaryOperator, x: Self) -> Self {
540 Self::Unary(op, Box::new(x))
541 }
542 pub fn between(lhs: Self, not: bool, start: Self, end: Self) -> Self {
544 Self::Between {
545 lhs: Box::new(lhs),
546 not,
547 start: Box::new(start),
548 end: Box::new(end),
549 }
550 }
551 pub fn in_list(lhs: Self, not: bool, rhs: Option<Vec<Self>>) -> Self {
553 Self::InList {
554 lhs: Box::new(lhs),
555 not,
556 rhs,
557 }
558 }
559 pub fn in_select(lhs: Self, not: bool, rhs: Select) -> Self {
561 Self::InSelect {
562 lhs: Box::new(lhs),
563 not,
564 rhs: Box::new(rhs),
565 }
566 }
567 pub fn in_table(lhs: Self, not: bool, rhs: QualifiedName, args: Option<Vec<Self>>) -> Self {
569 Self::InTable {
570 lhs: Box::new(lhs),
571 not,
572 rhs,
573 args,
574 }
575 }
576 pub fn sub_query(query: Select) -> Self {
578 Self::Subquery(Box::new(query))
579 }
580 pub fn function_call(
582 xt: YYCODETYPE,
583 x: Token,
584 distinctness: Option<Distinctness>,
585 args: Option<Vec<Self>>,
586 order_by: Option<FunctionCallOrder>,
587 filter_over: Option<FunctionTail>,
588 ) -> Result<Self, ParserError> {
589 #[cfg(feature = "extra_checks")]
590 if let Some(Distinctness::Distinct) = distinctness {
591 if args.as_ref().map_or(0, Vec::len) != 1 {
592 return Err(custom_err!(
593 "DISTINCT aggregates must have exactly one argument"
594 ));
595 }
596 }
597 Ok(Self::FunctionCall {
598 name: Id::from_token(xt, x),
599 distinctness,
600 args,
601 order_by,
602 filter_over,
603 })
604 }
605
606 pub fn is_integer(&self) -> Option<i64> {
608 if let Self::Literal(Literal::Numeric(s)) = self {
609 i64::from_str(s).ok()
610 } else if let Self::Unary(UnaryOperator::Positive, e) = self {
611 e.is_integer()
612 } else if let Self::Unary(UnaryOperator::Negative, e) = self {
613 e.is_integer().map(i64::saturating_neg)
614 } else {
615 None
616 }
617 }
618 #[cfg(feature = "extra_checks")]
619 fn check_range(&self, term: &str, mx: u16) -> Result<(), ParserError> {
620 if let Some(i) = self.is_integer() {
621 if i < 1 || i > mx as i64 {
622 return Err(custom_err!(
623 "{} BY term out of range - should be between 1 and {}",
624 term,
625 mx
626 ));
627 }
628 }
629 Ok(())
630 }
631}
632
633#[derive(Clone, Debug, PartialEq, Eq)]
635pub enum Literal {
636 Numeric(Box<str>),
638 String(Box<str>),
641 Blob(Box<str>),
644 Keyword(Box<str>),
646 Null,
648 CurrentDate,
650 CurrentTime,
652 CurrentTimestamp,
654}
655
656impl Literal {
657 pub fn from_ctime_kw(token: Token) -> Self {
659 if b"CURRENT_DATE".eq_ignore_ascii_case(token.1) {
660 Self::CurrentDate
661 } else if b"CURRENT_TIME".eq_ignore_ascii_case(token.1) {
662 Self::CurrentTime
663 } else if b"CURRENT_TIMESTAMP".eq_ignore_ascii_case(token.1) {
664 Self::CurrentTimestamp
665 } else {
666 unreachable!()
667 }
668 }
669}
670
671#[derive(Copy, Clone, Debug, PartialEq, Eq)]
673pub enum LikeOperator {
674 Glob,
676 Like,
678 Match,
680 Regexp,
682}
683
684impl LikeOperator {
685 pub fn from_token(token_type: YYCODETYPE, token: Token) -> Self {
687 if token_type == TK_MATCH as YYCODETYPE {
688 return Self::Match;
689 } else if token_type == TK_LIKE_KW as YYCODETYPE {
690 let token = token.1;
691 if b"LIKE".eq_ignore_ascii_case(token) {
692 return Self::Like;
693 } else if b"GLOB".eq_ignore_ascii_case(token) {
694 return Self::Glob;
695 } else if b"REGEXP".eq_ignore_ascii_case(token) {
696 return Self::Regexp;
697 }
698 }
699 unreachable!()
700 }
701}
702
703#[derive(Copy, Clone, Debug, PartialEq, Eq)]
705pub enum Operator {
706 Add,
708 And,
710 ArrowRight,
712 ArrowRightShift,
714 BitwiseAnd,
716 BitwiseOr,
718 Concat,
720 Equals,
722 Divide,
724 Greater,
726 GreaterEquals,
728 Is,
730 IsNot,
732 LeftShift,
734 Less,
736 LessEquals,
738 Modulus,
740 Multiply,
742 NotEquals,
744 Or,
746 RightShift,
748 Subtract,
750}
751
752impl From<YYCODETYPE> for Operator {
753 fn from(token_type: YYCODETYPE) -> Self {
754 match token_type {
755 x if x == TK_AND as YYCODETYPE => Self::And,
756 x if x == TK_OR as YYCODETYPE => Self::Or,
757 x if x == TK_LT as YYCODETYPE => Self::Less,
758 x if x == TK_GT as YYCODETYPE => Self::Greater,
759 x if x == TK_GE as YYCODETYPE => Self::GreaterEquals,
760 x if x == TK_LE as YYCODETYPE => Self::LessEquals,
761 x if x == TK_EQ as YYCODETYPE => Self::Equals,
762 x if x == TK_NE as YYCODETYPE => Self::NotEquals,
763 x if x == TK_BITAND as YYCODETYPE => Self::BitwiseAnd,
764 x if x == TK_BITOR as YYCODETYPE => Self::BitwiseOr,
765 x if x == TK_LSHIFT as YYCODETYPE => Self::LeftShift,
766 x if x == TK_RSHIFT as YYCODETYPE => Self::RightShift,
767 x if x == TK_PLUS as YYCODETYPE => Self::Add,
768 x if x == TK_MINUS as YYCODETYPE => Self::Subtract,
769 x if x == TK_STAR as YYCODETYPE => Self::Multiply,
770 x if x == TK_SLASH as YYCODETYPE => Self::Divide,
771 x if x == TK_REM as YYCODETYPE => Self::Modulus,
772 x if x == TK_CONCAT as YYCODETYPE => Self::Concat,
773 x if x == TK_IS as YYCODETYPE => Self::Is,
774 x if x == TK_NOT as YYCODETYPE => Self::IsNot,
775 _ => unreachable!(),
776 }
777 }
778}
779
780#[derive(Copy, Clone, Debug, PartialEq, Eq)]
782pub enum UnaryOperator {
783 BitwiseNot,
785 Negative,
787 Not,
789 Positive,
791}
792
793impl From<YYCODETYPE> for UnaryOperator {
794 fn from(token_type: YYCODETYPE) -> Self {
795 match token_type {
796 x if x == TK_BITNOT as YYCODETYPE => Self::BitwiseNot,
797 x if x == TK_MINUS as YYCODETYPE => Self::Negative,
798 x if x == TK_NOT as YYCODETYPE => Self::Not,
799 x if x == TK_PLUS as YYCODETYPE => Self::Positive,
800 _ => unreachable!(),
801 }
802 }
803}
804
805#[derive(Clone, Debug, PartialEq, Eq)]
809pub struct Select {
810 pub with: Option<With>, pub body: SelectBody,
814 pub order_by: Option<Vec<SortedColumn>>, pub limit: Option<Limit>,
818}
819
820impl Select {
821 pub fn new(
823 with: Option<With>,
824 body: SelectBody,
825 order_by: Option<Vec<SortedColumn>>,
826 limit: Option<Limit>,
827 ) -> Result<Self, ParserError> {
828 let select = Self {
829 with,
830 body,
831 order_by,
832 limit,
833 };
834 #[cfg(feature = "extra_checks")]
835 if let Self {
836 order_by: Some(ref scs),
837 ..
838 } = select
839 {
840 if let ColumnCount::Fixed(n) = select.column_count() {
841 for sc in scs {
842 sc.expr.check_range("ORDER", n)?;
843 }
844 }
845 }
846 Ok(select)
847 }
848}
849
850#[derive(Clone, Debug, PartialEq, Eq)]
852pub struct SelectBody {
853 pub select: OneSelect,
855 pub compounds: Option<Vec<CompoundSelect>>,
857}
858
859impl SelectBody {
860 pub(crate) fn push(&mut self, cs: CompoundSelect) -> Result<(), ParserError> {
861 #[cfg(feature = "extra_checks")]
862 if let ColumnCount::Fixed(n) = self.select.column_count() {
863 if let ColumnCount::Fixed(m) = cs.select.column_count() {
864 if n != m {
865 return Err(custom_err!(
866 "SELECTs to the left and right of {} do not have the same number of result columns",
867 cs.operator
868 ));
869 }
870 }
871 }
872 if let Some(ref mut v) = self.compounds {
873 v.push(cs);
874 } else {
875 self.compounds = Some(vec![cs]);
876 }
877 Ok(())
878 }
879}
880
881#[derive(Clone, Debug, PartialEq, Eq)]
883pub struct CompoundSelect {
884 pub operator: CompoundOperator,
886 pub select: OneSelect,
888}
889
890#[derive(Copy, Clone, Debug, PartialEq, Eq)]
893pub enum CompoundOperator {
894 Union,
896 UnionAll,
898 Except,
900 Intersect,
902}
903
904#[derive(Clone, Debug, PartialEq, Eq)]
907pub enum OneSelect {
908 Select {
910 distinctness: Option<Distinctness>,
912 columns: Vec<ResultColumn>,
914 from: Option<FromClause>,
916 where_clause: Option<Box<Expr>>,
918 group_by: Option<Vec<Expr>>,
920 having: Option<Box<Expr>>, window_clause: Option<Vec<WindowDef>>,
924 },
925 Values(Vec<Vec<Expr>>),
927}
928
929impl OneSelect {
930 pub fn new(
932 distinctness: Option<Distinctness>,
933 columns: Vec<ResultColumn>,
934 from: Option<FromClause>,
935 where_clause: Option<Expr>,
936 group_by: Option<Vec<Expr>>,
937 having: Option<Expr>,
938 window_clause: Option<Vec<WindowDef>>,
939 ) -> Result<Self, ParserError> {
940 #[cfg(feature = "extra_checks")]
941 if from.is_none()
942 && columns
943 .iter()
944 .any(|rc| matches!(rc, ResultColumn::Star | ResultColumn::TableStar(_)))
945 {
946 return Err(custom_err!("no tables specified"));
947 }
948 let select = Self::Select {
949 distinctness,
950 columns,
951 from,
952 where_clause: where_clause.map(Box::new),
953 group_by,
954 having: having.map(Box::new),
955 window_clause,
956 };
957 #[cfg(feature = "extra_checks")]
958 if let Self::Select {
959 group_by: Some(ref gb),
960 ..
961 } = select
962 {
963 if let ColumnCount::Fixed(n) = select.column_count() {
964 for expr in gb {
965 expr.check_range("GROUP", n)?;
966 }
967 }
968 }
969 Ok(select)
970 }
971 pub fn push(values: &mut Vec<Vec<Expr>>, v: Vec<Expr>) -> Result<(), ParserError> {
973 #[cfg(feature = "extra_checks")]
974 if values[0].len() != v.len() {
975 return Err(custom_err!("all VALUES must have the same number of terms"));
976 }
977 values.push(v);
978 Ok(())
979 }
980}
981
982#[derive(Clone, Debug, PartialEq, Eq)]
985pub struct FromClause {
986 pub select: Option<Box<SelectTable>>, pub joins: Option<Vec<JoinedSelectTable>>,
990 op: Option<JoinOperator>, }
992impl FromClause {
993 pub(crate) fn empty() -> Self {
994 Self {
995 select: None,
996 joins: None,
997 op: None,
998 }
999 }
1000
1001 pub(crate) fn push(
1002 &mut self,
1003 table: SelectTable,
1004 jc: Option<JoinConstraint>,
1005 ) -> Result<(), ParserError> {
1006 let op = self.op.take();
1007 if let Some(op) = op {
1008 let jst = JoinedSelectTable {
1009 operator: op,
1010 table,
1011 constraint: jc,
1012 };
1013 if jst.operator.is_natural() && jst.constraint.is_some() {
1014 return Err(custom_err!(
1015 "a NATURAL join may not have an ON or USING clause"
1016 ));
1017 }
1018 if let Some(ref mut joins) = self.joins {
1019 joins.push(jst);
1020 } else {
1021 self.joins = Some(vec![jst]);
1022 }
1023 } else {
1024 if jc.is_some() {
1025 return Err(custom_err!("a JOIN clause is required before ON"));
1026 }
1027 debug_assert!(self.select.is_none());
1028 debug_assert!(self.joins.is_none());
1029 self.select = Some(Box::new(table));
1030 }
1031 Ok(())
1032 }
1033
1034 pub(crate) fn push_op(&mut self, op: JoinOperator) {
1035 self.op = Some(op);
1036 }
1037}
1038
1039#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1041pub enum Distinctness {
1042 Distinct,
1044 All,
1046}
1047
1048#[derive(Clone, Debug, PartialEq, Eq)]
1051pub enum ResultColumn {
1052 Expr(Expr, Option<As>),
1054 Star,
1056 TableStar(Name),
1058}
1059
1060#[derive(Clone, Debug, PartialEq, Eq)]
1062pub enum As {
1063 As(Name),
1065 Elided(Name), }
1068
1069#[derive(Clone, Debug, PartialEq, Eq)]
1072pub struct JoinedSelectTable {
1073 pub operator: JoinOperator,
1075 pub table: SelectTable,
1077 pub constraint: Option<JoinConstraint>,
1079}
1080
1081#[derive(Clone, Debug, PartialEq, Eq)]
1084pub enum SelectTable {
1085 Table(QualifiedName, Option<As>, Option<Indexed>),
1087 TableCall(QualifiedName, Option<Vec<Expr>>, Option<As>),
1089 Select(Box<Select>, Option<As>),
1091 Sub(FromClause, Option<As>),
1093}
1094
1095#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1098pub enum JoinOperator {
1099 Comma,
1101 TypedJoin(Option<JoinType>),
1103}
1104
1105impl JoinOperator {
1106 pub(crate) fn from(
1107 token: Token,
1108 n1: Option<Name>,
1109 n2: Option<Name>,
1110 ) -> Result<Self, ParserError> {
1111 Ok({
1112 let mut jt = JoinType::try_from(token.1)?;
1113 for n in [&n1, &n2].into_iter().flatten() {
1114 jt |= JoinType::try_from(n.0.as_ref().as_bytes())?;
1115 }
1116 if (jt & (JoinType::INNER | JoinType::OUTER)) == (JoinType::INNER | JoinType::OUTER)
1117 || (jt & (JoinType::OUTER | JoinType::LEFT | JoinType::RIGHT)) == JoinType::OUTER
1118 {
1119 return Err(custom_err!(
1120 "unknown join type: {} {} {}",
1121 str::from_utf8(token.1).unwrap_or("invalid utf8"),
1122 n1.as_ref().map_or("", |n| n.0.as_ref()),
1123 n2.as_ref().map_or("", |n| n.0.as_ref())
1124 ));
1125 }
1126 Self::TypedJoin(Some(jt))
1127 })
1128 }
1129 fn is_natural(&self) -> bool {
1130 match self {
1131 Self::TypedJoin(Some(jt)) => jt.contains(JoinType::NATURAL),
1132 _ => false,
1133 }
1134 }
1135}
1136
1137bitflags::bitflags! {
1139 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1141 pub struct JoinType: u8 {
1142 const INNER = 0x01;
1144 const CROSS = 0x02;
1146 const NATURAL = 0x04;
1148 const LEFT = 0x08;
1150 const RIGHT = 0x10;
1152 const OUTER = 0x20;
1154 }
1155}
1156
1157impl TryFrom<&[u8]> for JoinType {
1158 type Error = ParserError;
1159 fn try_from(s: &[u8]) -> Result<Self, ParserError> {
1160 if b"CROSS".eq_ignore_ascii_case(s) {
1161 Ok(Self::INNER | Self::CROSS)
1162 } else if b"FULL".eq_ignore_ascii_case(s) {
1163 Ok(Self::LEFT | Self::RIGHT | Self::OUTER)
1164 } else if b"INNER".eq_ignore_ascii_case(s) {
1165 Ok(Self::INNER)
1166 } else if b"LEFT".eq_ignore_ascii_case(s) {
1167 Ok(Self::LEFT | Self::OUTER)
1168 } else if b"NATURAL".eq_ignore_ascii_case(s) {
1169 Ok(Self::NATURAL)
1170 } else if b"RIGHT".eq_ignore_ascii_case(s) {
1171 Ok(Self::RIGHT | Self::OUTER)
1172 } else if b"OUTER".eq_ignore_ascii_case(s) {
1173 Ok(Self::OUTER)
1174 } else {
1175 Err(custom_err!(
1176 "unknown join type: {}",
1177 str::from_utf8(s).unwrap_or("invalid utf8")
1178 ))
1179 }
1180 }
1181}
1182
1183#[derive(Clone, Debug, PartialEq, Eq)]
1185pub enum JoinConstraint {
1186 On(Expr),
1188 Using(DistinctNames),
1190}
1191
1192#[derive(Clone, Debug, PartialEq, Eq)]
1194pub struct Id(pub Box<str>);
1195
1196impl Id {
1197 pub fn from_token(ty: YYCODETYPE, token: Token) -> Self {
1199 Self(from_token(ty, token))
1200 }
1201}
1202
1203#[derive(Clone, Debug, Eq)]
1207pub struct Name(pub Box<str>); pub(crate) fn unquote(s: &str) -> (&str, u8) {
1210 if s.is_empty() {
1211 return (s, 0);
1212 }
1213 let bytes = s.as_bytes();
1214 let mut quote = bytes[0];
1215 if quote != b'"' && quote != b'`' && quote != b'\'' && quote != b'[' {
1216 return (s, 0);
1217 } else if quote == b'[' {
1218 quote = b']';
1219 }
1220 debug_assert!(bytes.len() > 1);
1221 debug_assert_eq!(quote, bytes[bytes.len() - 1]);
1222 let sub = &s[1..bytes.len() - 1];
1223 if quote == b']' || sub.len() < 2 {
1224 (sub, 0)
1225 } else {
1226 (sub, quote)
1227 }
1228}
1229
1230impl Name {
1231 pub fn from_token(ty: YYCODETYPE, token: Token) -> Self {
1233 Self(from_token(ty, token))
1234 }
1235
1236 fn as_bytes(&self) -> QuotedIterator<'_> {
1237 let (sub, quote) = unquote(self.0.as_ref());
1238 QuotedIterator(sub.bytes(), quote)
1239 }
1240 #[cfg(feature = "extra_checks")]
1241 fn is_reserved(&self) -> bool {
1242 let bytes = self.as_bytes();
1243 let reserved = QuotedIterator("sqlite_".bytes(), 0);
1244 bytes.zip(reserved).fold(0u8, |acc, (b1, b2)| {
1245 acc + if b1.eq_ignore_ascii_case(&b2) { 1 } else { 0 }
1246 }) == 7u8
1247 }
1248}
1249
1250struct QuotedIterator<'s>(Bytes<'s>, u8);
1251impl Iterator for QuotedIterator<'_> {
1252 type Item = u8;
1253
1254 fn next(&mut self) -> Option<u8> {
1255 match self.0.next() {
1256 x @ Some(b) => {
1257 if b == self.1 && self.0.next() != Some(self.1) {
1258 panic!("Malformed string literal: {:?}", self.0);
1259 }
1260 x
1261 }
1262 x => x,
1263 }
1264 }
1265
1266 fn size_hint(&self) -> (usize, Option<usize>) {
1267 if self.1 == 0 {
1268 return self.0.size_hint();
1269 }
1270 (0, None)
1271 }
1272}
1273
1274fn eq_ignore_case_and_quote(mut it: QuotedIterator<'_>, mut other: QuotedIterator<'_>) -> bool {
1275 loop {
1276 match (it.next(), other.next()) {
1277 (Some(b1), Some(b2)) => {
1278 if !b1.eq_ignore_ascii_case(&b2) {
1279 return false;
1280 }
1281 }
1282 (None, None) => break,
1283 _ => return false,
1284 }
1285 }
1286 true
1287}
1288
1289impl std::hash::Hash for Name {
1291 fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
1292 self.as_bytes()
1293 .for_each(|b| hasher.write_u8(b.to_ascii_lowercase()));
1294 }
1295}
1296impl PartialEq for Name {
1298 fn eq(&self, other: &Self) -> bool {
1299 eq_ignore_case_and_quote(self.as_bytes(), other.as_bytes())
1300 }
1301}
1302impl PartialEq<str> for Name {
1304 fn eq(&self, other: &str) -> bool {
1305 eq_ignore_case_and_quote(self.as_bytes(), QuotedIterator(other.bytes(), 0u8))
1306 }
1307}
1308impl PartialEq<&str> for Name {
1310 fn eq(&self, other: &&str) -> bool {
1311 eq_ignore_case_and_quote(self.as_bytes(), QuotedIterator(other.bytes(), 0u8))
1312 }
1313}
1314
1315#[derive(Clone, Debug, PartialEq, Eq)]
1317pub struct QualifiedName {
1318 pub db_name: Option<Name>,
1320 pub name: Name,
1322 pub alias: Option<Name>, }
1325
1326impl QualifiedName {
1327 pub fn single(name: Name) -> Self {
1329 Self {
1330 db_name: None,
1331 name,
1332 alias: None,
1333 }
1334 }
1335 pub fn fullname(db_name: Name, name: Name) -> Self {
1337 Self {
1338 db_name: Some(db_name),
1339 name,
1340 alias: None,
1341 }
1342 }
1343 pub fn xfullname(db_name: Name, name: Name, alias: Name) -> Self {
1345 Self {
1346 db_name: Some(db_name),
1347 name,
1348 alias: Some(alias),
1349 }
1350 }
1351 pub fn alias(name: Name, alias: Name) -> Self {
1353 Self {
1354 db_name: None,
1355 name,
1356 alias: Some(alias),
1357 }
1358 }
1359}
1360
1361#[derive(Clone, Debug, PartialEq, Eq)]
1363pub struct DistinctNames(IndexSet<Name>);
1364
1365impl DistinctNames {
1366 pub fn new(name: Name) -> Self {
1368 let mut dn = Self(IndexSet::new());
1369 dn.0.insert(name);
1370 dn
1371 }
1372 pub fn single(name: Name) -> Self {
1374 let mut dn = Self(IndexSet::with_capacity(1));
1375 dn.0.insert(name);
1376 dn
1377 }
1378 pub fn insert(&mut self, name: Name) -> Result<(), ParserError> {
1380 if self.0.contains(&name) {
1381 return Err(custom_err!("column \"{}\" specified more than once", name));
1382 }
1383 self.0.insert(name);
1384 Ok(())
1385 }
1386}
1387impl Deref for DistinctNames {
1388 type Target = IndexSet<Name>;
1389
1390 fn deref(&self) -> &IndexSet<Name> {
1391 &self.0
1392 }
1393}
1394
1395#[derive(Clone, Debug, PartialEq, Eq)]
1398pub enum AlterTableBody {
1399 RenameTo(Name),
1401 AddColumn(ColumnDefinition), RenameColumn {
1405 old: Name,
1407 new: Name,
1409 },
1410 DropColumn(Name), }
1413
1414bitflags::bitflags! {
1415 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1417 pub struct TabFlags: u32 {
1418 const HasHidden = 0x00000002;
1421 const HasPrimaryKey = 0x00000004;
1423 const Autoincrement = 0x00000008;
1425 const HasVirtual = 0x00000020;
1428 const HasStored = 0x00000040;
1430 const HasGenerated = 0x00000060;
1432 const WithoutRowid = 0x00000080;
1434 const HasNotNull = 0x00000800;
1441 const Strict = 0x00010000;
1447 }
1448}
1449
1450#[derive(Clone, Debug, PartialEq, Eq)]
1454pub enum CreateTableBody {
1455 ColumnsAndConstraints {
1457 columns: IndexMap<Name, ColumnDefinition>,
1459 constraints: Option<Vec<NamedTableConstraint>>,
1461 flags: TabFlags,
1463 },
1464 AsSelect(Box<Select>),
1466}
1467
1468impl CreateTableBody {
1469 pub fn columns_and_constraints(
1471 columns: IndexMap<Name, ColumnDefinition>,
1472 constraints: Option<Vec<NamedTableConstraint>>,
1473 mut flags: TabFlags,
1474 ) -> Result<Self, ParserError> {
1475 for col in columns.values() {
1476 if col.flags.contains(ColFlags::PRIMKEY) {
1477 flags |= TabFlags::HasPrimaryKey;
1478 }
1479 }
1480 if let Some(ref constraints) = constraints {
1481 for c in constraints {
1482 if let NamedTableConstraint {
1483 constraint: TableConstraint::PrimaryKey { .. },
1484 ..
1485 } = c
1486 {
1487 if flags.contains(TabFlags::HasPrimaryKey) {
1488 #[cfg(feature = "extra_checks")]
1490 return Err(custom_err!("table has more than one primary key"));
1491 } else {
1492 flags |= TabFlags::HasPrimaryKey;
1493 }
1494 }
1495 }
1496 }
1497 Ok(Self::ColumnsAndConstraints {
1498 columns,
1499 constraints,
1500 flags,
1501 })
1502 }
1503}
1504
1505bitflags::bitflags! {
1506 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1508 pub struct ColFlags: u16 {
1509 const PRIMKEY = 0x0001;
1511 const HASTYPE = 0x0004;
1515 const UNIQUE = 0x0008;
1517 const VIRTUAL = 0x0020;
1520 const STORED = 0x0040;
1522 const HASCOLL = 0x0200;
1526 const GENERATED = Self::STORED.bits() | Self::VIRTUAL.bits();
1529 }
1532}
1533
1534#[derive(Clone, Debug, PartialEq, Eq)]
1537pub struct ColumnDefinition {
1538 pub col_name: Name,
1540 pub col_type: Option<Type>,
1542 pub constraints: Vec<NamedColumnConstraint>,
1544 pub flags: ColFlags,
1546}
1547
1548impl ColumnDefinition {
1549 pub fn new(
1551 col_name: Name,
1552 mut col_type: Option<Type>,
1553 constraints: Vec<NamedColumnConstraint>,
1554 ) -> Result<Self, ParserError> {
1555 let mut flags = ColFlags::empty();
1556 #[allow(unused_variables)]
1557 let mut default = false;
1558 for constraint in &constraints {
1559 match &constraint.constraint {
1560 #[allow(unused_assignments)]
1561 ColumnConstraint::Default(..) => {
1562 default = true;
1563 }
1564 ColumnConstraint::Collate { .. } => {
1565 flags |= ColFlags::HASCOLL;
1566 }
1567 ColumnConstraint::Generated { typ, .. } => {
1568 flags |= ColFlags::VIRTUAL;
1569 if let Some(id) = typ {
1570 if id.0.eq_ignore_ascii_case("STORED") {
1571 flags |= ColFlags::STORED;
1572 }
1573 }
1574 }
1575 #[cfg(feature = "extra_checks")]
1576 ColumnConstraint::ForeignKey {
1577 clause:
1578 ForeignKeyClause {
1579 tbl_name, columns, ..
1580 },
1581 ..
1582 } => {
1583 if columns.as_ref().map_or(0, Vec::len) > 1 {
1585 return Err(custom_err!(
1586 "foreign key on {} should reference only one column of table {}",
1587 col_name,
1588 tbl_name
1589 ));
1590 }
1591 }
1592 #[allow(unused_variables)]
1593 ColumnConstraint::PrimaryKey { auto_increment, .. } => {
1594 #[cfg(feature = "extra_checks")]
1595 if *auto_increment
1596 && col_type.as_ref().is_none_or(|t| {
1597 !unquote(t.name.as_str()).0.eq_ignore_ascii_case("INTEGER")
1598 })
1599 {
1600 return Err(custom_err!(
1601 "AUTOINCREMENT is only allowed on an INTEGER PRIMARY KEY"
1602 ));
1603 }
1604 flags |= ColFlags::PRIMKEY | ColFlags::UNIQUE;
1605 }
1606 ColumnConstraint::Unique(..) => {
1607 flags |= ColFlags::UNIQUE;
1608 }
1609 _ => {}
1610 }
1611 }
1612 #[cfg(feature = "extra_checks")]
1613 if flags.contains(ColFlags::PRIMKEY) && flags.intersects(ColFlags::GENERATED) {
1614 return Err(custom_err!(
1615 "generated columns cannot be part of the PRIMARY KEY"
1616 ));
1617 } else if default && flags.intersects(ColFlags::GENERATED) {
1618 return Err(custom_err!("cannot use DEFAULT on a generated column"));
1619 }
1620 if flags.intersects(ColFlags::GENERATED) {
1621 if let Some(ref mut col_type) = col_type {
1623 let mut split = col_type.name.split_ascii_whitespace();
1624 if split
1625 .next_back()
1626 .is_some_and(|s| s.eq_ignore_ascii_case("ALWAYS"))
1627 && split
1628 .next_back()
1629 .is_some_and(|s| s.eq_ignore_ascii_case("GENERATED"))
1630 {
1631 let new_type: Vec<&str> = split.collect();
1633 col_type.name = new_type.join(" ");
1634 }
1635 }
1636 }
1637 if col_type.as_ref().is_some_and(|t| !t.name.is_empty()) {
1638 flags |= ColFlags::HASTYPE;
1639 }
1640 Ok(Self {
1641 col_name,
1642 col_type,
1643 constraints,
1644 flags,
1645 })
1646 }
1647 pub fn add_column(columns: &mut IndexMap<Name, Self>, cd: Self) -> Result<(), ParserError> {
1649 let col_name = &cd.col_name;
1650 if columns.contains_key(col_name) {
1651 return Err(custom_err!("duplicate column name: {}", col_name));
1652 } else if cd.flags.contains(ColFlags::PRIMKEY)
1653 && columns
1654 .values()
1655 .any(|c| c.flags.contains(ColFlags::PRIMKEY))
1656 {
1657 #[cfg(feature = "extra_checks")]
1658 return Err(custom_err!("table has more than one primary key")); }
1660 columns.insert(col_name.clone(), cd);
1661 Ok(())
1662 }
1663}
1664
1665#[derive(Clone, Debug, PartialEq, Eq)]
1668pub struct NamedColumnConstraint {
1669 pub name: Option<Name>,
1671 pub constraint: ColumnConstraint,
1673}
1674
1675#[derive(Clone, Debug, PartialEq, Eq)]
1678pub enum ColumnConstraint {
1679 PrimaryKey {
1681 order: Option<SortOrder>,
1683 conflict_clause: Option<ResolveType>,
1685 auto_increment: bool,
1687 },
1688 NotNull {
1690 nullable: bool,
1692 conflict_clause: Option<ResolveType>,
1694 },
1695 Unique(Option<ResolveType>),
1697 Check(Expr),
1699 Default(Expr),
1701 Defer(DeferSubclause), Collate {
1705 collation_name: Name, },
1708 ForeignKey {
1710 clause: ForeignKeyClause,
1712 deref_clause: Option<DeferSubclause>,
1714 },
1715 Generated {
1717 expr: Expr,
1719 typ: Option<Id>,
1721 },
1722}
1723
1724#[derive(Clone, Debug, PartialEq, Eq)]
1727pub struct NamedTableConstraint {
1728 pub name: Option<Name>,
1730 pub constraint: TableConstraint,
1732}
1733
1734#[derive(Clone, Debug, PartialEq, Eq)]
1737pub enum TableConstraint {
1738 PrimaryKey {
1740 columns: Vec<SortedColumn>,
1742 auto_increment: bool,
1744 conflict_clause: Option<ResolveType>,
1746 },
1747 Unique {
1749 columns: Vec<SortedColumn>,
1751 conflict_clause: Option<ResolveType>,
1753 },
1754 Check(Expr),
1756 ForeignKey {
1758 columns: Vec<IndexedColumn>,
1760 clause: ForeignKeyClause,
1762 deref_clause: Option<DeferSubclause>,
1764 },
1765}
1766
1767impl TableConstraint {
1768 pub fn primary_key(
1770 columns: Vec<SortedColumn>,
1771 auto_increment: bool,
1772 conflict_clause: Option<ResolveType>,
1773 ) -> Result<Self, ParserError> {
1774 has_expression(&columns)?;
1775 has_explicit_nulls(&columns)?;
1776 Ok(Self::PrimaryKey {
1777 columns,
1778 auto_increment,
1779 conflict_clause,
1780 })
1781 }
1782 pub fn unique(
1784 columns: Vec<SortedColumn>,
1785 conflict_clause: Option<ResolveType>,
1786 ) -> Result<Self, ParserError> {
1787 has_expression(&columns)?;
1788 has_explicit_nulls(&columns)?;
1789 Ok(Self::Unique {
1790 columns,
1791 conflict_clause,
1792 })
1793 }
1794}
1795
1796#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1798pub enum SortOrder {
1799 Asc,
1801 Desc,
1803}
1804
1805#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1807pub enum NullsOrder {
1808 First,
1810 Last,
1812}
1813
1814#[derive(Clone, Debug, PartialEq, Eq)]
1817pub struct ForeignKeyClause {
1818 pub tbl_name: Name,
1820 pub columns: Option<Vec<IndexedColumn>>,
1822 pub args: Vec<RefArg>,
1824}
1825
1826#[derive(Clone, Debug, PartialEq, Eq)]
1828pub enum RefArg {
1829 OnDelete(RefAct),
1831 OnInsert(RefAct),
1833 OnUpdate(RefAct),
1835 Match(Name),
1837}
1838
1839#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1841pub enum RefAct {
1842 SetNull,
1844 SetDefault,
1846 Cascade,
1848 Restrict,
1850 NoAction,
1852}
1853
1854#[derive(Clone, Debug, PartialEq, Eq)]
1856pub struct DeferSubclause {
1857 pub deferrable: bool,
1859 pub init_deferred: Option<InitDeferredPred>,
1861}
1862
1863#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1865pub enum InitDeferredPred {
1866 InitiallyDeferred,
1868 InitiallyImmediate, }
1871
1872#[derive(Clone, Debug, PartialEq, Eq)]
1875pub struct IndexedColumn {
1876 pub col_name: Name,
1878 pub collation_name: Option<Name>, pub order: Option<SortOrder>,
1882}
1883
1884#[derive(Clone, Debug, PartialEq, Eq)]
1886pub enum Indexed {
1887 IndexedBy(Name),
1889 NotIndexed,
1891}
1892
1893#[derive(Clone, Debug, PartialEq, Eq)]
1895pub struct SortedColumn {
1896 pub expr: Expr,
1898 pub order: Option<SortOrder>,
1900 pub nulls: Option<NullsOrder>,
1902}
1903
1904fn has_expression(columns: &Vec<SortedColumn>) -> Result<(), ParserError> {
1905 for _column in columns {
1906 if false {
1907 return Err(custom_err!(
1908 "expressions prohibited in PRIMARY KEY and UNIQUE constraints"
1909 ));
1910 }
1911 }
1912 Ok(())
1913}
1914#[allow(unused_variables)]
1915fn has_explicit_nulls(columns: &[SortedColumn]) -> Result<(), ParserError> {
1916 #[cfg(feature = "extra_checks")]
1917 for column in columns {
1918 if let Some(ref nulls) = column.nulls {
1919 return Err(custom_err!(
1920 "unsupported use of NULLS {}",
1921 if *nulls == NullsOrder::First {
1922 "FIRST"
1923 } else {
1924 "LAST"
1925 }
1926 ));
1927 }
1928 }
1929 Ok(())
1930}
1931
1932#[derive(Clone, Debug, PartialEq, Eq)]
1934pub struct Limit {
1935 pub expr: Expr,
1937 pub offset: Option<Expr>, }
1940
1941#[derive(Clone, Debug, PartialEq, Eq)]
1945pub enum InsertBody {
1946 Select(Box<Select>, Option<Box<Upsert>>),
1948 DefaultValues,
1950}
1951
1952#[derive(Clone, Debug, PartialEq, Eq)]
1954pub struct Set {
1955 pub col_names: DistinctNames,
1957 pub expr: Expr,
1959}
1960
1961#[derive(Clone, Debug, PartialEq, Eq)]
1964pub enum PragmaBody {
1965 Equals(PragmaValue),
1967 Call(PragmaValue),
1969}
1970
1971pub type PragmaValue = Expr; #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1977pub enum TriggerTime {
1978 Before, After,
1982 InsteadOf,
1984}
1985
1986#[derive(Clone, Debug, PartialEq, Eq)]
1988pub enum TriggerEvent {
1989 Delete,
1991 Insert,
1993 Update,
1995 UpdateOf(DistinctNames),
1997}
1998
1999#[derive(Clone, Debug, PartialEq, Eq)]
2003pub enum TriggerCmd {
2004 Update {
2006 or_conflict: Option<ResolveType>,
2008 tbl_name: Name,
2010 sets: Vec<Set>, from: Option<FromClause>,
2014 where_clause: Option<Expr>,
2016 },
2017 Insert {
2019 or_conflict: Option<ResolveType>,
2021 tbl_name: Name,
2023 col_names: Option<DistinctNames>,
2025 select: Box<Select>,
2027 upsert: Option<Box<Upsert>>,
2029 },
2030 Delete {
2032 tbl_name: Name,
2034 where_clause: Option<Expr>,
2036 },
2037 Select(Box<Select>),
2039}
2040
2041#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2043pub enum ResolveType {
2044 Rollback,
2046 Abort, Fail,
2050 Ignore,
2052 Replace,
2054}
2055
2056#[derive(Clone, Debug, PartialEq, Eq)]
2060pub struct With {
2061 pub recursive: bool,
2063 pub ctes: Vec<CommonTableExpr>,
2065}
2066
2067#[derive(Clone, Debug, PartialEq, Eq)]
2069pub enum Materialized {
2070 Any,
2072 Yes,
2074 No,
2076}
2077
2078#[derive(Clone, Debug, PartialEq, Eq)]
2081pub struct CommonTableExpr {
2082 pub tbl_name: Name,
2084 pub columns: Option<Vec<IndexedColumn>>, pub materialized: Materialized,
2088 pub select: Box<Select>,
2090}
2091
2092impl CommonTableExpr {
2093 pub fn new(
2095 tbl_name: Name,
2096 columns: Option<Vec<IndexedColumn>>,
2097 materialized: Materialized,
2098 select: Select,
2099 ) -> Result<Self, ParserError> {
2100 #[cfg(feature = "extra_checks")]
2101 if let Some(ref columns) = columns {
2102 if let check::ColumnCount::Fixed(cc) = select.column_count() {
2103 if cc as usize != columns.len() {
2104 return Err(custom_err!(
2105 "table {} has {} values for {} columns",
2106 tbl_name,
2107 cc,
2108 columns.len()
2109 ));
2110 }
2111 }
2112 }
2113 Ok(Self {
2114 tbl_name,
2115 columns,
2116 materialized,
2117 select: Box::new(select),
2118 })
2119 }
2120 pub fn add_cte(ctes: &mut Vec<Self>, cte: Self) -> Result<(), ParserError> {
2122 #[cfg(feature = "extra_checks")]
2123 if ctes.iter().any(|c| c.tbl_name == cte.tbl_name) {
2124 return Err(custom_err!("duplicate WITH table name: {}", cte.tbl_name));
2125 }
2126 ctes.push(cte);
2127 Ok(())
2128 }
2129}
2130
2131#[derive(Clone, Debug, PartialEq, Eq)]
2134pub struct Type {
2135 pub name: String, pub size: Option<TypeSize>,
2139}
2140
2141#[derive(Clone, Debug, PartialEq, Eq)]
2144pub enum TypeSize {
2145 MaxSize(Box<Expr>),
2147 TypeSize(Box<Expr>, Box<Expr>),
2149}
2150
2151#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2153pub enum TransactionType {
2154 Deferred, Immediate,
2158 Exclusive,
2160}
2161
2162#[derive(Clone, Debug, PartialEq, Eq)]
2166pub struct Upsert {
2167 pub index: Option<UpsertIndex>,
2169 pub do_clause: UpsertDo,
2171 pub next: Option<Box<Upsert>>,
2173}
2174
2175#[derive(Clone, Debug, PartialEq, Eq)]
2177pub struct UpsertIndex {
2178 pub targets: Vec<SortedColumn>,
2180 pub where_clause: Option<Expr>,
2182}
2183
2184impl UpsertIndex {
2185 pub fn new(
2187 targets: Vec<SortedColumn>,
2188 where_clause: Option<Expr>,
2189 ) -> Result<Self, ParserError> {
2190 has_explicit_nulls(&targets)?;
2191 Ok(Self {
2192 targets,
2193 where_clause,
2194 })
2195 }
2196}
2197
2198#[derive(Clone, Debug, PartialEq, Eq)]
2200pub enum UpsertDo {
2201 Set {
2203 sets: Vec<Set>,
2205 where_clause: Option<Expr>,
2207 },
2208 Nothing,
2210}
2211
2212#[derive(Clone, Debug, PartialEq, Eq)]
2214pub struct FunctionTail {
2215 pub filter_clause: Option<Box<Expr>>,
2217 pub over_clause: Option<Box<Over>>,
2219}
2220
2221#[derive(Clone, Debug, PartialEq, Eq)]
2224pub enum Over {
2225 Window(Box<Window>),
2227 Name(Name),
2229}
2230
2231#[derive(Clone, Debug, PartialEq, Eq)]
2233pub struct WindowDef {
2234 pub name: Name,
2236 pub window: Window,
2238}
2239
2240#[derive(Clone, Debug, PartialEq, Eq)]
2243pub struct Window {
2244 pub base: Option<Name>,
2246 pub partition_by: Option<Vec<Expr>>,
2248 pub order_by: Option<Vec<SortedColumn>>,
2250 pub frame_clause: Option<FrameClause>,
2252}
2253
2254#[derive(Clone, Debug, PartialEq, Eq)]
2257pub struct FrameClause {
2258 pub mode: FrameMode,
2260 pub start: FrameBound,
2262 pub end: Option<FrameBound>,
2264 pub exclude: Option<FrameExclude>,
2266}
2267
2268#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2270pub enum FrameMode {
2271 Groups,
2273 Range,
2275 Rows,
2277}
2278
2279#[derive(Clone, Debug, PartialEq, Eq)]
2281pub enum FrameBound {
2282 CurrentRow,
2284 Following(Expr),
2286 Preceding(Expr),
2288 UnboundedFollowing,
2290 UnboundedPreceding,
2292}
2293
2294#[derive(Clone, Debug, PartialEq, Eq)]
2296pub enum FrameExclude {
2297 NoOthers,
2299 CurrentRow,
2301 Group,
2303 Ties,
2305}
2306
2307#[cfg(test)]
2308mod test {
2309 use super::Name;
2310
2311 #[test]
2312 fn test_dequote() {
2313 assert_eq!(name("x"), "x");
2314 assert_eq!(name("`x`"), "x");
2315 assert_eq!(name("`x``y`"), "x`y");
2316 assert_eq!(name(r#""x""#), "x");
2317 assert_eq!(name(r#""x""y""#), "x\"y");
2318 assert_eq!(name("[x]"), "x");
2319 }
2320
2321 fn name(s: &'static str) -> Name {
2322 Name(s.into())
2323 }
2324}