1use crate::{
14 data_type::parse_data_type,
15 keywords::Keyword,
16 lexer::Token,
17 parser::{ParseError, Parser},
18 select::{parse_select, OrderFlag},
19 span::OptSpanned,
20 statement::parse_compound_query,
21 DataType, Identifier, SString, Span, Spanned, Statement,
22};
23use alloc::string::ToString;
24use alloc::vec;
25use alloc::{boxed::Box, vec::Vec};
26
27#[derive(Debug, Clone, PartialEq, Eq)]
29pub enum Function<'a> {
30 Abs,
31 Acos,
32 AddDate,
33 AddMonths,
34 AddTime,
35 Ascii,
36 Asin,
37 Atan,
38 Atan2,
39 Bin,
40 BitLength,
41 Ceil,
42 CharacterLength,
43 Chr,
44 Concat,
45 ConcatWs,
46 Conv,
47 ConvertTz,
48 Cos,
49 Cot,
50 Crc32,
51 Crc32c,
52 CurDate,
53 CurrentTimestamp,
54 CurTime,
55 Date,
56 DateDiff,
57 DateFormat,
58 DateSub,
59 Datetime,
60 DayName,
61 DayOfMonth,
62 DayOfWeek,
63 DayOfYear,
64 Degrees,
65 Elt,
66 Exists,
67 Exp,
68 ExportSet,
69 ExtractValue,
70 Field,
71 FindInSet,
72 Floor,
73 Format,
74 FromBase64,
75 FromDays,
76 FromUnixTime,
77 Greatest,
78 Hex,
79 Hour,
80 If,
81 IfNull,
82 Insert,
83 InStr,
84 JsonArray,
85 JsonArrayAgg,
86 JsonArrayAppend,
87 JsonArrayInsert,
88 JsonArrayIntersect,
89 JsonCompact,
90 JsonContains,
91 JsonContainsPath,
92 JsonDepth,
93 JsonDetailed,
94 JsonEquals,
95 JsonExists,
96 JsonExtract,
97 JsonInsert,
98 JsonKeys,
99 JsonLength,
100 JsonLoose,
101 JsonMerge,
102 JsonMergePath,
103 JsonMergePerserve,
104 JsonNormalize,
105 JsonObject,
106 JsonObjectAgg,
107 JsonObjectFilterKeys,
108 JsonObjectToArray,
109 JsonOverlaps,
110 JsonPretty,
111 JsonQuery,
112 JsonQuote,
113 JsonRemove,
114 JsonReplace,
115 JsonSchemaValid,
116 JsonSearch,
117 JsonSet,
118 JsonTable,
119 JsonType,
120 JsonUnquote,
121 JsonValid,
122 JsonValue,
123 Lag,
124 LastDay,
125 LCase,
126 Lead,
127 Least,
128 Left,
129 Length,
130 LengthB,
131 Ln,
132 LoadFile,
133 Locate,
134 Log,
135 Log10,
136 Log2,
137 Lower,
138 LPad,
139 LTrim,
140 MakeDate,
141 MakeSet,
142 MakeTime,
143 Max,
144 MicroSecond,
145 Mid,
146 Min,
147 Minute,
148 Month,
149 MonthName,
150 NaturalSortkey,
151 Now,
152 NullIf,
153 NVL2,
154 Oct,
155 OctetLength,
156 Ord,
157 PeriodAdd,
158 PeriodDiff,
159 Pi,
160 Position,
161 Pow,
162 Quarter,
163 Quote,
164 Radians,
165 Rand,
166 Repeat,
167 Replace,
168 Reverse,
169 Right,
170 Round,
171 RPad,
172 RTrim,
173 Second,
174 SecToTime,
175 SFormat,
176 Sign,
177 Sin,
178 SoundEx,
179 Space,
180 Sqrt,
181 StartsWith,
182 StrCmp,
183 Strftime,
184 StrToDate,
185 SubStr,
186 SubStringIndex,
187 SubTime,
188 Sum,
189 SysDate,
190 Tan,
191 Time,
192 TimeDiff,
193 TimeFormat,
194 Timestamp,
195 TimeToSec,
196 ToBase64,
197 ToChar,
198 ToDays,
199 ToSeconds,
200 Truncate,
201 UCase,
202 UncompressedLength,
203 UnHex,
204 UnixTimestamp,
205 Unknown,
206 UpdateXml,
207 Upper,
208 UtcDate,
209 UtcTime,
210 UtcTimeStamp,
211 Value,
212 Week,
213 Weekday,
214 WeekOfYear,
215 Year,
216 YearWeek,
217 Other(&'a str),
218}
219
220#[derive(Debug, Clone)]
222pub enum Variable<'a> {
223 TimeZone,
224 Other(&'a str),
225}
226
227#[derive(Debug, Clone, Copy)]
229pub enum BinaryOperator {
230 Or,
231 Xor,
232 And,
233 Eq,
234 NullSafeEq,
235 GtEq,
236 Gt,
237 LtEq,
238 Lt,
239 Neq,
240 ShiftLeft,
241 ShiftRight,
242 BitAnd,
243 BitOr,
244 BitXor,
245 Add,
246 Subtract,
247 Divide,
248 Div,
249 Mod,
250 Mult,
251 Like,
252 NotLike,
253}
254
255#[derive(Debug, Clone, Copy)]
257pub enum Is {
258 Null,
259 NotNull,
260 True,
261 NotTrue,
262 False,
263 NotFalse,
264 Unknown,
265 NotUnknown,
266}
267
268#[derive(Debug, Clone, Copy)]
270pub enum UnaryOperator {
271 Binary,
272 Collate,
273 LogicalNot,
274 Minus,
275 Not,
276}
277
278#[derive(Debug, Clone)]
280pub enum IdentifierPart<'a> {
281 Name(Identifier<'a>),
282 Star(Span),
283}
284
285impl<'a> Spanned for IdentifierPart<'a> {
286 fn span(&self) -> Span {
287 match &self {
288 IdentifierPart::Name(v) => v.span(),
289 IdentifierPart::Star(v) => v.span(),
290 }
291 }
292}
293
294#[derive(Debug, Clone)]
296pub struct When<'a> {
297 pub when_span: Span,
299 pub when: Expression<'a>,
301 pub then_span: Span,
303 pub then: Expression<'a>,
305}
306
307impl<'a> Spanned for When<'a> {
308 fn span(&self) -> Span {
309 self.when_span
310 .join_span(&self.when)
311 .join_span(&self.then_span)
312 .join_span(&self.then)
313 }
314}
315
316#[derive(Debug, Clone)]
318pub struct WindowSpec<'a> {
319 pub order_by: (Span, Vec<(Expression<'a>, OrderFlag)>),
321}
322
323impl<'a> Spanned for WindowSpec<'a> {
324 fn span(&self) -> Span {
325 self.order_by.span()
326 }
327}
328
329#[derive(Debug, Clone, PartialEq, Eq)]
331pub enum TimeUnit {
332 Microsecond,
334 Second,
336 Minute,
338 Hour,
340 Day,
342 Week,
344 Month,
346 Quarter,
348 Year,
350 SecondMicrosecond,
352 MinuteMicrosecond,
354 MinuteSecond,
356 HourMicrosecond,
358 HourSecond,
360 HourMinute,
362 DayMicrosecond,
364 DaySecond,
366 DayMinute,
368 DayHour,
370 YearMonth,
372}
373
374fn parse_time_unit(t: &Token<'_>) -> Option<TimeUnit> {
375 match t {
376 Token::Ident(_, Keyword::MICROSECOND) => Some(TimeUnit::Microsecond),
377 Token::Ident(_, Keyword::SECOND) => Some(TimeUnit::Second),
378 Token::Ident(_, Keyword::MINUTE) => Some(TimeUnit::Minute),
379 Token::Ident(_, Keyword::HOUR) => Some(TimeUnit::Hour),
380 Token::Ident(_, Keyword::DAY) => Some(TimeUnit::Day),
381 Token::Ident(_, Keyword::WEEK) => Some(TimeUnit::Week),
382 Token::Ident(_, Keyword::MONTH) => Some(TimeUnit::Month),
383 Token::Ident(_, Keyword::QUARTER) => Some(TimeUnit::Quarter),
384 Token::Ident(_, Keyword::YEAR) => Some(TimeUnit::Year),
385 Token::Ident(_, Keyword::SECOND_MICROSECOND) => Some(TimeUnit::SecondMicrosecond),
386 Token::Ident(_, Keyword::MINUTE_MICROSECOND) => Some(TimeUnit::MinuteMicrosecond),
387 Token::Ident(_, Keyword::MINUTE_SECOND) => Some(TimeUnit::MinuteSecond),
388 Token::Ident(_, Keyword::HOUR_MICROSECOND) => Some(TimeUnit::HourMicrosecond),
389 Token::Ident(_, Keyword::HOUR_SECOND) => Some(TimeUnit::HourSecond),
390 Token::Ident(_, Keyword::HOUR_MINUTE) => Some(TimeUnit::HourMinute),
391 Token::Ident(_, Keyword::DAY_MICROSECOND) => Some(TimeUnit::DayMicrosecond),
392 Token::Ident(_, Keyword::DAY_SECOND) => Some(TimeUnit::DaySecond),
393 Token::Ident(_, Keyword::DAY_MINUTE) => Some(TimeUnit::DayMinute),
394 Token::Ident(_, Keyword::DAY_HOUR) => Some(TimeUnit::DayHour),
395 Token::Ident(_, Keyword::YEAR_MONTH) => Some(TimeUnit::YearMonth),
396 _ => None,
397 }
398}
399
400#[derive(Debug, Clone)]
402pub enum Expression<'a> {
403 Binary {
405 op: BinaryOperator,
407 op_span: Span,
409 lhs: Box<Expression<'a>>,
411 rhs: Box<Expression<'a>>,
413 },
414 Unary {
416 op: UnaryOperator,
418 op_span: Span,
420 operand: Box<Expression<'a>>,
422 },
423 Subquery(Box<Statement<'a>>),
425 Null(Span),
427 Bool(bool, Span),
429 String(SString<'a>),
432 Integer((u64, Span)),
434 ListHack((usize, Span)),
436 Float((f64, Span)),
438 Function(Function<'a>, Vec<Expression<'a>>, Span),
440 WindowFunction {
442 function: Function<'a>,
443 args: Vec<Expression<'a>>,
444 function_span: Span,
445 over_span: Span,
446 window_spec: WindowSpec<'a>,
447 },
448 Identifier(Vec<IdentifierPart<'a>>),
450 Interval {
452 interval_span: Span,
454 time_interval: (Vec<i64>, Span),
456 time_unit: (TimeUnit, Span),
458 },
459 Arg((usize, Span)),
461 Exists(Box<Statement<'a>>),
463 Extract {
464 extract_span: Span,
466 time_unit: (TimeUnit, Span),
468 from_span: Span,
470 date: Box<Expression<'a>>,
472 },
473 In {
475 lhs: Box<Expression<'a>>,
477 rhs: Vec<Expression<'a>>,
479 in_span: Span,
481 not_in: bool,
483 },
484 Is(Box<Expression<'a>>, Is, Span),
486 Invalid(Span),
488 Case {
490 case_span: Span,
492 value: Option<Box<Expression<'a>>>,
494 whens: Vec<When<'a>>,
496 else_: Option<(Span, Box<Expression<'a>>)>,
498 end_span: Span,
500 },
501 Cast {
503 cast_span: Span,
505 expr: Box<Expression<'a>>,
507 as_span: Span,
509 type_: DataType<'a>,
511 },
512 Count {
514 count_span: Span,
516 distinct_span: Option<Span>,
518 expr: Box<Expression<'a>>,
520 },
521 GroupConcat {
523 group_concat_span: Span,
525 distinct_span: Option<Span>,
527 expr: Box<Expression<'a>>,
529 },
530 Variable {
532 global: Option<Span>,
534 session: Option<Span>,
536 dot: Option<Span>,
538 variable: Variable<'a>,
540 variable_span: Span,
542 },
543 TimestampAdd {
545 timestamp_add_span: Span,
546 unit: (TimeUnit, Span),
547 interval: Box<Expression<'a>>,
548 datetime: Box<Expression<'a>>,
549 },
550 TimestampDiff {
552 timestamp_diff_span: Span,
553 unit: (TimeUnit, Span),
554 e1: Box<Expression<'a>>,
555 e2: Box<Expression<'a>>,
556 },
557}
558
559impl<'a> Spanned for Expression<'a> {
560 fn span(&self) -> Span {
561 match &self {
562 Expression::Binary {
563 op_span, lhs, rhs, ..
564 } => op_span.join_span(lhs).join_span(rhs),
565 Expression::Unary {
566 op_span, operand, ..
567 } => op_span.join_span(operand),
568 Expression::Subquery(v) => v.span(),
569 Expression::Null(v) => v.span(),
570 Expression::Bool(_, v) => v.span(),
571 Expression::String(v) => v.span(),
572 Expression::Integer(v) => v.span(),
573 Expression::Float(v) => v.span(),
574 Expression::ListHack((_, s)) => s.span(),
575 Expression::Function(_, b, c) => c.join_span(b),
576 Expression::Identifier(v) => v.opt_span().expect("Span of identifier parts"),
577 Expression::Arg(v) => v.span(),
578 Expression::Exists(v) => v.span(),
579 Expression::In {
580 lhs, rhs, in_span, ..
581 } => in_span.join_span(lhs).join_span(rhs),
582 Expression::Is(a, _, b) => b.join_span(a),
583 Expression::Invalid(s) => s.span(),
584 Expression::Case {
585 case_span,
586 value,
587 whens,
588 else_,
589 end_span,
590 } => case_span
591 .join_span(value)
592 .join_span(whens)
593 .join_span(else_)
594 .join_span(end_span),
595 Expression::Cast {
596 cast_span,
597 expr,
598 as_span,
599 type_,
600 } => cast_span
601 .join_span(expr)
602 .join_span(as_span)
603 .join_span(type_),
604 Expression::Count {
605 count_span,
606 distinct_span,
607 expr,
608 } => count_span.join_span(distinct_span).join_span(expr),
609 Expression::GroupConcat {
610 group_concat_span,
611 distinct_span,
612 expr,
613 } => group_concat_span.join_span(distinct_span).join_span(expr),
614 Expression::Variable {
615 global,
616 session,
617 dot,
618 variable_span,
619 variable: _,
620 } => variable_span
621 .join_span(global)
622 .join_span(session)
623 .join_span(dot),
624 Expression::WindowFunction {
625 function: _,
626 args,
627 function_span,
628 over_span,
629 window_spec,
630 } => function_span
631 .join_span(args)
632 .join_span(over_span)
633 .join_span(window_spec),
634 Expression::Interval {
635 interval_span,
636 time_interval,
637 time_unit,
638 } => interval_span
639 .join_span(&time_interval.1)
640 .join_span(&time_unit.1),
641 Expression::Extract {
642 extract_span,
643 time_unit,
644 from_span,
645 date,
646 } => extract_span
647 .join_span(&time_unit.1)
648 .join_span(from_span)
649 .join_span(date),
650 Expression::TimestampAdd {
651 timestamp_add_span: timespan_add_span,
652 unit,
653 interval,
654 datetime,
655 } => timespan_add_span
656 .join_span(&unit.1)
657 .join_span(interval)
658 .join_span(datetime),
659 Expression::TimestampDiff {
660 timestamp_diff_span,
661 unit,
662 e1,
663 e2,
664 } => timestamp_diff_span
665 .join_span(&unit.1)
666 .join_span(e1)
667 .join_span(e2),
668 }
669 }
670}
671
672fn parse_function<'a>(
673 parser: &mut Parser<'a, '_>,
674 t: Token<'a>,
675 span: Span,
676) -> Result<Expression<'a>, ParseError> {
677 parser.consume_token(Token::LParen)?;
678 let func = match &t {
679 Token::Ident(_, Keyword::ASCII) => Function::Ascii,
681 Token::Ident(_, Keyword::BIN) => Function::Bin,
682 Token::Ident(_, Keyword::BIT_LENGTH) => Function::BitLength,
683 Token::Ident(_, Keyword::CHAR_LENGTH) => Function::CharacterLength,
684 Token::Ident(_, Keyword::CHARACTER_LENGTH) => Function::CharacterLength,
685 Token::Ident(_, Keyword::CHR) => Function::Chr,
686 Token::Ident(_, Keyword::CONCAT) => Function::Concat,
687 Token::Ident(_, Keyword::CONCAT_WS) => Function::ConcatWs,
688 Token::Ident(_, Keyword::ELT) => Function::Elt,
689 Token::Ident(_, Keyword::EXPORT_SET) => Function::ExportSet,
690 Token::Ident(_, Keyword::EXTRACTVALUE) => Function::ExtractValue,
691 Token::Ident(_, Keyword::FIELD) => Function::Field,
692 Token::Ident(_, Keyword::FIND_IN_SET) => Function::FindInSet,
693 Token::Ident(_, Keyword::FORMAT) => Function::Format,
694 Token::Ident(_, Keyword::FROM_BASE64) => Function::FromBase64,
695 Token::Ident(_, Keyword::HEX) => Function::Hex,
696 Token::Ident(_, Keyword::INSERT) => Function::Insert,
697 Token::Ident(_, Keyword::INSTR) => Function::InStr,
698 Token::Ident(_, Keyword::LCASE) => Function::LCase,
699 Token::Ident(_, Keyword::LEFT) => Function::Left,
700 Token::Ident(_, Keyword::LENGTH) => Function::Length,
701 Token::Ident(_, Keyword::LENGTHB) => Function::LengthB,
702 Token::Ident(_, Keyword::LOAD_FILE) => Function::LoadFile,
703 Token::Ident(_, Keyword::LOCATE) => Function::Locate,
704 Token::Ident(_, Keyword::LOWER) => Function::Lower,
705 Token::Ident(_, Keyword::LPAD) => Function::LPad,
706 Token::Ident(_, Keyword::LTRIM) => Function::LTrim,
707 Token::Ident(_, Keyword::MAKE_SET) => Function::MakeSet,
708 Token::Ident(_, Keyword::MID) => Function::Mid,
709 Token::Ident(_, Keyword::NATURAL_SORT_KEY) => Function::NaturalSortkey,
710 Token::Ident(_, Keyword::OCTET_LENGTH) => Function::OctetLength,
711 Token::Ident(_, Keyword::ORD) => Function::Ord,
712 Token::Ident(_, Keyword::POSITION) => Function::Position,
713 Token::Ident(_, Keyword::QUOTE) => Function::Quote,
714 Token::Ident(_, Keyword::REPEAT) => Function::Repeat,
715 Token::Ident(_, Keyword::REPLACE) => Function::Replace,
716 Token::Ident(_, Keyword::REVERSE) => Function::Reverse,
717 Token::Ident(_, Keyword::RIGHT) => Function::Right,
718 Token::Ident(_, Keyword::RPAD) => Function::RPad,
719 Token::Ident(_, Keyword::RTRIM) => Function::RTrim,
720 Token::Ident(_, Keyword::SOUNDEX) => Function::SoundEx,
721 Token::Ident(_, Keyword::SPACE) => Function::Space,
722 Token::Ident(_, Keyword::STRCMP) => Function::StrCmp,
723 Token::Ident(_, Keyword::SUBSTR) => Function::SubStr,
724 Token::Ident(_, Keyword::SUBSTRING) => Function::SubStr,
725 Token::Ident(_, Keyword::SUBSTRING_INDEX) => Function::SubStringIndex,
726 Token::Ident(_, Keyword::TO_BASE64) => Function::ToBase64,
727 Token::Ident(_, Keyword::TO_CHAR) => Function::ToChar,
728 Token::Ident(_, Keyword::UCASE) => Function::UCase,
729 Token::Ident(_, Keyword::UNCOMPRESSED_LENGTH) => Function::UncompressedLength,
730 Token::Ident(_, Keyword::UNHEX) => Function::UnHex,
731 Token::Ident(_, Keyword::UPDATEXML) => Function::UpdateXml,
732 Token::Ident(_, Keyword::UPPER) => Function::Upper,
733 Token::Ident(_, Keyword::SFORMAT) => Function::SFormat,
734
735 Token::Ident(_, Keyword::EXISTS) => Function::Exists,
737 Token::Ident(_, Keyword::MIN) => Function::Min,
738 Token::Ident(_, Keyword::MAX) => Function::Max,
739 Token::Ident(_, Keyword::SUM) => Function::Sum,
740 Token::Ident(_, Keyword::VALUE) => Function::Value,
741 Token::Ident(_, Keyword::VALUES) => Function::Value,
742 Token::Ident(_, Keyword::LEAD) => Function::Lead,
743 Token::Ident(_, Keyword::LAG) => Function::Lag,
744 Token::Ident(_, Keyword::STARTS_WITH) => Function::StartsWith,
745
746 Token::Ident(_, Keyword::IFNULL) => Function::IfNull,
748 Token::Ident(_, Keyword::NULLIF) => Function::NullIf,
749 Token::Ident(_, Keyword::NVL) => Function::IfNull,
750 Token::Ident(_, Keyword::NVL2) => Function::NVL2,
751 Token::Ident(_, Keyword::IF) => Function::If,
752
753 Token::Ident(_, Keyword::ABS) => Function::Abs,
755 Token::Ident(_, Keyword::ACOS) => Function::Acos,
756 Token::Ident(_, Keyword::ASIN) => Function::Asin,
757 Token::Ident(_, Keyword::ATAN) => Function::Atan,
758 Token::Ident(_, Keyword::ATAN2) => Function::Atan2,
759 Token::Ident(_, Keyword::CEIL | Keyword::CEILING) => Function::Ceil,
760 Token::Ident(_, Keyword::CONV) => Function::Conv,
761 Token::Ident(_, Keyword::COS) => Function::Cos,
762 Token::Ident(_, Keyword::COT) => Function::Cot,
763 Token::Ident(_, Keyword::CRC32) => Function::Crc32,
764 Token::Ident(_, Keyword::DEGREES) => Function::Degrees,
765 Token::Ident(_, Keyword::EXP) => Function::Exp,
766 Token::Ident(_, Keyword::FLOOR) => Function::Floor,
767 Token::Ident(_, Keyword::GREATEST) => Function::Greatest,
768 Token::Ident(_, Keyword::LN) => Function::Ln,
769 Token::Ident(_, Keyword::LOG) => Function::Log,
770 Token::Ident(_, Keyword::LOG10) => Function::Log10,
771 Token::Ident(_, Keyword::LOG2) => Function::Log2,
772 Token::Ident(_, Keyword::OCT) => Function::Oct,
773 Token::Ident(_, Keyword::PI) => Function::Pi,
774 Token::Ident(_, Keyword::POW | Keyword::POWER) => Function::Pow,
775 Token::Ident(_, Keyword::RADIANS) => Function::Radians,
776 Token::Ident(_, Keyword::RAND) => Function::Rand,
777 Token::Ident(_, Keyword::ROUND) => Function::Round,
778 Token::Ident(_, Keyword::SIGN) => Function::Sign,
779 Token::Ident(_, Keyword::SIN) => Function::Sin,
780 Token::Ident(_, Keyword::SQRT) => Function::Sqrt,
781 Token::Ident(_, Keyword::TAN) => Function::Tan,
782 Token::Ident(_, Keyword::TRUNCATE) => Function::Truncate,
783 Token::Ident(_, Keyword::CRC32C) => Function::Crc32c,
784 Token::Ident(_, Keyword::LEAST) => Function::Least,
785
786 Token::Ident(_, Keyword::ADDDATE) => Function::AddDate,
788 Token::Ident(_, Keyword::ADDTIME) => Function::AddTime,
789 Token::Ident(_, Keyword::CONVERT_TZ) => Function::ConvertTz,
790 Token::Ident(_, Keyword::CURDATE) => Function::CurDate,
791 Token::Ident(_, Keyword::CURRENT_DATE) => Function::CurDate,
792 Token::Ident(_, Keyword::CURRENT_TIME) => Function::CurTime,
793 Token::Ident(_, Keyword::CURTIME) => Function::CurTime,
794 Token::Ident(_, Keyword::DATE) => Function::Date,
795 Token::Ident(_, Keyword::HOUR) => Function::Hour,
796 Token::Ident(_, Keyword::DATEDIFF) => Function::DateDiff,
797 Token::Ident(_, Keyword::DATE_ADD) => Function::AddDate,
798 Token::Ident(_, Keyword::DATE_FORMAT) => Function::DateFormat,
799 Token::Ident(_, Keyword::DATE_SUB) => Function::DateSub,
800 Token::Ident(_, Keyword::DAY | Keyword::DAYOFMONTH) => Function::DayOfMonth,
801 Token::Ident(_, Keyword::DAYNAME) => Function::DayName,
802 Token::Ident(_, Keyword::DAYOFWEEK) => Function::DayOfWeek,
803 Token::Ident(_, Keyword::DAYOFYEAR) => Function::DayOfYear,
804 Token::Ident(_, Keyword::FROM_DAYS) => Function::FromDays,
805 Token::Ident(_, Keyword::CURRENT_TIMESTAMP) => Function::CurrentTimestamp,
806 Token::Ident(_, Keyword::LOCALTIME | Keyword::LOCALTIMESTAMP | Keyword::NOW) => {
807 Function::Now
808 }
809 Token::Ident(_, Keyword::MAKEDATE) => Function::MakeDate,
810 Token::Ident(_, Keyword::MAKETIME) => Function::MakeTime,
811 Token::Ident(_, Keyword::MICROSECOND) => Function::MicroSecond,
812 Token::Ident(_, Keyword::MINUTE) => Function::Minute,
813 Token::Ident(_, Keyword::MONTH) => Function::Month,
814 Token::Ident(_, Keyword::MONTHNAME) => Function::MonthName,
815 Token::Ident(_, Keyword::PERIOD_ADD) => Function::PeriodAdd,
816 Token::Ident(_, Keyword::PERIOD_DIFF) => Function::PeriodDiff,
817 Token::Ident(_, Keyword::QUARTER) => Function::Quarter,
818 Token::Ident(_, Keyword::SECOND) => Function::Second,
819 Token::Ident(_, Keyword::SEC_TO_TIME) => Function::SecToTime,
820 Token::Ident(_, Keyword::STR_TO_DATE) => Function::StrToDate,
821 Token::Ident(_, Keyword::SUBDATE) => Function::DateSub,
822 Token::Ident(_, Keyword::SUBTIME) => Function::SubTime,
823 Token::Ident(_, Keyword::TIME) => Function::Time,
824 Token::Ident(_, Keyword::LAST_DAY) => Function::LastDay,
825 Token::Ident(_, Keyword::TIMEDIFF) => Function::TimeDiff,
826 Token::Ident(_, Keyword::TIMESTAMP) => Function::Timestamp,
827 Token::Ident(_, Keyword::TIME_FORMAT) => Function::TimeFormat,
828 Token::Ident(_, Keyword::TIME_TO_SEC) => Function::TimeToSec,
829 Token::Ident(_, Keyword::TO_DAYS) => Function::ToDays,
830 Token::Ident(_, Keyword::TO_SECONDS) => Function::ToSeconds,
831 Token::Ident(_, Keyword::UNIX_TIMESTAMP) => Function::UnixTimestamp,
832 Token::Ident(_, Keyword::UTC_DATE) => Function::UtcDate,
833 Token::Ident(_, Keyword::UTC_TIME) => Function::UtcTime,
834 Token::Ident(_, Keyword::UTC_TIMESTAMP) => Function::UtcTimeStamp,
835 Token::Ident(_, Keyword::WEEK) => Function::Week,
836 Token::Ident(_, Keyword::WEEKDAY) => Function::Weekday,
837 Token::Ident(_, Keyword::WEEKOFYEAR) => Function::WeekOfYear,
838 Token::Ident(_, Keyword::ADD_MONTHS) => Function::AddMonths,
839 Token::Ident(_, Keyword::FROM_UNIXTIME) => Function::FromUnixTime,
840 Token::Ident(_, Keyword::YEAR) => Function::Year,
841 Token::Ident(_, Keyword::YEARWEEK) => Function::YearWeek,
842 Token::Ident(_, Keyword::SYSDATE) => Function::SysDate,
843
844 Token::Ident(_, Keyword::JSON_ARRAY) => Function::JsonArray,
846 Token::Ident(_, Keyword::JSON_ARRAYAGG) => Function::JsonArrayAgg,
847 Token::Ident(_, Keyword::JSON_ARRAY_APPEND) => Function::JsonArrayAppend,
848 Token::Ident(_, Keyword::JSON_ARRAY_INSERT) => Function::JsonArrayInsert,
849 Token::Ident(_, Keyword::JSON_ARRAY_INTERSECT) => Function::JsonArrayIntersect,
850 Token::Ident(_, Keyword::JSON_COMPACT) => Function::JsonCompact,
851 Token::Ident(_, Keyword::JSON_CONTAINS) => Function::JsonContains,
852 Token::Ident(_, Keyword::JSON_CONTAINS_PATH) => Function::JsonContainsPath,
853 Token::Ident(_, Keyword::JSON_DEPTH) => Function::JsonDepth,
854 Token::Ident(_, Keyword::JSON_DETAILED) => Function::JsonDetailed,
855 Token::Ident(_, Keyword::JSON_EQUALS) => Function::JsonEquals,
856 Token::Ident(_, Keyword::JSON_EXISTS) => Function::JsonExists,
857 Token::Ident(_, Keyword::JSON_EXTRACT) => Function::JsonExtract,
858 Token::Ident(_, Keyword::JSON_INSERT) => Function::JsonInsert,
859 Token::Ident(_, Keyword::JSON_KEYS) => Function::JsonKeys,
860 Token::Ident(_, Keyword::JSON_LENGTH) => Function::JsonLength,
861 Token::Ident(_, Keyword::JSON_LOOSE) => Function::JsonLoose,
862 Token::Ident(_, Keyword::JSON_MERGE) => Function::JsonMerge,
863 Token::Ident(_, Keyword::JSON_MERGE_PATCH) => Function::JsonMergePath,
864 Token::Ident(_, Keyword::JSON_MERGE_PRESERVE) => Function::JsonMergePerserve,
865 Token::Ident(_, Keyword::JSON_NORMALIZE) => Function::JsonNormalize,
866 Token::Ident(_, Keyword::JSON_OBJECT) => Function::JsonObject,
867 Token::Ident(_, Keyword::JSON_OBJECT_FILTER_KEYS) => Function::JsonObjectFilterKeys,
868 Token::Ident(_, Keyword::JSON_OBJECT_TO_ARRAY) => Function::JsonObjectToArray,
869 Token::Ident(_, Keyword::JSON_OBJECTAGG) => Function::JsonObjectAgg,
870 Token::Ident(_, Keyword::JSON_OVERLAPS) => Function::JsonOverlaps,
871 Token::Ident(_, Keyword::JSON_PRETTY) => Function::JsonPretty,
872 Token::Ident(_, Keyword::JSON_QUERY) => Function::JsonQuery,
873 Token::Ident(_, Keyword::JSON_QUOTE) => Function::JsonQuote,
874 Token::Ident(_, Keyword::JSON_REMOVE) => Function::JsonRemove,
875 Token::Ident(_, Keyword::JSON_REPLACE) => Function::JsonReplace,
876 Token::Ident(_, Keyword::JSON_SCHEMA_VALID) => Function::JsonSchemaValid,
877 Token::Ident(_, Keyword::JSON_SEARCH) => Function::JsonSearch,
878 Token::Ident(_, Keyword::JSON_SET) => Function::JsonSet,
879 Token::Ident(_, Keyword::JSON_TABLE) => Function::JsonTable,
880 Token::Ident(_, Keyword::JSON_TYPE) => Function::JsonType,
881 Token::Ident(_, Keyword::JSON_UNQUOTE) => Function::JsonUnquote,
882 Token::Ident(_, Keyword::JSON_VALID) => Function::JsonValid,
883 Token::Ident(_, Keyword::JSON_VALUE) => Function::JsonValue,
884
885 Token::Ident(_, Keyword::STRFTIME) => Function::Strftime,
887 Token::Ident(_, Keyword::DATETIME) => Function::Datetime,
888 Token::Ident(v, k) if !k.reserved() => Function::Other(v),
889 _ => {
890 parser.err("Unknown function", &span);
891 Function::Unknown
892 }
893 };
894
895 let mut args = Vec::new();
896 if !matches!(parser.token, Token::RParen) {
897 loop {
898 parser.recovered(
899 "')' or ','",
900 &|t| matches!(t, Token::RParen | Token::Comma),
901 |parser| {
902 args.push(parse_expression_outer(parser)?);
903 Ok(())
904 },
905 )?;
906 if parser.skip_token(Token::Comma).is_none() {
907 break;
908 }
909 }
910 }
911 parser.consume_token(Token::RParen)?;
912
913 if let Some(over_span) = parser.skip_keyword(Keyword::OVER) {
914 parser.consume_token(Token::LParen)?;
915 let order_span = parser.consume_keywords(&[Keyword::ORDER, Keyword::BY])?;
916 let mut order = Vec::new();
917 loop {
918 let e = parse_expression(parser, false)?;
919 let f = match &parser.token {
920 Token::Ident(_, Keyword::ASC) => OrderFlag::Asc(parser.consume()),
921 Token::Ident(_, Keyword::DESC) => OrderFlag::Desc(parser.consume()),
922 _ => OrderFlag::None,
923 };
924 order.push((e, f));
925 if parser.skip_token(Token::Comma).is_none() {
926 break;
927 }
928 }
929 parser.consume_token(Token::RParen)?;
930 Ok(Expression::WindowFunction {
931 function: func,
932 args,
933 function_span: span,
934 over_span,
935 window_spec: WindowSpec {
936 order_by: (order_span, order),
937 },
938 })
939 } else {
940 Ok(Expression::Function(func, args, span))
941 }
942}
943
944const IN_PRIORITY: usize = 110;
946
947trait Priority {
948 fn priority(&self) -> usize;
949}
950
951impl Priority for BinaryOperator {
952 fn priority(&self) -> usize {
953 match self {
954 BinaryOperator::Or => 140,
955 BinaryOperator::Xor => 150,
956 BinaryOperator::And => 160,
957 BinaryOperator::Eq => 110,
958 BinaryOperator::NullSafeEq => 110,
959 BinaryOperator::GtEq => 110,
960 BinaryOperator::Gt => 110,
961 BinaryOperator::LtEq => 110,
962 BinaryOperator::Lt => 110,
963 BinaryOperator::Neq => 110,
964 BinaryOperator::Like => 110,
965 BinaryOperator::NotLike => 110,
966 BinaryOperator::ShiftLeft => 80,
967 BinaryOperator::ShiftRight => 80,
968 BinaryOperator::BitAnd => 90,
969 BinaryOperator::BitOr => 100,
970 BinaryOperator::BitXor => 50,
971 BinaryOperator::Add => 70,
972 BinaryOperator::Subtract => 70,
973 BinaryOperator::Divide => 60,
974 BinaryOperator::Div => 60,
975 BinaryOperator::Mod => 60,
976 BinaryOperator::Mult => 60,
977 }
978 }
979}
980
981impl Priority for UnaryOperator {
982 fn priority(&self) -> usize {
983 match self {
984 UnaryOperator::Binary => 20,
985 UnaryOperator::Collate => 20,
986 UnaryOperator::LogicalNot => 30,
987 UnaryOperator::Minus => 40,
988 UnaryOperator::Not => 130,
989 }
990 }
991}
992
993#[derive(Debug)]
994enum ReduceMember<'a> {
995 Expression(Expression<'a>),
996 Binary(BinaryOperator, Span),
997 Unary(UnaryOperator, Span),
998}
999
1000struct Reducer<'a> {
1001 stack: Vec<ReduceMember<'a>>,
1002}
1003
1004impl<'a> Reducer<'a> {
1005 fn reduce(&mut self, priority: usize) -> Result<(), &'static str> {
1006 let mut e = match self.stack.pop() {
1007 Some(ReduceMember::Expression(e)) => e,
1008 _ => {
1009 return Err("Expected expression before here");
1010 }
1011 };
1012 loop {
1013 let v = self.stack.pop();
1014 match v {
1015 None => break,
1016 Some(ReduceMember::Expression(_)) => return Err("ICE Reduce stack error 1"),
1017 Some(ReduceMember::Unary(op, span)) if op.priority() > priority => {
1018 self.stack.push(ReduceMember::Unary(op, span));
1019 break;
1020 }
1021 Some(ReduceMember::Binary(op, span)) if op.priority() > priority => {
1022 self.stack.push(ReduceMember::Binary(op, span));
1023 break;
1024 }
1025 Some(ReduceMember::Unary(op, op_span)) => {
1026 e = Expression::Unary {
1027 op,
1028 op_span,
1029 operand: Box::new(e),
1030 };
1031 }
1032 Some(ReduceMember::Binary(op, op_span)) => {
1033 let lhs = match self.stack.pop() {
1034 Some(ReduceMember::Expression(e)) => e,
1035 _ => return Err("ICE Reduce stack error 2"),
1036 };
1037 e = Expression::Binary {
1038 op,
1039 op_span,
1040 lhs: Box::new(lhs),
1041 rhs: Box::new(e),
1042 };
1043 }
1044 }
1045 }
1046 self.stack.push(ReduceMember::Expression(e));
1047 Ok(())
1048 }
1049
1050 fn shift_binop(&mut self, span: Span, op: BinaryOperator) -> Result<(), &'static str> {
1051 self.reduce(op.priority())?;
1052 self.stack.push(ReduceMember::Binary(op, span));
1053 Ok(())
1054 }
1055
1056 fn shift_unary(&mut self, span: Span, op: UnaryOperator) -> Result<(), &'static str> {
1057 if matches!(self.stack.last(), Some(ReduceMember::Expression(_))) {
1058 return Err("Unary operator cannot come before expression");
1059 }
1060 self.stack.push(ReduceMember::Unary(op, span));
1061 Ok(())
1062 }
1063
1064 fn shift_expr(&mut self, e: Expression<'a>) -> Result<(), &'static str> {
1065 if matches!(self.stack.last(), Some(ReduceMember::Expression(_))) {
1066 return Err("Expression should not follow expression");
1068 }
1069 self.stack.push(ReduceMember::Expression(e));
1070 Ok(())
1071 }
1072}
1073
1074pub(crate) fn parse_expression<'a>(
1075 parser: &mut Parser<'a, '_>,
1076 inner: bool,
1077) -> Result<Expression<'a>, ParseError> {
1078 let mut r = Reducer { stack: Vec::new() };
1079 loop {
1080 let e = match parser.token.clone() {
1081 Token::Ident(_, Keyword::OR) | Token::DoublePipe if !inner => {
1082 r.shift_binop(parser.consume(), BinaryOperator::Or)
1083 }
1084 Token::Ident(_, Keyword::XOR) if !inner => {
1085 r.shift_binop(parser.consume(), BinaryOperator::Xor)
1086 }
1087 Token::Ident(_, Keyword::AND) | Token::DoubleAmpersand if !inner => {
1088 r.shift_binop(parser.consume(), BinaryOperator::And)
1089 }
1090 Token::Eq if !inner => r.shift_binop(parser.consume(), BinaryOperator::Eq),
1091 Token::Spaceship if !inner => {
1092 r.shift_binop(parser.consume(), BinaryOperator::NullSafeEq)
1093 }
1094 Token::GtEq if !inner => r.shift_binop(parser.consume(), BinaryOperator::GtEq),
1095 Token::Gt if !inner => r.shift_binop(parser.consume(), BinaryOperator::Gt),
1096 Token::LtEq if !inner => r.shift_binop(parser.consume(), BinaryOperator::LtEq),
1097 Token::Lt if !inner => r.shift_binop(parser.consume(), BinaryOperator::Lt),
1098 Token::Neq if !inner => r.shift_binop(parser.consume(), BinaryOperator::Neq),
1099 Token::ShiftLeft if !inner => {
1100 r.shift_binop(parser.consume(), BinaryOperator::ShiftLeft)
1101 }
1102 Token::ShiftRight if !inner => {
1103 r.shift_binop(parser.consume(), BinaryOperator::ShiftRight)
1104 }
1105 Token::Ampersand => r.shift_binop(parser.consume(), BinaryOperator::BitAnd),
1106 Token::Pipe if !inner => r.shift_binop(parser.consume(), BinaryOperator::BitOr),
1107 Token::Ident(_, Keyword::BINARY) if !inner => {
1108 r.shift_unary(parser.consume(), UnaryOperator::Binary)
1109 }
1110 Token::Ident(_, Keyword::COLLATE) if !inner => {
1111 r.shift_unary(parser.consume(), UnaryOperator::Collate)
1112 }
1113 Token::ExclamationMark if !inner => {
1114 r.shift_unary(parser.consume(), UnaryOperator::LogicalNot)
1115 }
1116 Token::Minus if !matches!(r.stack.last(), Some(ReduceMember::Expression(_))) => {
1117 r.shift_unary(parser.consume(), UnaryOperator::Minus)
1118 }
1119 Token::Minus
1120 if !inner && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1121 {
1122 r.shift_binop(parser.consume(), BinaryOperator::Subtract)
1123 }
1124 Token::Ident(_, Keyword::IN) if !inner => {
1125 if let Err(e) = r.reduce(IN_PRIORITY) {
1126 parser.err_here(e)?;
1127 }
1128 let lhs = match r.stack.pop() {
1129 Some(ReduceMember::Expression(e)) => e,
1130 _ => parser.err_here("Expected expression before here 3")?,
1131 };
1132 let op = parser.consume_keyword(Keyword::IN)?;
1133 parser.consume_token(Token::LParen)?;
1134 let mut rhs = Vec::new();
1135 loop {
1136 parser.recovered(
1137 "')' or ','",
1138 &|t| matches!(t, Token::RParen | Token::Comma),
1139 |parser| {
1140 rhs.push(parse_expression_paren(parser)?);
1141 Ok(())
1142 },
1143 )?;
1144 if parser.skip_token(Token::Comma).is_none() {
1145 break;
1146 }
1147 }
1148 parser.consume_token(Token::RParen)?;
1149 r.shift_expr(Expression::In {
1150 lhs: Box::new(lhs),
1151 rhs,
1152 in_span: op,
1153 not_in: false,
1154 })
1155 }
1156 Token::Ident(_, Keyword::IS) if !inner => {
1157 if let Err(e) = r.reduce(IN_PRIORITY) {
1158 parser.err_here(e)?;
1159 }
1160 let lhs = match r.stack.pop() {
1161 Some(ReduceMember::Expression(e)) => e,
1162 _ => parser.err_here("Expected expression before here 4")?,
1163 };
1164 let op = parser.consume_keyword(Keyword::IS)?;
1165 let (is, op) = match &parser.token {
1166 Token::Ident(_, Keyword::NOT) => {
1167 parser.consume();
1168 match &parser.token {
1169 Token::Ident(_, Keyword::TRUE) => {
1170 (Is::NotTrue, parser.consume().join_span(&op))
1171 }
1172 Token::Ident(_, Keyword::FALSE) => {
1173 (Is::NotFalse, parser.consume().join_span(&op))
1174 }
1175 Token::Ident(_, Keyword::NULL) => {
1176 (Is::NotNull, parser.consume().join_span(&op))
1177 }
1178 Token::Ident(_, Keyword::UNKNOWN) => {
1179 (Is::NotUnknown, parser.consume().join_span(&op))
1180 }
1181 _ => parser.expected_failure("'TRUE', 'FALSE', 'UNKNOWN' or 'NULL'")?,
1182 }
1183 }
1184 Token::Ident(_, Keyword::TRUE) => (Is::True, parser.consume().join_span(&op)),
1185 Token::Ident(_, Keyword::FALSE) => (Is::False, parser.consume().join_span(&op)),
1186 Token::Ident(_, Keyword::NULL) => (Is::Null, parser.consume().join_span(&op)),
1187 Token::Ident(_, Keyword::UNKNOWN) => {
1188 (Is::Unknown, parser.consume().join_span(&op))
1189 }
1190 _ => parser.expected_failure("'NOT', 'TRUE', 'FALSE', 'UNKNOWN' or 'NULL'")?,
1191 };
1192 r.shift_expr(Expression::Is(Box::new(lhs), is, op))
1193 }
1194 Token::Ident(_, Keyword::NOT)
1195 if !matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1196 {
1197 r.shift_unary(parser.consume(), UnaryOperator::Not)
1198 }
1199 Token::Ident(_, Keyword::NOT)
1200 if !inner && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1201 {
1202 if let Err(e) = r.reduce(IN_PRIORITY) {
1203 parser.err_here(e)?;
1204 }
1205 let lhs = match r.stack.pop() {
1206 Some(ReduceMember::Expression(e)) => e,
1207 _ => parser.err_here("Expected expression before here 2")?,
1208 };
1209 let op = parser.consume_keyword(Keyword::NOT)?;
1210 match &parser.token {
1211 Token::Ident(_, Keyword::IN) => {
1212 let op = parser.consume_keyword(Keyword::IN)?.join_span(&op);
1213 parser.consume_token(Token::LParen)?;
1214 let mut rhs = Vec::new();
1215 loop {
1216 parser.recovered(
1217 "')' or ','",
1218 &|t| matches!(t, Token::RParen | Token::Comma),
1219 |parser| {
1220 rhs.push(parse_expression_paren(parser)?);
1221 Ok(())
1222 },
1223 )?;
1224 if parser.skip_token(Token::Comma).is_none() {
1225 break;
1226 }
1227 }
1228 parser.consume_token(Token::RParen)?;
1229 r.shift_expr(Expression::In {
1230 lhs: Box::new(lhs),
1231 rhs,
1232 in_span: op,
1233 not_in: true,
1234 })
1235 }
1236 Token::Ident(_, Keyword::LIKE) => {
1237 r.stack.push(ReduceMember::Expression(lhs));
1238 r.shift_binop(parser.consume().join_span(&op), BinaryOperator::NotLike)
1239 }
1240 _ => parser.expected_failure("'IN' or 'LIKE'")?,
1241 }
1242 }
1243 Token::Ident(_, Keyword::LIKE) if !inner => {
1244 r.shift_binop(parser.consume(), BinaryOperator::Like)
1245 }
1246 Token::Ident(_, Keyword::INTERVAL) => {
1247 let interval_span = parser.consume();
1248 let time_interval = match parser.token {
1249 Token::SingleQuotedString(_) | Token::DoubleQuotedString(_) => {
1250 let v = parser.consume_string()?;
1251 let mut r = Vec::new();
1252 for part in v.split([':', '!', ',', '.', '-', ' ']) {
1253 let Ok(v) = part.parse() else {
1254 parser.err("Expected . separated integers in a string", &v);
1255 continue;
1256 };
1257 r.push(v);
1258 }
1259 (r, v.span())
1260 }
1261 Token::Integer(_) => {
1262 let (v, s) = parser.consume_int()?;
1263 (vec![v], s)
1264 }
1265 _ => parser.err_here("Expected integer or string")?,
1266 };
1267 let Some(u) = parse_time_unit(&parser.token) else {
1268 parser.err_here("Expected time unit")?
1269 };
1270 let time_unit = (u, parser.consume());
1271 let e = Expression::Interval {
1272 interval_span,
1273 time_interval,
1274 time_unit,
1275 };
1276 r.shift_expr(e)
1277 }
1278 Token::Ident(_, Keyword::TIMESTAMPADD) => {
1279 let timestamp_add_span = parser.consume();
1280 parser.consume_token(Token::LParen)?;
1281 let parts = parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
1282 let Some(u) = parse_time_unit(&parser.token) else {
1283 parser.err_here("Expected time unit")?
1284 };
1285 let unit = (u, parser.consume());
1286 parser.consume_token(Token::Comma)?;
1287 let interval = parse_expression_outer(parser)?;
1288 parser.consume_token(Token::Comma)?;
1289 let datetime = parse_expression_outer(parser)?;
1290 Ok(Some((unit, Box::new(interval), Box::new(datetime))))
1291 })?;
1292 parser.consume_token(Token::RParen)?;
1293 if let Some((unit, interval, datetime)) = parts {
1294 r.shift_expr(Expression::TimestampAdd {
1295 timestamp_add_span,
1296 unit,
1297 interval,
1298 datetime,
1299 })
1300 } else {
1301 r.shift_expr(Expression::Invalid(timestamp_add_span))
1302 }
1303 }
1304 Token::Ident(_, Keyword::TIMESTAMPDIFF) => {
1305 let timestamp_diff_span = parser.consume();
1306 parser.consume_token(Token::LParen)?;
1307 let parts = parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
1308 let Some(u) = parse_time_unit(&parser.token) else {
1309 parser.err_here("Expected time unit")?
1310 };
1311 let unit = (u, parser.consume());
1312 parser.consume_token(Token::Comma)?;
1313 let e1 = parse_expression_outer(parser)?;
1314 parser.consume_token(Token::Comma)?;
1315 let e2 = parse_expression_outer(parser)?;
1316 Ok(Some((unit, Box::new(e1), Box::new(e2))))
1317 })?;
1318 parser.consume_token(Token::RParen)?;
1319 if let Some((unit, e1, e2)) = parts {
1320 r.shift_expr(Expression::TimestampDiff {
1321 timestamp_diff_span,
1322 unit,
1323 e1,
1324 e2,
1325 })
1326 } else {
1327 r.shift_expr(Expression::Invalid(timestamp_diff_span))
1328 }
1329 }
1330 Token::Plus if !inner => r.shift_binop(parser.consume(), BinaryOperator::Add),
1331 Token::Div if !inner => r.shift_binop(parser.consume(), BinaryOperator::Divide),
1332 Token::Minus if !inner => r.shift_binop(parser.consume(), BinaryOperator::Subtract),
1333 Token::Ident(_, Keyword::LIKE) if !inner => {
1334 r.shift_binop(parser.consume(), BinaryOperator::Like)
1335 }
1336 Token::Mul if !matches!(r.stack.last(), Some(ReduceMember::Expression(_))) => r
1337 .shift_expr(Expression::Identifier(vec![IdentifierPart::Star(
1338 parser.consume_token(Token::Mul)?,
1339 )])),
1340 Token::Mul if !inner && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) => {
1341 r.shift_binop(parser.consume(), BinaryOperator::Mult)
1342 }
1343 Token::Ident(_, Keyword::TRUE) => r.shift_expr(Expression::Bool(
1344 true,
1345 parser.consume_keyword(Keyword::TRUE)?,
1346 )),
1347 Token::Ident(_, Keyword::FALSE) => r.shift_expr(Expression::Bool(
1348 false,
1349 parser.consume_keyword(Keyword::FALSE)?,
1350 )),
1351 Token::Ident(_, Keyword::NULL) => {
1352 r.shift_expr(Expression::Null(parser.consume_keyword(Keyword::NULL)?))
1353 }
1354 Token::Ident(_, Keyword::_LIST_) if parser.options.list_hack => {
1355 let arg = parser.arg;
1356 parser.arg += 1;
1357 r.shift_expr(Expression::ListHack((
1358 arg,
1359 parser.consume_keyword(Keyword::_LIST_)?,
1360 )))
1361 }
1362 Token::SingleQuotedString(_) | Token::DoubleQuotedString(_) => {
1363 r.shift_expr(Expression::String(parser.consume_string()?))
1364 }
1365 Token::Integer(_) => r.shift_expr(Expression::Integer(parser.consume_int()?)),
1366 Token::Float(_) => r.shift_expr(Expression::Float(parser.consume_float()?)),
1367
1368 Token::Ident(_, Keyword::CAST) => {
1369 let cast_span = parser.consume_keyword(Keyword::CAST)?;
1370 parser.consume_token(Token::LParen)?;
1371 let cast = parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
1372 let expr = parse_expression_outer(parser)?;
1373 let as_span = parser.consume_keyword(Keyword::AS)?;
1374 let type_ = parse_data_type(parser, false)?;
1375 Ok(Some((expr, as_span, type_)))
1376 })?;
1377 parser.consume_token(Token::RParen)?;
1378 if let Some((expr, as_span, type_)) = cast {
1379 r.shift_expr(Expression::Cast {
1380 cast_span,
1381 expr: Box::new(expr),
1382 as_span,
1383 type_,
1384 })
1385 } else {
1386 r.shift_expr(Expression::Invalid(cast_span))
1387 }
1388 }
1389 Token::Ident(_, Keyword::COUNT) => {
1390 let count_span = parser.consume_keyword(Keyword::COUNT)?;
1391 parser.consume_token(Token::LParen)?;
1392 let distinct_span = parser.skip_keyword(Keyword::DISTINCT);
1393 let expr = parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
1394 let expr = parse_expression_outer(parser)?;
1395 Ok(Some(expr))
1396 })?;
1397 parser.consume_token(Token::RParen)?;
1398 if let Some(expr) = expr {
1399 r.shift_expr(Expression::Count {
1400 count_span,
1401 distinct_span,
1402 expr: Box::new(expr),
1403 })
1404 } else {
1405 r.shift_expr(Expression::Invalid(count_span))
1406 }
1407 }
1408 Token::Ident(_, Keyword::GROUP_CONCAT) => {
1409 let group_concat_span: core::ops::Range<usize> =
1410 parser.consume_keyword(Keyword::GROUP_CONCAT)?;
1411 parser.consume_token(Token::LParen)?;
1412 let distinct_span: Option<core::ops::Range<usize>> =
1413 parser.skip_keyword(Keyword::DISTINCT);
1414 let expr = parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
1415 let expr = parse_expression_outer(parser)?;
1416 Ok(Some(expr))
1417 })?;
1418 parser.consume_token(Token::RParen)?;
1424 if let Some(expr) = expr {
1425 r.shift_expr(Expression::GroupConcat {
1426 group_concat_span,
1427 distinct_span,
1428 expr: Box::new(expr),
1429 })
1430 } else {
1431 r.shift_expr(Expression::Invalid(group_concat_span))
1432 }
1433 }
1434 Token::Ident(_, Keyword::EXTRACT) => {
1435 let extract_span = parser.consume_keyword(Keyword::EXTRACT)?;
1436 parser.consume_token(Token::LParen)?;
1437 let parts = parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
1438 let Some(u) = parse_time_unit(&parser.token) else {
1439 parser.err_here("Expected time unit")?
1440 };
1441 let time_unit = (u, parser.consume());
1442 let from_span = parser.consume_keyword(Keyword::FROM)?;
1443 let date = parse_expression_outer(parser)?;
1444 Ok(Some((time_unit, from_span, Box::new(date))))
1445 })?;
1446 parser.consume_token(Token::RParen)?;
1447 if let Some((time_unit, from_span, date)) = parts {
1448 r.shift_expr(Expression::Extract {
1449 extract_span,
1450 time_unit,
1451 from_span,
1452 date,
1453 })
1454 } else {
1455 r.shift_expr(Expression::Invalid(extract_span))
1456 }
1457 }
1458 Token::Ident(_, Keyword::LEFT) if matches!(parser.peek(), Token::LParen) => {
1459 let i = parser.token.clone();
1460 let s = parser.span.clone();
1461 parser.consume();
1462 r.shift_expr(parse_function(parser, i, s)?)
1463 }
1464 Token::Ident(_, k) if k.expr_ident() => {
1465 let i = parser.token.clone();
1466 let s = parser.span.clone();
1467 parser.consume();
1468 if matches!(parser.token, Token::LParen) {
1469 r.shift_expr(parse_function(parser, i, s)?)
1470 } else {
1471 let f = match i {
1472 Token::Ident(_, Keyword::CURRENT_TIMESTAMP) => {
1473 Some(Function::CurrentTimestamp)
1474 }
1475 Token::Ident(_, Keyword::LOCALTIME | Keyword::LOCALTIMESTAMP) => {
1476 Some(Function::Now)
1477 }
1478 Token::Ident(_, Keyword::UTC_TIMESTAMP) => Some(Function::UtcTimeStamp),
1479 Token::Ident(_, Keyword::UTC_DATE) => Some(Function::UtcDate),
1480 Token::Ident(_, Keyword::UTC_TIME) => Some(Function::UtcTime),
1481 Token::Ident(_, Keyword::CURRENT_DATE) => Some(Function::CurDate),
1482 Token::Ident(_, Keyword::CURRENT_TIME) => Some(Function::CurTime),
1483 _ => None,
1484 };
1485 if let Some(f) = f {
1486 r.shift_expr(Expression::Function(f, Vec::new(), s))
1487 } else {
1488 let mut parts = vec![IdentifierPart::Name(
1489 parser.token_to_plain_identifier(&i, s)?,
1490 )];
1491 loop {
1492 if parser.skip_token(Token::Period).is_none() {
1493 break;
1494 }
1495 match &parser.token {
1496 Token::Mul => parts
1497 .push(IdentifierPart::Star(parser.consume_token(Token::Mul)?)),
1498 Token::Ident(_, _) => parts
1499 .push(IdentifierPart::Name(parser.consume_plain_identifier()?)),
1500 _ => parser.expected_failure("Identifier or '*'")?,
1501 }
1502 }
1503 r.shift_expr(Expression::Identifier(parts))
1504 }
1505 }
1506 }
1507 Token::QuestionMark
1508 if matches!(parser.options.arguments, crate::SQLArguments::QuestionMark) =>
1509 {
1510 let arg = parser.arg;
1511 parser.arg += 1;
1512 r.shift_expr(Expression::Arg((
1513 arg,
1514 parser.consume_token(Token::QuestionMark)?,
1515 )))
1516 }
1517 Token::PercentS if matches!(parser.options.arguments, crate::SQLArguments::Percent) => {
1518 let arg = parser.arg;
1519 parser.arg += 1;
1520 r.shift_expr(Expression::Arg((
1521 arg,
1522 parser.consume_token(Token::PercentS)?,
1523 )))
1524 }
1525 Token::DollarArg(arg)
1526 if matches!(parser.options.arguments, crate::SQLArguments::Dollar) =>
1527 {
1528 r.shift_expr(Expression::Arg((arg - 1, parser.consume())))
1529 }
1530 Token::LParen => {
1531 parser.consume_token(Token::LParen)?;
1532 let ans = parse_expression_paren(parser)?;
1533 parser.consume_token(Token::RParen)?;
1534 r.shift_expr(ans)
1535 }
1536 Token::Ident(_, Keyword::EXISTS) => {
1537 parser.consume_keyword(Keyword::EXISTS)?;
1538 parser.consume_token(Token::LParen)?;
1539 let ans = Expression::Exists(Box::new(parse_compound_query(parser)?));
1540 parser.consume_token(Token::RParen)?;
1541 r.shift_expr(ans)
1542 }
1543 Token::Ident(_, Keyword::CASE) => {
1544 let case_span = parser.consume_keyword(Keyword::CASE)?;
1545 let value = if !matches!(parser.token, Token::Ident(_, Keyword::WHEN)) {
1546 Some(Box::new(parse_expression(parser, false)?))
1547 } else {
1548 None
1549 };
1550 let mut whens = Vec::new();
1551 let mut else_ = None;
1552 parser.recovered(
1553 "'END'",
1554 &|t| matches!(t, Token::Ident(_, Keyword::END)),
1555 |parser| {
1556 loop {
1557 let when_span = parser.consume_keyword(Keyword::WHEN)?;
1558 let when = parse_expression(parser, false)?;
1559 let then_span = parser.consume_keyword(Keyword::THEN)?;
1560 let then = parse_expression(parser, false)?;
1561 whens.push(When {
1562 when_span,
1563 when,
1564 then_span,
1565 then,
1566 });
1567 if !matches!(parser.token, Token::Ident(_, Keyword::WHEN)) {
1568 break;
1569 }
1570 }
1571 if let Some(span) = parser.skip_keyword(Keyword::ELSE) {
1572 else_ = Some((span, Box::new(parse_expression(parser, false)?)))
1573 };
1574 Ok(())
1575 },
1576 )?;
1577 let end_span = parser.consume_keyword(Keyword::END)?;
1578 r.shift_expr(Expression::Case {
1579 case_span,
1580 value,
1581 whens,
1582 else_,
1583 end_span,
1584 })
1585 }
1586 Token::AtAtGlobal | Token::AtAtSession => {
1587 let global = parser.skip_token(Token::AtAtGlobal);
1588 let session = if global.is_none() {
1589 Some(parser.consume_token(Token::AtAtSession)?)
1590 } else {
1591 None
1592 };
1593 let dot = Some(parser.consume_token(Token::Period)?);
1594 let variable = match &parser.token {
1595 Token::Ident(_, Keyword::TIME_ZONE) => Variable::TimeZone,
1596 Token::Ident(t, _) => Variable::Other(t),
1597 _ => parser.expected_failure("Identifier")?,
1598 };
1599 let variable_span = parser.consume();
1600 r.shift_expr(Expression::Variable {
1601 global,
1602 session,
1603 dot,
1604 variable,
1605 variable_span,
1606 })
1607 }
1608 _ => break,
1609 };
1610 if let Err(e) = e {
1611 parser.err_here(e.to_string())?;
1612 }
1613 }
1614 if r.reduce(99999).is_err() {
1615 parser.err_here("Expected expression")
1616 } else if r.stack.len() != 1 {
1617 parser.ice(file!(), line!())
1618 } else if let Some(ReduceMember::Expression(e)) = r.stack.pop() {
1619 Ok(e)
1620 } else {
1621 parser.ice(file!(), line!())
1622 }
1623}
1624
1625pub(crate) fn parse_expression_outer<'a>(
1626 parser: &mut Parser<'a, '_>,
1627) -> Result<Expression<'a>, ParseError> {
1628 if matches!(parser.token, Token::Ident(_, Keyword::SELECT)) {
1629 Ok(Expression::Subquery(Box::new(Statement::Select(
1630 parse_select(parser)?,
1631 ))))
1632 } else {
1633 parse_expression(parser, false)
1634 }
1635}
1636
1637pub(crate) fn parse_expression_paren<'a>(
1638 parser: &mut Parser<'a, '_>,
1639) -> Result<Expression<'a>, ParseError> {
1640 if matches!(parser.token, Token::Ident(_, Keyword::SELECT)) {
1641 Ok(Expression::Subquery(Box::new(parse_compound_query(
1642 parser,
1643 )?)))
1644 } else {
1645 parse_expression(parser, false)
1646 }
1647}
1648
1649#[cfg(test)]
1650mod tests {
1651 use core::ops::Deref;
1652
1653 use alloc::{
1654 format,
1655 string::{String, ToString},
1656 };
1657
1658 use crate::{
1659 expression::{BinaryOperator, Expression},
1660 issue::Issues,
1661 parser::Parser,
1662 Function, ParseOptions, SQLDialect,
1663 };
1664
1665 use super::{parse_expression, IdentifierPart};
1666
1667 fn test_ident<'a>(e: impl AsRef<Expression<'a>>, v: &str) -> Result<(), String> {
1668 let v = match e.as_ref() {
1669 Expression::Identifier(a) => match a.as_slice() {
1670 [IdentifierPart::Name(vv)] => vv.deref() == v,
1671 _ => false,
1672 },
1673 _ => false,
1674 };
1675 if !v {
1676 Err(format!("Expected identifier {} found {:?}", v, e.as_ref()))
1677 } else {
1678 Ok(())
1679 }
1680 }
1681
1682 fn test_expr(src: &'static str, f: impl FnOnce(&Expression<'_>) -> Result<(), String>) {
1683 let mut issues = Issues::new(src);
1684 let options = ParseOptions::new().dialect(SQLDialect::MariaDB);
1685 let mut parser = Parser::new(src, &mut issues, &options);
1686 let res = parse_expression(&mut parser, false).expect("Expression in test expr");
1687 if let Err(e) = f(&res) {
1688 panic!("Error parsing {}: {}\nGot {:#?}", src, e, res);
1689 }
1690 }
1691
1692 #[test]
1693 fn expressions() {
1694 test_expr("`a` + `b` * `c` + `d`", |e| {
1695 match e {
1696 Expression::Binary {
1697 op: BinaryOperator::Add,
1698 lhs,
1699 rhs,
1700 ..
1701 } => {
1702 match lhs.as_ref() {
1703 Expression::Binary {
1704 op: BinaryOperator::Add,
1705 lhs,
1706 rhs,
1707 ..
1708 } => {
1709 test_ident(lhs, "a")?;
1710 match rhs.as_ref() {
1711 Expression::Binary {
1712 op: BinaryOperator::Mult,
1713 lhs,
1714 rhs,
1715 ..
1716 } => {
1717 test_ident(lhs, "b")?;
1718 test_ident(rhs, "c")?;
1719 }
1720 _ => return Err("Lhs.Rhs".to_string()),
1721 }
1722 }
1723 _ => return Err("Lhs".to_string()),
1724 }
1725 test_ident(rhs, "d")?;
1726 }
1727 _ => return Err("Outer".to_string()),
1728 }
1729 Ok(())
1730 });
1731 }
1732
1733 #[test]
1734 fn mariadb_datetime_functions() {
1735 fn test_func(src: &'static str, f: Function, cnt: usize) {
1736 let mut issues = Issues::new(src);
1737 let options = ParseOptions::new().dialect(SQLDialect::MariaDB);
1738 let mut parser = Parser::new(src, &mut issues, &options);
1739 let res = match parse_expression(&mut parser, false) {
1740 Ok(res) => res,
1741 Err(e) => panic!("Unable to parse {}: {:?}", src, e),
1742 };
1743 let Expression::Function(pf, args, _) = res else {
1744 panic!("Should be parsed as function {}", src);
1745 };
1746 assert_eq!(pf, f, "Failure en expr {}", src);
1747 assert_eq!(args.len(), cnt, "Failure en expr {}", src);
1748 }
1749 test_func("ADD_MONTHS('2012-01-31', 2)", Function::AddMonths, 2);
1750 test_func(
1751 "ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002')",
1752 Function::AddTime,
1753 2,
1754 );
1755 test_func(
1756 "DATE_ADD('2008-01-02', INTERVAL 31 DAY)",
1757 Function::AddDate,
1758 2,
1759 );
1760 test_func(
1761 "ADDDATE('2008-01-02', INTERVAL 31 DAY)",
1762 Function::AddDate,
1763 2,
1764 );
1765 test_func("ADDDATE('2008-01-02', 31)", Function::AddDate, 2);
1766 test_func(
1767 "CONVERT_TZ('2016-01-01 12:00:00','+00:00','+10:00')",
1768 Function::ConvertTz,
1769 3,
1770 );
1771 test_func("CURDATE()", Function::CurDate, 0);
1772 test_func("CURRENT_DATE", Function::CurDate, 0);
1773 test_func("CURRENT_DATE()", Function::CurDate, 0);
1774 test_func("CURRENT_TIME", Function::CurTime, 0);
1775 test_func("CURRENT_TIME()", Function::CurTime, 0);
1776 test_func("CURTIME()", Function::CurTime, 0);
1777 test_func("CURTIME(2)", Function::CurTime, 1);
1778 test_func("CURRENT_DATE", Function::CurDate, 0);
1779 test_func("CURRENT_DATE()", Function::CurDate, 0);
1780 test_func("CURDATE()", Function::CurDate, 0);
1781 test_func("CURRENT_TIMESTAMP", Function::CurrentTimestamp, 0);
1782 test_func("CURRENT_TIMESTAMP()", Function::CurrentTimestamp, 0);
1783 test_func("CURRENT_TIMESTAMP(10)", Function::CurrentTimestamp, 1);
1784 test_func("LOCALTIME", Function::Now, 0);
1785 test_func("LOCALTIME()", Function::Now, 0);
1786 test_func("LOCALTIME(10)", Function::Now, 1);
1787 test_func("LOCALTIMESTAMP", Function::Now, 0);
1788 test_func("LOCALTIMESTAMP()", Function::Now, 0);
1789 test_func("LOCALTIMESTAMP(10)", Function::Now, 1);
1790 test_func("DATE('2013-07-18 12:21:32')", Function::Date, 1);
1791 test_func(
1792 "DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y')",
1793 Function::DateFormat,
1794 2,
1795 );
1796 test_func(
1797 "DATE_SUB('1998-01-02', INTERVAL 31 DAY)",
1798 Function::DateSub,
1799 2,
1800 );
1801 test_func("DAY('2007-02-03')", Function::DayOfMonth, 1);
1802 test_func("DAYOFMONTH('2007-02-03')", Function::DayOfMonth, 1);
1803 test_func(
1804 "DATEDIFF('2007-12-31 23:59:59','2007-12-30')",
1805 Function::DateDiff,
1806 2,
1807 );
1808 test_func("DAYNAME('2007-02-03')", Function::DayName, 1);
1809 test_func("DAYOFYEAR('2018-02-16')", Function::DayOfYear, 1);
1810 test_func("DAYOFWEEK('2007-02-03')", Function::DayOfWeek, 1);
1811 test_expr("EXTRACT(YEAR_MONTH FROM '2009-07-02 01:02:03')", |e| {
1812 let Expression::Extract { .. } = e else {
1813 return Err("Wrong type".to_string());
1814 };
1815 Ok(())
1816 });
1817 test_func("FROM_DAYS(730669)", Function::FromDays, 1);
1819 test_func("FROM_UNIXTIME(1196440219)", Function::FromUnixTime, 1);
1820 test_func(
1821 "FROM_UNIXTIME(UNIX_TIMESTAMP(), '%Y %D %M %h:%i:%s %x')",
1822 Function::FromUnixTime,
1823 2,
1824 );
1825 test_func("HOUR('10:05:03')", Function::Hour, 1);
1827 test_func("LAST_DAY('2004-01-01 01:01:01')", Function::LastDay, 1);
1828 test_func("MAKEDATE(2011,31)", Function::MakeDate, 2);
1829 test_func("MAKETIME(-13,57,33)", Function::MakeTime, 3);
1830 test_func("MICROSECOND('12:00:00.123456')", Function::MicroSecond, 1);
1831 test_func("MINUTE('2013-08-03 11:04:03')", Function::Minute, 1);
1832 test_func("MONTH('2019-01-03')", Function::Month, 1);
1833 test_func("MONTHNAME('2019-02-03')", Function::MonthName, 1);
1834 test_func("PERIOD_ADD(200801,2)", Function::PeriodAdd, 2);
1835 test_func("PERIOD_DIFF(200802,200703)", Function::PeriodDiff, 2);
1836 test_func("QUARTER('2008-04-01')", Function::Quarter, 1);
1837 test_func("SEC_TO_TIME(12414)", Function::SecToTime, 1);
1838 test_func("SECOND('10:05:03')", Function::Second, 1);
1839 test_func(
1840 "STR_TO_DATE('Wednesday, June 2, 2014', '%W, %M %e, %Y')",
1841 Function::StrToDate,
1842 2,
1843 );
1844 test_func(
1845 "DATE_SUB('2008-01-02', INTERVAL 31 DAY)",
1846 Function::DateSub,
1847 2,
1848 );
1849 test_func("SUBDATE('2008-01-02 12:00:00', 31)", Function::DateSub, 2);
1850 test_func(
1851 "SUBDATE('2008-01-02', INTERVAL 31 DAY)",
1852 Function::DateSub,
1853 2,
1854 );
1855 test_func(
1856 "SUBTIME('2007-12-31 23:59:59.999999','1 1:1:1.000002')",
1857 Function::SubTime,
1858 2,
1859 );
1860 test_func("SYSDATE()", Function::SysDate, 0);
1861 test_func("SYSDATE(4)", Function::SysDate, 1);
1862 test_func("TIME('2003-12-31 01:02:03')", Function::Time, 1);
1863 test_func(
1864 "TIME_FORMAT('100:00:00', '%H %k %h %I %l')",
1865 Function::TimeFormat,
1866 2,
1867 );
1868 test_func("TIME_TO_SEC('22:23:00')", Function::TimeToSec, 1);
1869 test_func(
1870 "TIMEDIFF('2008-12-31 23:59:59.000001', '2008-12-30 01:01:01.000002')",
1871 Function::TimeDiff,
1872 2,
1873 );
1874 test_func("TIMESTAMP('2003-12-31')", Function::Timestamp, 1);
1875 test_func(
1876 "TIMESTAMP('2003-12-31 12:00:00','6:30:00')",
1877 Function::Timestamp,
1878 2,
1879 );
1880 test_expr("TIMESTAMPADD(MINUTE,1,'2003-01-02')", |e| {
1881 let Expression::TimestampAdd { .. } = e else {
1882 return Err("Wrong type".to_string());
1883 };
1884 Ok(())
1885 });
1886 test_expr("TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');", |e| {
1887 let Expression::TimestampDiff { .. } = e else {
1888 return Err("Wrong type".to_string());
1889 };
1890 Ok(())
1891 });
1892 test_func("TO_DAYS('2007-10-07')", Function::ToDays, 1);
1893 test_func("UNIX_TIMESTAMP()", Function::UnixTimestamp, 0);
1894 test_func(
1895 "UNIX_TIMESTAMP('2007-11-30 10:30:19')",
1896 Function::UnixTimestamp,
1897 1,
1898 );
1899 test_func("UTC_DATE", Function::UtcDate, 0);
1900 test_func("UTC_DATE()", Function::UtcDate, 0);
1901 test_func("UTC_TIME", Function::UtcTime, 0);
1902 test_func("UTC_TIME()", Function::UtcTime, 0);
1903 test_func("UTC_TIME(5)", Function::UtcTime, 1);
1904 test_func("UTC_TIMESTAMP", Function::UtcTimeStamp, 0);
1905 test_func("UTC_TIMESTAMP()", Function::UtcTimeStamp, 0);
1906 test_func("UTC_TIMESTAMP(4)", Function::UtcTimeStamp, 1);
1907 test_func("WEEK('2008-02-20')", Function::Week, 1);
1908 test_func("WEEK('2008-02-20',0)", Function::Week, 2);
1909 test_func("WEEKDAY('2008-02-03 22:23:00')", Function::Weekday, 1);
1910 test_func("WEEKOFYEAR('2008-02-20')", Function::WeekOfYear, 1);
1911 test_func("YEAR('1987-01-01')", Function::Year, 1);
1912 test_func("YEARWEEK('1987-01-01')", Function::YearWeek, 1);
1913 test_func("YEARWEEK('1987-01-01',0)", Function::YearWeek, 2);
1914 }
1915}