Skip to content

Commit e431e2c

Browse files
SQLite: support CAST(expr AS) with empty type name
1 parent 0cb62a1 commit e431e2c

5 files changed

Lines changed: 40 additions & 2 deletions

File tree

‎src/ast/mod.rs‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2031,7 +2031,11 @@ impl fmt::Display for Expr {
20312031
format,
20322032
} => match kind {
20332033
CastKind::Cast => {
2034-
write!(f, "CAST({expr} AS {data_type}")?;
2034+
if matches!(data_type, DataType::Unspecified) {
2035+
write!(f, "CAST({expr} AS")?;
2036+
} else {
2037+
write!(f, "CAST({expr} AS {data_type}")?;
2038+
}
20352039
if let Some(format) = format {
20362040
write!(f, " FORMAT {format}")?;
20372041
}

‎src/dialect/mod.rs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,6 +1887,18 @@ pub trait Dialect: Debug + Any {
18871887
fn supports_map_literal_with_angle_brackets(&self) -> bool {
18881888
false
18891889
}
1890+
1891+
/// Returns true if the dialect supports `CAST(expr AS)` with an empty type name.
1892+
///
1893+
/// Example:
1894+
/// ```sql
1895+
/// SELECT CAST(a AS)
1896+
/// ```
1897+
///
1898+
/// [SQLite](https://www.sqlite.org/lang_expr.html)
1899+
fn supports_cast_empty_data_type_to_unspecified(&self) -> bool {
1900+
false
1901+
}
18901902
}
18911903

18921904
/// Operators for which precedence must be defined.

‎src/dialect/sqlite.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,8 @@ impl Dialect for SQLiteDialect {
129129
fn supports_numeric_literal_underscores(&self) -> bool {
130130
true
131131
}
132+
133+
fn supports_cast_empty_data_type_to_unspecified(&self) -> bool {
134+
true
135+
}
132136
}

‎src/parser/mod.rs‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2923,7 +2923,13 @@ impl<'a> Parser<'a> {
29232923
self.expect_token(&Token::LParen)?;
29242924
let expr = self.parse_expr()?;
29252925
self.expect_keyword_is(Keyword::AS)?;
2926-
let data_type = self.parse_data_type()?;
2926+
let data_type = if self.dialect.supports_cast_empty_data_type_to_unspecified()
2927+
&& self.peek_token_ref().token == Token::RParen
2928+
{
2929+
DataType::Unspecified
2930+
} else {
2931+
self.parse_data_type()?
2932+
};
29272933
let format = self.parse_optional_cast_format()?;
29282934
self.expect_token(&Token::RParen)?;
29292935
Ok(Expr::Cast {

‎tests/sqlparser_sqlite.rs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,18 @@ fn parse_pattern_operators_bind_at_like_precedence() {
957957
}
958958
}
959959

960+
#[test]
961+
fn test_cast_empty_type() {
962+
// SQLite allows CAST(expr AS) with an empty type name (typetoken can be empty)
963+
// See https://www.sqlite.org/lang_expr.html
964+
sqlite().verified_stmt("SELECT CAST(a AS)");
965+
966+
// Rejected by dialects without the flag
967+
assert!(TestedDialects::new(vec![Box::new(GenericDialect {})])
968+
.parse_sql_statements("SELECT CAST(a AS)")
969+
.is_err());
970+
}
971+
960972
fn sqlite() -> TestedDialects {
961973
TestedDialects::new(vec![Box::new(SQLiteDialect {})])
962974
}

0 commit comments

Comments
 (0)