Skip to main content

qusql_parse/
expression.rs

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