1use super::error::ParseError;
4use super::Parser;
5use crate::ast::{
6 AlterQueueQuery, CreateQueueQuery, DropQueueQuery, QueryExpr, QueueAvailability, QueueCommand,
7 QueueMode, QueueSide, DEFAULT_QUEUE_IN_FLIGHT_CAP_PER_GROUP, DEFAULT_QUEUE_LOCK_DEADLINE_MS,
8 DEFAULT_QUEUE_MAX_ATTEMPTS,
9};
10use crate::lexer::Token;
11
12impl<'a> Parser<'a> {
13 pub fn parse_create_queue_body(&mut self) -> Result<QueryExpr, ParseError> {
15 let if_not_exists = self.match_if_not_exists()?;
16 let name = self.expect_ident()?;
17
18 let mut mode = QueueMode::Work;
19 let mut priority = false;
20 let mut max_size = None;
21 let mut ttl_ms = None;
22 let mut dlq = None;
23 let mut max_attempts = DEFAULT_QUEUE_MAX_ATTEMPTS;
24 let mut lock_deadline_ms = DEFAULT_QUEUE_LOCK_DEADLINE_MS;
25 let mut in_flight_cap_per_group = DEFAULT_QUEUE_IN_FLIGHT_CAP_PER_GROUP;
26 let mut retry_delay_ms: Option<u64> = None;
27 let mut dedup_window_ms: Option<u64> = None;
28
29 loop {
31 if let Some(parsed_mode) = self.consume_queue_mode()? {
32 mode = parsed_mode;
33 } else if self.consume(&Token::Priority)? {
34 priority = true;
35 } else if self.consume_ident_ci("MAX_SIZE")? || self.consume_ident_ci("MAXSIZE")? {
36 max_size = Some(self.parse_positive_integer("MAX_SIZE")? as usize);
37 } else if self.consume_ident_ci("MAX_ATTEMPTS")?
38 || self.consume_ident_ci("MAXATTEMPTS")?
39 {
40 max_attempts = self.parse_integer()?.max(1) as u32;
41 } else if self.consume_ident_ci("LOCK_DEADLINE_MS")? {
42 lock_deadline_ms = self.parse_integer()?.max(1) as u64;
43 } else if self.consume_ident_ci("IN_FLIGHT_CAP_PER_GROUP")? {
44 in_flight_cap_per_group = self.parse_integer()?.max(1) as u32;
45 } else if self.consume_ident_ci("RETRY_DELAY")? {
46 let value = self.parse_float()?;
47 let unit = self.parse_queue_duration_unit()?;
48 retry_delay_ms = Some((value * unit).max(0.0) as u64);
49 } else if self.consume_ident_ci("DEDUP_WINDOW")? {
50 let value = self.parse_float()?;
51 let unit = self.parse_queue_duration_unit()?;
52 dedup_window_ms = Some((value * unit).max(0.0) as u64);
53 } else if self.consume(&Token::With)? {
54 if self.consume_ident_ci("EVENTS")? {
55 return Err(ParseError::new(
56 "queues cannot have event subscriptions".to_string(),
57 self.position(),
58 ));
59 } else if self.consume_ident_ci("TTL")? {
60 let value = self.parse_float()?;
61 let unit = self.parse_queue_duration_unit()?;
62 ttl_ms = Some((value * unit) as u64);
63 } else if self.consume_ident_ci("DLQ")? {
64 dlq = Some(self.expect_ident()?);
65 }
66 } else {
67 break;
68 }
69 }
70
71 Ok(QueryExpr::CreateQueue(CreateQueueQuery {
72 name,
73 mode,
74 priority,
75 max_size,
76 ttl_ms,
77 dlq,
78 max_attempts,
79 lock_deadline_ms,
80 in_flight_cap_per_group,
81 if_not_exists,
82 retry_delay_ms,
83 dedup_window_ms,
84 }))
85 }
86
87 pub fn parse_alter_queue_body(&mut self) -> Result<QueryExpr, ParseError> {
96 let name = self.expect_ident()?;
97 if !self.consume(&Token::Set)? && !self.consume_ident_ci("SET")? {
98 return Err(ParseError::expected(
99 vec!["SET"],
100 self.peek(),
101 self.position(),
102 ));
103 }
104
105 let mut alter = AlterQueueQuery {
106 name,
107 ..Default::default()
108 };
109
110 if self.consume(&Token::Mode)? || self.consume_ident_ci("MODE")? {
111 alter.mode = Some(self.parse_queue_mode()?);
112 } else if self.consume_ident_ci("MAX_ATTEMPTS")? || self.consume_ident_ci("MAXATTEMPTS")? {
113 alter.max_attempts = Some(self.parse_integer()?.max(1) as u32);
114 } else if self.consume_ident_ci("LOCK_DEADLINE_MS")? {
115 alter.lock_deadline_ms = Some(self.parse_integer()?.max(1) as u64);
116 } else if self.consume_ident_ci("IN_FLIGHT_CAP_PER_GROUP")? {
117 alter.in_flight_cap_per_group = Some(self.parse_integer()?.max(1) as u32);
118 } else if self.consume_ident_ci("DLQ")? {
119 alter.dlq = Some(self.expect_ident()?);
120 } else if self.consume_ident_ci("RETRY_DELAY")? {
121 let value = self.parse_float()?;
122 let unit = self.parse_queue_duration_unit()?;
123 alter.retry_delay_ms = Some((value * unit).max(0.0) as u64);
124 } else if self.consume_ident_ci("DEDUP_WINDOW")? {
125 let value = self.parse_float()?;
126 let unit = self.parse_queue_duration_unit()?;
127 alter.dedup_window_ms = Some((value * unit).max(0.0) as u64);
128 } else {
129 return Err(ParseError::expected(
130 vec![
131 "MODE",
132 "MAX_ATTEMPTS",
133 "LOCK_DEADLINE_MS",
134 "IN_FLIGHT_CAP_PER_GROUP",
135 "DLQ",
136 "RETRY_DELAY",
137 "DEDUP_WINDOW",
138 ],
139 self.peek(),
140 self.position(),
141 ));
142 }
143
144 Ok(QueryExpr::AlterQueue(alter))
145 }
146
147 pub fn parse_drop_queue_body(&mut self) -> Result<QueryExpr, ParseError> {
149 let if_exists = self.match_if_exists()?;
150 let name = self.parse_drop_collection_name()?;
151 Ok(QueryExpr::DropQueue(DropQueueQuery { name, if_exists }))
152 }
153
154 pub fn parse_queue_command(&mut self) -> Result<QueryExpr, ParseError> {
156 self.expect(Token::Queue)?;
157
158 match self.peek().clone() {
159 Token::Push => {
160 self.advance()?;
161 let queue = self.expect_ident()?;
162 let value = self.parse_value()?;
163 let (priority, key, available, dedup_key) = self.parse_push_tail_clauses()?;
164 Ok(QueryExpr::QueueCommand(QueueCommand::Push {
165 queue,
166 value,
167 side: QueueSide::Right,
168 priority,
169 key,
170 available,
171 dedup_key,
172 }))
173 }
174 Token::Pop => {
175 self.advance()?;
176 let queue = self.expect_ident()?;
177 let count = if self.consume(&Token::Count)? {
178 self.parse_integer()? as usize
179 } else {
180 1
181 };
182 self.reject_wait_clause("POP")?;
183 Ok(QueryExpr::QueueCommand(QueueCommand::Pop {
184 queue,
185 side: QueueSide::Left,
186 count,
187 }))
188 }
189 Token::Peek => {
190 self.advance()?;
191 let queue = self.expect_ident()?;
192 let count =
197 if self.consume(&Token::Count)? || matches!(self.peek(), Token::Integer(_)) {
198 self.parse_integer()? as usize
199 } else {
200 1
201 };
202 self.reject_wait_clause("PEEK")?;
203 Ok(QueryExpr::QueueCommand(QueueCommand::Peek { queue, count }))
204 }
205 Token::Ident(ref name) if name.eq_ignore_ascii_case("LEN") => {
206 self.advance()?;
207 let queue = self.expect_ident()?;
208 Ok(QueryExpr::QueueCommand(QueueCommand::Len { queue }))
209 }
210 Token::Ident(ref name) if name.eq_ignore_ascii_case("MOVE") => {
211 self.advance()?;
212 self.expect(Token::From)?;
213 let source = self.expect_ident()?;
214 self.expect(Token::To)?;
215 let destination = self.expect_ident()?;
216 let filter = if self.consume(&Token::Where)? {
217 Some(self.parse_filter()?)
218 } else {
219 None
220 };
221 let limit = if self.consume(&Token::Limit)? {
222 self.parse_positive_integer("LIMIT")? as usize
223 } else if filter.is_some() {
224 return Err(ParseError::expected(
225 vec!["LIMIT"],
226 self.peek(),
227 self.position(),
228 ));
229 } else {
230 1
231 };
232 Ok(QueryExpr::QueueCommand(QueueCommand::Move {
233 source,
234 destination,
235 filter,
236 limit,
237 }))
238 }
239 Token::Purge => {
240 self.advance()?;
241 let queue = self.expect_ident()?;
242 Ok(QueryExpr::QueueCommand(QueueCommand::Purge { queue }))
243 }
244 Token::Ident(ref name) if name.eq_ignore_ascii_case("LPOP") => {
245 self.advance()?;
246 let queue = self.expect_ident()?;
247 Ok(QueryExpr::QueueCommand(QueueCommand::Pop {
248 queue,
249 side: QueueSide::Left,
250 count: 1,
251 }))
252 }
253 Token::Ident(ref name) if name.eq_ignore_ascii_case("RPOP") => {
254 self.advance()?;
255 let queue = self.expect_ident()?;
256 Ok(QueryExpr::QueueCommand(QueueCommand::Pop {
257 queue,
258 side: QueueSide::Right,
259 count: 1,
260 }))
261 }
262 Token::Ident(ref name) if name.eq_ignore_ascii_case("LPUSH") => {
263 self.advance()?;
264 let queue = self.expect_ident()?;
265 let value = self.parse_value()?;
266 let (_priority, key, available, dedup_key) = self.parse_push_tail_clauses()?;
267 Ok(QueryExpr::QueueCommand(QueueCommand::Push {
268 queue,
269 value,
270 side: QueueSide::Left,
271 priority: None,
272 key,
273 available,
274 dedup_key,
275 }))
276 }
277 Token::Ident(ref name) if name.eq_ignore_ascii_case("RPUSH") => {
278 self.advance()?;
279 let queue = self.expect_ident()?;
280 let value = self.parse_value()?;
281 let (priority, key, available, dedup_key) = self.parse_push_tail_clauses()?;
282 Ok(QueryExpr::QueueCommand(QueueCommand::Push {
283 queue,
284 value,
285 side: QueueSide::Right,
286 priority,
287 key,
288 available,
289 dedup_key,
290 }))
291 }
292 Token::Group => {
293 self.advance()?;
294 self.expect(Token::Create)?;
295 let queue = self.expect_ident()?;
296 let group = self.expect_ident()?;
297 Ok(QueryExpr::QueueCommand(QueueCommand::GroupCreate {
298 queue,
299 group,
300 }))
301 }
302 Token::Ident(ref name) if name.eq_ignore_ascii_case("READ") => {
303 self.advance()?;
304 let queue = self.expect_ident()?;
305 let group = if self.consume(&Token::Group)? {
306 Some(self.expect_ident()?)
307 } else {
308 None
309 };
310 if !self.consume_ident_ci("CONSUMER")? {
312 return Err(ParseError::expected(
313 vec!["CONSUMER"],
314 self.peek(),
315 self.position(),
316 ));
317 }
318 let consumer = self.expect_ident()?;
319 let count = if self.consume(&Token::Count)? {
320 self.parse_integer()? as usize
321 } else {
322 1
323 };
324 let wait_ms = self.parse_optional_wait_clause()?;
325 Ok(QueryExpr::QueueCommand(QueueCommand::GroupRead {
326 queue,
327 group,
328 consumer,
329 count,
330 wait_ms,
331 }))
332 }
333 Token::Ident(ref name) if name.eq_ignore_ascii_case("PENDING") => {
334 self.advance()?;
335 let queue = self.expect_ident()?;
336 self.expect(Token::Group)?;
337 let group = self.expect_ident()?;
338 Ok(QueryExpr::QueueCommand(QueueCommand::Pending {
339 queue,
340 group,
341 }))
342 }
343 Token::Ident(ref name) if name.eq_ignore_ascii_case("CLAIM") => {
344 self.advance()?;
345 let queue = self.expect_ident()?;
346 self.expect(Token::Group)?;
347 let group = self.expect_ident()?;
348 if !self.consume_ident_ci("CONSUMER")? {
349 return Err(ParseError::expected(
350 vec!["CONSUMER"],
351 self.peek(),
352 self.position(),
353 ));
354 }
355 let consumer = self.expect_ident()?;
356 if !self.consume_ident_ci("MIN_IDLE")? {
357 return Err(ParseError::expected(
358 vec!["MIN_IDLE"],
359 self.peek(),
360 self.position(),
361 ));
362 }
363 let min_idle_ms = self.parse_integer()?.max(0) as u64;
364 Ok(QueryExpr::QueueCommand(QueueCommand::Claim {
365 queue,
366 group,
367 consumer,
368 min_idle_ms,
369 }))
370 }
371 Token::Ack => {
372 self.advance()?;
373 let queue = self.expect_ident()?;
374 let (group, message_id, delivery_id, _delay_ms) =
375 self.parse_ack_nack_handle(false)?;
376 Ok(QueryExpr::QueueCommand(QueueCommand::Ack {
377 queue,
378 group,
379 message_id,
380 delivery_id,
381 }))
382 }
383 Token::Nack => {
384 self.advance()?;
385 let queue = self.expect_ident()?;
386 let (group, message_id, delivery_id, delay_ms) =
387 self.parse_ack_nack_handle(true)?;
388 Ok(QueryExpr::QueueCommand(QueueCommand::Nack {
389 queue,
390 group,
391 message_id,
392 delivery_id,
393 delay_ms,
394 }))
395 }
396 _ => Err(ParseError::expected(
397 vec![
398 "PUSH", "POP", "PEEK", "LEN", "PURGE", "GROUP", "READ", "ACK", "NACK", "LPUSH",
399 "RPUSH", "LPOP", "RPOP", "PENDING", "CLAIM", "MOVE",
400 ],
401 self.peek(),
402 self.position(),
403 )),
404 }
405 }
406
407 fn parse_ack_nack_handle(
416 &mut self,
417 allow_delay: bool,
418 ) -> Result<(String, String, Option<String>, Option<u64>), ParseError> {
419 let (group, message_id) = if matches!(self.peek(), Token::Group) {
420 self.advance()?;
421 let group = self.expect_ident()?;
422 let message_id = self.parse_string()?;
423 (group, message_id)
424 } else {
425 (String::new(), String::new())
426 };
427 let mut delivery_id: Option<String> = None;
433 let mut delay_ms: Option<u64> = None;
434 while self.consume(&Token::With)? {
435 if self.consume_ident_ci("delivery_id")? {
436 if delivery_id.is_some() {
437 return Err(ParseError::new(
438 "duplicate WITH delivery_id clause".to_string(),
439 self.position(),
440 ));
441 }
442 if !self.consume(&Token::Eq)? {
443 return Err(ParseError::expected(
444 vec!["="],
445 self.peek(),
446 self.position(),
447 ));
448 }
449 delivery_id = Some(self.parse_string()?);
450 } else if allow_delay && self.consume_ident_ci("DELAY")? {
451 if delay_ms.is_some() {
452 return Err(ParseError::new(
453 "duplicate WITH DELAY clause".to_string(),
454 self.position(),
455 ));
456 }
457 let value = self.parse_float()?;
458 let unit = self.parse_queue_duration_unit()?;
459 delay_ms = Some((value * unit).max(0.0) as u64);
460 } else {
461 let mut expected = vec!["delivery_id"];
462 if allow_delay {
463 expected.push("DELAY");
464 }
465 return Err(ParseError::expected(expected, self.peek(), self.position()));
466 }
467 }
468 if group.is_empty() && delivery_id.is_none() {
469 let mut expected = vec!["GROUP", "WITH delivery_id"];
470 if allow_delay {
471 expected.push("WITH DELAY");
472 }
473 return Err(ParseError::expected(expected, self.peek(), self.position()));
474 }
475 Ok((group, message_id, delivery_id, delay_ms))
476 }
477
478 fn parse_push_tail_clauses(
486 &mut self,
487 ) -> Result<
488 (
489 Option<i32>,
490 Option<String>,
491 Option<QueueAvailability>,
492 Option<String>,
493 ),
494 ParseError,
495 > {
496 let mut priority: Option<i32> = None;
497 let mut key: Option<String> = None;
498 let mut available: Option<QueueAvailability> = None;
499 let mut dedup_key: Option<String> = None;
500 loop {
501 if self.consume(&Token::Priority)? {
502 if priority.is_some() {
503 return Err(ParseError::new(
504 "duplicate PRIORITY clause".to_string(),
505 self.position(),
506 ));
507 }
508 priority = Some(self.parse_integer()? as i32);
509 } else if self.consume(&Token::Key)? {
510 if key.is_some() {
511 return Err(ParseError::new(
512 "duplicate KEY clause".to_string(),
513 self.position(),
514 ));
515 }
516 if available.is_some() {
517 return Err(ParseError::new(
518 "QUEUE PUSH KEY cannot be combined with DELAY / AVAILABLE AT".to_string(),
519 self.position(),
520 ));
521 }
522 key = Some(self.parse_string()?);
523 } else if self.consume_ident_ci("DEDUP")? {
524 if dedup_key.is_some() {
525 return Err(ParseError::new(
526 "duplicate DEDUP clause".to_string(),
527 self.position(),
528 ));
529 }
530 dedup_key = Some(self.parse_string()?);
531 } else if self.peek_ident_ci("DELAY") {
532 self.advance()?;
533 if available.is_some() {
534 return Err(ParseError::new(
535 "QUEUE PUSH accepts at most one of DELAY / AVAILABLE AT".to_string(),
536 self.position(),
537 ));
538 }
539 if key.is_some() {
540 return Err(ParseError::new(
541 "QUEUE PUSH KEY cannot be combined with DELAY / AVAILABLE AT".to_string(),
542 self.position(),
543 ));
544 }
545 let value = self.parse_float()?;
546 let unit = self.parse_queue_duration_unit()?;
547 available = Some(QueueAvailability::DelayMs((value * unit).max(0.0) as u64));
548 } else if self.peek_ident_ci("AVAILABLE") {
549 self.advance()?;
550 if !self.consume_ident_ci("AT")? {
551 return Err(ParseError::expected(
552 vec!["AT"],
553 self.peek(),
554 self.position(),
555 ));
556 }
557 if available.is_some() {
558 return Err(ParseError::new(
559 "QUEUE PUSH accepts at most one of DELAY / AVAILABLE AT".to_string(),
560 self.position(),
561 ));
562 }
563 if key.is_some() {
564 return Err(ParseError::new(
565 "QUEUE PUSH KEY cannot be combined with DELAY / AVAILABLE AT".to_string(),
566 self.position(),
567 ));
568 }
569 let unix_ms = self.parse_integer()?.max(0) as u64;
570 available = Some(QueueAvailability::AtUnixMs(unix_ms));
571 } else {
572 break;
573 }
574 }
575 Ok((priority, key, available, dedup_key))
576 }
577
578 fn parse_optional_wait_clause(&mut self) -> Result<Option<u64>, ParseError> {
585 if !self.peek_ident_ci("WAIT") {
586 return Ok(None);
587 }
588 self.advance()?;
589 let value = self.parse_float()?;
590 let unit = self.parse_queue_duration_unit()?;
591 Ok(Some((value * unit).max(0.0) as u64))
592 }
593
594 fn reject_wait_clause(&mut self, command: &'static str) -> Result<(), ParseError> {
598 if self.peek_ident_ci("WAIT") {
599 return Err(ParseError::new(
600 format!("QUEUE {command} does not support WAIT; use QUEUE READ … WAIT <duration>"),
601 self.position(),
602 ));
603 }
604 Ok(())
605 }
606
607 fn peek_ident_ci(&self, name: &str) -> bool {
608 matches!(self.peek(), Token::Ident(id) if id.eq_ignore_ascii_case(name))
609 }
610
611 fn consume_queue_mode(&mut self) -> Result<Option<QueueMode>, ParseError> {
612 match self.peek() {
613 Token::Work => {
614 self.advance()?;
615 Ok(Some(QueueMode::Work))
616 }
617 Token::Ident(name) => {
618 if let Some(mode) = QueueMode::parse(name) {
619 self.advance()?;
620 Ok(Some(mode))
621 } else {
622 Ok(None)
623 }
624 }
625 _ => Ok(None),
626 }
627 }
628
629 fn parse_queue_mode(&mut self) -> Result<QueueMode, ParseError> {
630 match self.consume_queue_mode()? {
631 Some(mode) => Ok(mode),
632 None => Err(ParseError::expected(
633 vec!["FANOUT", "WORK", "STANDARD", "FIFO"],
634 self.peek(),
635 self.position(),
636 )),
637 }
638 }
639
640 fn parse_queue_duration_unit(&mut self) -> Result<f64, ParseError> {
642 match self.peek().clone() {
643 Token::Min => {
644 self.advance()?;
645 Ok(60_000.0)
646 }
647 Token::Ident(ref unit) => {
648 let mult = match unit.to_ascii_lowercase().as_str() {
649 "ms" => 1.0,
650 "s" | "sec" | "secs" => 1_000.0,
651 "m" | "min" | "mins" => 60_000.0,
652 "h" | "hr" | "hrs" => 3_600_000.0,
653 "d" | "day" | "days" => 86_400_000.0,
654 _ => return Ok(1_000.0),
655 };
656 self.advance()?;
657 Ok(mult)
658 }
659 _ => Ok(1_000.0),
660 }
661 }
662}