Skip to content

Commit a7e2ee5

Browse files
committed
allow calling position as regular function
1 parent 993216f commit a7e2ee5

File tree

3 files changed

+23
-23
lines changed

3 files changed

+23
-23
lines changed

src/parser/mod.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,7 @@ impl<'a> Parser<'a> {
10381038
Keyword::CEIL => self.parse_ceil_floor_expr(true),
10391039
Keyword::FLOOR => self.parse_ceil_floor_expr(false),
10401040
Keyword::POSITION if self.peek_token().token == Token::LParen => {
1041-
self.parse_position_expr()
1041+
self.parse_position_expr(w.to_ident())
10421042
}
10431043
Keyword::SUBSTRING => self.parse_substring_expr(),
10441044
Keyword::OVERLAY => self.parse_overlay_expr(),
@@ -1689,24 +1689,25 @@ impl<'a> Parser<'a> {
16891689
}
16901690
}
16911691

1692-
pub fn parse_position_expr(&mut self) -> Result<Expr, ParserError> {
1693-
// PARSE SELECT POSITION('@' in field)
1694-
self.expect_token(&Token::LParen)?;
1692+
pub fn parse_position_expr(&mut self, ident: Ident) -> Result<Expr, ParserError> {
1693+
match self.maybe_parse(|p| {
1694+
// PARSE SELECT POSITION('@' in field)
1695+
p.expect_token(&Token::LParen)?;
16951696

1696-
// Parse the subexpr till the IN keyword
1697-
let expr = self.parse_subexpr(Self::BETWEEN_PREC)?;
1698-
if self.parse_keyword(Keyword::IN) {
1699-
let from = self.parse_expr()?;
1700-
self.expect_token(&Token::RParen)?;
1697+
// Parse the subexpr till the IN keyword
1698+
let expr = p.parse_subexpr(Self::BETWEEN_PREC)?;
1699+
p.expect_keyword(Keyword::IN)?;
1700+
let from = p.parse_expr()?;
1701+
p.expect_token(&Token::RParen)?;
17011702
Ok(Expr::Position {
17021703
expr: Box::new(expr),
17031704
r#in: Box::new(from),
17041705
})
1705-
} else {
1706-
parser_err!(
1707-
"Position function must include IN keyword".to_string(),
1708-
self.peek_token().location
1709-
)
1706+
}) {
1707+
Some(expr) => Ok(expr),
1708+
// Snowflake supports `position` as an ordinary function call
1709+
// without the special `IN` syntax.
1710+
None => self.parse_function(ObjectName(vec![ident])),
17101711
}
17111712
}
17121713

tests/sqlparser_common.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4140,7 +4140,7 @@ fn parse_scalar_function_in_projection() {
41404140

41414141
for function_name in names {
41424142
// like SELECT sqrt(id) FROM foo
4143-
let sql = dbg!(format!("SELECT {function_name}(id) FROM foo"));
4143+
let sql = format!("SELECT {function_name}(id) FROM foo");
41444144
let select = verified_only_select(&sql);
41454145
assert_eq!(
41464146
&call(function_name, [Expr::Identifier(Ident::new("id"))]),
@@ -8202,17 +8202,10 @@ fn parse_position() {
82028202

82038203
#[test]
82048204
fn parse_position_negative() {
8205-
let sql = "SELECT POSITION(foo) from bar";
8206-
let res = parse_sql_statements(sql);
8207-
assert_eq!(
8208-
ParserError::ParserError("Position function must include IN keyword".to_string()),
8209-
res.unwrap_err()
8210-
);
8211-
82128205
let sql = "SELECT POSITION(foo IN) from bar";
82138206
let res = parse_sql_statements(sql);
82148207
assert_eq!(
8215-
ParserError::ParserError("Expected: an expression:, found: )".to_string()),
8208+
ParserError::ParserError("Expected: (, found: )".to_string()),
82168209
res.unwrap_err()
82178210
);
82188211
}

tests/sqlparser_snowflake.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2256,3 +2256,9 @@ fn asof_joins() {
22562256
"ORDER BY s.observed",
22572257
));
22582258
}
2259+
2260+
#[test]
2261+
fn test() {
2262+
snowflake().verified_query("SELECT position('an', 'banana', 1)");
2263+
snowflake().verified_query("SELECT n, h, POSITION(n IN h) FROM pos");
2264+
}

0 commit comments

Comments
 (0)