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