Skip to content

Commit 0916d91

Browse files
wojpadloWojciech Padłoclaude
authored
Task LAV-3305: Streamlit RENAME and UNDROP (#3697)
* Task LAV-3302: STREAMLIT catalog object — CREATE (FROM / ROOT_LOCATION forms), DROP, GRANT/REVOKE Metadata-only schema-level STREAMLIT: parser support for both CREATE forms and DROP [IF EXISTS], a store table persisting every documented property plus a generated url_id, stage / MAIN_FILE validation, creator OWNERSHIP and future grants on create, grant object-kind wiring (USAGE/MONITOR/EMBED/ALL, ON ALL row counting, OWNERSHIP 391811, invalid privilege 003008). 090106 is emitted bare, per the recorded snapshot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Task LAV-3305: ALTER STREAMLIT RENAME TO and UNDROP STREAMLIT Rename moves the store row (url_id, created_at, properties kept) and its grants; UNDROP restores the newest dropped generation plus the grants its DROP soft-deleted. Stacked on LAV-3302's Streamlit catalog commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * task LAV-3305: fix CI — resource-index site tests no longer sample a live only-xfail clause Implementing CREATE STREAMLIT ... ROOT_LOCATION scored the clause supported, breaking the live-site sample LAV-3295 had just moved there. No parameter cell in the repo is only-xfail any more, so pin the st-only-xfail rendering in the synthetic syntax and parameter render tests instead of chasing a live sample each time a feature lands. Scoring of ONLY_XFAIL stays covered by test_syntax_support.py / test_syntax_parameters.py. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Wojciech Padło <wojciech.padlo@localstack.cloud> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent dfc812e commit 0916d91

4 files changed

Lines changed: 63 additions & 2 deletions

File tree

‎src/ast/mod.rs‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6228,6 +6228,17 @@ pub enum Statement {
62286228
options: Vec<SqlOption>,
62296229
},
62306230
/// ```sql
6231+
/// ALTER STREAMLIT [ IF EXISTS ] <name> RENAME TO <new_name>
6232+
/// ```
6233+
AlterStreamlit {
6234+
/// `IF EXISTS` flag.
6235+
if_exists: bool,
6236+
/// Streamlit name.
6237+
name: ObjectName,
6238+
/// The alter operation.
6239+
operation: AlterStreamlitOperation,
6240+
},
6241+
/// ```sql
62316242
/// DROP STREAMLIT [ IF EXISTS ] <name>
62326243
/// ```
62336244
DropStreamlit {
@@ -9839,6 +9850,15 @@ impl fmt::Display for Statement {
98399850
}
98409851
Ok(())
98419852
}
9853+
Statement::AlterStreamlit {
9854+
if_exists,
9855+
name,
9856+
operation,
9857+
} => write!(
9858+
f,
9859+
"ALTER STREAMLIT {if_exists}{name} {operation}",
9860+
if_exists = if *if_exists { "IF EXISTS " } else { "" },
9861+
),
98429862
Statement::DropStreamlit { if_exists, name } => {
98439863
write!(
98449864
f,
@@ -12942,6 +12962,9 @@ pub enum ObjectType {
1294212962
/// An alert (Snowflake).
1294312963
/// <https://docs.snowflake.com/en/sql-reference/sql/drop-alert>
1294412964
Alert,
12965+
/// A Streamlit app (Snowflake).
12966+
/// <https://docs.snowflake.com/en/sql-reference/sql/undrop-streamlit>
12967+
Streamlit,
1294512968
}
1294612969

1294712970
impl fmt::Display for ObjectType {
@@ -12967,6 +12990,7 @@ impl fmt::Display for ObjectType {
1296712990
ObjectType::Task => "TASK",
1296812991
ObjectType::Pipe => "PIPE",
1296912992
ObjectType::Alert => "ALERT",
12993+
ObjectType::Streamlit => "STREAMLIT",
1297012994
})
1297112995
}
1297212996
}
@@ -15691,6 +15715,23 @@ impl fmt::Display for AlterExternalVolumeOperation {
1569115715
}
1569215716
}
1569315717

