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