Skip to content

Commit 3709d42

Browse files
committed
snowflake: fix parsing for position
1 parent 262475e commit 3709d42

1 file changed

Lines changed: 66 additions & 18 deletions

File tree

src/parser.rs

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,11 @@ impl<'a> Parser<'a> {
185185
break;
186186
}
187187

188-
expr = self.parse_infix(expr, next_precedence)?;
188+
let (parsed_expr, success) = self.parse_infix(expr, next_precedence)?;
189+
expr = parsed_expr;
190+
if !success {
191+
break;
192+
}
189193
}
190194
Ok(expr)
191195
}
@@ -245,6 +249,7 @@ impl<'a> Parser<'a> {
245249
Keyword::CASE => self.parse_case_expr(),
246250
Keyword::CAST => self.parse_cast_expr(false),
247251
Keyword::TRY_CAST => self.parse_cast_expr(true),
252+
Keyword::POSITION => self.parse_position(),
248253
Keyword::EXISTS => self.parse_exists_expr(),
249254
Keyword::EXTRACT => self.parse_extract_expr(),
250255
Keyword::INTERVAL => self.parse_literal_interval(),
@@ -495,6 +500,33 @@ impl<'a> Parser<'a> {
495500
})
496501
}
497502

503+
// https://docs.snowflake.com/en/sql-reference/functions/position.html
504+
pub fn parse_position(&mut self) -> Result<Expr, ParserError> {
505+
self.expect_token(&Token::LParen)?;
506+
let expr1 = self.parse_expr()?;
507+
let mut args = vec![FunctionArg::Unnamed(expr1)];
508+
if self.consume_token(&Token::Comma) {
509+
let more_args = self.parse_comma_separated(Parser::parse_expr)?;
510+
for arg in more_args {
511+
args.push(FunctionArg::Unnamed(arg));
512+
}
513+
} else {
514+
self.expect_keyword(Keyword::IN)?;
515+
args.push(FunctionArg::Unnamed(self.parse_expr()?));
516+
}
517+
self.expect_token(&Token::RParen)?;
518+
Ok(Expr::Function(Function {
519+
name: ObjectName(vec![Ident {
520+
value: "POSITION".to_owned(),
521+
quote_style: None,
522+
}]),
523+
args,
524+
within_group: vec![],
525+
over: None,
526+
distinct: false,
527+
}))
528+
}
529+
498530
/// Parse a SQL EXISTS expression e.g. `WHERE EXISTS(SELECT ...)`.
499531
pub fn parse_exists_expr(&mut self) -> Result<Expr, ParserError> {
500532
self.expect_token(&Token::LParen)?;
@@ -700,7 +732,9 @@ impl<'a> Parser<'a> {
700732
}
701733

702734
/// Parse an operator following an expression
703-
pub fn parse_infix(&mut self, expr: Expr, precedence: u8) -> Result<Expr, ParserError> {
735+
/// In the case where an infix operator wasn't successfully parsed, but we don't want to fail,
736+
/// the bool will be false; otherwise it will be true
737+
pub fn parse_infix(&mut self, expr: Expr, precedence: u8) -> Result<(Expr, bool), ParserError> {
704738
let tok = self.next_token();
705739
let regular_binary_operator = match &tok {
706740
Token::Eq => Some(BinaryOperator::Eq),
@@ -745,33 +779,44 @@ impl<'a> Parser<'a> {
745779
};
746780

747781
if let Some(op) = regular_binary_operator {
748-
Ok(Expr::BinaryOp {
749-
left: Box::new(expr),
750-
op,
751-
right: Box::new(self.parse_subexpr(precedence)?),
752-
})
782+
Ok((
783+
Expr::BinaryOp {
784+
left: Box::new(expr),
785+
op,
786+
right: Box::new(self.parse_subexpr(precedence)?),
787+
},
788+
true,
789+
))
753790
} else if let Token::Word(w) = &tok {
754791
match w.keyword {
755792
Keyword::IS => {
756793
if self.parse_keyword(Keyword::NULL) {
757-
Ok(Expr::IsNull(Box::new(expr)))
794+
Ok((Expr::IsNull(Box::new(expr)), true))
758795
} else if self.parse_keywords(&[Keyword::NOT, Keyword::NULL]) {
759-
Ok(Expr::IsNotNull(Box::new(expr)))
796+
Ok((Expr::IsNotNull(Box::new(expr)), true))
760797
} else {
761798
self.expected("NULL or NOT NULL after IS", self.peek_token())
762799
}
763800
}
764801
Keyword::NOT | Keyword::IN | Keyword::BETWEEN | Keyword::LIKE | Keyword::ILIKE => {
765802
self.prev_token();
803+
// allow backtracking if parsing IN doesn't work
804+
// https://docs.snowflake.com/en/sql-reference/functions/position.html
805+
let orig_index = self.index;
766806
let negated = self.parse_keyword(Keyword::NOT);
767807
if self.parse_keyword(Keyword::IN) {
768-
self.parse_in(expr, negated)
808+
if let Ok(in_expr) = self.parse_in(expr.clone(), negated) {
809+
Ok((in_expr, true))
810+
} else {
811+
self.index = orig_index;
812+
Ok((expr, false))
813+
}
769814
} else if self.parse_keyword(Keyword::BETWEEN) {
770-
self.parse_between(expr, negated)
815+
Ok((self.parse_between(expr, negated)?, true))
771816
} else if self.parse_keyword(Keyword::LIKE) {
772-
self.parse_like(expr, true, negated)
817+
Ok((self.parse_like(expr, true, negated)?, true))
773818
} else if self.parse_keyword(Keyword::ILIKE) {
774-
self.parse_like(expr, false, negated)
819+
Ok((self.parse_like(expr, false, negated)?, true))
775820
} else {
776821
self.expected("IN or BETWEEN or [I]LIKE after NOT", self.peek_token())
777822
}
@@ -780,13 +825,16 @@ impl<'a> Parser<'a> {
780825
_ => panic!("No infix parser for token {:?}", tok),
781826
}
782827
} else if Token::DoubleColon == tok {
783-
self.parse_pg_cast(expr)
828+
Ok((self.parse_pg_cast(expr)?, true))
784829
} else if Token::ExclamationMark == tok {
785830
// PostgreSQL factorial operation
786-
Ok(Expr::UnaryOp {
787-
op: UnaryOperator::PGPostfixFactorial,
788-
expr: Box::new(expr),
789-
})
831+
Ok((
832+
Expr::UnaryOp {
833+
op: UnaryOperator::PGPostfixFactorial,
834+
expr: Box::new(expr),
835+
},
836+
true,
837+
))
790838
} else {
791839
// Can only happen if `get_next_precedence` got out of sync with this function
792840
panic!("No infix parser for token {:?}", tok)

0 commit comments

Comments
 (0)