1use alloc::vec::Vec;
13
14use crate::{
15 expression::{parse_expression, Expression},
16 keywords::Keyword,
17 lexer::Token,
18 parser::{ParseError, Parser},
19 qualified_name::parse_qualified_name,
20 select::{parse_select, parse_select_expr, Select, SelectExpr},
21 Identifier, OptSpanned, QualifiedName, Span, Spanned,
22};
23
24#[derive(Clone, Debug)]
26pub enum InsertReplaceFlag {
27 LowPriority(Span),
28 HighPriority(Span),
29 Delayed(Span),
30 Ignore(Span),
31}
32
33impl Spanned for InsertReplaceFlag {
34 fn span(&self) -> Span {
35 match &self {
36 InsertReplaceFlag::LowPriority(v) => v.span(),
37 InsertReplaceFlag::HighPriority(v) => v.span(),
38 InsertReplaceFlag::Delayed(v) => v.span(),
39 InsertReplaceFlag::Ignore(v) => v.span(),
40 }
41 }
42}
43
44#[derive(Clone, Debug)]
45pub enum InsertReplaceType {
46 Insert(Span),
47 Replace(Span),
48}
49
50impl Spanned for InsertReplaceType {
51 fn span(&self) -> Span {
52 match self {
53 InsertReplaceType::Insert(a) => a.clone(),
54 InsertReplaceType::Replace(a) => a.clone(),
55 }
56 }
57}
58
59#[derive(Clone, Debug)]
60pub enum OnConflictTarget<'a> {
61 Column {
62 name: Identifier<'a>,
63 },
64 OnConstraint {
65 on_constraint_span: Span,
66 name: Identifier<'a>,
67 },
68 None,
69}
70
71impl<'a> OptSpanned for OnConflictTarget<'a> {
72 fn opt_span(&self) -> Option<Span> {
73 match self {
74 OnConflictTarget::Column { name } => Some(name.span()),
75 OnConflictTarget::OnConstraint {
76 on_constraint_span: token,
77 name,
78 } => Some(token.join_span(name)),
79 OnConflictTarget::None => None,
80 }
81 }
82}
83
84#[derive(Clone, Debug)]
85pub enum OnConflictAction<'a> {
86 DoNothing(Span),
87 DoUpdateSet {
88 do_update_set_span: Span,
89 sets: Vec<(Identifier<'a>, Expression<'a>)>,
90 where_: Option<(Span, alloc::boxed::Box<Expression<'a>>)>,
91 },
92}
93
94impl<'a> Spanned for OnConflictAction<'a> {
95 fn span(&self) -> Span {
96 match self {
97 OnConflictAction::DoNothing(span) => span.span(),
98 OnConflictAction::DoUpdateSet {
99 do_update_set_span,
100 sets,
101 where_,
102 } => do_update_set_span.join_span(sets).join_span(where_),
103 }
104 }
105}
106
107#[derive(Clone, Debug)]
108pub struct OnConflict<'a> {
109 pub on_conflict_span: Span,
110 pub target: OnConflictTarget<'a>,
111 pub action: OnConflictAction<'a>,
112}
113
114impl<'a> Spanned for OnConflict<'a> {
115 fn span(&self) -> Span {
116 self.on_conflict_span
117 .join_span(&self.target)
118 .join_span(&self.action)
119 }
120}
121
122#[derive(Clone, Debug)]
123pub struct InsertReplaceSetPair<'a> {
124 pub column: Identifier<'a>,
125 pub equal_span: Span,
126 pub value: Expression<'a>,
127}
128
129impl<'a> Spanned for InsertReplaceSetPair<'a> {
130 fn span(&self) -> Span {
131 self.column
132 .join_span(&self.equal_span)
133 .join_span(&self.value)
134 }
135}
136
137#[derive(Clone, Debug)]
138pub struct InsertReplaceSet<'a> {
139 pub set_span: Span,
140 pub pairs: Vec<InsertReplaceSetPair<'a>>,
141}
142
143impl<'a> Spanned for InsertReplaceSet<'a> {
144 fn span(&self) -> Span {
145 self.set_span.join_span(&self.pairs)
146 }
147}
148
149#[derive(Clone, Debug)]
150pub struct InsertReplaceOnDuplicateKeyUpdate<'a> {
151 pub on_duplicate_key_update_span: Span,
152 pub pairs: Vec<InsertReplaceSetPair<'a>>,
153}
154
155impl<'a> Spanned for InsertReplaceOnDuplicateKeyUpdate<'a> {
156 fn span(&self) -> Span {
157 self.on_duplicate_key_update_span.join_span(&self.pairs)
158 }
159}
160
161#[derive(Clone, Debug)]
220pub struct InsertReplace<'a> {
221 pub type_: InsertReplaceType,
223 pub flags: Vec<InsertReplaceFlag>,
225 pub into_span: Option<Span>,
227 pub table: QualifiedName<'a>,
229 pub columns: Vec<Identifier<'a>>,
231 pub values: Option<(Span, Vec<Vec<Expression<'a>>>)>,
233 pub select: Option<Select<'a>>,
235 pub set: Option<InsertReplaceSet<'a>>,
237 pub on_duplicate_key_update: Option<InsertReplaceOnDuplicateKeyUpdate<'a>>,
239 pub on_conflict: Option<OnConflict<'a>>,
241 pub returning: Option<(Span, Vec<SelectExpr<'a>>)>,
243}
244
245impl<'a> Spanned for InsertReplace<'a> {
246 fn span(&self) -> Span {
247 self.type_
248 .join_span(&self.flags)
249 .join_span(&self.into_span)
250 .join_span(&self.table)
251 .join_span(&self.values)
252 .join_span(&self.select)
253 .join_span(&self.set)
254 .join_span(&self.on_duplicate_key_update)
255 .join_span(&self.on_conflict)
256 .join_span(&self.returning)
257 }
258}
259
260pub(crate) fn parse_insert_replace<'a>(
261 parser: &mut Parser<'a, '_>,
262) -> Result<InsertReplace<'a>, ParseError> {
263 let type_ = match &parser.token {
264 Token::Ident(_, Keyword::INSERT) => InsertReplaceType::Insert(parser.consume()),
265 Token::Ident(_, Keyword::REPLACE) => InsertReplaceType::Replace(parser.consume()),
266 _ => parser.expected_failure("INSERT or REPLACE")?,
267 };
268
269 let insert = matches!(type_, InsertReplaceType::Insert(_));
270
271 let mut flags = Vec::new();
272 loop {
273 match &parser.token {
274 Token::Ident(_, Keyword::LOW_PRIORITY) => flags.push(InsertReplaceFlag::LowPriority(
275 parser.consume_keyword(Keyword::LOW_PRIORITY)?,
276 )),
277 Token::Ident(_, Keyword::HIGH_PRIORITY) => flags.push(InsertReplaceFlag::HighPriority(
278 parser.consume_keyword(Keyword::HIGH_PRIORITY)?,
279 )),
280 Token::Ident(_, Keyword::DELAYED) => flags.push(InsertReplaceFlag::Delayed(
281 parser.consume_keyword(Keyword::DELAYED)?,
282 )),
283 Token::Ident(_, Keyword::IGNORE) => flags.push(InsertReplaceFlag::Ignore(
284 parser.consume_keyword(Keyword::IGNORE)?,
285 )),
286 _ => break,
287 }
288 }
289
290 for flag in &flags {
291 match flag {
292 InsertReplaceFlag::LowPriority(_) => {}
293 InsertReplaceFlag::HighPriority(s) => {
294 if !insert {
295 parser.err("Not supported for replace", s);
296 }
297 }
298 InsertReplaceFlag::Delayed(_) => {}
299 InsertReplaceFlag::Ignore(s) => {
300 if !insert {
301 parser.err("Not supported for replace", s);
302 }
303 }
304 }
305 }
306
307 let into_span = parser.skip_keyword(Keyword::INTO);
308 let table = parse_qualified_name(parser)?;
309 let mut columns = Vec::new();
312 if parser.skip_token(Token::LParen).is_some() {
313 parser.recovered(")", &|t| t == &Token::RParen, |parser| {
314 loop {
315 columns.push(parser.consume_plain_identifier()?);
316 if parser.skip_token(Token::Comma).is_none() {
317 break;
318 }
319 }
320 Ok(())
321 })?;
322 parser.consume_token(Token::RParen)?;
323 }
324
325 let mut select = None;
326 let mut values = None;
327 let mut set = None;
328 match &parser.token {
329 Token::Ident(_, Keyword::SELECT) => {
330 select = Some(parse_select(parser)?);
331 }
332 Token::Ident(_, Keyword::VALUE | Keyword::VALUES) => {
333 let values_span = parser.consume();
334 let mut values_items = Vec::new();
335 loop {
336 let mut vals = Vec::new();
337 parser.consume_token(Token::LParen)?;
338 parser.recovered(")", &|t| t == &Token::RParen, |parser| {
339 loop {
340 vals.push(parse_expression(parser, false)?);
341 if parser.skip_token(Token::Comma).is_none() {
342 break;
343 }
344 }
345 Ok(())
346 })?;
347 parser.consume_token(Token::RParen)?;
348 values_items.push(vals);
349 if parser.skip_token(Token::Comma).is_none() {
350 break;
351 }
352 }
353 values = Some((values_span, values_items));
354 }
355 Token::Ident(_, Keyword::SET) => {
356 let set_span = parser.consume_keyword(Keyword::SET)?;
357 let mut pairs = Vec::new();
358 loop {
359 let column = parser.consume_plain_identifier()?;
360 let equal_span = parser.consume_token(Token::Eq)?;
361 let value: Expression<'_> = parse_expression(parser, false)?;
362 pairs.push(InsertReplaceSetPair {
363 column,
364 equal_span,
365 value,
366 });
367 if parser.skip_token(Token::Comma).is_none() {
368 break;
369 }
370 }
371 if let Some(cs) = columns.opt_span() {
372 parser
373 .err("Columns may not be used here", &cs)
374 .frag("Together with SET", &set_span);
375 }
376 set = Some(InsertReplaceSet { set_span, pairs });
377 }
378 _ => {
379 parser.expected_error("VALUE, VALUES, SELECT or SET");
380 }
381 }
382
383 let (on_duplicate_key_update, on_conflict) =
384 if matches!(parser.token, Token::Ident(_, Keyword::ON)) {
385 let on = parser.consume_keyword(Keyword::ON)?;
386 match &parser.token {
387 Token::Ident(_, Keyword::DUPLICATE) => {
388 let on_duplicate_key_update_span =
389 on.join_span(&parser.consume_keywords(&[
390 Keyword::DUPLICATE,
391 Keyword::KEY,
392 Keyword::UPDATE,
393 ])?);
394 let mut pairs = Vec::new();
395 loop {
396 let column = parser.consume_plain_identifier()?;
397 let equal_span = parser.consume_token(Token::Eq)?;
398 let value = parse_expression(parser, false)?;
399 pairs.push(InsertReplaceSetPair {
400 column,
401 equal_span,
402 value,
403 });
404 if parser.skip_token(Token::Comma).is_none() {
405 break;
406 }
407 }
408 if !parser.options.dialect.is_maria() {
409 parser.err(
410 "Only support by mariadb",
411 &on_duplicate_key_update_span.join_span(&pairs),
412 );
413 }
414 (
415 Some(InsertReplaceOnDuplicateKeyUpdate {
416 on_duplicate_key_update_span,
417 pairs,
418 }),
419 None,
420 )
421 }
422 Token::Ident(_, Keyword::CONFLICT) => {
423 let on_conflict_span =
424 on.join_span(&parser.consume_keyword(Keyword::CONFLICT)?);
425
426 let target = match &parser.token {
427 Token::LParen => {
428 parser.consume_token(Token::LParen)?;
429 let name = parser.consume_plain_identifier()?;
430 parser.consume_token(Token::RParen)?;
431 OnConflictTarget::Column { name }
432 }
433 Token::Ident(_, Keyword::ON) => {
434 let on_constraint =
435 parser.consume_keywords(&[Keyword::ON, Keyword::CONSTRAINT])?;
436 let name = parser.consume_plain_identifier()?;
437 OnConflictTarget::OnConstraint {
438 on_constraint_span: on_constraint,
439 name,
440 }
441 }
442 _ => OnConflictTarget::None,
443 };
444
445 let do_ = parser.consume_keyword(Keyword::DO)?;
446 let action = match &parser.token {
447 Token::Ident(_, Keyword::NOTHING) => OnConflictAction::DoNothing(
448 do_.join_span(&parser.consume_keyword(Keyword::NOTHING)?),
449 ),
450 Token::Ident(_, Keyword::UPDATE) => {
451 let do_update_set_span = do_.join_span(
452 &parser.consume_keywords(&[Keyword::UPDATE, Keyword::SET])?,
453 );
454 let mut sets = Vec::new();
455 loop {
456 let name = parser.consume_plain_identifier()?;
457 parser.consume_token(Token::Eq)?;
458 let expr = parse_expression(parser, false)?;
459 sets.push((name, expr));
460 if parser.skip_token(Token::Comma).is_none() {
461 break;
462 }
463 }
464 let where_ = if matches!(parser.token, Token::Ident(_, Keyword::WHERE))
465 {
466 let where_span = parser.consume_keyword(Keyword::WHERE)?;
467 let where_expr =
468 alloc::boxed::Box::new(parse_expression(parser, false)?);
469 Some((where_span, where_expr))
470 } else {
471 None
472 };
473 OnConflictAction::DoUpdateSet {
474 do_update_set_span,
475 sets,
476 where_,
477 }
478 }
479 _ => parser.expected_failure("'NOTHING' or 'UPDATE'")?,
480 };
481
482 let on_conflict = OnConflict {
483 on_conflict_span,
484 target,
485 action,
486 };
487
488 if !parser.options.dialect.is_postgresql() {
489 parser.err("Only support by postgesql", &on_conflict);
490 }
491
492 (None, Some(on_conflict))
493 }
494 _ => parser.expected_failure("'DUPLICATE' OR 'CONFLICT'")?,
495 }
496 } else {
497 (None, None)
498 };
499
500 let returning = if let Some(returning_span) = parser.skip_keyword(Keyword::RETURNING) {
501 let mut returning_exprs = Vec::new();
502 loop {
503 returning_exprs.push(parse_select_expr(parser)?);
504 if parser.skip_token(Token::Comma).is_none() {
505 break;
506 }
507 }
508 Some((returning_span, returning_exprs))
509 } else {
510 None
511 };
512
513 Ok(InsertReplace {
514 type_,
515 flags,
516 table,
517 columns,
518 into_span,
519 values,
520 select,
521 set,
522 on_duplicate_key_update,
523 on_conflict,
524 returning,
525 })
526}