iffyio commented on code in PR #1727:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1727#discussion_r1957667202


##########
tests/sqlparser_postgres.rs:
##########
@@ -5320,6 +5320,117 @@ fn parse_create_type_as_enum() {
     }
 }
 
+#[test]
+fn parse_alter_type() {
+    struct TestCase {
+        sql: &'static str,
+        canonical: &'static str,
+        name: &'static str,
+        operation: AlterTypeOperation,
+    }
+    vec![
+        TestCase {
+            sql: r#"ALTER TYPE public.my_type
+                        RENAME TO my_new_type"#,
+            canonical: "ALTER TYPE public.my_type RENAME TO my_new_type",
+            name: "public.my_type",
+            operation: AlterTypeOperation::Rename {
+                new_name: Ident::new("my_new_type"),
+            },
+        },
+        TestCase {
+            sql: r#"ALTER TYPE public.my_type
+                        ADD VALUE IF NOT EXISTS 'label3.5'
+                        BEFORE 'label4'"#,
+            canonical:
+                "ALTER TYPE public.my_type ADD VALUE IF NOT EXISTS 'label3.5' 
BEFORE 'label4'",
+            name: "public.my_type",
+            operation: AlterTypeOperation::AddValue {
+                if_not_exists: true,
+                value: Ident::with_quote('\'', "label3.5"),
+                position: 
AlterTypeOperationAddValuePosition::Before(Ident::with_quote(
+                    '\'', "label4",
+                )),
+            },
+        },
+        TestCase {
+            sql: r#"ALTER TYPE public.my_type
+                        ADD VALUE 'label3.5' BEFORE 'label4'"#,
+            canonical: "ALTER TYPE public.my_type ADD VALUE 'label3.5' BEFORE 
'label4'",
+            name: "public.my_type",
+            operation: AlterTypeOperation::AddValue {
+                if_not_exists: false,
+                value: Ident::with_quote('\'', "label3.5"),
+                position: 
AlterTypeOperationAddValuePosition::Before(Ident::with_quote(
+                    '\'', "label4",
+                )),
+            },
+        },
+        TestCase {
+            sql: r#"ALTER TYPE public.my_type
+                        ADD VALUE IF NOT EXISTS 'label3.5'
+                        AFTER 'label3'"#,
+            canonical:
+                "ALTER TYPE public.my_type ADD VALUE IF NOT EXISTS 'label3.5' 
AFTER 'label3'",
+            name: "public.my_type",
+            operation: AlterTypeOperation::AddValue {
+                if_not_exists: true,
+                value: Ident::with_quote('\'', "label3.5"),
+                position: 
AlterTypeOperationAddValuePosition::After(Ident::with_quote(
+                    '\'', "label3",
+                )),
+            },
+        },
+        TestCase {
+            sql: r#"ALTER TYPE public.my_type
+                        ADD VALUE 'label3.5'
+                        AFTER 'label3'"#,
+            canonical: "ALTER TYPE public.my_type ADD VALUE 'label3.5' AFTER 
'label3'",
+            name: "public.my_type",
+            operation: AlterTypeOperation::AddValue {
+                if_not_exists: false,
+                value: Ident::with_quote('\'', "label3.5"),
+                position: 
AlterTypeOperationAddValuePosition::After(Ident::with_quote(
+                    '\'', "label3",
+                )),
+            },
+        },
+        TestCase {
+            sql: r#"ALTER TYPE public.my_type
+                        ADD VALUE IF NOT EXISTS 'label5'"#,
+            canonical: "ALTER TYPE public.my_type ADD VALUE IF NOT EXISTS 
'label5'",
+            name: "public.my_type",
+            operation: AlterTypeOperation::AddValue {
+                if_not_exists: true,
+                value: Ident::with_quote('\'', "label5"),
+                position: AlterTypeOperationAddValuePosition::Default,
+            },
+        },
+        TestCase {
+            sql: r#"ALTER TYPE public.my_type
+                        ADD VALUE 'label5'"#,
+            canonical: "ALTER TYPE public.my_type ADD VALUE 'label5'",
+            name: "public.my_type",
+            operation: AlterTypeOperation::AddValue {
+                if_not_exists: false,
+                value: Ident::with_quote('\'', "label5"),
+                position: AlterTypeOperationAddValuePosition::Default,
+            },
+        },
+    ]
+    .into_iter()
+    .enumerate()
+    .for_each(|(index, tc)| {
+        let statement = pg_and_generic().one_statement_parses_to(tc.sql, 
tc.canonical);

Review Comment:
   ```suggestion
           let statement = pg_and_generic().verified_stmt(tc.sql);
   ```
   can we use verified_stmt instead?



##########
src/parser/mod.rs:
##########
@@ -14258,6 +14316,21 @@ impl<'a> Parser<'a> {
         })
     }
 
+    // See 
[PostgreSQL](https://www.postgresql.org/docs/current/sql-createtype.html)

Review Comment:
   ```suggestion
       /// See 
[PostgreSQL](https://www.postgresql.org/docs/current/sql-createtype.html)
   ```
   Can we also add a short description what the function does?



##########
src/ast/ddl.rs:
##########
@@ -640,6 +640,68 @@ impl fmt::Display for AlterIndexOperation {
     }
 }
 
+/// An `ALTER TYPE` (`Statement::AlterType`) operation
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum AlterTypeOperation {
+    Rename {
+        new_name: Ident,
+    },
+    AddValue {
+        if_not_exists: bool,
+        value: Ident,
+        position: AlterTypeOperationAddValuePosition,
+    },
+    RenameValue {
+        from: Ident,
+        to: Ident,
+    },
+}
+
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum AlterTypeOperationAddValuePosition {

Review Comment:
   ```suggestion
   pub enum AlterTypeAddValuePosition {
   ```
   maybe an opportunity to shorten the name, since AddValue is already an 
operation



##########
src/ast/mod.rs:
##########
@@ -2691,6 +2692,14 @@ pub enum Statement {
         with_options: Vec<SqlOption>,
     },
     /// ```sql
+    /// ALTER TYPE
+    /// See 
[PostgreSQL](https://www.postgresql.org/docs/current/sql-altertype.html)
+    /// ```
+    AlterType {
+        name: ObjectName,
+        operation: AlterTypeOperation,
+    },

Review Comment:
   Can we replace the anonymous enum variants (this and `AlterTypeOperation` 
with structs? we're slowly [moving a way from using this 
representation](https://github.com/apache/datafusion-sqlparser-rs/issues/1204)



##########
src/parser/mod.rs:
##########
@@ -14258,6 +14316,21 @@ impl<'a> Parser<'a> {
         })
     }
 
+    // See 
[PostgreSQL](https://www.postgresql.org/docs/current/sql-createtype.html)
+    pub fn parse_create_type_enum(&mut self, name: ObjectName) -> 
Result<Statement, ParserError> {
+        if !self.consume_token(&Token::LParen) {
+            return self.expected("'(' after CREATE TYPE AS ENUM", 
self.peek_token());
+        }

Review Comment:
   can we use `self.expect_token()` here?



##########
src/ast/ddl.rs:
##########
@@ -640,6 +640,68 @@ impl fmt::Display for AlterIndexOperation {
     }
 }
 
+/// An `ALTER TYPE` (`Statement::AlterType`) operation
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum AlterTypeOperation {
+    Rename {
+        new_name: Ident,
+    },
+    AddValue {
+        if_not_exists: bool,
+        value: Ident,
+        position: AlterTypeOperationAddValuePosition,

Review Comment:
   I think in order to follow convention we can make this field optional in 
order to remove the `Default` position variant?



##########
src/parser/mod.rs:
##########
@@ -8122,6 +8127,55 @@ impl<'a> Parser<'a> {
         })
     }
 
+    pub fn parse_alter_type(&mut self) -> Result<Statement, ParserError> {
+        let name = self.parse_object_name(false)?;
+
+        if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
+            let new_name = self.parse_identifier()?;
+            Ok(Statement::AlterType {
+                name,
+                operation: AlterTypeOperation::Rename { new_name },
+            })
+        } else if self.parse_keywords(&[Keyword::ADD, Keyword::VALUE]) {
+            let if_not_exists = self.parse_keywords(&[Keyword::IF, 
Keyword::NOT, Keyword::EXISTS]);
+            let new_enum_value = self.parse_identifier()?;
+            let position = if self.parse_keyword(Keyword::BEFORE) {
+                
AlterTypeOperationAddValuePosition::Before(self.parse_identifier()?)
+            } else if self.parse_keyword(Keyword::AFTER) {
+                
AlterTypeOperationAddValuePosition::After(self.parse_identifier()?)
+            } else {
+                AlterTypeOperationAddValuePosition::Default
+            };
+
+            Ok(Statement::AlterType {
+                name,
+                operation: AlterTypeOperation::AddValue {
+                    if_not_exists,
+                    value: new_enum_value,
+                    position,
+                },
+            })
+        } else if self.parse_keywords(&[Keyword::RENAME, Keyword::VALUE]) {
+            let existing_enum_value = self.parse_identifier()?;
+            self.expect_keyword(Keyword::TO)?;
+            let new_enum_value = self.parse_identifier()?;
+
+            Ok(Statement::AlterType {
+                name,
+                operation: AlterTypeOperation::RenameValue {
+                    from: existing_enum_value,
+                    to: new_enum_value,
+                },
+            })
+        } else {
+            self.expected_ref(
+                "{RENAME TO | { RENAME | ADD } VALUE}",
+                self.peek_token_ref(),
+            )?;
+            unreachable!()

Review Comment:
   ```suggestion
               )
   ```
   not sure I follow the use of unreachable here, i imagine returning the error 
should suffice? (we would want to avoid the panic in any case)



##########
src/dialect/mod.rs:
##########
@@ -490,6 +490,26 @@ pub trait Dialect: Debug + Any {
         false
     }
 
+    /// Return true if the dialect supports creating enum types
+    ///
+    /// Example:
+    /// ```sql
+    /// CREATE TYPE some_enum AS ENUM('one', 'two', 'three');
+    /// ```
+    fn supports_create_type_as_enum(&self) -> bool {
+        false
+    }
+
+    /// Return true if the dialect supports ALTER TYPE statements
+    ///
+    /// Example:
+    /// ```sql
+    /// ALTER TYPE some_enum ADD VALUE 'some_value';
+    /// ```
+    fn supports_alter_type(&self) -> bool {
+        false
+    }

Review Comment:
   Thinking we could skip the dialect flags for this case and have the parse 
the statement unconditionally, if it does not conflict with existing statements?



##########
src/parser/mod.rs:
##########
@@ -8122,6 +8127,55 @@ impl<'a> Parser<'a> {
         })
     }
 
+    pub fn parse_alter_type(&mut self) -> Result<Statement, ParserError> {

Review Comment:
   ```suggestion
       /// Parse a [Statement::AlterType].
       pub fn parse_alter_type(&mut self) -> Result<Statement, ParserError> {
   ```
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscr...@datafusion.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: github-unsubscr...@datafusion.apache.org
For additional commands, e-mail: github-h...@datafusion.apache.org

Reply via email to