Skip to content

Commit d1a27d1

Browse files
committed
feat(parser): parse SECURITY LABEL, CREATE USER MAPPING, CREATE TABLESPACE
Add parse_security_label to parse_statement dispatch on Keyword::SECURITY. Add parse_create_user_mapping dispatched from CREATE USER MAPPING branch (checked before existing CREATE USER fallthrough). Add parse_create_tablespace dispatched from parse_create on Keyword::TABLESPACE. Refs: pgmold-115, pgmold-119, pgmold-120
1 parent 846a692 commit d1a27d1

1 file changed

Lines changed: 138 additions & 1 deletion

File tree

src/parser/mod.rs

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,7 @@ impl<'a> Parser<'a> {
719719
self.parse_vacuum()
720720
}
721721
Keyword::RESET => self.parse_reset().map(Into::into),
722+
Keyword::SECURITY => self.parse_security_label().map(Into::into),
722723
_ => self.expected("an SQL statement", next_token),
723724
},
724725
Token::LParen => {
@@ -5172,7 +5173,11 @@ impl<'a> Parser<'a> {
51725173
} else if self.parse_keyword(Keyword::SECRET) {
51735174
self.parse_create_secret(or_replace, temporary, persistent)
51745175
} else if self.parse_keyword(Keyword::USER) {
5175-
self.parse_create_user(or_replace).map(Into::into)
5176+
if self.parse_keyword(Keyword::MAPPING) {
5177+
self.parse_create_user_mapping().map(Into::into)
5178+
} else {
5179+
self.parse_create_user(or_replace).map(Into::into)
5180+
}
51765181
} else if self.parse_keyword(Keyword::AGGREGATE) {
51775182
self.parse_create_aggregate(or_replace).map(Into::into)
51785183
} else if or_replace {
@@ -5232,6 +5237,8 @@ impl<'a> Parser<'a> {
52325237
self.parse_create_publication().map(Into::into)
52335238
} else if self.parse_keyword(Keyword::SUBSCRIPTION) {
52345239
self.parse_create_subscription().map(Into::into)
5240+
} else if self.parse_keyword(Keyword::TABLESPACE) {
5241+
self.parse_create_tablespace().map(Into::into)
52355242
} else {
52365243
self.expected_ref("an object type after CREATE", self.peek_token_ref())
52375244
}
@@ -20268,6 +20275,136 @@ impl<'a> Parser<'a> {
2026820275
})
2026920276
}
2027020277

