mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-23 22:22:28 +00:00
Support TO
in CREATE VIEW
clause for Clickhouse (#1313)
Co-authored-by: Ifeanyi Ubah <ify1992@yahoo.com> Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
f16c1afed0
commit
f3d2f78fb2
7 changed files with 51 additions and 2 deletions
|
@ -2029,6 +2029,9 @@ pub enum Statement {
|
||||||
if_not_exists: bool,
|
if_not_exists: bool,
|
||||||
/// if true, has SQLite `TEMP` or `TEMPORARY` clause <https://www.sqlite.org/lang_createview.html>
|
/// if true, has SQLite `TEMP` or `TEMPORARY` clause <https://www.sqlite.org/lang_createview.html>
|
||||||
temporary: bool,
|
temporary: bool,
|
||||||
|
/// if not None, has Clickhouse `TO` clause, specify the table into which to insert results
|
||||||
|
/// <https://clickhouse.com/docs/en/sql-reference/statements/create/view#materialized-view>
|
||||||
|
to: Option<ObjectName>,
|
||||||
},
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// CREATE TABLE
|
/// CREATE TABLE
|
||||||
|
@ -3329,15 +3332,20 @@ impl fmt::Display for Statement {
|
||||||
with_no_schema_binding,
|
with_no_schema_binding,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
to,
|
||||||
} => {
|
} => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"CREATE {or_replace}{materialized}{temporary}VIEW {if_not_exists}{name}",
|
"CREATE {or_replace}{materialized}{temporary}VIEW {if_not_exists}{name}{to}",
|
||||||
or_replace = if *or_replace { "OR REPLACE " } else { "" },
|
or_replace = if *or_replace { "OR REPLACE " } else { "" },
|
||||||
materialized = if *materialized { "MATERIALIZED " } else { "" },
|
materialized = if *materialized { "MATERIALIZED " } else { "" },
|
||||||
name = name,
|
name = name,
|
||||||
temporary = if *temporary { "TEMPORARY " } else { "" },
|
temporary = if *temporary { "TEMPORARY " } else { "" },
|
||||||
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" }
|
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
|
||||||
|
to = to
|
||||||
|
.as_ref()
|
||||||
|
.map(|to| format!(" TO {to}"))
|
||||||
|
.unwrap_or_default()
|
||||||
)?;
|
)?;
|
||||||
if let Some(comment) = comment {
|
if let Some(comment) = comment {
|
||||||
write!(
|
write!(
|
||||||
|
|
|
@ -4172,6 +4172,14 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let to = if dialect_of!(self is ClickHouseDialect | GenericDialect)
|
||||||
|
&& self.parse_keyword(Keyword::TO)
|
||||||
|
{
|
||||||
|
Some(self.parse_object_name(false)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let comment = if dialect_of!(self is SnowflakeDialect | GenericDialect)
|
let comment = if dialect_of!(self is SnowflakeDialect | GenericDialect)
|
||||||
&& self.parse_keyword(Keyword::COMMENT)
|
&& self.parse_keyword(Keyword::COMMENT)
|
||||||
{
|
{
|
||||||
|
@ -4209,6 +4217,7 @@ impl<'a> Parser<'a> {
|
||||||
with_no_schema_binding,
|
with_no_schema_binding,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
to,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -315,6 +315,7 @@ fn parse_create_view_if_not_exists() {
|
||||||
with_no_schema_binding: late_binding,
|
with_no_schema_binding: late_binding,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("mydataset.newview", name.to_string());
|
assert_eq!("mydataset.newview", name.to_string());
|
||||||
assert_eq!(Vec::<ViewColumnDef>::new(), columns);
|
assert_eq!(Vec::<ViewColumnDef>::new(), columns);
|
||||||
|
|
|
@ -561,6 +561,21 @@ fn parse_select_star_except_no_parens() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_create_materialized_view() {
|
||||||
|
// example sql
|
||||||
|
// https://clickhouse.com/docs/en/guides/developer/cascading-materialized-views
|
||||||
|
let sql = concat!(
|
||||||
|
"CREATE MATERIALIZED VIEW analytics.monthly_aggregated_data_mv ",
|
||||||
|
"TO analytics.monthly_aggregated_data ",
|
||||||
|
"AS SELECT toDate(toStartOfMonth(event_time)) ",
|
||||||
|
"AS month, domain_name, sumState(count_views) ",
|
||||||
|
"AS sumCountViews FROM analytics.hourly_data ",
|
||||||
|
"GROUP BY domain_name, month"
|
||||||
|
);
|
||||||
|
clickhouse_and_generic().verified_stmt(sql);
|
||||||
|
}
|
||||||
|
|
||||||
fn clickhouse() -> TestedDialects {
|
fn clickhouse() -> TestedDialects {
|
||||||
TestedDialects {
|
TestedDialects {
|
||||||
dialects: vec![Box::new(ClickHouseDialect {})],
|
dialects: vec![Box::new(ClickHouseDialect {})],
|
||||||
|
|
|
@ -6279,6 +6279,7 @@ fn parse_create_view() {
|
||||||
with_no_schema_binding: late_binding,
|
with_no_schema_binding: late_binding,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
to,
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("myschema.myview", name.to_string());
|
assert_eq!("myschema.myview", name.to_string());
|
||||||
assert_eq!(Vec::<ViewColumnDef>::new(), columns);
|
assert_eq!(Vec::<ViewColumnDef>::new(), columns);
|
||||||
|
@ -6291,6 +6292,7 @@ fn parse_create_view() {
|
||||||
assert!(!late_binding);
|
assert!(!late_binding);
|
||||||
assert!(!if_not_exists);
|
assert!(!if_not_exists);
|
||||||
assert!(!temporary);
|
assert!(!temporary);
|
||||||
|
assert!(to.is_none())
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -6335,6 +6337,7 @@ fn parse_create_view_with_columns() {
|
||||||
with_no_schema_binding: late_binding,
|
with_no_schema_binding: late_binding,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
to,
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("v", name.to_string());
|
assert_eq!("v", name.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -6357,6 +6360,7 @@ fn parse_create_view_with_columns() {
|
||||||
assert!(!late_binding);
|
assert!(!late_binding);
|
||||||
assert!(!if_not_exists);
|
assert!(!if_not_exists);
|
||||||
assert!(!temporary);
|
assert!(!temporary);
|
||||||
|
assert!(to.is_none())
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -6378,6 +6382,7 @@ fn parse_create_view_temporary() {
|
||||||
with_no_schema_binding: late_binding,
|
with_no_schema_binding: late_binding,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
to,
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("myschema.myview", name.to_string());
|
assert_eq!("myschema.myview", name.to_string());
|
||||||
assert_eq!(Vec::<ViewColumnDef>::new(), columns);
|
assert_eq!(Vec::<ViewColumnDef>::new(), columns);
|
||||||
|
@ -6390,6 +6395,7 @@ fn parse_create_view_temporary() {
|
||||||
assert!(!late_binding);
|
assert!(!late_binding);
|
||||||
assert!(!if_not_exists);
|
assert!(!if_not_exists);
|
||||||
assert!(temporary);
|
assert!(temporary);
|
||||||
|
assert!(to.is_none())
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -6411,6 +6417,7 @@ fn parse_create_or_replace_view() {
|
||||||
with_no_schema_binding: late_binding,
|
with_no_schema_binding: late_binding,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
to,
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("v", name.to_string());
|
assert_eq!("v", name.to_string());
|
||||||
assert_eq!(columns, vec![]);
|
assert_eq!(columns, vec![]);
|
||||||
|
@ -6423,6 +6430,7 @@ fn parse_create_or_replace_view() {
|
||||||
assert!(!late_binding);
|
assert!(!late_binding);
|
||||||
assert!(!if_not_exists);
|
assert!(!if_not_exists);
|
||||||
assert!(!temporary);
|
assert!(!temporary);
|
||||||
|
assert!(to.is_none())
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -6448,6 +6456,7 @@ fn parse_create_or_replace_materialized_view() {
|
||||||
with_no_schema_binding: late_binding,
|
with_no_schema_binding: late_binding,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
to,
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("v", name.to_string());
|
assert_eq!("v", name.to_string());
|
||||||
assert_eq!(columns, vec![]);
|
assert_eq!(columns, vec![]);
|
||||||
|
@ -6460,6 +6469,7 @@ fn parse_create_or_replace_materialized_view() {
|
||||||
assert!(!late_binding);
|
assert!(!late_binding);
|
||||||
assert!(!if_not_exists);
|
assert!(!if_not_exists);
|
||||||
assert!(!temporary);
|
assert!(!temporary);
|
||||||
|
assert!(to.is_none())
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -6481,6 +6491,7 @@ fn parse_create_materialized_view() {
|
||||||
with_no_schema_binding: late_binding,
|
with_no_schema_binding: late_binding,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
to,
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("myschema.myview", name.to_string());
|
assert_eq!("myschema.myview", name.to_string());
|
||||||
assert_eq!(Vec::<ViewColumnDef>::new(), columns);
|
assert_eq!(Vec::<ViewColumnDef>::new(), columns);
|
||||||
|
@ -6493,6 +6504,7 @@ fn parse_create_materialized_view() {
|
||||||
assert!(!late_binding);
|
assert!(!late_binding);
|
||||||
assert!(!if_not_exists);
|
assert!(!if_not_exists);
|
||||||
assert!(!temporary);
|
assert!(!temporary);
|
||||||
|
assert!(to.is_none())
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -6514,6 +6526,7 @@ fn parse_create_materialized_view_with_cluster_by() {
|
||||||
with_no_schema_binding: late_binding,
|
with_no_schema_binding: late_binding,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
to,
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("myschema.myview", name.to_string());
|
assert_eq!("myschema.myview", name.to_string());
|
||||||
assert_eq!(Vec::<ViewColumnDef>::new(), columns);
|
assert_eq!(Vec::<ViewColumnDef>::new(), columns);
|
||||||
|
@ -6526,6 +6539,7 @@ fn parse_create_materialized_view_with_cluster_by() {
|
||||||
assert!(!late_binding);
|
assert!(!late_binding);
|
||||||
assert!(!if_not_exists);
|
assert!(!if_not_exists);
|
||||||
assert!(!temporary);
|
assert!(!temporary);
|
||||||
|
assert!(to.is_none())
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -552,6 +552,7 @@ fn parse_sf_create_or_replace_with_comment_for_snowflake() {
|
||||||
with_no_schema_binding: late_binding,
|
with_no_schema_binding: late_binding,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("v", name.to_string());
|
assert_eq!("v", name.to_string());
|
||||||
assert_eq!(columns, vec![]);
|
assert_eq!(columns, vec![]);
|
||||||
|
|
|
@ -171,6 +171,7 @@ fn parse_create_view_temporary_if_not_exists() {
|
||||||
with_no_schema_binding: late_binding,
|
with_no_schema_binding: late_binding,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("myschema.myview", name.to_string());
|
assert_eq!("myschema.myview", name.to_string());
|
||||||
assert_eq!(Vec::<ViewColumnDef>::new(), columns);
|
assert_eq!(Vec::<ViewColumnDef>::new(), columns);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue