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, 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    Acosd,
29    Acosh,
30    AddDate,
31    AddMonths,
32    AddTime,
33    Area,
34    Abbrev,
35    Ascii,
36    Btrim,
37    Asin,
38    Asind,
39    Asinh,
40    Atan,
41    Atan2,
42    Atan2d,
43    Atand,
44    Atanh,
45    Bin,
46    BitLength,
47    Broadcast,
48    Casefold,
49    Cbrt,
50    Ceil,
51    Center,
52    Char,
53    CharacterLength,
54    Chr,
55    Concat,
56    ConcatWs,
57    Conv,
58    ConvertTz,
59    Cos,
60    Cosd,
61    Cosh,
62    Cot,
63    Cotd,
64    Crc32,
65    Crc32c,
66    CurrentCatalog,
67    CurrentRole,
68    CurrentUser,
69    CurDate,
70    CurrentTimestamp,
71    CurTime,
72    SessionUser,
73    Date,
74    DateDiff,
75    DateFormat,
76    DateSub,
77    Datetime,
78    DayName,
79    DayOfMonth,
80    DayOfWeek,
81    DayOfYear,
82    Degrees,
83    Diagonal,
84    Diameter,
85    Elt,
86    Exists,
87    Erf,
88    Erfc,
89    Exp,
90    EnumFirst,
91    EnumLast,
92    EnumRange,
93    ExportSet,
94    ExtractValue,
95    Family,
96    Field,
97    Factorial,
98    FindInSet,
99    Floor,
100    Format,
101    FromBase64,
102    FromDays,
103    FromUnixTime,
104    Gamma,
105    Gcd,
106    Greatest,
107    Hex,
108    Height,
109    Host,
110    Hour,
111    If,
112    IfNull,
113    Initcap,
114    Insert,
115    InStr,
116    JsonArray,
117    JsonArrayAgg,
118    JsonArrayAppend,
119    JsonArrayInsert,
120    JsonArrayIntersect,
121    JsonCompact,
122    JsonContains,
123    JsonContainsPath,
124    JsonDepth,
125    JsonDetailed,
126    JsonEquals,
127    JsonExists,
128    JsonExtract,
129    JsonInsert,
130    JsonKeys,
131    JsonLength,
132    JsonLoose,
133    JsonMerge,
134    JsonMergePath,
135    JsonMergePerserve,
136    JsonNormalize,
137    JsonObject,
138    JsonObjectAgg,
139    JsonObjectFilterKeys,
140    JsonObjectToArray,
141    JsonOverlaps,
142    JsonPretty,
143    JsonQuery,
144    JsonQuote,
145    JsonRemove,
146    JsonReplace,
147    JsonSchemaValid,
148    JsonSearch,
149    JsonSet,
150    JsonTable,
151    JsonType,
152    JsonUnquote,
153    JsonValid,
154    JsonValue,
155    Lag,
156    LastDay,
157    Avg,
158    Count,
159    LCase,
160    Lead,
161    Lcm,
162    Least,
163    Left,
164    Length,
165    LengthB,
166    Lgamma,
167    Ln,
168    LoadFile,
169    Locate,
170    Log,
171    Log10,
172    Log2,
173    Lower,
174    LPad,
175    LTrim,
176    MakeDate,
177    MakeSet,
178    MakeTime,
179    Max,
180    MicroSecond,
181    Mid,
182    Min,
183    Minute,
184    MinScale,
185    Mod,
186    Month,
187    MonthName,
188    Normalize,
189    NaturalSortkey,
190    Now,
191    NullIf,
192    NVL2,
193    Npoints,
194    Oct,
195    OctetLength,
196    Ord,
197    ParseIdent,
198    Pclose,
199    PeriodAdd,
200    PeriodDiff,
201    PgClientEncoding,
202    Pi,
203    Popen,
204    Position,
205    Pow,
206    Quarter,
207    Quote,
208    QuoteIdent,
209    QuoteLiteral,
210    QuoteNullable,
211    Radians,
212    Radius,
213    Rand,
214    RandomNormal,
215    Repeat,
216    Replace,
217    Reverse,
218    Right,
219    Round,
220    RPad,
221    RTrim,
222    Scale,
223    Second,
224    SecToTime,
225    SFormat,
226    SetBit,
227    SetSeed,
228    Sign,
229    Sin,
230    Sind,
231    Sinh,
232    Sleep,
233    Slope,
234    SoundEx,
235    Space,
236    SplitPart,
237    Sqrt,
238    StartsWith,
239    StrCmp,
240    Strpos,
241    Strftime,
242    StrToDate,
243    SubStr,
244    SubStringIndex,
245    SubTime,
246    Sum,
247    SysDate,
248    Tan,
249    Tand,
250    Tanh,
251    Time,
252    TimeDiff,
253    TimeFormat,
254    Timestamp,
255    TimeToSec,
256    ToAscii,
257    ToBase64,
258    ToBin,
259    ToChar,
260    ToDate,
261    ToDays,
262    ToHex,
263    ToNumber,
264    ToOct,
265    ToSeconds,
266    ToTimestamp,
267    Translate,
268    TrimScale,
269    Truncate,
270    UCase,
271    UncompressedLength,
272    UnHex,
273    UnixTimestamp,
274    Unknown,
275    UpdateXml,
276    Upper,
277    UnicodeAssigned,
278    Unistr,
279    UtcDate,
280    UtcTime,
281    UtcTimeStamp,
282    Value,
283    Week,
284    Weekday,
285    WeekOfYear,
286    Width,
287    WidthBucket,
288    Year,
289    YearWeek,
290    // MySQL 8.4 explicit functions
291    AesDecrypt,
292    AesEncrypt,
293    AnyValue,
294    Benchmark,
295    BinToUuid,
296    BitCount,
297    Charset,
298    Coercibility,
299    Collation,
300    Compress,
301    ConnectionId,
302    DatabaseFunc,
303    FirstValue,
304    FormatBytes,
305    FormatPicoTime,
306    FoundRows,
307    GetBit,
308    GetFormat,
309    GetLock,
310    Grouping,
311    IcuVersion,
312    Inet6Aton,
313    Inet6Ntoa,
314    InetAton,
315    InetNtoa,
316    IsFreeLock,
317    IsIPv4,
318    IsIPv4Compat,
319    IsIPv4Mapped,
320    IsIPv6,
321    InetMerge,
322    InetSameFamily,
323    Macaddr8Set7bit,
324    MaskLen,
325    NetMask,
326    Network,
327    SetMaskLen,
328    IsUsedLock,
329    IsUuid,
330    LastInsertId,
331    LastValue,
332    Md5,
333    NameConst,
334    NthValue,
335    Ntile,
336    PsCurrentThreadId,
337    PsThreadId,
338    RandomBytes,
339    RegexpCount,
340    RegexpInstr,
341    RegexpLike,
342    RegexpMatch,
343    RegexpMatches,
344    RegexpReplace,
345    RegexpSplitToArray,
346    RegexpSplitToTable,
347    RegexpSubstr,
348    ReleaseAllLocks,
349    ReleaseLock,
350    RolesGraphml,
351    RowCount,
352    RowNumber,
353    SchemaFunc,
354    SessionUserFunc,
355    Sha,
356    Sha1,
357    Sha2,
358    StatementDigest,
359    StatementDigestText,
360    SystemUser,
361    Uncompress,
362    UserFunc,
363    Uuid,
364    UuidShort,
365    UuidToBin,
366    ValidatePasswordStrength,
367    Version,
368    WeightString,
369    // PostgreSQL system functions
370    InetServerAddr,
371    InetServerPort,
372    HostMask,
373    PgPostmasterStartTime,
374    PostgisFullVersion,
375    // PostgreSQL system information functions (9.27)
376    ColDescription,
377    CurrentDatabase,
378    CurrentQuery,
379    CurrentSchemas,
380    FormatType,
381    HasAnyColumnPrivilege,
382    HasColumnPrivilege,
383    HasDatabasePrivilege,
384    HasForeignDataWrapperPrivilege,
385    HasFunctionPrivilege,
386    HasLanguagePrivilege,
387    HasLargeobjectPrivilege,
388    HasParameterPrivilege,
389    HasSchemaPrivilege,
390    HasSequencePrivilege,
391    HasServerPrivilege,
392    HasTablePrivilege,
393    HasTablespacePrivilege,
394    HasTypePrivilege,
395    IcuUnicodeVersion,
396    InetClientAddr,
397    InetClientPort,
398    Makeaclitem,
399    MxidAge,
400    ObjDescription,
401    PgAvailableWalSummaries,
402    PgBackendPid,
403    PgBlockingPids,
404    PgCharToEncoding,
405    PgCollationIsVisible,
406    PgConfLoadTime,
407    PgControlCheckpoint,
408    PgControlInit,
409    PgControlRecovery,
410    PgControlSystem,
411    PgConversionIsVisible,
412    PgCurrentLogfile,
413    PgCurrentSnapshot,
414    PgCurrentXactId,
415    PgCurrentXactIdIfAssigned,
416    PgDescribeObject,
417    PgEncodingToChar,
418    PgFunctionIsVisible,
419    PgGetAcl,
420    PgGetConstraintdef,
421    PgGetExpr,
422    PgGetFunctiondef,
423    PgGetFunctionArguments,
424    PgGetFunctionIdentityArguments,
425    PgGetFunctionResult,
426    PgGetIndexdef,
427    PgGetObjectAddress,
428    PgGetPartitionConstraintdef,
429    PgGetPartkeydef,
430    PgGetRuledef,
431    PgGetSerialSequence,
432    PgGetStatisticsobjdef,
433    PgGetTriggerdef,
434    PgGetUserbyid,
435    PgGetViewdef,
436    PgGetWalSummarizerState,
437    PgHasRole,
438    PgIndexColumnHasProperty,
439    PgIndexHasProperty,
440    PgIndexamHasProperty,
441    PgInputErrorInfo,
442    PgInputIsValid,
443    PgIsOtherTempSchema,
444    PgJitAvailable,
445    PgLastCommittedXact,
446    PgListeningChannels,
447    PgMyTempSchema,
448    PgNotificationQueueUsage,
449    PgOpclassIsVisible,
450    PgOperatorIsVisible,
451    PgOpfamilyIsVisible,
452    PgSafeSnapshotBlockingPids,
453    PgSettingsGetFlags,
454    PgSnapshotXip,
455    PgSnapshotXmax,
456    PgSnapshotXmin,
457    PgStatisticsObjIsVisible,
458    PgTableIsVisible,
459    PgTablespaceLocation,
460    PgTriggerDepth,
461    PgTsConfigIsVisible,
462    PgTsDictIsVisible,
463    PgTsParserIsVisible,
464    PgTsTemplateIsVisible,
465    PgTypeIsVisible,
466    PgTypeof,
467    PgVisibleInSnapshot,
468    PgXactCommitTimestamp,
469    PgXactStatus,
470    RowSecurityActive,
471    ShobjDescription,
472    ToRegclass,
473    ToRegcollation,
474    ToRegnamespace,
475    ToRegoper,
476    ToRegoperator,
477    ToRegproc,
478    ToRegprocedure,
479    ToRegrole,
480    ToRegtype,
481    ToRegtypemod,
482    UnicodeVersion,
483    ArrayAgg,
484    BitAnd,
485    BitOr,
486    BitXor,
487    BoolAnd,
488    BoolOr,
489    Corr,
490    CovarPop,
491    CovarSamp,
492    CumeDist,
493    DenseRank,
494    JsonAgg,
495    JsonbAgg,
496    JsonbObjectAgg,
497    JsonbSet,
498    JsonBuildObject,
499    PercentRank,
500    PercentileCont,
501    PercentileDisc,
502    Rank,
503    RegrAvgx,
504    RegrAvgy,
505    RegrCount,
506    RegrIntercept,
507    RegrR2,
508    RegrSlope,
509    RegrSxx,
510    RegrSxy,
511    RegrSyy,
512    Mode,
513    Std,
514    Stddev,
515    StddevPop,
516    StddevSamp,
517    StringAgg,
518    StringToArray,
519    StringToTable,
520    Variance,
521    VarPop,
522    VarSamp,
523    Xmlagg,
524    Coalesce,
525    // PostgreSQL geometric functions (non-PostGIS)
526    BoundBox,
527    Isclosed,
528    IsOpen,
529    // PostGIS / geometry functions
530    Box2D,
531    Box3D,
532    GeometryType,
533    StAddMeasure,
534    StAddPoint,
535    StAffine,
536    StArea,
537    StAsBinary,
538    StAsEwkb,
539    StAsEwkt,
540    StAsGeoJson,
541    StAsGml,
542    StAsHexEwkb,
543    StAsKml,
544    StAsSvg,
545    StAsText,
546    StAzimuth,
547    StBoundary,
548    StBuffer,
549    StBuildArea,
550    StCentroid,
551    StClosestPoint,
552    StCollect,
553    StCollectionExtract,
554    StContains,
555    StContainsProperly,
556    StConvexHull,
557    StCoordDim,
558    StCoveredBy,
559    StCovers,
560    StCrosses,
561    StCurveToLine,
562    StDFullyWithin,
563    StDifference,
564    StDimension,
565    StDisjoint,
566    StDistance,
567    StDistanceSphere,
568    StDistanceSpheroidal,
569    StDWithin,
570    StEndPoint,
571    StEnvelope,
572    StEquals,
573    StExteriorRing,
574    StForce2D,
575    StForce3D,
576    StForce3DM,
577    StForce3DZ,
578    StForce4D,
579    StForceCollection,
580    StForceRHR,
581    StGeoHash,
582    StGeomCollFromText,
583    StGeomFromEwkb,
584    StGeomFromEwkt,
585    StGeomFromGeoJson,
586    StGeomFromGml,
587    StGeomFromKml,
588    StGeomFromText,
589    StGeomFromWkb,
590    StGeometryFromText,
591    StGeometryN,
592    StGeometryType,
593    StGmlToSQL,
594    StHasArc,
595    StHausdorffDistance,
596    StInteriorRingN,
597    StIntersection,
598    StIntersects,
599    StIsClosed,
600    StIsEmpty,
601    StIsRing,
602    StIsSimple,
603    StIsValid,
604    StIsValidReason,
605    StLength,
606    StLength2D,
607    StLength3D,
608    StLineCrossingDirection,
609    StLineFromMultiPoint,
610    StLineFromText,
611    StLineFromWkb,
612    StLineMerge,
613    StLinestringFromWkb,
614    StLineToCurve,
615    StLineInterpolatePoint,
616    StLineLocatePoint,
617    StLineSubstring,
618    StLongestLine,
619    StM,
620    StMakeEnvelope,
621    StMakeLine,
622    StMakePoint,
623    StMakePointM,
624    StMakePolygon,
625    StMaxDistance,
626    StMemSize,
627    StMinimumBoundingCircle,
628    StMulti,
629    StNDims,
630    StNPoints,
631    StNRings,
632    StNumGeometries,
633    StNumInteriorRing,
634    StNumInteriorRings,
635    StNumPoints,
636    StOrderingEquals,
637    StOverlaps,
638    StPerimeter,
639    StPerimeter2D,
640    StPerimeter3D,
641    StPoint,
642    StPointFromText,
643    StPointFromWkb,
644    StPointN,
645    StPointOnSurface,
646    StPointInsideCircle,
647    StPolygon,
648    StPolygonFromText,
649    StPolygonize,
650    StRelate,
651    StRemovePoint,
652    StReverse,
653    StRotate,
654    StRotateX,
655    StRotateY,
656    StRotateZ,
657    StScale,
658    StSegmentize,
659    StSetPoint,
660    StSetSrid,
661    StShiftLongitude,
662    StShortestLine,
663    StSimplify,
664    StSimplifyPreserveTopology,
665    StSnapToGrid,
666    StSRID,
667    StStartPoint,
668    StSummary,
669    StSymDifference,
670    StTouches,
671    StTransform,
672    StTranslate,
673    StTransScale,
674    StUnion,
675    StWithin,
676    StWkbToSQL,
677    StWktToSQL,
678    StX,
679    StXMax,
680    StXMin,
681    StY,
682    StYMax,
683    StYMin,
684    StZ,
685    StZMax,
686    StZMin,
687    StZmflag,
688    // PostGIS additional functions
689    StMakeValid,
690    StIsValidDetail,
691    StDump,
692    StDumpPoints,
693    StDumpRings,
694    StDumpSegments,
695    StSnap,
696    StNode,
697    StSplit,
698    StSharedPaths,
699    StExpand,
700    StEstimatedExtent,
701    StFlipCoordinates,
702    StForceCw,
703    StForceCcw,
704    StForcePolygonCw,
705    StForcePolygonCcw,
706    StConcaveHull,
707    StVoronoiPolygons,
708    StVoronoiLines,
709    StDelaunayTriangles,
710    StSubdivide,
711    StGeneratePoints,
712    StBoundingDiagonal,
713    StMaximumInscribedCircle,
714    StChaikinSmoothing,
715    StFrechetDistance,
716    StProject,
717    StLocateAlong,
718    StLocateBetween,
719    StInterpolatePoint,
720    StMakeBox2D,
721    St3DMakeBox,
722    St3DDistance,
723    St3DMaxDistance,
724    St3DIntersects,
725    StExtent,
726    St3DExtent,
727    // PostgreSQL UUID functions
728    GenRandomUuid,
729    UuidExtractTimestamp,
730    UuidExtractVersion,
731    Uuidv4,
732    Uuidv7,
733    // PostgreSQL XML functions
734    CursorToXml,
735    CursorToXmlschema,
736    DatabaseToXml,
737    DatabaseToXmlAndXmlschema,
738    DatabaseToXmlschema,
739    QueryToXml,
740    QueryToXmlAndXmlschema,
741    QueryToXmlschema,
742    SchemaToXml,
743    SchemaToXmlAndXmlschema,
744    SchemaToXmlschema,
745    TableToXml,
746    TableToXmlAndXmlschema,
747    TableToXmlschema,
748    XmlComment,
749    XmlConcat,
750    XmlIsWellFormed,
751    XmlIsWellFormedContent,
752    XmlIsWellFormedDocument,
753    XmlText,
754    Xpath,
755    XpathExists,
756    // PostgreSQL JSON functions
757    ArrayToJson,
758    JsonArrayElements,
759    JsonArrayElementsText,
760    JsonArrayLength,
761    JsonBuildArray,
762    JsonEach,
763    JsonEachText,
764    JsonExtractPath,
765    JsonExtractPathText,
766    JsonObjectKeys,
767    JsonPopulateRecord,
768    JsonPopulateRecordset,
769    JsonScalar,
770    JsonSerialize,
771    JsonStripNulls,
772    JsonToRecord,
773    JsonToRecordset,
774    JsonTypeof,
775    JsonbArrayElements,
776    JsonbArrayElementsText,
777    JsonbArrayLength,
778    JsonbBuildArray,
779    JsonbBuildObject,
780    JsonbEach,
781    JsonbEachText,
782    JsonbExtractPath,
783    JsonbExtractPathText,
784    JsonbInsert,
785    JsonbObject,
786    JsonbObjectKeys,
787    JsonbPathExists,
788    JsonbPathExistsTz,
789    JsonbPathMatch,
790    JsonbPathMatchTz,
791    JsonbPathQuery,
792    JsonbPathQueryArray,
793    JsonbPathQueryArrayTz,
794    JsonbPathQueryFirst,
795    JsonbPathQueryFirstTz,
796    JsonbPathQueryTz,
797    JsonbPopulateRecord,
798    JsonbPopulateRecordValid,
799    JsonbPopulateRecordset,
800    JsonbPretty,
801    JsonbSetLax,
802    JsonbStripNulls,
803    JsonbToRecord,
804    JsonbToRecordset,
805    JsonbTypeof,
806    RowToJson,
807    ToJson,
808    ToJsonb,
809    // PostgreSQL sequence functions
810    Currval,
811    Lastval,
812    Nextval,
813    Setval,
814    // PostgreSQL array functions
815    ArrayAppend,
816    ArrayCat,
817    ArrayDims,
818    ArrayFill,
819    ArrayLength,
820    ArrayLower,
821    ArrayNdims,
822    ArrayPosition,
823    ArrayPositions,
824    ArrayPrepend,
825    ArrayRemove,
826    ArrayReplace,
827    ArrayReverse,
828    ArraySample,
829    ArrayShuffle,
830    ArraySort,
831    ArrayToString,
832    ArrayUpper,
833    Cardinality,
834    TrimArray,
835    // PostgreSQL range/multirange functions
836    IsEmpty,
837    LowerInc,
838    LowerInf,
839    UpperInc,
840    UpperInf,
841    RangeMerge,
842    Multirange,
843    Int4Range,
844    Int8Range,
845    NumRange,
846    TsRange,
847    TstzRange,
848    DateRange,
849    Int4Multirange,
850    Int8Multirange,
851    NumMultirange,
852    TsMultirange,
853    TstzMultirange,
854    DateMultirange,
855    // PostgreSQL text search functions
856    ArrayToTsvector,
857    GetCurrentTsConfig,
858    JsonToTsvector,
859    JsonbToTsvector,
860    Numnode,
861    PhraseToTsquery,
862    PlainToTsquery,
863    Querytree,
864    Setweight,
865    Strip,
866    ToTsquery,
867    ToTsvector,
868    TsDebug,
869    TsDelete,
870    TsFilter,
871    TsHeadline,
872    TsLexize,
873    TsParse,
874    TsRank,
875    TsRankCd,
876    TsRewrite,
877    TsStat,
878    TsTokenType,
879    TsqueryPhrase,
880    TsvectorToArray,
881    Unnest,
882    WebsearchToTsquery,
883    Other(Vec<Identifier<'a>>),
884}
885
886/// Function call expression,
887#[derive(Debug, Clone)]
888pub struct FunctionCallExpression<'a> {
889    pub function: Function<'a>,
890    pub args: Vec<Expression<'a>>,
891    pub function_span: Span,
892    pub r_paren_span: Span,
893}
894
895impl Spanned for FunctionCallExpression<'_> {
896    fn span(&self) -> Span {
897        self.function_span
898            .join_span(&self.args)
899            .join_span(&self.r_paren_span)
900    }
901}
902
903/// CHAR(N,... [USING charset_name]) expression
904#[derive(Debug, Clone)]
905pub struct CharFunctionExpression<'a> {
906    /// Span of "CHAR"
907    pub char_span: Span,
908    /// Arguments to CHAR()
909    pub args: Vec<Expression<'a>>,
910    /// Optional USING charset_name clause
911    pub using_charset: Option<(Span, Identifier<'a>)>,
912    pub r_paren_span: Span,
913}
914
915impl<'a> Spanned for CharFunctionExpression<'a> {
916    fn span(&self) -> Span {
917        self.char_span
918            .join_span(&self.args)
919            .join_span(&self.using_charset)
920            .join_span(&self.r_paren_span)
921    }
922}
923
924/// Window frame mode: ROWS, RANGE, or GROUPS
925#[derive(Debug, Clone)]
926pub enum WindowFrameMode {
927    Rows(Span),
928    Range(Span),
929    Groups(Span),
930}
931
932impl Spanned for WindowFrameMode {
933    fn span(&self) -> Span {
934        match self {
935            WindowFrameMode::Rows(s) | WindowFrameMode::Range(s) | WindowFrameMode::Groups(s) => {
936                s.clone()
937            }
938        }
939    }
940}
941
942/// One bound in a window frame clause
943#[derive(Debug, Clone)]
944pub enum WindowFrameBound<'a> {
945    /// UNBOUNDED PRECEDING
946    UnboundedPreceding(Span),
947    /// <expr> PRECEDING
948    Preceding(Expression<'a>, Span),
949    /// CURRENT ROW
950    CurrentRow(Span),
951    /// <expr> FOLLOWING
952    Following(Expression<'a>, Span),
953    /// UNBOUNDED FOLLOWING
954    UnboundedFollowing(Span),
955}
956
957impl<'a> Spanned for WindowFrameBound<'a> {
958    fn span(&self) -> Span {
959        match self {
960            WindowFrameBound::UnboundedPreceding(s) => s.clone(),
961            WindowFrameBound::Preceding(e, s) => e.span().join_span(s),
962            WindowFrameBound::CurrentRow(s) => s.clone(),
963            WindowFrameBound::Following(e, s) => e.span().join_span(s),
964            WindowFrameBound::UnboundedFollowing(s) => s.clone(),
965        }
966    }
967}
968
969/// Window frame clause: ROWS/RANGE/GROUPS { frame_start | BETWEEN frame_start AND frame_end }
970#[derive(Debug, Clone)]
971pub struct WindowFrame<'a> {
972    /// ROWS, RANGE, or GROUPS
973    pub mode: WindowFrameMode,
974    /// The start bound (or sole bound when no BETWEEN)
975    pub start: WindowFrameBound<'a>,
976    /// When BETWEEN was used: span covering "BETWEEN ... AND" and the end bound
977    pub between: Option<(Span, WindowFrameBound<'a>)>,
978}
979
980impl<'a> Spanned for WindowFrame<'a> {
981    fn span(&self) -> Span {
982        let s = self.mode.span().join_span(&self.start);
983        if let Some((and_span, end)) = &self.between {
984            s.join_span(and_span).join_span(end)
985        } else {
986            s
987        }
988    }
989}
990
991/// When part of CASE
992#[derive(Debug, Clone)]
993pub struct WindowSpec<'a> {
994    /// Span of the opening parenthesis -- used as fallback when the spec is empty
995    pub lparen_span: Span,
996    /// Span of "PARTITION BY" and list of partition expressions, if specified
997    pub partition_by: Option<(Span, Vec<Expression<'a>>)>,
998    /// Span of "ORDER BY" and list of order expression and directions, if specified
999    pub order_by: Option<(Span, Vec<(Expression<'a>, OrderFlag)>)>,
1000    /// Window frame clause (ROWS/RANGE BETWEEN ... AND ...), if specified
1001    pub frame: Option<WindowFrame<'a>>,
1002    /// Span of the closing ')'
1003    pub rparen_span: Span,
1004}
1005
1006impl<'a> Spanned for WindowSpec<'a> {
1007    fn span(&self) -> Span {
1008        self.lparen_span
1009            .join_span(&self.partition_by)
1010            .join_span(&self.order_by)
1011            .join_span(&self.frame)
1012            .join_span(&self.rparen_span)
1013    }
1014}
1015
1016#[derive(Debug, Clone)]
1017pub struct WindowClause<'a> {
1018    pub over_span: Span,
1019    pub window_spec: WindowSpec<'a>,
1020}
1021
1022impl Spanned for WindowClause<'_> {
1023    fn span(&self) -> Span {
1024        self.over_span.join_span(&self.window_spec)
1025    }
1026}
1027
1028/// A window function call expression
1029#[derive(Debug, Clone)]
1030pub struct WindowFunctionCallExpression<'a> {
1031    pub function: Function<'a>,
1032    pub args: Vec<Expression<'a>>,
1033    pub function_span: Span,
1034    pub r_paren_span: Span,
1035    pub over: WindowClause<'a>,
1036}
1037
1038impl Spanned for WindowFunctionCallExpression<'_> {
1039    fn span(&self) -> Span {
1040        self.function_span
1041            .join_span(&self.args)
1042            .join_span(&self.r_paren_span)
1043            .join_span(&self.over)
1044    }
1045}
1046
1047#[derive(Debug, Clone)]
1048pub struct AggregateFunctionCallExpression<'a> {
1049    pub function: Function<'a>,
1050    pub args: Vec<Expression<'a>>,
1051    pub function_span: Span,
1052    pub r_paren_span: Span,
1053    pub distinct_span: Option<Span>,
1054    pub within_group: Option<(Span, Vec<(Expression<'a>, OrderFlag)>)>,
1055    pub filter: Option<(Span, Expression<'a>)>,
1056    pub over: Option<WindowClause<'a>>,
1057}
1058
1059impl Spanned for AggregateFunctionCallExpression<'_> {
1060    fn span(&self) -> Span {
1061        self.function_span
1062            .join_span(&self.args)
1063            .join_span(&self.r_paren_span)
1064            .join_span(&self.distinct_span)
1065            .join_span(&self.within_group)
1066            .join_span(&self.filter)
1067            .join_span(&self.over)
1068    }
1069}
1070
1071pub(crate) fn is_aggregate_function_ident(keyword: &Keyword) -> bool {
1072    matches!(
1073        keyword,
1074        Keyword::COUNT
1075            | Keyword::AVG
1076            | Keyword::SUM
1077            | Keyword::MIN
1078            | Keyword::MAX
1079            | Keyword::JSON_ARRAYAGG
1080            | Keyword::JSON_OBJECTAGG
1081            | Keyword::ARRAY_AGG
1082            | Keyword::BIT_AND
1083            | Keyword::BIT_OR
1084            | Keyword::BIT_XOR
1085            | Keyword::BOOL_AND
1086            | Keyword::BOOL_OR
1087            | Keyword::CORR
1088            | Keyword::COVAR_POP
1089            | Keyword::COVAR_SAMP
1090            | Keyword::CUME_DIST
1091            | Keyword::DENSE_RANK
1092            | Keyword::EVERY
1093            | Keyword::JSON_AGG
1094            | Keyword::JSONB_AGG
1095            | Keyword::JSONB_OBJECT_AGG
1096            | Keyword::PERCENT_RANK
1097            | Keyword::PERCENTILE_CONT
1098            | Keyword::PERCENTILE_DISC
1099            | Keyword::RANK
1100            | Keyword::REGR_AVGX
1101            | Keyword::REGR_AVGY
1102            | Keyword::REGR_COUNT
1103            | Keyword::REGR_INTERCEPT
1104            | Keyword::REGR_R2
1105            | Keyword::REGR_SLOPE
1106            | Keyword::REGR_SXX
1107            | Keyword::REGR_SXY
1108            | Keyword::REGR_SYY
1109            | Keyword::STD
1110            | Keyword::STDDEV
1111            | Keyword::STDDEV_POP
1112            | Keyword::STDDEV_SAMP
1113            | Keyword::STRING_AGG
1114            | Keyword::VARIANCE
1115            | Keyword::VAR_POP
1116            | Keyword::VAR_SAMP
1117            | Keyword::XMLAGG
1118            | Keyword::MODE
1119    )
1120}
1121
1122fn parse_window_frame_bound<'a>(
1123    parser: &mut Parser<'a, '_>,
1124) -> Result<WindowFrameBound<'a>, ParseError> {
1125    match &parser.token {
1126        Token::Ident(_, Keyword::UNBOUNDED) => {
1127            let kw_span = parser.consume_keyword(Keyword::UNBOUNDED)?;
1128            if let Some(span) = parser.skip_keyword(Keyword::PRECEDING) {
1129                Ok(WindowFrameBound::UnboundedPreceding(
1130                    kw_span.join_span(&span),
1131                ))
1132            } else {
1133                Ok(WindowFrameBound::UnboundedFollowing(
1134                    parser
1135                        .consume_keyword(Keyword::FOLLOWING)?
1136                        .join_span(&kw_span),
1137                ))
1138            }
1139        }
1140        Token::Ident(_, Keyword::CURRENT) => {
1141            let current_row_span = parser.consume_keywords(&[Keyword::CURRENT, Keyword::ROW])?;
1142            Ok(WindowFrameBound::CurrentRow(current_row_span))
1143        }
1144        _ => {
1145            let expr = parse_expression_unreserved(parser, PRIORITY_MAX)?;
1146            if let Some(s) = parser.skip_keyword(Keyword::PRECEDING) {
1147                Ok(WindowFrameBound::Preceding(expr, s))
1148            } else {
1149                let s = parser.consume_keyword(Keyword::FOLLOWING)?;
1150                Ok(WindowFrameBound::Following(expr, s))
1151            }
1152        }
1153    }
1154}
1155
1156fn parse_window_frame<'a>(
1157    parser: &mut Parser<'a, '_>,
1158    mode: WindowFrameMode,
1159) -> Result<WindowFrame<'a>, ParseError> {
1160    if let Some(between_span) = parser.skip_keyword(Keyword::BETWEEN) {
1161        let start = parse_window_frame_bound(parser)?;
1162        let and_span = parser.consume_keyword(Keyword::AND)?;
1163        let end = parse_window_frame_bound(parser)?;
1164        Ok(WindowFrame {
1165            mode,
1166            start,
1167            between: Some((between_span.join_span(&and_span), end)),
1168        })
1169    } else {
1170        let start = parse_window_frame_bound(parser)?;
1171        Ok(WindowFrame {
1172            mode,
1173            start,
1174            between: None,
1175        })
1176    }
1177}
1178
1179fn parse_over_clause<'a>(
1180    parser: &mut Parser<'a, '_>,
1181) -> Result<Option<WindowClause<'a>>, ParseError> {
1182    let Some(over_span) = parser.skip_keyword(Keyword::OVER) else {
1183        return Ok(None);
1184    };
1185
1186    let lparen_span = parser.consume_token(Token::LParen)?;
1187
1188    let partition_by = if let Some(partition_span) = parser.skip_keyword(Keyword::PARTITION) {
1189        let partition_by_span = partition_span.join_span(&parser.consume_keyword(Keyword::BY)?);
1190        let mut partition_exprs = Vec::new();
1191        loop {
1192            partition_exprs.push(parse_expression_unreserved(parser, PRIORITY_MAX)?);
1193            if parser.skip_token(Token::Comma).is_none() {
1194                break;
1195            }
1196        }
1197        Some((partition_by_span, partition_exprs))
1198    } else {
1199        None
1200    };
1201
1202    let order_by = if let Some(span) = parser.skip_keyword(Keyword::ORDER) {
1203        let order_span = span.join_span(&parser.consume_keyword(Keyword::BY)?);
1204        let mut order = Vec::new();
1205        loop {
1206            let e = parse_expression_unreserved(parser, PRIORITY_MAX)?;
1207            let f = match &parser.token {
1208                Token::Ident(_, Keyword::ASC) => OrderFlag::Asc(parser.consume()),
1209                Token::Ident(_, Keyword::DESC) => OrderFlag::Desc(parser.consume()),
1210                _ => OrderFlag::None,
1211            };
1212            order.push((e, f));
1213            if parser.skip_token(Token::Comma).is_none() {
1214                break;
1215            }
1216        }
1217        Some((order_span, order))
1218    } else {
1219        None
1220    };
1221
1222    // Window frame clause: ROWS/RANGE { frame_start | BETWEEN frame_start AND frame_end }
1223    let frame = if let Some(s) = parser.skip_keyword(Keyword::ROWS) {
1224        Some(parse_window_frame(parser, WindowFrameMode::Rows(s))?)
1225    } else if let Some(s) = parser.skip_keyword(Keyword::RANGE) {
1226        Some(parse_window_frame(parser, WindowFrameMode::Range(s))?)
1227    } else {
1228        None
1229    };
1230
1231    let rparen_span = parser.consume_token(Token::RParen)?;
1232
1233    Ok(Some(WindowClause {
1234        over_span,
1235        window_spec: WindowSpec {
1236            lparen_span,
1237            partition_by,
1238            order_by,
1239            frame,
1240            rparen_span,
1241        },
1242    }))
1243}
1244
1245pub(crate) fn parse_aggregate_function<'a>(
1246    parser: &mut Parser<'a, '_>,
1247    t: Token<'a>,
1248    span: Span,
1249) -> Result<Expression<'a>, ParseError> {
1250    parser.consume_token(Token::LParen)?;
1251    let func = match &t {
1252        Token::Ident(_, Keyword::COUNT) => Function::Count,
1253        Token::Ident(_, Keyword::AVG) => Function::Avg,
1254        Token::Ident(_, Keyword::SUM) => Function::Sum,
1255        Token::Ident(_, Keyword::MIN) => Function::Min,
1256        Token::Ident(_, Keyword::MAX) => Function::Max,
1257        Token::Ident(_, Keyword::JSON_ARRAYAGG) => Function::JsonArrayAgg,
1258        Token::Ident(_, Keyword::JSON_OBJECTAGG) => Function::JsonObjectAgg,
1259        Token::Ident(_, Keyword::ARRAY_AGG) => Function::ArrayAgg,
1260        Token::Ident(_, Keyword::BIT_AND) => Function::BitAnd,
1261        Token::Ident(_, Keyword::BIT_OR) => Function::BitOr,
1262        Token::Ident(_, Keyword::BIT_XOR) => Function::BitXor,
1263        Token::Ident(_, Keyword::BOOL_AND) => Function::BoolAnd,
1264        Token::Ident(_, Keyword::BOOL_OR) => Function::BoolOr,
1265        Token::Ident(_, Keyword::CORR) => Function::Corr,
1266        Token::Ident(_, Keyword::COVAR_POP) => Function::CovarPop,
1267        Token::Ident(_, Keyword::COVAR_SAMP) => Function::CovarSamp,
1268        Token::Ident(_, Keyword::CUME_DIST) => Function::CumeDist,
1269        Token::Ident(_, Keyword::DENSE_RANK) => Function::DenseRank,
1270        Token::Ident(_, Keyword::EVERY) => Function::BoolAnd,
1271        Token::Ident(_, Keyword::JSON_AGG) => Function::JsonAgg,
1272        Token::Ident(_, Keyword::JSONB_AGG) => Function::JsonbAgg,
1273        Token::Ident(_, Keyword::JSONB_OBJECT_AGG) => Function::JsonbObjectAgg,
1274        Token::Ident(_, Keyword::JSONB_SET) => Function::JsonbSet,
1275        Token::Ident(_, Keyword::PERCENT_RANK) => Function::PercentRank,
1276        Token::Ident(_, Keyword::PERCENTILE_CONT) => Function::PercentileCont,
1277        Token::Ident(_, Keyword::PERCENTILE_DISC) => Function::PercentileDisc,
1278        Token::Ident(_, Keyword::RANK) => Function::Rank,
1279        Token::Ident(_, Keyword::REGR_AVGX) => Function::RegrAvgx,
1280        Token::Ident(_, Keyword::REGR_AVGY) => Function::RegrAvgy,
1281        Token::Ident(_, Keyword::REGR_COUNT) => Function::RegrCount,
1282        Token::Ident(_, Keyword::REGR_INTERCEPT) => Function::RegrIntercept,
1283        Token::Ident(_, Keyword::REGR_R2) => Function::RegrR2,
1284        Token::Ident(_, Keyword::REGR_SLOPE) => Function::RegrSlope,
1285        Token::Ident(_, Keyword::REGR_SXX) => Function::RegrSxx,
1286        Token::Ident(_, Keyword::REGR_SXY) => Function::RegrSxy,
1287        Token::Ident(_, Keyword::REGR_SYY) => Function::RegrSyy,
1288        Token::Ident(_, Keyword::STD) => Function::Std,
1289        Token::Ident(_, Keyword::STDDEV) => Function::Stddev,
1290        Token::Ident(_, Keyword::STDDEV_POP) => Function::StddevPop,
1291        Token::Ident(_, Keyword::STDDEV_SAMP) => Function::StddevSamp,
1292        Token::Ident(_, Keyword::STRING_AGG) => Function::StringAgg,
1293        Token::Ident(_, Keyword::VARIANCE) => Function::Variance,
1294        Token::Ident(_, Keyword::VAR_POP) => Function::VarPop,
1295        Token::Ident(_, Keyword::VAR_SAMP) => Function::VarSamp,
1296        Token::Ident(_, Keyword::XMLAGG) => Function::Xmlagg,
1297        Token::Ident(_, Keyword::MODE) => Function::Mode,
1298        _ => {
1299            parser.err("Unknown aggregate function", &span);
1300            Function::Unknown
1301        }
1302    };
1303
1304    let distinct_span = parser.skip_keyword(Keyword::DISTINCT);
1305    let mut args = Vec::new();
1306    if !matches!(parser.token, Token::RParen) {
1307        loop {
1308            parser.recovered(
1309                "')' or ','",
1310                &|t| matches!(t, Token::RParen | Token::Comma),
1311                |parser| {
1312                    args.push(parse_expression_outer(parser)?);
1313                    Ok(())
1314                },
1315            )?;
1316            if parser.skip_token(Token::Comma).is_none() {
1317                break;
1318            }
1319        }
1320    }
1321    let r_paren_span = parser.consume_token(Token::RParen)?;
1322
1323    let within_group = if let Some(within_span) = parser.skip_keyword(Keyword::WITHIN) {
1324        let within_group_span = within_span.join_span(&parser.consume_keyword(Keyword::GROUP)?);
1325        parser.consume_token(Token::LParen)?;
1326        let order_span = parser.consume_keyword(Keyword::ORDER)?;
1327        let order_by_span = order_span.join_span(&parser.consume_keyword(Keyword::BY)?);
1328        let mut order = Vec::new();
1329        loop {
1330            let e = parse_expression_unreserved(parser, PRIORITY_MAX)?;
1331            let f = match &parser.token {
1332                Token::Ident(_, Keyword::ASC) => OrderFlag::Asc(parser.consume()),
1333                Token::Ident(_, Keyword::DESC) => OrderFlag::Desc(parser.consume()),
1334                _ => OrderFlag::None,
1335            };
1336            order.push((e, f));
1337            if parser.skip_token(Token::Comma).is_none() {
1338                break;
1339            }
1340        }
1341        parser.consume_token(Token::RParen)?;
1342        Some((within_group_span.join_span(&order_by_span), order))
1343    } else {
1344        None
1345    };
1346
1347    let filter = if let Some(filter_span) = parser.skip_keyword(Keyword::FILTER) {
1348        parser.postgres_only(&filter_span);
1349        parser.consume_token(Token::LParen)?;
1350        parser.consume_keyword(Keyword::WHERE)?;
1351        let condition = parse_expression_unreserved(parser, PRIORITY_MAX)?;
1352        parser.consume_token(Token::RParen)?;
1353        Some((filter_span, condition))
1354    } else {
1355        None
1356    };
1357
1358    let over = parse_over_clause(parser)?;
1359
1360    Ok(Expression::AggregateFunction(Box::new(
1361        AggregateFunctionCallExpression {
1362            function: func,
1363            args,
1364            function_span: span,
1365            r_paren_span,
1366            distinct_span,
1367            within_group,
1368            filter,
1369            over,
1370        },
1371    )))
1372}
1373
1374pub(crate) fn parse_function<'a>(
1375    parser: &mut Parser<'a, '_>,
1376    t: Token<'a>,
1377    span: Span,
1378) -> Result<Expression<'a>, ParseError> {
1379    parser.consume_token(Token::LParen)?;
1380
1381    let func = match &t {
1382        // https://mariadb.com/kb/en/string-functions/
1383        Token::Ident(_, Keyword::ASCII) => Function::Ascii,
1384        Token::Ident(_, Keyword::BIN) => Function::Bin,
1385        Token::Ident(_, Keyword::BIT_LENGTH) => Function::BitLength,
1386        Token::Ident(_, Keyword::CHAR_LENGTH) => Function::CharacterLength,
1387        Token::Ident(_, Keyword::CHARACTER_LENGTH) => Function::CharacterLength,
1388        Token::Ident(_, Keyword::CHR) => Function::Chr,
1389        Token::Ident(_, Keyword::CONCAT) => Function::Concat,
1390        Token::Ident(_, Keyword::CONCAT_WS) => Function::ConcatWs,
1391        Token::Ident(_, Keyword::ELT) => Function::Elt,
1392        Token::Ident(_, Keyword::EXPORT_SET) => Function::ExportSet,
1393        Token::Ident(_, Keyword::EXTRACTVALUE) => Function::ExtractValue,
1394        Token::Ident(_, Keyword::FIELD) => Function::Field,
1395        Token::Ident(_, Keyword::FIND_IN_SET) => Function::FindInSet,
1396        Token::Ident(_, Keyword::FORMAT) => Function::Format,
1397        Token::Ident(_, Keyword::FROM_BASE64) => Function::FromBase64,
1398        Token::Ident(_, Keyword::HEX) => Function::Hex,
1399        Token::Ident(_, Keyword::INSERT) => Function::Insert,
1400        Token::Ident(_, Keyword::INSTR) => Function::InStr,
1401        Token::Ident(_, Keyword::LCASE) => Function::LCase,
1402        Token::Ident(_, Keyword::LEFT) => Function::Left,
1403        Token::Ident(_, Keyword::LENGTH) => Function::Length,
1404        Token::Ident(_, Keyword::LENGTHB) => Function::LengthB,
1405        Token::Ident(_, Keyword::LOAD_FILE) => Function::LoadFile,
1406        Token::Ident(_, Keyword::LOCATE) => Function::Locate,
1407        Token::Ident(_, Keyword::LOWER) => Function::Lower,
1408        Token::Ident(_, Keyword::LPAD) => Function::LPad,
1409        Token::Ident(_, Keyword::LTRIM) => Function::LTrim,
1410        Token::Ident(_, Keyword::MAKE_SET) => Function::MakeSet,
1411        Token::Ident(_, Keyword::MID) => Function::Mid,
1412        Token::Ident(_, Keyword::NATURAL_SORT_KEY) => Function::NaturalSortkey,
1413        Token::Ident(_, Keyword::OCTET_LENGTH) => Function::OctetLength,
1414        Token::Ident(_, Keyword::ORD) => Function::Ord,
1415        Token::Ident(_, Keyword::POSITION) => Function::Position,
1416        Token::Ident(_, Keyword::QUOTE) => Function::Quote,
1417        Token::Ident(_, Keyword::REPEAT) => Function::Repeat,
1418        Token::Ident(_, Keyword::REPLACE) => Function::Replace,
1419        Token::Ident(_, Keyword::REVERSE) => Function::Reverse,
1420        Token::Ident(_, Keyword::RIGHT) => Function::Right,
1421        Token::Ident(_, Keyword::RPAD) => Function::RPad,
1422        Token::Ident(_, Keyword::RTRIM) => Function::RTrim,
1423        Token::Ident(_, Keyword::SOUNDEX) => Function::SoundEx,
1424        Token::Ident(_, Keyword::SLEEP) => Function::Sleep,
1425        Token::Ident(_, Keyword::SPACE) => Function::Space,
1426        Token::Ident(_, Keyword::STRCMP) => Function::StrCmp,
1427        Token::Ident(_, Keyword::SUBSTR) => Function::SubStr,
1428        Token::Ident(_, Keyword::SUBSTRING) => Function::SubStr,
1429        Token::Ident(_, Keyword::SUBSTRING_INDEX) => Function::SubStringIndex,
1430        Token::Ident(_, Keyword::TO_BASE64) => Function::ToBase64,
1431        Token::Ident(_, Keyword::TO_CHAR) => Function::ToChar,
1432        Token::Ident(_, Keyword::TO_DATE) => Function::ToDate,
1433        Token::Ident(_, Keyword::TO_NUMBER) => Function::ToNumber,
1434        Token::Ident(_, Keyword::TO_TIMESTAMP) => Function::ToTimestamp,
1435        Token::Ident(_, Keyword::UCASE) => Function::UCase,
1436        Token::Ident(_, Keyword::UNCOMPRESSED_LENGTH) => Function::UncompressedLength,
1437        Token::Ident(_, Keyword::UNHEX) => Function::UnHex,
1438        Token::Ident(_, Keyword::UPDATEXML) => Function::UpdateXml,
1439        Token::Ident(_, Keyword::UPPER) => Function::Upper,
1440        Token::Ident(_, Keyword::SFORMAT) => Function::SFormat,
1441
1442        // PostgreSQL string functions
1443        Token::Ident(_, Keyword::BTRIM) if parser.options.dialect.is_postgresql() => {
1444            Function::Btrim
1445        }
1446        Token::Ident(_, Keyword::CASEFOLD) if parser.options.dialect.is_postgresql() => {
1447            Function::Casefold
1448        }
1449        Token::Ident(_, Keyword::INITCAP) if parser.options.dialect.is_postgresql() => {
1450            Function::Initcap
1451        }
1452        Token::Ident(_, Keyword::NORMALIZE) if parser.options.dialect.is_postgresql() => {
1453            Function::Normalize
1454        }
1455        Token::Ident(_, Keyword::PARSE_IDENT) if parser.options.dialect.is_postgresql() => {
1456            Function::ParseIdent
1457        }
1458        Token::Ident(_, Keyword::PG_CLIENT_ENCODING) if parser.options.dialect.is_postgresql() => {
1459            Function::PgClientEncoding
1460        }
1461        Token::Ident(_, Keyword::QUOTE_IDENT) if parser.options.dialect.is_postgresql() => {
1462            Function::QuoteIdent
1463        }
1464        Token::Ident(_, Keyword::QUOTE_LITERAL) if parser.options.dialect.is_postgresql() => {
1465            Function::QuoteLiteral
1466        }
1467        Token::Ident(_, Keyword::QUOTE_NULLABLE) if parser.options.dialect.is_postgresql() => {
1468            Function::QuoteNullable
1469        }
1470        Token::Ident(_, Keyword::SPLIT_PART) if parser.options.dialect.is_postgresql() => {
1471            Function::SplitPart
1472        }
1473        Token::Ident(_, Keyword::STRING_TO_ARRAY) if parser.options.dialect.is_postgresql() => {
1474            Function::StringToArray
1475        }
1476        Token::Ident(_, Keyword::STRING_TO_TABLE) if parser.options.dialect.is_postgresql() => {
1477            Function::StringToTable
1478        }
1479        Token::Ident(_, Keyword::STRPOS) if parser.options.dialect.is_postgresql() => {
1480            Function::Strpos
1481        }
1482        Token::Ident(_, Keyword::TO_ASCII) if parser.options.dialect.is_postgresql() => {
1483            Function::ToAscii
1484        }
1485        Token::Ident(_, Keyword::TO_BIN) if parser.options.dialect.is_postgresql() => {
1486            Function::ToBin
1487        }
1488        Token::Ident(_, Keyword::TO_HEX) if parser.options.dialect.is_postgresql() => {
1489            Function::ToHex
1490        }
1491        Token::Ident(_, Keyword::TO_OCT) if parser.options.dialect.is_postgresql() => {
1492            Function::ToOct
1493        }
1494        Token::Ident(_, Keyword::TRANSLATE) if parser.options.dialect.is_postgresql() => {
1495            Function::Translate
1496        }
1497        Token::Ident(_, Keyword::UNICODE_ASSIGNED) if parser.options.dialect.is_postgresql() => {
1498            Function::UnicodeAssigned
1499        }
1500        Token::Ident(_, Keyword::UNISTR) if parser.options.dialect.is_postgresql() => {
1501            Function::Unistr
1502        }
1503
1504        // TODO uncat
1505        Token::Ident(_, Keyword::EXISTS) => Function::Exists,
1506        Token::Ident(_, Keyword::COUNT) => Function::Count,
1507        Token::Ident(_, Keyword::AVG) => Function::Avg,
1508        Token::Ident(_, Keyword::MIN) => Function::Min,
1509        Token::Ident(_, Keyword::MAX) => Function::Max,
1510        Token::Ident(_, Keyword::SUM) => Function::Sum,
1511        Token::Ident(_, Keyword::VALUE) => Function::Value,
1512        Token::Ident(_, Keyword::VALUES) => Function::Value,
1513        Token::Ident(_, Keyword::LEAD) => Function::Lead,
1514        Token::Ident(_, Keyword::LAG) => Function::Lag,
1515        Token::Ident(_, Keyword::STARTS_WITH) => Function::StartsWith,
1516
1517        //https://mariadb.com/kb/en/control-flow-functions/
1518        Token::Ident(_, Keyword::IFNULL) => Function::IfNull,
1519        Token::Ident(_, Keyword::NULLIF) => Function::NullIf,
1520        Token::Ident(_, Keyword::NVL) => Function::IfNull,
1521        Token::Ident(_, Keyword::NVL2) => Function::NVL2,
1522        Token::Ident(_, Keyword::IF) => Function::If,
1523        Token::Ident(_, Keyword::COALESCE) => Function::Coalesce,
1524
1525        //https://mariadb.com/kb/en/numeric-functions/
1526        Token::Ident(_, Keyword::ABS) => Function::Abs,
1527        Token::Ident(_, Keyword::ACOS) => Function::Acos,
1528        Token::Ident(_, Keyword::ACOSD) => Function::Acosd,
1529        Token::Ident(_, Keyword::ACOSH) => Function::Acosh,
1530        Token::Ident(_, Keyword::ASIN) => Function::Asin,
1531        Token::Ident(_, Keyword::ASIND) => Function::Asind,
1532        Token::Ident(_, Keyword::ASINH) => Function::Asinh,
1533        Token::Ident(_, Keyword::ATAN) => Function::Atan,
1534        Token::Ident(_, Keyword::ATAN2) => Function::Atan2,
1535        Token::Ident(_, Keyword::ATAN2D) => Function::Atan2d,
1536        Token::Ident(_, Keyword::ATAND) => Function::Atand,
1537        Token::Ident(_, Keyword::ATANH) => Function::Atanh,
1538        Token::Ident(_, Keyword::CBRT) => Function::Cbrt,
1539        Token::Ident(_, Keyword::CEIL | Keyword::CEILING) => Function::Ceil,
1540        Token::Ident(_, Keyword::CONV) => Function::Conv,
1541        Token::Ident(_, Keyword::COS) => Function::Cos,
1542        Token::Ident(_, Keyword::COSD) => Function::Cosd,
1543        Token::Ident(_, Keyword::COSH) => Function::Cosh,
1544        Token::Ident(_, Keyword::COT) => Function::Cot,
1545        Token::Ident(_, Keyword::COTD) => Function::Cotd,
1546        Token::Ident(_, Keyword::CRC32) => Function::Crc32,
1547        Token::Ident(_, Keyword::DEGREES) => Function::Degrees,
1548        Token::Ident(_, Keyword::ERF) => Function::Erf,
1549        Token::Ident(_, Keyword::ERFC) => Function::Erfc,
1550        Token::Ident(_, Keyword::EXP) => Function::Exp,
1551        Token::Ident(_, Keyword::FACTORIAL) => Function::Factorial,
1552        Token::Ident(_, Keyword::FLOOR) => Function::Floor,
1553        Token::Ident(_, Keyword::GAMMA) => Function::Gamma,
1554        Token::Ident(_, Keyword::GCD) => Function::Gcd,
1555        Token::Ident(_, Keyword::GREATEST) => Function::Greatest,
1556        Token::Ident(_, Keyword::LCM) => Function::Lcm,
1557        Token::Ident(_, Keyword::LGAMMA) => Function::Lgamma,
1558        Token::Ident(_, Keyword::LN) => Function::Ln,
1559        Token::Ident(_, Keyword::LOG) => Function::Log,
1560        Token::Ident(_, Keyword::LOG10) => Function::Log10,
1561        Token::Ident(_, Keyword::LOG2) => Function::Log2,
1562        Token::Ident(_, Keyword::MIN_SCALE) => Function::MinScale,
1563        Token::Ident(_, Keyword::MOD) => Function::Mod,
1564        Token::Ident(_, Keyword::OCT) => Function::Oct,
1565        Token::Ident(_, Keyword::PI) => Function::Pi,
1566        Token::Ident(_, Keyword::POW | Keyword::POWER) => Function::Pow,
1567        Token::Ident(_, Keyword::RADIANS) => Function::Radians,
1568        Token::Ident(_, Keyword::RAND) => Function::Rand,
1569        Token::Ident(_, Keyword::RANDOM_NORMAL) => Function::RandomNormal,
1570        Token::Ident(_, Keyword::ROUND) => Function::Round,
1571        Token::Ident(_, Keyword::SCALE) => Function::Scale,
1572        Token::Ident(_, Keyword::SET_BIT) => Function::SetBit,
1573        Token::Ident(_, Keyword::SETSEED) => Function::SetSeed,
1574        Token::Ident(_, Keyword::SIGN) => Function::Sign,
1575        Token::Ident(_, Keyword::SIN) => Function::Sin,
1576        Token::Ident(_, Keyword::SIND) => Function::Sind,
1577        Token::Ident(_, Keyword::SINH) => Function::Sinh,
1578        Token::Ident(_, Keyword::SQRT) => Function::Sqrt,
1579        Token::Ident(_, Keyword::TAN) => Function::Tan,
1580        Token::Ident(_, Keyword::TAND) => Function::Tand,
1581        Token::Ident(_, Keyword::TANH) => Function::Tanh,
1582        Token::Ident(_, Keyword::TRIM_SCALE) => Function::TrimScale,
1583        Token::Ident(_, Keyword::TRUNCATE) => Function::Truncate,
1584        Token::Ident(_, Keyword::WIDTH_BUCKET) => Function::WidthBucket,
1585        Token::Ident(_, Keyword::CRC32C) => Function::Crc32c,
1586        Token::Ident(_, Keyword::LEAST) => Function::Least,
1587
1588        // https://mariadb.com/kb/en/date-time-functions/
1589        Token::Ident(_, Keyword::ADDDATE) => Function::AddDate,
1590        Token::Ident(_, Keyword::ADDTIME) => Function::AddTime,
1591        Token::Ident(_, Keyword::CONVERT_TZ) => Function::ConvertTz,
1592        Token::Ident(_, Keyword::CURDATE) => Function::CurDate,
1593        Token::Ident(_, Keyword::CURRENT_DATE) => Function::CurDate,
1594        Token::Ident(_, Keyword::CURRENT_TIME) => Function::CurTime,
1595        Token::Ident(_, Keyword::CURTIME) => Function::CurTime,
1596        Token::Ident(_, Keyword::DATE) => Function::Date,
1597        Token::Ident(_, Keyword::HOUR) => Function::Hour,
1598        Token::Ident(_, Keyword::DATEDIFF) => Function::DateDiff,
1599        Token::Ident(_, Keyword::DATE_ADD) => Function::AddDate,
1600        Token::Ident(_, Keyword::DATE_FORMAT) => Function::DateFormat,
1601        Token::Ident(_, Keyword::DATE_SUB) => Function::DateSub,
1602        Token::Ident(_, Keyword::DAY | Keyword::DAYOFMONTH) => Function::DayOfMonth,
1603        Token::Ident(_, Keyword::DAYNAME) => Function::DayName,
1604        Token::Ident(_, Keyword::DAYOFWEEK) => Function::DayOfWeek,
1605        Token::Ident(_, Keyword::DAYOFYEAR) => Function::DayOfYear,
1606        Token::Ident(_, Keyword::FROM_DAYS) => Function::FromDays,
1607        Token::Ident(_, Keyword::CURRENT_TIMESTAMP) => Function::CurrentTimestamp,
1608        Token::Ident(_, Keyword::LOCALTIME | Keyword::LOCALTIMESTAMP | Keyword::NOW) => {
1609            Function::Now
1610        }
1611        Token::Ident(_, Keyword::MAKEDATE) => Function::MakeDate,
1612        Token::Ident(_, Keyword::MAKETIME) => Function::MakeTime,
1613        Token::Ident(_, Keyword::MICROSECOND) => Function::MicroSecond,
1614        Token::Ident(_, Keyword::MINUTE) => Function::Minute,
1615        Token::Ident(_, Keyword::MONTH) => Function::Month,
1616        Token::Ident(_, Keyword::MONTHNAME) => Function::MonthName,
1617        Token::Ident(_, Keyword::PERIOD_ADD) => Function::PeriodAdd,
1618        Token::Ident(_, Keyword::PERIOD_DIFF) => Function::PeriodDiff,
1619        Token::Ident(_, Keyword::QUARTER) => Function::Quarter,
1620        Token::Ident(_, Keyword::SECOND) => Function::Second,
1621        Token::Ident(_, Keyword::SEC_TO_TIME) => Function::SecToTime,
1622        Token::Ident(_, Keyword::STR_TO_DATE) => Function::StrToDate,
1623        Token::Ident(_, Keyword::SUBDATE) => Function::DateSub,
1624        Token::Ident(_, Keyword::SUBTIME) => Function::SubTime,
1625        Token::Ident(_, Keyword::TIME) => Function::Time,
1626        Token::Ident(_, Keyword::LAST_DAY) => Function::LastDay,
1627        Token::Ident(_, Keyword::TIMEDIFF) => Function::TimeDiff,
1628        Token::Ident(_, Keyword::TIMESTAMP) => Function::Timestamp,
1629        Token::Ident(_, Keyword::TIME_FORMAT) => Function::TimeFormat,
1630        Token::Ident(_, Keyword::TIME_TO_SEC) => Function::TimeToSec,
1631        Token::Ident(_, Keyword::TO_DAYS) => Function::ToDays,
1632        Token::Ident(_, Keyword::TO_SECONDS) => Function::ToSeconds,
1633        Token::Ident(_, Keyword::UNIX_TIMESTAMP) => Function::UnixTimestamp,
1634        Token::Ident(_, Keyword::UTC_DATE) => Function::UtcDate,
1635        Token::Ident(_, Keyword::UTC_TIME) => Function::UtcTime,
1636        Token::Ident(_, Keyword::UTC_TIMESTAMP) => Function::UtcTimeStamp,
1637        Token::Ident(_, Keyword::WEEK) => Function::Week,
1638        Token::Ident(_, Keyword::WEEKDAY) => Function::Weekday,
1639        Token::Ident(_, Keyword::WEEKOFYEAR) => Function::WeekOfYear,
1640        Token::Ident(_, Keyword::ADD_MONTHS) => Function::AddMonths,
1641        Token::Ident(_, Keyword::FROM_UNIXTIME) => Function::FromUnixTime,
1642        Token::Ident(_, Keyword::YEAR) => Function::Year,
1643        Token::Ident(_, Keyword::YEARWEEK) => Function::YearWeek,
1644        Token::Ident(_, Keyword::SYSDATE) => Function::SysDate,
1645
1646        // https://mariadb.com/kb/en/json-functions/
1647        Token::Ident(_, Keyword::JSON_ARRAY) => Function::JsonArray,
1648        Token::Ident(_, Keyword::JSON_ARRAYAGG) => Function::JsonArrayAgg,
1649        Token::Ident(_, Keyword::JSON_ARRAY_APPEND) => Function::JsonArrayAppend,
1650        Token::Ident(_, Keyword::JSON_ARRAY_INSERT) => Function::JsonArrayInsert,
1651        Token::Ident(_, Keyword::JSON_ARRAY_INTERSECT) => Function::JsonArrayIntersect,
1652        Token::Ident(_, Keyword::JSON_COMPACT) => Function::JsonCompact,
1653        Token::Ident(_, Keyword::JSON_CONTAINS) => Function::JsonContains,
1654        Token::Ident(_, Keyword::JSON_CONTAINS_PATH) => Function::JsonContainsPath,
1655        Token::Ident(_, Keyword::JSON_DEPTH) => Function::JsonDepth,
1656        Token::Ident(_, Keyword::JSON_DETAILED) => Function::JsonDetailed,
1657        Token::Ident(_, Keyword::JSON_EQUALS) => Function::JsonEquals,
1658        Token::Ident(_, Keyword::JSON_EXISTS) => Function::JsonExists,
1659        Token::Ident(_, Keyword::JSON_EXTRACT) => Function::JsonExtract,
1660        Token::Ident(_, Keyword::JSON_INSERT) => Function::JsonInsert,
1661        Token::Ident(_, Keyword::JSON_KEYS) => Function::JsonKeys,
1662        Token::Ident(_, Keyword::JSON_LENGTH) => Function::JsonLength,
1663        Token::Ident(_, Keyword::JSON_LOOSE) => Function::JsonLoose,
1664        Token::Ident(_, Keyword::JSON_MERGE) => Function::JsonMerge,
1665        Token::Ident(_, Keyword::JSON_MERGE_PATCH) => Function::JsonMergePath,
1666        Token::Ident(_, Keyword::JSON_MERGE_PRESERVE) => Function::JsonMergePerserve,
1667        Token::Ident(_, Keyword::JSON_NORMALIZE) => Function::JsonNormalize,
1668        Token::Ident(_, Keyword::JSON_OBJECT) => Function::JsonObject,
1669        Token::Ident(_, Keyword::JSON_OBJECT_FILTER_KEYS) => Function::JsonObjectFilterKeys,
1670        Token::Ident(_, Keyword::JSON_OBJECT_TO_ARRAY) => Function::JsonObjectToArray,
1671        Token::Ident(_, Keyword::JSON_OBJECTAGG) => Function::JsonObjectAgg,
1672        Token::Ident(_, Keyword::JSON_OVERLAPS) => Function::JsonOverlaps,
1673        Token::Ident(_, Keyword::JSON_PRETTY) => Function::JsonPretty,
1674        Token::Ident(_, Keyword::JSON_QUERY) => Function::JsonQuery,
1675        Token::Ident(_, Keyword::JSON_QUOTE) => Function::JsonQuote,
1676        Token::Ident(_, Keyword::JSON_REMOVE) => Function::JsonRemove,
1677        Token::Ident(_, Keyword::JSON_REPLACE) => Function::JsonReplace,
1678        Token::Ident(_, Keyword::JSON_SCHEMA_VALID) => Function::JsonSchemaValid,
1679        Token::Ident(_, Keyword::JSON_SEARCH) => Function::JsonSearch,
1680        Token::Ident(_, Keyword::JSON_SET) => Function::JsonSet,
1681        Token::Ident(_, Keyword::JSON_TABLE) => Function::JsonTable,
1682        Token::Ident(_, Keyword::JSON_TYPE) => Function::JsonType,
1683        Token::Ident(_, Keyword::JSON_UNQUOTE) => Function::JsonUnquote,
1684        Token::Ident(_, Keyword::JSON_VALID) => Function::JsonValid,
1685        Token::Ident(_, Keyword::JSON_VALUE) => Function::JsonValue,
1686
1687        // Sqlite
1688        Token::Ident(_, Keyword::STRFTIME) if parser.options.dialect.is_sqlite() => {
1689            Function::Strftime
1690        }
1691        Token::Ident(_, Keyword::DATETIME) if parser.options.dialect.is_sqlite() => {
1692            Function::Datetime
1693        }
1694
1695        // MySQL 8.4 encryption / compression
1696        Token::Ident(_, Keyword::AES_DECRYPT) if parser.options.dialect.is_maria() => {
1697            Function::AesDecrypt
1698        }
1699        Token::Ident(_, Keyword::AES_ENCRYPT) if parser.options.dialect.is_maria() => {
1700            Function::AesEncrypt
1701        }
1702        Token::Ident(_, Keyword::COMPRESS) if parser.options.dialect.is_maria() => {
1703            Function::Compress
1704        }
1705        Token::Ident(_, Keyword::MD5) if parser.options.dialect.is_maria() => Function::Md5,
1706        Token::Ident(_, Keyword::RANDOM_BYTES) if parser.options.dialect.is_maria() => {
1707            Function::RandomBytes
1708        }
1709        Token::Ident(_, Keyword::SHA) if parser.options.dialect.is_maria() => Function::Sha,
1710        Token::Ident(_, Keyword::SHA1) if parser.options.dialect.is_maria() => Function::Sha1,
1711        Token::Ident(_, Keyword::SHA2) if parser.options.dialect.is_maria() => Function::Sha2,
1712        Token::Ident(_, Keyword::STATEMENT_DIGEST) if parser.options.dialect.is_maria() => {
1713            Function::StatementDigest
1714        }
1715        Token::Ident(_, Keyword::STATEMENT_DIGEST_TEXT) if parser.options.dialect.is_maria() => {
1716            Function::StatementDigestText
1717        }
1718        Token::Ident(_, Keyword::UNCOMPRESS) if parser.options.dialect.is_maria() => {
1719            Function::Uncompress
1720        }
1721        Token::Ident(_, Keyword::VALIDATE_PASSWORD_STRENGTH)
1722            if parser.options.dialect.is_maria() =>
1723        {
1724            Function::ValidatePasswordStrength
1725        }
1726
1727        // MySQL 8.4 locking
1728        Token::Ident(_, Keyword::GET_LOCK) if parser.options.dialect.is_maria() => {
1729            Function::GetLock
1730        }
1731        Token::Ident(_, Keyword::IS_FREE_LOCK) if parser.options.dialect.is_maria() => {
1732            Function::IsFreeLock
1733        }
1734        Token::Ident(_, Keyword::IS_USED_LOCK) if parser.options.dialect.is_maria() => {
1735            Function::IsUsedLock
1736        }
1737        Token::Ident(_, Keyword::RELEASE_ALL_LOCKS) if parser.options.dialect.is_maria() => {
1738            Function::ReleaseAllLocks
1739        }
1740        Token::Ident(_, Keyword::RELEASE_LOCK) if parser.options.dialect.is_maria() => {
1741            Function::ReleaseLock
1742        }
1743
1744        // MySQL 8.4 information
1745        Token::Ident(_, Keyword::BENCHMARK) if parser.options.dialect.is_maria() => {
1746            Function::Benchmark
1747        }
1748        Token::Ident(_, Keyword::CHARSET) if parser.options.dialect.is_maria() => Function::Charset,
1749        Token::Ident(_, Keyword::COERCIBILITY) if parser.options.dialect.is_maria() => {
1750            Function::Coercibility
1751        }
1752        Token::Ident(_, Keyword::COLLATION) if parser.options.dialect.is_maria() => {
1753            Function::Collation
1754        }
1755        Token::Ident(_, Keyword::CONNECTION_ID) if parser.options.dialect.is_maria() => {
1756            Function::ConnectionId
1757        }
1758        Token::Ident(_, Keyword::CURRENT_ROLE) => Function::CurrentRole,
1759        Token::Ident(_, Keyword::CURRENT_USER) => Function::CurrentUser,
1760        Token::Ident(_, Keyword::DATABASE) if parser.options.dialect.is_maria() => {
1761            Function::DatabaseFunc
1762        }
1763        Token::Ident(_, Keyword::FOUND_ROWS) if parser.options.dialect.is_maria() => {
1764            Function::FoundRows
1765        }
1766        Token::Ident(_, Keyword::ICU_VERSION) if parser.options.dialect.is_maria() => {
1767            Function::IcuVersion
1768        }
1769        Token::Ident(_, Keyword::LAST_INSERT_ID) if parser.options.dialect.is_maria() => {
1770            Function::LastInsertId
1771        }
1772        Token::Ident(_, Keyword::ROLES_GRAPHML) if parser.options.dialect.is_maria() => {
1773            Function::RolesGraphml
1774        }
1775        Token::Ident(_, Keyword::ROW_COUNT) if parser.options.dialect.is_maria() => {
1776            Function::RowCount
1777        }
1778        Token::Ident(_, Keyword::SCHEMA) if parser.options.dialect.is_maria() => {
1779            Function::SchemaFunc
1780        }
1781        Token::Ident(_, Keyword::SESSION_USER) => Function::SessionUserFunc,
1782        Token::Ident(_, Keyword::SYSTEM_USER) if parser.options.dialect.is_maria() => {
1783            Function::SystemUser
1784        }
1785        Token::Ident(_, Keyword::USER) if parser.options.dialect.is_maria() => Function::UserFunc,
1786        Token::Ident(_, Keyword::VERSION) => Function::Version,
1787        // PostgreSQL system functions
1788        Token::Ident(_, Keyword::INET_SERVER_ADDR) if parser.options.dialect.is_postgresql() => {
1789            Function::InetServerAddr
1790        }
1791        Token::Ident(_, Keyword::INET_SERVER_PORT) if parser.options.dialect.is_postgresql() => {
1792            Function::InetServerPort
1793        }
1794        Token::Ident(_, Keyword::JSON_BUILD_OBJECT) if parser.options.dialect.is_postgresql() => {
1795            Function::JsonBuildObject
1796        }
1797        Token::Ident(_, Keyword::JSONB_SET) if parser.options.dialect.is_postgresql() => {
1798            Function::JsonbSet
1799        }
1800        Token::Ident(_, Keyword::PG_POSTMASTER_START_TIME)
1801            if parser.options.dialect.is_postgresql() =>
1802        {
1803            Function::PgPostmasterStartTime
1804        }
1805        Token::Ident(_, Keyword::POSTGIS_FULL_VERSION) if parser.options.dialect.is_postgis() => {
1806            Function::PostgisFullVersion
1807        }
1808        // PostgreSQL system information functions (9.27)
1809        Token::Ident(_, Keyword::COL_DESCRIPTION) if parser.options.dialect.is_postgresql() => {
1810            Function::ColDescription
1811        }
1812        Token::Ident(_, Keyword::CURRENT_DATABASE) if parser.options.dialect.is_postgresql() => {
1813            Function::CurrentDatabase
1814        }
1815        Token::Ident(_, Keyword::CURRENT_QUERY) if parser.options.dialect.is_postgresql() => {
1816            Function::CurrentQuery
1817        }
1818        Token::Ident(_, Keyword::CURRENT_SCHEMAS) if parser.options.dialect.is_postgresql() => {
1819            Function::CurrentSchemas
1820        }
1821        Token::Ident(_, Keyword::FORMAT_TYPE) if parser.options.dialect.is_postgresql() => {
1822            Function::FormatType
1823        }
1824        Token::Ident(_, Keyword::HAS_ANY_COLUMN_PRIVILEGE)
1825            if parser.options.dialect.is_postgresql() =>
1826        {
1827            Function::HasAnyColumnPrivilege
1828        }
1829        Token::Ident(_, Keyword::HAS_COLUMN_PRIVILEGE)
1830            if parser.options.dialect.is_postgresql() =>
1831        {
1832            Function::HasColumnPrivilege
1833        }
1834        Token::Ident(_, Keyword::HAS_DATABASE_PRIVILEGE)
1835            if parser.options.dialect.is_postgresql() =>
1836        {
1837            Function::HasDatabasePrivilege
1838        }
1839        Token::Ident(_, Keyword::HAS_FOREIGN_DATA_WRAPPER_PRIVILEGE)
1840            if parser.options.dialect.is_postgresql() =>
1841        {
1842            Function::HasForeignDataWrapperPrivilege
1843        }
1844        Token::Ident(_, Keyword::HAS_FUNCTION_PRIVILEGE)
1845            if parser.options.dialect.is_postgresql() =>
1846        {
1847            Function::HasFunctionPrivilege
1848        }
1849        Token::Ident(_, Keyword::HAS_LANGUAGE_PRIVILEGE)
1850            if parser.options.dialect.is_postgresql() =>
1851        {
1852            Function::HasLanguagePrivilege
1853        }
1854        Token::Ident(_, Keyword::HAS_LARGEOBJECT_PRIVILEGE)
1855            if parser.options.dialect.is_postgresql() =>
1856        {
1857            Function::HasLargeobjectPrivilege
1858        }
1859        Token::Ident(_, Keyword::HAS_PARAMETER_PRIVILEGE)
1860            if parser.options.dialect.is_postgresql() =>
1861        {
1862            Function::HasParameterPrivilege
1863        }
1864        Token::Ident(_, Keyword::HAS_SCHEMA_PRIVILEGE)
1865            if parser.options.dialect.is_postgresql() =>
1866        {
1867            Function::HasSchemaPrivilege
1868        }
1869        Token::Ident(_, Keyword::HAS_SEQUENCE_PRIVILEGE)
1870            if parser.options.dialect.is_postgresql() =>
1871        {
1872            Function::HasSequencePrivilege
1873        }
1874        Token::Ident(_, Keyword::HAS_SERVER_PRIVILEGE)
1875            if parser.options.dialect.is_postgresql() =>
1876        {
1877            Function::HasServerPrivilege
1878        }
1879        Token::Ident(_, Keyword::HAS_TABLE_PRIVILEGE) if parser.options.dialect.is_postgresql() => {
1880            Function::HasTablePrivilege
1881        }
1882        Token::Ident(_, Keyword::HAS_TABLESPACE_PRIVILEGE)
1883            if parser.options.dialect.is_postgresql() =>
1884        {
1885            Function::HasTablespacePrivilege
1886        }
1887        Token::Ident(_, Keyword::HAS_TYPE_PRIVILEGE) if parser.options.dialect.is_postgresql() => {
1888            Function::HasTypePrivilege
1889        }
1890        Token::Ident(_, Keyword::ICU_UNICODE_VERSION) if parser.options.dialect.is_postgresql() => {
1891            Function::IcuUnicodeVersion
1892        }
1893        Token::Ident(_, Keyword::INET_CLIENT_ADDR) if parser.options.dialect.is_postgresql() => {
1894            Function::InetClientAddr
1895        }
1896        Token::Ident(_, Keyword::INET_CLIENT_PORT) if parser.options.dialect.is_postgresql() => {
1897            Function::InetClientPort
1898        }
1899        Token::Ident(_, Keyword::MAKEACLITEM) if parser.options.dialect.is_postgresql() => {
1900            Function::Makeaclitem
1901        }
1902        Token::Ident(_, Keyword::MXID_AGE) if parser.options.dialect.is_postgresql() => {
1903            Function::MxidAge
1904        }
1905        Token::Ident(_, Keyword::OBJ_DESCRIPTION) if parser.options.dialect.is_postgresql() => {
1906            Function::ObjDescription
1907        }
1908        Token::Ident(_, Keyword::PG_AVAILABLE_WAL_SUMMARIES)
1909            if parser.options.dialect.is_postgresql() =>
1910        {
1911            Function::PgAvailableWalSummaries
1912        }
1913        Token::Ident(_, Keyword::PG_BACKEND_PID) if parser.options.dialect.is_postgresql() => {
1914            Function::PgBackendPid
1915        }
1916        Token::Ident(_, Keyword::PG_BLOCKING_PIDS) if parser.options.dialect.is_postgresql() => {
1917            Function::PgBlockingPids
1918        }
1919        Token::Ident(_, Keyword::PG_CHAR_TO_ENCODING) if parser.options.dialect.is_postgresql() => {
1920            Function::PgCharToEncoding
1921        }
1922        Token::Ident(_, Keyword::PG_COLLATION_IS_VISIBLE)
1923            if parser.options.dialect.is_postgresql() =>
1924        {
1925            Function::PgCollationIsVisible
1926        }
1927        Token::Ident(_, Keyword::PG_CONF_LOAD_TIME) if parser.options.dialect.is_postgresql() => {
1928            Function::PgConfLoadTime
1929        }
1930        Token::Ident(_, Keyword::PG_CONTROL_CHECKPOINT)
1931            if parser.options.dialect.is_postgresql() =>
1932        {
1933            Function::PgControlCheckpoint
1934        }
1935        Token::Ident(_, Keyword::PG_CONTROL_INIT) if parser.options.dialect.is_postgresql() => {
1936            Function::PgControlInit
1937        }
1938        Token::Ident(_, Keyword::PG_CONTROL_RECOVERY) if parser.options.dialect.is_postgresql() => {
1939            Function::PgControlRecovery
1940        }
1941        Token::Ident(_, Keyword::PG_CONTROL_SYSTEM) if parser.options.dialect.is_postgresql() => {
1942            Function::PgControlSystem
1943        }
1944        Token::Ident(_, Keyword::PG_CONVERSION_IS_VISIBLE)
1945            if parser.options.dialect.is_postgresql() =>
1946        {
1947            Function::PgConversionIsVisible
1948        }
1949        Token::Ident(_, Keyword::PG_CURRENT_LOGFILE) if parser.options.dialect.is_postgresql() => {
1950            Function::PgCurrentLogfile
1951        }
1952        Token::Ident(_, Keyword::PG_CURRENT_SNAPSHOT) if parser.options.dialect.is_postgresql() => {
1953            Function::PgCurrentSnapshot
1954        }
1955        Token::Ident(_, Keyword::PG_CURRENT_XACT_ID) if parser.options.dialect.is_postgresql() => {
1956            Function::PgCurrentXactId
1957        }
1958        Token::Ident(_, Keyword::PG_CURRENT_XACT_ID_IF_ASSIGNED)
1959            if parser.options.dialect.is_postgresql() =>
1960        {
1961            Function::PgCurrentXactIdIfAssigned
1962        }
1963        Token::Ident(_, Keyword::PG_DESCRIBE_OBJECT) if parser.options.dialect.is_postgresql() => {
1964            Function::PgDescribeObject
1965        }
1966        Token::Ident(_, Keyword::PG_ENCODING_TO_CHAR) if parser.options.dialect.is_postgresql() => {
1967            Function::PgEncodingToChar
1968        }
1969        Token::Ident(_, Keyword::PG_FUNCTION_IS_VISIBLE)
1970            if parser.options.dialect.is_postgresql() =>
1971        {
1972            Function::PgFunctionIsVisible
1973        }
1974        Token::Ident(_, Keyword::PG_GET_ACL) if parser.options.dialect.is_postgresql() => {
1975            Function::PgGetAcl
1976        }
1977        Token::Ident(_, Keyword::PG_GET_CONSTRAINTDEF)
1978            if parser.options.dialect.is_postgresql() =>
1979        {
1980            Function::PgGetConstraintdef
1981        }
1982        Token::Ident(_, Keyword::PG_GET_EXPR) if parser.options.dialect.is_postgresql() => {
1983            Function::PgGetExpr
1984        }
1985        Token::Ident(_, Keyword::PG_GET_FUNCTIONDEF) if parser.options.dialect.is_postgresql() => {
1986            Function::PgGetFunctiondef
1987        }
1988        Token::Ident(_, Keyword::PG_GET_FUNCTION_ARGUMENTS)
1989            if parser.options.dialect.is_postgresql() =>
1990        {
1991            Function::PgGetFunctionArguments
1992        }
1993        Token::Ident(_, Keyword::PG_GET_FUNCTION_IDENTITY_ARGUMENTS)
1994            if parser.options.dialect.is_postgresql() =>
1995        {
1996            Function::PgGetFunctionIdentityArguments
1997        }
1998        Token::Ident(_, Keyword::PG_GET_FUNCTION_RESULT)
1999            if parser.options.dialect.is_postgresql() =>
2000        {
2001            Function::PgGetFunctionResult
2002        }
2003        Token::Ident(_, Keyword::PG_GET_INDEXDEF) if parser.options.dialect.is_postgresql() => {
2004            Function::PgGetIndexdef
2005        }
2006        Token::Ident(_, Keyword::PG_GET_OBJECT_ADDRESS)
2007            if parser.options.dialect.is_postgresql() =>
2008        {
2009            Function::PgGetObjectAddress
2010        }
2011        Token::Ident(_, Keyword::PG_GET_PARTITION_CONSTRAINTDEF)
2012            if parser.options.dialect.is_postgresql() =>
2013        {
2014            Function::PgGetPartitionConstraintdef
2015        }
2016        Token::Ident(_, Keyword::PG_GET_PARTKEYDEF) if parser.options.dialect.is_postgresql() => {
2017            Function::PgGetPartkeydef
2018        }
2019        Token::Ident(_, Keyword::PG_GET_RULEDEF) if parser.options.dialect.is_postgresql() => {
2020            Function::PgGetRuledef
2021        }
2022        Token::Ident(_, Keyword::PG_GET_SERIAL_SEQUENCE)
2023            if parser.options.dialect.is_postgresql() =>
2024        {
2025            Function::PgGetSerialSequence
2026        }
2027        Token::Ident(_, Keyword::PG_GET_STATISTICSOBJDEF)
2028            if parser.options.dialect.is_postgresql() =>
2029        {
2030            Function::PgGetStatisticsobjdef
2031        }
2032        Token::Ident(_, Keyword::PG_GET_TRIGGERDEF) if parser.options.dialect.is_postgresql() => {
2033            Function::PgGetTriggerdef
2034        }
2035        Token::Ident(_, Keyword::PG_GET_USERBYID) if parser.options.dialect.is_postgresql() => {
2036            Function::PgGetUserbyid
2037        }
2038        Token::Ident(_, Keyword::PG_GET_VIEWDEF) if parser.options.dialect.is_postgresql() => {
2039            Function::PgGetViewdef
2040        }
2041        Token::Ident(_, Keyword::PG_GET_WAL_SUMMARIZER_STATE)
2042            if parser.options.dialect.is_postgresql() =>
2043        {
2044            Function::PgGetWalSummarizerState
2045        }
2046        Token::Ident(_, Keyword::PG_HAS_ROLE) if parser.options.dialect.is_postgresql() => {
2047            Function::PgHasRole
2048        }
2049        Token::Ident(_, Keyword::PG_INDEX_COLUMN_HAS_PROPERTY)
2050            if parser.options.dialect.is_postgresql() =>
2051        {
2052            Function::PgIndexColumnHasProperty
2053        }
2054        Token::Ident(_, Keyword::PG_INDEX_HAS_PROPERTY)
2055            if parser.options.dialect.is_postgresql() =>
2056        {
2057            Function::PgIndexHasProperty
2058        }
2059        Token::Ident(_, Keyword::PG_INDEXAM_HAS_PROPERTY)
2060            if parser.options.dialect.is_postgresql() =>
2061        {
2062            Function::PgIndexamHasProperty
2063        }
2064        Token::Ident(_, Keyword::PG_INPUT_ERROR_INFO) if parser.options.dialect.is_postgresql() => {
2065            Function::PgInputErrorInfo
2066        }
2067        Token::Ident(_, Keyword::PG_INPUT_IS_VALID) if parser.options.dialect.is_postgresql() => {
2068            Function::PgInputIsValid
2069        }
2070        Token::Ident(_, Keyword::PG_IS_OTHER_TEMP_SCHEMA)
2071            if parser.options.dialect.is_postgresql() =>
2072        {
2073            Function::PgIsOtherTempSchema
2074        }
2075        Token::Ident(_, Keyword::PG_JIT_AVAILABLE) if parser.options.dialect.is_postgresql() => {
2076            Function::PgJitAvailable
2077        }
2078        Token::Ident(_, Keyword::PG_LAST_COMMITTED_XACT)
2079            if parser.options.dialect.is_postgresql() =>
2080        {
2081            Function::PgLastCommittedXact
2082        }
2083        Token::Ident(_, Keyword::PG_LISTENING_CHANNELS)
2084            if parser.options.dialect.is_postgresql() =>
2085        {
2086            Function::PgListeningChannels
2087        }
2088        Token::Ident(_, Keyword::PG_MY_TEMP_SCHEMA) if parser.options.dialect.is_postgresql() => {
2089            Function::PgMyTempSchema
2090        }
2091        Token::Ident(_, Keyword::PG_NOTIFICATION_QUEUE_USAGE)
2092            if parser.options.dialect.is_postgresql() =>
2093        {
2094            Function::PgNotificationQueueUsage
2095        }
2096        Token::Ident(_, Keyword::PG_OPCLASS_IS_VISIBLE)
2097            if parser.options.dialect.is_postgresql() =>
2098        {
2099            Function::PgOpclassIsVisible
2100        }
2101        Token::Ident(_, Keyword::PG_OPERATOR_IS_VISIBLE)
2102            if parser.options.dialect.is_postgresql() =>
2103        {
2104            Function::PgOperatorIsVisible
2105        }
2106        Token::Ident(_, Keyword::PG_OPFAMILY_IS_VISIBLE)
2107            if parser.options.dialect.is_postgresql() =>
2108        {
2109            Function::PgOpfamilyIsVisible
2110        }
2111        Token::Ident(_, Keyword::PG_SAFE_SNAPSHOT_BLOCKING_PIDS)
2112            if parser.options.dialect.is_postgresql() =>
2113        {
2114            Function::PgSafeSnapshotBlockingPids
2115        }
2116        Token::Ident(_, Keyword::PG_SETTINGS_GET_FLAGS)
2117            if parser.options.dialect.is_postgresql() =>
2118        {
2119            Function::PgSettingsGetFlags
2120        }
2121        Token::Ident(_, Keyword::PG_SNAPSHOT_XIP) if parser.options.dialect.is_postgresql() => {
2122            Function::PgSnapshotXip
2123        }
2124        Token::Ident(_, Keyword::PG_SNAPSHOT_XMAX) if parser.options.dialect.is_postgresql() => {
2125            Function::PgSnapshotXmax
2126        }
2127        Token::Ident(_, Keyword::PG_SNAPSHOT_XMIN) if parser.options.dialect.is_postgresql() => {
2128            Function::PgSnapshotXmin
2129        }
2130        Token::Ident(_, Keyword::PG_STATISTICS_OBJ_IS_VISIBLE)
2131            if parser.options.dialect.is_postgresql() =>
2132        {
2133            Function::PgStatisticsObjIsVisible
2134        }
2135        Token::Ident(_, Keyword::PG_TABLE_IS_VISIBLE) if parser.options.dialect.is_postgresql() => {
2136            Function::PgTableIsVisible
2137        }
2138        Token::Ident(_, Keyword::PG_TABLESPACE_LOCATION)
2139            if parser.options.dialect.is_postgresql() =>
2140        {
2141            Function::PgTablespaceLocation
2142        }
2143        Token::Ident(_, Keyword::PG_TRIGGER_DEPTH) if parser.options.dialect.is_postgresql() => {
2144            Function::PgTriggerDepth
2145        }
2146        Token::Ident(_, Keyword::PG_TS_CONFIG_IS_VISIBLE)
2147            if parser.options.dialect.is_postgresql() =>
2148        {
2149            Function::PgTsConfigIsVisible
2150        }
2151        Token::Ident(_, Keyword::PG_TS_DICT_IS_VISIBLE)
2152            if parser.options.dialect.is_postgresql() =>
2153        {
2154            Function::PgTsDictIsVisible
2155        }
2156        Token::Ident(_, Keyword::PG_TS_PARSER_IS_VISIBLE)
2157            if parser.options.dialect.is_postgresql() =>
2158        {
2159            Function::PgTsParserIsVisible
2160        }
2161        Token::Ident(_, Keyword::PG_TS_TEMPLATE_IS_VISIBLE)
2162            if parser.options.dialect.is_postgresql() =>
2163        {
2164            Function::PgTsTemplateIsVisible
2165        }
2166        Token::Ident(_, Keyword::PG_TYPE_IS_VISIBLE) if parser.options.dialect.is_postgresql() => {
2167            Function::PgTypeIsVisible
2168        }
2169        Token::Ident(_, Keyword::PG_TYPEOF) if parser.options.dialect.is_postgresql() => {
2170            Function::PgTypeof
2171        }
2172        Token::Ident(_, Keyword::PG_VISIBLE_IN_SNAPSHOT)
2173            if parser.options.dialect.is_postgresql() =>
2174        {
2175            Function::PgVisibleInSnapshot
2176        }
2177        Token::Ident(_, Keyword::PG_XACT_COMMIT_TIMESTAMP)
2178            if parser.options.dialect.is_postgresql() =>
2179        {
2180            Function::PgXactCommitTimestamp
2181        }
2182        Token::Ident(_, Keyword::PG_XACT_STATUS) if parser.options.dialect.is_postgresql() => {
2183            Function::PgXactStatus
2184        }
2185        Token::Ident(_, Keyword::ROW_SECURITY_ACTIVE) if parser.options.dialect.is_postgresql() => {
2186            Function::RowSecurityActive
2187        }
2188        Token::Ident(_, Keyword::SHOBJ_DESCRIPTION) if parser.options.dialect.is_postgresql() => {
2189            Function::ShobjDescription
2190        }
2191        Token::Ident(_, Keyword::TO_REGCLASS) if parser.options.dialect.is_postgresql() => {
2192            Function::ToRegclass
2193        }
2194        Token::Ident(_, Keyword::TO_REGCOLLATION) if parser.options.dialect.is_postgresql() => {
2195            Function::ToRegcollation
2196        }
2197        Token::Ident(_, Keyword::TO_REGNAMESPACE) if parser.options.dialect.is_postgresql() => {
2198            Function::ToRegnamespace
2199        }
2200        Token::Ident(_, Keyword::TO_REGOPER) if parser.options.dialect.is_postgresql() => {
2201            Function::ToRegoper
2202        }
2203        Token::Ident(_, Keyword::TO_REGOPERATOR) if parser.options.dialect.is_postgresql() => {
2204            Function::ToRegoperator
2205        }
2206        Token::Ident(_, Keyword::TO_REGPROC) if parser.options.dialect.is_postgresql() => {
2207            Function::ToRegproc
2208        }
2209        Token::Ident(_, Keyword::TO_REGPROCEDURE) if parser.options.dialect.is_postgresql() => {
2210            Function::ToRegprocedure
2211        }
2212        Token::Ident(_, Keyword::TO_REGROLE) if parser.options.dialect.is_postgresql() => {
2213            Function::ToRegrole
2214        }
2215        Token::Ident(_, Keyword::TO_REGTYPE) if parser.options.dialect.is_postgresql() => {
2216            Function::ToRegtype
2217        }
2218        Token::Ident(_, Keyword::TO_REGTYPEMOD) if parser.options.dialect.is_postgresql() => {
2219            Function::ToRegtypemod
2220        }
2221        Token::Ident(_, Keyword::UNICODE_VERSION) if parser.options.dialect.is_postgresql() => {
2222            Function::UnicodeVersion
2223        }
2224
2225        // PostgreSQL network address functions
2226        Token::Ident(_, Keyword::ABBREV) if parser.options.dialect.is_postgresql() => {
2227            Function::Abbrev
2228        }
2229        Token::Ident(_, Keyword::BROADCAST) if parser.options.dialect.is_postgresql() => {
2230            Function::Broadcast
2231        }
2232        Token::Ident(_, Keyword::FAMILY) if parser.options.dialect.is_postgresql() => {
2233            Function::Family
2234        }
2235        Token::Ident(_, Keyword::HOST) if parser.options.dialect.is_postgresql() => Function::Host,
2236        Token::Ident(_, Keyword::HOSTMASK) if parser.options.dialect.is_postgresql() => {
2237            Function::HostMask
2238        }
2239        Token::Ident(_, Keyword::INET_MERGE) if parser.options.dialect.is_postgresql() => {
2240            Function::InetMerge
2241        }
2242        Token::Ident(_, Keyword::INET_SAME_FAMILY) if parser.options.dialect.is_postgresql() => {
2243            Function::InetSameFamily
2244        }
2245        Token::Ident(_, Keyword::MACADDR8_SET7BIT) if parser.options.dialect.is_postgresql() => {
2246            Function::Macaddr8Set7bit
2247        }
2248        Token::Ident(_, Keyword::MASKLEN) if parser.options.dialect.is_postgresql() => {
2249            Function::MaskLen
2250        }
2251        Token::Ident(_, Keyword::NETMASK) if parser.options.dialect.is_postgresql() => {
2252            Function::NetMask
2253        }
2254        Token::Ident(_, Keyword::NETWORK) if parser.options.dialect.is_postgresql() => {
2255            Function::Network
2256        }
2257        Token::Ident(_, Keyword::SET_MASKLEN) if parser.options.dialect.is_postgresql() => {
2258            Function::SetMaskLen
2259        }
2260
2261        // PostgreSQL UUID functions
2262        Token::Ident(_, Keyword::GEN_RANDOM_UUID) if parser.options.dialect.is_postgresql() => {
2263            Function::GenRandomUuid
2264        }
2265        Token::Ident(_, Keyword::UUID_EXTRACT_TIMESTAMP)
2266            if parser.options.dialect.is_postgresql() =>
2267        {
2268            Function::UuidExtractTimestamp
2269        }
2270        Token::Ident(_, Keyword::UUID_EXTRACT_VERSION)
2271            if parser.options.dialect.is_postgresql() =>
2272        {
2273            Function::UuidExtractVersion
2274        }
2275        Token::Ident(_, Keyword::UUIDV4) if parser.options.dialect.is_postgresql() => {
2276            Function::Uuidv4
2277        }
2278        Token::Ident(_, Keyword::UUIDV7) if parser.options.dialect.is_postgresql() => {
2279            Function::Uuidv7
2280        }
2281
2282        // PostgreSQL XML functions
2283        Token::Ident(_, Keyword::CURSOR_TO_XML) if parser.options.dialect.is_postgresql() => {
2284            Function::CursorToXml
2285        }
2286        Token::Ident(_, Keyword::CURSOR_TO_XMLSCHEMA) if parser.options.dialect.is_postgresql() => {
2287            Function::CursorToXmlschema
2288        }
2289        Token::Ident(_, Keyword::DATABASE_TO_XML) if parser.options.dialect.is_postgresql() => {
2290            Function::DatabaseToXml
2291        }
2292        Token::Ident(_, Keyword::DATABASE_TO_XML_AND_XMLSCHEMA)
2293            if parser.options.dialect.is_postgresql() =>
2294        {
2295            Function::DatabaseToXmlAndXmlschema
2296        }
2297        Token::Ident(_, Keyword::DATABASE_TO_XMLSCHEMA)
2298            if parser.options.dialect.is_postgresql() =>
2299        {
2300            Function::DatabaseToXmlschema
2301        }
2302        Token::Ident(_, Keyword::QUERY_TO_XML) if parser.options.dialect.is_postgresql() => {
2303            Function::QueryToXml
2304        }
2305        Token::Ident(_, Keyword::QUERY_TO_XML_AND_XMLSCHEMA)
2306            if parser.options.dialect.is_postgresql() =>
2307        {
2308            Function::QueryToXmlAndXmlschema
2309        }
2310        Token::Ident(_, Keyword::QUERY_TO_XMLSCHEMA) if parser.options.dialect.is_postgresql() => {
2311            Function::QueryToXmlschema
2312        }
2313        Token::Ident(_, Keyword::SCHEMA_TO_XML) if parser.options.dialect.is_postgresql() => {
2314            Function::SchemaToXml
2315        }
2316        Token::Ident(_, Keyword::SCHEMA_TO_XML_AND_XMLSCHEMA)
2317            if parser.options.dialect.is_postgresql() =>
2318        {
2319            Function::SchemaToXmlAndXmlschema
2320        }
2321        Token::Ident(_, Keyword::SCHEMA_TO_XMLSCHEMA) if parser.options.dialect.is_postgresql() => {
2322            Function::SchemaToXmlschema
2323        }
2324        Token::Ident(_, Keyword::TABLE_TO_XML) if parser.options.dialect.is_postgresql() => {
2325            Function::TableToXml
2326        }
2327        Token::Ident(_, Keyword::TABLE_TO_XML_AND_XMLSCHEMA)
2328            if parser.options.dialect.is_postgresql() =>
2329        {
2330            Function::TableToXmlAndXmlschema
2331        }
2332        Token::Ident(_, Keyword::TABLE_TO_XMLSCHEMA) if parser.options.dialect.is_postgresql() => {
2333            Function::TableToXmlschema
2334        }
2335        Token::Ident(_, Keyword::XML_IS_WELL_FORMED) if parser.options.dialect.is_postgresql() => {
2336            Function::XmlIsWellFormed
2337        }
2338        Token::Ident(_, Keyword::XML_IS_WELL_FORMED_CONTENT)
2339            if parser.options.dialect.is_postgresql() =>
2340        {
2341            Function::XmlIsWellFormedContent
2342        }
2343        Token::Ident(_, Keyword::XML_IS_WELL_FORMED_DOCUMENT)
2344            if parser.options.dialect.is_postgresql() =>
2345        {
2346            Function::XmlIsWellFormedDocument
2347        }
2348        Token::Ident(_, Keyword::XMLCOMMENT) if parser.options.dialect.is_postgresql() => {
2349            Function::XmlComment
2350        }
2351        Token::Ident(_, Keyword::XMLCONCAT) if parser.options.dialect.is_postgresql() => {
2352            Function::XmlConcat
2353        }
2354        Token::Ident(_, Keyword::XMLTEXT) if parser.options.dialect.is_postgresql() => {
2355            Function::XmlText
2356        }
2357        Token::Ident(_, Keyword::XPATH) if parser.options.dialect.is_postgresql() => {
2358            Function::Xpath
2359        }
2360        Token::Ident(_, Keyword::XPATH_EXISTS) if parser.options.dialect.is_postgresql() => {
2361            Function::XpathExists
2362        }
2363
2364        // PostgreSQL JSON functions
2365        Token::Ident(_, Keyword::ARRAY_TO_JSON) if parser.options.dialect.is_postgresql() => {
2366            Function::ArrayToJson
2367        }
2368        Token::Ident(_, Keyword::JSON_ARRAY_ELEMENTS) if parser.options.dialect.is_postgresql() => {
2369            Function::JsonArrayElements
2370        }
2371        Token::Ident(_, Keyword::JSON_ARRAY_ELEMENTS_TEXT)
2372            if parser.options.dialect.is_postgresql() =>
2373        {
2374            Function::JsonArrayElementsText
2375        }
2376        Token::Ident(_, Keyword::JSON_ARRAY_LENGTH) if parser.options.dialect.is_postgresql() => {
2377            Function::JsonArrayLength
2378        }
2379        Token::Ident(_, Keyword::JSON_BUILD_ARRAY) if parser.options.dialect.is_postgresql() => {
2380            Function::JsonBuildArray
2381        }
2382        Token::Ident(_, Keyword::JSON_EACH) if parser.options.dialect.is_postgresql() => {
2383            Function::JsonEach
2384        }
2385        Token::Ident(_, Keyword::JSON_EACH_TEXT) if parser.options.dialect.is_postgresql() => {
2386            Function::JsonEachText
2387        }
2388        Token::Ident(_, Keyword::JSON_EXTRACT_PATH) if parser.options.dialect.is_postgresql() => {
2389            Function::JsonExtractPath
2390        }
2391        Token::Ident(_, Keyword::JSON_EXTRACT_PATH_TEXT)
2392            if parser.options.dialect.is_postgresql() =>
2393        {
2394            Function::JsonExtractPathText
2395        }
2396        Token::Ident(_, Keyword::JSON_OBJECT_KEYS) if parser.options.dialect.is_postgresql() => {
2397            Function::JsonObjectKeys
2398        }
2399        Token::Ident(_, Keyword::JSON_POPULATE_RECORD)
2400            if parser.options.dialect.is_postgresql() =>
2401        {
2402            Function::JsonPopulateRecord
2403        }
2404        Token::Ident(_, Keyword::JSON_POPULATE_RECORDSET)
2405            if parser.options.dialect.is_postgresql() =>
2406        {
2407            Function::JsonPopulateRecordset
2408        }
2409        Token::Ident(_, Keyword::JSON_SCALAR) if parser.options.dialect.is_postgresql() => {
2410            Function::JsonScalar
2411        }
2412        Token::Ident(_, Keyword::JSON_SERIALIZE) if parser.options.dialect.is_postgresql() => {
2413            Function::JsonSerialize
2414        }
2415        Token::Ident(_, Keyword::JSON_STRIP_NULLS) if parser.options.dialect.is_postgresql() => {
2416            Function::JsonStripNulls
2417        }
2418        Token::Ident(_, Keyword::JSON_TO_RECORD) if parser.options.dialect.is_postgresql() => {
2419            Function::JsonToRecord
2420        }
2421        Token::Ident(_, Keyword::JSON_TO_RECORDSET) if parser.options.dialect.is_postgresql() => {
2422            Function::JsonToRecordset
2423        }
2424        Token::Ident(_, Keyword::JSON_TYPEOF) if parser.options.dialect.is_postgresql() => {
2425            Function::JsonTypeof
2426        }
2427        Token::Ident(_, Keyword::JSONB_ARRAY_ELEMENTS)
2428            if parser.options.dialect.is_postgresql() =>
2429        {
2430            Function::JsonbArrayElements
2431        }
2432        Token::Ident(_, Keyword::JSONB_ARRAY_ELEMENTS_TEXT)
2433            if parser.options.dialect.is_postgresql() =>
2434        {
2435            Function::JsonbArrayElementsText
2436        }
2437        Token::Ident(_, Keyword::JSONB_ARRAY_LENGTH) if parser.options.dialect.is_postgresql() => {
2438            Function::JsonbArrayLength
2439        }
2440        Token::Ident(_, Keyword::JSONB_BUILD_ARRAY) if parser.options.dialect.is_postgresql() => {
2441            Function::JsonbBuildArray
2442        }
2443        Token::Ident(_, Keyword::JSONB_BUILD_OBJECT) if parser.options.dialect.is_postgresql() => {
2444            Function::JsonbBuildObject
2445        }
2446        Token::Ident(_, Keyword::JSONB_EACH) if parser.options.dialect.is_postgresql() => {
2447            Function::JsonbEach
2448        }
2449        Token::Ident(_, Keyword::JSONB_EACH_TEXT) if parser.options.dialect.is_postgresql() => {
2450            Function::JsonbEachText
2451        }
2452        Token::Ident(_, Keyword::JSONB_EXTRACT_PATH) if parser.options.dialect.is_postgresql() => {
2453            Function::JsonbExtractPath
2454        }
2455        Token::Ident(_, Keyword::JSONB_EXTRACT_PATH_TEXT)
2456            if parser.options.dialect.is_postgresql() =>
2457        {
2458            Function::JsonbExtractPathText
2459        }
2460        Token::Ident(_, Keyword::JSONB_INSERT) if parser.options.dialect.is_postgresql() => {
2461            Function::JsonbInsert
2462        }
2463        Token::Ident(_, Keyword::JSONB_OBJECT) if parser.options.dialect.is_postgresql() => {
2464            Function::JsonbObject
2465        }
2466        Token::Ident(_, Keyword::JSONB_OBJECT_KEYS) if parser.options.dialect.is_postgresql() => {
2467            Function::JsonbObjectKeys
2468        }
2469        Token::Ident(_, Keyword::JSONB_PATH_EXISTS) if parser.options.dialect.is_postgresql() => {
2470            Function::JsonbPathExists
2471        }
2472        Token::Ident(_, Keyword::JSONB_PATH_EXISTS_TZ)
2473            if parser.options.dialect.is_postgresql() =>
2474        {
2475            Function::JsonbPathExistsTz
2476        }
2477        Token::Ident(_, Keyword::JSONB_PATH_MATCH) if parser.options.dialect.is_postgresql() => {
2478            Function::JsonbPathMatch
2479        }
2480        Token::Ident(_, Keyword::JSONB_PATH_MATCH_TZ) if parser.options.dialect.is_postgresql() => {
2481            Function::JsonbPathMatchTz
2482        }
2483        Token::Ident(_, Keyword::JSONB_PATH_QUERY) if parser.options.dialect.is_postgresql() => {
2484            Function::JsonbPathQuery
2485        }
2486        Token::Ident(_, Keyword::JSONB_PATH_QUERY_ARRAY)
2487            if parser.options.dialect.is_postgresql() =>
2488        {
2489            Function::JsonbPathQueryArray
2490        }
2491        Token::Ident(_, Keyword::JSONB_PATH_QUERY_ARRAY_TZ)
2492            if parser.options.dialect.is_postgresql() =>
2493        {
2494            Function::JsonbPathQueryArrayTz
2495        }
2496        Token::Ident(_, Keyword::JSONB_PATH_QUERY_FIRST)
2497            if parser.options.dialect.is_postgresql() =>
2498        {
2499            Function::JsonbPathQueryFirst
2500        }
2501        Token::Ident(_, Keyword::JSONB_PATH_QUERY_FIRST_TZ)
2502            if parser.options.dialect.is_postgresql() =>
2503        {
2504            Function::JsonbPathQueryFirstTz
2505        }
2506        Token::Ident(_, Keyword::JSONB_PATH_QUERY_TZ) if parser.options.dialect.is_postgresql() => {
2507            Function::JsonbPathQueryTz
2508        }
2509        Token::Ident(_, Keyword::JSONB_POPULATE_RECORD)
2510            if parser.options.dialect.is_postgresql() =>
2511        {
2512            Function::JsonbPopulateRecord
2513        }
2514        Token::Ident(_, Keyword::JSONB_POPULATE_RECORD_VALID)
2515            if parser.options.dialect.is_postgresql() =>
2516        {
2517            Function::JsonbPopulateRecordValid
2518        }
2519        Token::Ident(_, Keyword::JSONB_POPULATE_RECORDSET)
2520            if parser.options.dialect.is_postgresql() =>
2521        {
2522            Function::JsonbPopulateRecordset
2523        }
2524        Token::Ident(_, Keyword::JSONB_PRETTY) if parser.options.dialect.is_postgresql() => {
2525            Function::JsonbPretty
2526        }
2527        Token::Ident(_, Keyword::JSONB_SET_LAX) if parser.options.dialect.is_postgresql() => {
2528            Function::JsonbSetLax
2529        }
2530        Token::Ident(_, Keyword::JSONB_STRIP_NULLS) if parser.options.dialect.is_postgresql() => {
2531            Function::JsonbStripNulls
2532        }
2533        Token::Ident(_, Keyword::JSONB_TO_RECORD) if parser.options.dialect.is_postgresql() => {
2534            Function::JsonbToRecord
2535        }
2536        Token::Ident(_, Keyword::JSONB_TO_RECORDSET) if parser.options.dialect.is_postgresql() => {
2537            Function::JsonbToRecordset
2538        }
2539        Token::Ident(_, Keyword::JSONB_TYPEOF) if parser.options.dialect.is_postgresql() => {
2540            Function::JsonbTypeof
2541        }
2542        Token::Ident(_, Keyword::ROW_TO_JSON) if parser.options.dialect.is_postgresql() => {
2543            Function::RowToJson
2544        }
2545        Token::Ident(_, Keyword::TO_JSON) if parser.options.dialect.is_postgresql() => {
2546            Function::ToJson
2547        }
2548        Token::Ident(_, Keyword::TO_JSONB) if parser.options.dialect.is_postgresql() => {
2549            Function::ToJsonb
2550        }
2551
2552        // PostgreSQL sequence functions
2553        Token::Ident(_, Keyword::CURRVAL) if parser.options.dialect.is_postgresql() => {
2554            Function::Currval
2555        }
2556        Token::Ident(_, Keyword::LASTVAL) if parser.options.dialect.is_postgresql() => {
2557            Function::Lastval
2558        }
2559        Token::Ident(_, Keyword::NEXTVAL) if parser.options.dialect.is_postgresql() => {
2560            Function::Nextval
2561        }
2562        Token::Ident(_, Keyword::SETVAL) if parser.options.dialect.is_postgresql() => {
2563            Function::Setval
2564        }
2565
2566        // PostgreSQL array functions
2567        Token::Ident(_, Keyword::ARRAY_APPEND) if parser.options.dialect.is_postgresql() => {
2568            Function::ArrayAppend
2569        }
2570        Token::Ident(_, Keyword::ARRAY_CAT) if parser.options.dialect.is_postgresql() => {
2571            Function::ArrayCat
2572        }
2573        Token::Ident(_, Keyword::ARRAY_DIMS) if parser.options.dialect.is_postgresql() => {
2574            Function::ArrayDims
2575        }
2576        Token::Ident(_, Keyword::ARRAY_FILL) if parser.options.dialect.is_postgresql() => {
2577            Function::ArrayFill
2578        }
2579        Token::Ident(_, Keyword::ARRAY_LENGTH) if parser.options.dialect.is_postgresql() => {
2580            Function::ArrayLength
2581        }
2582        Token::Ident(_, Keyword::ARRAY_LOWER) if parser.options.dialect.is_postgresql() => {
2583            Function::ArrayLower
2584        }
2585        Token::Ident(_, Keyword::ARRAY_NDIMS) if parser.options.dialect.is_postgresql() => {
2586            Function::ArrayNdims
2587        }
2588        Token::Ident(_, Keyword::ARRAY_POSITION) if parser.options.dialect.is_postgresql() => {
2589            Function::ArrayPosition
2590        }
2591        Token::Ident(_, Keyword::ARRAY_POSITIONS) if parser.options.dialect.is_postgresql() => {
2592            Function::ArrayPositions
2593        }
2594        Token::Ident(_, Keyword::ARRAY_PREPEND) if parser.options.dialect.is_postgresql() => {
2595            Function::ArrayPrepend
2596        }
2597        Token::Ident(_, Keyword::ARRAY_REMOVE) if parser.options.dialect.is_postgresql() => {
2598            Function::ArrayRemove
2599        }
2600        Token::Ident(_, Keyword::ARRAY_REPLACE) if parser.options.dialect.is_postgresql() => {
2601            Function::ArrayReplace
2602        }
2603        Token::Ident(_, Keyword::ARRAY_REVERSE) if parser.options.dialect.is_postgresql() => {
2604            Function::ArrayReverse
2605        }
2606        Token::Ident(_, Keyword::ARRAY_SAMPLE) if parser.options.dialect.is_postgresql() => {
2607            Function::ArraySample
2608        }
2609        Token::Ident(_, Keyword::ARRAY_SHUFFLE) if parser.options.dialect.is_postgresql() => {
2610            Function::ArrayShuffle
2611        }
2612        Token::Ident(_, Keyword::ARRAY_SORT) if parser.options.dialect.is_postgresql() => {
2613            Function::ArraySort
2614        }
2615        Token::Ident(_, Keyword::ARRAY_TO_STRING) if parser.options.dialect.is_postgresql() => {
2616            Function::ArrayToString
2617        }
2618        Token::Ident(_, Keyword::ARRAY_UPPER) if parser.options.dialect.is_postgresql() => {
2619            Function::ArrayUpper
2620        }
2621        Token::Ident(_, Keyword::CARDINALITY) if parser.options.dialect.is_postgresql() => {
2622            Function::Cardinality
2623        }
2624        Token::Ident(_, Keyword::TRIM_ARRAY) if parser.options.dialect.is_postgresql() => {
2625            Function::TrimArray
2626        }
2627
2628        // PostgreSQL range/multirange functions
2629        Token::Ident(_, Keyword::ISEMPTY) if parser.options.dialect.is_postgresql() => {
2630            Function::IsEmpty
2631        }
2632        Token::Ident(_, Keyword::LOWER_INC) if parser.options.dialect.is_postgresql() => {
2633            Function::LowerInc
2634        }
2635        Token::Ident(_, Keyword::LOWER_INF) if parser.options.dialect.is_postgresql() => {
2636            Function::LowerInf
2637        }
2638        Token::Ident(_, Keyword::UPPER_INC) if parser.options.dialect.is_postgresql() => {
2639            Function::UpperInc
2640        }
2641        Token::Ident(_, Keyword::UPPER_INF) if parser.options.dialect.is_postgresql() => {
2642            Function::UpperInf
2643        }
2644        Token::Ident(_, Keyword::RANGE_MERGE) if parser.options.dialect.is_postgresql() => {
2645            Function::RangeMerge
2646        }
2647        Token::Ident(_, Keyword::MULTIRANGE) if parser.options.dialect.is_postgresql() => {
2648            Function::Multirange
2649        }
2650        Token::Ident(_, Keyword::INT4RANGE) if parser.options.dialect.is_postgresql() => {
2651            Function::Int4Range
2652        }
2653        Token::Ident(_, Keyword::INT8RANGE) if parser.options.dialect.is_postgresql() => {
2654            Function::Int8Range
2655        }
2656        Token::Ident(_, Keyword::NUMRANGE) if parser.options.dialect.is_postgresql() => {
2657            Function::NumRange
2658        }
2659        Token::Ident(_, Keyword::TSRANGE) if parser.options.dialect.is_postgresql() => {
2660            Function::TsRange
2661        }
2662        Token::Ident(_, Keyword::TSTZRANGE) if parser.options.dialect.is_postgresql() => {
2663            Function::TstzRange
2664        }
2665        Token::Ident(_, Keyword::DATERANGE) if parser.options.dialect.is_postgresql() => {
2666            Function::DateRange
2667        }
2668        Token::Ident(_, Keyword::INT4MULTIRANGE) if parser.options.dialect.is_postgresql() => {
2669            Function::Int4Multirange
2670        }
2671        Token::Ident(_, Keyword::INT8MULTIRANGE) if parser.options.dialect.is_postgresql() => {
2672            Function::Int8Multirange
2673        }
2674        Token::Ident(_, Keyword::NUMMULTIRANGE) if parser.options.dialect.is_postgresql() => {
2675            Function::NumMultirange
2676        }
2677        Token::Ident(_, Keyword::TSMULTIRANGE) if parser.options.dialect.is_postgresql() => {
2678            Function::TsMultirange
2679        }
2680        Token::Ident(_, Keyword::TSTZMULTIRANGE) if parser.options.dialect.is_postgresql() => {
2681            Function::TstzMultirange
2682        }
2683        Token::Ident(_, Keyword::DATEMULTIRANGE) if parser.options.dialect.is_postgresql() => {
2684            Function::DateMultirange
2685        }
2686
2687        // PostgreSQL text search functions
2688        Token::Ident(_, Keyword::ARRAY_TO_TSVECTOR) if parser.options.dialect.is_postgresql() => {
2689            Function::ArrayToTsvector
2690        }
2691        Token::Ident(_, Keyword::GET_CURRENT_TS_CONFIG)
2692            if parser.options.dialect.is_postgresql() =>
2693        {
2694            Function::GetCurrentTsConfig
2695        }
2696        Token::Ident(_, Keyword::JSON_TO_TSVECTOR) if parser.options.dialect.is_postgresql() => {
2697            Function::JsonToTsvector
2698        }
2699        Token::Ident(_, Keyword::JSONB_TO_TSVECTOR) if parser.options.dialect.is_postgresql() => {
2700            Function::JsonbToTsvector
2701        }
2702        Token::Ident(_, Keyword::NUMNODE) if parser.options.dialect.is_postgresql() => {
2703            Function::Numnode
2704        }
2705        Token::Ident(_, Keyword::PHRASETO_TSQUERY) if parser.options.dialect.is_postgresql() => {
2706            Function::PhraseToTsquery
2707        }
2708        Token::Ident(_, Keyword::PLAINTO_TSQUERY) if parser.options.dialect.is_postgresql() => {
2709            Function::PlainToTsquery
2710        }
2711        Token::Ident(_, Keyword::QUERYTREE) if parser.options.dialect.is_postgresql() => {
2712            Function::Querytree
2713        }
2714        Token::Ident(_, Keyword::SETWEIGHT) if parser.options.dialect.is_postgresql() => {
2715            Function::Setweight
2716        }
2717        Token::Ident(_, Keyword::STRIP) if parser.options.dialect.is_postgresql() => {
2718            Function::Strip
2719        }
2720        Token::Ident(_, Keyword::TO_TSQUERY) if parser.options.dialect.is_postgresql() => {
2721            Function::ToTsquery
2722        }
2723        Token::Ident(_, Keyword::TO_TSVECTOR) if parser.options.dialect.is_postgresql() => {
2724            Function::ToTsvector
2725        }
2726        Token::Ident(_, Keyword::TS_DEBUG) if parser.options.dialect.is_postgresql() => {
2727            Function::TsDebug
2728        }
2729        Token::Ident(_, Keyword::TS_DELETE) if parser.options.dialect.is_postgresql() => {
2730            Function::TsDelete
2731        }
2732        Token::Ident(_, Keyword::TS_FILTER) if parser.options.dialect.is_postgresql() => {
2733            Function::TsFilter
2734        }
2735        Token::Ident(_, Keyword::TS_HEADLINE) if parser.options.dialect.is_postgresql() => {
2736            Function::TsHeadline
2737        }
2738        Token::Ident(_, Keyword::TS_LEXIZE) if parser.options.dialect.is_postgresql() => {
2739            Function::TsLexize
2740        }
2741        Token::Ident(_, Keyword::TS_PARSE) if parser.options.dialect.is_postgresql() => {
2742            Function::TsParse
2743        }
2744        Token::Ident(_, Keyword::TS_RANK) if parser.options.dialect.is_postgresql() => {
2745            Function::TsRank
2746        }
2747        Token::Ident(_, Keyword::TS_RANK_CD) if parser.options.dialect.is_postgresql() => {
2748            Function::TsRankCd
2749        }
2750        Token::Ident(_, Keyword::TS_REWRITE) if parser.options.dialect.is_postgresql() => {
2751            Function::TsRewrite
2752        }
2753        Token::Ident(_, Keyword::TS_STAT) if parser.options.dialect.is_postgresql() => {
2754            Function::TsStat
2755        }
2756        Token::Ident(_, Keyword::TS_TOKEN_TYPE) if parser.options.dialect.is_postgresql() => {
2757            Function::TsTokenType
2758        }
2759        Token::Ident(_, Keyword::TSQUERY_PHRASE) if parser.options.dialect.is_postgresql() => {
2760            Function::TsqueryPhrase
2761        }
2762        Token::Ident(_, Keyword::TSVECTOR_TO_ARRAY) if parser.options.dialect.is_postgresql() => {
2763            Function::TsvectorToArray
2764        }
2765        Token::Ident(_, Keyword::UNNEST) if parser.options.dialect.is_postgresql() => {
2766            Function::Unnest
2767        }
2768        Token::Ident(_, Keyword::WEBSEARCH_TO_TSQUERY)
2769            if parser.options.dialect.is_postgresql() =>
2770        {
2771            Function::WebsearchToTsquery
2772        }
2773
2774        // MySQL 8.4 regexp
2775        Token::Ident(_, Keyword::REGEXP_COUNT) if parser.options.dialect.is_maria() => {
2776            Function::RegexpCount
2777        }
2778        Token::Ident(_, Keyword::REGEXP_INSTR) if parser.options.dialect.is_maria() => {
2779            Function::RegexpInstr
2780        }
2781        Token::Ident(_, Keyword::REGEXP_LIKE) if parser.options.dialect.is_maria() => {
2782            Function::RegexpLike
2783        }
2784        Token::Ident(_, Keyword::REGEXP_MATCH) if parser.options.dialect.is_postgresql() => {
2785            Function::RegexpMatch
2786        }
2787        Token::Ident(_, Keyword::REGEXP_MATCHES) if parser.options.dialect.is_postgresql() => {
2788            Function::RegexpMatches
2789        }
2790        Token::Ident(_, Keyword::REGEXP_REPLACE) => Function::RegexpReplace,
2791        Token::Ident(_, Keyword::REGEXP_SPLIT_TO_ARRAY)
2792            if parser.options.dialect.is_postgresql() =>
2793        {
2794            Function::RegexpSplitToArray
2795        }
2796        Token::Ident(_, Keyword::REGEXP_SPLIT_TO_TABLE)
2797            if parser.options.dialect.is_postgresql() =>
2798        {
2799            Function::RegexpSplitToTable
2800        }
2801        Token::Ident(_, Keyword::REGEXP_SUBSTR) if parser.options.dialect.is_maria() => {
2802            Function::RegexpSubstr
2803        }
2804        Token::Ident(_, Keyword::WEIGHT_STRING) if parser.options.dialect.is_maria() => {
2805            Function::WeightString
2806        }
2807
2808        // MySQL 8.4 datetime
2809        Token::Ident(_, Keyword::GET_BIT) if parser.options.dialect.is_maria() => Function::GetBit,
2810        Token::Ident(_, Keyword::GET_FORMAT) if parser.options.dialect.is_maria() => {
2811            Function::GetFormat
2812        }
2813
2814        // MySQL 8.4 window / analytics
2815        Token::Ident(_, Keyword::FIRST_VALUE) if parser.options.dialect.is_maria() => {
2816            Function::FirstValue
2817        }
2818        Token::Ident(_, Keyword::LAST_VALUE) if parser.options.dialect.is_maria() => {
2819            Function::LastValue
2820        }
2821        Token::Ident(_, Keyword::NTH_VALUE) if parser.options.dialect.is_maria() => {
2822            Function::NthValue
2823        }
2824        Token::Ident(_, Keyword::NTILE) if parser.options.dialect.is_maria() => Function::Ntile,
2825        Token::Ident(_, Keyword::ROW_NUMBER) => Function::RowNumber,
2826
2827        // MySQL 8.4 performance schema
2828        Token::Ident(_, Keyword::FORMAT_BYTES) if parser.options.dialect.is_maria() => {
2829            Function::FormatBytes
2830        }
2831        Token::Ident(_, Keyword::FORMAT_PICO_TIME) if parser.options.dialect.is_maria() => {
2832            Function::FormatPicoTime
2833        }
2834        Token::Ident(_, Keyword::PS_CURRENT_THREAD_ID) if parser.options.dialect.is_maria() => {
2835            Function::PsCurrentThreadId
2836        }
2837        Token::Ident(_, Keyword::PS_THREAD_ID) if parser.options.dialect.is_maria() => {
2838            Function::PsThreadId
2839        }
2840
2841        // MySQL 8.4 miscellaneous
2842        Token::Ident(_, Keyword::ANY_VALUE) if parser.options.dialect.is_maria() => {
2843            Function::AnyValue
2844        }
2845        Token::Ident(_, Keyword::BIN_TO_UUID) if parser.options.dialect.is_maria() => {
2846            Function::BinToUuid
2847        }
2848        Token::Ident(_, Keyword::BIT_COUNT) if parser.options.dialect.is_maria() => {
2849            Function::BitCount
2850        }
2851        Token::Ident(_, Keyword::GROUPING) => Function::Grouping,
2852        Token::Ident(_, Keyword::INET6_ATON) if parser.options.dialect.is_maria() => {
2853            Function::Inet6Aton
2854        }
2855        Token::Ident(_, Keyword::INET6_NTOA) if parser.options.dialect.is_maria() => {
2856            Function::Inet6Ntoa
2857        }
2858        Token::Ident(_, Keyword::INET_ATON) if parser.options.dialect.is_maria() => {
2859            Function::InetAton
2860        }
2861        Token::Ident(_, Keyword::INET_NTOA) if parser.options.dialect.is_maria() => {
2862            Function::InetNtoa
2863        }
2864        Token::Ident(_, Keyword::IS_IPV4) if parser.options.dialect.is_maria() => Function::IsIPv4,
2865        Token::Ident(_, Keyword::IS_IPV4_COMPAT) if parser.options.dialect.is_maria() => {
2866            Function::IsIPv4Compat
2867        }
2868        Token::Ident(_, Keyword::IS_IPV4_MAPPED) if parser.options.dialect.is_maria() => {
2869            Function::IsIPv4Mapped
2870        }
2871        Token::Ident(_, Keyword::IS_IPV6) if parser.options.dialect.is_maria() => Function::IsIPv6,
2872        Token::Ident(_, Keyword::IS_UUID) if parser.options.dialect.is_maria() => Function::IsUuid,
2873        Token::Ident(_, Keyword::NAME_CONST) if parser.options.dialect.is_maria() => {
2874            Function::NameConst
2875        }
2876        Token::Ident(_, Keyword::UUID) => Function::Uuid,
2877        Token::Ident(_, Keyword::UUID_SHORT) if parser.options.dialect.is_maria() => {
2878            Function::UuidShort
2879        }
2880        Token::Ident(_, Keyword::UUID_TO_BIN) if parser.options.dialect.is_maria() => {
2881            Function::UuidToBin
2882        }
2883
2884        // PostgreSQL geometric functions (non-PostGIS) - Table 9.37
2885        Token::Ident(_, Keyword::AREA) if parser.options.dialect.is_postgresql() => Function::Area,
2886        Token::Ident(_, Keyword::BOUND_BOX) if parser.options.dialect.is_postgresql() => {
2887            Function::BoundBox
2888        }
2889        Token::Ident(_, Keyword::CENTER) if parser.options.dialect.is_postgresql() => {
2890            Function::Center
2891        }
2892        Token::Ident(_, Keyword::DIAGONAL) if parser.options.dialect.is_postgresql() => {
2893            Function::Diagonal
2894        }
2895        Token::Ident(_, Keyword::DIAMETER) if parser.options.dialect.is_postgresql() => {
2896            Function::Diameter
2897        }
2898        Token::Ident(_, Keyword::HEIGHT) if parser.options.dialect.is_postgresql() => {
2899            Function::Height
2900        }
2901        Token::Ident(_, Keyword::ISCLOSED) if parser.options.dialect.is_postgresql() => {
2902            Function::Isclosed
2903        }
2904        Token::Ident(_, Keyword::ISOPEN) if parser.options.dialect.is_postgresql() => {
2905            Function::IsOpen
2906        }
2907        Token::Ident(_, Keyword::NPOINTS) if parser.options.dialect.is_postgresql() => {
2908            Function::Npoints
2909        }
2910        Token::Ident(_, Keyword::PCLOSE) if parser.options.dialect.is_postgresql() => {
2911            Function::Pclose
2912        }
2913        Token::Ident(_, Keyword::POPEN) if parser.options.dialect.is_postgresql() => {
2914            Function::Popen
2915        }
2916        Token::Ident(_, Keyword::RADIUS) if parser.options.dialect.is_postgresql() => {
2917            Function::Radius
2918        }
2919        Token::Ident(_, Keyword::SLOPE) if parser.options.dialect.is_postgresql() => {
2920            Function::Slope
2921        }
2922        Token::Ident(_, Keyword::WIDTH) if parser.options.dialect.is_postgresql() => {
2923            Function::Width
2924        }
2925
2926        // PostgreSQL enum support functions
2927        Token::Ident(_, Keyword::ENUM_FIRST) if parser.options.dialect.is_postgresql() => {
2928            Function::EnumFirst
2929        }
2930        Token::Ident(_, Keyword::ENUM_LAST) if parser.options.dialect.is_postgresql() => {
2931            Function::EnumLast
2932        }
2933        Token::Ident(_, Keyword::ENUM_RANGE) if parser.options.dialect.is_postgresql() => {
2934            Function::EnumRange
2935        }
2936
2937        // PostGIS / geometry functions
2938        Token::Ident(_, Keyword::BOX2D) if parser.options.dialect.is_postgis() => Function::Box2D,
2939        Token::Ident(_, Keyword::BOX3D) if parser.options.dialect.is_postgis() => Function::Box3D,
2940        Token::Ident(_, Keyword::GEOMETRYTYPE) if parser.options.dialect.is_postgis() => {
2941            Function::GeometryType
2942        }
2943        Token::Ident(_, Keyword::ST_ADDMEASURE) if parser.options.dialect.is_postgis() => {
2944            Function::StAddMeasure
2945        }
2946        Token::Ident(_, Keyword::ST_ADDPOINT) if parser.options.dialect.is_postgis() => {
2947            Function::StAddPoint
2948        }
2949        Token::Ident(_, Keyword::ST_AFFINE) if parser.options.dialect.is_postgis() => {
2950            Function::StAffine
2951        }
2952        Token::Ident(_, Keyword::ST_AREA) if parser.options.dialect.is_postgis() => {
2953            Function::StArea
2954        }
2955        Token::Ident(_, Keyword::ST_ASBINARY) if parser.options.dialect.is_postgis() => {
2956            Function::StAsBinary
2957        }
2958        Token::Ident(_, Keyword::ST_ASEWKB) if parser.options.dialect.is_postgis() => {
2959            Function::StAsEwkb
2960        }
2961        Token::Ident(_, Keyword::ST_ASEWKT) if parser.options.dialect.is_postgis() => {
2962            Function::StAsEwkt
2963        }
2964        Token::Ident(_, Keyword::ST_ASGEOJSON) if parser.options.dialect.is_postgis() => {
2965            Function::StAsGeoJson
2966        }
2967        Token::Ident(_, Keyword::ST_ASGML) if parser.options.dialect.is_postgis() => {
2968            Function::StAsGml
2969        }
2970        Token::Ident(_, Keyword::ST_ASHEXEWKB) if parser.options.dialect.is_postgis() => {
2971            Function::StAsHexEwkb
2972        }
2973        Token::Ident(_, Keyword::ST_ASKML) if parser.options.dialect.is_postgis() => {
2974            Function::StAsKml
2975        }
2976        Token::Ident(_, Keyword::ST_ASSVG) if parser.options.dialect.is_postgis() => {
2977            Function::StAsSvg
2978        }
2979        Token::Ident(_, Keyword::ST_ASTEXT) if parser.options.dialect.is_postgis() => {
2980            Function::StAsText
2981        }
2982        Token::Ident(_, Keyword::ST_AZIMUTH) if parser.options.dialect.is_postgis() => {
2983            Function::StAzimuth
2984        }
2985        Token::Ident(_, Keyword::ST_BOUNDARY) if parser.options.dialect.is_postgis() => {
2986            Function::StBoundary
2987        }
2988        Token::Ident(_, Keyword::ST_BUFFER) if parser.options.dialect.is_postgis() => {
2989            Function::StBuffer
2990        }
2991        Token::Ident(_, Keyword::ST_BUILDAREA) if parser.options.dialect.is_postgis() => {
2992            Function::StBuildArea
2993        }
2994        Token::Ident(_, Keyword::ST_CENTROID) if parser.options.dialect.is_postgis() => {
2995            Function::StCentroid
2996        }
2997        Token::Ident(_, Keyword::ST_CLOSESTPOINT) if parser.options.dialect.is_postgis() => {
2998            Function::StClosestPoint
2999        }
3000        Token::Ident(_, Keyword::ST_COLLECT) if parser.options.dialect.is_postgis() => {
3001            Function::StCollect
3002        }
3003        Token::Ident(_, Keyword::ST_COLLECTIONEXTRACT) if parser.options.dialect.is_postgis() => {
3004            Function::StCollectionExtract
3005        }
3006        Token::Ident(_, Keyword::ST_CONTAINS) if parser.options.dialect.is_postgis() => {
3007            Function::StContains
3008        }
3009        Token::Ident(_, Keyword::ST_CONTAINSPROPERLY) if parser.options.dialect.is_postgis() => {
3010            Function::StContainsProperly
3011        }
3012        Token::Ident(_, Keyword::ST_CONVEXHULL) if parser.options.dialect.is_postgis() => {
3013            Function::StConvexHull
3014        }
3015        Token::Ident(_, Keyword::ST_COORDDIM) if parser.options.dialect.is_postgis() => {
3016            Function::StCoordDim
3017        }
3018        Token::Ident(_, Keyword::ST_COVEREDBY) if parser.options.dialect.is_postgis() => {
3019            Function::StCoveredBy
3020        }
3021        Token::Ident(_, Keyword::ST_COVERS) if parser.options.dialect.is_postgis() => {
3022            Function::StCovers
3023        }
3024        Token::Ident(_, Keyword::ST_CROSSES) if parser.options.dialect.is_postgis() => {
3025            Function::StCrosses
3026        }
3027        Token::Ident(_, Keyword::ST_CURVETOLINE) if parser.options.dialect.is_postgis() => {
3028            Function::StCurveToLine
3029        }
3030        Token::Ident(_, Keyword::ST_DFULLWITHIN) if parser.options.dialect.is_postgis() => {
3031            Function::StDFullyWithin
3032        }
3033        Token::Ident(_, Keyword::ST_DIFFERENCE) if parser.options.dialect.is_postgis() => {
3034            Function::StDifference
3035        }
3036        Token::Ident(_, Keyword::ST_DIMENSION) if parser.options.dialect.is_postgis() => {
3037            Function::StDimension
3038        }
3039        Token::Ident(_, Keyword::ST_DISJOINT) if parser.options.dialect.is_postgis() => {
3040            Function::StDisjoint
3041        }
3042        Token::Ident(_, Keyword::ST_DISTANCE) if parser.options.dialect.is_postgis() => {
3043            Function::StDistance
3044        }
3045        Token::Ident(_, Keyword::ST_DISTANCE_SPHERE) if parser.options.dialect.is_postgis() => {
3046            Function::StDistanceSphere
3047        }
3048        Token::Ident(_, Keyword::ST_DISTANCE_SPHEROID) if parser.options.dialect.is_postgis() => {
3049            Function::StDistanceSpheroidal
3050        }
3051        Token::Ident(_, Keyword::ST_DWITHIN) if parser.options.dialect.is_postgis() => {
3052            Function::StDWithin
3053        }
3054        Token::Ident(_, Keyword::ST_ENDPOINT) if parser.options.dialect.is_postgis() => {
3055            Function::StEndPoint
3056        }
3057        Token::Ident(_, Keyword::ST_ENVELOPE) if parser.options.dialect.is_postgis() => {
3058            Function::StEnvelope
3059        }
3060        Token::Ident(_, Keyword::ST_EQUALS) if parser.options.dialect.is_postgis() => {
3061            Function::StEquals
3062        }
3063        Token::Ident(_, Keyword::ST_EXTERIORRING) if parser.options.dialect.is_postgis() => {
3064            Function::StExteriorRing
3065        }
3066        Token::Ident(_, Keyword::ST_FORCE_2D) if parser.options.dialect.is_postgis() => {
3067            Function::StForce2D
3068        }
3069        Token::Ident(_, Keyword::ST_FORCE_3D) if parser.options.dialect.is_postgis() => {
3070            Function::StForce3D
3071        }
3072        Token::Ident(_, Keyword::ST_FORCE_3DM) if parser.options.dialect.is_postgis() => {
3073            Function::StForce3DM
3074        }
3075        Token::Ident(_, Keyword::ST_FORCE_3DZ) if parser.options.dialect.is_postgis() => {
3076            Function::StForce3DZ
3077        }
3078        Token::Ident(_, Keyword::ST_FORCE_4D) if parser.options.dialect.is_postgis() => {
3079            Function::StForce4D
3080        }
3081        Token::Ident(_, Keyword::ST_FORCE_COLLECTION) if parser.options.dialect.is_postgis() => {
3082            Function::StForceCollection
3083        }
3084        Token::Ident(_, Keyword::ST_FORCERHR) if parser.options.dialect.is_postgis() => {
3085            Function::StForceRHR
3086        }
3087        Token::Ident(_, Keyword::ST_GEOHASH) if parser.options.dialect.is_postgis() => {
3088            Function::StGeoHash
3089        }
3090        Token::Ident(_, Keyword::ST_GEOMCOLLFROMTEXT) if parser.options.dialect.is_postgis() => {
3091            Function::StGeomCollFromText
3092        }
3093        Token::Ident(_, Keyword::ST_GEOMFROMEWKB) if parser.options.dialect.is_postgis() => {
3094            Function::StGeomFromEwkb
3095        }
3096        Token::Ident(_, Keyword::ST_GEOMFROMEWKT) if parser.options.dialect.is_postgis() => {
3097            Function::StGeomFromEwkt
3098        }
3099        Token::Ident(_, Keyword::ST_GEOMFROMGEOJSON) if parser.options.dialect.is_postgis() => {
3100            Function::StGeomFromGeoJson
3101        }
3102        Token::Ident(_, Keyword::ST_GEOMFROMGML) if parser.options.dialect.is_postgis() => {
3103            Function::StGeomFromGml
3104        }
3105        Token::Ident(_, Keyword::ST_GEOMFROMKML) if parser.options.dialect.is_postgis() => {
3106            Function::StGeomFromKml
3107        }
3108        Token::Ident(_, Keyword::ST_GEOMFROMTEXT) if parser.options.dialect.is_postgis() => {
3109            Function::StGeomFromText
3110        }
3111        Token::Ident(_, Keyword::ST_GEOMFROMWKB) if parser.options.dialect.is_postgis() => {
3112            Function::StGeomFromWkb
3113        }
3114        Token::Ident(_, Keyword::ST_GEOMETRYFROMTEXT) if parser.options.dialect.is_postgis() => {
3115            Function::StGeometryFromText
3116        }
3117        Token::Ident(_, Keyword::ST_GEOMETRYN) if parser.options.dialect.is_postgis() => {
3118            Function::StGeometryN
3119        }
3120        Token::Ident(_, Keyword::ST_GEOMETRYTYPE) if parser.options.dialect.is_postgis() => {
3121            Function::StGeometryType
3122        }
3123        Token::Ident(_, Keyword::ST_GMLTOSQL) if parser.options.dialect.is_postgis() => {
3124            Function::StGmlToSQL
3125        }
3126        Token::Ident(_, Keyword::ST_HASARC) if parser.options.dialect.is_postgis() => {
3127            Function::StHasArc
3128        }
3129        Token::Ident(_, Keyword::ST_HAUSDORFFDISTANCE) if parser.options.dialect.is_postgis() => {
3130            Function::StHausdorffDistance
3131        }
3132        Token::Ident(_, Keyword::ST_INTERIORRINGN) if parser.options.dialect.is_postgis() => {
3133            Function::StInteriorRingN
3134        }
3135        Token::Ident(_, Keyword::ST_INTERSECTION) if parser.options.dialect.is_postgis() => {
3136            Function::StIntersection
3137        }
3138        Token::Ident(_, Keyword::ST_INTERSECTS) if parser.options.dialect.is_postgis() => {
3139            Function::StIntersects
3140        }
3141        Token::Ident(_, Keyword::ST_ISCLOSED) if parser.options.dialect.is_postgis() => {
3142            Function::StIsClosed
3143        }
3144        Token::Ident(_, Keyword::ST_ISEMPTY) if parser.options.dialect.is_postgis() => {
3145            Function::StIsEmpty
3146        }
3147        Token::Ident(_, Keyword::ST_ISRING) if parser.options.dialect.is_postgis() => {
3148            Function::StIsRing
3149        }
3150        Token::Ident(_, Keyword::ST_ISSIMPLE) if parser.options.dialect.is_postgis() => {
3151            Function::StIsSimple
3152        }
3153        Token::Ident(_, Keyword::ST_ISVALID) if parser.options.dialect.is_postgis() => {
3154            Function::StIsValid
3155        }
3156        Token::Ident(_, Keyword::ST_ISVALIDREASON) if parser.options.dialect.is_postgis() => {
3157            Function::StIsValidReason
3158        }
3159        Token::Ident(_, Keyword::ST_LENGTH) if parser.options.dialect.is_postgis() => {
3160            Function::StLength
3161        }
3162        Token::Ident(_, Keyword::ST_LENGTH2D) if parser.options.dialect.is_postgis() => {
3163            Function::StLength2D
3164        }
3165        Token::Ident(_, Keyword::ST_LENGTH3D) if parser.options.dialect.is_postgis() => {
3166            Function::StLength3D
3167        }
3168        Token::Ident(_, Keyword::ST_LINECROSSINGDIRECTION)
3169            if parser.options.dialect.is_postgis() =>
3170        {
3171            Function::StLineCrossingDirection
3172        }
3173        Token::Ident(_, Keyword::ST_LINEFROMMULTIPOINT) if parser.options.dialect.is_postgis() => {
3174            Function::StLineFromMultiPoint
3175        }
3176        Token::Ident(_, Keyword::ST_LINEFROMTEXT) if parser.options.dialect.is_postgis() => {
3177            Function::StLineFromText
3178        }
3179        Token::Ident(_, Keyword::ST_LINEFROMWKB) if parser.options.dialect.is_postgis() => {
3180            Function::StLineFromWkb
3181        }
3182        Token::Ident(_, Keyword::ST_LINEMERGE) if parser.options.dialect.is_postgis() => {
3183            Function::StLineMerge
3184        }
3185        Token::Ident(_, Keyword::ST_LINESTRINGFROMWKB) if parser.options.dialect.is_postgis() => {
3186            Function::StLinestringFromWkb
3187        }
3188        Token::Ident(_, Keyword::ST_LINETOCURVE) if parser.options.dialect.is_postgis() => {
3189            Function::StLineToCurve
3190        }
3191        Token::Ident(_, Keyword::ST_LINE_INTERPOLATE_POINT)
3192            if parser.options.dialect.is_postgis() =>
3193        {
3194            Function::StLineInterpolatePoint
3195        }
3196        Token::Ident(_, Keyword::ST_LINE_LOCATE_POINT) if parser.options.dialect.is_postgis() => {
3197            Function::StLineLocatePoint
3198        }
3199        Token::Ident(_, Keyword::ST_LINE_SUBSTRING) if parser.options.dialect.is_postgis() => {
3200            Function::StLineSubstring
3201        }
3202        Token::Ident(_, Keyword::ST_LONGESTLINE) if parser.options.dialect.is_postgis() => {
3203            Function::StLongestLine
3204        }
3205        Token::Ident(_, Keyword::ST_M) if parser.options.dialect.is_postgis() => Function::StM,
3206        Token::Ident(_, Keyword::ST_MAKEENVELOPE) if parser.options.dialect.is_postgis() => {
3207            Function::StMakeEnvelope
3208        }
3209        Token::Ident(_, Keyword::ST_MAKELINE) if parser.options.dialect.is_postgis() => {
3210            Function::StMakeLine
3211        }
3212        Token::Ident(_, Keyword::ST_MAKEPOINT) if parser.options.dialect.is_postgis() => {
3213            Function::StMakePoint
3214        }
3215        Token::Ident(_, Keyword::ST_MAKEPOINTM) if parser.options.dialect.is_postgis() => {
3216            Function::StMakePointM
3217        }
3218        Token::Ident(_, Keyword::ST_MAKEPOLYGON) if parser.options.dialect.is_postgis() => {
3219            Function::StMakePolygon
3220        }
3221        Token::Ident(_, Keyword::ST_MAXDISTANCE) if parser.options.dialect.is_postgis() => {
3222            Function::StMaxDistance
3223        }
3224        Token::Ident(_, Keyword::ST_MEM_SIZE) if parser.options.dialect.is_postgis() => {
3225            Function::StMemSize
3226        }
3227        Token::Ident(_, Keyword::ST_MINIMUMBOUNDINGCIRCLE)
3228            if parser.options.dialect.is_postgis() =>
3229        {
3230            Function::StMinimumBoundingCircle
3231        }
3232        Token::Ident(_, Keyword::ST_MULTI) if parser.options.dialect.is_postgis() => {
3233            Function::StMulti
3234        }
3235        Token::Ident(_, Keyword::ST_NDIMS) if parser.options.dialect.is_postgis() => {
3236            Function::StNDims
3237        }
3238        Token::Ident(_, Keyword::ST_NPOINTS) if parser.options.dialect.is_postgis() => {
3239            Function::StNPoints
3240        }
3241        Token::Ident(_, Keyword::ST_NRINGS) if parser.options.dialect.is_postgis() => {
3242            Function::StNRings
3243        }
3244        Token::Ident(_, Keyword::ST_NUMGEOMETRIES) if parser.options.dialect.is_postgis() => {
3245            Function::StNumGeometries
3246        }
3247        Token::Ident(_, Keyword::ST_NUMINTERIORRING) if parser.options.dialect.is_postgis() => {
3248            Function::StNumInteriorRing
3249        }
3250        Token::Ident(_, Keyword::ST_NUMINTERIORRINGS) if parser.options.dialect.is_postgis() => {
3251            Function::StNumInteriorRings
3252        }
3253        Token::Ident(_, Keyword::ST_NUMPOINTS) if parser.options.dialect.is_postgis() => {
3254            Function::StNumPoints
3255        }
3256        Token::Ident(_, Keyword::ST_ORDERINGEQUALS) if parser.options.dialect.is_postgis() => {
3257            Function::StOrderingEquals
3258        }
3259        Token::Ident(_, Keyword::ST_OVERLAPS) if parser.options.dialect.is_postgis() => {
3260            Function::StOverlaps
3261        }
3262        Token::Ident(_, Keyword::ST_PERIMETER) if parser.options.dialect.is_postgis() => {
3263            Function::StPerimeter
3264        }
3265        Token::Ident(_, Keyword::ST_PERIMETER2D) if parser.options.dialect.is_postgis() => {
3266            Function::StPerimeter2D
3267        }
3268        Token::Ident(_, Keyword::ST_PERIMETER3D) if parser.options.dialect.is_postgis() => {
3269            Function::StPerimeter3D
3270        }
3271        Token::Ident(_, Keyword::ST_POINT) if parser.options.dialect.is_postgis() => {
3272            Function::StPoint
3273        }
3274        Token::Ident(_, Keyword::ST_POINTFROMTEXT) if parser.options.dialect.is_postgis() => {
3275            Function::StPointFromText
3276        }
3277        Token::Ident(_, Keyword::ST_POINTFROMWKB) if parser.options.dialect.is_postgis() => {
3278            Function::StPointFromWkb
3279        }
3280        Token::Ident(_, Keyword::ST_POINTN) if parser.options.dialect.is_postgis() => {
3281            Function::StPointN
3282        }
3283        Token::Ident(_, Keyword::ST_POINTONSURFACE) if parser.options.dialect.is_postgis() => {
3284            Function::StPointOnSurface
3285        }
3286        Token::Ident(_, Keyword::ST_POINT_INSIDE_CIRCLE) if parser.options.dialect.is_postgis() => {
3287            Function::StPointInsideCircle
3288        }
3289        Token::Ident(_, Keyword::ST_POLYGON) if parser.options.dialect.is_postgis() => {
3290            Function::StPolygon
3291        }
3292        Token::Ident(_, Keyword::ST_POLYGONFROMTEXT) if parser.options.dialect.is_postgis() => {
3293            Function::StPolygonFromText
3294        }
3295        Token::Ident(_, Keyword::ST_POLYGONIZE) if parser.options.dialect.is_postgis() => {
3296            Function::StPolygonize
3297        }
3298        Token::Ident(_, Keyword::ST_RELATE) if parser.options.dialect.is_postgis() => {
3299            Function::StRelate
3300        }
3301        Token::Ident(_, Keyword::ST_REMOVEPOINT) if parser.options.dialect.is_postgis() => {
3302            Function::StRemovePoint
3303        }
3304        Token::Ident(_, Keyword::ST_REVERSE) if parser.options.dialect.is_postgis() => {
3305            Function::StReverse
3306        }
3307        Token::Ident(_, Keyword::ST_ROTATE) if parser.options.dialect.is_postgis() => {
3308            Function::StRotate
3309        }
3310        Token::Ident(_, Keyword::ST_ROTATEX) if parser.options.dialect.is_postgis() => {
3311            Function::StRotateX
3312        }
3313        Token::Ident(_, Keyword::ST_ROTATEY) if parser.options.dialect.is_postgis() => {
3314            Function::StRotateY
3315        }
3316        Token::Ident(_, Keyword::ST_ROTATEZ) if parser.options.dialect.is_postgis() => {
3317            Function::StRotateZ
3318        }
3319        Token::Ident(_, Keyword::ST_SCALE) if parser.options.dialect.is_postgis() => {
3320            Function::StScale
3321        }
3322        Token::Ident(_, Keyword::ST_SEGMENTIZE) if parser.options.dialect.is_postgis() => {
3323            Function::StSegmentize
3324        }
3325        Token::Ident(_, Keyword::ST_SETPOINT) if parser.options.dialect.is_postgis() => {
3326            Function::StSetPoint
3327        }
3328        Token::Ident(_, Keyword::ST_SETSRID) if parser.options.dialect.is_postgis() => {
3329            Function::StSetSrid
3330        }
3331        Token::Ident(_, Keyword::ST_SHIFT_LONGITUDE) if parser.options.dialect.is_postgis() => {
3332            Function::StShiftLongitude
3333        }
3334        Token::Ident(_, Keyword::ST_SHORTESTLINE) if parser.options.dialect.is_postgis() => {
3335            Function::StShortestLine
3336        }
3337        Token::Ident(_, Keyword::ST_SIMPLIFY) if parser.options.dialect.is_postgis() => {
3338            Function::StSimplify
3339        }
3340        Token::Ident(_, Keyword::ST_SIMPLIFYPRESERVETOPOLOGY)
3341            if parser.options.dialect.is_postgis() =>
3342        {
3343            Function::StSimplifyPreserveTopology
3344        }
3345        Token::Ident(_, Keyword::ST_SNAPTOGRID) if parser.options.dialect.is_postgis() => {
3346            Function::StSnapToGrid
3347        }
3348        Token::Ident(_, Keyword::ST_SRID) if parser.options.dialect.is_postgis() => {
3349            Function::StSRID
3350        }
3351        Token::Ident(_, Keyword::ST_STARTPOINT) if parser.options.dialect.is_postgis() => {
3352            Function::StStartPoint
3353        }
3354        Token::Ident(_, Keyword::ST_SUMMARY) if parser.options.dialect.is_postgis() => {
3355            Function::StSummary
3356        }
3357        Token::Ident(_, Keyword::ST_SYMDIFFERENCE) if parser.options.dialect.is_postgis() => {
3358            Function::StSymDifference
3359        }
3360        Token::Ident(_, Keyword::ST_TOUCHES) if parser.options.dialect.is_postgis() => {
3361            Function::StTouches
3362        }
3363        Token::Ident(_, Keyword::ST_TRANSFORM) if parser.options.dialect.is_postgis() => {
3364            Function::StTransform
3365        }
3366        Token::Ident(_, Keyword::ST_TRANSLATE) if parser.options.dialect.is_postgis() => {
3367            Function::StTranslate
3368        }
3369        Token::Ident(_, Keyword::ST_TRANSSCALE) if parser.options.dialect.is_postgis() => {
3370            Function::StTransScale
3371        }
3372        Token::Ident(_, Keyword::ST_UNION) if parser.options.dialect.is_postgis() => {
3373            Function::StUnion
3374        }
3375        Token::Ident(_, Keyword::ST_WITHIN) if parser.options.dialect.is_postgis() => {
3376            Function::StWithin
3377        }
3378        Token::Ident(_, Keyword::ST_WKBTOSQL) if parser.options.dialect.is_postgis() => {
3379            Function::StWkbToSQL
3380        }
3381        Token::Ident(_, Keyword::ST_WKTTOSQL) if parser.options.dialect.is_postgis() => {
3382            Function::StWktToSQL
3383        }
3384        Token::Ident(_, Keyword::ST_X) if parser.options.dialect.is_postgis() => Function::StX,
3385        Token::Ident(_, Keyword::ST_XMAX) if parser.options.dialect.is_postgis() => {
3386            Function::StXMax
3387        }
3388        Token::Ident(_, Keyword::ST_XMIN) if parser.options.dialect.is_postgis() => {
3389            Function::StXMin
3390        }
3391        Token::Ident(_, Keyword::ST_Y) if parser.options.dialect.is_postgis() => Function::StY,
3392        Token::Ident(_, Keyword::ST_YMAX) if parser.options.dialect.is_postgis() => {
3393            Function::StYMax
3394        }
3395        Token::Ident(_, Keyword::ST_YMIN) if parser.options.dialect.is_postgis() => {
3396            Function::StYMin
3397        }
3398        Token::Ident(_, Keyword::ST_Z) if parser.options.dialect.is_postgis() => Function::StZ,
3399        Token::Ident(_, Keyword::ST_ZMAX) if parser.options.dialect.is_postgis() => {
3400            Function::StZMax
3401        }
3402        Token::Ident(_, Keyword::ST_ZMIN) if parser.options.dialect.is_postgis() => {
3403            Function::StZMin
3404        }
3405        Token::Ident(_, Keyword::ST_ZMFLAG) if parser.options.dialect.is_postgis() => {
3406            Function::StZmflag
3407        }
3408        Token::Ident(_, Keyword::ST_3DDISTANCE) if parser.options.dialect.is_postgis() => {
3409            Function::St3DDistance
3410        }
3411        Token::Ident(_, Keyword::ST_3DMAXDISTANCE) if parser.options.dialect.is_postgis() => {
3412            Function::St3DMaxDistance
3413        }
3414        Token::Ident(_, Keyword::ST_3DINTERSECTS) if parser.options.dialect.is_postgis() => {
3415            Function::St3DIntersects
3416        }
3417        Token::Ident(_, Keyword::ST_MAKEVALID) if parser.options.dialect.is_postgis() => {
3418            Function::StMakeValid
3419        }
3420        Token::Ident(_, Keyword::ST_ISVALIDDETAIL) if parser.options.dialect.is_postgis() => {
3421            Function::StIsValidDetail
3422        }
3423        Token::Ident(_, Keyword::ST_DUMP) if parser.options.dialect.is_postgis() => {
3424            Function::StDump
3425        }
3426        Token::Ident(_, Keyword::ST_DUMPPOINTS) if parser.options.dialect.is_postgis() => {
3427            Function::StDumpPoints
3428        }
3429        Token::Ident(_, Keyword::ST_DUMPRINGS) if parser.options.dialect.is_postgis() => {
3430            Function::StDumpRings
3431        }
3432        Token::Ident(_, Keyword::ST_DUMPSEGMENTS) if parser.options.dialect.is_postgis() => {
3433            Function::StDumpSegments
3434        }
3435        Token::Ident(_, Keyword::ST_SNAP) if parser.options.dialect.is_postgis() => {
3436            Function::StSnap
3437        }
3438        Token::Ident(_, Keyword::ST_NODE) if parser.options.dialect.is_postgis() => {
3439            Function::StNode
3440        }
3441        Token::Ident(_, Keyword::ST_SPLIT) if parser.options.dialect.is_postgis() => {
3442            Function::StSplit
3443        }
3444        Token::Ident(_, Keyword::ST_SHAREDPATHS) if parser.options.dialect.is_postgis() => {
3445            Function::StSharedPaths
3446        }
3447        Token::Ident(_, Keyword::ST_EXPAND) if parser.options.dialect.is_postgis() => {
3448            Function::StExpand
3449        }
3450        Token::Ident(_, Keyword::ST_ESTIMATEDEXTENT) if parser.options.dialect.is_postgis() => {
3451            Function::StEstimatedExtent
3452        }
3453        Token::Ident(_, Keyword::ST_FLIPCOORDINATES) if parser.options.dialect.is_postgis() => {
3454            Function::StFlipCoordinates
3455        }
3456        Token::Ident(_, Keyword::ST_FORCECW) if parser.options.dialect.is_postgis() => {
3457            Function::StForceCw
3458        }
3459        Token::Ident(_, Keyword::ST_FORCECCW) if parser.options.dialect.is_postgis() => {
3460            Function::StForceCcw
3461        }
3462        Token::Ident(_, Keyword::ST_FORCEPOLYGONCW) if parser.options.dialect.is_postgis() => {
3463            Function::StForcePolygonCw
3464        }
3465        Token::Ident(_, Keyword::ST_FORCEPOLYGONCCW) if parser.options.dialect.is_postgis() => {
3466            Function::StForcePolygonCcw
3467        }
3468        Token::Ident(_, Keyword::ST_CONCAVEHULL) if parser.options.dialect.is_postgis() => {
3469            Function::StConcaveHull
3470        }
3471        Token::Ident(_, Keyword::ST_VORONOIPOLYGONS) if parser.options.dialect.is_postgis() => {
3472            Function::StVoronoiPolygons
3473        }
3474        Token::Ident(_, Keyword::ST_VORONOILINES) if parser.options.dialect.is_postgis() => {
3475            Function::StVoronoiLines
3476        }
3477        Token::Ident(_, Keyword::ST_DELAUNAYTRIANGLES) if parser.options.dialect.is_postgis() => {
3478            Function::StDelaunayTriangles
3479        }
3480        Token::Ident(_, Keyword::ST_SUBDIVIDE) if parser.options.dialect.is_postgis() => {
3481            Function::StSubdivide
3482        }
3483        Token::Ident(_, Keyword::ST_GENERATEPOINTS) if parser.options.dialect.is_postgis() => {
3484            Function::StGeneratePoints
3485        }
3486        Token::Ident(_, Keyword::ST_BOUNDINGDIAGONAL) if parser.options.dialect.is_postgis() => {
3487            Function::StBoundingDiagonal
3488        }
3489        Token::Ident(_, Keyword::ST_MAXIMUMINSCRIBEDCIRCLE)
3490            if parser.options.dialect.is_postgis() =>
3491        {
3492            Function::StMaximumInscribedCircle
3493        }
3494        Token::Ident(_, Keyword::ST_CHAIKINSMOOTHING) if parser.options.dialect.is_postgis() => {
3495            Function::StChaikinSmoothing
3496        }
3497        Token::Ident(_, Keyword::ST_FRECHETDISTANCE) if parser.options.dialect.is_postgis() => {
3498            Function::StFrechetDistance
3499        }
3500        Token::Ident(_, Keyword::ST_PROJECT) if parser.options.dialect.is_postgis() => {
3501            Function::StProject
3502        }
3503        Token::Ident(_, Keyword::ST_LOCATEALONG) if parser.options.dialect.is_postgis() => {
3504            Function::StLocateAlong
3505        }
3506        Token::Ident(_, Keyword::ST_LOCATEBETWEEN) if parser.options.dialect.is_postgis() => {
3507            Function::StLocateBetween
3508        }
3509        Token::Ident(_, Keyword::ST_INTERPOLATEPOINT) if parser.options.dialect.is_postgis() => {
3510            Function::StInterpolatePoint
3511        }
3512        Token::Ident(_, Keyword::ST_MAKEBOX2D) if parser.options.dialect.is_postgis() => {
3513            Function::StMakeBox2D
3514        }
3515        Token::Ident(_, Keyword::ST_3DMAKEBOX) if parser.options.dialect.is_postgis() => {
3516            Function::St3DMakeBox
3517        }
3518        Token::Ident(_, Keyword::ST_EXTENT) if parser.options.dialect.is_postgis() => {
3519            Function::StExtent
3520        }
3521        Token::Ident(_, Keyword::ST_3DEXTENT) if parser.options.dialect.is_postgis() => {
3522            Function::St3DExtent
3523        }
3524
3525        Token::Ident(v, k) if !k.restricted(parser.reserved()) => {
3526            Function::Other(alloc::vec![Identifier {
3527                value: v,
3528                span: span.clone(),
3529                case_sensitive: false,
3530            }])
3531        }
3532        _ => {
3533            parser.err("Unknown function", &span);
3534            Function::Unknown
3535        }
3536    };
3537
3538    let mut args = Vec::new();
3539
3540    // SQL-standard SUBSTRING(str FROM pos [FOR len]) — PostgreSQL and ANSI SQL.
3541    if matches!(func, Function::SubStr) && !matches!(parser.token, Token::RParen) {
3542        let expr = parse_expression_outer(parser)?;
3543        if let Some(_from) = parser.skip_keyword(Keyword::FROM) {
3544            let pos = parse_expression_outer(parser)?;
3545            args.push(expr);
3546            args.push(pos);
3547            if parser.skip_keyword(Keyword::FOR).is_some() {
3548                args.push(parse_expression_outer(parser)?);
3549            }
3550            let r_paren_span = parser.consume_token(Token::RParen)?;
3551            return Ok(Expression::Function(Box::new(FunctionCallExpression {
3552                function: func,
3553                args,
3554                function_span: span,
3555                r_paren_span,
3556            })));
3557        } else {
3558            // Comma-style: push first arg and continue normally
3559            args.push(expr);
3560            while parser.skip_token(Token::Comma).is_some() {
3561                parser.recovered(
3562                    "')' or ','",
3563                    &|t| matches!(t, Token::RParen | Token::Comma),
3564                    |parser| {
3565                        args.push(parse_expression_outer(parser)?);
3566                        Ok(())
3567                    },
3568                )?;
3569            }
3570            let r_paren_span = parser.consume_token(Token::RParen)?;
3571            if let Some(over) = parse_over_clause(parser)? {
3572                return Ok(Expression::WindowFunction(Box::new(
3573                    WindowFunctionCallExpression {
3574                        function: func,
3575                        args,
3576                        function_span: span,
3577                        r_paren_span,
3578                        over,
3579                    },
3580                )));
3581            }
3582            return Ok(Expression::Function(Box::new(FunctionCallExpression {
3583                function: func,
3584                args,
3585                function_span: span,
3586                r_paren_span,
3587            })));
3588        }
3589    }
3590
3591    if !matches!(parser.token, Token::RParen) {
3592        loop {
3593            parser.recovered(
3594                "')' or ','",
3595                &|t| matches!(t, Token::RParen | Token::Comma),
3596                |parser| {
3597                    args.push(parse_expression_outer(parser)?);
3598                    Ok(())
3599                },
3600            )?;
3601            if parser.skip_token(Token::Comma).is_none() {
3602                break;
3603            }
3604        }
3605    }
3606    let r_paren_span = parser.consume_token(Token::RParen)?;
3607
3608    if let Some(over) = parse_over_clause(parser)? {
3609        Ok(Expression::WindowFunction(Box::new(
3610            WindowFunctionCallExpression {
3611                function: func,
3612                args,
3613                function_span: span,
3614                r_paren_span,
3615                over,
3616            },
3617        )))
3618    } else {
3619        Ok(Expression::Function(Box::new(FunctionCallExpression {
3620            function: func,
3621            args,
3622            function_span: span,
3623            r_paren_span,
3624        })))
3625    }
3626}
3627
3628/// Parse the argument list and optional OVER clause for a schema-qualified function call.
3629/// The caller has already resolved `func = Function::Other(qualified_parts)` and
3630/// computed `function_span` covering the full qualified name.
3631pub(crate) fn parse_char_function<'a>(
3632    parser: &mut Parser<'a, '_>,
3633    char_span: Span,
3634) -> Result<Expression<'a>, ParseError> {
3635    parser.consume_token(Token::LParen)?;
3636    let mut args = Vec::new();
3637    if !matches!(parser.token, Token::RParen) {
3638        loop {
3639            parser.recovered(
3640                "')' or ','",
3641                &|t| {
3642                    matches!(
3643                        t,
3644                        Token::RParen | Token::Comma | Token::Ident(_, Keyword::USING)
3645                    )
3646                },
3647                |parser| {
3648                    args.push(parse_expression_outer(parser)?);
3649                    Ok(())
3650                },
3651            )?;
3652            if parser.skip_token(Token::Comma).is_none() {
3653                break;
3654            }
3655        }
3656    }
3657    // Optional USING charset_name
3658    let using_charset = if let Some(using_span) = parser.skip_keyword(Keyword::USING) {
3659        let charset = parser.consume_plain_identifier_unreserved()?;
3660        Some((using_span, charset))
3661    } else {
3662        None
3663    };
3664    let r_paren_span = parser.consume_token(Token::RParen)?;
3665    Ok(Expression::Char(Box::new(CharFunctionExpression {
3666        char_span,
3667        args,
3668        using_charset,
3669        r_paren_span,
3670    })))
3671}
3672
3673pub(crate) fn parse_function_call<'a>(
3674    parser: &mut Parser<'a, '_>,
3675    func: Function<'a>,
3676    function_span: Span,
3677) -> Result<Expression<'a>, ParseError> {
3678    parser.consume_token(Token::LParen)?;
3679    let mut args = Vec::new();
3680    if !matches!(parser.token, Token::RParen) {
3681        loop {
3682            parser.recovered(
3683                "')' or ','",
3684                &|t| matches!(t, Token::RParen | Token::Comma),
3685                |parser| {
3686                    args.push(parse_expression_outer(parser)?);
3687                    Ok(())
3688                },
3689            )?;
3690            if parser.skip_token(Token::Comma).is_none() {
3691                break;
3692            }
3693        }
3694    }
3695    let r_paren_span = parser.consume_token(Token::RParen)?;
3696
3697    if let Some(over) = parse_over_clause(parser)? {
3698        Ok(Expression::WindowFunction(Box::new(
3699            WindowFunctionCallExpression {
3700                function: func,
3701                args,
3702                function_span,
3703                r_paren_span,
3704                over,
3705            },
3706        )))
3707    } else {
3708        Ok(Expression::Function(Box::new(FunctionCallExpression {
3709            function: func,
3710            args,
3711            function_span,
3712            r_paren_span,
3713        })))
3714    }
3715}
3716
3717#[cfg(test)]
3718mod tests {
3719    use core::ops::Deref;
3720
3721    use alloc::string::{String, ToString};
3722
3723    use crate::{
3724        Function, FunctionCallExpression, ParseOptions, SQLDialect,
3725        expression::{Expression, PRIORITY_MAX},
3726        issue::Issues,
3727        parser::Parser,
3728    };
3729
3730    use super::parse_expression_unreserved;
3731
3732    fn test_expr(src: &'static str, f: impl FnOnce(&Expression<'_>) -> Result<(), String>) {
3733        let mut issues = Issues::new(src);
3734        let options = ParseOptions::new().dialect(SQLDialect::MariaDB);
3735        let mut parser = Parser::new(src, &mut issues, &options);
3736        let res = parse_expression_unreserved(&mut parser, PRIORITY_MAX)
3737            .expect("Expression in test expr");
3738        if let Err(e) = f(&res) {
3739            panic!("Error parsing {}: {}\nGot {:#?}", src, e, res);
3740        }
3741    }
3742
3743    #[test]
3744    fn mariadb_datetime_functions() {
3745        fn test_func(src: &'static str, f: Function, cnt: usize) {
3746            let mut issues = Issues::new(src);
3747            let options = ParseOptions::new().dialect(SQLDialect::MariaDB);
3748            let mut parser = Parser::new(src, &mut issues, &options);
3749            let res = match parse_expression_unreserved(&mut parser, PRIORITY_MAX) {
3750                Ok(res) => res,
3751                Err(e) => panic!("Unable to parse {}: {:?}", src, e),
3752            };
3753            let Expression::Function(r) = res else {
3754                panic!("Should be parsed as function {}", src);
3755            };
3756            let FunctionCallExpression {
3757                function: pf, args, ..
3758            } = r.deref();
3759            assert_eq!(pf, &f, "Failure en expr {}", src);
3760            assert_eq!(args.len(), cnt, "Failure en expr {}", src);
3761        }
3762        test_func("ADD_MONTHS('2012-01-31', 2)", Function::AddMonths, 2);
3763        test_func(
3764            "ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002')",
3765            Function::AddTime,
3766            2,
3767        );
3768        test_func(
3769            "DATE_ADD('2008-01-02', INTERVAL 31 DAY)",
3770            Function::AddDate,
3771            2,
3772        );
3773        test_func(
3774            "ADDDATE('2008-01-02', INTERVAL 31 DAY)",
3775            Function::AddDate,
3776            2,
3777        );
3778        test_func("ADDDATE('2008-01-02', 31)", Function::AddDate, 2);
3779        test_func(
3780            "CONVERT_TZ('2016-01-01 12:00:00','+00:00','+10:00')",
3781            Function::ConvertTz,
3782            3,
3783        );
3784        test_func("CURDATE()", Function::CurDate, 0);
3785        test_func("CURRENT_DATE", Function::CurDate, 0);
3786        test_func("CURRENT_DATE()", Function::CurDate, 0);
3787        test_func("CURRENT_TIME", Function::CurTime, 0);
3788        test_func("CURRENT_TIME()", Function::CurTime, 0);
3789        test_func("CURTIME()", Function::CurTime, 0);
3790        test_func("CURTIME(2)", Function::CurTime, 1);
3791        test_func("CURRENT_DATE", Function::CurDate, 0);
3792        test_func("CURRENT_DATE()", Function::CurDate, 0);
3793        test_func("CURDATE()", Function::CurDate, 0);
3794        test_func("CURRENT_TIMESTAMP", Function::CurrentTimestamp, 0);
3795        test_func("CURRENT_TIMESTAMP()", Function::CurrentTimestamp, 0);
3796        test_func("CURRENT_TIMESTAMP(10)", Function::CurrentTimestamp, 1);
3797        test_func("LOCALTIME", Function::Now, 0);
3798        test_func("LOCALTIME()", Function::Now, 0);
3799        test_func("LOCALTIME(10)", Function::Now, 1);
3800        test_func("LOCALTIMESTAMP", Function::Now, 0);
3801        test_func("LOCALTIMESTAMP()", Function::Now, 0);
3802        test_func("LOCALTIMESTAMP(10)", Function::Now, 1);
3803        test_func("DATE('2013-07-18 12:21:32')", Function::Date, 1);
3804        test_func(
3805            "DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y')",
3806            Function::DateFormat,
3807            2,
3808        );
3809        test_func(
3810            "DATE_SUB('1998-01-02', INTERVAL 31 DAY)",
3811            Function::DateSub,
3812            2,
3813        );
3814        test_func("DAY('2007-02-03')", Function::DayOfMonth, 1);
3815        test_func("DAYOFMONTH('2007-02-03')", Function::DayOfMonth, 1);
3816        test_func(
3817            "DATEDIFF('2007-12-31 23:59:59','2007-12-30')",
3818            Function::DateDiff,
3819            2,
3820        );
3821        test_func("DAYNAME('2007-02-03')", Function::DayName, 1);
3822        test_func("DAYOFYEAR('2018-02-16')", Function::DayOfYear, 1);
3823        test_func("DAYOFWEEK('2007-02-03')", Function::DayOfWeek, 1);
3824        test_expr("EXTRACT(YEAR_MONTH FROM '2009-07-02 01:02:03')", |e| {
3825            let Expression::Extract { .. } = e else {
3826                return Err("Wrong type".to_string());
3827            };
3828            Ok(())
3829        });
3830        //test_func("FORMAT_PICO_TIME(4321123443212345) AS h", Function::DayOfWeek, 1);
3831        test_func("FROM_DAYS(730669)", Function::FromDays, 1);
3832        test_func("FROM_UNIXTIME(1196440219)", Function::FromUnixTime, 1);
3833        test_func(
3834            "FROM_UNIXTIME(UNIX_TIMESTAMP(), '%Y %D %M %h:%i:%s %x')",
3835            Function::FromUnixTime,
3836            2,
3837        );
3838        //test_func("GET_FORMAT(DATE, 'EUR')", Function::GetFormat, 2);
3839        test_func("HOUR('10:05:03')", Function::Hour, 1);
3840        test_func("LAST_DAY('2004-01-01 01:01:01')", Function::LastDay, 1);
3841        test_func("MAKEDATE(2011,31)", Function::MakeDate, 2);
3842        test_func("MAKETIME(-13,57,33)", Function::MakeTime, 3);
3843        test_func("MICROSECOND('12:00:00.123456')", Function::MicroSecond, 1);
3844        test_func("MINUTE('2013-08-03 11:04:03')", Function::Minute, 1);
3845        test_func("MONTH('2019-01-03')", Function::Month, 1);
3846        test_func("MONTHNAME('2019-02-03')", Function::MonthName, 1);
3847        test_func("PERIOD_ADD(200801,2)", Function::PeriodAdd, 2);
3848        test_func("PERIOD_DIFF(200802,200703)", Function::PeriodDiff, 2);
3849        test_func("QUARTER('2008-04-01')", Function::Quarter, 1);
3850        test_func("SEC_TO_TIME(12414)", Function::SecToTime, 1);
3851        test_func("SECOND('10:05:03')", Function::Second, 1);
3852        test_func(
3853            "STR_TO_DATE('Wednesday, June 2, 2014', '%W, %M %e, %Y')",
3854            Function::StrToDate,
3855            2,
3856        );
3857        test_func(
3858            "DATE_SUB('2008-01-02', INTERVAL 31 DAY)",
3859            Function::DateSub,
3860            2,
3861        );
3862        test_func("SUBDATE('2008-01-02 12:00:00', 31)", Function::DateSub, 2);
3863        test_func(
3864            "SUBDATE('2008-01-02', INTERVAL 31 DAY)",
3865            Function::DateSub,
3866            2,
3867        );
3868        test_func(
3869            "SUBTIME('2007-12-31 23:59:59.999999','1 1:1:1.000002')",
3870            Function::SubTime,
3871            2,
3872        );
3873        test_func("SYSDATE()", Function::SysDate, 0);
3874        test_func("SYSDATE(4)", Function::SysDate, 1);
3875        test_func("TIME('2003-12-31 01:02:03')", Function::Time, 1);
3876        test_func(
3877            "TIME_FORMAT('100:00:00', '%H %k %h %I %l')",
3878            Function::TimeFormat,
3879            2,
3880        );
3881        test_func("TIME_TO_SEC('22:23:00')", Function::TimeToSec, 1);
3882        test_func(
3883            "TIMEDIFF('2008-12-31 23:59:59.000001', '2008-12-30 01:01:01.000002')",
3884            Function::TimeDiff,
3885            2,
3886        );
3887        test_func("TIMESTAMP('2003-12-31')", Function::Timestamp, 1);
3888        test_func(
3889            "TIMESTAMP('2003-12-31 12:00:00','6:30:00')",
3890            Function::Timestamp,
3891            2,
3892        );
3893        test_expr("TIMESTAMPADD(MINUTE,1,'2003-01-02')", |e| {
3894            let Expression::TimestampAdd { .. } = e else {
3895                return Err("Wrong type".to_string());
3896            };
3897            Ok(())
3898        });
3899        test_expr("TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');", |e| {
3900            let Expression::TimestampDiff { .. } = e else {
3901                return Err("Wrong type".to_string());
3902            };
3903            Ok(())
3904        });
3905        test_func("TO_DAYS('2007-10-07')", Function::ToDays, 1);
3906        test_func("UNIX_TIMESTAMP()", Function::UnixTimestamp, 0);
3907        test_func(
3908            "UNIX_TIMESTAMP('2007-11-30 10:30:19')",
3909            Function::UnixTimestamp,
3910            1,
3911        );
3912        test_func("UTC_DATE", Function::UtcDate, 0);
3913        test_func("UTC_DATE()", Function::UtcDate, 0);
3914        test_func("UTC_TIME", Function::UtcTime, 0);
3915        test_func("UTC_TIME()", Function::UtcTime, 0);
3916        test_func("UTC_TIME(5)", Function::UtcTime, 1);
3917        test_func("UTC_TIMESTAMP", Function::UtcTimeStamp, 0);
3918        test_func("UTC_TIMESTAMP()", Function::UtcTimeStamp, 0);
3919        test_func("UTC_TIMESTAMP(4)", Function::UtcTimeStamp, 1);
3920        test_func("WEEK('2008-02-20')", Function::Week, 1);
3921        test_func("WEEK('2008-02-20',0)", Function::Week, 2);
3922        test_func("WEEKDAY('2008-02-03 22:23:00')", Function::Weekday, 1);
3923        test_func("WEEKOFYEAR('2008-02-20')", Function::WeekOfYear, 1);
3924        test_func("YEAR('1987-01-01')", Function::Year, 1);
3925        test_func("YEARWEEK('1987-01-01')", Function::YearWeek, 1);
3926        test_func("YEARWEEK('1987-01-01',0)", Function::YearWeek, 2);
3927    }
3928}