1use alloc::vec::Vec;
14
15use crate::{
16 expression::{parse_expression, Expression},
17 keywords::Keyword,
18 lexer::Token,
19 parser::{ParseError, Parser},
20 qualified_name::parse_qualified_name,
21 select::{parse_select_expr, parse_table_reference},
22 QualifiedName, SelectExpr, Span, Spanned, TableReference,
23};
24
25#[derive(Clone, Debug)]
27pub enum DeleteFlag {
28 LowPriority(Span),
29 Quick(Span),
30 Ignore(Span),
31}
32
33impl Spanned for DeleteFlag {
34 fn span(&self) -> Span {
35 match &self {
36 DeleteFlag::LowPriority(v) => v.span(),
37 DeleteFlag::Quick(v) => v.span(),
38 DeleteFlag::Ignore(v) => v.span(),
39 }
40 }
41}
42
43#[derive(Clone, Debug)]
68pub struct Delete<'a> {
69 pub delete_span: Span,
71 pub flags: Vec<DeleteFlag>,
73 pub from_span: Span,
75 pub tables: Vec<QualifiedName<'a>>,
77 pub using: Vec<TableReference<'a>>,
79 pub where_: Option<(Expression<'a>, Span)>,
81 pub returning: Option<(Span, Vec<SelectExpr<'a>>)>,
83}
84
85impl<'a> Spanned for Delete<'a> {
86 fn span(&self) -> Span {
87 self.delete_span
88 .join_span(&self.flags)
89 .join_span(&self.from_span)
90 .join_span(&self.tables)
91 .join_span(&self.using)
92 .join_span(&self.where_)
93 .join_span(&self.returning)
94 }
95}
96
97pub(crate) fn parse_delete<'a>(parser: &mut Parser<'a, '_>) -> Result<Delete<'a>, ParseError> {
98 let delete_span = parser.consume_keyword(Keyword::DELETE)?;
99 let mut flags = Vec::new();
100
101 loop {
102 match &parser.token {
103 Token::Ident(_, Keyword::LOW_PRIORITY) => flags.push(DeleteFlag::LowPriority(
104 parser.consume_keyword(Keyword::LOW_PRIORITY)?,
105 )),
106 Token::Ident(_, Keyword::QUICK) => {
107 flags.push(DeleteFlag::Quick(parser.consume_keyword(Keyword::QUICK)?))
108 }
109 Token::Ident(_, Keyword::IGNORE) => {
110 flags.push(DeleteFlag::Ignore(parser.consume_keyword(Keyword::IGNORE)?))
111 }
112 _ => break,
113 }
114 }
115
116 let mut tables = Vec::new();
117 let mut using = Vec::new();
118 let from_span = if let Some(from_span) = parser.skip_keyword(Keyword::FROM) {
119 loop {
120 tables.push(parse_qualified_name(parser)?);
121 if parser.skip_token(Token::Comma).is_none() {
122 break;
123 }
124 }
125 from_span
126 } else {
127 loop {
128 tables.push(parse_qualified_name(parser)?);
129 if parser.skip_token(Token::Comma).is_none() {
130 break;
131 }
132 }
133 let from_span = parser.consume_keyword(Keyword::FROM)?;
134 loop {
135 using.push(parse_table_reference(parser)?);
136 if parser.skip_token(Token::Comma).is_none() {
137 break;
138 }
139 }
140 from_span
141 };
142
143 if let Some(using_span) = parser.skip_keyword(Keyword::USING) {
147 if !using.is_empty() {
148 parser.err(
149 "Using not allowed in delete with table names before FROM",
150 &using_span,
151 );
152 }
153 loop {
154 using.push(parse_table_reference(parser)?);
155 if parser.skip_token(Token::Comma).is_none() {
156 break;
157 }
158 }
159 }
160
161 let where_ = if let Some(span) = parser.skip_keyword(Keyword::WHERE) {
162 Some((parse_expression(parser, false)?, span))
163 } else {
164 None
165 };
166 let returning = if let Some(returning_span) = parser.skip_keyword(Keyword::RETURNING) {
170 let mut returning_exprs = Vec::new();
171 loop {
172 returning_exprs.push(parse_select_expr(parser)?);
173 if parser.skip_token(Token::Comma).is_none() {
174 break;
175 }
176 }
177 Some((returning_span, returning_exprs))
178 } else {
179 None
180 };
181
182 Ok(Delete {
183 flags,
184 delete_span,
185 tables,
186 using,
187 from_span,
188 where_,
189 returning,
190 })
191}