mirror of
				https://github.com/apache/datafusion-sqlparser-rs.git
				synced 2025-10-30 06:47:17 +00:00 
			
		
		
		
	Support for Snowflake ASOF joins (#1288)
This commit is contained in:
		
							parent
							
								
									375742d1fa
								
							
						
					
					
						commit
						80c03f5c6a
					
				
					 5 changed files with 123 additions and 3 deletions
				
			
		|  | @ -1562,6 +1562,15 @@ impl fmt::Display for Join { | |||
|             ), | ||||
|             JoinOperator::CrossApply => write!(f, " CROSS APPLY {}", self.relation), | ||||
|             JoinOperator::OuterApply => write!(f, " OUTER APPLY {}", self.relation), | ||||
|             JoinOperator::AsOf { | ||||
|                 match_condition, | ||||
|                 constraint, | ||||
|             } => write!( | ||||
|                 f, | ||||
|                 " ASOF JOIN {} MATCH_CONDITION ({match_condition}){}", | ||||
|                 self.relation, | ||||
|                 suffix(constraint) | ||||
|             ), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -1587,6 +1596,14 @@ pub enum JoinOperator { | |||
|     CrossApply, | ||||
|     /// OUTER APPLY (non-standard)
 | ||||
|     OuterApply, | ||||
|     /// `ASOF` joins are used for joining tables containing time-series data
 | ||||
|     /// whose timestamp columns do not match exactly.
 | ||||
|     ///
 | ||||
|     /// See <https://docs.snowflake.com/en/sql-reference/constructs/asof-join>.
 | ||||
|     AsOf { | ||||
|         match_condition: Expr, | ||||
|         constraint: JoinConstraint, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] | ||||
|  |  | |||
|  | @ -91,6 +91,7 @@ define_keywords!( | |||
|     AS, | ||||
|     ASC, | ||||
|     ASENSITIVE, | ||||
|     ASOF, | ||||
|     ASSERT, | ||||
|     ASYMMETRIC, | ||||
|     AT, | ||||
|  | @ -418,6 +419,7 @@ define_keywords!( | |||
|     MATCH, | ||||
|     MATCHED, | ||||
|     MATCHES, | ||||
|     MATCH_CONDITION, | ||||
|     MATCH_RECOGNIZE, | ||||
|     MATERIALIZED, | ||||
|     MAX, | ||||
|  |  | |||
|  | @ -3196,6 +3196,16 @@ impl<'a> Parser<'a> { | |||
|         Ok(values) | ||||
|     } | ||||
| 
 | ||||
|     pub fn parse_parenthesized<T, F>(&mut self, mut f: F) -> Result<T, ParserError> | ||||
|     where | ||||
|         F: FnMut(&mut Parser<'a>) -> Result<T, ParserError>, | ||||
|     { | ||||
|         self.expect_token(&Token::LParen)?; | ||||
|         let res = f(self)?; | ||||
|         self.expect_token(&Token::RParen)?; | ||||
|         Ok(res) | ||||
|     } | ||||
| 
 | ||||
|     /// Parse a comma-separated list of 0+ items accepted by `F`
 | ||||
|     pub fn parse_comma_separated0<T, F>(&mut self, f: F) -> Result<Vec<T>, ParserError> | ||||
|     where | ||||
|  | @ -8505,6 +8515,18 @@ impl<'a> Parser<'a> { | |||
|                     relation: self.parse_table_factor()?, | ||||
|                     join_operator: JoinOperator::OuterApply, | ||||
|                 } | ||||
|             } else if self.parse_keyword(Keyword::ASOF) { | ||||
|                 self.expect_keyword(Keyword::JOIN)?; | ||||
|                 let relation = self.parse_table_factor()?; | ||||
|                 self.expect_keyword(Keyword::MATCH_CONDITION)?; | ||||
|                 let match_condition = self.parse_parenthesized(Self::parse_expr)?; | ||||
|                 Join { | ||||
|                     relation, | ||||
|                     join_operator: JoinOperator::AsOf { | ||||
|                         match_condition, | ||||
|                         constraint: self.parse_join_constraint(false)?, | ||||
|                     }, | ||||
|                 } | ||||
|             } else { | ||||
|                 let natural = self.parse_keyword(Keyword::NATURAL); | ||||
|                 let peek_keyword = if let Token::Word(w) = self.peek_token().token { | ||||
|  | @ -8951,9 +8973,7 @@ impl<'a> Parser<'a> { | |||
|             }; | ||||
| 
 | ||||
|         self.expect_keyword(Keyword::PATTERN)?; | ||||
|         self.expect_token(&Token::LParen)?; | ||||
|         let pattern = self.parse_pattern()?; | ||||
|         self.expect_token(&Token::RParen)?; | ||||
|         let pattern = self.parse_parenthesized(Self::parse_pattern)?; | ||||
| 
 | ||||
|         self.expect_keyword(Keyword::DEFINE)?; | ||||
| 
 | ||||
|  |  | |||
|  | @ -312,6 +312,20 @@ pub fn table(name: impl Into<String>) -> TableFactor { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn table_with_alias(name: impl Into<String>, alias: impl Into<String>) -> TableFactor { | ||||
|     TableFactor::Table { | ||||
|         name: ObjectName(vec![Ident::new(name)]), | ||||
|         alias: Some(TableAlias { | ||||
|             name: Ident::new(alias), | ||||
|             columns: vec![], | ||||
|         }), | ||||
|         args: None, | ||||
|         with_hints: vec![], | ||||
|         version: None, | ||||
|         partitions: vec![], | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn join(relation: TableFactor) -> Join { | ||||
|     Join { | ||||
|         relation, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Joey Hain
						Joey Hain