Skip to content

Commit f509acc

Browse files
yuval-illumexMazterQyou
authored andcommitted
Add Support in the "Position" Function (apache#463)
* Add support in the position function * Add Test * Add lint fixes * Remove if * Change from to in * Remove special method for position * Fix lint * PR Review
1 parent ef389d8 commit f509acc

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

src/ast/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@ pub enum Expr {
262262
field: DateTimeField,
263263
expr: Box<Expr>,
264264
},
265+
/// POSITION(<expr> in <expr>)
266+
Position {
267+
expr: Box<Expr>,
268+
r#in: Box<Expr>,
269+
},
265270
/// SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])
266271
Substring {
267272
expr: Box<Expr>,
@@ -418,6 +423,7 @@ impl fmt::Display for Expr {
418423
Expr::Cast { expr, data_type } => write!(f, "CAST({} AS {})", expr, data_type),
419424
Expr::TryCast { expr, data_type } => write!(f, "TRY_CAST({} AS {})", expr, data_type),
420425
Expr::Extract { field, expr } => write!(f, "EXTRACT({} FROM {})", field, expr),
426+
Expr::Position { expr, r#in } => write!(f, "POSITION({} IN {})", expr, r#in),
421427
Expr::Collate { expr, collation } => write!(f, "{} COLLATE {}", expr, collation),
422428
Expr::Nested(ast) => write!(f, "({})", ast),
423429
Expr::Value(v) => write!(f, "{}", v),

src/parser.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ impl<'a> Parser<'a> {
447447
Keyword::TRY_CAST => self.parse_try_cast_expr(),
448448
Keyword::EXISTS => self.parse_exists_expr(),
449449
Keyword::EXTRACT => self.parse_extract_expr(),
450+
Keyword::POSITION => self.parse_position_expr(),
450451
Keyword::SUBSTRING => self.parse_substring_expr(),
451452
Keyword::TRIM => self.parse_trim_expr(),
452453
Keyword::INTERVAL => self.parse_literal_interval(),
@@ -826,6 +827,24 @@ impl<'a> Parser<'a> {
826827
})
827828
}
828829

830+
pub fn parse_position_expr(&mut self) -> Result<Expr, ParserError> {
831+
// PARSE SELECT POSITION('@' in field)
832+
self.expect_token(&Token::LParen)?;
833+
834+
// Parse the subexpr till the IN keyword
835+
let expr = self.parse_subexpr(Self::BETWEEN_PREC)?;
836+
if self.parse_keyword(Keyword::IN) {
837+
let from = self.parse_expr()?;
838+
self.expect_token(&Token::RParen)?;
839+
Ok(Expr::Position {
840+
expr: Box::new(expr),
841+
r#in: Box::new(from),
842+
})
843+
} else {
844+
return parser_err!("Position function must include IN keyword".to_string());
845+
}
846+
}
847+
829848
pub fn parse_substring_expr(&mut self) -> Result<Expr, ParserError> {
830849
// PARSE SUBSTRING (EXPR [FROM 1] [FOR 3])
831850
self.expect_token(&Token::LParen)?;

tests/sqlparser_common.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4903,3 +4903,16 @@ fn parse_cursor() {
49034903
_ => unreachable!(),
49044904
}
49054905
}
4906+
4907+
#[test]
4908+
fn parse_position() {
4909+
let sql = "SELECT POSITION('@' IN field)";
4910+
let select = verified_only_select(sql);
4911+
assert_eq!(
4912+
&Expr::Position {
4913+
expr: Box::new(Expr::Value(Value::SingleQuotedString("@".to_string()))),
4914+
r#in: Box::new(Expr::Identifier(Ident::new("field"))),
4915+
},
4916+
expr_from_projection(only(&select.projection))
4917+
);
4918+
}

0 commit comments

Comments
 (0)