Skip to content

Commit fee2963

Browse files
committed
allow calling position as regular function
1 parent 3c33ac1 commit fee2963

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
@@ -1035,7 +1035,7 @@ impl<'a> Parser<'a> {
10351035
Keyword::CEIL => self.parse_ceil_floor_expr(true),
10361036
Keyword::FLOOR => self.parse_ceil_floor_expr(false),
10371037
Keyword::POSITION if self.peek_token().token == Token::LParen => {
1038-
self.parse_position_expr()
1038+
self.parse_position_expr(w.to_ident())
10391039
}
10401040
Keyword::SUBSTRING => self.parse_substring_expr(),
10411041
Keyword::OVERLAY => self.parse_overlay_expr(),
@@ -1674,24 +1674,25 @@ impl<'a> Parser<'a> {
16741674
}
16751675
}
16761676

1677-
pub fn parse_position_expr(&mut self) -> Result<Expr, ParserError> {
1678-
// PARSE SELECT POSITION('@' in field)
1679-
self.expect_token(&Token::LParen)?;
1677+
pub fn parse_position_expr(&mut self, ident: Ident) -> Result<Expr, ParserError> {
1678+
match self.maybe_parse(|p| {
1679+
// PARSE SELECT POSITION('@' in field)
1680+
p.expect_token(&Token::LParen)?;
16801681

1681-
// Parse the subexpr till the IN keyword
1682-
let expr = self.parse_subexpr(Self::BETWEEN_PREC)?;
1683-
if self.parse_keyword(Keyword::IN) {
1684-
let from = self.parse_expr()?;
1685-
self.expect_token(&Token::RParen)?;
1682+
// Parse the subexpr till the IN keyword
1683+
let expr = p.parse_subexpr(Self::BETWEEN_PREC)?;
1684+
p.expect_keyword(Keyword::IN)?;
1685+
let from = p.parse_expr()?;
1686+
p.expect_token(&Token::RParen)?;
16861687
Ok(Expr::Position {
16871688
expr: Box::new(expr),
16881689
r#in: Box::new(from),
16891690
})
1690-
} else {
1691-
parser_err!(
1692-
"Position function must include IN keyword".to_string(),
1693-
self.peek_token().location
1694-
)
1691+
}) {
1692+
Some(expr) => Ok(expr),
1693+
// Snowflake supports `position` as an ordinary function call
1694+
// without the special `IN` syntax.
1695+
None => self.parse_function(ObjectName(vec![ident])),
16951696
}
16961697
}
16971698

tests/sqlparser_common.rs

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

40984098
for function_name in names {
40994099
// like SELECT sqrt(id) FROM foo
4100-
let sql = dbg!(format!("SELECT {function_name}(id) FROM foo"));
4100+
let sql = format!("SELECT {function_name}(id) FROM foo");
41014101
let select = verified_only_select(&sql);
41024102
assert_eq!(
41034103
&call(function_name, [Expr::Identifier(Ident::new("id"))]),
@@ -8097,17 +8097,10 @@ fn parse_position() {
80978097

80988098
#[test]
80998099
fn parse_position_negative() {
8100-
let sql = "SELECT POSITION(foo) from bar";
8101-
let res = parse_sql_statements(sql);
8102-
assert_eq!(
8103-
ParserError::ParserError("Position function must include IN keyword".to_string()),
8104-
res.unwrap_err()
8105-
);
8106-
81078100
let sql = "SELECT POSITION(foo IN) from bar";
81088101
let res = parse_sql_statements(sql);
81098102
assert_eq!(
8110-
ParserError::ParserError("Expected an expression:, found: )".to_string()),
8103+
ParserError::ParserError("Expected (, found: )".to_string()),
81118104
res.unwrap_err()
81128105
);
81138106
}

tests/sqlparser_snowflake.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1785,3 +1785,9 @@ fn asof_joins() {
17851785
"ORDER BY s.observed",
17861786
));
17871787
}
1788+
1789+
#[test]
1790+
fn test() {
1791+
snowflake().verified_query("SELECT position('an', 'banana', 1)");
1792+
snowflake().verified_query("SELECT n, h, POSITION(n IN h) FROM pos");
1793+
}

0 commit comments

Comments
 (0)