Skip to content

Commit 2b1ec01

Browse files
authored
Merge pull request #14 from fmguerreiro/feat/security-storage
feat: parse SECURITY LABEL, CREATE USER MAPPING, CREATE TABLESPACE
2 parents 4c4d773 + e7ea590 commit 2b1ec01

6 files changed

Lines changed: 502 additions & 3 deletions

File tree

src/ast/ddl.rs

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6512,3 +6512,202 @@ impl From<CreateSubscription> for crate::ast::Statement {
65126512
crate::ast::Statement::CreateSubscription(v)
65136513
}
65146514
}
6515+
6516+
/// The object kind targeted by a `SECURITY LABEL` statement.
6517+
///
6518+
/// See <https://www.postgresql.org/docs/current/sql-securitylabel.html>
6519+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6520+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6521+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6522+
pub enum SecurityLabelObjectKind {
6523+
/// `TABLE name`
6524+
Table,
6525+
/// `COLUMN name.colname`
6526+
Column,
6527+
/// `DATABASE name`
6528+
Database,
6529+
/// `DOMAIN name`
6530+
Domain,
6531+
/// `FUNCTION name`
6532+
Function,
6533+
/// `ROLE name`
6534+
Role,
6535+
/// `SCHEMA name`
6536+
Schema,
6537+
/// `SEQUENCE name`
6538+
Sequence,
6539+
/// `TYPE name`
6540+
Type,
6541+
/// `VIEW name`
6542+
View,
6543+
/// `MATERIALIZED VIEW name`
6544+
MaterializedView,
6545+
}
6546+
6547+
impl fmt::Display for SecurityLabelObjectKind {
6548+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6549+
match self {
6550+
SecurityLabelObjectKind::Table => write!(f, "TABLE"),
6551+
SecurityLabelObjectKind::Column => write!(f, "COLUMN"),
6552+
SecurityLabelObjectKind::Database => write!(f, "DATABASE"),
6553+
SecurityLabelObjectKind::Domain => write!(f, "DOMAIN"),
6554+
SecurityLabelObjectKind::Function => write!(f, "FUNCTION"),
6555+
SecurityLabelObjectKind::Role => write!(f, "ROLE"),
6556+
SecurityLabelObjectKind::Schema => write!(f, "SCHEMA"),
6557+
SecurityLabelObjectKind::Sequence => write!(f, "SEQUENCE"),
6558+
SecurityLabelObjectKind::Type => write!(f, "TYPE"),
6559+
SecurityLabelObjectKind::View => write!(f, "VIEW"),
6560+
SecurityLabelObjectKind::MaterializedView => write!(f, "MATERIALIZED VIEW"),
6561+
}
6562+
}
6563+
}
6564+
6565+
/// A `SECURITY LABEL` statement.
6566+
///
6567+
/// Note: this is a PostgreSQL-specific statement.
6568+
/// <https://www.postgresql.org/docs/current/sql-securitylabel.html>
6569+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6570+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6571+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6572+
pub struct SecurityLabel {
6573+
/// Optional `FOR provider_name` clause.
6574+
pub provider: Option<Ident>,
6575+
/// The kind of object the label is applied to.
6576+
pub object_kind: SecurityLabelObjectKind,
6577+
/// The name of the object the label is applied to.
6578+
pub object_name: ObjectName,
6579+
/// The label string, or `None` for `IS NULL`.
6580+
pub label: Option<Value>,
6581+
}
6582+
6583+
impl fmt::Display for SecurityLabel {
6584+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6585+
write!(f, "SECURITY LABEL")?;
6586+
if let Some(provider) = &self.provider {
6587+
write!(f, " FOR {provider}")?;
6588+
}
6589+
write!(f, " ON {} {}", self.object_kind, self.object_name)?;
6590+
write!(f, " IS ")?;
6591+
match &self.label {
6592+
Some(label) => write!(f, "{label}"),
6593+
None => write!(f, "NULL"),
6594+
}
6595+
}
6596+
}
6597+
6598+
impl From<SecurityLabel> for crate::ast::Statement {
6599+
fn from(v: SecurityLabel) -> Self {
6600+
crate::ast::Statement::SecurityLabel(v)
6601+
}
6602+
}
6603+
6604+
/// The role specification in a `CREATE USER MAPPING` statement.
6605+
///
6606+
/// See <https://www.postgresql.org/docs/current/sql-createusermapping.html>
6607+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6608+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6609+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6610+
pub enum UserMappingUser {
6611+
/// A specific role name.
6612+
Ident(Ident),
6613+
/// `USER` (current user)
6614+
User,
6615+
/// `CURRENT_ROLE`
6616+
CurrentRole,
6617+
/// `CURRENT_USER`
6618+
CurrentUser,
6619+
/// `PUBLIC`
6620+
Public,
6621+
}
6622+
6623+
impl fmt::Display for UserMappingUser {
6624+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6625+
match self {
6626+
UserMappingUser::Ident(ident) => write!(f, "{ident}"),
6627+
UserMappingUser::User => write!(f, "USER"),
6628+
UserMappingUser::CurrentRole => write!(f, "CURRENT_ROLE"),
6629+
UserMappingUser::CurrentUser => write!(f, "CURRENT_USER"),
6630+
UserMappingUser::Public => write!(f, "PUBLIC"),
6631+
}
6632+
}
6633+
}
6634+
6635+
/// A `CREATE USER MAPPING` statement.
6636+
///
6637+
/// Note: this is a PostgreSQL-specific statement.
6638+
/// <https://www.postgresql.org/docs/current/sql-createusermapping.html>
6639+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6640+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6641+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6642+
pub struct CreateUserMapping {
6643+
/// `IF NOT EXISTS`
6644+
pub if_not_exists: bool,
6645+
/// The user/role for the mapping.
6646+
pub user: UserMappingUser,
6647+
/// The foreign server name.
6648+
pub server_name: Ident,
6649+
/// Optional `OPTIONS (key 'value', ...)` clause.
6650+
pub options: Option<Vec<CreateServerOption>>,
6651+
}
6652+
6653+
impl fmt::Display for CreateUserMapping {
6654+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6655+
write!(f, "CREATE USER MAPPING")?;
6656+
if self.if_not_exists {
6657+
write!(f, " IF NOT EXISTS")?;
6658+
}
6659+
write!(f, " FOR {} SERVER {}", self.user, self.server_name)?;
6660+
if let Some(options) = &self.options {
6661+
write!(
6662+
f,
6663+
" OPTIONS ({})",
6664+
display_comma_separated(options)
6665+
)?;
6666+
}
6667+
Ok(())
6668+
}
6669+
}
6670+
6671+
impl From<CreateUserMapping> for crate::ast::Statement {
6672+
fn from(v: CreateUserMapping) -> Self {
6673+
crate::ast::Statement::CreateUserMapping(v)
6674+
}
6675+
}
6676+
6677+
/// A `CREATE TABLESPACE` statement.
6678+
///
6679+
/// Note: this is a PostgreSQL-specific statement.
6680+
/// <https://www.postgresql.org/docs/current/sql-createtablespace.html>
6681+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6682+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6683+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6684+
pub struct CreateTablespace {
6685+
/// The tablespace name.
6686+
pub name: Ident,
6687+
/// Optional `OWNER role` clause.
6688+
pub owner: Option<Ident>,
6689+
/// The `LOCATION 'directory'` string.
6690+
pub location: Value,
6691+
/// Optional `WITH (option = value, ...)` clause.
6692+
pub with_options: Vec<SqlOption>,
6693+
}
6694+
6695+
impl fmt::Display for CreateTablespace {
6696+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6697+
write!(f, "CREATE TABLESPACE {}", self.name)?;
6698+
if let Some(owner) = &self.owner {
6699+
write!(f, " OWNER {owner}")?;
6700+
}
6701+
write!(f, " LOCATION {}", self.location)?;
6702+
if !self.with_options.is_empty() {
6703+
write!(f, " WITH ({})", display_comma_separated(&self.with_options))?;
6704+
}
6705+
Ok(())
6706+
}
6707+
}
6708+
6709+
impl From<CreateTablespace> for crate::ast::Statement {
6710+
fn from(v: CreateTablespace) -> Self {
6711+
crate::ast::Statement::CreateTablespace(v)
6712+
}
6713+
}

