diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 89e135756..d47e5e43d 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -857,6 +857,8 @@ pub enum Statement { default_charset: Option, collation: Option, on_commit: Option, + clickhouse_order: Option>, + query_after: Option>, }, /// SQLite's `CREATE VIRTUAL TABLE .. USING ()` CreateVirtualTable { @@ -1332,6 +1334,8 @@ impl fmt::Display for Statement { engine, collation, on_commit, + clickhouse_order, + query_after, } => { // We want to allow the following options // Empty column list, allowed by PostgreSQL: @@ -1364,7 +1368,7 @@ impl fmt::Display for Statement { write!(f, ", ")?; } write!(f, "{})", display_comma_separated(constraints))?; - } else if query.is_none() && like.is_none() { + } else if query.is_none() && query_after.is_none() && like.is_none() { // PostgreSQL allows `CREATE TABLE t ();`, but requires empty parens write!(f, " ()")?; } @@ -1476,6 +1480,14 @@ impl fmt::Display for Statement { write!(f, " COLLATE={}", collation)?; } + if let Some(clickhouse_order) = clickhouse_order { + write!(f, " ORDER BY {}", display_comma_separated(clickhouse_order))?; + } + + if let Some(query_after) = query_after { + write!(f, " AS {}", query_after)?; + } + if on_commit.is_some() { let on_commit = match on_commit { Some(OnCommit::DeleteRows) => "ON COMMIT DELETE ROWS", diff --git a/src/parser.rs b/src/parser.rs index 1ca493b98..14f54a560 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1672,6 +1672,8 @@ impl<'a> Parser<'a> { engine: None, collation: None, on_commit: None, + clickhouse_order: None, + query_after: None, }) } @@ -1877,6 +1879,20 @@ impl<'a> Parser<'a> { None }; + let clickhouse_order = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) { + self.parse_comma_separated(Parser::parse_identifier).ok() + } else { + None + }; + + //in clickhouse, query comes after engine = + + let query_after = if self.parse_keyword(Keyword::AS) { + Some(Box::new(self.parse_query()?)) + } else { + None + }; + let on_commit: Option = if self.parse_keywords(&[Keyword::ON, Keyword::COMMIT, Keyword::DELETE, Keyword::ROWS]) { @@ -1916,6 +1932,8 @@ impl<'a> Parser<'a> { default_charset, collation, on_commit, + clickhouse_order, + query_after, }) } diff --git a/tests/sqpparser_clickhouse.rs b/tests/sqpparser_clickhouse.rs index dfd555200..5105404da 100644 --- a/tests/sqpparser_clickhouse.rs +++ b/tests/sqpparser_clickhouse.rs @@ -118,6 +118,37 @@ fn parse_array_expr() { ) } +#[test] +fn parse_create() { + let sql = "CREATE TABLE TEST (a STRING, b UInt64) ENGINE=MergeTree ORDER BY a"; + let stm = clickhouse().verified_stmt(sql); + match stm { + Statement::CreateTable { + clickhouse_order, .. + } => assert_eq!( + clickhouse_order, + Some(vec!(Ident { + value: "a".to_string(), + quote_style: None + })) + ), + _ => panic!("Expected Create tabme"), + } +} + + +#[test] +fn parse_select_from_create() { + let sql = "CREATE TABLE TEST ENGINE=MergeTree ORDER BY a AS SELECT * FROM source"; + clickhouse().verified_stmt(sql); +} + +#[test] +fn parse_select_from_create_s3() { + let sql = "CREATE TABLE TEST ENGINE=S3 ORDER BY a AS SELECT * FROM source"; + clickhouse().verified_stmt(sql); +} + fn clickhouse() -> TestedDialects { TestedDialects { dialects: vec![Box::new(ClickHouseDialect {})],