mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-21 21:22:28 +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
292
src/ast/dml.rs
292
src/ast/dml.rs
|
@ -11,18 +11,304 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::{boxed::Box, string::String, vec::Vec};
|
||||||
|
|
||||||
|
use core::fmt::{self, Display};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "visitor")]
|
#[cfg(feature = "visitor")]
|
||||||
use sqlparser_derive::{Visit, VisitMut};
|
use sqlparser_derive::{Visit, VisitMut};
|
||||||
|
|
||||||
|
pub use super::ddl::{ColumnDef, TableConstraint};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Expr, FromTable, Ident, InsertAliases, MysqlInsertPriority, ObjectName, OnInsert, OrderByExpr,
|
display_comma_separated, display_separated, Expr, FileFormat, FromTable, HiveDistributionStyle,
|
||||||
Query, SelectItem, SqliteOnConflict, TableWithJoins,
|
HiveFormat, HiveIOFormat, HiveRowFormat, Ident, InsertAliases, MysqlInsertPriority, ObjectName,
|
||||||
|
OnCommit, OnInsert, OrderByExpr, Query, SelectItem, SqlOption, SqliteOnConflict,
|
||||||
|
TableWithJoins,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// CREATE INDEX statement.
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
pub struct CreateIndex {
|
||||||
|
/// index name
|
||||||
|
pub name: Option<ObjectName>,
|
||||||
|
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
|
||||||
|
pub table_name: ObjectName,
|
||||||
|
pub using: Option<Ident>,
|
||||||
|
pub columns: Vec<OrderByExpr>,
|
||||||
|
pub unique: bool,
|
||||||
|
pub concurrently: bool,
|
||||||
|
pub if_not_exists: bool,
|
||||||
|
pub include: Vec<Ident>,
|
||||||
|
pub nulls_distinct: Option<bool>,
|
||||||
|
pub predicate: Option<Expr>,
|
||||||
|
}
|
||||||
|
/// CREATE TABLE statement.
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
pub struct CreateTable {
|
||||||
|
pub or_replace: bool,
|
||||||
|
pub temporary: bool,
|
||||||
|
pub external: bool,
|
||||||
|
pub global: Option<bool>,
|
||||||
|
pub if_not_exists: bool,
|
||||||
|
pub transient: bool,
|
||||||
|
/// Table name
|
||||||
|
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
|
||||||
|
pub name: ObjectName,
|
||||||
|
/// Optional schema
|
||||||
|
pub columns: Vec<ColumnDef>,
|
||||||
|
pub constraints: Vec<TableConstraint>,
|
||||||
|
pub hive_distribution: HiveDistributionStyle,
|
||||||
|
pub hive_formats: Option<HiveFormat>,
|
||||||
|
pub table_properties: Vec<SqlOption>,
|
||||||
|
pub with_options: Vec<SqlOption>,
|
||||||
|
pub file_format: Option<FileFormat>,
|
||||||
|
pub location: Option<String>,
|
||||||
|
pub query: Option<Box<Query>>,
|
||||||
|
pub without_rowid: bool,
|
||||||
|
pub like: Option<ObjectName>,
|
||||||
|
pub clone: Option<ObjectName>,
|
||||||
|
pub engine: Option<String>,
|
||||||
|
pub comment: Option<String>,
|
||||||
|
pub auto_increment_offset: Option<u32>,
|
||||||
|
pub default_charset: Option<String>,
|
||||||
|
pub collation: Option<String>,
|
||||||
|
pub on_commit: Option<OnCommit>,
|
||||||
|
/// ClickHouse "ON CLUSTER" clause:
|
||||||
|
/// <https://clickhouse.com/docs/en/sql-reference/distributed-ddl/>
|
||||||
|
pub 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/>
|
||||||
|
pub 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>
|
||||||
|
pub 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>
|
||||||
|
pub cluster_by: Option<Vec<Ident>>,
|
||||||
|
/// BigQuery: Table options list.
|
||||||
|
/// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
|
||||||
|
pub 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.
|
||||||
|
pub strict: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for CreateTable {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
// 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 self.or_replace { "OR REPLACE " } else { "" },
|
||||||
|
external = if self.external { "EXTERNAL " } else { "" },
|
||||||
|
global = self.global
|
||||||
|
.map(|global| {
|
||||||
|
if global {
|
||||||
|
"GLOBAL "
|
||||||
|
} else {
|
||||||
|
"LOCAL "
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or(""),
|
||||||
|
if_not_exists = if self.if_not_exists { "IF NOT EXISTS " } else { "" },
|
||||||
|
temporary = if self.temporary { "TEMPORARY " } else { "" },
|
||||||
|
transient = if self.transient { "TRANSIENT " } else { "" },
|
||||||
|
name = self.name,
|
||||||
|
)?;
|
||||||
|
if let Some(on_cluster) = &self.on_cluster {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
" ON CLUSTER {}",
|
||||||
|
on_cluster.replace('{', "'{").replace('}', "}'")
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
if !self.columns.is_empty() || !self.constraints.is_empty() {
|
||||||
|
write!(f, " ({}", display_comma_separated(&self.columns))?;
|
||||||
|
if !self.columns.is_empty() && !self.constraints.is_empty() {
|
||||||
|
write!(f, ", ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{})", display_comma_separated(&self.constraints))?;
|
||||||
|
} else if self.query.is_none() && self.like.is_none() && self.clone.is_none() {
|
||||||
|
// PostgreSQL allows `CREATE TABLE t ();`, but requires empty parens
|
||||||
|
write!(f, " ()")?;
|
||||||
|
}
|
||||||
|
// Only for SQLite
|
||||||
|
if self.without_rowid {
|
||||||
|
write!(f, " WITHOUT ROWID")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only for Hive
|
||||||
|
if let Some(l) = &self.like {
|
||||||
|
write!(f, " LIKE {l}")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(c) = &self.clone {
|
||||||
|
write!(f, " CLONE {c}")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
match &self.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,
|
||||||
|
}) = &self.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 !self.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 !self.external {
|
||||||
|
if let Some(loc) = location {
|
||||||
|
write!(f, " LOCATION '{loc}'")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.external {
|
||||||
|
if let Some(file_format) = self.file_format {
|
||||||
|
write!(f, " STORED AS {file_format}")?;
|
||||||
|
}
|
||||||
|
write!(f, " LOCATION '{}'", self.location.as_ref().unwrap())?;
|
||||||
|
}
|
||||||
|
if !self.table_properties.is_empty() {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
" TBLPROPERTIES ({})",
|
||||||
|
display_comma_separated(&self.table_properties)
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
if !self.with_options.is_empty() {
|
||||||
|
write!(f, " WITH ({})", display_comma_separated(&self.with_options))?;
|
||||||
|
}
|
||||||
|
if let Some(engine) = &self.engine {
|
||||||
|
write!(f, " ENGINE={engine}")?;
|
||||||
|
}
|
||||||
|
if let Some(comment) = &self.comment {
|
||||||
|
write!(f, " COMMENT '{comment}'")?;
|
||||||
|
}
|
||||||
|
if let Some(auto_increment_offset) = self.auto_increment_offset {
|
||||||
|
write!(f, " AUTO_INCREMENT {auto_increment_offset}")?;
|
||||||
|
}
|
||||||
|
if let Some(order_by) = &self.order_by {
|
||||||
|
write!(f, " ORDER BY ({})", display_comma_separated(order_by))?;
|
||||||
|
}
|
||||||
|
if let Some(partition_by) = self.partition_by.as_ref() {
|
||||||
|
write!(f, " PARTITION BY {partition_by}")?;
|
||||||
|
}
|
||||||
|
if let Some(cluster_by) = self.cluster_by.as_ref() {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
" CLUSTER BY {}",
|
||||||
|
display_comma_separated(cluster_by.as_slice())
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
if let Some(options) = self.options.as_ref() {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
" OPTIONS({})",
|
||||||
|
display_comma_separated(options.as_slice())
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
if let Some(query) = &self.query {
|
||||||
|
write!(f, " AS {query}")?;
|
||||||
|
}
|
||||||
|
if let Some(default_charset) = &self.default_charset {
|
||||||
|
write!(f, " DEFAULT CHARSET={default_charset}")?;
|
||||||
|
}
|
||||||
|
if let Some(collation) = &self.collation {
|
||||||
|
write!(f, " COLLATE={collation}")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.on_commit.is_some() {
|
||||||
|
let on_commit = match self.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 self.strict {
|
||||||
|
write!(f, " STRICT")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// INSERT statement.
|
/// INSERT statement.
|
||||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
|
|
@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "visitor")]
|
#[cfg(feature = "visitor")]
|
||||||
use sqlparser_derive::{Visit, VisitMut};
|
use sqlparser_derive::{Visit, VisitMut};
|
||||||
|
|
||||||
|
use super::super::dml::CreateTable;
|
||||||
use crate::ast::{
|
use crate::ast::{
|
||||||
ColumnDef, Expr, FileFormat, HiveDistributionStyle, HiveFormat, Ident, ObjectName, OnCommit,
|
ColumnDef, Expr, FileFormat, HiveDistributionStyle, HiveFormat, Ident, ObjectName, OnCommit,
|
||||||
Query, SqlOption, Statement, TableConstraint,
|
Query, SqlOption, Statement, TableConstraint,
|
||||||
|
@ -263,7 +264,7 @@ impl CreateTableBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Statement {
|
pub fn build(self) -> Statement {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
or_replace: self.or_replace,
|
or_replace: self.or_replace,
|
||||||
temporary: self.temporary,
|
temporary: self.temporary,
|
||||||
external: self.external,
|
external: self.external,
|
||||||
|
@ -295,7 +296,7 @@ impl CreateTableBuilder {
|
||||||
cluster_by: self.cluster_by,
|
cluster_by: self.cluster_by,
|
||||||
options: self.options,
|
options: self.options,
|
||||||
strict: self.strict,
|
strict: self.strict,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +307,7 @@ impl TryFrom<Statement> for CreateTableBuilder {
|
||||||
// ownership.
|
// ownership.
|
||||||
fn try_from(stmt: Statement) -> Result<Self, Self::Error> {
|
fn try_from(stmt: Statement) -> Result<Self, Self::Error> {
|
||||||
match stmt {
|
match stmt {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
or_replace,
|
or_replace,
|
||||||
temporary,
|
temporary,
|
||||||
external,
|
external,
|
||||||
|
@ -338,7 +339,7 @@ impl TryFrom<Statement> for CreateTableBuilder {
|
||||||
cluster_by,
|
cluster_by,
|
||||||
options,
|
options,
|
||||||
strict,
|
strict,
|
||||||
} => Ok(Self {
|
}) => Ok(Self {
|
||||||
or_replace,
|
or_replace,
|
||||||
temporary,
|
temporary,
|
||||||
external,
|
external,
|
||||||
|
|
318
src/ast/mod.rs
318
src/ast/mod.rs
|
@ -38,7 +38,7 @@ pub use self::ddl::{
|
||||||
ReferentialAction, TableConstraint, UserDefinedTypeCompositeAttributeDef,
|
ReferentialAction, TableConstraint, UserDefinedTypeCompositeAttributeDef,
|
||||||
UserDefinedTypeRepresentation, ViewColumnDef,
|
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::operator::{BinaryOperator, UnaryOperator};
|
||||||
pub use self::query::{
|
pub use self::query::{
|
||||||
AfterMatchSkip, ConnectBy, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
|
AfterMatchSkip, ConnectBy, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
|
||||||
|
@ -75,7 +75,7 @@ mod value;
|
||||||
#[cfg(feature = "visitor")]
|
#[cfg(feature = "visitor")]
|
||||||
mod visitor;
|
mod visitor;
|
||||||
|
|
||||||
struct DisplaySeparated<'a, T>
|
pub struct DisplaySeparated<'a, T>
|
||||||
where
|
where
|
||||||
T: fmt::Display,
|
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
|
where
|
||||||
T: fmt::Display,
|
T: fmt::Display,
|
||||||
{
|
{
|
||||||
DisplaySeparated { slice, sep }
|
DisplaySeparated { slice, sep }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
|
pub fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
|
||||||
where
|
where
|
||||||
T: fmt::Display,
|
T: fmt::Display,
|
||||||
{
|
{
|
||||||
|
@ -2033,56 +2033,7 @@ pub enum Statement {
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// CREATE TABLE
|
/// CREATE TABLE
|
||||||
/// ```
|
/// ```
|
||||||
CreateTable {
|
CreateTable(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,
|
|
||||||
},
|
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
|
/// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -2097,20 +2048,7 @@ pub enum Statement {
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// `CREATE INDEX`
|
/// `CREATE INDEX`
|
||||||
/// ```
|
/// ```
|
||||||
CreateIndex {
|
CreateIndex(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>,
|
|
||||||
},
|
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// CREATE ROLE
|
/// CREATE ROLE
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -3426,245 +3364,7 @@ impl fmt::Display for Statement {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(create_table) => create_table.fmt(f),
|
||||||
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::CreateVirtualTable {
|
Statement::CreateVirtualTable {
|
||||||
name,
|
name,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
|
@ -3683,7 +3383,7 @@ impl fmt::Display for Statement {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Statement::CreateIndex {
|
Statement::CreateIndex(CreateIndex {
|
||||||
name,
|
name,
|
||||||
table_name,
|
table_name,
|
||||||
using,
|
using,
|
||||||
|
@ -3694,7 +3394,7 @@ impl fmt::Display for Statement {
|
||||||
include,
|
include,
|
||||||
nulls_distinct,
|
nulls_distinct,
|
||||||
predicate,
|
predicate,
|
||||||
} => {
|
}) => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"CREATE {unique}INDEX {concurrently}{if_not_exists}",
|
"CREATE {unique}INDEX {concurrently}{if_not_exists}",
|
||||||
|
|
|
@ -4963,7 +4963,7 @@ impl<'a> Parser<'a> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Statement::CreateIndex {
|
Ok(Statement::CreateIndex(CreateIndex {
|
||||||
name: index_name,
|
name: index_name,
|
||||||
table_name,
|
table_name,
|
||||||
using,
|
using,
|
||||||
|
@ -4974,7 +4974,7 @@ impl<'a> Parser<'a> {
|
||||||
include,
|
include,
|
||||||
nulls_distinct,
|
nulls_distinct,
|
||||||
predicate,
|
predicate,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_create_extension(&mut self) -> Result<Statement, ParserError> {
|
pub fn parse_create_extension(&mut self) -> Result<Statement, ParserError> {
|
||||||
|
|
|
@ -354,7 +354,7 @@ fn parse_create_view_with_unquoted_hyphen() {
|
||||||
fn parse_create_table_with_unquoted_hyphen() {
|
fn parse_create_table_with_unquoted_hyphen() {
|
||||||
let sql = "CREATE TABLE my-pro-ject.mydataset.mytable (x INT64)";
|
let sql = "CREATE TABLE my-pro-ject.mydataset.mytable (x INT64)";
|
||||||
match bigquery().verified_stmt(sql) {
|
match bigquery().verified_stmt(sql) {
|
||||||
Statement::CreateTable { name, columns, .. } => {
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
name,
|
name,
|
||||||
ObjectName(vec![
|
ObjectName(vec![
|
||||||
|
@ -388,14 +388,14 @@ fn parse_create_table_with_options() {
|
||||||
r#"OPTIONS(partition_expiration_days = 1, description = "table option description")"#
|
r#"OPTIONS(partition_expiration_days = 1, description = "table option description")"#
|
||||||
);
|
);
|
||||||
match bigquery().verified_stmt(sql) {
|
match bigquery().verified_stmt(sql) {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
partition_by,
|
partition_by,
|
||||||
cluster_by,
|
cluster_by,
|
||||||
options,
|
options,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
name,
|
name,
|
||||||
ObjectName(vec!["mydataset".into(), "newtable".into()])
|
ObjectName(vec!["mydataset".into(), "newtable".into()])
|
||||||
|
@ -477,7 +477,7 @@ fn parse_create_table_with_options() {
|
||||||
fn parse_nested_data_types() {
|
fn parse_nested_data_types() {
|
||||||
let sql = "CREATE TABLE table (x STRUCT<a ARRAY<INT64>, b BYTES(42)>, y ARRAY<STRUCT<INT64>>)";
|
let sql = "CREATE TABLE table (x STRUCT<a ARRAY<INT64>, b BYTES(42)>, y ARRAY<STRUCT<INT64>>)";
|
||||||
match bigquery_and_generic().one_statement_parses_to(sql, sql) {
|
match bigquery_and_generic().one_statement_parses_to(sql, sql) {
|
||||||
Statement::CreateTable { name, columns, .. } => {
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
assert_eq!(name, ObjectName(vec!["table".into()]));
|
assert_eq!(name, ObjectName(vec!["table".into()]));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
columns,
|
columns,
|
||||||
|
|
|
@ -2747,7 +2747,7 @@ fn parse_create_table() {
|
||||||
FOREIGN KEY (lng) REFERENCES othertable4(longitude) ON UPDATE SET NULL)",
|
FOREIGN KEY (lng) REFERENCES othertable4(longitude) ON UPDATE SET NULL)",
|
||||||
);
|
);
|
||||||
match ast {
|
match ast {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
constraints,
|
constraints,
|
||||||
|
@ -2757,7 +2757,7 @@ fn parse_create_table() {
|
||||||
file_format: None,
|
file_format: None,
|
||||||
location: None,
|
location: None,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!("uk_cities", name.to_string());
|
assert_eq!("uk_cities", name.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
columns,
|
columns,
|
||||||
|
@ -2936,7 +2936,7 @@ fn parse_create_table_with_constraint_characteristics() {
|
||||||
FOREIGN KEY (lng) REFERENCES othertable4(longitude) ON UPDATE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE ENFORCED)",
|
FOREIGN KEY (lng) REFERENCES othertable4(longitude) ON UPDATE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE ENFORCED)",
|
||||||
);
|
);
|
||||||
match ast {
|
match ast {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
constraints,
|
constraints,
|
||||||
|
@ -2946,7 +2946,7 @@ fn parse_create_table_with_constraint_characteristics() {
|
||||||
file_format: None,
|
file_format: None,
|
||||||
location: None,
|
location: None,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!("uk_cities", name.to_string());
|
assert_eq!("uk_cities", name.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
columns,
|
columns,
|
||||||
|
@ -3104,7 +3104,7 @@ fn parse_create_table_column_constraint_characteristics() {
|
||||||
};
|
};
|
||||||
|
|
||||||
match ast {
|
match ast {
|
||||||
Statement::CreateTable { columns, .. } => {
|
Statement::CreateTable(CreateTable { columns, .. }) => {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
columns,
|
columns,
|
||||||
vec![ColumnDef {
|
vec![ColumnDef {
|
||||||
|
@ -3214,12 +3214,12 @@ fn parse_create_table_hive_array() {
|
||||||
};
|
};
|
||||||
|
|
||||||
match dialects.one_statement_parses_to(sql.as_str(), sql.as_str()) {
|
match dialects.one_statement_parses_to(sql.as_str(), sql.as_str()) {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert!(if_not_exists);
|
assert!(if_not_exists);
|
||||||
assert_eq!(name, ObjectName(vec!["something".into()]));
|
assert_eq!(name, ObjectName(vec!["something".into()]));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -3373,7 +3373,7 @@ fn parse_create_table_as() {
|
||||||
let sql = "CREATE TABLE t AS SELECT * FROM a";
|
let sql = "CREATE TABLE t AS SELECT * FROM a";
|
||||||
|
|
||||||
match verified_stmt(sql) {
|
match verified_stmt(sql) {
|
||||||
Statement::CreateTable { name, query, .. } => {
|
Statement::CreateTable(CreateTable { name, query, .. }) => {
|
||||||
assert_eq!(name.to_string(), "t".to_string());
|
assert_eq!(name.to_string(), "t".to_string());
|
||||||
assert_eq!(query, Some(Box::new(verified_query("SELECT * FROM a"))));
|
assert_eq!(query, Some(Box::new(verified_query("SELECT * FROM a"))));
|
||||||
}
|
}
|
||||||
|
@ -3385,7 +3385,7 @@ fn parse_create_table_as() {
|
||||||
// (without data types) in a CTAS, but we have yet to support that.
|
// (without data types) in a CTAS, but we have yet to support that.
|
||||||
let sql = "CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a";
|
let sql = "CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a";
|
||||||
match verified_stmt(sql) {
|
match verified_stmt(sql) {
|
||||||
Statement::CreateTable { columns, query, .. } => {
|
Statement::CreateTable(CreateTable { columns, query, .. }) => {
|
||||||
assert_eq!(columns.len(), 2);
|
assert_eq!(columns.len(), 2);
|
||||||
assert_eq!(columns[0].to_string(), "a INT".to_string());
|
assert_eq!(columns[0].to_string(), "a INT".to_string());
|
||||||
assert_eq!(columns[1].to_string(), "b INT".to_string());
|
assert_eq!(columns[1].to_string(), "b INT".to_string());
|
||||||
|
@ -3418,7 +3418,7 @@ fn parse_create_table_as_table() {
|
||||||
});
|
});
|
||||||
|
|
||||||
match verified_stmt(sql1) {
|
match verified_stmt(sql1) {
|
||||||
Statement::CreateTable { query, name, .. } => {
|
Statement::CreateTable(CreateTable { query, name, .. }) => {
|
||||||
assert_eq!(name, ObjectName(vec![Ident::new("new_table")]));
|
assert_eq!(name, ObjectName(vec![Ident::new("new_table")]));
|
||||||
assert_eq!(query.unwrap(), expected_query1);
|
assert_eq!(query.unwrap(), expected_query1);
|
||||||
}
|
}
|
||||||
|
@ -3443,7 +3443,7 @@ fn parse_create_table_as_table() {
|
||||||
});
|
});
|
||||||
|
|
||||||
match verified_stmt(sql2) {
|
match verified_stmt(sql2) {
|
||||||
Statement::CreateTable { query, name, .. } => {
|
Statement::CreateTable(CreateTable { query, name, .. }) => {
|
||||||
assert_eq!(name, ObjectName(vec![Ident::new("new_table")]));
|
assert_eq!(name, ObjectName(vec![Ident::new("new_table")]));
|
||||||
assert_eq!(query.unwrap(), expected_query2);
|
assert_eq!(query.unwrap(), expected_query2);
|
||||||
}
|
}
|
||||||
|
@ -3456,7 +3456,7 @@ fn parse_create_table_on_cluster() {
|
||||||
// Using single-quote literal to define current cluster
|
// Using single-quote literal to define current cluster
|
||||||
let sql = "CREATE TABLE t ON CLUSTER '{cluster}' (a INT, b INT)";
|
let sql = "CREATE TABLE t ON CLUSTER '{cluster}' (a INT, b INT)";
|
||||||
match verified_stmt(sql) {
|
match verified_stmt(sql) {
|
||||||
Statement::CreateTable { on_cluster, .. } => {
|
Statement::CreateTable(CreateTable { on_cluster, .. }) => {
|
||||||
assert_eq!(on_cluster.unwrap(), "{cluster}".to_string());
|
assert_eq!(on_cluster.unwrap(), "{cluster}".to_string());
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -3465,7 +3465,7 @@ fn parse_create_table_on_cluster() {
|
||||||
// Using explicitly declared cluster name
|
// Using explicitly declared cluster name
|
||||||
let sql = "CREATE TABLE t ON CLUSTER my_cluster (a INT, b INT)";
|
let sql = "CREATE TABLE t ON CLUSTER my_cluster (a INT, b INT)";
|
||||||
match verified_stmt(sql) {
|
match verified_stmt(sql) {
|
||||||
Statement::CreateTable { on_cluster, .. } => {
|
Statement::CreateTable(CreateTable { on_cluster, .. }) => {
|
||||||
assert_eq!(on_cluster.unwrap(), "my_cluster".to_string());
|
assert_eq!(on_cluster.unwrap(), "my_cluster".to_string());
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -3477,9 +3477,9 @@ fn parse_create_or_replace_table() {
|
||||||
let sql = "CREATE OR REPLACE TABLE t (a INT)";
|
let sql = "CREATE OR REPLACE TABLE t (a INT)";
|
||||||
|
|
||||||
match verified_stmt(sql) {
|
match verified_stmt(sql) {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name, or_replace, ..
|
name, or_replace, ..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!(name.to_string(), "t".to_string());
|
assert_eq!(name.to_string(), "t".to_string());
|
||||||
assert!(or_replace);
|
assert!(or_replace);
|
||||||
}
|
}
|
||||||
|
@ -3488,7 +3488,7 @@ fn parse_create_or_replace_table() {
|
||||||
|
|
||||||
let sql = "CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a";
|
let sql = "CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a";
|
||||||
match verified_stmt(sql) {
|
match verified_stmt(sql) {
|
||||||
Statement::CreateTable { columns, query, .. } => {
|
Statement::CreateTable(CreateTable { columns, query, .. }) => {
|
||||||
assert_eq!(columns.len(), 2);
|
assert_eq!(columns.len(), 2);
|
||||||
assert_eq!(columns[0].to_string(), "a INT".to_string());
|
assert_eq!(columns[0].to_string(), "a INT".to_string());
|
||||||
assert_eq!(columns[1].to_string(), "b INT".to_string());
|
assert_eq!(columns[1].to_string(), "b INT".to_string());
|
||||||
|
@ -3519,7 +3519,7 @@ fn parse_create_table_with_on_delete_on_update_2in_any_order() -> Result<(), Par
|
||||||
fn parse_create_table_with_options() {
|
fn parse_create_table_with_options() {
|
||||||
let sql = "CREATE TABLE t (c INT) WITH (foo = 'bar', a = 123)";
|
let sql = "CREATE TABLE t (c INT) WITH (foo = 'bar', a = 123)";
|
||||||
match verified_stmt(sql) {
|
match verified_stmt(sql) {
|
||||||
Statement::CreateTable { with_options, .. } => {
|
Statement::CreateTable(CreateTable { with_options, .. }) => {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
SqlOption {
|
SqlOption {
|
||||||
|
@ -3542,7 +3542,7 @@ fn parse_create_table_with_options() {
|
||||||
fn parse_create_table_clone() {
|
fn parse_create_table_clone() {
|
||||||
let sql = "CREATE OR REPLACE TABLE a CLONE a_tmp";
|
let sql = "CREATE OR REPLACE TABLE a CLONE a_tmp";
|
||||||
match verified_stmt(sql) {
|
match verified_stmt(sql) {
|
||||||
Statement::CreateTable { name, clone, .. } => {
|
Statement::CreateTable(CreateTable { name, clone, .. }) => {
|
||||||
assert_eq!(ObjectName(vec![Ident::new("a")]), name);
|
assert_eq!(ObjectName(vec![Ident::new("a")]), name);
|
||||||
assert_eq!(Some(ObjectName(vec![(Ident::new("a_tmp"))])), clone)
|
assert_eq!(Some(ObjectName(vec![(Ident::new("a_tmp"))])), clone)
|
||||||
}
|
}
|
||||||
|
@ -3572,7 +3572,7 @@ fn parse_create_external_table() {
|
||||||
STORED AS TEXTFILE LOCATION '/tmp/example.csv'",
|
STORED AS TEXTFILE LOCATION '/tmp/example.csv'",
|
||||||
);
|
);
|
||||||
match ast {
|
match ast {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
constraints,
|
constraints,
|
||||||
|
@ -3582,7 +3582,7 @@ fn parse_create_external_table() {
|
||||||
file_format,
|
file_format,
|
||||||
location,
|
location,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!("uk_cities", name.to_string());
|
assert_eq!("uk_cities", name.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
columns,
|
columns,
|
||||||
|
@ -3643,7 +3643,7 @@ fn parse_create_or_replace_external_table() {
|
||||||
STORED AS TEXTFILE LOCATION '/tmp/example.csv'",
|
STORED AS TEXTFILE LOCATION '/tmp/example.csv'",
|
||||||
);
|
);
|
||||||
match ast {
|
match ast {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
constraints,
|
constraints,
|
||||||
|
@ -3654,7 +3654,7 @@ fn parse_create_or_replace_external_table() {
|
||||||
location,
|
location,
|
||||||
or_replace,
|
or_replace,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!("uk_cities", name.to_string());
|
assert_eq!("uk_cities", name.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
columns,
|
columns,
|
||||||
|
@ -3700,7 +3700,7 @@ fn parse_create_external_table_lowercase() {
|
||||||
lng DOUBLE) \
|
lng DOUBLE) \
|
||||||
STORED AS PARQUET LOCATION '/tmp/example.csv'",
|
STORED AS PARQUET LOCATION '/tmp/example.csv'",
|
||||||
);
|
);
|
||||||
assert_matches!(ast, Statement::CreateTable { .. });
|
assert_matches!(ast, Statement::CreateTable(CreateTable { .. }));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -7210,14 +7210,14 @@ fn parse_create_index() {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
match verified_stmt(sql) {
|
match verified_stmt(sql) {
|
||||||
Statement::CreateIndex {
|
Statement::CreateIndex(CreateIndex {
|
||||||
name: Some(name),
|
name: Some(name),
|
||||||
table_name,
|
table_name,
|
||||||
columns,
|
columns,
|
||||||
unique,
|
unique,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!("idx_name", name.to_string());
|
assert_eq!("idx_name", name.to_string());
|
||||||
assert_eq!("test", table_name.to_string());
|
assert_eq!("test", table_name.to_string());
|
||||||
assert_eq!(indexed_columns, columns);
|
assert_eq!(indexed_columns, columns);
|
||||||
|
@ -7244,7 +7244,7 @@ fn test_create_index_with_using_function() {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
match verified_stmt(sql) {
|
match verified_stmt(sql) {
|
||||||
Statement::CreateIndex {
|
Statement::CreateIndex(CreateIndex {
|
||||||
name: Some(name),
|
name: Some(name),
|
||||||
table_name,
|
table_name,
|
||||||
using,
|
using,
|
||||||
|
@ -7255,7 +7255,7 @@ fn test_create_index_with_using_function() {
|
||||||
include,
|
include,
|
||||||
nulls_distinct: None,
|
nulls_distinct: None,
|
||||||
predicate: None,
|
predicate: None,
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!("idx_name", name.to_string());
|
assert_eq!("idx_name", name.to_string());
|
||||||
assert_eq!("test", table_name.to_string());
|
assert_eq!("test", table_name.to_string());
|
||||||
assert_eq!("btree", using.unwrap().to_string());
|
assert_eq!("btree", using.unwrap().to_string());
|
||||||
|
|
|
@ -470,7 +470,7 @@ fn parse_set_variables() {
|
||||||
fn parse_create_table_auto_increment() {
|
fn parse_create_table_auto_increment() {
|
||||||
let sql = "CREATE TABLE foo (bar INT PRIMARY KEY AUTO_INCREMENT)";
|
let sql = "CREATE TABLE foo (bar INT PRIMARY KEY AUTO_INCREMENT)";
|
||||||
match mysql().verified_stmt(sql) {
|
match mysql().verified_stmt(sql) {
|
||||||
Statement::CreateTable { name, columns, .. } => {
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![ColumnDef {
|
vec![ColumnDef {
|
||||||
|
@ -541,12 +541,12 @@ fn parse_create_table_primary_and_unique_key() {
|
||||||
|
|
||||||
for (sql, index_type_display) in sqls.iter().zip(index_type_display) {
|
for (sql, index_type_display) in sqls.iter().zip(index_type_display) {
|
||||||
match mysql().one_statement_parses_to(sql, "") {
|
match mysql().one_statement_parses_to(sql, "") {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
constraints,
|
constraints,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
|
|
||||||
let expected_constraint = table_constraint_unique_primary_ctor(
|
let expected_constraint = table_constraint_unique_primary_ctor(
|
||||||
|
@ -609,9 +609,9 @@ fn parse_create_table_primary_and_unique_key_with_index_options() {
|
||||||
|
|
||||||
for (sql, index_type_display) in sqls.iter().zip(index_type_display) {
|
for (sql, index_type_display) in sqls.iter().zip(index_type_display) {
|
||||||
match mysql_and_generic().one_statement_parses_to(sql, "") {
|
match mysql_and_generic().one_statement_parses_to(sql, "") {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name, constraints, ..
|
name, constraints, ..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
|
|
||||||
let expected_constraint = table_constraint_unique_primary_ctor(
|
let expected_constraint = table_constraint_unique_primary_ctor(
|
||||||
|
@ -647,9 +647,9 @@ fn parse_create_table_primary_and_unique_key_with_index_type() {
|
||||||
|
|
||||||
for (sql, index_type_display) in sqls.iter().zip(index_type_display) {
|
for (sql, index_type_display) in sqls.iter().zip(index_type_display) {
|
||||||
match mysql_and_generic().one_statement_parses_to(sql, "") {
|
match mysql_and_generic().one_statement_parses_to(sql, "") {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name, constraints, ..
|
name, constraints, ..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
|
|
||||||
let expected_constraint = table_constraint_unique_primary_ctor(
|
let expected_constraint = table_constraint_unique_primary_ctor(
|
||||||
|
@ -690,7 +690,7 @@ fn parse_create_table_comment() {
|
||||||
|
|
||||||
for sql in [canonical, with_equal] {
|
for sql in [canonical, with_equal] {
|
||||||
match mysql().one_statement_parses_to(sql, canonical) {
|
match mysql().one_statement_parses_to(sql, canonical) {
|
||||||
Statement::CreateTable { name, comment, .. } => {
|
Statement::CreateTable(CreateTable { name, comment, .. }) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
assert_eq!(comment.expect("Should exist").to_string(), "baz");
|
assert_eq!(comment.expect("Should exist").to_string(), "baz");
|
||||||
}
|
}
|
||||||
|
@ -708,11 +708,11 @@ fn parse_create_table_auto_increment_offset() {
|
||||||
|
|
||||||
for sql in [canonical, with_equal] {
|
for sql in [canonical, with_equal] {
|
||||||
match mysql().one_statement_parses_to(sql, canonical) {
|
match mysql().one_statement_parses_to(sql, canonical) {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
auto_increment_offset,
|
auto_increment_offset,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
auto_increment_offset.expect("Should exist").to_string(),
|
auto_increment_offset.expect("Should exist").to_string(),
|
||||||
|
@ -728,7 +728,7 @@ fn parse_create_table_auto_increment_offset() {
|
||||||
fn parse_create_table_set_enum() {
|
fn parse_create_table_set_enum() {
|
||||||
let sql = "CREATE TABLE foo (bar SET('a', 'b'), baz ENUM('a', 'b'))";
|
let sql = "CREATE TABLE foo (bar SET('a', 'b'), baz ENUM('a', 'b'))";
|
||||||
match mysql().verified_stmt(sql) {
|
match mysql().verified_stmt(sql) {
|
||||||
Statement::CreateTable { name, columns, .. } => {
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
|
@ -756,13 +756,13 @@ fn parse_create_table_set_enum() {
|
||||||
fn parse_create_table_engine_default_charset() {
|
fn parse_create_table_engine_default_charset() {
|
||||||
let sql = "CREATE TABLE foo (id INT(11)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3";
|
let sql = "CREATE TABLE foo (id INT(11)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3";
|
||||||
match mysql().verified_stmt(sql) {
|
match mysql().verified_stmt(sql) {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
engine,
|
engine,
|
||||||
default_charset,
|
default_charset,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![ColumnDef {
|
vec![ColumnDef {
|
||||||
|
@ -784,12 +784,12 @@ fn parse_create_table_engine_default_charset() {
|
||||||
fn parse_create_table_collate() {
|
fn parse_create_table_collate() {
|
||||||
let sql = "CREATE TABLE foo (id INT(11)) COLLATE=utf8mb4_0900_ai_ci";
|
let sql = "CREATE TABLE foo (id INT(11)) COLLATE=utf8mb4_0900_ai_ci";
|
||||||
match mysql().verified_stmt(sql) {
|
match mysql().verified_stmt(sql) {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
collation,
|
collation,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![ColumnDef {
|
vec![ColumnDef {
|
||||||
|
@ -810,7 +810,7 @@ fn parse_create_table_collate() {
|
||||||
fn parse_create_table_comment_character_set() {
|
fn parse_create_table_comment_character_set() {
|
||||||
let sql = "CREATE TABLE foo (s TEXT CHARACTER SET utf8mb4 COMMENT 'comment')";
|
let sql = "CREATE TABLE foo (s TEXT CHARACTER SET utf8mb4 COMMENT 'comment')";
|
||||||
match mysql().verified_stmt(sql) {
|
match mysql().verified_stmt(sql) {
|
||||||
Statement::CreateTable { name, columns, .. } => {
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![ColumnDef {
|
vec![ColumnDef {
|
||||||
|
@ -857,7 +857,7 @@ fn parse_create_table_gencol() {
|
||||||
fn parse_quote_identifiers() {
|
fn parse_quote_identifiers() {
|
||||||
let sql = "CREATE TABLE `PRIMARY` (`BEGIN` INT PRIMARY KEY)";
|
let sql = "CREATE TABLE `PRIMARY` (`BEGIN` INT PRIMARY KEY)";
|
||||||
match mysql().verified_stmt(sql) {
|
match mysql().verified_stmt(sql) {
|
||||||
Statement::CreateTable { name, columns, .. } => {
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
assert_eq!(name.to_string(), "`PRIMARY`");
|
assert_eq!(name.to_string(), "`PRIMARY`");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![ColumnDef {
|
vec![ColumnDef {
|
||||||
|
@ -1126,7 +1126,7 @@ fn check_roundtrip_of_escaped_string() {
|
||||||
fn parse_create_table_with_minimum_display_width() {
|
fn parse_create_table_with_minimum_display_width() {
|
||||||
let sql = "CREATE TABLE foo (bar_tinyint TINYINT(3), bar_smallint SMALLINT(5), bar_mediumint MEDIUMINT(6), bar_int INT(11), bar_bigint BIGINT(20))";
|
let sql = "CREATE TABLE foo (bar_tinyint TINYINT(3), bar_smallint SMALLINT(5), bar_mediumint MEDIUMINT(6), bar_int INT(11), bar_bigint BIGINT(20))";
|
||||||
match mysql().verified_stmt(sql) {
|
match mysql().verified_stmt(sql) {
|
||||||
Statement::CreateTable { name, columns, .. } => {
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
|
@ -1172,7 +1172,7 @@ fn parse_create_table_with_minimum_display_width() {
|
||||||
fn parse_create_table_unsigned() {
|
fn parse_create_table_unsigned() {
|
||||||
let sql = "CREATE TABLE foo (bar_tinyint TINYINT(3) UNSIGNED, bar_smallint SMALLINT(5) UNSIGNED, bar_mediumint MEDIUMINT(13) UNSIGNED, bar_int INT(11) UNSIGNED, bar_bigint BIGINT(20) UNSIGNED)";
|
let sql = "CREATE TABLE foo (bar_tinyint TINYINT(3) UNSIGNED, bar_smallint SMALLINT(5) UNSIGNED, bar_mediumint MEDIUMINT(13) UNSIGNED, bar_int INT(11) UNSIGNED, bar_bigint BIGINT(20) UNSIGNED)";
|
||||||
match mysql().verified_stmt(sql) {
|
match mysql().verified_stmt(sql) {
|
||||||
Statement::CreateTable { name, columns, .. } => {
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
|
@ -2321,7 +2321,7 @@ fn parse_kill() {
|
||||||
fn parse_table_colum_option_on_update() {
|
fn parse_table_colum_option_on_update() {
|
||||||
let sql1 = "CREATE TABLE foo (`modification_time` DATETIME ON UPDATE CURRENT_TIMESTAMP())";
|
let sql1 = "CREATE TABLE foo (`modification_time` DATETIME ON UPDATE CURRENT_TIMESTAMP())";
|
||||||
match mysql().verified_stmt(sql1) {
|
match mysql().verified_stmt(sql1) {
|
||||||
Statement::CreateTable { name, columns, .. } => {
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![ColumnDef {
|
vec![ColumnDef {
|
||||||
|
@ -2622,7 +2622,7 @@ fn parse_create_table_with_column_collate() {
|
||||||
let sql = "CREATE TABLE tb (id TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci)";
|
let sql = "CREATE TABLE tb (id TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci)";
|
||||||
let canonical = "CREATE TABLE tb (id TEXT COLLATE utf8mb4_0900_ai_ci CHARACTER SET utf8mb4)";
|
let canonical = "CREATE TABLE tb (id TEXT COLLATE utf8mb4_0900_ai_ci CHARACTER SET utf8mb4)";
|
||||||
match mysql().one_statement_parses_to(sql, canonical) {
|
match mysql().one_statement_parses_to(sql, canonical) {
|
||||||
Statement::CreateTable { name, columns, .. } => {
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
assert_eq!(name.to_string(), "tb");
|
assert_eq!(name.to_string(), "tb");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![ColumnDef {
|
vec![ColumnDef {
|
||||||
|
|
|
@ -317,7 +317,7 @@ fn parse_create_table_with_defaults() {
|
||||||
active int NOT NULL
|
active int NOT NULL
|
||||||
) WITH (fillfactor = 20, user_catalog_table = true, autovacuum_vacuum_threshold = 100)";
|
) WITH (fillfactor = 20, user_catalog_table = true, autovacuum_vacuum_threshold = 100)";
|
||||||
match pg_and_generic().one_statement_parses_to(sql, "") {
|
match pg_and_generic().one_statement_parses_to(sql, "") {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
constraints,
|
constraints,
|
||||||
|
@ -327,7 +327,7 @@ fn parse_create_table_with_defaults() {
|
||||||
file_format: None,
|
file_format: None,
|
||||||
location: None,
|
location: None,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
assert_eq!("public.customer", name.to_string());
|
assert_eq!("public.customer", name.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -537,12 +537,12 @@ fn parse_create_table_constraints_only() {
|
||||||
let sql = "CREATE TABLE t (CONSTRAINT positive CHECK (2 > 1))";
|
let sql = "CREATE TABLE t (CONSTRAINT positive CHECK (2 > 1))";
|
||||||
let ast = pg_and_generic().verified_stmt(sql);
|
let ast = pg_and_generic().verified_stmt(sql);
|
||||||
match ast {
|
match ast {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
constraints,
|
constraints,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!("t", name.to_string());
|
assert_eq!("t", name.to_string());
|
||||||
assert!(columns.is_empty());
|
assert!(columns.is_empty());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -718,11 +718,11 @@ fn parse_create_table_if_not_exists() {
|
||||||
let sql = "CREATE TABLE IF NOT EXISTS uk_cities ()";
|
let sql = "CREATE TABLE IF NOT EXISTS uk_cities ()";
|
||||||
let ast = pg_and_generic().verified_stmt(sql);
|
let ast = pg_and_generic().verified_stmt(sql);
|
||||||
match ast {
|
match ast {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
if_not_exists: true,
|
if_not_exists: true,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!("uk_cities", name.to_string());
|
assert_eq!("uk_cities", name.to_string());
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -2086,7 +2086,7 @@ fn parse_array_multi_subscript() {
|
||||||
fn parse_create_index() {
|
fn parse_create_index() {
|
||||||
let sql = "CREATE INDEX IF NOT EXISTS my_index ON my_table(col1,col2)";
|
let sql = "CREATE INDEX IF NOT EXISTS my_index ON my_table(col1,col2)";
|
||||||
match pg().verified_stmt(sql) {
|
match pg().verified_stmt(sql) {
|
||||||
Statement::CreateIndex {
|
Statement::CreateIndex(CreateIndex {
|
||||||
name: Some(ObjectName(name)),
|
name: Some(ObjectName(name)),
|
||||||
table_name: ObjectName(table_name),
|
table_name: ObjectName(table_name),
|
||||||
using,
|
using,
|
||||||
|
@ -2097,7 +2097,7 @@ fn parse_create_index() {
|
||||||
nulls_distinct: None,
|
nulls_distinct: None,
|
||||||
include,
|
include,
|
||||||
predicate: None,
|
predicate: None,
|
||||||
} => {
|
}) => {
|
||||||
assert_eq_vec(&["my_index"], &name);
|
assert_eq_vec(&["my_index"], &name);
|
||||||
assert_eq_vec(&["my_table"], &table_name);
|
assert_eq_vec(&["my_table"], &table_name);
|
||||||
assert_eq!(None, using);
|
assert_eq!(None, using);
|
||||||
|
@ -2115,7 +2115,7 @@ fn parse_create_index() {
|
||||||
fn parse_create_anonymous_index() {
|
fn parse_create_anonymous_index() {
|
||||||
let sql = "CREATE INDEX ON my_table(col1,col2)";
|
let sql = "CREATE INDEX ON my_table(col1,col2)";
|
||||||
match pg().verified_stmt(sql) {
|
match pg().verified_stmt(sql) {
|
||||||
Statement::CreateIndex {
|
Statement::CreateIndex(CreateIndex {
|
||||||
name,
|
name,
|
||||||
table_name: ObjectName(table_name),
|
table_name: ObjectName(table_name),
|
||||||
using,
|
using,
|
||||||
|
@ -2126,7 +2126,7 @@ fn parse_create_anonymous_index() {
|
||||||
include,
|
include,
|
||||||
nulls_distinct: None,
|
nulls_distinct: None,
|
||||||
predicate: None,
|
predicate: None,
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!(None, name);
|
assert_eq!(None, name);
|
||||||
assert_eq_vec(&["my_table"], &table_name);
|
assert_eq_vec(&["my_table"], &table_name);
|
||||||
assert_eq!(None, using);
|
assert_eq!(None, using);
|
||||||
|
@ -2144,7 +2144,7 @@ fn parse_create_anonymous_index() {
|
||||||
fn parse_create_index_concurrently() {
|
fn parse_create_index_concurrently() {
|
||||||
let sql = "CREATE INDEX CONCURRENTLY IF NOT EXISTS my_index ON my_table(col1,col2)";
|
let sql = "CREATE INDEX CONCURRENTLY IF NOT EXISTS my_index ON my_table(col1,col2)";
|
||||||
match pg().verified_stmt(sql) {
|
match pg().verified_stmt(sql) {
|
||||||
Statement::CreateIndex {
|
Statement::CreateIndex(CreateIndex {
|
||||||
name: Some(ObjectName(name)),
|
name: Some(ObjectName(name)),
|
||||||
table_name: ObjectName(table_name),
|
table_name: ObjectName(table_name),
|
||||||
using,
|
using,
|
||||||
|
@ -2155,7 +2155,7 @@ fn parse_create_index_concurrently() {
|
||||||
include,
|
include,
|
||||||
nulls_distinct: None,
|
nulls_distinct: None,
|
||||||
predicate: None,
|
predicate: None,
|
||||||
} => {
|
}) => {
|
||||||
assert_eq_vec(&["my_index"], &name);
|
assert_eq_vec(&["my_index"], &name);
|
||||||
assert_eq_vec(&["my_table"], &table_name);
|
assert_eq_vec(&["my_table"], &table_name);
|
||||||
assert_eq!(None, using);
|
assert_eq!(None, using);
|
||||||
|
@ -2173,7 +2173,7 @@ fn parse_create_index_concurrently() {
|
||||||
fn parse_create_index_with_predicate() {
|
fn parse_create_index_with_predicate() {
|
||||||
let sql = "CREATE INDEX IF NOT EXISTS my_index ON my_table(col1,col2) WHERE col3 IS NULL";
|
let sql = "CREATE INDEX IF NOT EXISTS my_index ON my_table(col1,col2) WHERE col3 IS NULL";
|
||||||
match pg().verified_stmt(sql) {
|
match pg().verified_stmt(sql) {
|
||||||
Statement::CreateIndex {
|
Statement::CreateIndex(CreateIndex {
|
||||||
name: Some(ObjectName(name)),
|
name: Some(ObjectName(name)),
|
||||||
table_name: ObjectName(table_name),
|
table_name: ObjectName(table_name),
|
||||||
using,
|
using,
|
||||||
|
@ -2184,7 +2184,7 @@ fn parse_create_index_with_predicate() {
|
||||||
include,
|
include,
|
||||||
nulls_distinct: None,
|
nulls_distinct: None,
|
||||||
predicate: Some(_),
|
predicate: Some(_),
|
||||||
} => {
|
}) => {
|
||||||
assert_eq_vec(&["my_index"], &name);
|
assert_eq_vec(&["my_index"], &name);
|
||||||
assert_eq_vec(&["my_table"], &table_name);
|
assert_eq_vec(&["my_table"], &table_name);
|
||||||
assert_eq!(None, using);
|
assert_eq!(None, using);
|
||||||
|
@ -2202,7 +2202,7 @@ fn parse_create_index_with_predicate() {
|
||||||
fn parse_create_index_with_include() {
|
fn parse_create_index_with_include() {
|
||||||
let sql = "CREATE INDEX IF NOT EXISTS my_index ON my_table(col1,col2) INCLUDE (col3)";
|
let sql = "CREATE INDEX IF NOT EXISTS my_index ON my_table(col1,col2) INCLUDE (col3)";
|
||||||
match pg().verified_stmt(sql) {
|
match pg().verified_stmt(sql) {
|
||||||
Statement::CreateIndex {
|
Statement::CreateIndex(CreateIndex {
|
||||||
name: Some(ObjectName(name)),
|
name: Some(ObjectName(name)),
|
||||||
table_name: ObjectName(table_name),
|
table_name: ObjectName(table_name),
|
||||||
using,
|
using,
|
||||||
|
@ -2213,7 +2213,7 @@ fn parse_create_index_with_include() {
|
||||||
include,
|
include,
|
||||||
nulls_distinct: None,
|
nulls_distinct: None,
|
||||||
predicate: None,
|
predicate: None,
|
||||||
} => {
|
}) => {
|
||||||
assert_eq_vec(&["my_index"], &name);
|
assert_eq_vec(&["my_index"], &name);
|
||||||
assert_eq_vec(&["my_table"], &table_name);
|
assert_eq_vec(&["my_table"], &table_name);
|
||||||
assert_eq!(None, using);
|
assert_eq!(None, using);
|
||||||
|
@ -2231,7 +2231,7 @@ fn parse_create_index_with_include() {
|
||||||
fn parse_create_index_with_nulls_distinct() {
|
fn parse_create_index_with_nulls_distinct() {
|
||||||
let sql = "CREATE INDEX IF NOT EXISTS my_index ON my_table(col1,col2) NULLS NOT DISTINCT";
|
let sql = "CREATE INDEX IF NOT EXISTS my_index ON my_table(col1,col2) NULLS NOT DISTINCT";
|
||||||
match pg().verified_stmt(sql) {
|
match pg().verified_stmt(sql) {
|
||||||
Statement::CreateIndex {
|
Statement::CreateIndex(CreateIndex {
|
||||||
name: Some(ObjectName(name)),
|
name: Some(ObjectName(name)),
|
||||||
table_name: ObjectName(table_name),
|
table_name: ObjectName(table_name),
|
||||||
using,
|
using,
|
||||||
|
@ -2242,7 +2242,7 @@ fn parse_create_index_with_nulls_distinct() {
|
||||||
include,
|
include,
|
||||||
nulls_distinct: Some(nulls_distinct),
|
nulls_distinct: Some(nulls_distinct),
|
||||||
predicate: None,
|
predicate: None,
|
||||||
} => {
|
}) => {
|
||||||
assert_eq_vec(&["my_index"], &name);
|
assert_eq_vec(&["my_index"], &name);
|
||||||
assert_eq_vec(&["my_table"], &table_name);
|
assert_eq_vec(&["my_table"], &table_name);
|
||||||
assert_eq!(None, using);
|
assert_eq!(None, using);
|
||||||
|
@ -2258,7 +2258,7 @@ fn parse_create_index_with_nulls_distinct() {
|
||||||
|
|
||||||
let sql = "CREATE INDEX IF NOT EXISTS my_index ON my_table(col1,col2) NULLS DISTINCT";
|
let sql = "CREATE INDEX IF NOT EXISTS my_index ON my_table(col1,col2) NULLS DISTINCT";
|
||||||
match pg().verified_stmt(sql) {
|
match pg().verified_stmt(sql) {
|
||||||
Statement::CreateIndex {
|
Statement::CreateIndex(CreateIndex {
|
||||||
name: Some(ObjectName(name)),
|
name: Some(ObjectName(name)),
|
||||||
table_name: ObjectName(table_name),
|
table_name: ObjectName(table_name),
|
||||||
using,
|
using,
|
||||||
|
@ -2269,7 +2269,7 @@ fn parse_create_index_with_nulls_distinct() {
|
||||||
include,
|
include,
|
||||||
nulls_distinct: Some(nulls_distinct),
|
nulls_distinct: Some(nulls_distinct),
|
||||||
predicate: None,
|
predicate: None,
|
||||||
} => {
|
}) => {
|
||||||
assert_eq_vec(&["my_index"], &name);
|
assert_eq_vec(&["my_index"], &name);
|
||||||
assert_eq_vec(&["my_table"], &table_name);
|
assert_eq_vec(&["my_table"], &table_name);
|
||||||
assert_eq!(None, using);
|
assert_eq!(None, using);
|
||||||
|
@ -3704,7 +3704,7 @@ fn parse_create_table_with_alias() {
|
||||||
bool_col BOOL,
|
bool_col BOOL,
|
||||||
);";
|
);";
|
||||||
match pg_and_generic().one_statement_parses_to(sql, "") {
|
match pg_and_generic().one_statement_parses_to(sql, "") {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
constraints,
|
constraints,
|
||||||
|
@ -3714,7 +3714,7 @@ fn parse_create_table_with_alias() {
|
||||||
file_format: None,
|
file_format: None,
|
||||||
location: None,
|
location: None,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!("public.datatype_aliases", name.to_string());
|
assert_eq!("public.datatype_aliases", name.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
columns,
|
columns,
|
||||||
|
|
|
@ -33,7 +33,7 @@ use pretty_assertions::assert_eq;
|
||||||
fn test_snowflake_create_table() {
|
fn test_snowflake_create_table() {
|
||||||
let sql = "CREATE TABLE _my_$table (am00unt number)";
|
let sql = "CREATE TABLE _my_$table (am00unt number)";
|
||||||
match snowflake_and_generic().verified_stmt(sql) {
|
match snowflake_and_generic().verified_stmt(sql) {
|
||||||
Statement::CreateTable { name, .. } => {
|
Statement::CreateTable(CreateTable { name, .. }) => {
|
||||||
assert_eq!("_my_$table", name.to_string());
|
assert_eq!("_my_$table", name.to_string());
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -44,9 +44,9 @@ fn test_snowflake_create_table() {
|
||||||
fn test_snowflake_create_transient_table() {
|
fn test_snowflake_create_transient_table() {
|
||||||
let sql = "CREATE TRANSIENT TABLE CUSTOMER (id INT, name VARCHAR(255))";
|
let sql = "CREATE TRANSIENT TABLE CUSTOMER (id INT, name VARCHAR(255))";
|
||||||
match snowflake_and_generic().verified_stmt(sql) {
|
match snowflake_and_generic().verified_stmt(sql) {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name, transient, ..
|
name, transient, ..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!("CUSTOMER", name.to_string());
|
assert_eq!("CUSTOMER", name.to_string());
|
||||||
assert!(transient)
|
assert!(transient)
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,11 +122,11 @@ fn pragma_eq_placeholder_style() {
|
||||||
fn parse_create_table_without_rowid() {
|
fn parse_create_table_without_rowid() {
|
||||||
let sql = "CREATE TABLE t (a INT) WITHOUT ROWID";
|
let sql = "CREATE TABLE t (a INT) WITHOUT ROWID";
|
||||||
match sqlite_and_generic().verified_stmt(sql) {
|
match sqlite_and_generic().verified_stmt(sql) {
|
||||||
Statement::CreateTable {
|
Statement::CreateTable(CreateTable {
|
||||||
name,
|
name,
|
||||||
without_rowid: true,
|
without_rowid: true,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_eq!("t", name.to_string());
|
assert_eq!("t", name.to_string());
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -200,7 +200,7 @@ fn double_equality_operator() {
|
||||||
fn parse_create_table_auto_increment() {
|
fn parse_create_table_auto_increment() {
|
||||||
let sql = "CREATE TABLE foo (bar INT PRIMARY KEY AUTOINCREMENT)";
|
let sql = "CREATE TABLE foo (bar INT PRIMARY KEY AUTOINCREMENT)";
|
||||||
match sqlite_and_generic().verified_stmt(sql) {
|
match sqlite_and_generic().verified_stmt(sql) {
|
||||||
Statement::CreateTable { name, columns, .. } => {
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
assert_eq!(name.to_string(), "foo");
|
assert_eq!(name.to_string(), "foo");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![ColumnDef {
|
vec![ColumnDef {
|
||||||
|
@ -234,7 +234,7 @@ fn parse_create_table_auto_increment() {
|
||||||
fn parse_create_sqlite_quote() {
|
fn parse_create_sqlite_quote() {
|
||||||
let sql = "CREATE TABLE `PRIMARY` (\"KEY\" INT, [INDEX] INT)";
|
let sql = "CREATE TABLE `PRIMARY` (\"KEY\" INT, [INDEX] INT)";
|
||||||
match sqlite().verified_stmt(sql) {
|
match sqlite().verified_stmt(sql) {
|
||||||
Statement::CreateTable { name, columns, .. } => {
|
Statement::CreateTable(CreateTable { name, columns, .. }) => {
|
||||||
assert_eq!(name.to_string(), "`PRIMARY`");
|
assert_eq!(name.to_string(), "`PRIMARY`");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
|
@ -295,7 +295,7 @@ fn test_placeholder() {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_create_table_with_strict() {
|
fn parse_create_table_with_strict() {
|
||||||
let sql = "CREATE TABLE Fruits (id TEXT NOT NULL PRIMARY KEY) STRICT";
|
let sql = "CREATE TABLE Fruits (id TEXT NOT NULL PRIMARY KEY) STRICT";
|
||||||
if let Statement::CreateTable { name, strict, .. } = sqlite().verified_stmt(sql) {
|
if let Statement::CreateTable(CreateTable { name, strict, .. }) = sqlite().verified_stmt(sql) {
|
||||||
assert_eq!(name.to_string(), "Fruits");
|
assert_eq!(name.to_string(), "Fruits");
|
||||||
assert!(strict);
|
assert!(strict);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue