Skip to content

Commit 8ecb6c9

Browse files
committed
feat(parser): parse CREATE FOREIGN DATA WRAPPER and CREATE FOREIGN TABLE
- Dispatch on FOREIGN keyword in parse_create, branching on DATA WRAPPER or TABLE - parse_create_foreign_data_wrapper: parses optional HANDLER/NO HANDLER, VALIDATOR/NO VALIDATOR, and OPTIONS clauses - parse_create_foreign_table: parses IF NOT EXISTS, column list via parse_columns, required SERVER name, and optional OPTIONS clause
1 parent 613c05f commit 8ecb6c9

1 file changed

Lines changed: 91 additions & 0 deletions

File tree

src/parser/mod.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5213,6 +5213,17 @@ impl<'a> Parser<'a> {
52135213
}
52145214
} else if self.parse_keyword(Keyword::SERVER) {
52155215
self.parse_pg_create_server()
5216+
} else if self.parse_keyword(Keyword::FOREIGN) {
5217+
if self.parse_keywords(&[Keyword::DATA, Keyword::WRAPPER]) {
5218+
self.parse_create_foreign_data_wrapper().map(Into::into)
5219+
} else if self.parse_keyword(Keyword::TABLE) {
5220+
self.parse_create_foreign_table().map(Into::into)
5221+
} else {
5222+
self.expected_ref(
5223+
"DATA WRAPPER or TABLE after CREATE FOREIGN",
5224+
self.peek_token_ref(),
5225+
)
5226+
}
52165227
} else {
52175228
self.expected_ref("an object type after CREATE", self.peek_token_ref())
52185229
}
@@ -19757,6 +19768,86 @@ impl<'a> Parser<'a> {
1975719768
}))
1975819769
}
1975919770

19771+
/// Parse a `CREATE FOREIGN DATA WRAPPER` statement.
19772+
///
19773+
/// See <https://www.postgresql.org/docs/current/sql-createforeigndatawrapper.html>
19774+
pub fn parse_create_foreign_data_wrapper(
19775+
&mut self,
19776+
) -> Result<CreateForeignDataWrapper, ParserError> {
19777+
let name = self.parse_identifier()?;
19778+
19779+
let handler = if self.parse_keyword(Keyword::HANDLER) {
19780+
Some(FdwRoutineClause::Function(self.parse_object_name(false)?))
19781+
} else if self.parse_keywords(&[Keyword::NO, Keyword::HANDLER]) {
19782+
Some(FdwRoutineClause::NoFunction)
19783+
} else {
19784+
None
19785+
};
19786+
19787+
let validator = if self.parse_keyword(Keyword::VALIDATOR) {
19788+
Some(FdwRoutineClause::Function(self.parse_object_name(false)?))
19789+
} else if self.parse_keywords(&[Keyword::NO, Keyword::VALIDATOR]) {
19790+
Some(FdwRoutineClause::NoFunction)
19791+
} else {
19792+
None
19793+
};
19794+
19795+
let options = if self.parse_keyword(Keyword::OPTIONS) {
19796+
self.expect_token(&Token::LParen)?;
19797+
let opts = self.parse_comma_separated(|p| {
19798+
let key = p.parse_identifier()?;
19799+
let value = p.parse_identifier()?;
19800+
Ok(CreateServerOption { key, value })
19801+
})?;
19802+
self.expect_token(&Token::RParen)?;
19803+
Some(opts)
19804+
} else {
19805+
None
19806+
};
19807+
19808+
Ok(CreateForeignDataWrapper {
19809+
name,
19810+
handler,
19811+
validator,
19812+
options,
19813+
})
19814+
}
19815+
19816+
/// Parse a `CREATE FOREIGN TABLE` statement.
19817+
///
19818+
/// See <https://www.postgresql.org/docs/current/sql-createforeigntable.html>
19819+
pub fn parse_create_foreign_table(
19820+
&mut self,
19821+
) -> Result<CreateForeignTable, ParserError> {
19822+
let if_not_exists =
19823+
self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
19824+
let name = self.parse_object_name(false)?;
19825+
let (columns, _constraints) = self.parse_columns()?;
19826+
self.expect_keyword_is(Keyword::SERVER)?;
19827+
let server_name = self.parse_identifier()?;
19828+
19829+
let options = if self.parse_keyword(Keyword::OPTIONS) {
19830+
self.expect_token(&Token::LParen)?;
19831+
let opts = self.parse_comma_separated(|p| {
19832+
let key = p.parse_identifier()?;
19833+
let value = p.parse_identifier()?;
19834+
Ok(CreateServerOption { key, value })
19835+
})?;
19836+
self.expect_token(&Token::RParen)?;
19837+
Some(opts)
19838+
} else {
19839+
None
19840+
};
19841+
19842+
Ok(CreateForeignTable {
19843+
name,
19844+
if_not_exists,
19845+
columns,
19846+
server_name,
19847+
options,
19848+
})
19849+
}
19850+
1976019851
/// The index of the first unprocessed token.
1976119852
pub fn index(&self) -> usize {
1976219853
self.index

0 commit comments

Comments
 (0)