Skip to content

Commit 2e52d87

Browse files
committed
Adds support for pg CREATE EXTENSION
1 parent a75778c commit 2e52d87

File tree

4 files changed

+97
-0
lines changed

4 files changed

+97
-0
lines changed

src/ast/mod.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,6 +1763,21 @@ pub enum Statement {
17631763
query: Box<Query>,
17641764
},
17651765
/// ```sql
1766+
/// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
1767+
/// [ WITH ] [ SCHEMA schema_name ]
1768+
/// [ VERSION version ]
1769+
/// [ CASCADE ]
1770+
/// ```
1771+
///
1772+
/// Note: this is a PostgreSQL-specific statement,
1773+
CreateExtension {
1774+
name: Ident,
1775+
if_not_exists: bool,
1776+
cascade: bool,
1777+
schema: Option<Ident>,
1778+
version: Option<Ident>,
1779+
},
1780+
/// ```sql
17661781
/// FETCH
17671782
/// ```
17681783
/// Retrieve rows from a query using a cursor
@@ -3004,6 +3019,34 @@ impl fmt::Display for Statement {
30043019
}
30053020
Ok(())
30063021
}
3022+
Statement::CreateExtension {
3023+
name,
3024+
if_not_exists,
3025+
cascade,
3026+
schema,
3027+
version,
3028+
} => {
3029+
write!(
3030+
f,
3031+
"CREATE EXTENSION {if_not_exists}{name}",
3032+
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" }
3033+
)?;
3034+
if *cascade || schema.is_some() || version.is_some() {
3035+
write!(f, " WITH")?;
3036+
3037+
if let Some(name) = schema {
3038+
write!(f, " SCHEMA {name}")?;
3039+
}
3040+
if let Some(version) = version {
3041+
write!(f, " VERSION {version}")?;
3042+
}
3043+
if *cascade {
3044+
write!(f, " CASCADE")?;
3045+
}
3046+
}
3047+
3048+
Ok(())
3049+
}
30073050
Statement::CreateRole {
30083051
names,
30093052
if_not_exists,

src/keywords.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ define_keywords!(
270270
EXPLICIT,
271271
EXPORT,
272272
EXTENDED,
273+
EXTENSION,
273274
EXTERNAL,
274275
EXTRACT,
275276
FAIL,
@@ -705,6 +706,7 @@ define_keywords!(
705706
VAR_POP,
706707
VAR_SAMP,
707708
VERBOSE,
709+
VERSION,
708710
VERSIONING,
709711
VIEW,
710712
VIRTUAL,

src/parser/mod.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2970,6 +2970,8 @@ impl<'a> Parser<'a> {
29702970
"[EXTERNAL] TABLE or [MATERIALIZED] VIEW or FUNCTION after CREATE OR REPLACE",
29712971
self.peek_token(),
29722972
)
2973+
} else if self.parse_keyword(Keyword::EXTENSION) {
2974+
self.parse_create_extension()
29732975
} else if self.parse_keyword(Keyword::INDEX) {
29742976
self.parse_create_index(false)
29752977
} else if self.parse_keywords(&[Keyword::UNIQUE, Keyword::INDEX]) {
@@ -3988,6 +3990,39 @@ impl<'a> Parser<'a> {
39883990
})
39893991
}
39903992

3993+
pub fn parse_create_extension(&mut self) -> Result<Statement, ParserError> {
3994+
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
3995+
let name = self.parse_identifier()?;
3996+
3997+
let (schema, version, cascade) = if self.parse_keyword(Keyword::WITH) {
3998+
let schema = if self.parse_keyword(Keyword::SCHEMA) {
3999+
Some(self.parse_identifier()?)
4000+
} else {
4001+
None
4002+
};
4003+
4004+
let version = if self.parse_keyword(Keyword::VERSION) {
4005+
Some(self.parse_identifier()?)
4006+
} else {
4007+
None
4008+
};
4009+
4010+
let cascade = self.parse_keyword(Keyword::CASCADE);
4011+
4012+
(schema, version, cascade)
4013+
} else {
4014+
(None, None, false)
4015+
};
4016+
4017+
Ok(Statement::CreateExtension {
4018+
name,
4019+
if_not_exists,
4020+
schema,
4021+
version,
4022+
cascade,
4023+
})
4024+
}
4025+
39914026
//TODO: Implement parsing for Skewed and Clustered
39924027
pub fn parse_hive_distribution(&mut self) -> Result<HiveDistributionStyle, ParserError> {
39934028
if self.parse_keywords(&[Keyword::PARTITIONED, Keyword::BY]) {

tests/sqlparser_postgres.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,23 @@ fn parse_alter_table_enable() {
584584
pg_and_generic().verified_stmt("ALTER TABLE tab ENABLE TRIGGER USER");
585585
pg_and_generic().verified_stmt("ALTER TABLE tab ENABLE TRIGGER trigger_name");
586586
}
587+
588+
#[test]
589+
fn parse_create_extension() {
590+
pg_and_generic().verified_stmt("CREATE EXTENSION extension_name");
591+
pg_and_generic().verified_stmt("CREATE EXTENSION extension_name WITH SCHEMA schema_name");
592+
pg_and_generic().verified_stmt("CREATE EXTENSION extension_name WITH VERSION version");
593+
pg_and_generic().verified_stmt("CREATE EXTENSION extension_name WITH CASCADE");
594+
pg_and_generic().verified_stmt(
595+
"CREATE EXTENSION extension_name WITH SCHEMA schema_name VERSION version CASCADE",
596+
);
597+
pg_and_generic()
598+
.verified_stmt("CREATE EXTENSION extension_name WITH SCHEMA schema_name CASCADE");
599+
pg_and_generic().verified_stmt("CREATE EXTENSION extension_name WITH VERSION version CASCADE");
600+
pg_and_generic()
601+
.verified_stmt("CREATE EXTENSION extension_name WITH SCHEMA schema_name VERSION version");
602+
}
603+
587604
#[test]
588605
fn parse_alter_table_alter_column() {
589606
pg().one_statement_parses_to(

0 commit comments

Comments
 (0)