mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-19 05:30:19 +00:00
Add support for ClickHouse DDL query syntax (on cluster
) (#527)
* Add on_cluster to Statement::CreateTable * Add printing of on_cluster * Update src/ast/mod.rs Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org> * Fix fmt + nostd * Remove unintended diff Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
f74753436a
commit
16af309c74
3 changed files with 46 additions and 0 deletions
|
@ -883,6 +883,9 @@ pub enum Statement {
|
||||||
default_charset: Option<String>,
|
default_charset: Option<String>,
|
||||||
collation: Option<String>,
|
collation: Option<String>,
|
||||||
on_commit: Option<OnCommit>,
|
on_commit: Option<OnCommit>,
|
||||||
|
/// Click house "ON CLUSTER" clause:
|
||||||
|
/// <https://clickhouse.com/docs/en/sql-reference/distributed-ddl/>
|
||||||
|
on_cluster: Option<String>,
|
||||||
},
|
},
|
||||||
/// SQLite's `CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
|
/// SQLite's `CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
|
||||||
CreateVirtualTable {
|
CreateVirtualTable {
|
||||||
|
@ -1509,6 +1512,7 @@ impl fmt::Display for Statement {
|
||||||
engine,
|
engine,
|
||||||
collation,
|
collation,
|
||||||
on_commit,
|
on_commit,
|
||||||
|
on_cluster,
|
||||||
} => {
|
} => {
|
||||||
// We want to allow the following options
|
// We want to allow the following options
|
||||||
// Empty column list, allowed by PostgreSQL:
|
// Empty column list, allowed by PostgreSQL:
|
||||||
|
@ -1535,6 +1539,13 @@ impl fmt::Display for Statement {
|
||||||
temporary = if *temporary { "TEMPORARY " } else { "" },
|
temporary = if *temporary { "TEMPORARY " } else { "" },
|
||||||
name = name,
|
name = name,
|
||||||
)?;
|
)?;
|
||||||
|
if let Some(on_cluster) = on_cluster {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
" ON CLUSTER {}",
|
||||||
|
on_cluster.replace('{', "'{").replace('}', "}'")
|
||||||
|
)?;
|
||||||
|
}
|
||||||
if !columns.is_empty() || !constraints.is_empty() {
|
if !columns.is_empty() || !constraints.is_empty() {
|
||||||
write!(f, " ({}", display_comma_separated(columns))?;
|
write!(f, " ({}", display_comma_separated(columns))?;
|
||||||
if !columns.is_empty() && !constraints.is_empty() {
|
if !columns.is_empty() && !constraints.is_empty() {
|
||||||
|
|
|
@ -1826,6 +1826,7 @@ impl<'a> Parser<'a> {
|
||||||
engine: None,
|
engine: None,
|
||||||
collation: None,
|
collation: None,
|
||||||
on_commit: None,
|
on_commit: None,
|
||||||
|
on_cluster: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2107,6 +2108,18 @@ impl<'a> Parser<'a> {
|
||||||
) -> Result<Statement, ParserError> {
|
) -> Result<Statement, ParserError> {
|
||||||
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
||||||
let table_name = self.parse_object_name()?;
|
let table_name = self.parse_object_name()?;
|
||||||
|
|
||||||
|
// Clickhouse has `ON CLUSTER 'cluster'` syntax for DDLs
|
||||||
|
let on_cluster = if self.parse_keywords(&[Keyword::ON, Keyword::CLUSTER]) {
|
||||||
|
match self.next_token() {
|
||||||
|
Token::SingleQuotedString(s) => Some(s),
|
||||||
|
Token::Word(s) => Some(s.to_string()),
|
||||||
|
unexpected => self.expected("identifier or cluster literal", unexpected)?,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let like = if self.parse_keyword(Keyword::LIKE) || self.parse_keyword(Keyword::ILIKE) {
|
let like = if self.parse_keyword(Keyword::LIKE) || self.parse_keyword(Keyword::ILIKE) {
|
||||||
self.parse_object_name().ok()
|
self.parse_object_name().ok()
|
||||||
} else {
|
} else {
|
||||||
|
@ -2207,6 +2220,7 @@ impl<'a> Parser<'a> {
|
||||||
default_charset,
|
default_charset,
|
||||||
collation,
|
collation,
|
||||||
on_commit,
|
on_commit,
|
||||||
|
on_cluster,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1995,6 +1995,27 @@ fn parse_create_table_as() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_create_table_on_cluster() {
|
||||||
|
// Using single-quote literal to define current cluster
|
||||||
|
let sql = "CREATE TABLE t ON CLUSTER '{cluster}' (a INT, b INT)";
|
||||||
|
match verified_stmt(sql) {
|
||||||
|
Statement::CreateTable { on_cluster, .. } => {
|
||||||
|
assert_eq!(on_cluster.unwrap(), "{cluster}".to_string());
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using explicitly declared cluster name
|
||||||
|
let sql = "CREATE TABLE t ON CLUSTER my_cluster (a INT, b INT)";
|
||||||
|
match verified_stmt(sql) {
|
||||||
|
Statement::CreateTable { on_cluster, .. } => {
|
||||||
|
assert_eq!(on_cluster.unwrap(), "my_cluster".to_string());
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_create_or_replace_table() {
|
fn parse_create_or_replace_table() {
|
||||||
let sql = "CREATE OR REPLACE TABLE t (a INT)";
|
let sql = "CREATE OR REPLACE TABLE t (a INT)";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue