Skip to content

Add ORDER BY to CreateTable for ClickHouse #478

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,8 @@ pub enum Statement {
default_charset: Option<String>,
collation: Option<String>,
on_commit: Option<OnCommit>,
clickhouse_order: Option<Vec<Ident>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please change this field name to order by to match the SQL more closely (and perhaps add a comment that it is to support the clickhouse variant)?

query_after: Option<Box<Query>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add a comment here that this supports a query at the end of the statement (aka for clickhouse)

},
/// SQLite's `CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
CreateVirtualTable {
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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, " ()")?;
}
Expand Down Expand Up @@ -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",
Expand Down
18 changes: 18 additions & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1672,6 +1672,8 @@ impl<'a> Parser<'a> {
engine: None,
collation: None,
on_commit: None,
clickhouse_order: None,
query_after: None,
})
}

Expand Down Expand Up @@ -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<OnCommit> =
if self.parse_keywords(&[Keyword::ON, Keyword::COMMIT, Keyword::DELETE, Keyword::ROWS])
{
Expand Down Expand Up @@ -1916,6 +1932,8 @@ impl<'a> Parser<'a> {
default_charset,
collation,
on_commit,
clickhouse_order,
query_after,
})
}

Expand Down
31 changes: 31 additions & 0 deletions tests/sqpparser_clickhouse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {})],
Expand Down