mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-10-10 05:52:13 +00:00
Encapsulate CreateTable
, CreateIndex
into specific structs (#1291)
This commit is contained in:
parent
f3f5de51e5
commit
a0f511cb21
10 changed files with 387 additions and 400 deletions
318
src/ast/mod.rs
318
src/ast/mod.rs
|
@ -38,7 +38,7 @@ pub use self::ddl::{
|
|||
ReferentialAction, TableConstraint, UserDefinedTypeCompositeAttributeDef,
|
||||
UserDefinedTypeRepresentation, ViewColumnDef,
|
||||
};
|
||||
pub use self::dml::{Delete, Insert};
|
||||
pub use self::dml::{CreateIndex, CreateTable, Delete, Insert};
|
||||
pub use self::operator::{BinaryOperator, UnaryOperator};
|
||||
pub use self::query::{
|
||||
AfterMatchSkip, ConnectBy, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
|
||||
|
@ -75,7 +75,7 @@ mod value;
|
|||
#[cfg(feature = "visitor")]
|
||||
mod visitor;
|
||||
|
||||
struct DisplaySeparated<'a, T>
|
||||
pub struct DisplaySeparated<'a, T>
|
||||
where
|
||||
T: fmt::Display,
|
||||
{
|
||||
|
@ -98,14 +98,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
|
||||
pub fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
|
||||
where
|
||||
T: fmt::Display,
|
||||
{
|
||||
DisplaySeparated { slice, sep }
|
||||
}
|
||||
|
||||
fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
|
||||
pub fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
|
||||
where
|
||||
T: fmt::Display,
|
||||
{
|
||||
|
@ -2033,56 +2033,7 @@ pub enum Statement {
|
|||
/// ```sql
|
||||
/// CREATE TABLE
|
||||
/// ```
|
||||
CreateTable {
|
||||
or_replace: bool,
|
||||
temporary: bool,
|
||||
external: bool,
|
||||
global: Option<bool>,
|
||||
if_not_exists: bool,
|
||||
transient: bool,
|
||||
/// Table name
|
||||
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
|
||||
name: ObjectName,
|
||||
/// Optional schema
|
||||
columns: Vec<ColumnDef>,
|
||||
constraints: Vec<TableConstraint>,
|
||||
hive_distribution: HiveDistributionStyle,
|
||||
hive_formats: Option<HiveFormat>,
|
||||
table_properties: Vec<SqlOption>,
|
||||
with_options: Vec<SqlOption>,
|
||||
file_format: Option<FileFormat>,
|
||||
location: Option<String>,
|
||||
query: Option<Box<Query>>,
|
||||
without_rowid: bool,
|
||||
like: Option<ObjectName>,
|
||||
clone: Option<ObjectName>,
|
||||
engine: Option<String>,
|
||||
comment: Option<String>,
|
||||
auto_increment_offset: Option<u32>,
|
||||
default_charset: Option<String>,
|
||||
collation: Option<String>,
|
||||
on_commit: Option<OnCommit>,
|
||||
/// 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>>,
|
||||
/// BigQuery: A partition expression for the table.
|
||||
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#partition_expression>
|
||||
partition_by: Option<Box<Expr>>,
|
||||
/// BigQuery: Table clustering column list.
|
||||
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
|
||||
cluster_by: Option<Vec<Ident>>,
|
||||
/// BigQuery: Table options list.
|
||||
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
|
||||
options: Option<Vec<SqlOption>>,
|
||||
/// SQLite "STRICT" clause.
|
||||
/// if the "STRICT" table-option keyword is added to the end, after the closing ")",
|
||||
/// then strict typing rules apply to that table.
|
||||
strict: bool,
|
||||
},
|
||||
CreateTable(CreateTable),
|
||||
/// ```sql
|
||||
/// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
|
||||
/// ```
|
||||
|
@ -2097,20 +2048,7 @@ pub enum Statement {
|
|||
/// ```sql
|
||||
/// `CREATE INDEX`
|
||||
/// ```
|
||||
CreateIndex {
|
||||
/// index name
|
||||
name: Option<ObjectName>,
|
||||
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
|
||||
table_name: ObjectName,
|
||||
using: Option<Ident>,
|
||||
columns: Vec<OrderByExpr>,
|
||||
unique: bool,
|
||||
concurrently: bool,
|
||||
if_not_exists: bool,
|
||||
include: Vec<Ident>,
|
||||
nulls_distinct: Option<bool>,
|
||||
predicate: Option<Expr>,
|
||||
},
|
||||
CreateIndex(CreateIndex),
|
||||
/// ```sql
|
||||
/// CREATE ROLE
|
||||
/// ```
|
||||
|
@ -3426,245 +3364,7 @@ impl fmt::Display for Statement {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
Statement::CreateTable {
|
||||
name,
|
||||
columns,
|
||||
constraints,
|
||||
table_properties,
|
||||
with_options,
|
||||
or_replace,
|
||||
if_not_exists,
|
||||
transient,
|
||||
hive_distribution,
|
||||
hive_formats,
|
||||
external,
|
||||
global,
|
||||
temporary,
|
||||
file_format,
|
||||
location,
|
||||
query,
|
||||
without_rowid,
|
||||
like,
|
||||
clone,
|
||||
default_charset,
|
||||
engine,
|
||||
comment,
|
||||
auto_increment_offset,
|
||||
collation,
|
||||
on_commit,
|
||||
on_cluster,
|
||||
order_by,
|
||||
partition_by,
|
||||
cluster_by,
|
||||
options,
|
||||
strict,
|
||||
} => {
|
||||
// We want to allow the following options
|
||||
// Empty column list, allowed by PostgreSQL:
|
||||
// `CREATE TABLE t ()`
|
||||
// No columns provided for CREATE TABLE AS:
|
||||
// `CREATE TABLE t AS SELECT a from t2`
|
||||
// Columns provided for CREATE TABLE AS:
|
||||
// `CREATE TABLE t (a INT) AS SELECT a from t2`
|
||||
write!(
|
||||
f,
|
||||
"CREATE {or_replace}{external}{global}{temporary}{transient}TABLE {if_not_exists}{name}",
|
||||
or_replace = if *or_replace { "OR REPLACE " } else { "" },
|
||||
external = if *external { "EXTERNAL " } else { "" },
|
||||
global = global
|
||||
.map(|global| {
|
||||
if global {
|
||||
"GLOBAL "
|
||||
} else {
|
||||
"LOCAL "
|
||||
}
|
||||
})
|
||||
.unwrap_or(""),
|
||||
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
|
||||
temporary = if *temporary { "TEMPORARY " } else { "" },
|
||||
transient = if *transient { "TRANSIENT " } else { "" },
|
||||
name = name,
|
||||
)?;
|
||||
if let Some(on_cluster) = on_cluster {
|
||||
write!(
|
||||
f,
|
||||
" ON CLUSTER {}",
|
||||
on_cluster.replace('{', "'{").replace('}', "}'")
|
||||
)?;
|
||||
}
|
||||
if !columns.is_empty() || !constraints.is_empty() {
|
||||
write!(f, " ({}", display_comma_separated(columns))?;
|
||||
if !columns.is_empty() && !constraints.is_empty() {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
write!(f, "{})", display_comma_separated(constraints))?;
|
||||
} else if query.is_none() && like.is_none() && clone.is_none() {
|
||||
// PostgreSQL allows `CREATE TABLE t ();`, but requires empty parens
|
||||
write!(f, " ()")?;
|
||||
}
|
||||
// Only for SQLite
|
||||
if *without_rowid {
|
||||
write!(f, " WITHOUT ROWID")?;
|
||||
}
|
||||
|
||||
// Only for Hive
|
||||
if let Some(l) = like {
|
||||
write!(f, " LIKE {l}")?;
|
||||
}
|
||||
|
||||
if let Some(c) = clone {
|
||||
write!(f, " CLONE {c}")?;
|
||||
}
|
||||
|
||||
match hive_distribution {
|
||||
HiveDistributionStyle::PARTITIONED { columns } => {
|
||||
write!(f, " PARTITIONED BY ({})", display_comma_separated(columns))?;
|
||||
}
|
||||
HiveDistributionStyle::CLUSTERED {
|
||||
columns,
|
||||
sorted_by,
|
||||
num_buckets,
|
||||
} => {
|
||||
write!(f, " CLUSTERED BY ({})", display_comma_separated(columns))?;
|
||||
if !sorted_by.is_empty() {
|
||||
write!(f, " SORTED BY ({})", display_comma_separated(sorted_by))?;
|
||||
}
|
||||
if *num_buckets > 0 {
|
||||
write!(f, " INTO {num_buckets} BUCKETS")?;
|
||||
}
|
||||
}
|
||||
HiveDistributionStyle::SKEWED {
|
||||
columns,
|
||||
on,
|
||||
stored_as_directories,
|
||||
} => {
|
||||
write!(
|
||||
f,
|
||||
" SKEWED BY ({})) ON ({})",
|
||||
display_comma_separated(columns),
|
||||
display_comma_separated(on)
|
||||
)?;
|
||||
if *stored_as_directories {
|
||||
write!(f, " STORED AS DIRECTORIES")?;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if let Some(HiveFormat {
|
||||
row_format,
|
||||
serde_properties,
|
||||
storage,
|
||||
location,
|
||||
}) = hive_formats
|
||||
{
|
||||
match row_format {
|
||||
Some(HiveRowFormat::SERDE { class }) => {
|
||||
write!(f, " ROW FORMAT SERDE '{class}'")?
|
||||
}
|
||||
Some(HiveRowFormat::DELIMITED { delimiters }) => {
|
||||
write!(f, " ROW FORMAT DELIMITED")?;
|
||||
if !delimiters.is_empty() {
|
||||
write!(f, " {}", display_separated(delimiters, " "))?;
|
||||
}
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
match storage {
|
||||
Some(HiveIOFormat::IOF {
|
||||
input_format,
|
||||
output_format,
|
||||
}) => write!(
|
||||
f,
|
||||
" STORED AS INPUTFORMAT {input_format} OUTPUTFORMAT {output_format}"
|
||||
)?,
|
||||
Some(HiveIOFormat::FileFormat { format }) if !*external => {
|
||||
write!(f, " STORED AS {format}")?
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
if let Some(serde_properties) = serde_properties.as_ref() {
|
||||
write!(
|
||||
f,
|
||||
" WITH SERDEPROPERTIES ({})",
|
||||
display_comma_separated(serde_properties)
|
||||
)?;
|
||||
}
|
||||
if !*external {
|
||||
if let Some(loc) = location {
|
||||
write!(f, " LOCATION '{loc}'")?;
|
||||
}
|
||||
}
|
||||
}
|
||||
if *external {
|
||||
if let Some(file_format) = &file_format {
|
||||
write!(f, " STORED AS {file_format}")?;
|
||||
}
|
||||
write!(f, " LOCATION '{}'", location.as_ref().unwrap())?;
|
||||
}
|
||||
if !table_properties.is_empty() {
|
||||
write!(
|
||||
f,
|
||||
" TBLPROPERTIES ({})",
|
||||
display_comma_separated(table_properties)
|
||||
)?;
|
||||
}
|
||||
if !with_options.is_empty() {
|
||||
write!(f, " WITH ({})", display_comma_separated(with_options))?;
|
||||
}
|
||||
if let Some(engine) = engine {
|
||||
write!(f, " ENGINE={engine}")?;
|
||||
}
|
||||
if let Some(comment) = comment {
|
||||
write!(f, " COMMENT '{comment}'")?;
|
||||
}
|
||||
if let Some(auto_increment_offset) = auto_increment_offset {
|
||||
write!(f, " AUTO_INCREMENT {auto_increment_offset}")?;
|
||||
}
|
||||
if let Some(order_by) = order_by {
|
||||
write!(f, " ORDER BY ({})", display_comma_separated(order_by))?;
|
||||
}
|
||||
if let Some(partition_by) = partition_by.as_ref() {
|
||||
write!(f, " PARTITION BY {partition_by}")?;
|
||||
}
|
||||
if let Some(cluster_by) = cluster_by.as_ref() {
|
||||
write!(
|
||||
f,
|
||||
" CLUSTER BY {}",
|
||||
display_comma_separated(cluster_by.as_slice())
|
||||
)?;
|
||||
}
|
||||
if let Some(options) = options.as_ref() {
|
||||
write!(
|
||||
f,
|
||||
" OPTIONS({})",
|
||||
display_comma_separated(options.as_slice())
|
||||
)?;
|
||||
}
|
||||
if let Some(query) = query {
|
||||
write!(f, " AS {query}")?;
|
||||
}
|
||||
if let Some(default_charset) = default_charset {
|
||||
write!(f, " DEFAULT CHARSET={default_charset}")?;
|
||||
}
|
||||
if let Some(collation) = collation {
|
||||
write!(f, " COLLATE={collation}")?;
|
||||
}
|
||||
|
||||
if on_commit.is_some() {
|
||||
let on_commit = match on_commit {
|
||||
Some(OnCommit::DeleteRows) => "ON COMMIT DELETE ROWS",
|
||||
Some(OnCommit::PreserveRows) => "ON COMMIT PRESERVE ROWS",
|
||||
Some(OnCommit::Drop) => "ON COMMIT DROP",
|
||||
None => "",
|
||||
};
|
||||
write!(f, " {on_commit}")?;
|
||||
}
|
||||
if *strict {
|
||||
write!(f, " STRICT")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Statement::CreateTable(create_table) => create_table.fmt(f),
|
||||
Statement::CreateVirtualTable {
|
||||
name,
|
||||
if_not_exists,
|
||||
|
@ -3683,7 +3383,7 @@ impl fmt::Display for Statement {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
Statement::CreateIndex {
|
||||
Statement::CreateIndex(CreateIndex {
|
||||
name,
|
||||
table_name,
|
||||
using,
|
||||
|
@ -3694,7 +3394,7 @@ impl fmt::Display for Statement {
|
|||
include,
|
||||
nulls_distinct,
|
||||
predicate,
|
||||
} => {
|
||||
}) => {
|
||||
write!(
|
||||
f,
|
||||
"CREATE {unique}INDEX {concurrently}{if_not_exists}",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue