This is an automated email from the ASF dual-hosted git repository.

iffyio pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new 3adc746b Parse MySQL ALTER TABLE ALGORITHM option (#1745)
3adc746b is described below

commit 3adc746b11411746f78f5c2506e1bf72e1caf583
Author: Michael Victor Zink <[email protected]>
AuthorDate: Tue Feb 25 22:03:38 2025 -0800

    Parse MySQL ALTER TABLE ALGORITHM option (#1745)
---
 src/ast/ddl.rs           | 45 +++++++++++++++++++++++++++++++++++++++++----
 src/ast/mod.rs           | 18 +++++++++---------
 src/ast/spans.rs         |  1 +
 src/keywords.rs          |  2 ++
 src/parser/mod.rs        | 18 ++++++++++++++++++
 tests/sqlparser_mysql.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 119 insertions(+), 13 deletions(-)

diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs
index 1fbc4560..372a75ad 100644
--- a/src/ast/ddl.rs
+++ b/src/ast/ddl.rs
@@ -65,7 +65,6 @@ pub enum AlterTableOperation {
         name: Ident,
         select: ProjectionSelect,
     },
-
     /// `DROP PROJECTION [IF EXISTS] name`
     ///
     /// Note: this is a ClickHouse-specific operation.
@@ -74,7 +73,6 @@ pub enum AlterTableOperation {
         if_exists: bool,
         name: Ident,
     },
-
     /// `MATERIALIZE PROJECTION [IF EXISTS] name [IN PARTITION partition_name]`
     ///
     ///  Note: this is a ClickHouse-specific operation.
@@ -84,7 +82,6 @@ pub enum AlterTableOperation {
         name: Ident,
         partition: Option<Ident>,
     },
-
     /// `CLEAR PROJECTION [IF EXISTS] name [IN PARTITION partition_name]`
     ///
     /// Note: this is a ClickHouse-specific operation.
@@ -94,7 +91,6 @@ pub enum AlterTableOperation {
         name: Ident,
         partition: Option<Ident>,
     },
-
     /// `DISABLE ROW LEVEL SECURITY`
     ///
     /// Note: this is a PostgreSQL-specific operation.
@@ -272,6 +268,15 @@ pub enum AlterTableOperation {
     DropClusteringKey,
     SuspendRecluster,
     ResumeRecluster,
+    /// `ALGORITHM [=] { DEFAULT | INSTANT | INPLACE | COPY }`
+    ///
+    /// [MySQL]-specific table alter algorithm.
+    ///
+    /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
+    Algorithm {
+        equals: bool,
+        algorithm: AlterTableAlgorithm,
+    },
 }
 
 /// An `ALTER Policy` (`Statement::AlterPolicy`) operation
@@ -317,6 +322,30 @@ impl fmt::Display for AlterPolicyOperation {
     }
 }
 
+/// [MySQL] `ALTER TABLE` algorithm.
+///
+/// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum AlterTableAlgorithm {
+    Default,
+    Instant,
+    Inplace,
+    Copy,
+}
+
+impl fmt::Display for AlterTableAlgorithm {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str(match self {
+            Self::Default => "DEFAULT",
+            Self::Instant => "INSTANT",
+            Self::Inplace => "INPLACE",
+            Self::Copy => "COPY",
+        })
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
@@ -407,6 +436,14 @@ impl fmt::Display for AlterTableOperation {
                 }
                 write!(f, " {} ({})", name, query)
             }
+            AlterTableOperation::Algorithm { equals, algorithm } => {
+                write!(
+                    f,
+                    "ALGORITHM {}{}",
+                    if *equals { "= " } else { "" },
+                    algorithm
+                )
+            }
             AlterTableOperation::DropProjection { if_exists, name } => {
                 write!(f, "DROP PROJECTION")?;
                 if *if_exists {
diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index 85d3ed91..72be3ff6 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -48,15 +48,15 @@ pub use self::dcl::{
 };
 pub use self::ddl::{
     AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, 
AlterPolicyOperation,
-    AlterTableOperation, AlterType, AlterTypeAddValue, 
AlterTypeAddValuePosition,
-    AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, 
ColumnDef,
-    ColumnOption, ColumnOptionDef, ColumnPolicy, ColumnPolicyProperty, 
ConstraintCharacteristics,
-    CreateConnector, CreateFunction, Deduplicate, DeferrableInitial, 
DropBehavior, GeneratedAs,
-    GeneratedExpressionMode, IdentityParameters, IdentityProperty, 
IdentityPropertyFormatKind,
-    IdentityPropertyKind, IdentityPropertyOrder, IndexOption, IndexType, 
KeyOrIndexDisplay,
-    NullsDistinctOption, Owner, Partition, ProcedureParam, ReferentialAction, 
TableConstraint,
-    TagsColumnOption, UserDefinedTypeCompositeAttributeDef, 
UserDefinedTypeRepresentation,
-    ViewColumnDef,
+    AlterTableAlgorithm, AlterTableOperation, AlterType, AlterTypeAddValue,
+    AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, 
AlterTypeRenameValue,
+    ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnPolicy, 
ColumnPolicyProperty,
+    ConstraintCharacteristics, CreateConnector, CreateFunction, Deduplicate, 
DeferrableInitial,
+    DropBehavior, GeneratedAs, GeneratedExpressionMode, IdentityParameters, 
IdentityProperty,
+    IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, 
IndexOption,
+    IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition, 
ProcedureParam,
+    ReferentialAction, TableConstraint, TagsColumnOption, 
UserDefinedTypeCompositeAttributeDef,
+    UserDefinedTypeRepresentation, ViewColumnDef,
 };
 pub use self::dml::{CreateIndex, CreateTable, Delete, Insert};
 pub use self::operator::{BinaryOperator, UnaryOperator};
diff --git a/src/ast/spans.rs b/src/ast/spans.rs
index cfc3eb63..7cb5ddfe 100644
--- a/src/ast/spans.rs
+++ b/src/ast/spans.rs
@@ -1062,6 +1062,7 @@ impl Spanned for AlterTableOperation {
             AlterTableOperation::DropClusteringKey => Span::empty(),
             AlterTableOperation::SuspendRecluster => Span::empty(),
             AlterTableOperation::ResumeRecluster => Span::empty(),
+            AlterTableOperation::Algorithm { .. } => Span::empty(),
         }
     }
 }
