mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-10-09 21:42:05 +00:00
feat: allow multiple actions in one ALTER TABLE
statement (#960)
This commit is contained in:
parent
e0afd4b179
commit
25e037c50f
7 changed files with 349 additions and 326 deletions
|
@ -1407,7 +1407,9 @@ pub enum Statement {
|
||||||
/// Table name
|
/// Table name
|
||||||
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
|
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
|
||||||
name: ObjectName,
|
name: ObjectName,
|
||||||
operation: AlterTableOperation,
|
if_exists: bool,
|
||||||
|
only: bool,
|
||||||
|
operations: Vec<AlterTableOperation>,
|
||||||
},
|
},
|
||||||
AlterIndex {
|
AlterIndex {
|
||||||
name: ObjectName,
|
name: ObjectName,
|
||||||
|
@ -2618,8 +2620,24 @@ impl fmt::Display for Statement {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Statement::AlterTable { name, operation } => {
|
Statement::AlterTable {
|
||||||
write!(f, "ALTER TABLE {name} {operation}")
|
name,
|
||||||
|
if_exists,
|
||||||
|
only,
|
||||||
|
operations,
|
||||||
|
} => {
|
||||||
|
write!(f, "ALTER TABLE ")?;
|
||||||
|
if *if_exists {
|
||||||
|
write!(f, "IF EXISTS ")?;
|
||||||
|
}
|
||||||
|
if *only {
|
||||||
|
write!(f, "ONLY ")?;
|
||||||
|
}
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{name} {operations}",
|
||||||
|
operations = display_comma_separated(operations)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Statement::AlterIndex { name, operation } => {
|
Statement::AlterIndex { name, operation } => {
|
||||||
write!(f, "ALTER INDEX {name} {operation}")
|
write!(f, "ALTER INDEX {name} {operation}")
|
||||||
|
|
|
@ -4081,6 +4081,174 @@ impl<'a> Parser<'a> {
|
||||||
Ok(SqlOption { name, value })
|
Ok(SqlOption { name, value })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_alter_table_operation(&mut self) -> Result<AlterTableOperation, ParserError> {
|
||||||
|
let operation = if self.parse_keyword(Keyword::ADD) {
|
||||||
|
if let Some(constraint) = self.parse_optional_table_constraint()? {
|
||||||
|
AlterTableOperation::AddConstraint(constraint)
|
||||||
|
} else {
|
||||||
|
let if_not_exists =
|
||||||
|
self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
||||||
|
if self.parse_keyword(Keyword::PARTITION) {
|
||||||
|
self.expect_token(&Token::LParen)?;
|
||||||
|
let partitions = self.parse_comma_separated(Parser::parse_expr)?;
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
AlterTableOperation::AddPartitions {
|
||||||
|
if_not_exists,
|
||||||
|
new_partitions: partitions,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let column_keyword = self.parse_keyword(Keyword::COLUMN);
|
||||||
|
|
||||||
|
let if_not_exists = if dialect_of!(self is PostgreSqlDialect | BigQueryDialect | DuckDbDialect | GenericDialect)
|
||||||
|
{
|
||||||
|
self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS])
|
||||||
|
|| if_not_exists
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
let column_def = self.parse_column_def()?;
|
||||||
|
AlterTableOperation::AddColumn {
|
||||||
|
column_keyword,
|
||||||
|
if_not_exists,
|
||||||
|
column_def,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if self.parse_keyword(Keyword::RENAME) {
|
||||||
|
if dialect_of!(self is PostgreSqlDialect) && self.parse_keyword(Keyword::CONSTRAINT) {
|
||||||
|
let old_name = self.parse_identifier()?;
|
||||||
|
self.expect_keyword(Keyword::TO)?;
|
||||||
|
let new_name = self.parse_identifier()?;
|
||||||
|
AlterTableOperation::RenameConstraint { old_name, new_name }
|
||||||
|
} else if self.parse_keyword(Keyword::TO) {
|
||||||
|
let table_name = self.parse_object_name()?;
|
||||||
|
AlterTableOperation::RenameTable { table_name }
|
||||||
|
} else {
|
||||||
|
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
|
||||||
|
let old_column_name = self.parse_identifier()?;
|
||||||
|
self.expect_keyword(Keyword::TO)?;
|
||||||
|
let new_column_name = self.parse_identifier()?;
|
||||||
|
AlterTableOperation::RenameColumn {
|
||||||
|
old_column_name,
|
||||||
|
new_column_name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if self.parse_keyword(Keyword::DROP) {
|
||||||
|
if self.parse_keywords(&[Keyword::IF, Keyword::EXISTS, Keyword::PARTITION]) {
|
||||||
|
self.expect_token(&Token::LParen)?;
|
||||||
|
let partitions = self.parse_comma_separated(Parser::parse_expr)?;
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
AlterTableOperation::DropPartitions {
|
||||||
|
partitions,
|
||||||
|
if_exists: true,
|
||||||
|
}
|
||||||
|
} else if self.parse_keyword(Keyword::PARTITION) {
|
||||||
|
self.expect_token(&Token::LParen)?;
|
||||||
|
let partitions = self.parse_comma_separated(Parser::parse_expr)?;
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
AlterTableOperation::DropPartitions {
|
||||||
|
partitions,
|
||||||
|
if_exists: false,
|
||||||
|
}
|
||||||
|
} else if self.parse_keyword(Keyword::CONSTRAINT) {
|
||||||
|
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||||
|
let name = self.parse_identifier()?;
|
||||||
|
let cascade = self.parse_keyword(Keyword::CASCADE);
|
||||||
|
AlterTableOperation::DropConstraint {
|
||||||
|
if_exists,
|
||||||
|
name,
|
||||||
|
cascade,
|
||||||
|
}
|
||||||
|
} else if self.parse_keywords(&[Keyword::PRIMARY, Keyword::KEY])
|
||||||
|
&& dialect_of!(self is MySqlDialect | GenericDialect)
|
||||||
|
{
|
||||||
|
AlterTableOperation::DropPrimaryKey
|
||||||
|
} else {
|
||||||
|
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
|
||||||
|
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||||
|
let column_name = self.parse_identifier()?;
|
||||||
|
let cascade = self.parse_keyword(Keyword::CASCADE);
|
||||||
|
AlterTableOperation::DropColumn {
|
||||||
|
column_name,
|
||||||
|
if_exists,
|
||||||
|
cascade,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if self.parse_keyword(Keyword::PARTITION) {
|
||||||
|
self.expect_token(&Token::LParen)?;
|
||||||
|
let before = self.parse_comma_separated(Parser::parse_expr)?;
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
self.expect_keyword(Keyword::RENAME)?;
|
||||||
|
self.expect_keywords(&[Keyword::TO, Keyword::PARTITION])?;
|
||||||
|
self.expect_token(&Token::LParen)?;
|
||||||
|
let renames = self.parse_comma_separated(Parser::parse_expr)?;
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
AlterTableOperation::RenamePartitions {
|
||||||
|
old_partitions: before,
|
||||||
|
new_partitions: renames,
|
||||||
|
}
|
||||||
|
} else if self.parse_keyword(Keyword::CHANGE) {
|
||||||
|
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
|
||||||
|
let old_name = self.parse_identifier()?;
|
||||||
|
let new_name = self.parse_identifier()?;
|
||||||
|
let data_type = self.parse_data_type()?;
|
||||||
|
let mut options = vec![];
|
||||||
|
while let Some(option) = self.parse_optional_column_option()? {
|
||||||
|
options.push(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
AlterTableOperation::ChangeColumn {
|
||||||
|
old_name,
|
||||||
|
new_name,
|
||||||
|
data_type,
|
||||||
|
options,
|
||||||
|
}
|
||||||
|
} else if self.parse_keyword(Keyword::ALTER) {
|
||||||
|
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
|
||||||
|
let column_name = self.parse_identifier()?;
|
||||||
|
let is_postgresql = dialect_of!(self is PostgreSqlDialect);
|
||||||
|
|
||||||
|
let op = if self.parse_keywords(&[Keyword::SET, Keyword::NOT, Keyword::NULL]) {
|
||||||
|
AlterColumnOperation::SetNotNull {}
|
||||||
|
} else if self.parse_keywords(&[Keyword::DROP, Keyword::NOT, Keyword::NULL]) {
|
||||||
|
AlterColumnOperation::DropNotNull {}
|
||||||
|
} else if self.parse_keywords(&[Keyword::SET, Keyword::DEFAULT]) {
|
||||||
|
AlterColumnOperation::SetDefault {
|
||||||
|
value: self.parse_expr()?,
|
||||||
|
}
|
||||||
|
} else if self.parse_keywords(&[Keyword::DROP, Keyword::DEFAULT]) {
|
||||||
|
AlterColumnOperation::DropDefault {}
|
||||||
|
} else if self.parse_keywords(&[Keyword::SET, Keyword::DATA, Keyword::TYPE])
|
||||||
|
|| (is_postgresql && self.parse_keyword(Keyword::TYPE))
|
||||||
|
{
|
||||||
|
let data_type = self.parse_data_type()?;
|
||||||
|
let using = if is_postgresql && self.parse_keyword(Keyword::USING) {
|
||||||
|
Some(self.parse_expr()?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
AlterColumnOperation::SetDataType { data_type, using }
|
||||||
|
} else {
|
||||||
|
return self.expected(
|
||||||
|
"SET/DROP NOT NULL, SET DEFAULT, SET DATA TYPE after ALTER COLUMN",
|
||||||
|
self.peek_token(),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
AlterTableOperation::AlterColumn { column_name, op }
|
||||||
|
} else if self.parse_keyword(Keyword::SWAP) {
|
||||||
|
self.expect_keyword(Keyword::WITH)?;
|
||||||
|
let table_name = self.parse_object_name()?;
|
||||||
|
AlterTableOperation::SwapWith { table_name }
|
||||||
|
} else {
|
||||||
|
return self.expected(
|
||||||
|
"ADD, RENAME, PARTITION, SWAP or DROP after ALTER TABLE",
|
||||||
|
self.peek_token(),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
Ok(operation)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_alter(&mut self) -> Result<Statement, ParserError> {
|
pub fn parse_alter(&mut self) -> Result<Statement, ParserError> {
|
||||||
let object_type = self.expect_one_of_keywords(&[
|
let object_type = self.expect_one_of_keywords(&[
|
||||||
Keyword::VIEW,
|
Keyword::VIEW,
|
||||||
|
@ -4091,177 +4259,15 @@ impl<'a> Parser<'a> {
|
||||||
match object_type {
|
match object_type {
|
||||||
Keyword::VIEW => self.parse_alter_view(),
|
Keyword::VIEW => self.parse_alter_view(),
|
||||||
Keyword::TABLE => {
|
Keyword::TABLE => {
|
||||||
let _ = self.parse_keyword(Keyword::ONLY); // [ ONLY ]
|
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||||
|
let only = self.parse_keyword(Keyword::ONLY); // [ ONLY ]
|
||||||
let table_name = self.parse_object_name()?;
|
let table_name = self.parse_object_name()?;
|
||||||
let operation = if self.parse_keyword(Keyword::ADD) {
|
let operations = self.parse_comma_separated(Parser::parse_alter_table_operation)?;
|
||||||
if let Some(constraint) = self.parse_optional_table_constraint()? {
|
|
||||||
AlterTableOperation::AddConstraint(constraint)
|
|
||||||
} else {
|
|
||||||
let if_not_exists =
|
|
||||||
self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
|
||||||
if self.parse_keyword(Keyword::PARTITION) {
|
|
||||||
self.expect_token(&Token::LParen)?;
|
|
||||||
let partitions = self.parse_comma_separated(Parser::parse_expr)?;
|
|
||||||
self.expect_token(&Token::RParen)?;
|
|
||||||
AlterTableOperation::AddPartitions {
|
|
||||||
if_not_exists,
|
|
||||||
new_partitions: partitions,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let column_keyword = self.parse_keyword(Keyword::COLUMN);
|
|
||||||
|
|
||||||
let if_not_exists = if dialect_of!(self is PostgreSqlDialect | BigQueryDialect | DuckDbDialect | GenericDialect)
|
|
||||||
{
|
|
||||||
self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS])
|
|
||||||
|| if_not_exists
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
let column_def = self.parse_column_def()?;
|
|
||||||
AlterTableOperation::AddColumn {
|
|
||||||
column_keyword,
|
|
||||||
if_not_exists,
|
|
||||||
column_def,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if self.parse_keyword(Keyword::RENAME) {
|
|
||||||
if dialect_of!(self is PostgreSqlDialect)
|
|
||||||
&& self.parse_keyword(Keyword::CONSTRAINT)
|
|
||||||
{
|
|
||||||
let old_name = self.parse_identifier()?;
|
|
||||||
self.expect_keyword(Keyword::TO)?;
|
|
||||||
let new_name = self.parse_identifier()?;
|
|
||||||
AlterTableOperation::RenameConstraint { old_name, new_name }
|
|
||||||
} else if self.parse_keyword(Keyword::TO) {
|
|
||||||
let table_name = self.parse_object_name()?;
|
|
||||||
AlterTableOperation::RenameTable { table_name }
|
|
||||||
} else {
|
|
||||||
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
|
|
||||||
let old_column_name = self.parse_identifier()?;
|
|
||||||
self.expect_keyword(Keyword::TO)?;
|
|
||||||
let new_column_name = self.parse_identifier()?;
|
|
||||||
AlterTableOperation::RenameColumn {
|
|
||||||
old_column_name,
|
|
||||||
new_column_name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if self.parse_keyword(Keyword::DROP) {
|
|
||||||
if self.parse_keywords(&[Keyword::IF, Keyword::EXISTS, Keyword::PARTITION]) {
|
|
||||||
self.expect_token(&Token::LParen)?;
|
|
||||||
let partitions = self.parse_comma_separated(Parser::parse_expr)?;
|
|
||||||
self.expect_token(&Token::RParen)?;
|
|
||||||
AlterTableOperation::DropPartitions {
|
|
||||||
partitions,
|
|
||||||
if_exists: true,
|
|
||||||
}
|
|
||||||
} else if self.parse_keyword(Keyword::PARTITION) {
|
|
||||||
self.expect_token(&Token::LParen)?;
|
|
||||||
let partitions = self.parse_comma_separated(Parser::parse_expr)?;
|
|
||||||
self.expect_token(&Token::RParen)?;
|
|
||||||
AlterTableOperation::DropPartitions {
|
|
||||||
partitions,
|
|
||||||
if_exists: false,
|
|
||||||
}
|
|
||||||
} else if self.parse_keyword(Keyword::CONSTRAINT) {
|
|
||||||
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
|
||||||
let name = self.parse_identifier()?;
|
|
||||||
let cascade = self.parse_keyword(Keyword::CASCADE);
|
|
||||||
AlterTableOperation::DropConstraint {
|
|
||||||
if_exists,
|
|
||||||
name,
|
|
||||||
cascade,
|
|
||||||
}
|
|
||||||
} else if self.parse_keywords(&[Keyword::PRIMARY, Keyword::KEY])
|
|
||||||
&& dialect_of!(self is MySqlDialect | GenericDialect)
|
|
||||||
{
|
|
||||||
AlterTableOperation::DropPrimaryKey
|
|
||||||
} else {
|
|
||||||
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
|
|
||||||
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
|
||||||
let column_name = self.parse_identifier()?;
|
|
||||||
let cascade = self.parse_keyword(Keyword::CASCADE);
|
|
||||||
AlterTableOperation::DropColumn {
|
|
||||||
column_name,
|
|
||||||
if_exists,
|
|
||||||
cascade,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if self.parse_keyword(Keyword::PARTITION) {
|
|
||||||
self.expect_token(&Token::LParen)?;
|
|
||||||
let before = self.parse_comma_separated(Parser::parse_expr)?;
|
|
||||||
self.expect_token(&Token::RParen)?;
|
|
||||||
self.expect_keyword(Keyword::RENAME)?;
|
|
||||||
self.expect_keywords(&[Keyword::TO, Keyword::PARTITION])?;
|
|
||||||
self.expect_token(&Token::LParen)?;
|
|
||||||
let renames = self.parse_comma_separated(Parser::parse_expr)?;
|
|
||||||
self.expect_token(&Token::RParen)?;
|
|
||||||
AlterTableOperation::RenamePartitions {
|
|
||||||
old_partitions: before,
|
|
||||||
new_partitions: renames,
|
|
||||||
}
|
|
||||||
} else if self.parse_keyword(Keyword::CHANGE) {
|
|
||||||
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
|
|
||||||
let old_name = self.parse_identifier()?;
|
|
||||||
let new_name = self.parse_identifier()?;
|
|
||||||
let data_type = self.parse_data_type()?;
|
|
||||||
let mut options = vec![];
|
|
||||||
while let Some(option) = self.parse_optional_column_option()? {
|
|
||||||
options.push(option);
|
|
||||||
}
|
|
||||||
|
|
||||||
AlterTableOperation::ChangeColumn {
|
|
||||||
old_name,
|
|
||||||
new_name,
|
|
||||||
data_type,
|
|
||||||
options,
|
|
||||||
}
|
|
||||||
} else if self.parse_keyword(Keyword::ALTER) {
|
|
||||||
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
|
|
||||||
let column_name = self.parse_identifier()?;
|
|
||||||
let is_postgresql = dialect_of!(self is PostgreSqlDialect);
|
|
||||||
|
|
||||||
let op = if self.parse_keywords(&[Keyword::SET, Keyword::NOT, Keyword::NULL]) {
|
|
||||||
AlterColumnOperation::SetNotNull {}
|
|
||||||
} else if self.parse_keywords(&[Keyword::DROP, Keyword::NOT, Keyword::NULL]) {
|
|
||||||
AlterColumnOperation::DropNotNull {}
|
|
||||||
} else if self.parse_keywords(&[Keyword::SET, Keyword::DEFAULT]) {
|
|
||||||
AlterColumnOperation::SetDefault {
|
|
||||||
value: self.parse_expr()?,
|
|
||||||
}
|
|
||||||
} else if self.parse_keywords(&[Keyword::DROP, Keyword::DEFAULT]) {
|
|
||||||
AlterColumnOperation::DropDefault {}
|
|
||||||
} else if self.parse_keywords(&[Keyword::SET, Keyword::DATA, Keyword::TYPE])
|
|
||||||
|| (is_postgresql && self.parse_keyword(Keyword::TYPE))
|
|
||||||
{
|
|
||||||
let data_type = self.parse_data_type()?;
|
|
||||||
let using = if is_postgresql && self.parse_keyword(Keyword::USING) {
|
|
||||||
Some(self.parse_expr()?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
AlterColumnOperation::SetDataType { data_type, using }
|
|
||||||
} else {
|
|
||||||
return self.expected(
|
|
||||||
"SET/DROP NOT NULL, SET DEFAULT, SET DATA TYPE after ALTER COLUMN",
|
|
||||||
self.peek_token(),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
AlterTableOperation::AlterColumn { column_name, op }
|
|
||||||
} else if self.parse_keyword(Keyword::SWAP) {
|
|
||||||
self.expect_keyword(Keyword::WITH)?;
|
|
||||||
let table_name = self.parse_object_name()?;
|
|
||||||
AlterTableOperation::SwapWith { table_name }
|
|
||||||
} else {
|
|
||||||
return self.expected(
|
|
||||||
"ADD, RENAME, PARTITION, SWAP or DROP after ALTER TABLE",
|
|
||||||
self.peek_token(),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
Ok(Statement::AlterTable {
|
Ok(Statement::AlterTable {
|
||||||
name: table_name,
|
name: table_name,
|
||||||
operation,
|
if_exists,
|
||||||
|
only,
|
||||||
|
operations,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Keyword::INDEX => {
|
Keyword::INDEX => {
|
||||||
|
|
|
@ -209,6 +209,26 @@ pub fn expr_from_projection(item: &SelectItem) -> &Expr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn alter_table_op_with_name(stmt: Statement, expected_name: &str) -> AlterTableOperation {
|
||||||
|
match stmt {
|
||||||
|
Statement::AlterTable {
|
||||||
|
name,
|
||||||
|
if_exists,
|
||||||
|
only: is_only,
|
||||||
|
operations,
|
||||||
|
} => {
|
||||||
|
assert_eq!(name.to_string(), expected_name);
|
||||||
|
assert!(!if_exists);
|
||||||
|
assert!(!is_only);
|
||||||
|
only(operations)
|
||||||
|
}
|
||||||
|
_ => panic!("Expected ALTER TABLE statement"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn alter_table_op(stmt: Statement) -> AlterTableOperation {
|
||||||
|
alter_table_op_with_name(stmt, "tab")
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a `Value::Number`, panic'ing if n is not a number
|
/// Creates a `Value::Number`, panic'ing if n is not a number
|
||||||
pub fn number(n: &str) -> Value {
|
pub fn number(n: &str) -> Value {
|
||||||
Value::Number(n.parse().unwrap(), false)
|
Value::Number(n.parse().unwrap(), false)
|
||||||
|
|
|
@ -30,8 +30,8 @@ use sqlparser::dialect::{
|
||||||
use sqlparser::keywords::ALL_KEYWORDS;
|
use sqlparser::keywords::ALL_KEYWORDS;
|
||||||
use sqlparser::parser::{Parser, ParserError, ParserOptions};
|
use sqlparser::parser::{Parser, ParserError, ParserOptions};
|
||||||
use test_utils::{
|
use test_utils::{
|
||||||
all_dialects, assert_eq_vec, expr_from_projection, join, number, only, table, table_alias,
|
all_dialects, alter_table_op, assert_eq_vec, expr_from_projection, join, number, only, table,
|
||||||
TestedDialects,
|
table_alias, TestedDialects,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -2920,19 +2920,17 @@ fn parse_create_external_table_lowercase() {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_alter_table() {
|
fn parse_alter_table() {
|
||||||
let add_column = "ALTER TABLE tab ADD COLUMN foo TEXT;";
|
let add_column = "ALTER TABLE tab ADD COLUMN foo TEXT;";
|
||||||
match one_statement_parses_to(add_column, "ALTER TABLE tab ADD COLUMN foo TEXT") {
|
match alter_table_op(one_statement_parses_to(
|
||||||
Statement::AlterTable {
|
add_column,
|
||||||
name,
|
"ALTER TABLE tab ADD COLUMN foo TEXT",
|
||||||
operation:
|
)) {
|
||||||
AlterTableOperation::AddColumn {
|
AlterTableOperation::AddColumn {
|
||||||
column_keyword,
|
column_keyword,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
column_def,
|
column_def,
|
||||||
},
|
|
||||||
} => {
|
} => {
|
||||||
assert!(column_keyword);
|
assert!(column_keyword);
|
||||||
assert!(!if_not_exists);
|
assert!(!if_not_exists);
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!("foo", column_def.name.to_string());
|
assert_eq!("foo", column_def.name.to_string());
|
||||||
assert_eq!("TEXT", column_def.data_type.to_string());
|
assert_eq!("TEXT", column_def.data_type.to_string());
|
||||||
}
|
}
|
||||||
|
@ -2940,28 +2938,19 @@ fn parse_alter_table() {
|
||||||
};
|
};
|
||||||
|
|
||||||
let rename_table = "ALTER TABLE tab RENAME TO new_tab";
|
let rename_table = "ALTER TABLE tab RENAME TO new_tab";
|
||||||
match verified_stmt(rename_table) {
|
match alter_table_op(verified_stmt(rename_table)) {
|
||||||
Statement::AlterTable {
|
AlterTableOperation::RenameTable { table_name } => {
|
||||||
name,
|
assert_eq!("new_tab", table_name.to_string());
|
||||||
operation: AlterTableOperation::RenameTable { table_name },
|
|
||||||
} => {
|
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!("new_tab", table_name.to_string())
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let rename_column = "ALTER TABLE tab RENAME COLUMN foo TO new_foo";
|
let rename_column = "ALTER TABLE tab RENAME COLUMN foo TO new_foo";
|
||||||
match verified_stmt(rename_column) {
|
match alter_table_op(verified_stmt(rename_column)) {
|
||||||
Statement::AlterTable {
|
AlterTableOperation::RenameColumn {
|
||||||
name,
|
old_column_name,
|
||||||
operation:
|
new_column_name,
|
||||||
AlterTableOperation::RenameColumn {
|
|
||||||
old_column_name,
|
|
||||||
new_column_name,
|
|
||||||
},
|
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!(old_column_name.to_string(), "foo");
|
assert_eq!(old_column_name.to_string(), "foo");
|
||||||
assert_eq!(new_column_name.to_string(), "new_foo");
|
assert_eq!(new_column_name.to_string(), "new_foo");
|
||||||
}
|
}
|
||||||
|
@ -3047,21 +3036,15 @@ fn parse_alter_view_with_columns() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_alter_table_add_column() {
|
fn parse_alter_table_add_column() {
|
||||||
match verified_stmt("ALTER TABLE tab ADD foo TEXT") {
|
match alter_table_op(verified_stmt("ALTER TABLE tab ADD foo TEXT")) {
|
||||||
Statement::AlterTable {
|
AlterTableOperation::AddColumn { column_keyword, .. } => {
|
||||||
operation: AlterTableOperation::AddColumn { column_keyword, .. },
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
assert!(!column_keyword);
|
assert!(!column_keyword);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match verified_stmt("ALTER TABLE tab ADD COLUMN foo TEXT") {
|
match alter_table_op(verified_stmt("ALTER TABLE tab ADD COLUMN foo TEXT")) {
|
||||||
Statement::AlterTable {
|
AlterTableOperation::AddColumn { column_keyword, .. } => {
|
||||||
operation: AlterTableOperation::AddColumn { column_keyword, .. },
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
assert!(column_keyword);
|
assert!(column_keyword);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -3080,24 +3063,19 @@ fn parse_alter_table_add_column_if_not_exists() {
|
||||||
options: None,
|
options: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
match dialects.verified_stmt("ALTER TABLE tab ADD IF NOT EXISTS foo TEXT") {
|
match alter_table_op(dialects.verified_stmt("ALTER TABLE tab ADD IF NOT EXISTS foo TEXT")) {
|
||||||
Statement::AlterTable {
|
AlterTableOperation::AddColumn { if_not_exists, .. } => {
|
||||||
operation: AlterTableOperation::AddColumn { if_not_exists, .. },
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
assert!(if_not_exists);
|
assert!(if_not_exists);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match dialects.verified_stmt("ALTER TABLE tab ADD COLUMN IF NOT EXISTS foo TEXT") {
|
match alter_table_op(
|
||||||
Statement::AlterTable {
|
dialects.verified_stmt("ALTER TABLE tab ADD COLUMN IF NOT EXISTS foo TEXT"),
|
||||||
operation:
|
) {
|
||||||
AlterTableOperation::AddColumn {
|
AlterTableOperation::AddColumn {
|
||||||
column_keyword,
|
column_keyword,
|
||||||
if_not_exists,
|
if_not_exists,
|
||||||
..
|
|
||||||
},
|
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
assert!(column_keyword);
|
assert!(column_keyword);
|
||||||
|
@ -3123,12 +3101,10 @@ fn parse_alter_table_constraints() {
|
||||||
check_one("CHECK (end_date > start_date OR end_date IS NULL)");
|
check_one("CHECK (end_date > start_date OR end_date IS NULL)");
|
||||||
|
|
||||||
fn check_one(constraint_text: &str) {
|
fn check_one(constraint_text: &str) {
|
||||||
match verified_stmt(&format!("ALTER TABLE tab ADD {constraint_text}")) {
|
match alter_table_op(verified_stmt(&format!(
|
||||||
Statement::AlterTable {
|
"ALTER TABLE tab ADD {constraint_text}"
|
||||||
name,
|
))) {
|
||||||
operation: AlterTableOperation::AddConstraint(constraint),
|
AlterTableOperation::AddConstraint(constraint) => {
|
||||||
} => {
|
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!(constraint_text, constraint.to_string());
|
assert_eq!(constraint_text, constraint.to_string());
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -3150,17 +3126,12 @@ fn parse_alter_table_drop_column() {
|
||||||
);
|
);
|
||||||
|
|
||||||
fn check_one(constraint_text: &str) {
|
fn check_one(constraint_text: &str) {
|
||||||
match verified_stmt(&format!("ALTER TABLE tab {constraint_text}")) {
|
match alter_table_op(verified_stmt(&format!("ALTER TABLE tab {constraint_text}"))) {
|
||||||
Statement::AlterTable {
|
AlterTableOperation::DropColumn {
|
||||||
name,
|
column_name,
|
||||||
operation:
|
if_exists,
|
||||||
AlterTableOperation::DropColumn {
|
cascade,
|
||||||
column_name,
|
|
||||||
if_exists,
|
|
||||||
cascade,
|
|
||||||
},
|
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!("is_active", column_name.to_string());
|
assert_eq!("is_active", column_name.to_string());
|
||||||
assert!(if_exists);
|
assert!(if_exists);
|
||||||
assert!(cascade);
|
assert!(cascade);
|
||||||
|
@ -3173,12 +3144,10 @@ fn parse_alter_table_drop_column() {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_alter_table_alter_column() {
|
fn parse_alter_table_alter_column() {
|
||||||
let alter_stmt = "ALTER TABLE tab";
|
let alter_stmt = "ALTER TABLE tab";
|
||||||
match verified_stmt(&format!("{alter_stmt} ALTER COLUMN is_active SET NOT NULL")) {
|
match alter_table_op(verified_stmt(&format!(
|
||||||
Statement::AlterTable {
|
"{alter_stmt} ALTER COLUMN is_active SET NOT NULL"
|
||||||
name,
|
))) {
|
||||||
operation: AlterTableOperation::AlterColumn { column_name, op },
|
AlterTableOperation::AlterColumn { column_name, op } => {
|
||||||
} => {
|
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!("is_active", column_name.to_string());
|
assert_eq!("is_active", column_name.to_string());
|
||||||
assert_eq!(op, AlterColumnOperation::SetNotNull {});
|
assert_eq!(op, AlterColumnOperation::SetNotNull {});
|
||||||
}
|
}
|
||||||
|
@ -3190,14 +3159,10 @@ fn parse_alter_table_alter_column() {
|
||||||
"ALTER TABLE tab ALTER COLUMN is_active DROP NOT NULL",
|
"ALTER TABLE tab ALTER COLUMN is_active DROP NOT NULL",
|
||||||
);
|
);
|
||||||
|
|
||||||
match verified_stmt(&format!(
|
match alter_table_op(verified_stmt(&format!(
|
||||||
"{alter_stmt} ALTER COLUMN is_active SET DEFAULT false"
|
"{alter_stmt} ALTER COLUMN is_active SET DEFAULT false"
|
||||||
)) {
|
))) {
|
||||||
Statement::AlterTable {
|
AlterTableOperation::AlterColumn { column_name, op } => {
|
||||||
name,
|
|
||||||
operation: AlterTableOperation::AlterColumn { column_name, op },
|
|
||||||
} => {
|
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!("is_active", column_name.to_string());
|
assert_eq!("is_active", column_name.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
op,
|
op,
|
||||||
|
@ -3209,12 +3174,10 @@ fn parse_alter_table_alter_column() {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
match verified_stmt(&format!("{alter_stmt} ALTER COLUMN is_active DROP DEFAULT")) {
|
match alter_table_op(verified_stmt(&format!(
|
||||||
Statement::AlterTable {
|
"{alter_stmt} ALTER COLUMN is_active DROP DEFAULT"
|
||||||
name,
|
))) {
|
||||||
operation: AlterTableOperation::AlterColumn { column_name, op },
|
AlterTableOperation::AlterColumn { column_name, op } => {
|
||||||
} => {
|
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!("is_active", column_name.to_string());
|
assert_eq!("is_active", column_name.to_string());
|
||||||
assert_eq!(op, AlterColumnOperation::DropDefault {});
|
assert_eq!(op, AlterColumnOperation::DropDefault {});
|
||||||
}
|
}
|
||||||
|
@ -3225,12 +3188,10 @@ fn parse_alter_table_alter_column() {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_alter_table_alter_column_type() {
|
fn parse_alter_table_alter_column_type() {
|
||||||
let alter_stmt = "ALTER TABLE tab";
|
let alter_stmt = "ALTER TABLE tab";
|
||||||
match verified_stmt("ALTER TABLE tab ALTER COLUMN is_active SET DATA TYPE TEXT") {
|
match alter_table_op(verified_stmt(
|
||||||
Statement::AlterTable {
|
"ALTER TABLE tab ALTER COLUMN is_active SET DATA TYPE TEXT",
|
||||||
name,
|
)) {
|
||||||
operation: AlterTableOperation::AlterColumn { column_name, op },
|
AlterTableOperation::AlterColumn { column_name, op } => {
|
||||||
} => {
|
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!("is_active", column_name.to_string());
|
assert_eq!("is_active", column_name.to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
op,
|
op,
|
||||||
|
@ -3267,34 +3228,28 @@ fn parse_alter_table_alter_column_type() {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_alter_table_drop_constraint() {
|
fn parse_alter_table_drop_constraint() {
|
||||||
let alter_stmt = "ALTER TABLE tab";
|
let alter_stmt = "ALTER TABLE tab";
|
||||||
match verified_stmt("ALTER TABLE tab DROP CONSTRAINT constraint_name CASCADE") {
|
match alter_table_op(verified_stmt(
|
||||||
Statement::AlterTable {
|
"ALTER TABLE tab DROP CONSTRAINT constraint_name CASCADE",
|
||||||
name,
|
)) {
|
||||||
operation:
|
AlterTableOperation::DropConstraint {
|
||||||
AlterTableOperation::DropConstraint {
|
name: constr_name,
|
||||||
name: constr_name,
|
if_exists,
|
||||||
if_exists,
|
cascade,
|
||||||
cascade,
|
|
||||||
},
|
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!("constraint_name", constr_name.to_string());
|
assert_eq!("constraint_name", constr_name.to_string());
|
||||||
assert!(!if_exists);
|
assert!(!if_exists);
|
||||||
assert!(cascade);
|
assert!(cascade);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
match verified_stmt("ALTER TABLE tab DROP CONSTRAINT IF EXISTS constraint_name") {
|
match alter_table_op(verified_stmt(
|
||||||
Statement::AlterTable {
|
"ALTER TABLE tab DROP CONSTRAINT IF EXISTS constraint_name",
|
||||||
name,
|
)) {
|
||||||
operation:
|
AlterTableOperation::DropConstraint {
|
||||||
AlterTableOperation::DropConstraint {
|
name: constr_name,
|
||||||
name: constr_name,
|
if_exists,
|
||||||
if_exists,
|
cascade,
|
||||||
cascade,
|
|
||||||
},
|
|
||||||
} => {
|
} => {
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!("constraint_name", constr_name.to_string());
|
assert_eq!("constraint_name", constr_name.to_string());
|
||||||
assert!(if_exists);
|
assert!(if_exists);
|
||||||
assert!(!cascade);
|
assert!(!cascade);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
//! Test SQL syntax specific to MySQL. The parser based on the generic dialect
|
//! Test SQL syntax specific to MySQL. The parser based on the generic dialect
|
||||||
//! is also tested (on the inputs it can handle).
|
//! is also tested (on the inputs it can handle).
|
||||||
|
|
||||||
|
use matches::assert_matches;
|
||||||
use sqlparser::ast::Expr;
|
use sqlparser::ast::Expr;
|
||||||
use sqlparser::ast::Value;
|
use sqlparser::ast::Value;
|
||||||
use sqlparser::ast::*;
|
use sqlparser::ast::*;
|
||||||
|
@ -1256,15 +1257,10 @@ fn parse_update_with_joins() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_alter_table_drop_primary_key() {
|
fn parse_alter_table_drop_primary_key() {
|
||||||
match mysql_and_generic().verified_stmt("ALTER TABLE tab DROP PRIMARY KEY") {
|
assert_matches!(
|
||||||
Statement::AlterTable {
|
alter_table_op(mysql_and_generic().verified_stmt("ALTER TABLE tab DROP PRIMARY KEY")),
|
||||||
name,
|
AlterTableOperation::DropPrimaryKey
|
||||||
operation: AlterTableOperation::DropPrimaryKey,
|
);
|
||||||
} => {
|
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1278,22 +1274,16 @@ fn parse_alter_table_change_column() {
|
||||||
};
|
};
|
||||||
|
|
||||||
let sql1 = "ALTER TABLE orders CHANGE COLUMN description desc TEXT NOT NULL";
|
let sql1 = "ALTER TABLE orders CHANGE COLUMN description desc TEXT NOT NULL";
|
||||||
match mysql().verified_stmt(sql1) {
|
let operation =
|
||||||
Statement::AlterTable { name, operation } => {
|
alter_table_op_with_name(mysql().verified_stmt(sql1), &expected_name.to_string());
|
||||||
assert_eq!(expected_name, name);
|
assert_eq!(expected_operation, operation);
|
||||||
assert_eq!(expected_operation, operation);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
let sql2 = "ALTER TABLE orders CHANGE description desc TEXT NOT NULL";
|
let sql2 = "ALTER TABLE orders CHANGE description desc TEXT NOT NULL";
|
||||||
match mysql().one_statement_parses_to(sql2, sql1) {
|
let operation = alter_table_op_with_name(
|
||||||
Statement::AlterTable { name, operation } => {
|
mysql().one_statement_parses_to(sql2, sql1),
|
||||||
assert_eq!(expected_name, name);
|
&expected_name.to_string(),
|
||||||
assert_eq!(expected_operation, operation);
|
);
|
||||||
}
|
assert_eq!(expected_operation, operation);
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -546,12 +546,10 @@ fn parse_create_table_constraints_only() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_alter_table_constraints_rename() {
|
fn parse_alter_table_constraints_rename() {
|
||||||
match pg().verified_stmt("ALTER TABLE tab RENAME CONSTRAINT old_name TO new_name") {
|
match alter_table_op(
|
||||||
Statement::AlterTable {
|
pg().verified_stmt("ALTER TABLE tab RENAME CONSTRAINT old_name TO new_name"),
|
||||||
name,
|
) {
|
||||||
operation: AlterTableOperation::RenameConstraint { old_name, new_name },
|
AlterTableOperation::RenameConstraint { old_name, new_name } => {
|
||||||
} => {
|
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!(old_name.to_string(), "old_name");
|
assert_eq!(old_name.to_string(), "old_name");
|
||||||
assert_eq!(new_name.to_string(), "new_name");
|
assert_eq!(new_name.to_string(), "new_name");
|
||||||
}
|
}
|
||||||
|
@ -566,14 +564,12 @@ fn parse_alter_table_alter_column() {
|
||||||
"ALTER TABLE tab ALTER COLUMN is_active SET DATA TYPE TEXT USING 'text'",
|
"ALTER TABLE tab ALTER COLUMN is_active SET DATA TYPE TEXT USING 'text'",
|
||||||
);
|
);
|
||||||
|
|
||||||
match pg()
|
match alter_table_op(
|
||||||
.verified_stmt("ALTER TABLE tab ALTER COLUMN is_active SET DATA TYPE TEXT USING 'text'")
|
pg().verified_stmt(
|
||||||
{
|
"ALTER TABLE tab ALTER COLUMN is_active SET DATA TYPE TEXT USING 'text'",
|
||||||
Statement::AlterTable {
|
),
|
||||||
name,
|
) {
|
||||||
operation: AlterTableOperation::AlterColumn { column_name, op },
|
AlterTableOperation::AlterColumn { column_name, op } => {
|
||||||
} => {
|
|
||||||
assert_eq!("tab", name.to_string());
|
|
||||||
assert_eq!("is_active", column_name.to_string());
|
assert_eq!("is_active", column_name.to_string());
|
||||||
let using_expr = Expr::Value(Value::SingleQuotedString("text".to_string()));
|
let using_expr = Expr::Value(Value::SingleQuotedString("text".to_string()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -588,6 +584,48 @@ fn parse_alter_table_alter_column() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_alter_table_add_columns() {
|
||||||
|
match pg().verified_stmt("ALTER TABLE IF EXISTS ONLY tab ADD COLUMN a TEXT, ADD COLUMN b INT") {
|
||||||
|
Statement::AlterTable {
|
||||||
|
name,
|
||||||
|
if_exists,
|
||||||
|
only,
|
||||||
|
operations,
|
||||||
|
} => {
|
||||||
|
assert_eq!(name.to_string(), "tab");
|
||||||
|
assert!(if_exists);
|
||||||
|
assert!(only);
|
||||||
|
assert_eq!(
|
||||||
|
operations,
|
||||||
|
vec![
|
||||||
|
AlterTableOperation::AddColumn {
|
||||||
|
column_keyword: true,
|
||||||
|
if_not_exists: false,
|
||||||
|
column_def: ColumnDef {
|
||||||
|
name: "a".into(),
|
||||||
|
data_type: DataType::Text,
|
||||||
|
collation: None,
|
||||||
|
options: vec![],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
AlterTableOperation::AddColumn {
|
||||||
|
column_keyword: true,
|
||||||
|
if_not_exists: false,
|
||||||
|
column_def: ColumnDef {
|
||||||
|
name: "b".into(),
|
||||||
|
data_type: DataType::Int(None),
|
||||||
|
collation: None,
|
||||||
|
options: vec![],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_create_table_if_not_exists() {
|
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 ()";
|
||||||
|
|
|
@ -502,12 +502,8 @@ fn test_select_wildcard_with_exclude_and_rename() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_alter_table_swap_with() {
|
fn test_alter_table_swap_with() {
|
||||||
let sql = "ALTER TABLE tab1 SWAP WITH tab2";
|
let sql = "ALTER TABLE tab1 SWAP WITH tab2";
|
||||||
match snowflake_and_generic().verified_stmt(sql) {
|
match alter_table_op_with_name(snowflake_and_generic().verified_stmt(sql), "tab1") {
|
||||||
Statement::AlterTable {
|
AlterTableOperation::SwapWith { table_name } => {
|
||||||
name,
|
|
||||||
operation: AlterTableOperation::SwapWith { table_name },
|
|
||||||
} => {
|
|
||||||
assert_eq!("tab1", name.to_string());
|
|
||||||
assert_eq!("tab2", table_name.to_string());
|
assert_eq!("tab2", table_name.to_string());
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue