Skip to main content

qusql_parse/
function_expression.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5// http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12
13use crate::{
14    Expression, Identifier, OptSpanned, Span, Spanned,
15    expression::{PRIORITY_MAX, parse_expression_outer, parse_expression_unreserved},
16    keywords::Keyword,
17    lexer::Token,
18    parser::{ParseError, Parser},
19    select::OrderFlag,
20};
21use alloc::{boxed::Box, vec::Vec};
22
23/// Function to execute
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum Function<'a> {
26    Abs,
27    Acos,
28    AddDate,
29    AddMonths,
30    AddTime,
31    Ascii,
32    Asin,
33    Atan,
34    Atan2,
35    Bin,
36    BitLength,
37    Ceil,
38    Char,
39    CharacterLength,
40    Chr,
41    Concat,
42    ConcatWs,
43    Conv,
44    ConvertTz,
45    Cos,
46    Cot,
47    Crc32,
48    Crc32c,
49    CurrentCatalog,
50    CurrentRole,
51    CurrentUser,
52    CurDate,
53    CurrentTimestamp,
54    CurTime,
55    SessionUser,
56    Date,
57    DateDiff,
58    DateFormat,
59    DateSub,
60    Datetime,
61    DayName,
62    DayOfMonth,
63    DayOfWeek,
64    DayOfYear,
65    Degrees,
66    Elt,
67    Exists,
68    Exp,
69    ExportSet,
70    ExtractValue,
71    Field,
72    FindInSet,
73    Floor,
74    Format,
75    FromBase64,
76    FromDays,
77    FromUnixTime,
78    Greatest,
79    Hex,
80    Hour,
81    If,
82    IfNull,
83    Insert,
84    InStr,
85    JsonArray,
86    JsonArrayAgg,
87    JsonArrayAppend,
88    JsonArrayInsert,
89    JsonArrayIntersect,
90    JsonCompact,
91    JsonContains,
92    JsonContainsPath,
93    JsonDepth,
94    JsonDetailed,
95    JsonEquals,
96    JsonExists,
97    JsonExtract,
98    JsonInsert,
99    JsonKeys,
100    JsonLength,
101    JsonLoose,
102    JsonMerge,
103    JsonMergePath,
104    JsonMergePerserve,
105    JsonNormalize,
106    JsonObject,
107    JsonObjectAgg,
108    JsonObjectFilterKeys,
109    JsonObjectToArray,
110    JsonOverlaps,
111    JsonPretty,
112    JsonQuery,
113    JsonQuote,
114    JsonRemove,
115    JsonReplace,
116    JsonSchemaValid,
117    JsonSearch,
118    JsonSet,
119    JsonTable,
120    JsonType,
121    JsonUnquote,
122    JsonValid,
123    JsonValue,
124    Lag,
125    LastDay,
126    Avg,
127    Count,
128    LCase,
129    Lead,
130    Least,
131    Left,
132    Length,
133    LengthB,
134    Ln,
135    LoadFile,
136    Locate,
137    Log,
138    Log10,
139    Log2,
140    Lower,
141    LPad,
142    LTrim,
143    MakeDate,
144    MakeSet,
145    MakeTime,
146    Max,
147    MicroSecond,
148    Mid,
149    Min,
150    Minute,
151    Mod,
152    Month,
153    MonthName,
154    NaturalSortkey,
155    Now,
156    NullIf,
157    NVL2,
158    Oct,
159    OctetLength,
160    Ord,
161    PeriodAdd,
162    PeriodDiff,
163    Pi,
164    Position,
165    Pow,
166    Quarter,
167    Quote,
168    Radians,
169    Rand,
170    Repeat,
171    Replace,
172    Reverse,
173    Right,
174    Round,
175    RPad,
176    RTrim,
177    Second,
178    SecToTime,
179    SFormat,
180    Sign,
181    Sin,
182    Sleep,
183    SoundEx,
184    Space,
185    Sqrt,
186    StartsWith,
187    StrCmp,
188    Strftime,
189    StrToDate,
190    SubStr,
191    SubStringIndex,
192    SubTime,
193    Sum,
194    SysDate,
195    Tan,
196    Time,
197    TimeDiff,
198    TimeFormat,
199    Timestamp,
200    TimeToSec,
201    ToBase64,
202    ToChar,
203    ToDays,
204    ToSeconds,
205    Truncate,
206    UCase,
207    UncompressedLength,
208    UnHex,
209    UnixTimestamp,
210    Unknown,
211    UpdateXml,
212    Upper,
213    UtcDate,
214    UtcTime,
215    UtcTimeStamp,
216    Value,
217    Week,
218    Weekday,
219    WeekOfYear,
220    Year,
221    YearWeek,
222    // MySQL 8.4 explicit functions
223    AesDecrypt,
224    AesEncrypt,
225    AnyValue,
226    Benchmark,
227    BinToUuid,
228    BitCount,
229    Charset,
230    Coercibility,
231    Collation,
232    Compress,
233    ConnectionId,
234    DatabaseFunc,
235    FirstValue,
236    FormatBytes,
237    FormatPicoTime,
238    FoundRows,
239    GetFormat,
240    GetLock,
241    Grouping,
242    IcuVersion,
243    Inet6Aton,
244    Inet6Ntoa,
245    InetAton,
246    InetNtoa,
247    IsFreeLock,
248    IsIPv4,
249    IsIPv4Compat,
250    IsIPv4Mapped,
251    IsIPv6,
252    IsUsedLock,
253    IsUuid,
254    LastInsertId,
255    LastValue,
256    Md5,
257    NameConst,
258    NthValue,
259    Ntile,
260    PsCurrentThreadId,
261    PsThreadId,
262    RandomBytes,
263    RegexpInstr,
264    RegexpLike,
265    RegexpReplace,
266    RegexpSubstr,
267    ReleaseAllLocks,
268    ReleaseLock,
269    RolesGraphml,
270    RowCount,
271    RowNumber,
272    SchemaFunc,
273    SessionUserFunc,
274    Sha,
275    Sha1,
276    Sha2,
277    StatementDigest,
278    StatementDigestText,
279    SystemUser,
280    Uncompress,
281    UserFunc,
282    Uuid,
283    UuidShort,
284    UuidToBin,
285    ValidatePasswordStrength,
286    Version,
287    WeightString,
288    ArrayAgg,
289    BitAnd,
290    BitOr,
291    BitXor,
292    BoolAnd,
293    BoolOr,
294    Corr,
295    CovarPop,
296    CovarSamp,
297    CumeDist,
298    DenseRank,
299    JsonAgg,
300    JsonbAgg,
301    JsonbObjectAgg,
302    PercentRank,
303    PercentileCont,
304    PercentileDisc,
305    Rank,
306    RegrAvgx,
307    RegrAvgy,
308    RegrCount,
309    RegrIntercept,
310    RegrR2,
311    RegrSlope,
312    RegrSxx,
313    RegrSxy,
314    RegrSyy,
315    Mode,
316    Std,
317    Stddev,
318    StddevPop,
319    StddevSamp,
320    StringAgg,
321    Variance,
322    VarPop,
323    VarSamp,
324    Xmlagg,
325    Other(Vec<Identifier<'a>>),
326}
327
328/// Function call expression,
329#[derive(Debug, Clone)]
330pub struct FunctionCallExpression<'a> {
331    pub function: Function<'a>,
332    pub args: Vec<Expression<'a>>,
333    pub function_span: Span,
334}
335
336impl Spanned for FunctionCallExpression<'_> {
337    fn span(&self) -> Span {
338        self.function_span.join_span(&self.args)
339    }
340}
341
342/// CHAR(N,... [USING charset_name]) expression
343#[derive(Debug, Clone)]
344pub struct CharFunctionExpression<'a> {
345    /// Span of "CHAR"
346    pub char_span: Span,
347    /// Arguments to CHAR()
348    pub args: Vec<Expression<'a>>,
349    /// Optional USING charset_name clause
350    pub using_charset: Option<(Span, Identifier<'a>)>,
351}
352
353impl<'a> Spanned for CharFunctionExpression<'a> {
354    fn span(&self) -> Span {
355        self.char_span
356            .join_span(&self.args)
357            .join_span(&self.using_charset)
358    }
359}
360
361/// Window frame mode: ROWS, RANGE, or GROUPS
362#[derive(Debug, Clone)]
363pub enum WindowFrameMode {
364    Rows(Span),
365    Range(Span),
366    Groups(Span),
367}
368
369impl Spanned for WindowFrameMode {
370    fn span(&self) -> Span {
371        match self {
372            WindowFrameMode::Rows(s) | WindowFrameMode::Range(s) | WindowFrameMode::Groups(s) => {
373                s.clone()
374            }
375        }
376    }
377}
378
379/// One bound in a window frame clause
380#[derive(Debug, Clone)]
381pub enum WindowFrameBound<'a> {
382    /// UNBOUNDED PRECEDING
383    UnboundedPreceding(Span),
384    /// <expr> PRECEDING
385    Preceding(Expression<'a>, Span),
386    /// CURRENT ROW
387    CurrentRow(Span),
388    /// <expr> FOLLOWING
389    Following(Expression<'a>, Span),
390    /// UNBOUNDED FOLLOWING
391    UnboundedFollowing(Span),
392}
393
394impl<'a> Spanned for WindowFrameBound<'a> {
395    fn span(&self) -> Span {
396        match self {
397            WindowFrameBound::UnboundedPreceding(s) => s.clone(),
398            WindowFrameBound::Preceding(e, s) => e.span().join_span(s),
399            WindowFrameBound::CurrentRow(s) => s.clone(),
400            WindowFrameBound::Following(e, s) => e.span().join_span(s),
401            WindowFrameBound::UnboundedFollowing(s) => s.clone(),
402        }
403    }
404}
405
406/// Window frame clause: ROWS/RANGE/GROUPS { frame_start | BETWEEN frame_start AND frame_end }
407#[derive(Debug, Clone)]
408pub struct WindowFrame<'a> {
409    /// ROWS, RANGE, or GROUPS
410    pub mode: WindowFrameMode,
411    /// The start bound (or sole bound when no BETWEEN)
412    pub start: WindowFrameBound<'a>,
413    /// When BETWEEN was used: span covering "BETWEEN ... AND" and the end bound
414    pub between: Option<(Span, WindowFrameBound<'a>)>,
415}
416
417impl<'a> Spanned for WindowFrame<'a> {
418    fn span(&self) -> Span {
419        let s = self.mode.span().join_span(&self.start);
420        if let Some((and_span, end)) = &self.between {
421            s.join_span(and_span).join_span(end)
422        } else {
423            s
424        }
425    }
426}
427
428/// When part of CASE
429#[derive(Debug, Clone)]
430pub struct WindowSpec<'a> {
431    /// Span of "PARTITION BY" and list of partition expressions, if specified
432    pub partition_by: Option<(Span, Vec<Expression<'a>>)>,
433    /// Span of "ORDER BY" and list of order expression and directions, if specified
434    pub order_by: Option<(Span, Vec<(Expression<'a>, OrderFlag)>)>,
435    /// Window frame clause (ROWS/RANGE BETWEEN ... AND ...), if specified
436    pub frame: Option<WindowFrame<'a>>,
437}
438
439impl<'a> Spanned for WindowSpec<'a> {
440    fn span(&self) -> Span {
441        self.partition_by
442            .opt_join_span(&self.order_by)
443            .opt_join_span(&self.frame)
444            .expect("Either partition_by, order_by, or frame must be specified")
445    }
446}
447
448#[derive(Debug, Clone)]
449pub struct WindowClause<'a> {
450    pub over_span: Span,
451    pub window_spec: WindowSpec<'a>,
452}
453
454impl Spanned for WindowClause<'_> {
455    fn span(&self) -> Span {
456        self.over_span.join_span(&self.window_spec)
457    }
458}
459
460/// A window function call expression
461#[derive(Debug, Clone)]
462pub struct WindowFunctionCallExpression<'a> {
463    pub function: Function<'a>,
464    pub args: Vec<Expression<'a>>,
465    pub function_span: Span,
466    pub over: WindowClause<'a>,
467}
468
469impl Spanned for WindowFunctionCallExpression<'_> {
470    fn span(&self) -> Span {
471        self.function_span
472            .join_span(&self.args)
473            .join_span(&self.over)
474    }
475}
476
477#[derive(Debug, Clone)]
478pub struct AggregateFunctionCallExpression<'a> {
479    pub function: Function<'a>,
480    pub args: Vec<Expression<'a>>,
481    pub function_span: Span,
482    pub distinct_span: Option<Span>,
483    pub within_group: Option<(Span, Vec<(Expression<'a>, OrderFlag)>)>,
484    pub filter: Option<(Span, Expression<'a>)>,
485    pub over: Option<WindowClause<'a>>,
486}
487
488impl Spanned for AggregateFunctionCallExpression<'_> {
489    fn span(&self) -> Span {
490        self.function_span
491            .join_span(&self.args)
492            .join_span(&self.distinct_span)
493            .join_span(&self.within_group)
494            .join_span(&self.filter)
495            .join_span(&self.over)
496    }
497}
498
499pub(crate) fn is_aggregate_function_ident(keyword: &Keyword) -> bool {
500    matches!(
501        keyword,
502        Keyword::COUNT
503            | Keyword::AVG
504            | Keyword::SUM
505            | Keyword::MIN
506            | Keyword::MAX
507            | Keyword::JSON_ARRAYAGG
508            | Keyword::JSON_OBJECTAGG
509            | Keyword::ARRAY_AGG
510            | Keyword::BIT_AND
511            | Keyword::BIT_OR
512            | Keyword::BIT_XOR
513            | Keyword::BOOL_AND
514            | Keyword::BOOL_OR
515            | Keyword::CORR
516            | Keyword::COVAR_POP
517            | Keyword::COVAR_SAMP
518            | Keyword::CUME_DIST
519            | Keyword::DENSE_RANK
520            | Keyword::EVERY
521            | Keyword::JSON_AGG
522            | Keyword::JSONB_AGG
523            | Keyword::JSONB_OBJECT_AGG
524            | Keyword::PERCENT_RANK
525            | Keyword::PERCENTILE_CONT
526            | Keyword::PERCENTILE_DISC
527            | Keyword::RANK
528            | Keyword::REGR_AVGX
529            | Keyword::REGR_AVGY
530            | Keyword::REGR_COUNT
531            | Keyword::REGR_INTERCEPT
532            | Keyword::REGR_R2
533            | Keyword::REGR_SLOPE
534            | Keyword::REGR_SXX
535            | Keyword::REGR_SXY
536            | Keyword::REGR_SYY
537            | Keyword::STD
538            | Keyword::STDDEV
539            | Keyword::STDDEV_POP
540            | Keyword::STDDEV_SAMP
541            | Keyword::STRING_AGG
542            | Keyword::VARIANCE
543            | Keyword::VAR_POP
544            | Keyword::VAR_SAMP
545            | Keyword::XMLAGG
546            | Keyword::MODE
547    )
548}
549
550fn parse_window_frame_bound<'a>(
551    parser: &mut Parser<'a, '_>,
552) -> Result<WindowFrameBound<'a>, ParseError> {
553    match &parser.token {
554        Token::Ident(_, Keyword::UNBOUNDED) => {
555            let kw_span = parser.consume_keyword(Keyword::UNBOUNDED)?;
556            if let Some(span) = parser.skip_keyword(Keyword::PRECEDING) {
557                Ok(WindowFrameBound::UnboundedPreceding(
558                    kw_span.join_span(&span),
559                ))
560            } else {
561                Ok(WindowFrameBound::UnboundedFollowing(
562                    parser
563                        .consume_keyword(Keyword::FOLLOWING)?
564                        .join_span(&kw_span),
565                ))
566            }
567        }
568        Token::Ident(_, Keyword::CURRENT) => {
569            let current_row_span = parser.consume_keywords(&[Keyword::CURRENT, Keyword::ROW])?;
570            Ok(WindowFrameBound::CurrentRow(current_row_span))
571        }
572        _ => {
573            let expr = parse_expression_unreserved(parser, PRIORITY_MAX)?;
574            if let Some(s) = parser.skip_keyword(Keyword::PRECEDING) {
575                Ok(WindowFrameBound::Preceding(expr, s))
576            } else {
577                let s = parser.consume_keyword(Keyword::FOLLOWING)?;
578                Ok(WindowFrameBound::Following(expr, s))
579            }
580        }
581    }
582}
583
584fn parse_window_frame<'a>(
585    parser: &mut Parser<'a, '_>,
586    mode: WindowFrameMode,
587) -> Result<WindowFrame<'a>, ParseError> {
588    if let Some(between_span) = parser.skip_keyword(Keyword::BETWEEN) {
589        let start = parse_window_frame_bound(parser)?;
590        let and_span = parser.consume_keyword(Keyword::AND)?;
591        let end = parse_window_frame_bound(parser)?;
592        Ok(WindowFrame {
593            mode,
594            start,
595            between: Some((between_span.join_span(&and_span), end)),
596        })
597    } else {
598        let start = parse_window_frame_bound(parser)?;
599        Ok(WindowFrame {
600            mode,
601            start,
602            between: None,
603        })
604    }
605}
606
607fn parse_over_clause<'a>(
608    parser: &mut Parser<'a, '_>,
609) -> Result<Option<WindowClause<'a>>, ParseError> {
610    let Some(over_span) = parser.skip_keyword(Keyword::OVER) else {
611        return Ok(None);
612    };
613
614    parser.consume_token(Token::LParen)?;
615
616    let partition_by = if let Some(partition_span) = parser.skip_keyword(Keyword::PARTITION) {
617        let partition_by_span = partition_span.join_span(&parser.consume_keyword(Keyword::BY)?);
618        let mut partition_exprs = Vec::new();
619        loop {
620            partition_exprs.push(parse_expression_unreserved(parser, PRIORITY_MAX)?);
621            if parser.skip_token(Token::Comma).is_none() {
622                break;
623            }
624        }
625        Some((partition_by_span, partition_exprs))
626    } else {
627        None
628    };
629
630    let order_by = if let Some(span) = parser.skip_keyword(Keyword::ORDER) {
631        let order_span = span.join_span(&parser.consume_keyword(Keyword::BY)?);
632        let mut order = Vec::new();
633        loop {
634            let e = parse_expression_unreserved(parser, PRIORITY_MAX)?;
635            let f = match &parser.token {
636                Token::Ident(_, Keyword::ASC) => OrderFlag::Asc(parser.consume()),
637                Token::Ident(_, Keyword::DESC) => OrderFlag::Desc(parser.consume()),
638                _ => OrderFlag::None,
639            };
640            order.push((e, f));
641            if parser.skip_token(Token::Comma).is_none() {
642                break;
643            }
644        }
645        Some((order_span, order))
646    } else {
647        None
648    };
649
650    // Window frame clause: ROWS/RANGE { frame_start | BETWEEN frame_start AND frame_end }
651    let frame = if let Some(s) = parser.skip_keyword(Keyword::ROWS) {
652        Some(parse_window_frame(parser, WindowFrameMode::Rows(s))?)
653    } else if let Some(s) = parser.skip_keyword(Keyword::RANGE) {
654        Some(parse_window_frame(parser, WindowFrameMode::Range(s))?)
655    } else {
656        None
657    };
658
659    parser.consume_token(Token::RParen)?;
660
661    Ok(Some(WindowClause {
662        over_span,
663        window_spec: WindowSpec {
664            partition_by,
665            order_by,
666            frame,
667        },
668    }))
669}
670
671pub(crate) fn parse_aggregate_function<'a>(
672    parser: &mut Parser<'a, '_>,
673    t: Token<'a>,
674    span: Span,
675) -> Result<Expression<'a>, ParseError> {
676    parser.consume_token(Token::LParen)?;
677    let func = match &t {
678        Token::Ident(_, Keyword::COUNT) => Function::Count,
679        Token::Ident(_, Keyword::AVG) => Function::Avg,
680        Token::Ident(_, Keyword::SUM) => Function::Sum,
681        Token::Ident(_, Keyword::MIN) => Function::Min,
682        Token::Ident(_, Keyword::MAX) => Function::Max,
683        Token::Ident(_, Keyword::JSON_ARRAYAGG) => Function::JsonArrayAgg,
684        Token::Ident(_, Keyword::JSON_OBJECTAGG) => Function::JsonObjectAgg,
685        Token::Ident(_, Keyword::ARRAY_AGG) => Function::ArrayAgg,
686        Token::Ident(_, Keyword::BIT_AND) => Function::BitAnd,
687        Token::Ident(_, Keyword::BIT_OR) => Function::BitOr,
688        Token::Ident(_, Keyword::BIT_XOR) => Function::BitXor,
689        Token::Ident(_, Keyword::BOOL_AND) => Function::BoolAnd,
690        Token::Ident(_, Keyword::BOOL_OR) => Function::BoolOr,
691        Token::Ident(_, Keyword::CORR) => Function::Corr,
692        Token::Ident(_, Keyword::COVAR_POP) => Function::CovarPop,
693        Token::Ident(_, Keyword::COVAR_SAMP) => Function::CovarSamp,
694        Token::Ident(_, Keyword::CUME_DIST) => Function::CumeDist,
695        Token::Ident(_, Keyword::DENSE_RANK) => Function::DenseRank,
696        Token::Ident(_, Keyword::EVERY) => Function::BoolAnd,
697        Token::Ident(_, Keyword::JSON_AGG) => Function::JsonAgg,
698        Token::Ident(_, Keyword::JSONB_AGG) => Function::JsonbAgg,
699        Token::Ident(_, Keyword::JSONB_OBJECT_AGG) => Function::JsonbObjectAgg,
700        Token::Ident(_, Keyword::PERCENT_RANK) => Function::PercentRank,
701        Token::Ident(_, Keyword::PERCENTILE_CONT) => Function::PercentileCont,
702        Token::Ident(_, Keyword::PERCENTILE_DISC) => Function::PercentileDisc,
703        Token::Ident(_, Keyword::RANK) => Function::Rank,
704        Token::Ident(_, Keyword::REGR_AVGX) => Function::RegrAvgx,
705        Token::Ident(_, Keyword::REGR_AVGY) => Function::RegrAvgy,
706        Token::Ident(_, Keyword::REGR_COUNT) => Function::RegrCount,
707        Token::Ident(_, Keyword::REGR_INTERCEPT) => Function::RegrIntercept,
708        Token::Ident(_, Keyword::REGR_R2) => Function::RegrR2,
709        Token::Ident(_, Keyword::REGR_SLOPE) => Function::RegrSlope,
710        Token::Ident(_, Keyword::REGR_SXX) => Function::RegrSxx,
711        Token::Ident(_, Keyword::REGR_SXY) => Function::RegrSxy,
712        Token::Ident(_, Keyword::REGR_SYY) => Function::RegrSyy,
713        Token::Ident(_, Keyword::STD) => Function::Std,
714        Token::Ident(_, Keyword::STDDEV) => Function::Stddev,
715        Token::Ident(_, Keyword::STDDEV_POP) => Function::StddevPop,
716        Token::Ident(_, Keyword::STDDEV_SAMP) => Function::StddevSamp,
717        Token::Ident(_, Keyword::STRING_AGG) => Function::StringAgg,
718        Token::Ident(_, Keyword::VARIANCE) => Function::Variance,
719        Token::Ident(_, Keyword::VAR_POP) => Function::VarPop,
720        Token::Ident(_, Keyword::VAR_SAMP) => Function::VarSamp,
721        Token::Ident(_, Keyword::XMLAGG) => Function::Xmlagg,
722        Token::Ident(_, Keyword::MODE) => Function::Mode,
723        _ => {
724            parser.err("Unknown aggregate function", &span);
725            Function::Unknown
726        }
727    };
728
729    let distinct_span = parser.skip_keyword(Keyword::DISTINCT);
730    let mut args = Vec::new();
731    if !matches!(parser.token, Token::RParen) {
732        loop {
733            parser.recovered(
734                "')' or ','",
735                &|t| matches!(t, Token::RParen | Token::Comma),
736                |parser| {
737                    args.push(parse_expression_outer(parser)?);
738                    Ok(())
739                },
740            )?;
741            if parser.skip_token(Token::Comma).is_none() {
742                break;
743            }
744        }
745    }
746    parser.consume_token(Token::RParen)?;
747
748    let within_group = if let Some(within_span) = parser.skip_keyword(Keyword::WITHIN) {
749        let within_group_span = within_span.join_span(&parser.consume_keyword(Keyword::GROUP)?);
750        parser.consume_token(Token::LParen)?;
751        let order_span = parser.consume_keyword(Keyword::ORDER)?;
752        let order_by_span = order_span.join_span(&parser.consume_keyword(Keyword::BY)?);
753        let mut order = Vec::new();
754        loop {
755            let e = parse_expression_unreserved(parser, PRIORITY_MAX)?;
756            let f = match &parser.token {
757                Token::Ident(_, Keyword::ASC) => OrderFlag::Asc(parser.consume()),
758                Token::Ident(_, Keyword::DESC) => OrderFlag::Desc(parser.consume()),
759                _ => OrderFlag::None,
760            };
761            order.push((e, f));
762            if parser.skip_token(Token::Comma).is_none() {
763                break;
764            }
765        }
766        parser.consume_token(Token::RParen)?;
767        Some((within_group_span.join_span(&order_by_span), order))
768    } else {
769        None
770    };
771
772    let filter = if let Some(filter_span) = parser.skip_keyword(Keyword::FILTER) {
773        parser.postgres_only(&filter_span);
774        parser.consume_token(Token::LParen)?;
775        parser.consume_keyword(Keyword::WHERE)?;
776        let condition = parse_expression_unreserved(parser, PRIORITY_MAX)?;
777        parser.consume_token(Token::RParen)?;
778        Some((filter_span, condition))
779    } else {
780        None
781    };
782
783    let over = parse_over_clause(parser)?;
784
785    Ok(Expression::AggregateFunction(Box::new(
786        AggregateFunctionCallExpression {
787            function: func,
788            args,
789            function_span: span,
790            distinct_span,
791            within_group,
792            filter,
793            over,
794        },
795    )))
796}
797
798pub(crate) fn parse_function<'a>(
799    parser: &mut Parser<'a, '_>,
800    t: Token<'a>,
801    span: Span,
802) -> Result<Expression<'a>, ParseError> {
803    parser.consume_token(Token::LParen)?;
804
805    let func = match &t {
806        // https://mariadb.com/kb/en/string-functions/
807        Token::Ident(_, Keyword::ASCII) => Function::Ascii,
808        Token::Ident(_, Keyword::BIN) => Function::Bin,
809        Token::Ident(_, Keyword::BIT_LENGTH) => Function::BitLength,
810        Token::Ident(_, Keyword::CHAR_LENGTH) => Function::CharacterLength,
811        Token::Ident(_, Keyword::CHARACTER_LENGTH) => Function::CharacterLength,
812        Token::Ident(_, Keyword::CHR) => Function::Chr,
813        Token::Ident(_, Keyword::CONCAT) => Function::Concat,
814        Token::Ident(_, Keyword::CONCAT_WS) => Function::ConcatWs,
815        Token::Ident(_, Keyword::ELT) => Function::Elt,
816        Token::Ident(_, Keyword::EXPORT_SET) => Function::ExportSet,
817        Token::Ident(_, Keyword::EXTRACTVALUE) => Function::ExtractValue,
818        Token::Ident(_, Keyword::FIELD) => Function::Field,
819        Token::Ident(_, Keyword::FIND_IN_SET) => Function::FindInSet,
820        Token::Ident(_, Keyword::FORMAT) => Function::Format,
821        Token::Ident(_, Keyword::FROM_BASE64) => Function::FromBase64,
822        Token::Ident(_, Keyword::HEX) => Function::Hex,
823        Token::Ident(_, Keyword::INSERT) => Function::Insert,
824        Token::Ident(_, Keyword::INSTR) => Function::InStr,
825        Token::Ident(_, Keyword::LCASE) => Function::LCase,
826        Token::Ident(_, Keyword::LEFT) => Function::Left,
827        Token::Ident(_, Keyword::LENGTH) => Function::Length,
828        Token::Ident(_, Keyword::LENGTHB) => Function::LengthB,
829        Token::Ident(_, Keyword::LOAD_FILE) => Function::LoadFile,
830        Token::Ident(_, Keyword::LOCATE) => Function::Locate,
831        Token::Ident(_, Keyword::LOWER) => Function::Lower,
832        Token::Ident(_, Keyword::LPAD) => Function::LPad,
833        Token::Ident(_, Keyword::LTRIM) => Function::LTrim,
834        Token::Ident(_, Keyword::MAKE_SET) => Function::MakeSet,
835        Token::Ident(_, Keyword::MID) => Function::Mid,
836        Token::Ident(_, Keyword::NATURAL_SORT_KEY) => Function::NaturalSortkey,
837        Token::Ident(_, Keyword::OCTET_LENGTH) => Function::OctetLength,
838        Token::Ident(_, Keyword::ORD) => Function::Ord,
839        Token::Ident(_, Keyword::POSITION) => Function::Position,
840        Token::Ident(_, Keyword::QUOTE) => Function::Quote,
841        Token::Ident(_, Keyword::REPEAT) => Function::Repeat,
842        Token::Ident(_, Keyword::REPLACE) => Function::Replace,
843        Token::Ident(_, Keyword::REVERSE) => Function::Reverse,
844        Token::Ident(_, Keyword::RIGHT) => Function::Right,
845        Token::Ident(_, Keyword::RPAD) => Function::RPad,
846        Token::Ident(_, Keyword::RTRIM) => Function::RTrim,
847        Token::Ident(_, Keyword::SOUNDEX) => Function::SoundEx,
848        Token::Ident(_, Keyword::SLEEP) => Function::Sleep,
849        Token::Ident(_, Keyword::SPACE) => Function::Space,
850        Token::Ident(_, Keyword::STRCMP) => Function::StrCmp,
851        Token::Ident(_, Keyword::SUBSTR) => Function::SubStr,
852        Token::Ident(_, Keyword::SUBSTRING) => Function::SubStr,
853        Token::Ident(_, Keyword::SUBSTRING_INDEX) => Function::SubStringIndex,
854        Token::Ident(_, Keyword::TO_BASE64) => Function::ToBase64,
855        Token::Ident(_, Keyword::TO_CHAR) => Function::ToChar,
856        Token::Ident(_, Keyword::UCASE) => Function::UCase,
857        Token::Ident(_, Keyword::UNCOMPRESSED_LENGTH) => Function::UncompressedLength,
858        Token::Ident(_, Keyword::UNHEX) => Function::UnHex,
859        Token::Ident(_, Keyword::UPDATEXML) => Function::UpdateXml,
860        Token::Ident(_, Keyword::UPPER) => Function::Upper,
861        Token::Ident(_, Keyword::SFORMAT) => Function::SFormat,
862
863        // TODO uncat
864        Token::Ident(_, Keyword::EXISTS) => Function::Exists,
865        Token::Ident(_, Keyword::COUNT) => Function::Count,
866        Token::Ident(_, Keyword::AVG) => Function::Avg,
867        Token::Ident(_, Keyword::MIN) => Function::Min,
868        Token::Ident(_, Keyword::MAX) => Function::Max,
869        Token::Ident(_, Keyword::SUM) => Function::Sum,
870        Token::Ident(_, Keyword::VALUE) => Function::Value,
871        Token::Ident(_, Keyword::VALUES) => Function::Value,
872        Token::Ident(_, Keyword::LEAD) => Function::Lead,
873        Token::Ident(_, Keyword::LAG) => Function::Lag,
874        Token::Ident(_, Keyword::STARTS_WITH) => Function::StartsWith,
875
876        //https://mariadb.com/kb/en/control-flow-functions/
877        Token::Ident(_, Keyword::IFNULL) => Function::IfNull,
878        Token::Ident(_, Keyword::NULLIF) => Function::NullIf,
879        Token::Ident(_, Keyword::NVL) => Function::IfNull,
880        Token::Ident(_, Keyword::NVL2) => Function::NVL2,
881        Token::Ident(_, Keyword::IF) => Function::If,
882
883        //https://mariadb.com/kb/en/numeric-functions/
884        Token::Ident(_, Keyword::ABS) => Function::Abs,
885        Token::Ident(_, Keyword::ACOS) => Function::Acos,
886        Token::Ident(_, Keyword::ASIN) => Function::Asin,
887        Token::Ident(_, Keyword::ATAN) => Function::Atan,
888        Token::Ident(_, Keyword::ATAN2) => Function::Atan2,
889        Token::Ident(_, Keyword::CEIL | Keyword::CEILING) => Function::Ceil,
890        Token::Ident(_, Keyword::CONV) => Function::Conv,
891        Token::Ident(_, Keyword::COS) => Function::Cos,
892        Token::Ident(_, Keyword::COT) => Function::Cot,
893        Token::Ident(_, Keyword::CRC32) => Function::Crc32,
894        Token::Ident(_, Keyword::DEGREES) => Function::Degrees,
895        Token::Ident(_, Keyword::EXP) => Function::Exp,
896        Token::Ident(_, Keyword::FLOOR) => Function::Floor,
897        Token::Ident(_, Keyword::GREATEST) => Function::Greatest,
898        Token::Ident(_, Keyword::LN) => Function::Ln,
899        Token::Ident(_, Keyword::LOG) => Function::Log,
900        Token::Ident(_, Keyword::LOG10) => Function::Log10,
901        Token::Ident(_, Keyword::LOG2) => Function::Log2,
902        Token::Ident(_, Keyword::MOD) => Function::Mod,
903        Token::Ident(_, Keyword::OCT) => Function::Oct,
904        Token::Ident(_, Keyword::PI) => Function::Pi,
905        Token::Ident(_, Keyword::POW | Keyword::POWER) => Function::Pow,
906        Token::Ident(_, Keyword::RADIANS) => Function::Radians,
907        Token::Ident(_, Keyword::RAND) => Function::Rand,
908        Token::Ident(_, Keyword::ROUND) => Function::Round,
909        Token::Ident(_, Keyword::SIGN) => Function::Sign,
910        Token::Ident(_, Keyword::SIN) => Function::Sin,
911        Token::Ident(_, Keyword::SQRT) => Function::Sqrt,
912        Token::Ident(_, Keyword::TAN) => Function::Tan,
913        Token::Ident(_, Keyword::TRUNCATE) => Function::Truncate,
914        Token::Ident(_, Keyword::CRC32C) => Function::Crc32c,
915        Token::Ident(_, Keyword::LEAST) => Function::Least,
916
917        // https://mariadb.com/kb/en/date-time-functions/
918        Token::Ident(_, Keyword::ADDDATE) => Function::AddDate,
919        Token::Ident(_, Keyword::ADDTIME) => Function::AddTime,
920        Token::Ident(_, Keyword::CONVERT_TZ) => Function::ConvertTz,
921        Token::Ident(_, Keyword::CURDATE) => Function::CurDate,
922        Token::Ident(_, Keyword::CURRENT_DATE) => Function::CurDate,
923        Token::Ident(_, Keyword::CURRENT_TIME) => Function::CurTime,
924        Token::Ident(_, Keyword::CURTIME) => Function::CurTime,
925        Token::Ident(_, Keyword::DATE) => Function::Date,
926        Token::Ident(_, Keyword::HOUR) => Function::Hour,
927        Token::Ident(_, Keyword::DATEDIFF) => Function::DateDiff,
928        Token::Ident(_, Keyword::DATE_ADD) => Function::AddDate,
929        Token::Ident(_, Keyword::DATE_FORMAT) => Function::DateFormat,
930        Token::Ident(_, Keyword::DATE_SUB) => Function::DateSub,
931        Token::Ident(_, Keyword::DAY | Keyword::DAYOFMONTH) => Function::DayOfMonth,
932        Token::Ident(_, Keyword::DAYNAME) => Function::DayName,
933        Token::Ident(_, Keyword::DAYOFWEEK) => Function::DayOfWeek,
934        Token::Ident(_, Keyword::DAYOFYEAR) => Function::DayOfYear,
935        Token::Ident(_, Keyword::FROM_DAYS) => Function::FromDays,
936        Token::Ident(_, Keyword::CURRENT_TIMESTAMP) => Function::CurrentTimestamp,
937        Token::Ident(_, Keyword::LOCALTIME | Keyword::LOCALTIMESTAMP | Keyword::NOW) => {
938            Function::Now
939        }
940        Token::Ident(_, Keyword::MAKEDATE) => Function::MakeDate,
941        Token::Ident(_, Keyword::MAKETIME) => Function::MakeTime,
942        Token::Ident(_, Keyword::MICROSECOND) => Function::MicroSecond,
943        Token::Ident(_, Keyword::MINUTE) => Function::Minute,
944        Token::Ident(_, Keyword::MONTH) => Function::Month,
945        Token::Ident(_, Keyword::MONTHNAME) => Function::MonthName,
946        Token::Ident(_, Keyword::PERIOD_ADD) => Function::PeriodAdd,
947        Token::Ident(_, Keyword::PERIOD_DIFF) => Function::PeriodDiff,
948        Token::Ident(_, Keyword::QUARTER) => Function::Quarter,
949        Token::Ident(_, Keyword::SECOND) => Function::Second,
950        Token::Ident(_, Keyword::SEC_TO_TIME) => Function::SecToTime,
951        Token::Ident(_, Keyword::STR_TO_DATE) => Function::StrToDate,
952        Token::Ident(_, Keyword::SUBDATE) => Function::DateSub,
953        Token::Ident(_, Keyword::SUBTIME) => Function::SubTime,
954        Token::Ident(_, Keyword::TIME) => Function::Time,
955        Token::Ident(_, Keyword::LAST_DAY) => Function::LastDay,
956        Token::Ident(_, Keyword::TIMEDIFF) => Function::TimeDiff,
957        Token::Ident(_, Keyword::TIMESTAMP) => Function::Timestamp,
958        Token::Ident(_, Keyword::TIME_FORMAT) => Function::TimeFormat,
959        Token::Ident(_, Keyword::TIME_TO_SEC) => Function::TimeToSec,
960        Token::Ident(_, Keyword::TO_DAYS) => Function::ToDays,
961        Token::Ident(_, Keyword::TO_SECONDS) => Function::ToSeconds,
962        Token::Ident(_, Keyword::UNIX_TIMESTAMP) => Function::UnixTimestamp,
963        Token::Ident(_, Keyword::UTC_DATE) => Function::UtcDate,
964        Token::Ident(_, Keyword::UTC_TIME) => Function::UtcTime,
965        Token::Ident(_, Keyword::UTC_TIMESTAMP) => Function::UtcTimeStamp,
966        Token::Ident(_, Keyword::WEEK) => Function::Week,
967        Token::Ident(_, Keyword::WEEKDAY) => Function::Weekday,
968        Token::Ident(_, Keyword::WEEKOFYEAR) => Function::WeekOfYear,
969        Token::Ident(_, Keyword::ADD_MONTHS) => Function::AddMonths,
970        Token::Ident(_, Keyword::FROM_UNIXTIME) => Function::FromUnixTime,
971        Token::Ident(_, Keyword::YEAR) => Function::Year,
972        Token::Ident(_, Keyword::YEARWEEK) => Function::YearWeek,
973        Token::Ident(_, Keyword::SYSDATE) => Function::SysDate,
974
975        // https://mariadb.com/kb/en/json-functions/
976        Token::Ident(_, Keyword::JSON_ARRAY) => Function::JsonArray,
977        Token::Ident(_, Keyword::JSON_ARRAYAGG) => Function::JsonArrayAgg,
978        Token::Ident(_, Keyword::JSON_ARRAY_APPEND) => Function::JsonArrayAppend,
979        Token::Ident(_, Keyword::JSON_ARRAY_INSERT) => Function::JsonArrayInsert,
980        Token::Ident(_, Keyword::JSON_ARRAY_INTERSECT) => Function::JsonArrayIntersect,
981        Token::Ident(_, Keyword::JSON_COMPACT) => Function::JsonCompact,
982        Token::Ident(_, Keyword::JSON_CONTAINS) => Function::JsonContains,
983        Token::Ident(_, Keyword::JSON_CONTAINS_PATH) => Function::JsonContainsPath,
984        Token::Ident(_, Keyword::JSON_DEPTH) => Function::JsonDepth,
985        Token::Ident(_, Keyword::JSON_DETAILED) => Function::JsonDetailed,
986        Token::Ident(_, Keyword::JSON_EQUALS) => Function::JsonEquals,
987        Token::Ident(_, Keyword::JSON_EXISTS) => Function::JsonExists,
988        Token::Ident(_, Keyword::JSON_EXTRACT) => Function::JsonExtract,
989        Token::Ident(_, Keyword::JSON_INSERT) => Function::JsonInsert,
990        Token::Ident(_, Keyword::JSON_KEYS) => Function::JsonKeys,
991        Token::Ident(_, Keyword::JSON_LENGTH) => Function::JsonLength,
992        Token::Ident(_, Keyword::JSON_LOOSE) => Function::JsonLoose,
993        Token::Ident(_, Keyword::JSON_MERGE) => Function::JsonMerge,
994        Token::Ident(_, Keyword::JSON_MERGE_PATCH) => Function::JsonMergePath,
995        Token::Ident(_, Keyword::JSON_MERGE_PRESERVE) => Function::JsonMergePerserve,
996        Token::Ident(_, Keyword::JSON_NORMALIZE) => Function::JsonNormalize,
997        Token::Ident(_, Keyword::JSON_OBJECT) => Function::JsonObject,
998        Token::Ident(_, Keyword::JSON_OBJECT_FILTER_KEYS) => Function::JsonObjectFilterKeys,
999        Token::Ident(_, Keyword::JSON_OBJECT_TO_ARRAY) => Function::JsonObjectToArray,
1000        Token::Ident(_, Keyword::JSON_OBJECTAGG) => Function::JsonObjectAgg,
1001        Token::Ident(_, Keyword::JSON_OVERLAPS) => Function::JsonOverlaps,
1002        Token::Ident(_, Keyword::JSON_PRETTY) => Function::JsonPretty,
1003        Token::Ident(_, Keyword::JSON_QUERY) => Function::JsonQuery,
1004        Token::Ident(_, Keyword::JSON_QUOTE) => Function::JsonQuote,
1005        Token::Ident(_, Keyword::JSON_REMOVE) => Function::JsonRemove,
1006        Token::Ident(_, Keyword::JSON_REPLACE) => Function::JsonReplace,
1007        Token::Ident(_, Keyword::JSON_SCHEMA_VALID) => Function::JsonSchemaValid,
1008        Token::Ident(_, Keyword::JSON_SEARCH) => Function::JsonSearch,
1009        Token::Ident(_, Keyword::JSON_SET) => Function::JsonSet,
1010        Token::Ident(_, Keyword::JSON_TABLE) => Function::JsonTable,
1011        Token::Ident(_, Keyword::JSON_TYPE) => Function::JsonType,
1012        Token::Ident(_, Keyword::JSON_UNQUOTE) => Function::JsonUnquote,
1013        Token::Ident(_, Keyword::JSON_VALID) => Function::JsonValid,
1014        Token::Ident(_, Keyword::JSON_VALUE) => Function::JsonValue,
1015
1016        // Sqlite
1017        Token::Ident(_, Keyword::STRFTIME) => Function::Strftime,
1018        Token::Ident(_, Keyword::DATETIME) => Function::Datetime,
1019
1020        // MySQL 8.4 encryption / compression
1021        Token::Ident(_, Keyword::AES_DECRYPT) => Function::AesDecrypt,
1022        Token::Ident(_, Keyword::AES_ENCRYPT) => Function::AesEncrypt,
1023        Token::Ident(_, Keyword::COMPRESS) => Function::Compress,
1024        Token::Ident(_, Keyword::MD5) => Function::Md5,
1025        Token::Ident(_, Keyword::RANDOM_BYTES) => Function::RandomBytes,
1026        Token::Ident(_, Keyword::SHA) => Function::Sha,
1027        Token::Ident(_, Keyword::SHA1) => Function::Sha1,
1028        Token::Ident(_, Keyword::SHA2) => Function::Sha2,
1029        Token::Ident(_, Keyword::STATEMENT_DIGEST) => Function::StatementDigest,
1030        Token::Ident(_, Keyword::STATEMENT_DIGEST_TEXT) => Function::StatementDigestText,
1031        Token::Ident(_, Keyword::UNCOMPRESS) => Function::Uncompress,
1032        Token::Ident(_, Keyword::VALIDATE_PASSWORD_STRENGTH) => Function::ValidatePasswordStrength,
1033
1034        // MySQL 8.4 locking
1035        Token::Ident(_, Keyword::GET_LOCK) => Function::GetLock,
1036        Token::Ident(_, Keyword::IS_FREE_LOCK) => Function::IsFreeLock,
1037        Token::Ident(_, Keyword::IS_USED_LOCK) => Function::IsUsedLock,
1038        Token::Ident(_, Keyword::RELEASE_ALL_LOCKS) => Function::ReleaseAllLocks,
1039        Token::Ident(_, Keyword::RELEASE_LOCK) => Function::ReleaseLock,
1040
1041        // MySQL 8.4 information
1042        Token::Ident(_, Keyword::BENCHMARK) => Function::Benchmark,
1043        Token::Ident(_, Keyword::CHARSET) => Function::Charset,
1044        Token::Ident(_, Keyword::COERCIBILITY) => Function::Coercibility,
1045        Token::Ident(_, Keyword::COLLATION) => Function::Collation,
1046        Token::Ident(_, Keyword::CONNECTION_ID) => Function::ConnectionId,
1047        Token::Ident(_, Keyword::CURRENT_ROLE) => Function::CurrentRole,
1048        Token::Ident(_, Keyword::CURRENT_USER) => Function::CurrentUser,
1049        Token::Ident(_, Keyword::DATABASE) => Function::DatabaseFunc,
1050        Token::Ident(_, Keyword::FOUND_ROWS) => Function::FoundRows,
1051        Token::Ident(_, Keyword::ICU_VERSION) => Function::IcuVersion,
1052        Token::Ident(_, Keyword::LAST_INSERT_ID) => Function::LastInsertId,
1053        Token::Ident(_, Keyword::ROLES_GRAPHML) => Function::RolesGraphml,
1054        Token::Ident(_, Keyword::ROW_COUNT) => Function::RowCount,
1055        Token::Ident(_, Keyword::SCHEMA) => Function::SchemaFunc,
1056        Token::Ident(_, Keyword::SESSION_USER) => Function::SessionUserFunc,
1057        Token::Ident(_, Keyword::SYSTEM_USER) => Function::SystemUser,
1058        Token::Ident(_, Keyword::USER) => Function::UserFunc,
1059        Token::Ident(_, Keyword::VERSION) => Function::Version,
1060
1061        // MySQL 8.4 regexp
1062        Token::Ident(_, Keyword::REGEXP_INSTR) => Function::RegexpInstr,
1063        Token::Ident(_, Keyword::REGEXP_LIKE) => Function::RegexpLike,
1064        Token::Ident(_, Keyword::REGEXP_REPLACE) => Function::RegexpReplace,
1065        Token::Ident(_, Keyword::REGEXP_SUBSTR) => Function::RegexpSubstr,
1066        Token::Ident(_, Keyword::WEIGHT_STRING) => Function::WeightString,
1067
1068        // MySQL 8.4 datetime
1069        Token::Ident(_, Keyword::GET_FORMAT) => Function::GetFormat,
1070
1071        // MySQL 8.4 window / analytics
1072        Token::Ident(_, Keyword::FIRST_VALUE) => Function::FirstValue,
1073        Token::Ident(_, Keyword::LAST_VALUE) => Function::LastValue,
1074        Token::Ident(_, Keyword::NTH_VALUE) => Function::NthValue,
1075        Token::Ident(_, Keyword::NTILE) => Function::Ntile,
1076        Token::Ident(_, Keyword::ROW_NUMBER) => Function::RowNumber,
1077
1078        // MySQL 8.4 performance schema
1079        Token::Ident(_, Keyword::FORMAT_BYTES) => Function::FormatBytes,
1080        Token::Ident(_, Keyword::FORMAT_PICO_TIME) => Function::FormatPicoTime,
1081        Token::Ident(_, Keyword::PS_CURRENT_THREAD_ID) => Function::PsCurrentThreadId,
1082        Token::Ident(_, Keyword::PS_THREAD_ID) => Function::PsThreadId,
1083
1084        // MySQL 8.4 miscellaneous
1085        Token::Ident(_, Keyword::ANY_VALUE) => Function::AnyValue,
1086        Token::Ident(_, Keyword::BIN_TO_UUID) => Function::BinToUuid,
1087        Token::Ident(_, Keyword::BIT_COUNT) => Function::BitCount,
1088        Token::Ident(_, Keyword::GROUPING) => Function::Grouping,
1089        Token::Ident(_, Keyword::INET6_ATON) => Function::Inet6Aton,
1090        Token::Ident(_, Keyword::INET6_NTOA) => Function::Inet6Ntoa,
1091        Token::Ident(_, Keyword::INET_ATON) => Function::InetAton,
1092        Token::Ident(_, Keyword::INET_NTOA) => Function::InetNtoa,
1093        Token::Ident(_, Keyword::IS_IPV4) => Function::IsIPv4,
1094        Token::Ident(_, Keyword::IS_IPV4_COMPAT) => Function::IsIPv4Compat,
1095        Token::Ident(_, Keyword::IS_IPV4_MAPPED) => Function::IsIPv4Mapped,
1096        Token::Ident(_, Keyword::IS_IPV6) => Function::IsIPv6,
1097        Token::Ident(_, Keyword::IS_UUID) => Function::IsUuid,
1098        Token::Ident(_, Keyword::NAME_CONST) => Function::NameConst,
1099        Token::Ident(_, Keyword::UUID) => Function::Uuid,
1100        Token::Ident(_, Keyword::UUID_SHORT) => Function::UuidShort,
1101        Token::Ident(_, Keyword::UUID_TO_BIN) => Function::UuidToBin,
1102
1103        Token::Ident(v, k) if !k.restricted(parser.reserved()) => {
1104            Function::Other(alloc::vec![Identifier {
1105                value: v,
1106                span: span.clone()
1107            }])
1108        }
1109        _ => {
1110            parser.err("Unknown function", &span);
1111            Function::Unknown
1112        }
1113    };
1114
1115    let mut args = Vec::new();
1116    if !matches!(parser.token, Token::RParen) {
1117        loop {
1118            parser.recovered(
1119                "')' or ','",
1120                &|t| matches!(t, Token::RParen | Token::Comma),
1121                |parser| {
1122                    args.push(parse_expression_outer(parser)?);
1123                    Ok(())
1124                },
1125            )?;
1126            if parser.skip_token(Token::Comma).is_none() {
1127                break;
1128            }
1129        }
1130    }
1131    parser.consume_token(Token::RParen)?;
1132
1133    if let Some(over) = parse_over_clause(parser)? {
1134        Ok(Expression::WindowFunction(Box::new(
1135            WindowFunctionCallExpression {
1136                function: func,
1137                args,
1138                function_span: span,
1139                over,
1140            },
1141        )))
1142    } else {
1143        Ok(Expression::Function(Box::new(FunctionCallExpression {
1144            function: func,
1145            args,
1146            function_span: span,
1147        })))
1148    }
1149}
1150
1151/// Parse the argument list and optional OVER clause for a schema-qualified function call.
1152/// The caller has already resolved `func = Function::Other(qualified_parts)` and
1153/// computed `function_span` covering the full qualified name.
1154pub(crate) fn parse_char_function<'a>(
1155    parser: &mut Parser<'a, '_>,
1156    char_span: Span,
1157) -> Result<Expression<'a>, ParseError> {
1158    parser.consume_token(Token::LParen)?;
1159    let mut args = Vec::new();
1160    if !matches!(parser.token, Token::RParen) {
1161        loop {
1162            parser.recovered(
1163                "')' or ','",
1164                &|t| {
1165                    matches!(
1166                        t,
1167                        Token::RParen | Token::Comma | Token::Ident(_, Keyword::USING)
1168                    )
1169                },
1170                |parser| {
1171                    args.push(parse_expression_outer(parser)?);
1172                    Ok(())
1173                },
1174            )?;
1175            if parser.skip_token(Token::Comma).is_none() {
1176                break;
1177            }
1178        }
1179    }
1180    // Optional USING charset_name
1181    let using_charset = if let Some(using_span) = parser.skip_keyword(Keyword::USING) {
1182        let charset = parser.consume_plain_identifier_unreserved()?;
1183        Some((using_span, charset))
1184    } else {
1185        None
1186    };
1187    parser.consume_token(Token::RParen)?;
1188    Ok(Expression::Char(Box::new(CharFunctionExpression {
1189        char_span,
1190        args,
1191        using_charset,
1192    })))
1193}
1194
1195pub(crate) fn parse_function_call<'a>(
1196    parser: &mut Parser<'a, '_>,
1197    func: Function<'a>,
1198    function_span: Span,
1199) -> Result<Expression<'a>, ParseError> {
1200    parser.consume_token(Token::LParen)?;
1201    let mut args = Vec::new();
1202    if !matches!(parser.token, Token::RParen) {
1203        loop {
1204            parser.recovered(
1205                "')' or ','",
1206                &|t| matches!(t, Token::RParen | Token::Comma),
1207                |parser| {
1208                    args.push(parse_expression_outer(parser)?);
1209                    Ok(())
1210                },
1211            )?;
1212            if parser.skip_token(Token::Comma).is_none() {
1213                break;
1214            }
1215        }
1216    }
1217    parser.consume_token(Token::RParen)?;
1218    if let Some(over) = parse_over_clause(parser)? {
1219        Ok(Expression::WindowFunction(Box::new(
1220            WindowFunctionCallExpression {
1221                function: func,
1222                args,
1223                function_span,
1224                over,
1225            },
1226        )))
1227    } else {
1228        Ok(Expression::Function(Box::new(FunctionCallExpression {
1229            function: func,
1230            args,
1231            function_span,
1232        })))
1233    }
1234}
1235
1236#[cfg(test)]
1237mod tests {
1238    use core::ops::Deref;
1239
1240    use alloc::string::{String, ToString};
1241
1242    use crate::{
1243        Function, FunctionCallExpression, ParseOptions, SQLDialect,
1244        expression::{Expression, PRIORITY_MAX},
1245        issue::Issues,
1246        parser::Parser,
1247    };
1248
1249    use super::parse_expression_unreserved;
1250
1251    fn test_expr(src: &'static str, f: impl FnOnce(&Expression<'_>) -> Result<(), String>) {
1252        let mut issues = Issues::new(src);
1253        let options = ParseOptions::new().dialect(SQLDialect::MariaDB);
1254        let mut parser = Parser::new(src, &mut issues, &options);
1255        let res = parse_expression_unreserved(&mut parser, PRIORITY_MAX)
1256            .expect("Expression in test expr");
1257        if let Err(e) = f(&res) {
1258            panic!("Error parsing {}: {}\nGot {:#?}", src, e, res);
1259        }
1260    }
1261
1262    #[test]
1263    fn mariadb_datetime_functions() {
1264        fn test_func(src: &'static str, f: Function, cnt: usize) {
1265            let mut issues = Issues::new(src);
1266            let options = ParseOptions::new().dialect(SQLDialect::MariaDB);
1267            let mut parser = Parser::new(src, &mut issues, &options);
1268            let res = match parse_expression_unreserved(&mut parser, PRIORITY_MAX) {
1269                Ok(res) => res,
1270                Err(e) => panic!("Unable to parse {}: {:?}", src, e),
1271            };
1272            let Expression::Function(r) = res else {
1273                panic!("Should be parsed as function {}", src);
1274            };
1275            let FunctionCallExpression {
1276                function: pf, args, ..
1277            } = r.deref();
1278            assert_eq!(pf, &f, "Failure en expr {}", src);
1279            assert_eq!(args.len(), cnt, "Failure en expr {}", src);
1280        }
1281        test_func("ADD_MONTHS('2012-01-31', 2)", Function::AddMonths, 2);
1282        test_func(
1283            "ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002')",
1284            Function::AddTime,
1285            2,
1286        );
1287        test_func(
1288            "DATE_ADD('2008-01-02', INTERVAL 31 DAY)",
1289            Function::AddDate,
1290            2,
1291        );
1292        test_func(
1293            "ADDDATE('2008-01-02', INTERVAL 31 DAY)",
1294            Function::AddDate,
1295            2,
1296        );
1297        test_func("ADDDATE('2008-01-02', 31)", Function::AddDate, 2);
1298        test_func(
1299            "CONVERT_TZ('2016-01-01 12:00:00','+00:00','+10:00')",
1300            Function::ConvertTz,
1301            3,
1302        );
1303        test_func("CURDATE()", Function::CurDate, 0);
1304        test_func("CURRENT_DATE", Function::CurDate, 0);
1305        test_func("CURRENT_DATE()", Function::CurDate, 0);
1306        test_func("CURRENT_TIME", Function::CurTime, 0);
1307        test_func("CURRENT_TIME()", Function::CurTime, 0);
1308        test_func("CURTIME()", Function::CurTime, 0);
1309        test_func("CURTIME(2)", Function::CurTime, 1);
1310        test_func("CURRENT_DATE", Function::CurDate, 0);
1311        test_func("CURRENT_DATE()", Function::CurDate, 0);
1312        test_func("CURDATE()", Function::CurDate, 0);
1313        test_func("CURRENT_TIMESTAMP", Function::CurrentTimestamp, 0);
1314        test_func("CURRENT_TIMESTAMP()", Function::CurrentTimestamp, 0);
1315        test_func("CURRENT_TIMESTAMP(10)", Function::CurrentTimestamp, 1);
1316        test_func("LOCALTIME", Function::Now, 0);
1317        test_func("LOCALTIME()", Function::Now, 0);
1318        test_func("LOCALTIME(10)", Function::Now, 1);
1319        test_func("LOCALTIMESTAMP", Function::Now, 0);
1320        test_func("LOCALTIMESTAMP()", Function::Now, 0);
1321        test_func("LOCALTIMESTAMP(10)", Function::Now, 1);
1322        test_func("DATE('2013-07-18 12:21:32')", Function::Date, 1);
1323        test_func(
1324            "DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y')",
1325            Function::DateFormat,
1326            2,
1327        );
1328        test_func(
1329            "DATE_SUB('1998-01-02', INTERVAL 31 DAY)",
1330            Function::DateSub,
1331            2,
1332        );
1333        test_func("DAY('2007-02-03')", Function::DayOfMonth, 1);
1334        test_func("DAYOFMONTH('2007-02-03')", Function::DayOfMonth, 1);
1335        test_func(
1336            "DATEDIFF('2007-12-31 23:59:59','2007-12-30')",
1337            Function::DateDiff,
1338            2,
1339        );
1340        test_func("DAYNAME('2007-02-03')", Function::DayName, 1);
1341        test_func("DAYOFYEAR('2018-02-16')", Function::DayOfYear, 1);
1342        test_func("DAYOFWEEK('2007-02-03')", Function::DayOfWeek, 1);
1343        test_expr("EXTRACT(YEAR_MONTH FROM '2009-07-02 01:02:03')", |e| {
1344            let Expression::Extract { .. } = e else {
1345                return Err("Wrong type".to_string());
1346            };
1347            Ok(())
1348        });
1349        //test_func("FORMAT_PICO_TIME(4321123443212345) AS h", Function::DayOfWeek, 1);
1350        test_func("FROM_DAYS(730669)", Function::FromDays, 1);
1351        test_func("FROM_UNIXTIME(1196440219)", Function::FromUnixTime, 1);
1352        test_func(
1353            "FROM_UNIXTIME(UNIX_TIMESTAMP(), '%Y %D %M %h:%i:%s %x')",
1354            Function::FromUnixTime,
1355            2,
1356        );
1357        //test_func("GET_FORMAT(DATE, 'EUR')", Function::GetFormat, 2);
1358        test_func("HOUR('10:05:03')", Function::Hour, 1);
1359        test_func("LAST_DAY('2004-01-01 01:01:01')", Function::LastDay, 1);
1360        test_func("MAKEDATE(2011,31)", Function::MakeDate, 2);
1361        test_func("MAKETIME(-13,57,33)", Function::MakeTime, 3);
1362        test_func("MICROSECOND('12:00:00.123456')", Function::MicroSecond, 1);
1363        test_func("MINUTE('2013-08-03 11:04:03')", Function::Minute, 1);
1364        test_func("MONTH('2019-01-03')", Function::Month, 1);
1365        test_func("MONTHNAME('2019-02-03')", Function::MonthName, 1);
1366        test_func("PERIOD_ADD(200801,2)", Function::PeriodAdd, 2);
1367        test_func("PERIOD_DIFF(200802,200703)", Function::PeriodDiff, 2);
1368        test_func("QUARTER('2008-04-01')", Function::Quarter, 1);
1369        test_func("SEC_TO_TIME(12414)", Function::SecToTime, 1);
1370        test_func("SECOND('10:05:03')", Function::Second, 1);
1371        test_func(
1372            "STR_TO_DATE('Wednesday, June 2, 2014', '%W, %M %e, %Y')",
1373            Function::StrToDate,
1374            2,
1375        );
1376        test_func(
1377            "DATE_SUB('2008-01-02', INTERVAL 31 DAY)",
1378            Function::DateSub,
1379            2,
1380        );
1381        test_func("SUBDATE('2008-01-02 12:00:00', 31)", Function::DateSub, 2);
1382        test_func(
1383            "SUBDATE('2008-01-02', INTERVAL 31 DAY)",
1384            Function::DateSub,
1385            2,
1386        );
1387        test_func(
1388            "SUBTIME('2007-12-31 23:59:59.999999','1 1:1:1.000002')",
1389            Function::SubTime,
1390            2,
1391        );
1392        test_func("SYSDATE()", Function::SysDate, 0);
1393        test_func("SYSDATE(4)", Function::SysDate, 1);
1394        test_func("TIME('2003-12-31 01:02:03')", Function::Time, 1);
1395        test_func(
1396            "TIME_FORMAT('100:00:00', '%H %k %h %I %l')",
1397            Function::TimeFormat,
1398            2,
1399        );
1400        test_func("TIME_TO_SEC('22:23:00')", Function::TimeToSec, 1);
1401        test_func(
1402            "TIMEDIFF('2008-12-31 23:59:59.000001', '2008-12-30 01:01:01.000002')",
1403            Function::TimeDiff,
1404            2,
1405        );
1406        test_func("TIMESTAMP('2003-12-31')", Function::Timestamp, 1);
1407        test_func(
1408            "TIMESTAMP('2003-12-31 12:00:00','6:30:00')",
1409            Function::Timestamp,
1410            2,
1411        );
1412        test_expr("TIMESTAMPADD(MINUTE,1,'2003-01-02')", |e| {
1413            let Expression::TimestampAdd { .. } = e else {
1414                return Err("Wrong type".to_string());
1415            };
1416            Ok(())
1417        });
1418        test_expr("TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');", |e| {
1419            let Expression::TimestampDiff { .. } = e else {
1420                return Err("Wrong type".to_string());
1421            };
1422            Ok(())
1423        });
1424        test_func("TO_DAYS('2007-10-07')", Function::ToDays, 1);
1425        test_func("UNIX_TIMESTAMP()", Function::UnixTimestamp, 0);
1426        test_func(
1427            "UNIX_TIMESTAMP('2007-11-30 10:30:19')",
1428            Function::UnixTimestamp,
1429            1,
1430        );
1431        test_func("UTC_DATE", Function::UtcDate, 0);
1432        test_func("UTC_DATE()", Function::UtcDate, 0);
1433        test_func("UTC_TIME", Function::UtcTime, 0);
1434        test_func("UTC_TIME()", Function::UtcTime, 0);
1435        test_func("UTC_TIME(5)", Function::UtcTime, 1);
1436        test_func("UTC_TIMESTAMP", Function::UtcTimeStamp, 0);
1437        test_func("UTC_TIMESTAMP()", Function::UtcTimeStamp, 0);
1438        test_func("UTC_TIMESTAMP(4)", Function::UtcTimeStamp, 1);
1439        test_func("WEEK('2008-02-20')", Function::Week, 1);
1440        test_func("WEEK('2008-02-20',0)", Function::Week, 2);
1441        test_func("WEEKDAY('2008-02-03 22:23:00')", Function::Weekday, 1);
1442        test_func("WEEKOFYEAR('2008-02-20')", Function::WeekOfYear, 1);
1443        test_func("YEAR('1987-01-01')", Function::Year, 1);
1444        test_func("YEARWEEK('1987-01-01')", Function::YearWeek, 1);
1445        test_func("YEARWEEK('1987-01-01',0)", Function::YearWeek, 2);
1446    }
1447}