Skip to main content

qusql_parse/
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    DataType, Identifier, QualifiedName, SString, Span, Spanned, Statement,
15    data_type::{DataTypeContext, parse_data_type},
16    function_expression::{
17        AggregateFunctionCallExpression, CharFunctionExpression, Function, FunctionCallExpression,
18        WindowFunctionCallExpression, is_aggregate_function_ident, parse_aggregate_function,
19        parse_char_function, parse_function, parse_function_call,
20    },
21    keywords::{Keyword, Restrict},
22    lexer::Token,
23    operator::parse_operator_name,
24    parser::{ParseError, Parser},
25    span::OptSpanned,
26    statement::parse_compound_query,
27};
28use alloc::string::ToString;
29use alloc::vec;
30use alloc::{boxed::Box, vec::Vec};
31
32/// Function to execute
33#[derive(Debug, Clone)]
34pub enum Variable<'a> {
35    TimeZone,
36    Other(&'a str),
37}
38
39/// Binary operator to apply
40#[derive(Debug, Clone)]
41pub enum BinaryOperator<'a> {
42    Or(Span),
43    Xor(Span),
44    And(Span),
45    Eq(Span),
46    NullSafeEq(Span),
47    GtEq(Span),
48    Gt(Span),
49    LtEq(Span),
50    Lt(Span),
51    Neq(Span),
52    ShiftLeft(Span),
53    ShiftRight(Span),
54    BitAnd(Span),
55    BitOr(Span),
56    BitXor(Span),
57    Add(Span),
58    Subtract(Span),
59    Divide(Span),
60    Div(Span),
61    Mod(Span),
62    Mult(Span),
63    Like(Span),
64    NotLike(Span),
65    Regexp(Span),
66    NotRegexp(Span),
67    Rlike(Span),
68    NotRlike(Span),
69    Collate(Span),
70    JsonExtract(Span),
71    JsonExtractUnquote(Span),
72    Assignment(Span),
73    /// String/array concatenation `||`
74    Concat(Span),
75    // PostgreSQL-specific binary operators
76    /// && (array/range overlap)
77    Overlap(Span),
78    /// @>
79    Contains(Span),
80    /// <@
81    ContainedBy(Span),
82    /// @@ (full-text / jsonpath match)
83    JsonPathMatch(Span),
84    /// @?
85    JsonPathExists(Span),
86    /// ? (jsonb key exists)
87    JsonbKeyExists(Span),
88    /// ?|
89    JsonbAnyKeyExists(Span),
90    /// ?&
91    JsonbAllKeyExists(Span),
92    /// #>
93    JsonGetPath(Span),
94    /// #>>
95    JsonGetPathText(Span),
96    /// #-
97    JsonDeletePath(Span),
98    /// ~ (regex match)
99    RegexMatch(Span),
100    /// ~* (case-insensitive regex match)
101    RegexIMatch(Span),
102    /// !~ (regex not match)
103    NotRegexMatch(Span),
104    /// !~* (case-insensitive regex not match)
105    NotRegexIMatch(Span),
106    /// User-defined / unrecognised PostgreSQL operator
107    User(&'a str, Span),
108    /// PostgreSQL OPERATOR(schema.op) expression
109    Operator(QualifiedName<'a>, Span),
110}
111
112impl<'a> Spanned for BinaryOperator<'a> {
113    fn span(&self) -> Span {
114        match self {
115            BinaryOperator::Or(s)
116            | BinaryOperator::Xor(s)
117            | BinaryOperator::And(s)
118            | BinaryOperator::Eq(s)
119            | BinaryOperator::NullSafeEq(s)
120            | BinaryOperator::GtEq(s)
121            | BinaryOperator::Gt(s)
122            | BinaryOperator::LtEq(s)
123            | BinaryOperator::Lt(s)
124            | BinaryOperator::Neq(s)
125            | BinaryOperator::ShiftLeft(s)
126            | BinaryOperator::ShiftRight(s)
127            | BinaryOperator::BitAnd(s)
128            | BinaryOperator::BitOr(s)
129            | BinaryOperator::BitXor(s)
130            | BinaryOperator::Add(s)
131            | BinaryOperator::Subtract(s)
132            | BinaryOperator::Divide(s)
133            | BinaryOperator::Div(s)
134            | BinaryOperator::Mod(s)
135            | BinaryOperator::Mult(s)
136            | BinaryOperator::Like(s)
137            | BinaryOperator::NotLike(s)
138            | BinaryOperator::Regexp(s)
139            | BinaryOperator::NotRegexp(s)
140            | BinaryOperator::Rlike(s)
141            | BinaryOperator::NotRlike(s)
142            | BinaryOperator::Collate(s)
143            | BinaryOperator::JsonExtract(s)
144            | BinaryOperator::JsonExtractUnquote(s)
145            | BinaryOperator::Assignment(s)
146            | BinaryOperator::Concat(s)
147            | BinaryOperator::Overlap(s)
148            | BinaryOperator::Contains(s)
149            | BinaryOperator::ContainedBy(s)
150            | BinaryOperator::JsonPathMatch(s)
151            | BinaryOperator::JsonPathExists(s)
152            | BinaryOperator::JsonbKeyExists(s)
153            | BinaryOperator::JsonbAnyKeyExists(s)
154            | BinaryOperator::JsonbAllKeyExists(s)
155            | BinaryOperator::JsonGetPath(s)
156            | BinaryOperator::JsonGetPathText(s)
157            | BinaryOperator::JsonDeletePath(s)
158            | BinaryOperator::RegexMatch(s)
159            | BinaryOperator::RegexIMatch(s)
160            | BinaryOperator::NotRegexMatch(s)
161            | BinaryOperator::NotRegexIMatch(s) => s.clone(),
162            BinaryOperator::User(_, s) => s.clone(),
163            BinaryOperator::Operator(_, s) => s.clone(),
164        }
165    }
166}
167
168/// Mode for MATCH ... AGAINST
169#[derive(Debug, Clone)]
170pub enum MatchMode {
171    InBoolean(Span),
172    InNaturalLanguage(Span),
173    InNaturalLanguageWithQueryExpansion(Span),
174    WithQueryExpansion(Span),
175}
176
177impl Spanned for MatchMode {
178    fn span(&self) -> Span {
179        match self {
180            MatchMode::InBoolean(s) => s.clone(),
181            MatchMode::InNaturalLanguage(s) => s.clone(),
182            MatchMode::InNaturalLanguageWithQueryExpansion(s) => s.clone(),
183            MatchMode::WithQueryExpansion(s) => s.clone(),
184        }
185    }
186}
187
188/// Type of is expression
189#[derive(Debug, Clone)]
190pub enum Is<'a> {
191    Null,
192    NotNull,
193    True,
194    NotTrue,
195    False,
196    NotFalse,
197    Unknown,
198    NotUnknown,
199    DistinctFrom(Expression<'a>),
200    NotDistinctFrom(Expression<'a>),
201}
202
203/// Unary operator to apply
204#[derive(Debug, Clone)]
205pub enum UnaryOperator {
206    Binary(Span),
207    LogicalNot(Span),
208    Minus(Span),
209    Not(Span),
210}
211
212impl Spanned for UnaryOperator {
213    fn span(&self) -> Span {
214        match self {
215            UnaryOperator::Binary(s)
216            | UnaryOperator::LogicalNot(s)
217            | UnaryOperator::Minus(s)
218            | UnaryOperator::Not(s) => s.clone(),
219        }
220    }
221}
222
223/// Part of a full identifier
224#[derive(Debug, Clone)]
225pub enum IdentifierPart<'a> {
226    Name(Identifier<'a>),
227    Star(Span),
228}
229
230impl<'a> Spanned for IdentifierPart<'a> {
231    fn span(&self) -> Span {
232        match &self {
233            IdentifierPart::Name(v) => v.span(),
234            IdentifierPart::Star(v) => v.span(),
235        }
236    }
237}
238
239/// When part of CASE
240#[derive(Debug, Clone)]
241pub struct When<'a> {
242    /// Span of WHEN
243    pub when_span: Span,
244    /// When to return then
245    pub when: Expression<'a>,
246    /// Span of THEN
247    pub then_span: Span,
248    /// What to return when when applyes
249    pub then: Expression<'a>,
250}
251
252impl<'a> Spanned for When<'a> {
253    fn span(&self) -> Span {
254        self.when_span
255            .join_span(&self.when)
256            .join_span(&self.then_span)
257            .join_span(&self.then)
258    }
259}
260
261/// Units of time
262#[derive(Debug, Clone, PartialEq, Eq)]
263pub enum TimeUnit {
264    /// Microseconds
265    Microsecond,
266    /// Seconds
267    Second,
268    /// Minutes
269    Minute,
270    /// Hours
271    Hour,
272    /// Days
273    Day,
274    /// Weeks
275    Week,
276    /// Months
277    Month,
278    /// Quarters
279    Quarter,
280    /// Years
281    Year,
282    /// Seconds.Microseconds
283    SecondMicrosecond,
284    /// Minutes.Seconds.Microseconds
285    MinuteMicrosecond,
286    /// Minutes.Seconds
287    MinuteSecond,
288    /// Hours.Minutes.Seconds.Microseconds
289    HourMicrosecond,
290    /// Hours.Minutes.Seconds
291    HourSecond,
292    /// Hours.Minutes
293    HourMinute,
294    /// Days Hours.Minutes.Seconds.Microseconds
295    DayMicrosecond,
296    /// Days Hours.Minutes.Seconds
297    DaySecond,
298    /// Days Hours.Minutes
299    DayMinute,
300    /// Days Hours
301    DayHour,
302    /// Years-Months
303    YearMonth,
304    /// PostgreSQL: epoch (seconds since 1970-01-01)
305    Epoch,
306    /// PostgreSQL: day of week (0=Sunday)
307    Dow,
308    /// PostgreSQL: day of year
309    Doy,
310    /// PostgreSQL: century
311    Century,
312    /// PostgreSQL: decade
313    Decade,
314    /// PostgreSQL: ISO day of week (1=Monday)
315    IsoDow,
316    /// PostgreSQL: ISO year
317    IsoYear,
318    /// PostgreSQL: Julian day
319    Julian,
320    /// PostgreSQL: millennium
321    Millennium,
322    /// PostgreSQL: timezone offset in seconds
323    Timezone,
324    /// PostgreSQL: timezone hours component
325    TimezoneHour,
326    /// PostgreSQL: timezone minutes component
327    TimezoneMinute,
328}
329
330fn parse_time_unit_from_str(s: &str) -> Option<TimeUnit> {
331    match s.to_ascii_lowercase().trim_end_matches('s') {
332        "microsecond" => Some(TimeUnit::Microsecond),
333        "second" => Some(TimeUnit::Second),
334        "minute" => Some(TimeUnit::Minute),
335        "hour" => Some(TimeUnit::Hour),
336        "day" => Some(TimeUnit::Day),
337        "week" => Some(TimeUnit::Week),
338        "month" => Some(TimeUnit::Month),
339        "quarter" => Some(TimeUnit::Quarter),
340        "year" => Some(TimeUnit::Year),
341        "epoch" => Some(TimeUnit::Epoch),
342        "dow" => Some(TimeUnit::Dow),
343        "doy" => Some(TimeUnit::Doy),
344        "century" | "centurie" => Some(TimeUnit::Century),
345        "decade" => Some(TimeUnit::Decade),
346        "isodow" => Some(TimeUnit::IsoDow),
347        "isoyear" => Some(TimeUnit::IsoYear),
348        "julian" => Some(TimeUnit::Julian),
349        "millennium" | "millennia" | "millenniu" => Some(TimeUnit::Millennium),
350        "timezone" => Some(TimeUnit::Timezone),
351        "timezone_hour" => Some(TimeUnit::TimezoneHour),
352        "timezone_minute" => Some(TimeUnit::TimezoneMinute),
353        _ => None,
354    }
355}
356
357fn parse_time_unit(t: &Token<'_>) -> Option<TimeUnit> {
358    match t {
359        Token::Ident(_, Keyword::MICROSECOND) => Some(TimeUnit::Microsecond),
360        Token::Ident(_, Keyword::SECOND) => Some(TimeUnit::Second),
361        Token::Ident(_, Keyword::MINUTE) => Some(TimeUnit::Minute),
362        Token::Ident(_, Keyword::HOUR) => Some(TimeUnit::Hour),
363        Token::Ident(_, Keyword::DAY) => Some(TimeUnit::Day),
364        Token::Ident(_, Keyword::WEEK) => Some(TimeUnit::Week),
365        Token::Ident(_, Keyword::MONTH) => Some(TimeUnit::Month),
366        Token::Ident(_, Keyword::QUARTER) => Some(TimeUnit::Quarter),
367        Token::Ident(_, Keyword::YEAR) => Some(TimeUnit::Year),
368        Token::Ident(_, Keyword::SECOND_MICROSECOND) => Some(TimeUnit::SecondMicrosecond),
369        Token::Ident(_, Keyword::MINUTE_MICROSECOND) => Some(TimeUnit::MinuteMicrosecond),
370        Token::Ident(_, Keyword::MINUTE_SECOND) => Some(TimeUnit::MinuteSecond),
371        Token::Ident(_, Keyword::HOUR_MICROSECOND) => Some(TimeUnit::HourMicrosecond),
372        Token::Ident(_, Keyword::HOUR_SECOND) => Some(TimeUnit::HourSecond),
373        Token::Ident(_, Keyword::HOUR_MINUTE) => Some(TimeUnit::HourMinute),
374        Token::Ident(_, Keyword::DAY_MICROSECOND) => Some(TimeUnit::DayMicrosecond),
375        Token::Ident(_, Keyword::DAY_SECOND) => Some(TimeUnit::DaySecond),
376        Token::Ident(_, Keyword::DAY_MINUTE) => Some(TimeUnit::DayMinute),
377        Token::Ident(_, Keyword::DAY_HOUR) => Some(TimeUnit::DayHour),
378        Token::Ident(_, Keyword::YEAR_MONTH) => Some(TimeUnit::YearMonth),
379        Token::Ident(s, Keyword::NOT_A_KEYWORD) => parse_time_unit_from_str(s),
380        _ => None,
381    }
382}
383
384/// Expression with binary operator
385#[derive(Debug, Clone)]
386pub struct BinaryExpression<'a> {
387    pub op: BinaryOperator<'a>,
388    pub lhs: Expression<'a>,
389    pub rhs: Expression<'a>,
390}
391
392impl Spanned for BinaryExpression<'_> {
393    fn span(&self) -> Span {
394        self.op.span().join_span(&self.lhs).join_span(&self.rhs)
395    }
396}
397
398/// Expression with a unary (prefix) operator
399#[derive(Debug, Clone)]
400pub struct UnaryExpression<'a> {
401    pub op: UnaryOperator,
402    pub operand: Expression<'a>,
403}
404
405impl Spanned for UnaryExpression<'_> {
406    fn span(&self) -> Span {
407        self.op.span().join_span(&self.operand)
408    }
409}
410/// Time Interval
411#[derive(Debug, Clone)]
412pub struct IntervalExpression {
413    /// Span of "INTERVAL"
414    pub interval_span: Span,
415    /// Time internal
416    pub time_interval: (Vec<i64>, Span),
417    /// Unit of the time interval
418    pub time_unit: (TimeUnit, Span),
419}
420
421impl Spanned for IntervalExpression {
422    fn span(&self) -> Span {
423        self.interval_span
424            .join_span(&self.time_interval.1)
425            .join_span(&self.time_unit.1)
426    }
427}
428
429/// Extract expression
430#[derive(Debug, Clone)]
431pub struct ExtractExpression<'a> {
432    /// Span of "EXTRACT"
433    pub extract_span: Span,
434    /// Unit of the time interval
435    pub time_unit: (TimeUnit, Span),
436    /// Span of "FROM"
437    pub from_span: Span,
438    /// Date expression
439    pub date: Expression<'a>,
440}
441
442impl Spanned for ExtractExpression<'_> {
443    fn span(&self) -> Span {
444        self.extract_span
445            .join_span(&self.time_unit.1)
446            .join_span(&self.from_span)
447            .join_span(&self.date)
448    }
449}
450
451/// Direction for TRIM()
452#[derive(Debug, Clone)]
453pub enum TrimDirection {
454    Both(Span),
455    Leading(Span),
456    Trailing(Span),
457}
458
459impl Spanned for TrimDirection {
460    fn span(&self) -> Span {
461        match self {
462            TrimDirection::Both(s) | TrimDirection::Leading(s) | TrimDirection::Trailing(s) => {
463                s.clone()
464            }
465        }
466    }
467}
468
469/// TRIM([{BOTH|LEADING|TRAILING} [remstr] FROM] str) expression
470#[derive(Debug, Clone)]
471pub struct TrimExpression<'a> {
472    /// Span of "TRIM"
473    pub trim_span: Span,
474    /// Optional BOTH / LEADING / TRAILING direction
475    pub direction: Option<TrimDirection>,
476    /// Optional removal string (remstr)
477    pub what: Option<Expression<'a>>,
478    /// Span of "FROM" when present
479    pub from_span: Option<Span>,
480    /// The string to trim
481    pub value: Expression<'a>,
482}
483
484impl Spanned for TrimExpression<'_> {
485    fn span(&self) -> Span {
486        self.trim_span
487            .join_span(&self.direction)
488            .join_span(&self.what)
489            .join_span(&self.from_span)
490            .join_span(&self.value)
491    }
492}
493
494/// In expression
495#[derive(Debug, Clone)]
496pub struct InExpression<'a> {
497    /// Left hand side expression
498    pub lhs: Expression<'a>,
499    /// Right hand side expression
500    pub rhs: Vec<Expression<'a>>,
501    /// Span of "IN" or "NOT IN"
502    pub in_span: Span,
503    /// True if not in
504    pub not_in: bool,
505}
506
507impl Spanned for InExpression<'_> {
508    fn span(&self) -> Span {
509        self.in_span.join_span(&self.lhs).join_span(&self.rhs)
510    }
511}
512
513/// Between expression (expr BETWEEN low AND high)
514#[derive(Debug, Clone)]
515pub struct BetweenExpression<'a> {
516    /// The value being tested
517    pub lhs: Expression<'a>,
518    /// Lower bound
519    pub low: Expression<'a>,
520    /// Upper bound
521    pub high: Expression<'a>,
522    /// Span covering "BETWEEN ... AND"
523    pub between_span: Span,
524    /// True if NOT BETWEEN
525    pub not_between: bool,
526}
527
528impl Spanned for BetweenExpression<'_> {
529    fn span(&self) -> Span {
530        self.between_span
531            .join_span(&self.lhs)
532            .join_span(&self.low)
533            .join_span(&self.high)
534    }
535}
536
537/// Member of expression
538#[derive(Debug, Clone)]
539pub struct MemberOfExpression<'a> {
540    /// Left hand side expression
541    pub lhs: Expression<'a>,
542    /// Right hand side expression
543    pub rhs: Expression<'a>,
544    /// Span of "MEMBER OF"
545    pub member_of_span: Span,
546}
547
548impl Spanned for MemberOfExpression<'_> {
549    fn span(&self) -> Span {
550        self.member_of_span
551            .join_span(&self.lhs)
552            .join_span(&self.rhs)
553    }
554}
555
556/// Case expression
557#[derive(Debug, Clone)]
558pub struct CaseExpression<'a> {
559    /// Span of "CASE"
560    pub case_span: Span,
561    /// Optional value to switch over
562    pub value: Option<Expression<'a>>,
563    /// When parts
564    pub whens: Vec<When<'a>>,
565    /// Span of "ELSE" and else value if specified
566    pub else_: Option<(Span, Expression<'a>)>,
567    /// Span of "END"
568    pub end_span: Span,
569}
570
571impl Spanned for CaseExpression<'_> {
572    fn span(&self) -> Span {
573        self.case_span
574            .join_span(&self.value)
575            .join_span(&self.whens)
576            .join_span(&self.else_)
577            .join_span(&self.end_span)
578    }
579}
580
581/// Cast expression
582#[derive(Debug, Clone)]
583pub struct CastExpression<'a> {
584    /// Span of "CAST"
585    pub cast_span: Span,
586    /// Value to cast
587    pub expr: Expression<'a>,
588    /// Span of "AS"
589    pub as_span: Span,
590    /// Type to cast to
591    pub type_: DataType<'a>,
592}
593
594impl Spanned for CastExpression<'_> {
595    fn span(&self) -> Span {
596        self.cast_span
597            .join_span(&self.expr)
598            .join_span(&self.as_span)
599            .join_span(&self.type_)
600    }
601}
602
603/// Convert expression (CONVERT(expr, type) or CONVERT(expr USING charset))
604#[derive(Debug, Clone)]
605pub struct ConvertExpression<'a> {
606    /// Span of "CONVERT"
607    pub convert_span: Span,
608    /// Value to convert
609    pub expr: Expression<'a>,
610    /// Type to convert to (for CONVERT(expr, type))
611    pub type_: Option<DataType<'a>>,
612    /// Charset (for CONVERT(expr USING charset))
613    pub using_charset: Option<(Span, Identifier<'a>)>,
614}
615
616impl Spanned for ConvertExpression<'_> {
617    fn span(&self) -> Span {
618        self.convert_span
619            .join_span(&self.expr)
620            .join_span(&self.type_)
621            .join_span(&self.using_charset)
622    }
623}
624
625/// PostgreSQL-style typecast expression (expr::type)
626#[derive(Debug, Clone)]
627pub struct TypeCastExpression<'a> {
628    /// The expression being cast
629    pub expr: Expression<'a>,
630    /// Span of "::"
631    pub doublecolon_span: Span,
632    /// Type to cast to
633    pub type_: DataType<'a>,
634}
635
636impl Spanned for TypeCastExpression<'_> {
637    fn span(&self) -> Span {
638        self.expr
639            .span()
640            .join_span(&self.doublecolon_span)
641            .join_span(&self.type_)
642    }
643}
644
645/// PostgreSQL ARRAY[...] literal expression
646#[derive(Debug, Clone)]
647pub struct ArrayExpression<'a> {
648    /// Span of the "ARRAY" keyword
649    pub array_span: Span,
650    /// Span of the bracket region "[...]"
651    pub bracket_span: Span,
652    /// The element expressions
653    pub elements: Vec<Expression<'a>>,
654}
655
656impl Spanned for ArrayExpression<'_> {
657    fn span(&self) -> Span {
658        self.array_span.join_span(&self.bracket_span)
659    }
660}
661
662/// Array subscript or slice expression: expr[idx] or expr[lower:upper]
663#[derive(Debug, Clone)]
664pub struct ArraySubscriptExpression<'a> {
665    /// The array expression being subscripted
666    pub expr: Expression<'a>,
667    /// Span of the "[...]" bracket region
668    pub bracket_span: Span,
669    /// The lower bound / index
670    pub lower: Expression<'a>,
671    /// The upper bound for slice notation (expr[lower:upper])
672    pub upper: Option<Expression<'a>>,
673}
674
675impl Spanned for ArraySubscriptExpression<'_> {
676    fn span(&self) -> Span {
677        self.expr.span().join_span(&self.bracket_span)
678    }
679}
680
681/// PostgreSQL composite type field access: (expr).field
682#[derive(Debug, Clone)]
683pub struct FieldAccessExpression<'a> {
684    /// The expression whose field is accessed
685    pub expr: Expression<'a>,
686    /// Span of the "."
687    pub dot_span: Span,
688    /// The field name
689    pub field: Identifier<'a>,
690}
691
692impl Spanned for FieldAccessExpression<'_> {
693    fn span(&self) -> Span {
694        self.expr
695            .span()
696            .join_span(&self.dot_span)
697            .join_span(&self.field)
698    }
699}
700
701/// Group contat expression
702#[derive(Debug, Clone)]
703pub struct GroupConcatExpression<'a> {
704    /// Span of "GROUP_CONCAT"
705    pub group_concat_span: Span,
706    /// Span of "DISTINCT" if specified
707    pub distinct_span: Option<Span>,
708    /// Expression to count
709    pub expr: Expression<'a>,
710}
711
712impl Spanned for GroupConcatExpression<'_> {
713    fn span(&self) -> Span {
714        self.group_concat_span
715            .join_span(&self.distinct_span)
716            .join_span(&self.expr)
717    }
718}
719
720/// Variable expression
721#[derive(Debug, Clone)]
722pub struct VariableExpression<'a> {
723    /// Span of "@@GLOBAL"
724    pub global: Option<Span>,
725    /// Span of "@@SESSION"
726    pub session: Option<Span>,
727    /// Span of '.'
728    pub dot: Option<Span>,
729    /// variable
730    pub variable: Variable<'a>,
731    // Span of variable
732    pub variable_span: Span,
733}
734
735impl Spanned for VariableExpression<'_> {
736    fn span(&self) -> Span {
737        self.variable_span
738            .join_span(&self.global)
739            .join_span(&self.session)
740            .join_span(&self.dot)
741    }
742}
743
744/// User variable expression (@variable_name)
745#[derive(Debug, Clone)]
746pub struct UserVariableExpression<'a> {
747    /// The variable name
748    pub name: Identifier<'a>,
749    /// Span of '@'
750    pub at_span: Span,
751}
752
753impl Spanned for UserVariableExpression<'_> {
754    fn span(&self) -> Span {
755        self.at_span.join_span(&self.name)
756    }
757}
758
759/// Timestampadd call
760#[derive(Debug, Clone)]
761pub struct TimestampAddExpression<'a> {
762    /// Span of "TIMESTAMPADD"
763    pub timestamp_add_span: Span,
764    /// Unit of the interval
765    pub unit: (TimeUnit, Span),
766    /// Interval expression
767    pub interval: Expression<'a>,
768    /// Datetime expression
769    pub datetime: Expression<'a>,
770}
771
772impl Spanned for TimestampAddExpression<'_> {
773    fn span(&self) -> Span {
774        self.timestamp_add_span
775            .join_span(&self.unit.1)
776            .join_span(&self.interval)
777            .join_span(&self.datetime)
778    }
779}
780
781/// Timestampdiff call
782#[derive(Debug, Clone)]
783pub struct TimestampDiffExpression<'a> {
784    /// Span of "TIMESTAMPDIFF"
785    pub timestamp_diff_span: Span,
786    /// Unit of the interval
787    pub unit: (TimeUnit, Span),
788    /// First expression
789    pub e1: Expression<'a>,
790    /// Second expression
791    pub e2: Expression<'a>,
792}
793
794impl Spanned for TimestampDiffExpression<'_> {
795    fn span(&self) -> Span {
796        self.timestamp_diff_span
797            .join_span(&self.unit.1)
798            .join_span(&self.e1)
799            .join_span(&self.e2)
800    }
801}
802
803/// Full-text MATCH ... AGAINST expression
804#[derive(Debug, Clone)]
805pub struct MatchAgainstExpression<'a> {
806    /// Span of "MATCH"
807    pub match_span: Span,
808    /// Columns to match against
809    pub columns: Vec<Expression<'a>>,
810    /// Span of "AGAINST"
811    pub against_span: Span,
812    /// Expression to match against
813    pub expr: Expression<'a>,
814    /// Match mode
815    pub mode: Option<MatchMode>,
816}
817
818impl Spanned for MatchAgainstExpression<'_> {
819    fn span(&self) -> Span {
820        self.match_span
821            .join_span(&self.columns)
822            .join_span(&self.against_span)
823            .join_span(&self.expr)
824            .join_span(&self.mode)
825    }
826}
827
828/// Is expression
829#[derive(Debug, Clone)]
830pub struct IsExpression<'a> {
831    /// Left hand side expression
832    pub lhs: Expression<'a>,
833    /// Type of is expression
834    pub is: Is<'a>,
835    /// Span of "IS" and "NOT"
836    pub is_span: Span,
837}
838
839impl<'a> Spanned for IsExpression<'a> {
840    fn span(&self) -> Span {
841        match &self.is {
842            Is::DistinctFrom(rhs) | Is::NotDistinctFrom(rhs) => {
843                self.lhs.span().join_span(&self.is_span).join_span(rhs)
844            }
845            _ => self.lhs.span().join_span(&self.is_span),
846        }
847    }
848}
849
850/// Literal NULL expression
851#[derive(Debug, Clone)]
852pub struct NullExpression {
853    /// Span of "NULL"
854    pub span: Span,
855}
856
857impl Spanned for NullExpression {
858    fn span(&self) -> Span {
859        self.span.clone()
860    }
861}
862
863/// Literal DEFAULT expression
864#[derive(Debug, Clone)]
865pub struct DefaultExpression {
866    /// Span of "DEFAULT"
867    pub span: Span,
868}
869
870impl Spanned for DefaultExpression {
871    fn span(&self) -> Span {
872        self.span.clone()
873    }
874}
875
876/// Literal bool expression "TRUE" or "FALSE"
877#[derive(Debug, Clone)]
878pub struct BoolExpression {
879    /// The boolean value
880    pub value: bool,
881    /// Span of "TRUE" or "FALSE"
882    pub span: Span,
883}
884
885impl Spanned for BoolExpression {
886    fn span(&self) -> Span {
887        self.span.clone()
888    }
889}
890
891/// Literal integer expression
892#[derive(Debug, Clone)]
893pub struct IntegerExpression {
894    /// The integer value
895    pub value: u64,
896    /// Span of the integer
897    pub span: Span,
898}
899
900impl Spanned for IntegerExpression {
901    fn span(&self) -> Span {
902        self.span.clone()
903    }
904}
905
906/// Literal _LIST_ expression
907#[derive(Debug, Clone)]
908pub struct ListHackExpression {
909    /// The index of the list
910    pub index: usize,
911    /// Span of the list
912    pub span: Span,
913}
914
915impl Spanned for ListHackExpression {
916    fn span(&self) -> Span {
917        self.span.clone()
918    }
919}
920
921/// Literal floating point expression
922#[derive(Debug, Clone)]
923pub struct FloatExpression {
924    /// The floating point value
925    pub value: f64,
926    /// Span of the floating point
927    pub span: Span,
928}
929
930impl Spanned for FloatExpression {
931    fn span(&self) -> Span {
932        self.span.clone()
933    }
934}
935
936/// Input argument to query, the first argument is the occurrence number of the argument
937#[derive(Debug, Clone)]
938pub struct ArgExpression {
939    /// The occurrence number of the argument
940    pub index: usize,
941    /// Span of the argument
942    pub span: Span,
943}
944
945impl Spanned for ArgExpression {
946    fn span(&self) -> Span {
947        self.span.clone()
948    }
949}
950
951/// Invalid expression, returned on recovery of a parse error
952#[derive(Debug, Clone)]
953pub struct InvalidExpression {
954    /// Span of the invalid expression
955    pub span: Span,
956}
957
958impl Spanned for InvalidExpression {
959    fn span(&self) -> Span {
960        self.span.clone()
961    }
962}
963
964/// Identifier pointing to column
965#[derive(Debug, Clone)]
966pub struct IdentifierExpression<'a> {
967    /// The identifier  parts, for example in "a.b.*" the parts are "a", "b" and "*"
968    pub parts: Vec<IdentifierPart<'a>>,
969}
970
971impl<'a> Spanned for IdentifierExpression<'a> {
972    fn span(&self) -> Span {
973        self.parts.opt_span().expect("Span of identifier parts")
974    }
975}
976
977/// Subquery expression
978#[derive(Debug, Clone)]
979pub struct SubqueryExpression<'a> {
980    /// The subquery
981    pub expression: Statement<'a>,
982}
983
984impl Spanned for SubqueryExpression<'_> {
985    fn span(&self) -> Span {
986        self.expression.span()
987    }
988}
989
990/// Exists expression
991#[derive(Debug, Clone)]
992pub struct ExistsExpression<'a> {
993    /// Span of "EXISTS"
994    pub exists_span: Span,
995    /// The subquery
996    pub subquery: Statement<'a>,
997}
998
999impl Spanned for ExistsExpression<'_> {
1000    fn span(&self) -> Span {
1001        self.exists_span.join_span(&self.subquery)
1002    }
1003}
1004
1005/// Which row quantifier keyword was used
1006#[derive(Debug, Clone, PartialEq, Eq)]
1007pub enum Quantifier {
1008    /// ANY(subquery_or_array)
1009    Any(Span),
1010    /// SOME(subquery_or_array) — synonym for ANY in PostgreSQL
1011    Some(Span),
1012    /// ALL(subquery_or_array)
1013    All(Span),
1014}
1015
1016impl Spanned for Quantifier {
1017    fn span(&self) -> Span {
1018        match self {
1019            Quantifier::Any(s) | Quantifier::Some(s) | Quantifier::All(s) => s.clone(),
1020        }
1021    }
1022}
1023
1024/// PostgreSQL ANY / SOME / ALL quantifier expression.
1025///
1026/// Appears as the right-hand operand of a comparison:
1027/// `expr op ANY (subquery_or_array)`
1028#[derive(Debug, Clone)]
1029pub struct QuantifierExpression<'a> {
1030    /// Which quantifier keyword was written
1031    pub quantifier: Quantifier,
1032    /// The operand — either a subquery expression or an array expression
1033    pub operand: Expression<'a>,
1034}
1035
1036impl Spanned for QuantifierExpression<'_> {
1037    fn span(&self) -> Span {
1038        self.quantifier.join_span(&self.operand)
1039    }
1040}
1041
1042/// A row/tuple constructor expression: `(expr1, expr2, ...)`
1043#[derive(Debug, Clone)]
1044pub struct RowExpression<'a> {
1045    /// Span of the surrounding parentheses
1046    pub paren_span: Span,
1047    /// Elements of the tuple
1048    pub elements: Vec<Expression<'a>>,
1049}
1050
1051impl Spanned for RowExpression<'_> {
1052    fn span(&self) -> Span {
1053        self.paren_span.clone()
1054    }
1055}
1056
1057/// Representation of an expression
1058#[derive(Debug, Clone)]
1059pub enum Expression<'a> {
1060    /// Expression with binary operator
1061    Binary(Box<BinaryExpression<'a>>),
1062    /// Expression with a unary (prefix) operator
1063    Unary(Box<UnaryExpression<'a>>),
1064    /// Subquery expression
1065    Subquery(Box<SubqueryExpression<'a>>),
1066    /// Literal NULL expression
1067    Null(Box<NullExpression>),
1068    /// Literal DEFAULT expression
1069    Default(Box<DefaultExpression>),
1070    /// Literal bool expression "TRUE" or "FALSE"
1071    Bool(Box<BoolExpression>),
1072    /// Literal string expression, the SString contains the represented string
1073    /// with escaping removed
1074    String(Box<SString<'a>>),
1075    /// Literal integer expression
1076    Integer(Box<IntegerExpression>),
1077    /// Literal _LIST_
1078    ListHack(Box<ListHackExpression>),
1079    /// Literal floating point expression
1080    Float(Box<FloatExpression>),
1081    /// Function call expression,
1082    Function(Box<FunctionCallExpression<'a>>),
1083    /// A window function call expression
1084    WindowFunction(Box<WindowFunctionCallExpression<'a>>),
1085    /// Aggregate function call expression with optional DISTINCT/FILTER/OVER
1086    AggregateFunction(Box<AggregateFunctionCallExpression<'a>>),
1087    /// Identifier pointing to column
1088    Identifier(Box<IdentifierExpression<'a>>),
1089    /// Time Interval
1090    Interval(Box<IntervalExpression>),
1091    /// Input argument to query, the first argument is the occurrence number of the argument
1092    Arg(Box<ArgExpression>),
1093    /// Exists expression
1094    Exists(Box<ExistsExpression<'a>>),
1095    /// Extract expression
1096    Extract(Box<ExtractExpression<'a>>),
1097    /// Trim expression
1098    Trim(Box<TrimExpression<'a>>),
1099    /// In expression
1100    In(Box<InExpression<'a>>),
1101    /// Between expression
1102    Between(Box<BetweenExpression<'a>>),
1103    /// Member of expression
1104    MemberOf(Box<MemberOfExpression<'a>>),
1105    /// Is expression
1106    Is(Box<IsExpression<'a>>),
1107    /// Invalid expression, returned on recovery of a parse error
1108    Invalid(Box<InvalidExpression>),
1109    /// Case expression
1110    Case(Box<CaseExpression<'a>>),
1111    /// Cast expression
1112    Cast(Box<CastExpression<'a>>),
1113    /// Convert expression (CONVERT(expr, type) or CONVERT(expr USING charset))
1114    Convert(Box<ConvertExpression<'a>>),
1115    /// Group contat expression
1116    GroupConcat(Box<GroupConcatExpression<'a>>),
1117    /// Variable expression
1118    Variable(Box<VariableExpression<'a>>),
1119    /// User variable expression (@variable_name)
1120    UserVariable(Box<UserVariableExpression<'a>>),
1121    /// Timestampadd call
1122    TimestampAdd(Box<TimestampAddExpression<'a>>),
1123    /// Timestampdiff call
1124    TimestampDiff(Box<TimestampDiffExpression<'a>>),
1125    /// PostgreSQL-style typecast expression (expr::type)
1126    TypeCast(Box<TypeCastExpression<'a>>),
1127    /// Full-text MATCH ... AGAINST expression
1128    MatchAgainst(Box<MatchAgainstExpression<'a>>),
1129    /// PostgreSQL ARRAY[...] literal expression
1130    Array(Box<ArrayExpression<'a>>),
1131    /// Array subscript / slice expression: expr[idx] or expr[lower:upper]
1132    ArraySubscript(Box<ArraySubscriptExpression<'a>>),
1133    /// PostgreSQL ANY / SOME / ALL quantifier: ANY(subquery_or_array)
1134    Quantifier(Box<QuantifierExpression<'a>>),
1135    /// PostgreSQL composite type field access: (expr).field
1136    FieldAccess(Box<FieldAccessExpression<'a>>),
1137    /// CHAR(N,... [USING charset_name]) expression
1138    Char(Box<CharFunctionExpression<'a>>),
1139    /// Row / tuple constructor: `(expr1, expr2, ...)`
1140    Row(Box<RowExpression<'a>>),
1141}
1142
1143impl<'a> Spanned for Expression<'a> {
1144    fn span(&self) -> Span {
1145        match &self {
1146            Expression::Binary(e) => e.span(),
1147            Expression::Unary(e) => e.span(),
1148            Expression::Subquery(v) => v.span(),
1149            Expression::Null(v) => v.span(),
1150            Expression::Default(v) => v.span(),
1151            Expression::Bool(v) => v.span(),
1152            Expression::String(v) => v.span(),
1153            Expression::Integer(v) => v.span(),
1154            Expression::Float(v) => v.span(),
1155            Expression::ListHack(v) => v.span(),
1156            Expression::Function(e) => e.span(),
1157            Expression::AggregateFunction(e) => e.span(),
1158            Expression::Identifier(e) => e.span(),
1159            Expression::Arg(v) => v.span(),
1160            Expression::Exists(v) => v.span(),
1161            Expression::In(e) => e.span(),
1162            Expression::Between(e) => e.span(),
1163            Expression::MemberOf(e) => e.span(),
1164            Expression::Is(e) => e.span(),
1165            Expression::Invalid(s) => s.span(),
1166            Expression::Case(e) => e.span(),
1167            Expression::Cast(e) => e.span(),
1168            Expression::Convert(e) => e.span(),
1169            Expression::TypeCast(e) => e.span(),
1170            Expression::GroupConcat(e) => e.span(),
1171            Expression::Variable(e) => e.span(),
1172            Expression::UserVariable(e) => e.span(),
1173            Expression::WindowFunction(e) => e.span(),
1174            Expression::Interval(e) => e.span(),
1175            Expression::Extract(e) => e.span(),
1176            Expression::Trim(e) => e.span(),
1177            Expression::TimestampAdd(e) => e.span(),
1178            Expression::TimestampDiff(e) => e.span(),
1179            Expression::MatchAgainst(e) => e.span(),
1180            Expression::Array(e) => e.span(),
1181            Expression::ArraySubscript(e) => e.span(),
1182            Expression::Quantifier(e) => e.span(),
1183            Expression::FieldAccess(e) => e.span(),
1184            Expression::Char(e) => e.span(),
1185            Expression::Row(e) => e.span(),
1186        }
1187    }
1188}
1189
1190// Operator parsing priority table.
1191// Lower number = tighter binding (reduced later, applied first).
1192// An operator is only parsed when its priority < max_priority passed to the parser.
1193pub(crate) const PRIORITY_TYPECAST: usize = 10; // ::
1194pub(crate) const PRIORITY_JSON_EXTRACT: usize = 30; // -> ->>
1195pub(crate) const PRIORITY_BITXOR: usize = 50; // ^ (XOR bitwise)
1196pub(crate) const PRIORITY_MULT: usize = 60; // * / % DIV MOD
1197pub(crate) const PRIORITY_ADD: usize = 70; // + -
1198pub(crate) const PRIORITY_PG_CUSTOM: usize = 75; // PostgreSQL custom / user-defined operators
1199pub(crate) const PRIORITY_SHIFT: usize = 80; // << >>
1200pub(crate) const PRIORITY_BITAND: usize = 90; // &
1201pub(crate) const PRIORITY_BITOR: usize = 100; // |
1202pub(crate) const PRIORITY_CMP: usize = 110; // = != < > <= >= IS IN LIKE BETWEEN SIMILAR TO ...
1203pub(crate) const PRIORITY_AND: usize = 140; // AND  (tighter than OR)
1204pub(crate) const PRIORITY_XOR: usize = 150; // XOR (keyword logical XOR)
1205pub(crate) const PRIORITY_OR: usize = 160; // OR   (loosest binary operator)
1206pub(crate) const PRIORITY_ASSIGN: usize = 200; // :=
1207
1208/// Parse all operators (no restriction).
1209pub(crate) const PRIORITY_MAX: usize = usize::MAX;
1210
1211trait Priority {
1212    fn priority(&self) -> usize;
1213}
1214
1215impl<'a> Priority for BinaryOperator<'a> {
1216    fn priority(&self) -> usize {
1217        match self {
1218            BinaryOperator::Assignment(_) => PRIORITY_ASSIGN,
1219            BinaryOperator::Or(_) => PRIORITY_OR,
1220            BinaryOperator::Concat(_) => PRIORITY_ADD,
1221            BinaryOperator::Xor(_) => PRIORITY_XOR,
1222            BinaryOperator::And(_) => PRIORITY_AND,
1223            BinaryOperator::Eq(_) => PRIORITY_CMP,
1224            BinaryOperator::NullSafeEq(_) => PRIORITY_CMP,
1225            BinaryOperator::GtEq(_) => PRIORITY_CMP,
1226            BinaryOperator::Gt(_) => PRIORITY_CMP,
1227            BinaryOperator::LtEq(_) => PRIORITY_CMP,
1228            BinaryOperator::Lt(_) => PRIORITY_CMP,
1229            BinaryOperator::Neq(_) => PRIORITY_CMP,
1230            BinaryOperator::Like(_) => PRIORITY_CMP,
1231            BinaryOperator::NotLike(_) => PRIORITY_CMP,
1232            BinaryOperator::Regexp(_) => PRIORITY_CMP,
1233            BinaryOperator::NotRegexp(_) => PRIORITY_CMP,
1234            BinaryOperator::Rlike(_) => PRIORITY_CMP,
1235            BinaryOperator::NotRlike(_) => PRIORITY_CMP,
1236            BinaryOperator::ShiftLeft(_) => PRIORITY_SHIFT,
1237            BinaryOperator::ShiftRight(_) => PRIORITY_SHIFT,
1238            BinaryOperator::BitAnd(_) => PRIORITY_BITAND,
1239            BinaryOperator::BitOr(_) => PRIORITY_BITOR,
1240            BinaryOperator::BitXor(_) => PRIORITY_BITXOR,
1241            BinaryOperator::Add(_) => PRIORITY_ADD,
1242            BinaryOperator::Subtract(_) => PRIORITY_ADD,
1243            BinaryOperator::Divide(_) => PRIORITY_MULT,
1244            BinaryOperator::Div(_) => PRIORITY_MULT,
1245            BinaryOperator::Mod(_) => PRIORITY_MULT,
1246            BinaryOperator::Mult(_) => PRIORITY_MULT,
1247            BinaryOperator::Collate(_) => 20,
1248            BinaryOperator::JsonExtract(_) => PRIORITY_JSON_EXTRACT,
1249            BinaryOperator::JsonExtractUnquote(_) => PRIORITY_JSON_EXTRACT,
1250            BinaryOperator::Overlap(_)
1251            | BinaryOperator::Contains(_)
1252            | BinaryOperator::ContainedBy(_)
1253            | BinaryOperator::JsonPathMatch(_)
1254            | BinaryOperator::JsonPathExists(_)
1255            | BinaryOperator::JsonbKeyExists(_)
1256            | BinaryOperator::JsonbAnyKeyExists(_)
1257            | BinaryOperator::JsonbAllKeyExists(_)
1258            | BinaryOperator::JsonGetPath(_)
1259            | BinaryOperator::JsonGetPathText(_)
1260            | BinaryOperator::JsonDeletePath(_)
1261            | BinaryOperator::RegexMatch(_)
1262            | BinaryOperator::RegexIMatch(_)
1263            | BinaryOperator::NotRegexMatch(_)
1264            | BinaryOperator::NotRegexIMatch(_)
1265            | BinaryOperator::User(_, _)
1266            | BinaryOperator::Operator(_, _) => PRIORITY_PG_CUSTOM,
1267        }
1268    }
1269}
1270
1271impl Priority for UnaryOperator {
1272    fn priority(&self) -> usize {
1273        match self {
1274            UnaryOperator::Binary(_) => 20,
1275            UnaryOperator::LogicalNot(_) => 30,
1276            UnaryOperator::Minus(_) => 40,
1277            UnaryOperator::Not(_) => 130,
1278        }
1279    }
1280}
1281
1282#[derive(Debug)]
1283enum ReduceMember<'a> {
1284    Expression(Expression<'a>),
1285    Binary(BinaryOperator<'a>),
1286    Unary(UnaryOperator),
1287}
1288
1289struct Reducer<'a> {
1290    stack: Vec<ReduceMember<'a>>,
1291}
1292
1293impl<'a> Reducer<'a> {
1294    fn reduce(&mut self, priority: usize) -> Result<(), &'static str> {
1295        let mut e = match self.stack.pop() {
1296            Some(ReduceMember::Expression(e)) => e,
1297            _ => {
1298                return Err("Expected expression before here");
1299            }
1300        };
1301        loop {
1302            let v = self.stack.pop();
1303            match v {
1304                None => break,
1305                Some(ReduceMember::Expression(_)) => return Err("ICE Reduce stack error 1"),
1306                Some(ReduceMember::Unary(op)) if op.priority() > priority => {
1307                    self.stack.push(ReduceMember::Unary(op));
1308                    break;
1309                }
1310                Some(ReduceMember::Binary(op)) if op.priority() > priority => {
1311                    self.stack.push(ReduceMember::Binary(op));
1312                    break;
1313                }
1314                Some(ReduceMember::Unary(op)) => {
1315                    e = Expression::Unary(Box::new(UnaryExpression { op, operand: e }));
1316                }
1317                Some(ReduceMember::Binary(op)) => {
1318                    let lhs = match self.stack.pop() {
1319                        Some(ReduceMember::Expression(e)) => e,
1320                        _ => return Err("ICE Reduce stack error 2"),
1321                    };
1322                    e = Expression::Binary(Box::new(BinaryExpression { op, lhs, rhs: e }));
1323                }
1324            }
1325        }
1326        self.stack.push(ReduceMember::Expression(e));
1327        Ok(())
1328    }
1329
1330    fn shift_binop(&mut self, op: BinaryOperator<'a>) -> Result<(), &'static str> {
1331        self.reduce(op.priority())?;
1332        self.stack.push(ReduceMember::Binary(op));
1333        Ok(())
1334    }
1335
1336    fn shift_unary(&mut self, op: UnaryOperator) -> Result<(), &'static str> {
1337        if matches!(self.stack.last(), Some(ReduceMember::Expression(_))) {
1338            return Err("Unary operator cannot come before expression");
1339        }
1340        self.stack.push(ReduceMember::Unary(op));
1341        Ok(())
1342    }
1343
1344    fn shift_expr(&mut self, e: Expression<'a>) -> Result<(), &'static str> {
1345        if matches!(self.stack.last(), Some(ReduceMember::Expression(_))) {
1346            //panic!();
1347            return Err("Expression should not follow expression");
1348        }
1349        self.stack.push(ReduceMember::Expression(e));
1350        Ok(())
1351    }
1352}
1353
1354/// Parse a single element inside an ARRAY[...] literal.
1355/// If the current token is `[`, parses a nested sub-array `[elem, ...]` recursively.
1356/// Otherwise delegates to `parse_expression_unreserved`.
1357fn parse_array_element<'a>(parser: &mut Parser<'a, '_>) -> Result<Expression<'a>, ParseError> {
1358    if matches!(parser.token, Token::LBracket) {
1359        let lbracket = parser.consume_token(Token::LBracket)?;
1360        let mut elements = Vec::new();
1361        if !matches!(parser.token, Token::RBracket) {
1362            loop {
1363                parser.recovered(
1364                    "']' or ','",
1365                    &|t| matches!(t, Token::RBracket | Token::Comma),
1366                    |parser| {
1367                        elements.push(parse_array_element(parser)?);
1368                        Ok(())
1369                    },
1370                )?;
1371                if parser.skip_token(Token::Comma).is_none() {
1372                    break;
1373                }
1374            }
1375        }
1376        let rbracket = parser.consume_token(Token::RBracket)?;
1377        let bracket_span = lbracket.join_span(&rbracket);
1378        Ok(Expression::Array(Box::new(ArrayExpression {
1379            array_span: bracket_span.clone(),
1380            bracket_span,
1381            elements,
1382        })))
1383    } else {
1384        parse_expression_unreserved(parser, PRIORITY_MAX)
1385    }
1386}
1387
1388pub(crate) fn parse_expression_restricted<'a>(
1389    parser: &mut Parser<'a, '_>,
1390    max_priority: usize,
1391    restrict: Restrict,
1392) -> Result<Expression<'a>, ParseError> {
1393    let mut r = Reducer { stack: Vec::new() };
1394    loop {
1395        if matches!(r.stack.last(), Some(ReduceMember::Expression(_)))
1396            && matches!(
1397                parser.token,
1398                Token::Ident(
1399                    _,
1400                    Keyword::NULLS
1401                        | Keyword::FIRST
1402                        | Keyword::LAST
1403                        | Keyword::ROW
1404                        | Keyword::ROWS
1405                        | Keyword::RANGE
1406                        | Keyword::ONLY
1407                        | Keyword::FILTER
1408                        | Keyword::PRECEDING
1409                        | Keyword::FOLLOWING
1410                )
1411            )
1412        {
1413            break;
1414        }
1415        // `NOT NULL` is a column constraint, not an expression operator
1416        // (e.g. `DEFAULT (foo())::TEXT NOT NULL`).  Break before consuming
1417        // the NOT so the caller can handle NOT NULL as a constraint.
1418        if matches!(r.stack.last(), Some(ReduceMember::Expression(_)))
1419            && matches!(parser.token, Token::Ident(_, Keyword::NOT))
1420            && matches!(parser.peek(), Token::Ident(_, Keyword::NULL))
1421        {
1422            break;
1423        }
1424        let e = match parser.token.clone() {
1425            Token::ColonEq if PRIORITY_ASSIGN < max_priority => {
1426                r.shift_binop(BinaryOperator::Assignment(parser.consume()))
1427            }
1428            Token::Ident(_, Keyword::OR) if PRIORITY_OR < max_priority => {
1429                r.shift_binop(BinaryOperator::Or(parser.consume()))
1430            }
1431            Token::DoublePipe if PRIORITY_ADD < max_priority => {
1432                r.shift_binop(BinaryOperator::Concat(parser.consume()))
1433            }
1434            Token::Ident(_, Keyword::XOR) if PRIORITY_XOR < max_priority => {
1435                r.shift_binop(BinaryOperator::Xor(parser.consume()))
1436            }
1437            Token::Ident(_, Keyword::AND) if PRIORITY_AND < max_priority => {
1438                r.shift_binop(BinaryOperator::And(parser.consume()))
1439            }
1440            Token::DoubleAmpersand
1441                if PRIORITY_AND < max_priority && !parser.options.dialect.is_postgresql() =>
1442            {
1443                r.shift_binop(BinaryOperator::And(parser.consume()))
1444            }
1445            Token::DoubleAmpersand
1446                if PRIORITY_PG_CUSTOM < max_priority && parser.options.dialect.is_postgresql() =>
1447            {
1448                r.shift_binop(BinaryOperator::Overlap(parser.consume()))
1449            }
1450            Token::Eq if PRIORITY_CMP < max_priority => {
1451                r.shift_binop(BinaryOperator::Eq(parser.consume()))
1452            }
1453            Token::Spaceship if PRIORITY_CMP < max_priority => {
1454                r.shift_binop(BinaryOperator::NullSafeEq(parser.consume()))
1455            }
1456            Token::GtEq if PRIORITY_CMP < max_priority => {
1457                r.shift_binop(BinaryOperator::GtEq(parser.consume()))
1458            }
1459            Token::Gt if PRIORITY_CMP < max_priority => {
1460                r.shift_binop(BinaryOperator::Gt(parser.consume()))
1461            }
1462            Token::LtEq if PRIORITY_CMP < max_priority => {
1463                r.shift_binop(BinaryOperator::LtEq(parser.consume()))
1464            }
1465            Token::Lt if PRIORITY_CMP < max_priority => {
1466                r.shift_binop(BinaryOperator::Lt(parser.consume()))
1467            }
1468            Token::Neq if PRIORITY_CMP < max_priority => {
1469                r.shift_binop(BinaryOperator::Neq(parser.consume()))
1470            }
1471            Token::ShiftLeft if PRIORITY_SHIFT < max_priority => {
1472                r.shift_binop(BinaryOperator::ShiftLeft(parser.consume()))
1473            }
1474            Token::ShiftRight if PRIORITY_SHIFT < max_priority => {
1475                r.shift_binop(BinaryOperator::ShiftRight(parser.consume()))
1476            }
1477            Token::Ampersand => r.shift_binop(BinaryOperator::BitAnd(parser.consume())),
1478            Token::Pipe if PRIORITY_BITOR < max_priority => {
1479                r.shift_binop(BinaryOperator::BitOr(parser.consume()))
1480            }
1481            Token::Ident(_, Keyword::BINARY) if PRIORITY_JSON_EXTRACT < max_priority => {
1482                r.shift_unary(UnaryOperator::Binary(parser.consume()))
1483            }
1484            Token::Ident(_, Keyword::COLLATE)
1485                if 20 < max_priority
1486                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1487            {
1488                // COLLATE is a binary operator: expr COLLATE collation_name
1489                let collate_span = parser.consume_keyword(Keyword::COLLATE)?;
1490                let collation = parser.consume_plain_identifier_unreserved()?;
1491                if let Err(e) = r.shift_binop(BinaryOperator::Collate(collate_span)) {
1492                    parser.err_here(e)?;
1493                }
1494                r.shift_expr(Expression::Identifier(Box::new(IdentifierExpression {
1495                    parts: vec![IdentifierPart::Name(collation)],
1496                })))
1497            }
1498            Token::ExclamationMark if PRIORITY_JSON_EXTRACT < max_priority => {
1499                r.shift_unary(UnaryOperator::LogicalNot(parser.consume()))
1500            }
1501            Token::Minus if !matches!(r.stack.last(), Some(ReduceMember::Expression(_))) => {
1502                r.shift_unary(UnaryOperator::Minus(parser.consume()))
1503            }
1504            Token::Minus
1505                if PRIORITY_ADD < max_priority
1506                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1507            {
1508                r.shift_binop(BinaryOperator::Subtract(parser.consume()))
1509            }
1510            Token::Ident(_, Keyword::IN) if PRIORITY_CMP < max_priority => {
1511                if let Err(e) = r.reduce(PRIORITY_CMP) {
1512                    parser.err_here(e)?;
1513                }
1514                let lhs = match r.stack.pop() {
1515                    Some(ReduceMember::Expression(e)) => e,
1516                    _ => parser.err_here("Expected expression before here 3")?,
1517                };
1518                let op = parser.consume_keyword(Keyword::IN)?;
1519                parser.consume_token(Token::LParen)?;
1520                let mut rhs = Vec::new();
1521                loop {
1522                    parser.recovered(
1523                        "')' or ','",
1524                        &|t| matches!(t, Token::RParen | Token::Comma),
1525                        |parser| {
1526                            rhs.push(parse_expression_paren(parser)?);
1527                            Ok(())
1528                        },
1529                    )?;
1530                    if parser.skip_token(Token::Comma).is_none() {
1531                        break;
1532                    }
1533                }
1534                parser.consume_token(Token::RParen)?;
1535                r.shift_expr(Expression::In(Box::new(InExpression {
1536                    lhs,
1537                    rhs,
1538                    in_span: op,
1539                    not_in: false,
1540                })))
1541            }
1542            Token::Ident(_, Keyword::IS) if PRIORITY_CMP < max_priority => {
1543                if let Err(e) = r.reduce(PRIORITY_CMP) {
1544                    parser.err_here(e)?;
1545                }
1546                let lhs = match r.stack.pop() {
1547                    Some(ReduceMember::Expression(e)) => e,
1548                    _ => parser.err_here("Expected expression before here 4")?,
1549                };
1550                let op = parser.consume_keyword(Keyword::IS)?;
1551                let (is, op) = match &parser.token {
1552                    Token::Ident(_, Keyword::NOT) => {
1553                        parser.consume();
1554                        match &parser.token {
1555                            Token::Ident(_, Keyword::TRUE) => {
1556                                (Is::NotTrue, parser.consume().join_span(&op))
1557                            }
1558                            Token::Ident(_, Keyword::FALSE) => {
1559                                (Is::NotFalse, parser.consume().join_span(&op))
1560                            }
1561                            Token::Ident(_, Keyword::NULL) => {
1562                                (Is::NotNull, parser.consume().join_span(&op))
1563                            }
1564                            Token::Ident(_, Keyword::UNKNOWN) => {
1565                                (Is::NotUnknown, parser.consume().join_span(&op))
1566                            }
1567                            Token::Ident(_, Keyword::DISTINCT) => {
1568                                let op_span = parser
1569                                    .consume_keywords(&[Keyword::DISTINCT, Keyword::FROM])?
1570                                    .join_span(&op);
1571                                parser.postgres_only(&op_span);
1572                                let rhs = parse_expression_unreserved(parser, PRIORITY_AND)?;
1573                                (Is::NotDistinctFrom(rhs), op_span)
1574                            }
1575                            _ => parser.expected_failure(
1576                                "'TRUE', 'FALSE', 'UNKNOWN', 'NULL' or 'DISTINCT'",
1577                            )?,
1578                        }
1579                    }
1580                    Token::Ident(_, Keyword::TRUE) => (Is::True, parser.consume().join_span(&op)),
1581                    Token::Ident(_, Keyword::FALSE) => (Is::False, parser.consume().join_span(&op)),
1582                    Token::Ident(_, Keyword::NULL) => (Is::Null, parser.consume().join_span(&op)),
1583                    Token::Ident(_, Keyword::DISTINCT) => {
1584                        let op_span = parser
1585                            .consume_keywords(&[Keyword::DISTINCT, Keyword::FROM])?
1586                            .join_span(&op);
1587                        parser.postgres_only(&op_span);
1588                        let rhs = parse_expression_unreserved(parser, PRIORITY_AND)?;
1589                        (Is::DistinctFrom(rhs), op_span)
1590                    }
1591                    Token::Ident(_, Keyword::UNKNOWN) => {
1592                        (Is::Unknown, parser.consume().join_span(&op))
1593                    }
1594                    _ => parser.expected_failure(
1595                        "'NOT', 'TRUE', 'FALSE', 'UNKNOWN', 'NULL' or 'DISTINCT'",
1596                    )?,
1597                };
1598                r.shift_expr(Expression::Is(Box::new(IsExpression {
1599                    lhs,
1600                    is,
1601                    is_span: op,
1602                })))
1603            }
1604            Token::DoubleColon
1605                if parser.options.dialect.is_postgresql()
1606                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1607            {
1608                // PostgreSQL typecast operator: expr::type
1609                // Reduce with very high priority (binds tighter than most operators)
1610                if let Err(e) = r.reduce(PRIORITY_TYPECAST) {
1611                    parser.err_here(e)?;
1612                }
1613                let expr = match r.stack.pop() {
1614                    Some(ReduceMember::Expression(e)) => e,
1615                    _ => parser.err_here("Expected expression before '::'")?,
1616                };
1617                let doublecolon_span = parser.consume_token(Token::DoubleColon)?;
1618                let type_ = parse_data_type(parser, DataTypeContext::TypeRef)?;
1619                r.shift_expr(Expression::TypeCast(Box::new(TypeCastExpression {
1620                    expr,
1621                    doublecolon_span,
1622                    type_,
1623                })))
1624            }
1625            Token::LBracket
1626                if parser.options.dialect.is_postgresql()
1627                    && PRIORITY_TYPECAST < max_priority
1628                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1629            {
1630                // Array subscript / slice: expr[idx] or expr[lower:upper]
1631                if let Err(e) = r.reduce(PRIORITY_TYPECAST) {
1632                    parser.err_here(e)?;
1633                }
1634                let expr = match r.stack.pop() {
1635                    Some(ReduceMember::Expression(e)) => e,
1636                    _ => parser.err_here("Expected expression before '['")?,
1637                };
1638                let lbracket = parser.consume_token(Token::LBracket)?;
1639                let lower = parse_expression_unreserved(parser, PRIORITY_MAX)?;
1640                let upper = if parser.skip_token(Token::Colon).is_some() {
1641                    Some(parse_expression_unreserved(parser, PRIORITY_MAX)?)
1642                } else {
1643                    None
1644                };
1645                let rbracket = parser.consume_token(Token::RBracket)?;
1646                let bracket_span = lbracket.join_span(&rbracket);
1647                r.shift_expr(Expression::ArraySubscript(Box::new(
1648                    ArraySubscriptExpression {
1649                        expr,
1650                        bracket_span,
1651                        lower,
1652                        upper,
1653                    },
1654                )))
1655            }
1656            Token::Period
1657                if parser.options.dialect.is_postgresql()
1658                    && PRIORITY_TYPECAST < max_priority
1659                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1660            {
1661                // PostgreSQL composite type field access: (expr).field
1662                if let Err(e) = r.reduce(PRIORITY_TYPECAST) {
1663                    parser.err_here(e)?;
1664                }
1665                let expr = match r.stack.pop() {
1666                    Some(ReduceMember::Expression(e)) => e,
1667                    _ => parser.err_here("Expected expression before '.'")?,
1668                };
1669                let dot_span = parser.consume_token(Token::Period)?;
1670                let field = parser.consume_plain_identifier_unreserved()?;
1671                r.shift_expr(Expression::FieldAccess(Box::new(FieldAccessExpression {
1672                    expr,
1673                    dot_span,
1674                    field,
1675                })))
1676            }
1677            Token::Ident(_, Keyword::NOT)
1678                if !matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1679            {
1680                r.shift_unary(UnaryOperator::Not(parser.consume()))
1681            }
1682            Token::Ident(_, Keyword::NOT)
1683                if PRIORITY_CMP < max_priority
1684                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1685            {
1686                if let Err(e) = r.reduce(PRIORITY_CMP) {
1687                    parser.err_here(e)?;
1688                }
1689                let lhs = match r.stack.pop() {
1690                    Some(ReduceMember::Expression(e)) => e,
1691                    _ => parser.err_here("Expected expression before here 2")?,
1692                };
1693                let op = parser.consume_keyword(Keyword::NOT)?;
1694                match &parser.token {
1695                    Token::Ident(_, Keyword::IN) => {
1696                        let op = parser.consume_keyword(Keyword::IN)?.join_span(&op);
1697                        parser.consume_token(Token::LParen)?;
1698                        let mut rhs = Vec::new();
1699                        loop {
1700                            parser.recovered(
1701                                "')' or ','",
1702                                &|t| matches!(t, Token::RParen | Token::Comma),
1703                                |parser| {
1704                                    rhs.push(parse_expression_paren(parser)?);
1705                                    Ok(())
1706                                },
1707                            )?;
1708                            if parser.skip_token(Token::Comma).is_none() {
1709                                break;
1710                            }
1711                        }
1712                        parser.consume_token(Token::RParen)?;
1713                        r.shift_expr(Expression::In(Box::new(InExpression {
1714                            lhs,
1715                            rhs,
1716                            in_span: op,
1717                            not_in: true,
1718                        })))
1719                    }
1720                    Token::Ident(_, Keyword::LIKE) => {
1721                        r.stack.push(ReduceMember::Expression(lhs));
1722                        r.shift_binop(BinaryOperator::NotLike(parser.consume().join_span(&op)))
1723                    }
1724                    Token::Ident(_, Keyword::REGEXP) if parser.options.dialect.is_maria() => {
1725                        r.stack.push(ReduceMember::Expression(lhs));
1726                        r.shift_binop(BinaryOperator::NotRegexp(parser.consume().join_span(&op)))
1727                    }
1728                    Token::Ident(_, Keyword::RLIKE) if parser.options.dialect.is_maria() => {
1729                        r.stack.push(ReduceMember::Expression(lhs));
1730                        r.shift_binop(BinaryOperator::NotRlike(parser.consume().join_span(&op)))
1731                    }
1732                    Token::Ident(_, Keyword::BETWEEN) => {
1733                        let between_span = parser.consume_keyword(Keyword::BETWEEN)?.join_span(&op);
1734                        let low = parse_expression_unreserved(parser, PRIORITY_AND)?;
1735                        let and_span = parser.consume_keyword(Keyword::AND)?;
1736                        let high = parse_expression_unreserved(parser, PRIORITY_AND)?;
1737                        r.shift_expr(Expression::Between(Box::new(BetweenExpression {
1738                            lhs,
1739                            low,
1740                            high,
1741                            between_span: between_span.join_span(&and_span),
1742                            not_between: true,
1743                        })))
1744                    }
1745                    _ => parser.expected_failure("'IN', 'LIKE', 'REGEXP', 'RLIKE' or 'BETWEEN'")?,
1746                }
1747            }
1748            Token::Ident(_, Keyword::BETWEEN)
1749                if PRIORITY_CMP < max_priority
1750                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1751            {
1752                if let Err(e) = r.reduce(PRIORITY_CMP) {
1753                    parser.err_here(e)?;
1754                }
1755                let lhs = match r.stack.pop() {
1756                    Some(ReduceMember::Expression(e)) => e,
1757                    _ => parser.err_here("Expected expression before BETWEEN")?,
1758                };
1759                let between_span = parser.consume_keyword(Keyword::BETWEEN)?;
1760                let low = parse_expression_unreserved(parser, PRIORITY_AND)?;
1761                let and_span = parser.consume_keyword(Keyword::AND)?;
1762                let high = parse_expression_unreserved(parser, PRIORITY_AND)?;
1763                r.shift_expr(Expression::Between(Box::new(BetweenExpression {
1764                    lhs,
1765                    low,
1766                    high,
1767                    between_span: between_span.join_span(&and_span),
1768                    not_between: false,
1769                })))
1770            }
1771            Token::Ident(_, Keyword::LIKE) if PRIORITY_CMP < max_priority => {
1772                r.shift_binop(BinaryOperator::Like(parser.consume()))
1773            }
1774            Token::Ident(_, Keyword::SIMILAR)
1775                if PRIORITY_CMP < max_priority
1776                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1777            {
1778                // SIMILAR TO expr (PostgreSQL)
1779                if let Err(e) = r.reduce(PRIORITY_CMP) {
1780                    parser.err_here(e)?;
1781                }
1782                let lhs = match r.stack.pop() {
1783                    Some(ReduceMember::Expression(e)) => e,
1784                    _ => parser.err_here("Expected expression before SIMILAR")?,
1785                };
1786                let op_span = parser.consume_keywords(&[Keyword::SIMILAR, Keyword::TO])?;
1787                parser.postgres_only(&op_span);
1788                r.stack.push(ReduceMember::Expression(lhs));
1789                r.shift_binop(BinaryOperator::Like(op_span))
1790            }
1791            Token::Ident(_, Keyword::REGEXP)
1792                if PRIORITY_CMP < max_priority && parser.options.dialect.is_maria() =>
1793            {
1794                r.shift_binop(BinaryOperator::Regexp(parser.consume()))
1795            }
1796            Token::Ident(_, Keyword::RLIKE)
1797                if PRIORITY_CMP < max_priority && parser.options.dialect.is_maria() =>
1798            {
1799                r.shift_binop(BinaryOperator::Rlike(parser.consume()))
1800            }
1801            Token::RArrowJson if PRIORITY_JSON_EXTRACT < max_priority => {
1802                r.shift_binop(BinaryOperator::JsonExtract(parser.consume()))
1803            }
1804            Token::RDoubleArrowJson if PRIORITY_JSON_EXTRACT < max_priority => {
1805                r.shift_binop(BinaryOperator::JsonExtractUnquote(parser.consume()))
1806            }
1807            // PostgreSQL built-in operator tokens
1808            Token::Contains if PRIORITY_PG_CUSTOM < max_priority => {
1809                r.shift_binop(BinaryOperator::Contains(parser.consume()))
1810            }
1811            Token::ContainedBy if PRIORITY_PG_CUSTOM < max_priority => {
1812                r.shift_binop(BinaryOperator::ContainedBy(parser.consume()))
1813            }
1814            Token::AtQuestion if PRIORITY_PG_CUSTOM < max_priority => {
1815                r.shift_binop(BinaryOperator::JsonPathExists(parser.consume()))
1816            }
1817            Token::QuestionPipe if PRIORITY_PG_CUSTOM < max_priority => {
1818                r.shift_binop(BinaryOperator::JsonbAnyKeyExists(parser.consume()))
1819            }
1820            Token::QuestionAmpersand if PRIORITY_PG_CUSTOM < max_priority => {
1821                r.shift_binop(BinaryOperator::JsonbAllKeyExists(parser.consume()))
1822            }
1823            Token::HashArrow if PRIORITY_PG_CUSTOM < max_priority => {
1824                r.shift_binop(BinaryOperator::JsonGetPath(parser.consume()))
1825            }
1826            Token::HashDoubleArrow if PRIORITY_PG_CUSTOM < max_priority => {
1827                r.shift_binop(BinaryOperator::JsonGetPathText(parser.consume()))
1828            }
1829            Token::HashMinus if PRIORITY_PG_CUSTOM < max_priority => {
1830                r.shift_binop(BinaryOperator::JsonDeletePath(parser.consume()))
1831            }
1832            Token::TildeStar if PRIORITY_PG_CUSTOM < max_priority => {
1833                r.shift_binop(BinaryOperator::RegexIMatch(parser.consume()))
1834            }
1835            Token::NotTilde if PRIORITY_PG_CUSTOM < max_priority => {
1836                r.shift_binop(BinaryOperator::NotRegexMatch(parser.consume()))
1837            }
1838            Token::NotTildeStar if PRIORITY_PG_CUSTOM < max_priority => {
1839                r.shift_binop(BinaryOperator::NotRegexIMatch(parser.consume()))
1840            }
1841            Token::LikeTilde if PRIORITY_CMP < max_priority => {
1842                r.shift_binop(BinaryOperator::Like(parser.consume()))
1843            }
1844            Token::NotLikeTilde if PRIORITY_CMP < max_priority => {
1845                r.shift_binop(BinaryOperator::NotLike(parser.consume()))
1846            }
1847            // @@ as binary (full-text / jsonpath match)
1848            Token::AtAt
1849                if PRIORITY_PG_CUSTOM < max_priority
1850                    && parser.options.dialect.is_postgresql()
1851                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1852            {
1853                r.shift_binop(BinaryOperator::JsonPathMatch(parser.consume()))
1854            }
1855            // ~ as binary regex match (only when expression already on left)
1856            Token::Tilde
1857                if PRIORITY_PG_CUSTOM < max_priority
1858                    && parser.options.dialect.is_postgresql()
1859                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1860            {
1861                r.shift_binop(BinaryOperator::RegexMatch(parser.consume()))
1862            }
1863            // ? as jsonb key-exists binary operator (PG, non-argument mode)
1864            Token::QuestionMark
1865                if PRIORITY_PG_CUSTOM < max_priority
1866                    && parser.options.dialect.is_postgresql()
1867                    && !matches!(parser.options.arguments, crate::SQLArguments::QuestionMark)
1868                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1869            {
1870                r.shift_binop(BinaryOperator::JsonbKeyExists(parser.consume()))
1871            }
1872            // Remaining user-defined PostgreSQL operators
1873            Token::PostgresOperator(op)
1874                if PRIORITY_PG_CUSTOM < max_priority
1875                    && parser.options.dialect.is_postgresql()
1876                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1877            {
1878                r.shift_binop(BinaryOperator::User(op, parser.consume()))
1879            }
1880            Token::Ident(_, Keyword::OPERATOR)
1881                if PRIORITY_PG_CUSTOM < max_priority
1882                    && parser.options.dialect.is_postgresql()
1883                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1884            {
1885                let operator_span = parser.consume_keyword(Keyword::OPERATOR)?;
1886                parser.consume_token(Token::LParen)?;
1887                let op_name = parse_operator_name(parser)?;
1888                let rparen_span = parser.consume_token(Token::RParen)?;
1889                let full_span = operator_span.join_span(&rparen_span);
1890                r.shift_binop(BinaryOperator::Operator(op_name, full_span))
1891            }
1892            Token::Ident(_, Keyword::MEMBER)
1893                if PRIORITY_CMP < max_priority
1894                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
1895            {
1896                if let Err(e) = r.reduce(PRIORITY_CMP) {
1897                    parser.err_here(e)?;
1898                }
1899                let lhs = match r.stack.pop() {
1900                    Some(ReduceMember::Expression(e)) => e,
1901                    _ => parser.err_here("Expected expression before here")?,
1902                };
1903                let member_span = parser.consume_keyword(Keyword::MEMBER)?;
1904                let of_span = parser.consume_keyword(Keyword::OF)?;
1905                parser.consume_token(Token::LParen)?;
1906                let rhs = parse_expression_paren(parser)?;
1907                parser.consume_token(Token::RParen)?;
1908                r.shift_expr(Expression::MemberOf(Box::new(MemberOfExpression {
1909                    lhs,
1910                    rhs,
1911                    member_of_span: member_span.join_span(&of_span),
1912                })))
1913            }
1914            Token::Ident(_, Keyword::INTERVAL) => {
1915                let interval_span = parser.consume();
1916                let (time_interval, embedded_unit) = match parser.token {
1917                    Token::String(..) => {
1918                        let v = parser.consume_string()?;
1919                        let str_span = v.span();
1920                        let mut nums = Vec::new();
1921                        let mut embedded: Option<TimeUnit> = None;
1922                        for part in v.split([':', '!', ',', '.', '-', ' ']) {
1923                            if let Ok(n) = part.parse::<i64>() {
1924                                nums.push(n);
1925                            } else if !part.is_empty() {
1926                                embedded = parse_time_unit_from_str(part);
1927                            }
1928                        }
1929                        ((nums, str_span), embedded)
1930                    }
1931                    Token::Integer(_) => {
1932                        let (v, s) = parser.consume_int()?;
1933                        ((vec![v], s), None)
1934                    }
1935                    _ => parser.err_here("Expected integer or string")?,
1936                };
1937                let time_unit = if let Some(u) = parse_time_unit(&parser.token) {
1938                    (u, parser.consume())
1939                } else if let Some(u) = embedded_unit {
1940                    (u, time_interval.1.clone())
1941                } else {
1942                    parser.err_here("Expected time unit")?
1943                };
1944                let e = Expression::Interval(Box::new(IntervalExpression {
1945                    interval_span,
1946                    time_interval,
1947                    time_unit,
1948                }));
1949                r.shift_expr(e)
1950            }
1951            Token::Ident(_, Keyword::TIMESTAMPADD) => {
1952                let timestamp_add_span = parser.consume();
1953                parser.consume_token(Token::LParen)?;
1954                let parts = parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
1955                    let Some(u) = parse_time_unit(&parser.token) else {
1956                        parser.err_here("Expected time unit")?
1957                    };
1958                    let unit = (u, parser.consume());
1959                    parser.consume_token(Token::Comma)?;
1960                    let interval = parse_expression_outer(parser)?;
1961                    parser.consume_token(Token::Comma)?;
1962                    let datetime = parse_expression_outer(parser)?;
1963                    Ok(Some((unit, interval, datetime)))
1964                })?;
1965                parser.consume_token(Token::RParen)?;
1966                if let Some((unit, interval, datetime)) = parts {
1967                    r.shift_expr(Expression::TimestampAdd(Box::new(TimestampAddExpression {
1968                        timestamp_add_span,
1969                        unit,
1970                        interval,
1971                        datetime,
1972                    })))
1973                } else {
1974                    r.shift_expr(Expression::Invalid(Box::new(InvalidExpression {
1975                        span: timestamp_add_span,
1976                    })))
1977                }
1978            }
1979            Token::Ident(_, Keyword::TIMESTAMPDIFF) => {
1980                let timestamp_diff_span = parser.consume();
1981                parser.consume_token(Token::LParen)?;
1982                let parts = parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
1983                    let Some(u) = parse_time_unit(&parser.token) else {
1984                        parser.err_here("Expected time unit")?
1985                    };
1986                    let unit = (u, parser.consume());
1987                    parser.consume_token(Token::Comma)?;
1988                    let e1 = parse_expression_outer(parser)?;
1989                    parser.consume_token(Token::Comma)?;
1990                    let e2 = parse_expression_outer(parser)?;
1991                    Ok(Some((unit, e1, e2)))
1992                })?;
1993                parser.consume_token(Token::RParen)?;
1994                if let Some((unit, e1, e2)) = parts {
1995                    r.shift_expr(Expression::TimestampDiff(Box::new(
1996                        TimestampDiffExpression {
1997                            timestamp_diff_span,
1998                            unit,
1999                            e1,
2000                            e2,
2001                        },
2002                    )))
2003                } else {
2004                    r.shift_expr(Expression::Invalid(Box::new(InvalidExpression {
2005                        span: timestamp_diff_span,
2006                    })))
2007                }
2008            }
2009            Token::Plus if PRIORITY_ADD < max_priority => {
2010                r.shift_binop(BinaryOperator::Add(parser.consume()))
2011            }
2012            Token::Div if PRIORITY_MULT < max_priority => {
2013                r.shift_binop(BinaryOperator::Divide(parser.consume()))
2014            }
2015            Token::Ident(_, Keyword::DIV) if PRIORITY_MULT < max_priority => {
2016                r.shift_binop(BinaryOperator::Div(parser.consume()))
2017            }
2018            Token::Minus if PRIORITY_ADD < max_priority => {
2019                r.shift_binop(BinaryOperator::Subtract(parser.consume()))
2020            }
2021            Token::Ident(_, Keyword::LIKE) if PRIORITY_CMP < max_priority => {
2022                r.shift_binop(BinaryOperator::Like(parser.consume()))
2023            }
2024            Token::Mul if !matches!(r.stack.last(), Some(ReduceMember::Expression(_))) => r
2025                .shift_expr(Expression::Identifier(Box::new(IdentifierExpression {
2026                    parts: vec![IdentifierPart::Star(parser.consume_token(Token::Mul)?)],
2027                }))),
2028            Token::Mul
2029                if PRIORITY_MULT < max_priority
2030                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
2031            {
2032                r.shift_binop(BinaryOperator::Mult(parser.consume()))
2033            }
2034            Token::Mod if PRIORITY_MULT < max_priority => {
2035                r.shift_binop(BinaryOperator::Mod(parser.consume()))
2036            }
2037            Token::Ident(_, Keyword::MOD)
2038                if PRIORITY_MULT < max_priority
2039                    && matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
2040            {
2041                r.shift_binop(BinaryOperator::Mod(parser.consume()))
2042            }
2043            Token::Ident(_, Keyword::TRUE) => {
2044                r.shift_expr(Expression::Bool(Box::new(BoolExpression {
2045                    value: true,
2046                    span: parser.consume_keyword(Keyword::TRUE)?,
2047                })))
2048            }
2049            Token::Ident(_, Keyword::FALSE) => {
2050                r.shift_expr(Expression::Bool(Box::new(BoolExpression {
2051                    value: false,
2052                    span: parser.consume_keyword(Keyword::FALSE)?,
2053                })))
2054            }
2055            Token::Ident(_, Keyword::NULL) => {
2056                r.shift_expr(Expression::Null(Box::new(NullExpression {
2057                    span: parser.consume_keyword(Keyword::NULL)?,
2058                })))
2059            }
2060            Token::Ident(_, Keyword::_LIST_) if parser.options.list_hack => {
2061                let arg = parser.arg;
2062                parser.arg += 1;
2063                r.shift_expr(Expression::ListHack(Box::new(ListHackExpression {
2064                    index: arg,
2065                    span: parser.consume_keyword(Keyword::_LIST_)?,
2066                })))
2067            }
2068            Token::String(..) => {
2069                r.shift_expr(Expression::String(Box::new(parser.consume_string()?)))
2070            }
2071            Token::Integer(_) => {
2072                let (value, span) = parser.consume_int()?;
2073                r.shift_expr(Expression::Integer(Box::new(IntegerExpression {
2074                    value,
2075                    span,
2076                })))
2077            }
2078            Token::Float(_) => {
2079                let (value, span) = parser.consume_float()?;
2080                r.shift_expr(Expression::Float(Box::new(FloatExpression { value, span })))
2081            }
2082            Token::Ident(_, Keyword::CAST) => {
2083                let cast_span = parser.consume_keyword(Keyword::CAST)?;
2084                parser.consume_token(Token::LParen)?;
2085                let cast = parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
2086                    let expr = parse_expression_outer(parser)?;
2087                    let as_span = parser.consume_keyword(Keyword::AS)?;
2088                    let type_ = parse_data_type(parser, DataTypeContext::TypeRef)?;
2089                    Ok(Some((expr, as_span, type_)))
2090                })?;
2091                parser.consume_token(Token::RParen)?;
2092                if let Some((expr, as_span, type_)) = cast {
2093                    r.shift_expr(Expression::Cast(Box::new(CastExpression {
2094                        cast_span,
2095                        expr,
2096                        as_span,
2097                        type_,
2098                    })))
2099                } else {
2100                    r.shift_expr(Expression::Invalid(Box::new(InvalidExpression {
2101                        span: cast_span,
2102                    })))
2103                }
2104            }
2105            Token::Ident(_, Keyword::CONVERT) => {
2106                let convert_span = parser.consume_keyword(Keyword::CONVERT)?;
2107                parser.consume_token(Token::LParen)?;
2108                let convert =
2109                    parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
2110                        let expr = parse_expression_outer(parser)?;
2111                        // Check if it's CONVERT(expr, type) or CONVERT(expr USING charset)
2112                        if parser.skip_keyword(Keyword::USING).is_some() {
2113                            // CONVERT(expr USING charset)
2114                            let charset = parser.consume_plain_identifier_unreserved()?;
2115                            Ok(Some((expr, None, Some(charset))))
2116                        } else {
2117                            // CONVERT(expr, type)
2118                            parser.consume_token(Token::Comma)?;
2119                            let type_ = parse_data_type(parser, DataTypeContext::TypeRef)?;
2120                            Ok(Some((expr, Some(type_), None)))
2121                        }
2122                    })?;
2123                parser.consume_token(Token::RParen)?;
2124                if let Some((expr, type_, charset)) = convert {
2125                    r.shift_expr(Expression::Convert(Box::new(ConvertExpression {
2126                        convert_span,
2127                        expr,
2128                        type_,
2129                        using_charset: charset.map(|c| (c.span(), c)),
2130                    })))
2131                } else {
2132                    r.shift_expr(Expression::Invalid(Box::new(InvalidExpression {
2133                        span: convert_span,
2134                    })))
2135                }
2136            }
2137            Token::Ident(_, Keyword::GROUP_CONCAT) => {
2138                let group_concat_span: core::ops::Range<usize> =
2139                    parser.consume_keyword(Keyword::GROUP_CONCAT)?;
2140                parser.consume_token(Token::LParen)?;
2141                let distinct_span: Option<core::ops::Range<usize>> =
2142                    parser.skip_keyword(Keyword::DISTINCT);
2143                let expr = parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
2144                    let expr = parse_expression_outer(parser)?;
2145                    Ok(Some(expr))
2146                })?;
2147                // TODO
2148                // [ORDER BY {unsigned_integer | col_name | expr}
2149                //     [ASC | DESC] [,col_name ...]]
2150                // [SEPARATOR str_val]
2151                // [LIMIT {[offset,] row_count | row_count OFFSET offset}])
2152                parser.consume_token(Token::RParen)?;
2153                if let Some(expr) = expr {
2154                    r.shift_expr(Expression::GroupConcat(Box::new(GroupConcatExpression {
2155                        group_concat_span,
2156                        distinct_span,
2157                        expr,
2158                    })))
2159                } else {
2160                    r.shift_expr(Expression::Invalid(Box::new(InvalidExpression {
2161                        span: group_concat_span,
2162                    })))
2163                }
2164            }
2165            Token::Ident(_, Keyword::TRIM) if matches!(parser.peek(), Token::LParen) => {
2166                let trim_span = parser.consume_keyword(Keyword::TRIM)?;
2167                parser.consume_token(Token::LParen)?;
2168                let parts = parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
2169                    // Optional BOTH / LEADING / TRAILING
2170                    let direction = match &parser.token {
2171                        Token::Ident(_, Keyword::BOTH) => {
2172                            Some(TrimDirection::Both(parser.consume()))
2173                        }
2174                        Token::Ident(_, Keyword::LEADING) => {
2175                            Some(TrimDirection::Leading(parser.consume()))
2176                        }
2177                        Token::Ident(_, Keyword::TRAILING) => {
2178                            Some(TrimDirection::Trailing(parser.consume()))
2179                        }
2180                        _ => None,
2181                    };
2182
2183                    let (what, from_span, value) = if direction.is_some() {
2184                        // After direction: optionally [remstr] FROM value
2185                        if let Some(from_s) = parser.skip_keyword(Keyword::FROM) {
2186                            // No remstr: TRIM(BOTH FROM str)
2187                            let value = parse_expression_outer(parser)?;
2188                            (None, Some(from_s), value)
2189                        } else {
2190                            // Has remstr: TRIM(BOTH remstr FROM str)
2191                            let what = parse_expression_outer(parser)?;
2192                            let from_s = parser.consume_keyword(Keyword::FROM)?;
2193                            let value = parse_expression_outer(parser)?;
2194                            (Some(what), Some(from_s), value)
2195                        }
2196                    } else {
2197                        // No direction: TRIM(str) or TRIM(remstr FROM str)
2198                        let first = parse_expression_outer(parser)?;
2199                        if let Some(from_s) = parser.skip_keyword(Keyword::FROM) {
2200                            // first is remstr
2201                            let value = parse_expression_outer(parser)?;
2202                            (Some(first), Some(from_s), value)
2203                        } else {
2204                            // first is the value itself
2205                            (None, None, first)
2206                        }
2207                    };
2208                    Ok(Some((direction, what, from_span, value)))
2209                })?;
2210                parser.consume_token(Token::RParen)?;
2211                if let Some((direction, what, from_span, value)) = parts {
2212                    r.shift_expr(Expression::Trim(Box::new(TrimExpression {
2213                        trim_span,
2214                        direction,
2215                        what,
2216                        from_span,
2217                        value,
2218                    })))
2219                } else {
2220                    r.shift_expr(Expression::Invalid(Box::new(InvalidExpression {
2221                        span: trim_span,
2222                    })))
2223                }
2224            }
2225            Token::Ident(_, Keyword::EXTRACT) => {
2226                let extract_span = parser.consume_keyword(Keyword::EXTRACT)?;
2227                parser.consume_token(Token::LParen)?;
2228                let parts = parser.recovered("')'", &|t| matches!(t, Token::RParen), |parser| {
2229                    let Some(u) = parse_time_unit(&parser.token) else {
2230                        parser.err_here("Expected time unit")?
2231                    };
2232                    let time_unit = (u, parser.consume());
2233                    let from_span = parser.consume_keyword(Keyword::FROM)?;
2234                    let date = parse_expression_outer(parser)?;
2235                    Ok(Some((time_unit, from_span, date)))
2236                })?;
2237                parser.consume_token(Token::RParen)?;
2238                if let Some((time_unit, from_span, date)) = parts {
2239                    r.shift_expr(Expression::Extract(Box::new(ExtractExpression {
2240                        extract_span,
2241                        time_unit,
2242                        from_span,
2243                        date,
2244                    })))
2245                } else {
2246                    r.shift_expr(Expression::Invalid(Box::new(InvalidExpression {
2247                        span: extract_span,
2248                    })))
2249                }
2250            }
2251            Token::Ident(_, Keyword::MATCH) => {
2252                let match_span = parser.consume_keyword(Keyword::MATCH)?;
2253                parser.consume_token(Token::LParen)?;
2254                let mut cols = Vec::new();
2255                loop {
2256                    parser.recovered(
2257                        "')' or ','",
2258                        &|t| matches!(t, Token::RParen | Token::Comma),
2259                        |parser| {
2260                            cols.push(parse_expression_paren(parser)?);
2261                            Ok(())
2262                        },
2263                    )?;
2264                    if parser.skip_token(Token::Comma).is_none() {
2265                        break;
2266                    }
2267                }
2268                parser.consume_token(Token::RParen)?;
2269                let against_span = parser.consume_keyword(Keyword::AGAINST)?;
2270                parser.consume_token(Token::LParen)?;
2271
2272                // Parse the search expression but don't treat `IN`/`WITH` as binary
2273                // operators here — they are MATCH modes and may appear inside the
2274                // AGAINST(...) parentheses (MySQL allows both inside and outside).
2275                // PRIORITY_CMP stops before IN/WITH so they remain available as MATCH mode keywords
2276                let expr = parse_expression_unreserved(parser, PRIORITY_CMP)?;
2277
2278                // optional mode that may appear inside the AGAINST(...) parentheses
2279                let mut mode: Option<MatchMode> = None;
2280                if parser.skip_keyword(Keyword::IN).is_some() {
2281                    if let Some(boolean_span) = parser.skip_keyword(Keyword::BOOLEAN) {
2282                        let mode_span = parser.consume_keyword(Keyword::MODE)?;
2283                        mode = Some(MatchMode::InBoolean(boolean_span.join_span(&mode_span)));
2284                    } else if let Some(natural_span) = parser.skip_keyword(Keyword::NATURAL) {
2285                        // optional LANGUAGE after NATURAL
2286                        let _language_span = parser.skip_keyword(Keyword::LANGUAGE);
2287                        let mode_span = parser.consume_keyword(Keyword::MODE)?;
2288                        let natural_total = natural_span.join_span(&mode_span);
2289                        // optional WITH QUERY EXPANSION following NATURAL MODE inside parens
2290                        if let Some(with_span) = parser.skip_keyword(Keyword::WITH) {
2291                            let expansion_total = with_span.join_span(
2292                                &parser.consume_keywords(&[Keyword::QUERY, Keyword::EXPANSION])?,
2293                            );
2294                            mode = Some(MatchMode::InNaturalLanguageWithQueryExpansion(
2295                                natural_total.join_span(&expansion_total),
2296                            ));
2297                        } else {
2298                            mode = Some(MatchMode::InNaturalLanguage(natural_total));
2299                        }
2300                    }
2301                } else if let Some(with_span) = parser.skip_keyword(Keyword::WITH) {
2302                    mode = Some(MatchMode::WithQueryExpansion(with_span.join_span(
2303                        &parser.consume_keywords(&[Keyword::QUERY, Keyword::EXPANSION])?,
2304                    )));
2305                }
2306
2307                parser.consume_token(Token::RParen)?;
2308
2309                // If no mode was found inside the parens, allow it after the closing
2310                // parenthesis as well (some dialects/placeholders may put it there).
2311                if mode.is_none() {
2312                    if parser.skip_keyword(Keyword::IN).is_some() {
2313                        if let Some(boolean_span) = parser.skip_keyword(Keyword::BOOLEAN) {
2314                            let mode_span = parser.consume_keyword(Keyword::MODE)?;
2315                            mode = Some(MatchMode::InBoolean(boolean_span.join_span(&mode_span)));
2316                        } else if let Some(natural_span) = parser.skip_keyword(Keyword::NATURAL) {
2317                            let _language_span = parser.skip_keyword(Keyword::LANGUAGE);
2318                            let mode_span = parser.consume_keyword(Keyword::MODE)?;
2319                            let natural_total = natural_span.join_span(&mode_span);
2320                            // optional WITH QUERY EXPANSION following NATURAL MODE after paren
2321                            if let Some(with_span) = parser.skip_keyword(Keyword::WITH) {
2322                                let expansion_total = with_span.join_span(
2323                                    &parser
2324                                        .consume_keywords(&[Keyword::QUERY, Keyword::EXPANSION])?,
2325                                );
2326                                mode = Some(MatchMode::InNaturalLanguageWithQueryExpansion(
2327                                    natural_total.join_span(&expansion_total),
2328                                ));
2329                            } else {
2330                                mode = Some(MatchMode::InNaturalLanguage(natural_total));
2331                            }
2332                        }
2333                    } else if let Some(with_span) = parser.skip_keyword(Keyword::WITH) {
2334                        mode = Some(MatchMode::WithQueryExpansion(with_span.join_span(
2335                            &parser.consume_keywords(&[Keyword::QUERY, Keyword::EXPANSION])?,
2336                        )));
2337                    }
2338                }
2339
2340                r.shift_expr(Expression::MatchAgainst(Box::new(MatchAgainstExpression {
2341                    match_span,
2342                    columns: cols,
2343                    against_span,
2344                    expr,
2345                    mode,
2346                })))
2347            }
2348            Token::Ident(_, Keyword::LEFT) if matches!(parser.peek(), Token::LParen) => {
2349                let i = parser.token.clone();
2350                let s = parser.span.clone();
2351                parser.consume();
2352                r.shift_expr(parse_function(parser, i, s)?)
2353            }
2354            Token::Ident(_, Keyword::CHAR) if matches!(parser.peek(), Token::LParen) => {
2355                let s = parser.span.clone();
2356                parser.consume();
2357                r.shift_expr(parse_char_function(parser, s)?)
2358            }
2359            Token::Ident(_, keyword)
2360                if matches!(parser.peek(), Token::LParen)
2361                    && is_aggregate_function_ident(&keyword) =>
2362            {
2363                let i = parser.token.clone();
2364                let s = parser.span.clone();
2365                parser.consume();
2366                r.shift_expr(parse_aggregate_function(parser, i, s)?)
2367            }
2368            // Handle charset-prefixed strings like _utf8mb4 'abc' or _binary 'data'
2369            Token::Ident(charset, _)
2370                if charset.starts_with('_') && matches!(parser.peek(), Token::String(..)) =>
2371            {
2372                // Consume the charset prefix
2373                parser.consume();
2374                // Parse the string literal
2375                r.shift_expr(Expression::String(Box::new(parser.consume_string()?)))
2376            }
2377            // PostgreSQL ARRAY[...] literal
2378            Token::Ident(_, Keyword::ARRAY) if matches!(parser.peek(), Token::LBracket) => {
2379                let array_span = parser.consume_keyword(Keyword::ARRAY)?;
2380                parser.postgres_only(&array_span);
2381                let lbracket = parser.consume_token(Token::LBracket)?;
2382                let mut elements = Vec::new();
2383                if !matches!(parser.token, Token::RBracket) {
2384                    loop {
2385                        parser.recovered(
2386                            "']' or ','",
2387                            &|t| matches!(t, Token::RBracket | Token::Comma),
2388                            |parser| {
2389                                elements.push(parse_array_element(parser)?);
2390                                Ok(())
2391                            },
2392                        )?;
2393                        if parser.skip_token(Token::Comma).is_none() {
2394                            break;
2395                        }
2396                    }
2397                }
2398                let rbracket = parser.consume_token(Token::RBracket)?;
2399                let bracket_span = lbracket.join_span(&rbracket);
2400                r.shift_expr(Expression::Array(Box::new(ArrayExpression {
2401                    array_span,
2402                    bracket_span,
2403                    elements,
2404                })))
2405            }
2406            Token::Ident(_, k)
2407                if (k.expr_ident() || !k.restricted(restrict))
2408                    && !matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
2409            {
2410                let i = parser.token.clone();
2411                let s = parser.span.clone();
2412                parser.consume();
2413                if matches!(parser.token, Token::LParen) {
2414                    r.shift_expr(parse_function(parser, i, s)?)
2415                } else {
2416                    let f = match i {
2417                        Token::Ident(_, Keyword::CURRENT_TIMESTAMP) => {
2418                            Some(Function::CurrentTimestamp)
2419                        }
2420                        Token::Ident(_, Keyword::LOCALTIME | Keyword::LOCALTIMESTAMP) => {
2421                            Some(Function::Now)
2422                        }
2423                        Token::Ident(_, Keyword::UTC_TIMESTAMP) => Some(Function::UtcTimeStamp),
2424                        Token::Ident(_, Keyword::UTC_DATE) => Some(Function::UtcDate),
2425                        Token::Ident(_, Keyword::UTC_TIME) => Some(Function::UtcTime),
2426                        Token::Ident(_, Keyword::CURRENT_DATE) => Some(Function::CurDate),
2427                        Token::Ident(_, Keyword::CURRENT_TIME) => Some(Function::CurTime),
2428                        Token::Ident(_, Keyword::CURRENT_USER) => Some(Function::CurrentUser),
2429                        Token::Ident(_, Keyword::CURRENT_ROLE) => Some(Function::CurrentRole),
2430                        Token::Ident(_, Keyword::CURRENT_CATALOG) => Some(Function::CurrentCatalog),
2431                        Token::Ident(_, Keyword::SESSION_USER) => Some(Function::SessionUser),
2432                        Token::Ident(_, Keyword::USER)
2433                            if parser.options.dialect.is_postgresql() =>
2434                        {
2435                            Some(Function::CurrentUser)
2436                        }
2437                        _ => None,
2438                    };
2439                    if let Some(f) = f {
2440                        r.shift_expr(Expression::Function(Box::new(FunctionCallExpression {
2441                            function: f,
2442                            args: Vec::new(),
2443                            function_span: s,
2444                        })))
2445                    } else {
2446                        let mut parts = vec![IdentifierPart::Name(
2447                            parser.token_to_plain_identifier(&i, s)?,
2448                        )];
2449                        // Save the last identifier token so we can call parse_function if
2450                        // the chain is followed by `(` (schema-qualified function call).
2451                        let mut last_ident_tok: Option<(Token<'a>, Span)> = None;
2452                        loop {
2453                            if parser.skip_token(Token::Period).is_none() {
2454                                break;
2455                            }
2456                            match &parser.token {
2457                                Token::Mul => {
2458                                    last_ident_tok = None;
2459                                    parts.push(IdentifierPart::Star(
2460                                        parser.consume_token(Token::Mul)?,
2461                                    ));
2462                                }
2463                                Token::Ident(_, _) => {
2464                                    let fn_tok = parser.token.clone();
2465                                    let fn_span = parser.span.clone();
2466                                    last_ident_tok = Some((fn_tok, fn_span));
2467                                    parts.push(IdentifierPart::Name(
2468                                        parser.consume_plain_identifier_unreserved()?,
2469                                    ));
2470                                }
2471                                _ => parser.expected_failure("Identifier or '*'")?,
2472                            }
2473                        }
2474                        // Schema-qualified function call: schema.func(args)
2475                        if matches!(parser.token, Token::LParen) {
2476                            if let Some((fn_tok, fn_span)) = last_ident_tok {
2477                                // All parts form the qualified name; last part is function name
2478                                let mut all_idents: Vec<Identifier<'a>> = parts[..parts.len() - 1]
2479                                    .iter()
2480                                    .filter_map(|p| match p {
2481                                        IdentifierPart::Name(id) => Some(id.clone()),
2482                                        _ => None,
2483                                    })
2484                                    .collect();
2485                                let fn_ident = Identifier {
2486                                    value: match &fn_tok {
2487                                        Token::Ident(v, _) => v,
2488                                        _ => "",
2489                                    },
2490                                    span: fn_span.clone(),
2491                                };
2492                                all_idents.push(fn_ident);
2493                                // function_span covers from first qualifier to function name
2494                                let function_span = if all_idents.len() > 1 {
2495                                    all_idents[0].span.join_span(&fn_span)
2496                                } else {
2497                                    fn_span
2498                                };
2499                                r.shift_expr(parse_function_call(
2500                                    parser,
2501                                    Function::Other(all_idents),
2502                                    function_span,
2503                                )?)
2504                            } else {
2505                                r.shift_expr(Expression::Identifier(Box::new(
2506                                    IdentifierExpression { parts },
2507                                )))
2508                            }
2509                        } else {
2510                            r.shift_expr(Expression::Identifier(Box::new(IdentifierExpression {
2511                                parts,
2512                            })))
2513                        }
2514                    }
2515                }
2516            }
2517            Token::QuestionMark
2518                if matches!(parser.options.arguments, crate::SQLArguments::QuestionMark) =>
2519            {
2520                let arg = parser.arg;
2521                parser.arg += 1;
2522                r.shift_expr(Expression::Arg(Box::new(ArgExpression {
2523                    index: arg,
2524                    span: parser.consume_token(Token::QuestionMark)?,
2525                })))
2526            }
2527            Token::PercentS if matches!(parser.options.arguments, crate::SQLArguments::Percent) => {
2528                let arg = parser.arg;
2529                parser.arg += 1;
2530                r.shift_expr(Expression::Arg(Box::new(ArgExpression {
2531                    index: arg,
2532                    span: parser.consume_token(Token::PercentS)?,
2533                })))
2534            }
2535            Token::DollarArg(arg)
2536                if matches!(parser.options.arguments, crate::SQLArguments::Dollar) =>
2537            {
2538                r.shift_expr(Expression::Arg(Box::new(ArgExpression {
2539                    index: arg - 1,
2540                    span: parser.consume(),
2541                })))
2542            }
2543            Token::LParen => {
2544                let paren_start = parser.consume_token(Token::LParen)?;
2545                let first = parse_expression_paren(parser)?;
2546                if parser.skip_token(Token::Comma).is_some() {
2547                    // Row / tuple constructor: (expr1, expr2, ...)
2548                    let mut elements = vec![first];
2549                    loop {
2550                        if matches!(parser.token, Token::RParen) {
2551                            break;
2552                        }
2553                        parser.recovered(
2554                            "')' or ','",
2555                            &|t| matches!(t, Token::RParen | Token::Comma),
2556                            |parser| {
2557                                elements.push(parse_expression_paren(parser)?);
2558                                Ok(())
2559                            },
2560                        )?;
2561                        if parser.skip_token(Token::Comma).is_none() {
2562                            break;
2563                        }
2564                    }
2565                    let paren_end = parser.consume_token(Token::RParen)?;
2566                    r.shift_expr(Expression::Row(Box::new(RowExpression {
2567                        paren_span: paren_start.join_span(&paren_end),
2568                        elements,
2569                    })))
2570                } else {
2571                    parser.consume_token(Token::RParen)?;
2572                    r.shift_expr(first)
2573                }
2574            }
2575            Token::Ident(_, Keyword::EXISTS) => {
2576                let exists_span = parser.consume_keyword(Keyword::EXISTS)?;
2577                parser.consume_token(Token::LParen)?;
2578                let subquery = parse_compound_query(parser)?;
2579                parser.consume_token(Token::RParen)?;
2580                let ans = Expression::Exists(Box::new(ExistsExpression {
2581                    exists_span,
2582                    subquery,
2583                }));
2584                r.shift_expr(ans)
2585            }
2586            Token::Ident(_, Keyword::ANY | Keyword::SOME | Keyword::ALL)
2587                if parser.options.dialect.is_postgresql()
2588                    && !matches!(r.stack.last(), Some(ReduceMember::Expression(_))) =>
2589            {
2590                let quantifier = match &parser.token {
2591                    Token::Ident(_, Keyword::ANY) => {
2592                        Quantifier::Any(parser.consume_keyword(Keyword::ANY)?)
2593                    }
2594                    Token::Ident(_, Keyword::SOME) => {
2595                        Quantifier::Some(parser.consume_keyword(Keyword::SOME)?)
2596                    }
2597                    _ => Quantifier::All(parser.consume_keyword(Keyword::ALL)?),
2598                };
2599                parser.consume_token(Token::LParen)?;
2600                let operand = parse_expression_paren(parser)?;
2601                parser.consume_token(Token::RParen)?;
2602                r.shift_expr(Expression::Quantifier(Box::new(QuantifierExpression {
2603                    quantifier,
2604                    operand,
2605                })))
2606            }
2607            Token::Ident(_, Keyword::CASE) => {
2608                let case_span = parser.consume_keyword(Keyword::CASE)?;
2609                let value = if !matches!(parser.token, Token::Ident(_, Keyword::WHEN)) {
2610                    Some(parse_expression_unreserved(parser, PRIORITY_MAX)?)
2611                } else {
2612                    None
2613                };
2614                let mut whens = Vec::new();
2615                let mut else_ = None;
2616                parser.recovered(
2617                    "'END'",
2618                    &|t| matches!(t, Token::Ident(_, Keyword::END)),
2619                    |parser| {
2620                        loop {
2621                            let when_span = parser.consume_keyword(Keyword::WHEN)?;
2622                            let when = parse_expression_unreserved(parser, PRIORITY_MAX)?;
2623                            let then_span = parser.consume_keyword(Keyword::THEN)?;
2624                            let then = parse_expression_unreserved(parser, PRIORITY_MAX)?;
2625                            whens.push(When {
2626                                when_span,
2627                                when,
2628                                then_span,
2629                                then,
2630                            });
2631                            if !matches!(parser.token, Token::Ident(_, Keyword::WHEN)) {
2632                                break;
2633                            }
2634                        }
2635                        if let Some(span) = parser.skip_keyword(Keyword::ELSE) {
2636                            else_ = Some((span, parse_expression_unreserved(parser, PRIORITY_MAX)?))
2637                        };
2638                        Ok(())
2639                    },
2640                )?;
2641                let end_span = parser.consume_keyword(Keyword::END)?;
2642                r.shift_expr(Expression::Case(Box::new(CaseExpression {
2643                    case_span,
2644                    value,
2645                    whens,
2646                    else_,
2647                    end_span,
2648                })))
2649            }
2650            Token::AtAtGlobal | Token::AtAtSession => {
2651                let global = parser.skip_token(Token::AtAtGlobal);
2652                let session = if global.is_none() {
2653                    Some(parser.consume_token(Token::AtAtSession)?)
2654                } else {
2655                    None
2656                };
2657                let dot = Some(parser.consume_token(Token::Period)?);
2658                let variable = match &parser.token {
2659                    Token::Ident(_, Keyword::TIME_ZONE) => Variable::TimeZone,
2660                    Token::Ident(t, _) => Variable::Other(t),
2661                    _ => parser.expected_failure("Identifier")?,
2662                };
2663                let variable_span = parser.consume();
2664                r.shift_expr(Expression::Variable(Box::new(VariableExpression {
2665                    global,
2666                    session,
2667                    dot,
2668                    variable,
2669                    variable_span,
2670                })))
2671            }
2672            Token::At => {
2673                // User variable: @variable_name
2674                let at_span = parser.consume_token(Token::At)?;
2675                let name = parser.consume_plain_identifier_unreserved()?;
2676                r.shift_expr(Expression::UserVariable(Box::new(UserVariableExpression {
2677                    name,
2678                    at_span,
2679                })))
2680            }
2681            _ => break,
2682        };
2683        if let Err(e) = e {
2684            parser.err_here(e.to_string())?;
2685        }
2686    }
2687    if r.reduce(99999).is_err() {
2688        parser.err_here("Expected expression")
2689    } else if r.stack.len() != 1 {
2690        parser.ice(file!(), line!())
2691    } else if let Some(ReduceMember::Expression(e)) = r.stack.pop() {
2692        Ok(e)
2693    } else {
2694        parser.ice(file!(), line!())
2695    }
2696}
2697
2698pub(crate) fn parse_expression_unreserved<'a>(
2699    parser: &mut Parser<'a, '_>,
2700    max_priority: usize,
2701) -> Result<Expression<'a>, ParseError> {
2702    parse_expression_restricted(parser, max_priority, parser.reserved())
2703}
2704
2705/// Parse an expression that may be DEFAULT (for INSERT VALUES, INSERT SET, UPDATE SET contexts)
2706pub(crate) fn parse_expression_or_default<'a>(
2707    parser: &mut Parser<'a, '_>,
2708    max_priority: usize,
2709) -> Result<Expression<'a>, ParseError> {
2710    if matches!(parser.token, Token::Ident(_, Keyword::DEFAULT)) {
2711        Ok(Expression::Default(Box::new(DefaultExpression {
2712            span: parser.consume_keyword(Keyword::DEFAULT)?,
2713        })))
2714    } else {
2715        parse_expression_unreserved(parser, max_priority)
2716    }
2717}
2718
2719pub(crate) fn parse_expression_outer<'a>(
2720    parser: &mut Parser<'a, '_>,
2721) -> Result<Expression<'a>, ParseError> {
2722    if matches!(parser.token, Token::Ident(_, Keyword::SELECT)) {
2723        Ok(Expression::Subquery(Box::new(SubqueryExpression {
2724            expression: parse_compound_query(parser)?,
2725        })))
2726    } else {
2727        parse_expression_unreserved(parser, PRIORITY_MAX)
2728    }
2729}
2730
2731pub(crate) fn parse_expression_paren<'a>(
2732    parser: &mut Parser<'a, '_>,
2733) -> Result<Expression<'a>, ParseError> {
2734    if matches!(parser.token, Token::Ident(_, Keyword::SELECT)) {
2735        Ok(Expression::Subquery(Box::new(SubqueryExpression {
2736            expression: parse_compound_query(parser)?,
2737        })))
2738    } else {
2739        parse_expression_unreserved(parser, PRIORITY_MAX)
2740    }
2741}
2742
2743#[cfg(test)]
2744mod tests {
2745    use core::ops::Deref;
2746
2747    use alloc::{
2748        format,
2749        string::{String, ToString},
2750    };
2751
2752    use crate::{
2753        BinaryExpression, ParseOptions, SQLDialect,
2754        expression::{BinaryOperator, Expression, PRIORITY_MAX, Quantifier},
2755        issue::Issues,
2756        parser::Parser,
2757    };
2758
2759    use super::{IdentifierPart, parse_expression_unreserved};
2760
2761    fn test_ident<'a>(e: &Expression<'a>, v: &str) -> Result<(), String> {
2762        let v = match e {
2763            Expression::Identifier(a) => match a.parts.as_slice() {
2764                [IdentifierPart::Name(vv)] => vv.deref() == v,
2765                _ => false,
2766            },
2767            _ => false,
2768        };
2769        if !v {
2770            Err(format!("Expected identifier {} found {:?}", v, e))
2771        } else {
2772            Ok(())
2773        }
2774    }
2775
2776    fn test_expr(src: &'static str, f: impl FnOnce(&Expression<'_>) -> Result<(), String>) {
2777        let mut issues = Issues::new(src);
2778        let options = ParseOptions::new().dialect(SQLDialect::MariaDB);
2779        let mut parser = Parser::new(src, &mut issues, &options);
2780        let res = parse_expression_unreserved(&mut parser, PRIORITY_MAX)
2781            .expect("Expression in test expr");
2782        if let Err(e) = f(&res) {
2783            panic!("Error parsing {}: {}\nGot {:#?}", src, e, res);
2784        }
2785    }
2786
2787    #[test]
2788    fn expressions() {
2789        test_expr("`a` + `b` * `c` + `d`", |e| {
2790            match e {
2791                Expression::Binary(b) => {
2792                    let BinaryExpression {
2793                        op: BinaryOperator::Add(_),
2794                        lhs,
2795                        rhs,
2796                        ..
2797                    } = b.as_ref()
2798                    else {
2799                        return Err("Expected outer +".to_string());
2800                    };
2801                    match lhs {
2802                        Expression::Binary(b) => {
2803                            let BinaryExpression {
2804                                op: BinaryOperator::Add(_),
2805                                lhs,
2806                                rhs,
2807                                ..
2808                            } = b.as_ref()
2809                            else {
2810                                return Err("Expected inner +".to_string());
2811                            };
2812                            test_ident(lhs, "a")?;
2813                            match rhs {
2814                                Expression::Binary(b) => {
2815                                    let BinaryExpression {
2816                                        op: BinaryOperator::Mult(_),
2817                                        lhs,
2818                                        rhs,
2819                                        ..
2820                                    } = b.as_ref()
2821                                    else {
2822                                        return Err("Expected *".to_string());
2823                                    };
2824                                    test_ident(lhs, "b")?;
2825                                    test_ident(rhs, "c")?;
2826                                }
2827                                _ => return Err("Lhs.Rhs".to_string()),
2828                            }
2829                        }
2830                        _ => return Err("Lhs".to_string()),
2831                    }
2832                    test_ident(rhs, "d")?;
2833                }
2834                _ => return Err("Outer".to_string()),
2835            }
2836            Ok(())
2837        });
2838    }
2839
2840    fn test_expr_pg(src: &'static str, f: impl FnOnce(&Expression<'_>) -> Result<(), String>) {
2841        let mut issues = Issues::new(src);
2842        let options = ParseOptions::new().dialect(SQLDialect::PostgreSQL);
2843        let mut parser = Parser::new(src, &mut issues, &options);
2844        let res = parse_expression_unreserved(&mut parser, PRIORITY_MAX)
2845            .expect("Expression in test_expr_pg");
2846        if let Err(e) = f(&res) {
2847            panic!("Error parsing {}: {}\nGot {:#?}", src, e, res);
2848        }
2849    }
2850
2851    #[test]
2852    fn quantifier_any() {
2853        test_expr_pg(
2854            "salary > ANY (SELECT max_salary FROM departments)",
2855            |e| match e {
2856                Expression::Binary(b) => match &b.rhs {
2857                    Expression::Quantifier(q) => {
2858                        assert!(matches!(q.quantifier, Quantifier::Any(_)));
2859                        Ok(())
2860                    }
2861                    _ => Err(format!("Expected Quantifier RHS, got {:?}", b.rhs)),
2862                },
2863                _ => Err(format!("Expected Binary expression, got {:?}", e)),
2864            },
2865        );
2866    }
2867
2868    #[test]
2869    fn quantifier_some() {
2870        test_expr_pg("x = SOME (ARRAY[1, 2, 3])", |e| match e {
2871            Expression::Binary(b) => match &b.rhs {
2872                Expression::Quantifier(q) => {
2873                    assert!(matches!(q.quantifier, Quantifier::Some(_)));
2874                    Ok(())
2875                }
2876                _ => Err(format!("Expected Quantifier RHS, got {:?}", b.rhs)),
2877            },
2878            _ => Err(format!("Expected Binary expression, got {:?}", e)),
2879        });
2880    }
2881
2882    #[test]
2883    fn quantifier_all() {
2884        test_expr_pg("price <= ALL (SELECT price FROM products)", |e| match e {
2885            Expression::Binary(b) => match &b.rhs {
2886                Expression::Quantifier(q) => {
2887                    assert!(matches!(q.quantifier, Quantifier::All(_)));
2888                    Ok(())
2889                }
2890                _ => Err(format!("Expected Quantifier RHS, got {:?}", b.rhs)),
2891            },
2892            _ => Err(format!("Expected Binary expression, got {:?}", e)),
2893        });
2894    }
2895}