mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-23 15:34:09 +00:00
ClickHouse CREATE TABLE Fixes: add ORDER BY and fix clause ordering (#824)
* Fix ClickHouse (add ORDER BY) * Improve test case
This commit is contained in:
parent
1cf913e717
commit
d69b875367
4 changed files with 59 additions and 11 deletions
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
|||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
use crate::ast::{
|
||||
ColumnDef, FileFormat, HiveDistributionStyle, HiveFormat, ObjectName, OnCommit, Query,
|
||||
ColumnDef, FileFormat, HiveDistributionStyle, HiveFormat, Ident, ObjectName, OnCommit, Query,
|
||||
SqlOption, Statement, TableConstraint,
|
||||
};
|
||||
use crate::parser::ParserError;
|
||||
|
@ -69,6 +69,7 @@ pub struct CreateTableBuilder {
|
|||
pub collation: Option<String>,
|
||||
pub on_commit: Option<OnCommit>,
|
||||
pub on_cluster: Option<String>,
|
||||
pub order_by: Option<Vec<Ident>>,
|
||||
}
|
||||
|
||||
impl CreateTableBuilder {
|
||||
|
@ -98,6 +99,7 @@ impl CreateTableBuilder {
|
|||
collation: None,
|
||||
on_commit: None,
|
||||
on_cluster: None,
|
||||
order_by: None,
|
||||
}
|
||||
}
|
||||
pub fn or_replace(mut self, or_replace: bool) -> Self {
|
||||
|
@ -213,6 +215,11 @@ impl CreateTableBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn order_by(mut self, order_by: Option<Vec<Ident>>) -> Self {
|
||||
self.order_by = order_by;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Statement {
|
||||
Statement::CreateTable {
|
||||
or_replace: self.or_replace,
|
||||
|
@ -239,6 +246,7 @@ impl CreateTableBuilder {
|
|||
collation: self.collation,
|
||||
on_commit: self.on_commit,
|
||||
on_cluster: self.on_cluster,
|
||||
order_by: self.order_by,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -275,6 +283,7 @@ impl TryFrom<Statement> for CreateTableBuilder {
|
|||
collation,
|
||||
on_commit,
|
||||
on_cluster,
|
||||
order_by,
|
||||
} => Ok(Self {
|
||||
or_replace,
|
||||
temporary,
|
||||
|
@ -300,6 +309,7 @@ impl TryFrom<Statement> for CreateTableBuilder {
|
|||
collation,
|
||||
on_commit,
|
||||
on_cluster,
|
||||
order_by,
|
||||
}),
|
||||
_ => Err(ParserError::ParserError(format!(
|
||||
"Expected create table statement, but received: {stmt}"
|
||||
|
|
|
@ -1254,9 +1254,13 @@ pub enum Statement {
|
|||
default_charset: Option<String>,
|
||||
collation: Option<String>,
|
||||
on_commit: Option<OnCommit>,
|
||||
/// Click house "ON CLUSTER" clause:
|
||||
/// ClickHouse "ON CLUSTER" clause:
|
||||
/// <https://clickhouse.com/docs/en/sql-reference/distributed-ddl/>
|
||||
on_cluster: Option<String>,
|
||||
/// ClickHouse "ORDER BY " clause. Note that omitted ORDER BY is different
|
||||
/// than empty (represented as ()), the latter meaning "no sorting".
|
||||
/// <https://clickhouse.com/docs/en/sql-reference/statements/create/table/>
|
||||
order_by: Option<Vec<Ident>>,
|
||||
},
|
||||
/// SQLite's `CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
|
||||
CreateVirtualTable {
|
||||
|
@ -2053,6 +2057,7 @@ impl fmt::Display for Statement {
|
|||
collation,
|
||||
on_commit,
|
||||
on_cluster,
|
||||
order_by,
|
||||
} => {
|
||||
// We want to allow the following options
|
||||
// Empty column list, allowed by PostgreSQL:
|
||||
|
@ -2196,12 +2201,15 @@ impl fmt::Display for Statement {
|
|||
if !with_options.is_empty() {
|
||||
write!(f, " WITH ({})", display_comma_separated(with_options))?;
|
||||
}
|
||||
if let Some(query) = query {
|
||||
write!(f, " AS {query}")?;
|
||||
}
|
||||
if let Some(engine) = engine {
|
||||
write!(f, " ENGINE={engine}")?;
|
||||
}
|
||||
if let Some(order_by) = order_by {
|
||||
write!(f, " ORDER BY ({})", display_comma_separated(order_by))?;
|
||||
}
|
||||
if let Some(query) = query {
|
||||
write!(f, " AS {query}")?;
|
||||
}
|
||||
if let Some(default_charset) = default_charset {
|
||||
write!(f, " DEFAULT CHARSET={default_charset}")?;
|
||||
}
|
||||
|
|
|
@ -3340,12 +3340,6 @@ impl<'a> Parser<'a> {
|
|||
// PostgreSQL supports `WITH ( options )`, before `AS`
|
||||
let with_options = self.parse_options(Keyword::WITH)?;
|
||||
let table_properties = self.parse_options(Keyword::TBLPROPERTIES)?;
|
||||
// Parse optional `AS ( query )`
|
||||
let query = if self.parse_keyword(Keyword::AS) {
|
||||
Some(Box::new(self.parse_query()?))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let engine = if self.parse_keyword(Keyword::ENGINE) {
|
||||
self.expect_token(&Token::Eq)?;
|
||||
|
@ -3358,6 +3352,29 @@ impl<'a> Parser<'a> {
|
|||
None
|
||||
};
|
||||
|
||||
let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
|
||||
if self.consume_token(&Token::LParen) {
|
||||
let columns = if self.peek_token() != Token::RParen {
|
||||
self.parse_comma_separated(Parser::parse_identifier)?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
self.expect_token(&Token::RParen)?;
|
||||
Some(columns)
|
||||
} else {
|
||||
Some(vec![self.parse_identifier()?])
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Parse optional `AS ( query )`
|
||||
let query = if self.parse_keyword(Keyword::AS) {
|
||||
Some(Box::new(self.parse_query()?))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let default_charset = if self.parse_keywords(&[Keyword::DEFAULT, Keyword::CHARSET]) {
|
||||
self.expect_token(&Token::Eq)?;
|
||||
let next_token = self.next_token();
|
||||
|
@ -3414,6 +3431,7 @@ impl<'a> Parser<'a> {
|
|||
.like(like)
|
||||
.clone_clause(clone)
|
||||
.engine(engine)
|
||||
.order_by(order_by)
|
||||
.default_charset(default_charset)
|
||||
.collation(collation)
|
||||
.on_commit(on_commit)
|
||||
|
|
|
@ -317,6 +317,18 @@ fn parse_similar_to() {
|
|||
chk(true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_create_table() {
|
||||
clickhouse().verified_stmt(r#"CREATE TABLE "x" ("a" "int") ENGINE=MergeTree ORDER BY ("x")"#);
|
||||
clickhouse().one_statement_parses_to(
|
||||
r#"CREATE TABLE "x" ("a" "int") ENGINE=MergeTree ORDER BY "x""#,
|
||||
r#"CREATE TABLE "x" ("a" "int") ENGINE=MergeTree ORDER BY ("x")"#,
|
||||
);
|
||||
clickhouse().verified_stmt(
|
||||
r#"CREATE TABLE "x" ("a" "int") ENGINE=MergeTree ORDER BY ("x") AS SELECT * FROM "t" WHERE true"#,
|
||||
);
|
||||
}
|
||||
|
||||
fn clickhouse() -> TestedDialects {
|
||||
TestedDialects {
|
||||
dialects: vec![Box::new(ClickHouseDialect {})],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue