Support for ClickHouse array types (e.g. [1,2,3]) (#429)

This commit is contained in:
Simon Liu 2022-03-09 00:44:32 +08:00 committed by GitHub
parent 994b86a45c
commit 3f5619446f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 14 deletions

View file

@ -157,6 +157,24 @@ impl fmt::Display for ObjectName {
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Array {
pub elem: Vec<Expr>,
pub named: bool,
}
impl fmt::Display for Array {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}[{}]",
if self.named { "ARRAY" } else { "" },
display_comma_separated(&self.elem)
)
}
}
/// An SQL expression of any type.
///
/// The parser does not distinguish between expressions of different types
@ -298,7 +316,7 @@ pub enum Expr {
indexs: Vec<Expr>,
},
/// An array expression e.g. `ARRAY[1, 2]`
Array(Vec<Expr>),
Array(Array),
}
impl fmt::Display for Expr {
@ -482,7 +500,7 @@ impl fmt::Display for Expr {
Ok(())
}
Expr::Array(set) => {
write!(f, "ARRAY[{}]", display_comma_separated(set))
write!(f, "{}", set)
}
}
}

View file

@ -420,7 +420,7 @@ impl<'a> Parser<'a> {
Keyword::TRIM => self.parse_trim_expr(),
Keyword::INTERVAL => self.parse_literal_interval(),
Keyword::LISTAGG => self.parse_listagg_expr(),
Keyword::ARRAY => self.parse_array_expr(),
Keyword::ARRAY => self.parse_array_expr(true),
Keyword::NOT => Ok(Expr::UnaryOp {
op: UnaryOperator::Not,
expr: Box::new(self.parse_subexpr(Self::UNARY_NOT_PREC)?),
@ -450,6 +450,7 @@ impl<'a> Parser<'a> {
_ => Ok(Expr::Identifier(w.to_ident())),
},
}, // End of Token::Word
Token::LBracket => self.parse_array_expr(false),
tok @ Token::Minus | tok @ Token::Plus => {
let op = if tok == Token::Plus {
UnaryOperator::Plus
@ -825,11 +826,13 @@ impl<'a> Parser<'a> {
}
}
pub fn parse_array_expr(&mut self) -> Result<Expr, ParserError> {
self.expect_token(&Token::LBracket)?;
pub fn parse_array_expr(&mut self, named: bool) -> Result<Expr, ParserError> {
if named {
self.expect_token(&Token::LBracket)?;
}
let exprs = self.parse_comma_separated(Parser::parse_expr)?;
self.expect_token(&Token::RBracket)?;
Ok(Expr::Array(exprs))
Ok(Expr::Array(Array { elem: exprs, named }))
}
/// Parse a SQL LISTAGG expression, e.g. `LISTAGG(...) WITHIN GROUP (ORDER BY ...)`.