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


##########
src/ast/mod.rs:
##########
@@ -9203,6 +9232,30 @@ pub enum CopyIntoSnowflakeKind {
     Location,
 }
 
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ReturnStatement {
+    pub value: Option<ReturnStatementValue>,
+}
+
+impl fmt::Display for ReturnStatement {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match &self.value {
+            Some(ReturnStatementValue::Expr(expr)) => write!(f, "RETURN {}", 
expr),
+            None => write!(f, "RETURN")
+        }
+    }
+}
+
+/// Variants of the Mssql `RETURN` statement

Review Comment:
   ```suggestion
   /// Variants of a `RETURN` statement
   ```
   since this statement isn't mysql specific



##########
src/parser/mod.rs:
##########
@@ -5135,6 +5142,69 @@ impl<'a> Parser<'a> {
         }))
     }
 
+    /// Parse `CREATE FUNCTION` for [MsSql]
+    ///
+    /// [MsSql]: 
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
+    fn parse_mssql_create_function(
+        &mut self,
+        or_alter: bool,
+        or_replace: bool,
+        temporary: bool,
+    ) -> Result<Statement, ParserError> {
+        let name = self.parse_object_name(false)?;
+
+        let parse_function_param =
+            |parser: &mut Parser| -> Result<OperateFunctionArg, ParserError> {
+                let name = parser.parse_identifier()?;
+                let data_type = parser.parse_data_type()?;
+                Ok(OperateFunctionArg {
+                    mode: None,
+                    name: Some(name),
+                    data_type,
+                    default_expr: None,
+                })
+            };
+        self.expect_token(&Token::LParen)?;
+        let args = self.parse_comma_separated0(parse_function_param, 
Token::RParen)?;
+        self.expect_token(&Token::RParen)?;
+
+        let return_type = if self.parse_keyword(Keyword::RETURNS) {
+            Some(self.parse_data_type()?)
+        } else {
+            None
+        };

Review Comment:
   This part looks identical to the [bigquery 
implementation](https://github.com/apache/datafusion-sqlparser-rs/blob/1b50dd9d0764b96d9a6b4e81f77d77e7cae84097/src/parser/mod.rs#L5064-L5085)
 could we pull the logic out into a function to be reused by both?



##########
src/ast/mod.rs:
##########
@@ -4050,6 +4051,13 @@ pub enum Statement {
         arguments: Vec<Expr>,
         options: Vec<RaisErrorOption>,
     },
+    /// Return (Mssql)
+    ///
+    /// for Functions:
+    /// RETURN scalar_expression
+    ///
+    /// See: 
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql

Review Comment:
   Maybe we can move this to the `ReturnStatement` struct definition, and here 
we can only point to the statement like `Parse a [ReturnStatement]`? Thinking 
having it on the struct will be more visible as the struct can be 
reused/reached from more places



##########
src/ast/mod.rs:
##########
@@ -8368,6 +8387,22 @@ pub enum CreateFunctionBody {
     ///
     /// [BigQuery]: 
https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11
     AsAfterOptions(Expr),
+    /// Function body with statements before the `RETURN` keyword.
+    ///
+    /// Example:
+    /// ```sql
+    /// CREATE FUNCTION my_scalar_udf(a INT, b INT)
+    /// RETURNS INT
+    /// AS
+    /// BEGIN
+    ///     DECLARE c INT;
+    ///     SET c = a + b;
+    ///     RETURN c;
+    /// END;
+    /// ```
+    ///
+    /// [SQL Server]: 
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
+    MultiStatement(Vec<Statement>),

Review Comment:
   Yeah I think we ideally have it in this PR since this adds a new API that 
will otherwise need to be changed



##########
src/ast/mod.rs:
##########
@@ -4050,6 +4051,13 @@ pub enum Statement {
         arguments: Vec<Expr>,
         options: Vec<RaisErrorOption>,
     },
+    /// Return (Mssql)
+    ///
+    /// for Functions:
+    /// RETURN scalar_expression
+    ///
+    /// See: 
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql

Review Comment:
   ```suggestion
       /// Return
       ///
       /// for Functions:
       /// RETURN scalar_expression
       ///
       /// [MsSql]: 
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
   ```
   since the statement is supported by other dialects



##########
src/parser/mod.rs:
##########
@@ -15017,6 +15075,13 @@ impl<'a> Parser<'a> {
         }
     }
 
+    fn parse_return(&mut self) -> Result<Statement, ParserError> {
+        let expr = self.parse_expr()?;

Review Comment:
   Maybe we can remove the return statement bits from this PR and tackle it 
separately as its own PR?
   
   Otherwise indeed the expectation would be that this uses maybe_parse and we 
have the test cases in place as part of this PR



##########
src/parser/mod.rs:
##########
@@ -5135,6 +5146,63 @@ impl<'a> Parser<'a> {
         }))
     }
 
