Skip to content

Commit 0f7e144

Browse files
Support the ARRAY type of Snowflake (#699)
* Snowflake Array * Use the array data type * Try to fix build * Try to fix build * Change Array to option * Remove unused import
1 parent bbf32a9 commit 0f7e144

File tree

5 files changed

+52
-21
lines changed

5 files changed

+52
-21
lines changed

src/ast/data_type.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ pub enum DataType {
141141
/// Custom type such as enums
142142
Custom(ObjectName, Vec<String>),
143143
/// Arrays
144-
Array(Box<DataType>),
144+
Array(Option<Box<DataType>>),
145145
/// Enums
146146
Enum(Vec<String>),
147147
/// Set
@@ -232,7 +232,13 @@ impl fmt::Display for DataType {
232232
DataType::Text => write!(f, "TEXT"),
233233
DataType::String => write!(f, "STRING"),
234234
DataType::Bytea => write!(f, "BYTEA"),
235-
DataType::Array(ty) => write!(f, "{}[]", ty),
235+
DataType::Array(ty) => {
236+
if let Some(t) = &ty {
237+
write!(f, "{}[]", t)
238+
} else {
239+
write!(f, "ARRAY")
240+
}
241+
}
236242
DataType::Custom(ty, modifiers) => {
237243
if modifiers.is_empty() {
238244
write!(f, "{}", ty)

src/parser.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3672,13 +3672,17 @@ impl<'a> Parser<'a> {
36723672
Keyword::ENUM => Ok(DataType::Enum(self.parse_string_values()?)),
36733673
Keyword::SET => Ok(DataType::Set(self.parse_string_values()?)),
36743674
Keyword::ARRAY => {
3675-
// Hive array syntax. Note that nesting arrays - or other Hive syntax
3676-
// that ends with > will fail due to "C++" problem - >> is parsed as
3677-
// Token::ShiftRight
3678-
self.expect_token(&Token::Lt)?;
3679-
let inside_type = self.parse_data_type()?;
3680-
self.expect_token(&Token::Gt)?;
3681-
Ok(DataType::Array(Box::new(inside_type)))
3675+
if dialect_of!(self is SnowflakeDialect) {
3676+
Ok(DataType::Array(None))
3677+
} else {
3678+
// Hive array syntax. Note that nesting arrays - or other Hive syntax
3679+
// that ends with > will fail due to "C++" problem - >> is parsed as
3680+
// Token::ShiftRight
3681+
self.expect_token(&Token::Lt)?;
3682+
let inside_type = self.parse_data_type()?;
3683+
self.expect_token(&Token::Gt)?;
3684+
Ok(DataType::Array(Some(Box::new(inside_type))))
3685+
}
36823686
}
36833687
_ => {
36843688
self.prev_token();
@@ -3697,7 +3701,7 @@ impl<'a> Parser<'a> {
36973701
// Keyword::ARRAY syntax from above
36983702
while self.consume_token(&Token::LBracket) {
36993703
self.expect_token(&Token::RBracket)?;
3700-
data = DataType::Array(Box::new(data))
3704+
data = DataType::Array(Some(Box::new(data)))
37013705
}
37023706
Ok(data)
37033707
}

tests/sqlparser_common.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use sqlparser::ast::SelectItem::UnnamedExpr;
2424
use sqlparser::ast::*;
2525
use sqlparser::dialect::{
2626
AnsiDialect, BigQueryDialect, ClickHouseDialect, GenericDialect, HiveDialect, MsSqlDialect,
27-
PostgreSqlDialect, SQLiteDialect, SnowflakeDialect,
27+
MySqlDialect, PostgreSqlDialect, SQLiteDialect, SnowflakeDialect,
2828
};
2929
use sqlparser::keywords::ALL_KEYWORDS;
3030
use sqlparser::parser::{Parser, ParserError};
@@ -2099,7 +2099,7 @@ fn parse_create_table_hive_array() {
20992099
},
21002100
ColumnDef {
21012101
name: Ident::new("val"),
2102-
data_type: DataType::Array(Box::new(DataType::Int(None))),
2102+
data_type: DataType::Array(Some(Box::new(DataType::Int(None)))),
21032103
collation: None,
21042104
options: vec![],
21052105
},
@@ -2109,12 +2109,20 @@ fn parse_create_table_hive_array() {
21092109
_ => unreachable!(),
21102110
}
21112111

2112-
let res =
2113-
parse_sql_statements("CREATE TABLE IF NOT EXISTS something (name int, val array<int)");
2114-
assert!(res
2115-
.unwrap_err()
2116-
.to_string()
2117-
.contains("Expected >, found: )"));
2112+
// SnowflakeDialect using array diffrent
2113+
let dialects = TestedDialects {
2114+
dialects: vec![
2115+
Box::new(PostgreSqlDialect {}),
2116+
Box::new(HiveDialect {}),
2117+
Box::new(MySqlDialect {}),
2118+
],
2119+
};
2120+
let sql = "CREATE TABLE IF NOT EXISTS something (name int, val array<int)";
2121+
2122+
assert_eq!(
2123+
dialects.parse_sql_statements(sql).unwrap_err(),
2124+
ParserError::ParserError("Expected >, found: )".to_string())
2125+
);
21182126
}
21192127

21202128
#[test]

tests/sqlparser_postgres.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,9 +1324,9 @@ fn parse_array_index_expr() {
13241324
})],
13251325
named: true,
13261326
})),
1327-
data_type: DataType::Array(Box::new(DataType::Array(Box::new(DataType::Int(
1328-
None
1329-
)))))
1327+
data_type: DataType::Array(Some(Box::new(DataType::Array(Some(Box::new(
1328+
DataType::Int(None)
1329+
))))))
13301330
}))),
13311331
indexes: vec![num[1].clone(), num[2].clone()],
13321332
},

tests/sqlparser_snowflake.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,19 @@ fn test_single_table_in_parenthesis_with_alias() {
143143
);
144144
}
145145

146+
#[test]
147+
fn parse_array() {
148+
let sql = "SELECT CAST(a AS ARRAY) FROM customer";
149+
let select = snowflake().verified_only_select(sql);
150+
assert_eq!(
151+
&Expr::Cast {
152+
expr: Box::new(Expr::Identifier(Ident::new("a"))),
153+
data_type: DataType::Array(None),
154+
},
155+
expr_from_projection(only(&select.projection))
156+
);
157+
}
158+
146159
#[test]
147160
fn parse_json_using_colon() {
148161
let sql = "SELECT a:b FROM t";

0 commit comments

Comments
 (0)