mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-12-23 11:12:51 +00:00
Support for Postgres array slice syntax (#1290)
Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
80c03f5c6a
commit
afa5f08db9
5 changed files with 356 additions and 61 deletions
|
|
@ -2544,8 +2544,7 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
} else if Token::LBracket == tok {
|
||||
if dialect_of!(self is PostgreSqlDialect | DuckDbDialect | GenericDialect) {
|
||||
// parse index
|
||||
self.parse_array_index(expr)
|
||||
self.parse_subscript(expr)
|
||||
} else if dialect_of!(self is SnowflakeDialect) {
|
||||
self.prev_token();
|
||||
self.parse_json_access(expr)
|
||||
|
|
@ -2573,18 +2572,87 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_array_index(&mut self, expr: Expr) -> Result<Expr, ParserError> {
|
||||
let index = self.parse_expr()?;
|
||||
self.expect_token(&Token::RBracket)?;
|
||||
let mut indexes: Vec<Expr> = vec![index];
|
||||
while self.consume_token(&Token::LBracket) {
|
||||
let index = self.parse_expr()?;
|
||||
self.expect_token(&Token::RBracket)?;
|
||||
indexes.push(index);
|
||||
/// Parses an array subscript like
|
||||
/// * `[:]`
|
||||
/// * `[l]`
|
||||
/// * `[l:]`
|
||||
/// * `[:u]`
|
||||
/// * `[l:u]`
|
||||
/// * `[l:u:s]`
|
||||
///
|
||||
/// Parser is right after `[`
|
||||
fn parse_subscript_inner(&mut self) -> Result<Subscript, ParserError> {
|
||||
// at either `<lower>:(rest)` or `:(rest)]`
|
||||
let lower_bound = if self.consume_token(&Token::Colon) {
|
||||
None
|
||||
} else {
|
||||
Some(self.parse_expr()?)
|
||||
};
|
||||
|
||||
// check for end
|
||||
if self.consume_token(&Token::RBracket) {
|
||||
if let Some(lower_bound) = lower_bound {
|
||||
return Ok(Subscript::Index { index: lower_bound });
|
||||
};
|
||||
return Ok(Subscript::Slice {
|
||||
lower_bound,
|
||||
upper_bound: None,
|
||||
stride: None,
|
||||
});
|
||||
}
|
||||
Ok(Expr::ArrayIndex {
|
||||
obj: Box::new(expr),
|
||||
indexes,
|
||||
|
||||
// consume the `:`
|
||||
if lower_bound.is_some() {
|
||||
self.expect_token(&Token::Colon)?;
|
||||
}
|
||||
|
||||
// we are now at either `]`, `<upper>(rest)]`
|
||||
let upper_bound = if self.consume_token(&Token::RBracket) {
|
||||
return Ok(Subscript::Slice {
|
||||
lower_bound,
|
||||
upper_bound: None,
|
||||
stride: None,
|
||||
});
|
||||
} else {
|
||||
Some(self.parse_expr()?)
|
||||
};
|
||||
|
||||
// check for end
|
||||
if self.consume_token(&Token::RBracket) {
|
||||
return Ok(Subscript::Slice {
|
||||
lower_bound,
|
||||
upper_bound,
|
||||
stride: None,
|
||||
});
|
||||
}
|
||||
|
||||
// we are now at `:]` or `:stride]`
|
||||
self.expect_token(&Token::Colon)?;
|
||||
let stride = if self.consume_token(&Token::RBracket) {
|
||||
None
|
||||
} else {
|
||||
Some(self.parse_expr()?)
|
||||
};
|
||||
|
||||
if stride.is_some() {
|
||||
self.expect_token(&Token::RBracket)?;
|
||||
}
|
||||
|
||||
Ok(Subscript::Slice {
|
||||
lower_bound,
|
||||
upper_bound,
|
||||
stride,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses an array subscript like `[1:3]`
|
||||
///
|
||||
/// Parser is right after `[`
|
||||
pub fn parse_subscript(&mut self, expr: Expr) -> Result<Expr, ParserError> {
|
||||
let subscript = self.parse_subscript_inner()?;
|
||||
Ok(Expr::Subscript {
|
||||
expr: Box::new(expr),
|
||||
subscript: Box::new(subscript),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -2838,7 +2906,7 @@ impl<'a> Parser<'a> {
|
|||
Ok(Self::MUL_DIV_MOD_OP_PREC)
|
||||
}
|
||||
Token::DoubleColon => Ok(50),
|
||||
Token::Colon => Ok(50),
|
||||
Token::Colon if dialect_of!(self is SnowflakeDialect) => Ok(50),
|
||||
Token::ExclamationMark => Ok(50),
|
||||
Token::LBracket | Token::Overlap | Token::CaretAt => Ok(50),
|
||||
Token::Arrow
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue