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