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