diff --git a/src/keywords.rs b/src/keywords.rs
index 020b404e..a6854f07 100644
--- a/src/keywords.rs
+++ b/src/keywords.rs
@@ -427,11 +427,13 @@ define_keywords!(
     INNER,
     INOUT,
     INPATH,
+    INPLACE,
     INPUT,
     INPUTFORMAT,
     INSENSITIVE,
     INSERT,
     INSTALL,
+    INSTANT,
     INSTEAD,
     INT,
     INT128,
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index ddcb6055..86a86824 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -8163,6 +8163,24 @@ impl<'a> Parser<'a> {
             AlterTableOperation::SuspendRecluster
         } else if self.parse_keywords(&[Keyword::RESUME, Keyword::RECLUSTER]) {
             AlterTableOperation::ResumeRecluster
+        } else if self.parse_keyword(Keyword::ALGORITHM) {
+            let equals = self.consume_token(&Token::Eq);
+            let algorithm = match self.parse_one_of_keywords(&[
+                Keyword::DEFAULT,
+                Keyword::INSTANT,
+                Keyword::INPLACE,
+                Keyword::COPY,
+            ]) {
+                Some(Keyword::DEFAULT) => AlterTableAlgorithm::Default,
+                Some(Keyword::INSTANT) => AlterTableAlgorithm::Instant,
+                Some(Keyword::INPLACE) => AlterTableAlgorithm::Inplace,
+                Some(Keyword::COPY) => AlterTableAlgorithm::Copy,
+                _ => self.expected(
+                    "DEFAULT, INSTANT, INPLACE, or COPY after ALGORITHM [=]",
+                    self.peek_token(),
+                )?,
+            };
+            AlterTableOperation::Algorithm { equals, algorithm }
         } else {
             let options: Vec<SqlOption> =
                 self.parse_options_with_keywords(&[Keyword::SET, 
Keyword::TBLPROPERTIES])?;
diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs
index 4856bd89..5e98d3f4 100644
--- a/tests/sqlparser_mysql.rs
+++ b/tests/sqlparser_mysql.rs
@@ -2422,6 +2422,54 @@ fn parse_alter_table_modify_column() {
     assert_eq!(expected_operation, operation);
 }
 
+#[test]
+fn parse_alter_table_with_algorithm() {
+    let sql = "ALTER TABLE tab ALGORITHM = COPY";
+    let expected_operation = AlterTableOperation::Algorithm {
+        equals: true,
+        algorithm: AlterTableAlgorithm::Copy,
+    };
+    let operation = alter_table_op(mysql_and_generic().verified_stmt(sql));
+    assert_eq!(expected_operation, operation);
+
+    //  Check order doesn't matter
+    let sql =
+        "ALTER TABLE users DROP COLUMN password_digest, ALGORITHM = COPY, 
RENAME COLUMN name TO username";
+    let stmt = mysql_and_generic().verified_stmt(sql);
+    match stmt {
+        Statement::AlterTable { operations, .. } => {
+            assert_eq!(
+                operations,
+                vec![
+                    AlterTableOperation::DropColumn {
+                        column_name: Ident::new("password_digest"),
+                        if_exists: false,
+                        drop_behavior: None,
+                    },
+                    AlterTableOperation::Algorithm {
+                        equals: true,
+                        algorithm: AlterTableAlgorithm::Copy,
+                    },
+                    AlterTableOperation::RenameColumn {
+                        old_column_name: Ident::new("name"),
+                        new_column_name: Ident::new("username")
+                    },
+                ]
+            )
+        }
+        _ => panic!("Unexpected statement {stmt}"),
+    }
+
+    mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM DEFAULT");
+    mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM INSTANT");
+    mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM INPLACE");
+    mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM COPY");
+    mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM = 
DEFAULT");
+    mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM = 
INSTANT");
+    mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM = 
INPLACE");
+    mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM = COPY");
+}
+
 #[test]
 fn parse_alter_table_modify_column_with_column_position() {
     let expected_name = ObjectName::from(vec![Ident::new("orders")]);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to