improvements after review

This commit is contained in:
Sergey Olontsev 2025-07-02 08:05:34 +03:00
parent 1b916b8781
commit 77b868b0a2
No known key found for this signature in database
GPG key ID: 67DDC06CA52E8A39
4 changed files with 126 additions and 98 deletions

View file

@ -29,12 +29,12 @@ use helpers::{
};
use core::cmp::Ordering;
use core::fmt::Formatter;
use core::ops::Deref;
use core::{
fmt::{self, Display},
hash,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@ -3315,18 +3315,8 @@ pub enum Statement {
secret_type: Ident,
options: Vec<SecretOption>,
},
/// ```sql
/// CREATE SERVER
/// ```
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createserver.html)
CreateServer {
name: ObjectName,
if_not_exists: bool,
server_type: Option<Ident>,
version: Option<Ident>,
foreign_data_wrapper: ObjectName,
options: Option<Vec<ServerOption>>,
},
/// A `CREATE SERVER` statement.
CreateServer(CreateServerStatement),
/// ```sql
/// CREATE POLICY
/// ```
@ -5187,35 +5177,8 @@ impl fmt::Display for Statement {
write!(f, " )")?;
Ok(())
}
Statement::CreateServer {
name,
if_not_exists,
server_type,
version,
foreign_data_wrapper,
options,
} => {
write!(
f,
"CREATE SERVER {if_not_exists}{name} ",
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
)?;
if let Some(st) = server_type {
write!(f, "TYPE {st} ")?;
}
if let Some(v) = version {
write!(f, "VERSION {v} ")?;
}
write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
if let Some(o) = options {
write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
}
Ok(())
Statement::CreateServer(stmt) => {
write!(f, "{stmt}")
}
Statement::CreatePolicy {
name,
@ -8015,6 +7978,63 @@ impl fmt::Display for SecretOption {
}
}
/// A `CREATE SERVER` statement.
///
/// Examples:
/// ```sql
/// CREATE SERVER [ IF NOT EXISTS ] server_name [ TYPE 'server_type' ] [ VERSION 'server_version' ]
/// FOREIGN DATA WRAPPER fdw_name
/// [ OPTIONS ( option 'value' [, ... ] ) ]
/// ```
///
/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.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 CreateServerStatement {
pub name: ObjectName,
pub if_not_exists: bool,
pub server_type: Option<Ident>,
pub version: Option<Ident>,
pub foreign_data_wrapper: ObjectName,
pub options: Option<Vec<CreateServerOption>>,
}
impl fmt::Display for CreateServerStatement {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let CreateServerStatement {
name,
if_not_exists,
server_type,
version,
foreign_data_wrapper,
options,
} = self;
write!(
f,
"CREATE SERVER {if_not_exists}{name} ",
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
)?;
if let Some(st) = server_type {
write!(f, "TYPE {st} ")?;
}
if let Some(v) = version {
write!(f, "VERSION {v} ")?;
}
write!(f, "FOREIGN DATA WRAPPER {foreign_data_wrapper}")?;
if let Some(o) = options {
write!(f, " OPTIONS ({o})", o = display_comma_separated(o))?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
@ -8023,7 +8043,7 @@ pub struct CreateServerOption {
pub value: Ident,
}
impl fmt::Display for ServerOption {
impl fmt::Display for CreateServerOption {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {}", self.key, self.value)
}

View file

@ -163,6 +163,7 @@ extern crate alloc;
#[macro_use]
#[cfg(test)]
extern crate pretty_assertions;
extern crate core;
pub mod ast;
#[macro_use]

View file

@ -15840,19 +15840,19 @@ impl<'a> Parser<'a> {
options = Some(self.parse_comma_separated(|p| {
let key = p.parse_identifier()?;
let value = p.parse_identifier()?;
Ok(ServerOption { key, value })
Ok(CreateServerOption { key, value })
})?);
self.expect_token(&Token::RParen)?;
}
Ok(CreateServer {
Ok(CreateServer(CreateServerStatement {
name,
if_not_exists: ine,
server_type,
version,
foreign_data_wrapper,
options,
})
}))
}
/// The index of the first unprocessed token.

View file

@ -6234,21 +6234,21 @@ fn parse_ts_datatypes() {
#[test]
fn parse_create_server() {
assert_eq!(
pg_and_generic().verified_stmt("CREATE SERVER myserver FOREIGN DATA WRAPPER postgres_fdw"),
Statement::CreateServer {
name: ObjectName::from(vec!["myserver".into()]),
if_not_exists: false,
server_type: None,
version: None,
foreign_data_wrapper: ObjectName::from(vec!["postgres_fdw".into()]),
options: None,
}
);
assert_eq!(
pg_and_generic().verified_stmt("CREATE SERVER IF NOT EXISTS myserver TYPE 'server_type' VERSION 'server_version' FOREIGN DATA WRAPPER postgres_fdw"),
Statement::CreateServer {
let test_cases = vec![
(
"CREATE SERVER myserver FOREIGN DATA WRAPPER postgres_fdw",
CreateServerStatement {
name: ObjectName::from(vec!["myserver".into()]),
if_not_exists: false,
server_type: None,
version: None,
foreign_data_wrapper: ObjectName::from(vec!["postgres_fdw".into()]),
options: None,
},
),
(
"CREATE SERVER IF NOT EXISTS myserver TYPE 'server_type' VERSION 'server_version' FOREIGN DATA WRAPPER postgres_fdw",
CreateServerStatement {
name: ObjectName::from(vec!["myserver".into()]),
if_not_exists: true,
server_type: Some(Ident {
@ -6264,42 +6264,49 @@ fn parse_create_server() {
foreign_data_wrapper: ObjectName::from(vec!["postgres_fdw".into()]),
options: None,
}
);
),
(
"CREATE SERVER myserver2 FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'foo', dbname 'foodb', port '5432')",
CreateServerStatement {
name: ObjectName::from(vec!["myserver2".into()]),
if_not_exists: false,
server_type: None,
version: None,
foreign_data_wrapper: ObjectName::from(vec!["postgres_fdw".into()]),
options: Some(vec![
CreateServerOption {
key: "host".into(),
value: Ident {
value: "foo".to_string(),
quote_style: Some('\''),
span: Span::empty(),
},
},
CreateServerOption {
key: "dbname".into(),
value: Ident {
value: "foodb".to_string(),
quote_style: Some('\''),
span: Span::empty(),
},
},
CreateServerOption {
key: "port".into(),
value: Ident {
value: "5432".to_string(),
quote_style: Some('\''),
span: Span::empty(),
},
},
]),
}
)
];
assert_eq!(
pg_and_generic().verified_stmt("CREATE SERVER myserver2 FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'foo', dbname 'foodb', port '5432')"),
Statement::CreateServer {
name: ObjectName::from(vec!["myserver2".into()]),
if_not_exists: false,
server_type: None,
version: None,
foreign_data_wrapper: ObjectName::from(vec!["postgres_fdw".into()]),
options: Some(vec![
ServerOption {
key: "host".into(),
value: Ident {
value: "foo".to_string(),
quote_style: Some('\''),
span: Span::empty(),
},
},
ServerOption {
key: "dbname".into(),
value: Ident {
value: "foodb".to_string(),
quote_style: Some('\''),
span: Span::empty(),
},
},
ServerOption {
key: "port".into(),
value: Ident {
value: "5432".to_string(),
quote_style: Some('\''),
span: Span::empty(),
},
},
]),
}
)
for (sql, expected) in test_cases {
let Statement::CreateServer(stmt) = pg_and_generic().verified_stmt(sql) else {
unreachable!()
};
assert_eq!(stmt, expected);
}
}