+    /// Parse `CREATE FUNCTION` for [SQL Server]
+    ///
+    /// [SQL Server]: 
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
+    fn parse_mssql_create_function(
+        &mut self,
+        or_alter: bool,
+        or_replace: bool,
+        temporary: bool,
+    ) -> Result<Statement, ParserError> {
+        let name = self.parse_object_name(false)?;
+
+        let parse_function_param =
+            |parser: &mut Parser| -> Result<OperateFunctionArg, ParserError> {
+                let name = parser.parse_identifier()?;
+                let data_type = parser.parse_data_type()?;
+                Ok(OperateFunctionArg {
+                    mode: None,
+                    name: Some(name),
+                    data_type,
+                    default_expr: None,
+                })
+            };
+        self.expect_token(&Token::LParen)?;
+        let args = self.parse_comma_separated0(parse_function_param, 
Token::RParen)?;
+        self.expect_token(&Token::RParen)?;
+
+        let return_type = if self.parse_keyword(Keyword::RETURNS) {
+            Some(self.parse_data_type()?)
+        } else {
+            None
+        };
+
+        self.expect_keyword_is(Keyword::AS)?;
+        self.expect_keyword_is(Keyword::BEGIN)?;
+        let function_body = 
Some(CreateFunctionBody::MultiStatement(self.parse_statements()?));

Review Comment:
   > but I'm not yet sure how to actually implement that statement parsing logic
   
   hmm not sure I followed what we mean here? parsing a semicolon-less 
statement I imagine would follow from the above code snippet by calling 
`self.parse_statements_inner(false)`
   
   It would indeed be good to resolve in this PR, currently in the PR we seem 
to have a workaround for this behavior 
[here](https://github.com/apache/datafusion-sqlparser-rs/blob/1b50dd9d0764b96d9a6b4e81f77d77e7cae84097/src/parser/mod.rs#L487-L493)
 and 
[here](https://github.com/apache/datafusion-sqlparser-rs/blob/1b50dd9d0764b96d9a6b4e81f77d77e7cae84097/src/parser/mod.rs#L5180-L5185)
 and another in the Go statement PR.



##########
src/parser/mod.rs:
##########
@@ -5135,6 +5146,63 @@ impl<'a> Parser<'a> {
         }))
     }
 
+    /// Parse `CREATE FUNCTION` for [SQL Server]
+    ///
+    /// [SQL Server]: 
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql

Review Comment:
   Yeah the mssql name used in the library is unfortunate, but it wouldn't be 
worth the breakage to rename the [dialect 
itself](https://github.com/apache/datafusion-sqlparser-rs/blob/main/src/dialect/mssql.rs#L29-L31)
 and the documentation  in the code follows from there, so that I think it 
would be preferable to remain consistent with the naming at this point even if 
the name isn't optimal



##########
src/parser/mod.rs:
##########
@@ -5135,6 +5142,69 @@ impl<'a> Parser<'a> {
         }))
     }
 
+    /// Parse `CREATE FUNCTION` for [MsSql]
+    ///
+    /// [MsSql]: 
https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
+    fn parse_mssql_create_function(
+        &mut self,
+        or_alter: bool,
+        or_replace: bool,
+        temporary: bool,
+    ) -> Result<Statement, ParserError> {
+        let name = self.parse_object_name(false)?;
+
+        let parse_function_param =
+            |parser: &mut Parser| -> Result<OperateFunctionArg, ParserError> {
+                let name = parser.parse_identifier()?;
+                let data_type = parser.parse_data_type()?;
+                Ok(OperateFunctionArg {
+                    mode: None,
+                    name: Some(name),
+                    data_type,
+                    default_expr: None,
+                })
+            };
+        self.expect_token(&Token::LParen)?;
+        let args = self.parse_comma_separated0(parse_function_param, 
Token::RParen)?;
+        self.expect_token(&Token::RParen)?;
+
+        let return_type = if self.parse_keyword(Keyword::RETURNS) {
+            Some(self.parse_data_type()?)
+        } else {
+            None
+        };

Review Comment:
   Yeah it sounds reasonable in that case to expect the returns clause



-- 
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