mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-19 13:40:15 +00:00
feat: support SAFE_CAST for bigquery (#552)
Co-authored-by: togami2864 <yoshiaki.togami@plaid.co.jp>
This commit is contained in:
parent
2a04212e56
commit
e24951e080
4 changed files with 29 additions and 0 deletions
|
@ -285,6 +285,13 @@ pub enum Expr {
|
||||||
expr: Box<Expr>,
|
expr: Box<Expr>,
|
||||||
data_type: DataType,
|
data_type: DataType,
|
||||||
},
|
},
|
||||||
|
/// SAFE_CAST an expression to a different data type e.g. `SAFE_CAST(foo AS FLOAT64)`
|
||||||
|
// only available for BigQuery: https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#safe_casting
|
||||||
|
// this works the same as `TRY_CAST`
|
||||||
|
SafeCast {
|
||||||
|
expr: Box<Expr>,
|
||||||
|
data_type: DataType,
|
||||||
|
},
|
||||||
/// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
|
/// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
|
||||||
AtTimeZone {
|
AtTimeZone {
|
||||||
timestamp: Box<Expr>,
|
timestamp: Box<Expr>,
|
||||||
|
@ -442,6 +449,7 @@ impl fmt::Display for Expr {
|
||||||
}
|
}
|
||||||
Expr::Cast { expr, data_type } => write!(f, "CAST({} AS {})", expr, data_type),
|
Expr::Cast { expr, data_type } => write!(f, "CAST({} AS {})", expr, data_type),
|
||||||
Expr::TryCast { expr, data_type } => write!(f, "TRY_CAST({} AS {})", expr, data_type),
|
Expr::TryCast { expr, data_type } => write!(f, "TRY_CAST({} AS {})", expr, data_type),
|
||||||
|
Expr::SafeCast { expr, data_type } => write!(f, "SAFE_CAST({} AS {})", expr, data_type),
|
||||||
Expr::Extract { field, expr } => write!(f, "EXTRACT({} FROM {})", field, expr),
|
Expr::Extract { field, expr } => write!(f, "EXTRACT({} FROM {})", field, expr),
|
||||||
Expr::Position { expr, r#in } => write!(f, "POSITION({} IN {})", expr, r#in),
|
Expr::Position { expr, r#in } => write!(f, "POSITION({} IN {})", expr, r#in),
|
||||||
Expr::Collate { expr, collation } => write!(f, "{} COLLATE {}", expr, collation),
|
Expr::Collate { expr, collation } => write!(f, "{} COLLATE {}", expr, collation),
|
||||||
|
|
|
@ -439,6 +439,7 @@ define_keywords!(
|
||||||
ROWID,
|
ROWID,
|
||||||
ROWS,
|
ROWS,
|
||||||
ROW_NUMBER,
|
ROW_NUMBER,
|
||||||
|
SAFE_CAST,
|
||||||
SAVEPOINT,
|
SAVEPOINT,
|
||||||
SCHEMA,
|
SCHEMA,
|
||||||
SCOPE,
|
SCOPE,
|
||||||
|
|
|
@ -426,6 +426,7 @@ impl<'a> Parser<'a> {
|
||||||
Keyword::CASE => self.parse_case_expr(),
|
Keyword::CASE => self.parse_case_expr(),
|
||||||
Keyword::CAST => self.parse_cast_expr(),
|
Keyword::CAST => self.parse_cast_expr(),
|
||||||
Keyword::TRY_CAST => self.parse_try_cast_expr(),
|
Keyword::TRY_CAST => self.parse_try_cast_expr(),
|
||||||
|
Keyword::SAFE_CAST => self.parse_safe_cast_expr(),
|
||||||
Keyword::EXISTS => self.parse_exists_expr(false),
|
Keyword::EXISTS => self.parse_exists_expr(false),
|
||||||
Keyword::EXTRACT => self.parse_extract_expr(),
|
Keyword::EXTRACT => self.parse_extract_expr(),
|
||||||
Keyword::POSITION => self.parse_position_expr(),
|
Keyword::POSITION => self.parse_position_expr(),
|
||||||
|
@ -780,6 +781,19 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a BigQuery SAFE_CAST function e.g. `SAFE_CAST(expr AS FLOAT64)`
|
||||||
|
pub fn parse_safe_cast_expr(&mut self) -> Result<Expr, ParserError> {
|
||||||
|
self.expect_token(&Token::LParen)?;
|
||||||
|
let expr = self.parse_expr()?;
|
||||||
|
self.expect_keyword(Keyword::AS)?;
|
||||||
|
let data_type = self.parse_data_type()?;
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
Ok(Expr::SafeCast {
|
||||||
|
expr: Box::new(expr),
|
||||||
|
data_type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a SQL EXISTS expression e.g. `WHERE EXISTS(SELECT ...)`.
|
/// Parse a SQL EXISTS expression e.g. `WHERE EXISTS(SELECT ...)`.
|
||||||
pub fn parse_exists_expr(&mut self, negated: bool) -> Result<Expr, ParserError> {
|
pub fn parse_exists_expr(&mut self, negated: bool) -> Result<Expr, ParserError> {
|
||||||
self.expect_token(&Token::LParen)?;
|
self.expect_token(&Token::LParen)?;
|
||||||
|
|
|
@ -94,6 +94,12 @@ fn parse_table_identifiers() {
|
||||||
test_table_ident("abc5.GROUP", vec![Ident::new("abc5"), Ident::new("GROUP")]);
|
test_table_ident("abc5.GROUP", vec![Ident::new("abc5"), Ident::new("GROUP")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_cast_type() {
|
||||||
|
let sql = r#"SELECT SAFE_CAST(1 AS INT64)"#;
|
||||||
|
bigquery().verified_only_select(sql);
|
||||||
|
}
|
||||||
|
|
||||||
fn bigquery() -> TestedDialects {
|
fn bigquery() -> TestedDialects {
|
||||||
TestedDialects {
|
TestedDialects {
|
||||||
dialects: vec![Box::new(BigQueryDialect {})],
|
dialects: vec![Box::new(BigQueryDialect {})],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue