fmguerreiro commented on code in PR #2317:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/2317#discussion_r4335695882


##########
src/parser/mod.rs:
##########
@@ -20756,6 +20763,53 @@ impl<'a> Parser<'a> {
         })
     }
 
+    /// Parse a `CREATE FOREIGN DATA WRAPPER` statement.
+    ///
+    /// See 
<https://www.postgresql.org/docs/current/sql-createforeigndatawrapper.html>
+    pub fn parse_create_foreign_data_wrapper(
+        &mut self,
+    ) -> Result<CreateForeignDataWrapper, ParserError> {
+        let name = self.parse_identifier()?;
+
+        // PostgreSQL accepts HANDLER and VALIDATOR in either order, so they 
are
+        // consumed in a loop rather than positionally.
+        let mut handler = None;
+        let mut validator = None;
+        loop {
+            let loc = self.peek_token_ref().span.start;
+            let (slot, clause) = if self.parse_keyword(Keyword::HANDLER) {
+                (
+                    &mut handler,
+                    
ForeignDataWrapperRoutineClause::Function(self.parse_object_name(false)?),
+                )
+            } else if self.parse_keywords(&[Keyword::NO, Keyword::HANDLER]) {
+                (&mut handler, ForeignDataWrapperRoutineClause::Absent)
+            } else if self.parse_keyword(Keyword::VALIDATOR) {
+                (
+                    &mut validator,
+                    
ForeignDataWrapperRoutineClause::Function(self.parse_object_name(false)?),
+                )
+            } else if self.parse_keywords(&[Keyword::NO, Keyword::VALIDATOR]) {
+                (&mut validator, ForeignDataWrapperRoutineClause::Absent)
+            } else {
+                break;
+            };
+            if slot.is_some() {
+                return parser_err!("conflicting or redundant options", loc);
+            }
+            *slot = Some(clause);
+        }
+
+        let options = self.parse_pg_options_clause()?;
+
+        Ok(CreateForeignDataWrapper {
+            name,
+            handler,
+            validator,
+            options,
+        })

Review Comment:
   fixed in df5a604c.



##########
src/ast/ddl.rs:
##########
@@ -6056,6 +6056,60 @@ impl fmt::Display for CreateForeignTable {
     }
 }
 
