ClickHouse: create view with fields and data types (#1292)

This commit is contained in:
Aleksei Piianin 2024-05-30 18:24:12 +02:00 committed by GitHub
parent 029a999645
commit 375742d1fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 60 additions and 2 deletions

View file

@ -815,7 +815,7 @@ impl fmt::Display for ColumnDef {
/// ///
/// Syntax /// Syntax
/// ```markdown /// ```markdown
/// <name> [OPTIONS(option, ...)] /// <name> [data_type][OPTIONS(option, ...)]
/// ///
/// option: <name> = <value> /// option: <name> = <value>
/// ``` /// ```
@ -824,18 +824,23 @@ impl fmt::Display for ColumnDef {
/// ```sql /// ```sql
/// name /// name
/// age OPTIONS(description = "age column", tag = "prod") /// age OPTIONS(description = "age column", tag = "prod")
/// created_at DateTime64
/// ``` /// ```
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct ViewColumnDef { pub struct ViewColumnDef {
pub name: Ident, pub name: Ident,
pub data_type: Option<DataType>,
pub options: Option<Vec<SqlOption>>, pub options: Option<Vec<SqlOption>>,
} }
impl fmt::Display for ViewColumnDef { impl fmt::Display for ViewColumnDef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)?; write!(f, "{}", self.name)?;
if let Some(data_type) = self.data_type.as_ref() {
write!(f, " {}", data_type)?;
}
if let Some(options) = self.options.as_ref() { if let Some(options) = self.options.as_ref() {
write!( write!(
f, f,

View file

@ -7282,7 +7282,16 @@ impl<'a> Parser<'a> {
} else { } else {
None None
}; };
Ok(ViewColumnDef { name, options }) let data_type = if dialect_of!(self is ClickHouseDialect) {
Some(self.parse_data_type()?)
} else {
None
};
Ok(ViewColumnDef {
name,
data_type,
options,
})
} }
/// Parse a parenthesized comma-separated list of unqualified, possibly quoted identifiers /// Parse a parenthesized comma-separated list of unqualified, possibly quoted identifiers

View file

@ -261,10 +261,12 @@ fn parse_create_view_with_options() {
vec![ vec![
ViewColumnDef { ViewColumnDef {
name: Ident::new("name"), name: Ident::new("name"),
data_type: None,
options: None, options: None,
}, },
ViewColumnDef { ViewColumnDef {
name: Ident::new("age"), name: Ident::new("age"),
data_type: None,
options: Some(vec![SqlOption { options: Some(vec![SqlOption {
name: Ident::new("description"), name: Ident::new("description"),
value: Expr::Value(Value::DoubleQuotedString("field age".to_string())), value: Expr::Value(Value::DoubleQuotedString("field age".to_string())),

View file

@ -220,6 +220,47 @@ fn parse_create_table() {
); );
} }
#[test]
fn parse_create_view_with_fields_data_types() {
match clickhouse().verified_stmt(r#"CREATE VIEW v (i "int", f "String") AS SELECT * FROM t"#) {
Statement::CreateView { name, columns, .. } => {
assert_eq!(name, ObjectName(vec!["v".into()]));
assert_eq!(
columns,
vec![
ViewColumnDef {
name: "i".into(),
data_type: Some(DataType::Custom(
ObjectName(vec![Ident {
value: "int".into(),
quote_style: Some('"')
}]),
vec![]
)),
options: None
},
ViewColumnDef {
name: "f".into(),
data_type: Some(DataType::Custom(
ObjectName(vec![Ident {
value: "String".into(),
quote_style: Some('"')
}]),
vec![]
)),
options: None
},
]
);
}
_ => unreachable!(),
}
clickhouse()
.parse_sql_statements(r#"CREATE VIEW v (i, f) AS SELECT * FROM t"#)
.expect_err("CREATE VIEW with fields and without data types should be invalid");
}
#[test] #[test]
fn parse_double_equal() { fn parse_double_equal() {
clickhouse().one_statement_parses_to( clickhouse().one_statement_parses_to(

View file

@ -6319,6 +6319,7 @@ fn parse_create_view_with_columns() {
.into_iter() .into_iter()
.map(|name| ViewColumnDef { .map(|name| ViewColumnDef {
name, name,
data_type: None,
options: None options: None
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()