Skip to content

Commit 88efe5a

Browse files
Merge main
2 parents 7279c43 + e11127e commit 88efe5a

5 files changed

Lines changed: 111 additions & 10 deletions

File tree

‎src/ast/ddl.rs‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5076,11 +5076,16 @@ impl fmt::Display for AlterDomain {
50765076
}
50775077
}
50785078

5079-
/// `ALTER VIEW` statement.
5079+
/// `ALTER [ MATERIALIZED ] VIEW` statement.
5080+
///
5081+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-altermaterializedview.html)
50805082
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
50815083
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
50825084
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
50835085
pub struct AlterView {
5086+
/// Whether `MATERIALIZED` was specified. A materialized view's operation is never
5087+
/// [`AlterViewOperation::As`] or [`AlterViewOperation::AlterColumn`].
5088+
pub materialized: bool,
50845089
/// View name being altered.
50855090
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
50865091
pub name: ObjectName,
@@ -5204,7 +5209,11 @@ impl fmt::Display for AlterViewOperation {
52045209

52055210
impl fmt::Display for AlterView {
52065211
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5207-
write!(f, "ALTER VIEW ")?;
5212+
write!(f, "ALTER ")?;
5213+
if self.materialized {
5214+
write!(f, "MATERIALIZED ")?;
5215+
}
5216+
write!(f, "VIEW ")?;
52085217
if self.if_exists {
52095218
write!(f, "IF EXISTS ")?;
52105219
}

‎src/ast/mod.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3922,7 +3922,7 @@ pub enum Statement {
39223922
operation: AlterIndexOperation,
39233923
},
39243924
/// ```sql
3925-
/// ALTER VIEW
3925+
/// ALTER [ MATERIALIZED ] VIEW
39263926
/// ```
39273927
AlterView(AlterView),
39283928
/// ```sql

‎src/parser/mod.rs‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11935,7 +11935,11 @@ impl<'a> Parser<'a> {
1193511935
self.prev_token();
1193611936
self.parse_alter_schema()
1193711937
}
11938-
Keyword::VIEW => self.parse_alter_view(),
11938+
Keyword::VIEW => self.parse_alter_view(false),
11939+
Keyword::MATERIALIZED => {
11940+
self.expect_keyword_is(Keyword::VIEW)?;
11941+
self.parse_alter_view(true)
11942+
}
1193911943
Keyword::TYPE => self.parse_alter_type(),
1194011944
Keyword::COLLATION => self.parse_alter_collation().map(Into::into),
1194111945
Keyword::DOMAIN => self.parse_alter_domain().map(Into::into),
@@ -11988,7 +11992,7 @@ impl<'a> Parser<'a> {
1198811992
_ => {
1198911993
self.index = index;
1199011994
self.expected_ref(
11991-
"one of VIEW or TYPE or COLLATION or DOMAIN or TABLE or INDEX or FUNCTION or AGGREGATE or ROLE or POLICY or TRIGGER or CONNECTOR or ICEBERG or FOREIGN TABLE or SCHEMA or USER or OPERATOR",
11995+
"one of VIEW or MATERIALIZED VIEW or TYPE or COLLATION or DOMAIN or TABLE or INDEX or FUNCTION or AGGREGATE or ROLE or POLICY or TRIGGER or CONNECTOR or ICEBERG or FOREIGN TABLE or SCHEMA or USER or OPERATOR",
1199211996
self.peek_token_ref(),
1199311997
)
1199411998
}
@@ -12266,8 +12270,8 @@ impl<'a> Parser<'a> {
1226612270
.into())
1226712271
}
1226812272

12269-
/// Parse an `ALTER VIEW` statement.
12270-
pub fn parse_alter_view(&mut self) -> Result<Statement, ParserError> {
12273+
/// Parse an `ALTER [ MATERIALIZED ] VIEW` statement.
12274+
pub fn parse_alter_view(&mut self, materialized: bool) -> Result<Statement, ParserError> {
1227112275
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
1227212276
let name = self.parse_object_name(false)?;
1227312277

@@ -12337,6 +12341,7 @@ impl<'a> Parser<'a> {
1233712341
};
1233812342

1233912343
Ok(AlterView {
12344+
materialized,
1234012345
name,
1234112346
if_exists,
1234212347
operation,

‎tests/sqlparser_common.rs‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5669,6 +5669,7 @@ fn parse_alter_view() {
56695669
let sql = "ALTER VIEW myschema.myview AS SELECT foo FROM bar";
56705670
match verified_stmt(sql) {
56715671
Statement::AlterView(AlterView {
5672+
materialized: false,
56725673
name,
56735674
if_exists,
56745675
operation:
@@ -5723,6 +5724,7 @@ fn parse_alter_view_with_columns() {
57235724
let sql = "ALTER VIEW v (has, cols) AS SELECT 1, 2";
57245725
match verified_stmt(sql) {
57255726
Statement::AlterView(AlterView {
5727+
materialized: false,
57265728
name,
57275729
if_exists,
57285730
operation:
@@ -5752,6 +5754,7 @@ fn parse_alter_view_operations() {
57525754
assert_eq!(
57535755
verified_stmt("ALTER VIEW IF EXISTS s.v OWNER TO o"),
57545756
Statement::AlterView(AlterView {
5757+
materialized: false,
57555758
name: ObjectName::from(vec![Ident::new("s"), Ident::new("v")]),
57565759
if_exists: true,
57575760
operation: AlterViewOperation::OwnerTo(Owner::Ident(Ident::new("o"))),
@@ -5902,7 +5905,7 @@ fn display_alter_view_propagates_write_errors() {
59025905
}
59035906

59045907
let with_options = verified_stmt("ALTER VIEW IF EXISTS v WITH (x = 1) AS SELECT 1");
5905-
for rejected in ["ALTER VIEW ", "IF EXISTS ", "WITH ("] {
5908+
for rejected in ["ALTER ", "VIEW ", "IF EXISTS ", "WITH ("] {
59065909
let mut writer = RejectingWriter(rejected);
59075910
assert_eq!(
59085911
write!(writer, "{with_options}"),
@@ -5912,7 +5915,7 @@ fn display_alter_view_propagates_write_errors() {
59125915
}
59135916

59145917
let columns = verified_stmt("ALTER VIEW IF EXISTS v (zeta) AS SELECT 1");
5915-
for rejected in ["ALTER VIEW ", "IF EXISTS ", "("] {
5918+
for rejected in ["ALTER ", "VIEW ", "IF EXISTS ", "("] {
59165919
let mut writer = RejectingWriter(rejected);
59175920
assert_eq!(write!(writer, "{columns}"), Err(fmt::Error), "{rejected:?}");
59185921
}
@@ -16193,7 +16196,7 @@ fn parse_alter_trigger_spans() {
1619316196

1619416197
#[test]
1619516198
fn parse_alter_rejects_missing_or_unknown_object_type() {
16196-
let objects = "one of VIEW or TYPE or COLLATION or DOMAIN or TABLE or INDEX or FUNCTION or AGGREGATE or ROLE or POLICY or TRIGGER or CONNECTOR or ICEBERG or FOREIGN TABLE or SCHEMA or USER or OPERATOR";
16199+
let objects = "one of VIEW or MATERIALIZED VIEW or TYPE or COLLATION or DOMAIN or TABLE or INDEX or FUNCTION or AGGREGATE or ROLE or POLICY or TRIGGER or CONNECTOR or ICEBERG or FOREIGN TABLE or SCHEMA or USER or OPERATOR";
1619716200
for (sql, found) in [
1619816201
("ALTER", "EOF"),
1619916202
("ALTER 1", "1"),

‎tests/sqlparser_postgres.rs‎

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12774,6 +12774,90 @@ fn parse_alter_foreign_table_rejects_clauses() {
1277412774
}
1277512775
}
1277612776

12777+
#[test]
12778+
fn parse_alter_materialized_view() {
12779+
assert_eq!(
12780+
pg_and_generic().verified_stmt("ALTER MATERIALIZED VIEW IF EXISTS s.m OWNER TO alice"),
12781+
Statement::AlterView(AlterView {
12782+
materialized: true,
12783+
name: ObjectName::from(vec![Ident::new("s"), Ident::new("m")]),
12784+
if_exists: true,
12785+
operation: AlterViewOperation::OwnerTo(Owner::Ident(Ident::new("alice"))),
12786+
})
12787+
);
12788+
assert_eq!(
12789+
pg_and_generic().verified_stmt("ALTER MATERIALIZED VIEW m SET (fillfactor = 70)"),
12790+
Statement::AlterView(AlterView {
12791+
materialized: true,
12792+
name: ObjectName::from(vec![Ident::new("m")]),
12793+
if_exists: false,
12794+
operation: AlterViewOperation::SetOptions {
12795+
options: vec![SqlOption::KeyValue {
12796+
key: ObjectName::from(vec![Ident::new("fillfactor")]),
12797+
value: Expr::value(number("70")),
12798+
}],
12799+
},
12800+
})
12801+
);
12802+
for sql in [
12803+
"ALTER MATERIALIZED VIEW m RESET (fillfactor, autovacuum_enabled)",
12804+
"ALTER MATERIALIZED VIEW m RENAME TO m2",
12805+
"ALTER MATERIALIZED VIEW m RENAME COLUMN a TO b",
12806+
"ALTER MATERIALIZED VIEW m SET SCHEMA s",
12807+
] {
12808+
pg_and_generic().verified_stmt(sql);
12809+
}
12810+
assert_eq!(
12811+
pg_and_generic().verified_stmt("ALTER MATERIALIZED VIEW m ALTER COLUMN c SET DEFAULT 1"),
12812+
Statement::AlterView(AlterView {
12813+
materialized: true,
12814+
name: ObjectName::from(vec![Ident::new("m")]),
12815+
if_exists: false,
12816+
operation: AlterViewOperation::AlterColumn {
12817+
column_name: Ident::new("c"),
12818+
op: AlterColumnOperation::SetDefault {
12819+
value: Expr::value(number("1")),
12820+
},
12821+
},
12822+
})
12823+
);
12824+
pg_and_generic().verified_stmt("ALTER MATERIALIZED VIEW m ALTER COLUMN c DROP DEFAULT");
12825+
12826+
assert_eq!(
12827+
pg_and_generic()
12828+
.parse_sql_statements("ALTER MATERIALIZED m OWNER TO alice")
12829+
.unwrap_err(),
12830+
ParserError::ParserError("Expected: VIEW, found: m".to_string())
12831+
);
12832+
}
12833+
12834+
#[test]
12835+
fn display_alter_materialized_view_propagates_write_errors() {
12836+
use core::fmt::{self, Write};
12837+
12838+
struct RejectingWriter(&'static str);
12839+
12840+
impl Write for RejectingWriter {
12841+
fn write_str(&mut self, value: &str) -> fmt::Result {
12842+
if value == self.0 {
12843+
Err(fmt::Error)
12844+
} else {
12845+
Ok(())
12846+
}
12847+
}
12848+
}
12849+
12850+
let materialized = pg_and_generic().verified_stmt("ALTER MATERIALIZED VIEW m RENAME TO m2");
12851+
for rejected in ["ALTER ", "MATERIALIZED ", "VIEW "] {
12852+
let mut writer = RejectingWriter(rejected);
12853+
assert_eq!(
12854+
write!(writer, "{materialized}"),
12855+
Err(fmt::Error),
12856+
"{rejected:?}"
12857+
);
12858+
}
12859+
}
12860+
1277712861
#[test]
1277812862
fn parse_alter_domain() {
1277912863
let ident = |name: &str| Ident::new(name);

0 commit comments

Comments
 (0)