20278+
/// Parse a `SECURITY LABEL` statement.
20279+
///
20280+
/// See <https://www.postgresql.org/docs/current/sql-securitylabel.html>
20281+
pub fn parse_security_label(&mut self) -> Result<SecurityLabel, ParserError> {
20282+
self.expect_keyword_is(Keyword::LABEL)?;
20283+
20284+
let provider = if self.parse_keyword(Keyword::FOR) {
20285+
Some(self.parse_identifier()?)
20286+
} else {
20287+
None
20288+
};
20289+
20290+
self.expect_keyword_is(Keyword::ON)?;
20291+
20292+
let object_kind = if self.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEW]) {
20293+
SecurityLabelObjectKind::MaterializedView
20294+
} else if self.parse_keyword(Keyword::TABLE) {
20295+
SecurityLabelObjectKind::Table
20296+
} else if self.parse_keyword(Keyword::COLUMN) {
20297+
SecurityLabelObjectKind::Column
20298+
} else if self.parse_keyword(Keyword::DATABASE) {
20299+
SecurityLabelObjectKind::Database
20300+
} else if self.parse_keyword(Keyword::DOMAIN) {
20301+
SecurityLabelObjectKind::Domain
20302+
} else if self.parse_keyword(Keyword::FUNCTION) {
20303+
SecurityLabelObjectKind::Function
20304+
} else if self.parse_keyword(Keyword::ROLE) {
20305+
SecurityLabelObjectKind::Role
20306+
} else if self.parse_keyword(Keyword::SCHEMA) {
20307+
SecurityLabelObjectKind::Schema
20308+
} else if self.parse_keyword(Keyword::SEQUENCE) {
20309+
SecurityLabelObjectKind::Sequence
20310+
} else if self.parse_keyword(Keyword::TYPE) {
20311+
SecurityLabelObjectKind::Type
20312+
} else if self.parse_keyword(Keyword::VIEW) {
20313+
SecurityLabelObjectKind::View
20314+
} else {
20315+
return self.expected_ref(
20316+
"TABLE, COLUMN, DATABASE, DOMAIN, FUNCTION, MATERIALIZED VIEW, ROLE, SCHEMA, SEQUENCE, TYPE, or VIEW after ON",
20317+
self.peek_token_ref(),
20318+
);
20319+
};
20320+
20321+
let object_name = self.parse_object_name(false)?;
20322+
20323+
self.expect_keyword_is(Keyword::IS)?;
20324+
20325+
let label = if self.parse_keyword(Keyword::NULL) {
20326+
None
20327+
} else {
20328+
Some(self.parse_value()?.value)
20329+
};
20330+
20331+
Ok(SecurityLabel {
20332+
provider,
20333+
object_kind,
20334+
object_name,
20335+
label,
20336+
})
20337+
}
20338+
20339+
/// Parse a `CREATE USER MAPPING` statement.
20340+
///
20341+
/// See <https://www.postgresql.org/docs/current/sql-createusermapping.html>
20342+
pub fn parse_create_user_mapping(&mut self) -> Result<CreateUserMapping, ParserError> {
20343+
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
20344+
20345+
self.expect_keyword_is(Keyword::FOR)?;
20346+
20347+
let user = if self.parse_keyword(Keyword::CURRENT_ROLE) {
20348+
UserMappingUser::CurrentRole
20349+
} else if self.parse_keyword(Keyword::CURRENT_USER) {
20350+
UserMappingUser::CurrentUser
20351+
} else if self.parse_keyword(Keyword::PUBLIC) {
20352+
UserMappingUser::Public
20353+
} else if self.parse_keyword(Keyword::USER) {
20354+
UserMappingUser::User
20355+
} else {
20356+
UserMappingUser::Ident(self.parse_identifier()?)
20357+
};
20358+
20359+
self.expect_keyword_is(Keyword::SERVER)?;
20360+
let server_name = self.parse_identifier()?;
20361+
20362+
let options = if self.parse_keyword(Keyword::OPTIONS) {
20363+
self.expect_token(&Token::LParen)?;
20364+
let opts = self.parse_comma_separated(|p| {
20365+
let key = p.parse_identifier()?;
20366+
let value = p.parse_identifier()?;
20367+
Ok(CreateServerOption { key, value })
20368+
})?;
20369+
self.expect_token(&Token::RParen)?;
20370+
Some(opts)
20371+
} else {
20372+
None
20373+
};
20374+
20375+
Ok(CreateUserMapping {
20376+
if_not_exists,
20377+
user,
20378+
server_name,
20379+
options,
20380+
})
20381+
}
20382+
20383+
/// Parse a `CREATE TABLESPACE` statement.
20384+
///
20385+
/// See <https://www.postgresql.org/docs/current/sql-createtablespace.html>
20386+
pub fn parse_create_tablespace(&mut self) -> Result<CreateTablespace, ParserError> {
20387+
let name = self.parse_identifier()?;
20388+
20389+
let owner = if self.parse_keyword(Keyword::OWNER) {
20390+
Some(self.parse_identifier()?)
20391+
} else {
20392+
None
20393+
};
20394+
20395+
self.expect_keyword_is(Keyword::LOCATION)?;
20396+
let location = self.parse_value()?.value;
20397+
20398+
let with_options = self.parse_options(Keyword::WITH)?;
20399+
20400+
Ok(CreateTablespace {
20401+
name,
20402+
owner,
20403+
location,
20404+
with_options,
20405+
})
20406+
}
20407+
2027120408
/// The index of the first unprocessed token.
2027220409
pub fn index(&self) -> usize {
2027320410
self.index

0 commit comments

Comments
 (0)