+/// The handler/validator clause of a `CREATE FOREIGN DATA WRAPPER` statement.
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum ForeignDataWrapperRoutineClause {
+    /// A named function, e.g. `HANDLER myhandler` or `VALIDATOR myvalidator`.
+    Function(ObjectName),
+    /// The `NO HANDLER` / `NO VALIDATOR` form.
+    Absent,
+}
+
+impl ForeignDataWrapperRoutineClause {
+    fn fmt_with_label(&self, f: &mut fmt::Formatter<'_>, label: &str) -> 
fmt::Result {
+        match self {
+            ForeignDataWrapperRoutineClause::Function(name) => write!(f, " 
{label} {name}"),
+            ForeignDataWrapperRoutineClause::Absent => write!(f, " NO 
{label}"),
+        }
+    }
+}

Review Comment:
   fixed in 6c333723.



##########
src/ast/ddl.rs:
##########
@@ -6056,6 +6056,60 @@ impl fmt::Display for CreateForeignTable {
     }
 }
 
+/// The handler/validator clause of a `CREATE FOREIGN DATA WRAPPER` statement.
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum ForeignDataWrapperRoutineClause {
+    /// A named function, e.g. `HANDLER myhandler` or `VALIDATOR myvalidator`.
+    Function(ObjectName),
+    /// The `NO HANDLER` / `NO VALIDATOR` form.
+    Absent,
+}
+
+impl ForeignDataWrapperRoutineClause {
+    fn fmt_with_label(&self, f: &mut fmt::Formatter<'_>, label: &str) -> 
fmt::Result {
+        match self {
+            ForeignDataWrapperRoutineClause::Function(name) => write!(f, " 
{label} {name}"),
+            ForeignDataWrapperRoutineClause::Absent => write!(f, " NO 
{label}"),
+        }
+    }
+}
+
+/// A `CREATE FOREIGN DATA WRAPPER` statement.
+///
+/// See 
[PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigndatawrapper.html)
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateForeignDataWrapper {
+    /// The name of the foreign-data wrapper. Per PostgreSQL this is a bare
+    /// identifier and cannot be schema-qualified.
+    pub name: Ident,
+    /// Optional `HANDLER handler_function` or `NO HANDLER` clause.
+    pub handler: Option<ForeignDataWrapperRoutineClause>,
+    /// Optional `VALIDATOR validator_function` or `NO VALIDATOR` clause.
+    pub validator: Option<ForeignDataWrapperRoutineClause>,

Review Comment:
   fixed in 09072669.



##########
src/ast/ddl.rs:
##########
@@ -6056,6 +6056,60 @@ impl fmt::Display for CreateForeignTable {
     }
 }
 
+/// The handler/validator clause of a `CREATE FOREIGN DATA WRAPPER` statement.
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum ForeignDataWrapperRoutineClause {
+    /// A named function, e.g. `HANDLER myhandler` or `VALIDATOR myvalidator`.
+    Function(ObjectName),
+    /// The `NO HANDLER` / `NO VALIDATOR` form.
+    Absent,
+}
+
+impl ForeignDataWrapperRoutineClause {
+    fn fmt_with_label(&self, f: &mut fmt::Formatter<'_>, label: &str) -> 
fmt::Result {
+        match self {
+            ForeignDataWrapperRoutineClause::Function(name) => write!(f, " 
{label} {name}"),
+            ForeignDataWrapperRoutineClause::Absent => write!(f, " NO 
{label}"),
+        }
+    }
+}
+
+/// A `CREATE FOREIGN DATA WRAPPER` statement.
+///
+/// See 
[PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigndatawrapper.html)
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateForeignDataWrapper {
+    /// The name of the foreign-data wrapper. Per PostgreSQL this is a bare
+    /// identifier and cannot be schema-qualified.
+    pub name: Ident,
+    /// Optional `HANDLER handler_function` or `NO HANDLER` clause.
+    pub handler: Option<ForeignDataWrapperRoutineClause>,
+    /// Optional `VALIDATOR validator_function` or `NO VALIDATOR` clause.
+    pub validator: Option<ForeignDataWrapperRoutineClause>,
+    /// Optional `OPTIONS (key 'value', ...)` clause.
+    pub options: Option<Vec<CreateServerOption>>,
+}
+
+impl fmt::Display for CreateForeignDataWrapper {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "CREATE FOREIGN DATA WRAPPER {}", self.name)?;
+        if let Some(handler) = &self.handler {
+            handler.fmt_with_label(f, "HANDLER")?;
+        }
+        if let Some(validator) = &self.validator {
+            validator.fmt_with_label(f, "VALIDATOR")?;
+        }

Review Comment:
   fixed in b62f3d9e.



##########
src/ast/ddl.rs:
##########
@@ -6078,3 +6132,29 @@ impl Spanned for CreateForeignTable {
         )
     }
 }
+
+impl From<CreateForeignDataWrapper> for crate::ast::Statement {
+    fn from(v: CreateForeignDataWrapper) -> Self {
+        crate::ast::Statement::CreateForeignDataWrapper(v)
+    }
+}
+
+impl Spanned for CreateForeignDataWrapper {
+    fn span(&self) -> Span {
+        let routine_span = |clause: &Option<ForeignDataWrapperRoutineClause>| 
match clause {
+            Some(ForeignDataWrapperRoutineClause::Function(name)) => 
Some(name.span()),
+            _ => None,
+        };
+        Span::union_iter(
+            core::iter::once(self.name.span)
+                .chain(routine_span(&self.handler))
+                .chain(routine_span(&self.validator))

Review Comment:
   fixed in b73f98fb.



-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to