src/ast/mod.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ pub use self::ddl::{
7575
CreateDomain, CreateExtension, CreateForeignDataWrapper, CreateForeignTable, CreateFunction,
7676
CreateIndex, CreateOperator, CreateOperatorClass, CreateOperatorFamily, CreatePolicy,
7777
CreatePolicyCommand, CreatePolicyType, CreatePublication, CreateSubscription, CreateTable,
78-
CreateTextSearchConfiguration, CreateTextSearchDictionary, CreateTextSearchParser,
79-
CreateTextSearchTemplate, CreateTrigger, PublicationTarget,
78+
CreateTablespace, CreateTextSearchConfiguration, CreateTextSearchDictionary,
79+
CreateTextSearchParser, CreateTextSearchTemplate, CreateTrigger, CreateUserMapping,
80+
PublicationTarget, SecurityLabel, SecurityLabelObjectKind, UserMappingUser,
8081
CreateView, Deduplicate, DeferrableInitial, DistStyle, DropBehavior, DropExtension,
8182
DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily, DropOperatorSignature,
8283
DropPolicy, DropTrigger, FdwRoutineClause, ForValues, FunctionReturnType, GeneratedAs,
@@ -4049,6 +4050,24 @@ pub enum Statement {
40494050
/// <https://www.postgresql.org/docs/current/sql-createsubscription.html>
40504051
CreateSubscription(CreateSubscription),
40514052
/// ```sql
4053+
/// SECURITY LABEL [ FOR provider_name ] ON object_type object_name IS { 'label' | NULL }
4054+
/// ```
4055+
/// Note: this is a PostgreSQL-specific statement.
4056+
/// <https://www.postgresql.org/docs/current/sql-securitylabel.html>
4057+
SecurityLabel(SecurityLabel),
4058+
/// ```sql
4059+
/// CREATE USER MAPPING [ IF NOT EXISTS ] FOR { role | USER | CURRENT_ROLE | CURRENT_USER | PUBLIC } SERVER server_name [ OPTIONS (...) ]
4060+
/// ```
4061+
/// Note: this is a PostgreSQL-specific statement.
4062+
/// <https://www.postgresql.org/docs/current/sql-createusermapping.html>
4063+
CreateUserMapping(CreateUserMapping),
4064+
/// ```sql
4065+
/// CREATE TABLESPACE name [ OWNER role ] LOCATION 'directory' [ WITH (options) ]
4066+
/// ```
4067+
/// Note: this is a PostgreSQL-specific statement.
4068+
/// <https://www.postgresql.org/docs/current/sql-createtablespace.html>
4069+
CreateTablespace(CreateTablespace),
4070+
/// ```sql
40524071
/// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
40534072
/// ```
40544073
/// Note: this is a PostgreSQL-specific statement.
@@ -5537,6 +5556,9 @@ impl fmt::Display for Statement {
55375556
Statement::CreateTextSearchTemplate(v) => write!(f, "{v}"),
55385557
Statement::CreatePublication(v) => write!(f, "{v}"),
55395558
Statement::CreateSubscription(v) => write!(f, "{v}"),
5559+
Statement::SecurityLabel(v) => write!(f, "{v}"),
5560+
Statement::CreateUserMapping(v) => write!(f, "{v}"),
5561+
Statement::CreateTablespace(v) => write!(f, "{v}"),
55405562
Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
55415563
Statement::DropOperator(drop_operator) => write!(f, "{drop_operator}"),
55425564
Statement::DropOperatorFamily(drop_operator_family) => {

src/ast/spans.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,9 @@ impl Spanned for Statement {
390390
Statement::CreateTextSearchTemplate(_) => Span::empty(),
391391
Statement::CreatePublication(_) => Span::empty(),
392392
Statement::CreateSubscription(_) => Span::empty(),
393+
Statement::SecurityLabel(_) => Span::empty(),
394+
Statement::CreateUserMapping(_) => Span::empty(),
395+
Statement::CreateTablespace(_) => Span::empty(),
393396
Statement::DropExtension(drop_extension) => drop_extension.span(),
394397
Statement::DropOperator(drop_operator) => drop_operator.span(),
395398
Statement::DropOperatorFamily(drop_operator_family) => drop_operator_family.span(),

src/keywords.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ define_keywords!(
567567
KEYS,
568568
KEY_BLOCK_SIZE,
569569
KILL,
570+
LABEL,
570571
LAG,
571572
LAMBDA,
572573
LANGUAGE,
@@ -616,6 +617,7 @@ define_keywords!(
616617
MANAGEDLOCATION,
617618
MANIFEST,
618619
MAP,
620+
MAPPING,
619621
MASKING,
620622
MATCH,
621623
MATCHED,

0 commit comments

Comments
 (0)