Skip to main content

qusql_parse/
values.rs

1//! PostgreSQL VALUES statement parsing and AST definitions.
2//!
3//! See https://www.postgresql.org/docs/current/sql-values.html
4// Licensed under the Apache License, Version 2.0
5// See LICENSE.TXT for details.
6
7use crate::keywords::Keyword;
8use crate::lexer::Token;
9use crate::parser::{ParseError, Parser};
10use crate::{Expression, OptSpanned, Span, Spanned};
11use alloc::format;
12use alloc::vec::Vec;
13
14/// Direction for FETCH clause (FIRST or NEXT)
15#[derive(Debug, Clone)]
16pub enum FetchDirection {
17    /// FETCH FIRST ...
18    First(Span),
19    /// FETCH NEXT ...
20    Next(Span),
21}
22
23impl Spanned for FetchDirection {
24    fn span(&self) -> Span {
25        match self {
26            FetchDirection::First(span) => span.clone(),
27            FetchDirection::Next(span) => span.clone(),
28        }
29    }
30}
31
32/// Representation of a FETCH clause in VALUES
33#[derive(Debug, Clone)]
34pub struct Fetch<'a> {
35    /// Span of the FETCH keyword
36    pub fetch_span: Span,
37    /// Direction (FIRST/NEXT) if present
38    pub direction: Option<FetchDirection>,
39    /// Row count expression if present
40    pub count: Option<Expression<'a>>,
41    /// Span of ROW/ROWS ONLY
42    pub row_span: Span,
43}
44
45/// Compute the span for a FETCH clause
46impl<'a> Spanned for Fetch<'a> {
47    fn span(&self) -> Span {
48        self.fetch_span
49            .join_span(&self.direction)
50            .join_span(&self.count)
51            .join_span(&self.row_span)
52    }
53}
54
55/// Parse a FETCH clause (assumes FETCH keyword already consumed)
56fn parse_fetch<'a>(parser: &mut Parser<'a, '_>, fetch_span: Span) -> Result<Fetch<'a>, ParseError> {
57    let direction = match &parser.token {
58        Token::Ident(_, Keyword::FIRST) => Some(FetchDirection::First(parser.consume())),
59        Token::Ident(_, Keyword::NEXT) => Some(FetchDirection::Next(parser.consume())),
60        _ => None,
61    };
62    let count = if !matches!(
63        &parser.token,
64        Token::Ident(_, Keyword::ROW | Keyword::ROWS | Keyword::ONLY)
65    ) {
66        Some(crate::expression::parse_expression_unreserved(
67            parser,
68            crate::expression::PRIORITY_MAX,
69        )?)
70    } else {
71        None
72    };
73    // Capture the span of ROW/ROWS ONLY
74    let row_span = match &parser.token {
75        Token::Ident(_, Keyword::ROW | Keyword::ROWS) => Some(parser.consume()),
76        _ => None,
77    };
78    let row_span = parser.consume_keyword(Keyword::ONLY)?.join_span(&row_span);
79    Ok(Fetch {
80        fetch_span,
81        direction,
82        count,
83        row_span,
84    })
85}
86
87/// Representation of a VALUES statement
88///
89/// ```
90/// # use qusql_parse::{SQLDialect, SQLArguments, ParseOptions, parse_statement, Values, Statement, Issues};
91/// # let options = ParseOptions::new().dialect(SQLDialect::PostgreSQL);
92/// #
93/// let sql = "VALUES (1, 'one'), (2, 'two')";
94/// let mut issues = Issues::new(sql);
95/// let stmt = parse_statement(sql, &mut issues, &options);
96///
97/// # assert!(issues.is_ok());
98/// let v: Values = match stmt {
99///     Some(Statement::Values(v)) => *v,
100///     _ => panic!("We should get a VALUES statement")
101/// };
102///
103/// println!("{:#?}", v.rows);
104/// ```
105#[derive(Debug, Clone)]
106pub struct Values<'a> {
107    pub values_span: Span,
108    pub rows: Vec<Vec<Expression<'a>>>,
109    pub order_by: Option<(Span, Vec<(Expression<'a>, crate::select::OrderFlag)>)>, // (ORDER BY span, list of (expr, OrderFlag))
110    pub limit: Option<(Span, Expression<'a>)>,
111    pub offset: Option<(Span, Expression<'a>)>,
112    pub fetch: Option<Fetch<'a>>,
113}
114
115impl<'a> Spanned for Values<'a> {
116    fn span(&self) -> Span {
117        self.values_span
118            .join_span(&self.rows)
119            .join_span(&self.order_by)
120            .join_span(&self.limit)
121            .join_span(&self.offset)
122            .join_span(&self.fetch)
123    }
124}
125
126/// Parse a VALUES statement (PostgreSQL style)
127pub(crate) fn parse_values<'a>(parser: &mut Parser<'a, '_>) -> Result<Values<'a>, ParseError> {
128    let values_span = parser.consume_keyword(Keyword::VALUES)?;
129    parser.postgres_only(&values_span);
130
131    let mut rows = Vec::new();
132    loop {
133        parser.consume_token(Token::LParen)?;
134        let mut row = Vec::new();
135        parser.recovered(
136            "')' or ','",
137            &|t| matches!(t, Token::RParen | Token::Comma),
138            |parser| {
139                loop {
140                    row.push(crate::expression::parse_expression_unreserved(
141                        parser,
142                        crate::expression::PRIORITY_MAX,
143                    )?);
144                    if parser.skip_token(Token::Comma).is_none() {
145                        break;
146                    }
147                }
148                Ok(())
149            },
150        )?;
151        parser.consume_token(Token::RParen)?;
152        rows.push(row);
153        if parser.skip_token(Token::Comma).is_none() {
154            break;
155        }
156    }
157    // Ensure all rows have the same number of columns
158    if let Some(first_row) = rows.first() {
159        let cols = first_row.len();
160        for row in rows.iter() {
161            if row.len() != cols {
162                parser
163                    .err(
164                        format!("This row has {} members", row.len()),
165                        &row.opt_span().unwrap(),
166                    )
167                    .frag(
168                        format!("Expected {} members", cols),
169                        &first_row.opt_span().unwrap(),
170                    );
171            }
172        }
173    }
174
175    // Parse optional ORDER BY
176    let order_by = if let Some(order_span) = parser.skip_keyword(Keyword::ORDER) {
177        let by_span = parser.consume_keyword(Keyword::BY)?;
178        let span = order_span.join_span(&by_span);
179        let mut items = Vec::new();
180        loop {
181            let expr = crate::expression::parse_expression_unreserved(
182                parser,
183                crate::expression::PRIORITY_MAX,
184            )?;
185            let order_flag = match &parser.token {
186                Token::Ident(_, Keyword::ASC) => crate::select::OrderFlag::Asc(parser.consume()),
187                Token::Ident(_, Keyword::DESC) => crate::select::OrderFlag::Desc(parser.consume()),
188                _ => crate::select::OrderFlag::None,
189            };
190            items.push((expr, order_flag));
191            if parser.skip_token(Token::Comma).is_none() {
192                break;
193            }
194        }
195        Some((span, items))
196    } else {
197        None
198    };
199
200    // Parse optional LIMIT
201    let limit = if let Some(limit_span) = parser.skip_keyword(Keyword::LIMIT) {
202        let expr = crate::expression::parse_expression_unreserved(
203            parser,
204            crate::expression::PRIORITY_MAX,
205        )?;
206        Some((limit_span, expr))
207    } else {
208        None
209    };
210
211    // Parse optional OFFSET
212    let offset = if let Some(offset_span) = parser.skip_keyword(Keyword::OFFSET) {
213        let expr = crate::expression::parse_expression_unreserved(
214            parser,
215            crate::expression::PRIORITY_MAX,
216        )?;
217        // Optionally consume ROW/ROWS
218        if matches!(parser.token, Token::Ident(_, Keyword::ROW | Keyword::ROWS)) {
219            parser.consume();
220        }
221        Some((offset_span, expr))
222    } else {
223        None
224    };
225
226    // Parse optional FETCH FIRST/NEXT ... ROW/ROWS ONLY
227    let fetch = if let Some(fetch_span) = parser.skip_keyword(Keyword::FETCH) {
228        Some(parse_fetch(parser, fetch_span)?)
229    } else {
230        None
231    };
232
233    Ok(Values {
234        values_span,
235        rows,
236        order_by,
237        limit,
238        offset,
239        fetch,
240    })
241}