15718+
/// Operations for `ALTER STREAMLIT`.
15719+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
15720+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15721+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
15722+
pub enum AlterStreamlitOperation {
15723+
/// `RENAME TO <new_name>`
15724+
RenameTo(ObjectName),
15725+
}
15726+
15727+
impl fmt::Display for AlterStreamlitOperation {
15728+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15729+
match self {
15730+
AlterStreamlitOperation::RenameTo(name) => write!(f, "RENAME TO {name}"),
15731+
}
15732+
}
15733+
}
15734+
1569415735
/// Operations for `ALTER FILE FORMAT`.
1569515736
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1569615737
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]

‎src/ast/spans.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ impl Spanned for Statement {
635635
Statement::DropSnowflakeSecret { .. } => Span::empty(),
636636
Statement::CreateStreamlit { .. } => Span::empty(),
637637
Statement::DropStreamlit { .. } => Span::empty(),
638+
Statement::AlterStreamlit { .. } => Span::empty(),
638639
Statement::DescribeSnowflakeSecret { .. } => Span::empty(),
639640
Statement::ShowSnowflakeSecrets { .. } => Span::empty(),
640641
Statement::CreateSnowflakeIndex { .. } => Span::empty(),

‎src/dialect/snowflake.rs‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use crate::ast::helpers::stmt_data_loading::{
2929
use crate::ast::{
3030
visit_expressions,
3131
AlterAlertOperation, AlterBackupPolicyOperation, AlterColumnOperation,
32-
AlterExternalVolumeOperation, AlterFileFormatOperation, AlterMaskingPolicyOperation,
32+
AlterExternalVolumeOperation, AlterFileFormatOperation, AlterStreamlitOperation, AlterMaskingPolicyOperation,
3333
AlterAuthenticationPolicyOperation, AlterDatabaseRoleOperation, AlterNetworkRuleOperation,
3434
AlterPasswordPolicyOperation, AlterRoleOperation, AlterSemanticViewOperation,
3535
AlterSessionPolicyOperation, AlterSnowflakeSecretOperation,
@@ -245,6 +245,10 @@ impl SnowflakeDialect {
245245
return Some(parse_alter_procedure(parser));
246246
}
247247

248+
if parser.parse_keywords(&[Keyword::ALTER, Keyword::STREAMLIT]) {
249+
return Some(parse_alter_streamlit(parser));
250+
}
251+
248252
if parser.parse_keywords(&[Keyword::ALTER, Keyword::FILE, Keyword::FORMAT]) {
249253
// ALTER FILE FORMAT
250254
return Some(parse_alter_file_format(parser));
@@ -6231,6 +6235,19 @@ fn parse_create_streamlit(or_replace: bool, parser: &mut Parser) -> Result<State
62316235
})
62326236
}
62336237

6238+
/// Parse `ALTER STREAMLIT [IF EXISTS] <name> RENAME TO <new_name>`.
6239+
fn parse_alter_streamlit(parser: &mut Parser) -> Result<Statement, ParserError> {
6240+
let if_exists = parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
6241+
let name = parser.parse_object_name(false)?;
6242+
parser.expect_keywords(&[Keyword::RENAME, Keyword::TO])?;
6243+
let operation = AlterStreamlitOperation::RenameTo(parser.parse_object_name(false)?);
6244+
Ok(Statement::AlterStreamlit {
6245+
if_exists,
6246+
name,
6247+
operation,
6248+
})
6249+
}
6250+
62346251
/// Parse `DROP STREAMLIT [IF EXISTS] <name>`.
62356252
fn parse_drop_streamlit(parser: &mut Parser) -> Result<Statement, ParserError> {
62366253
let if_exists = parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);

‎src/parser/mod.rs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8712,9 +8712,11 @@ impl<'a> Parser<'a> {
87128712
ObjectType::Alert
87138713
} else if self.parse_keyword(Keyword::STAGE) {
87148714
ObjectType::Stage
8715+
} else if self.parse_keyword(Keyword::STREAMLIT) {
8716+
ObjectType::Streamlit
87158717
} else {
87168718
return self.expected_ref(
8717-
"ACCOUNT, ALERT, DATABASE, DYNAMIC TABLE, SCHEMA, STAGE, TABLE or VIEW after UNDROP",
8719+
"ACCOUNT, ALERT, DATABASE, DYNAMIC TABLE, SCHEMA, STAGE, STREAMLIT, TABLE or VIEW after UNDROP",
87188720
self.peek_token_ref(),
87198721
);
87208722
};

0 commit comments

Comments
 (0)