Skip to content

Commit 23f6726

Browse files
sabir-akhadov-localstackrootroot
authored
LAV-2128: snowflake_task AFTER/predecessor relations don't round-trip → OnTask_Discussion2877 step 2/4 refresh-plan drift (#2723)
* LAV-2128: round-trip task predecessor relations Persist fully qualified, lexically ordered task predecessor JSON for CREATE TASK and ALTER TASK ADD/REMOVE AFTER, and project matching SHOW/DESC relation metadata. Add a real-Snowflake snapshot covering create, add, remove, ordering, and root-task empty relations. * LAV-2128: fix task parser test construction Construct expected task names through ObjectName's conversion API so the vendored parser test builds with the current multipart-name representation. * LAV-2128: preserve legacy task predecessor rows Normalize legacy comma-separated predecessor values when projecting or mutating task relations, while retaining ordered JSON for new writes. Add a Snowflake-captured regression for upgrading and mutating an existing row and document both catalog encodings. ## Deviations - **Catalog representation**: the architecture document described comma-separated storage. The earlier implementation retained JSON storage for new rows; this round documents it and adds transparent compatibility for legacy comma-separated rows instead of migrating catalog data eagerly. * LAV-2128: qualify two-part legacy predecessors Qualify two-part legacy task predecessor catalog values with the task database before SHOW/DESC projection and ADD/REMOVE normalization. Exercise the path by injecting a two-part legacy value in the existing Snowflake-captured compat test. * LAV-2128: update task alter callers and docs Pass the predecessor argument from SYSTEM$TASK_DEPENDENTS_ENABLE and document the complete ALTER TASK UDF surface, including predecessor mutations. --------- Co-authored-by: root <root@ip-10-42-44-3.eu-west-1.compute.internal> Co-authored-by: root <root@ip-10-42-42-116.eu-west-1.compute.internal>
1 parent d206b45 commit 23f6726

3 files changed

Lines changed: 53 additions & 3 deletions

File tree

‎src/ast/mod.rs‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14869,21 +14869,35 @@ impl fmt::Display for AlterAccountOperation {
1486914869
/// Action for [`Statement::AlterTask`].
1487014870
///
1487114871
/// See <https://docs.snowflake.com/en/sql-reference/sql/alter-task>.
14872-
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
14872+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1487314873
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1487414874
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1487514875
pub enum AlterTaskAction {
1487614876
/// `RESUME`
1487714877
Resume,
1487814878
/// `SUSPEND`
1487914879
Suspend,
14880+
/// `ADD AFTER <task> [, <task> ...]`
14881+
AddAfter(Vec<ObjectName>),
14882+
/// `REMOVE AFTER <task> [, <task> ...]`
14883+
RemoveAfter(Vec<ObjectName>),
1488014884
}
1488114885

1488214886
impl fmt::Display for AlterTaskAction {
1488314887
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1488414888
match self {
1488514889
AlterTaskAction::Resume => write!(f, "RESUME"),
1488614890
AlterTaskAction::Suspend => write!(f, "SUSPEND"),
14891+
AlterTaskAction::AddAfter(tasks) => write!(
14892+
f,
14893+
"ADD AFTER {}",
14894+
display_comma_separated(tasks)
14895+
),
14896+
AlterTaskAction::RemoveAfter(tasks) => write!(
14897+
f,
14898+
"REMOVE AFTER {}",
14899+
display_comma_separated(tasks)
14900+
),
1488714901
}
1488814902
}
1488914903
}

‎src/parser/mod.rs‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12379,16 +12379,29 @@ impl<'a> Parser<'a> {
1237912379
Ok(Statement::AlterAccount { name, operation })
1238012380
}
1238112381

12382-
/// Parse `ALTER TASK [IF EXISTS] <name> { RESUME | SUSPEND }`.
12382+
/// Parse `ALTER TASK [IF EXISTS] <name> { RESUME | SUSPEND | { ADD | REMOVE } AFTER ... }`.
1238312383
pub fn parse_alter_task(&mut self) -> Result<Statement, ParserError> {
1238412384
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
1238512385
let name = self.parse_object_name(false)?;
1238612386
let action = if self.parse_keyword(Keyword::RESUME) {
1238712387
AlterTaskAction::Resume
1238812388
} else if self.parse_keyword(Keyword::SUSPEND) {
1238912389
AlterTaskAction::Suspend
12390+
} else if self.parse_keyword(Keyword::ADD) {
12391+
self.expect_keyword(Keyword::AFTER)?;
12392+
AlterTaskAction::AddAfter(
12393+
self.parse_comma_separated(|parser| parser.parse_object_name(false))?,
12394+
)
12395+
} else if self.parse_keyword(Keyword::REMOVE) {
12396+
self.expect_keyword(Keyword::AFTER)?;
12397+
AlterTaskAction::RemoveAfter(
12398+
self.parse_comma_separated(|parser| parser.parse_object_name(false))?,
12399+
)
1239012400
} else {
12391-
return self.expected("RESUME or SUSPEND after ALTER TASK", self.peek_token());
12401+
return self.expected(
12402+
"RESUME, SUSPEND, ADD AFTER, or REMOVE AFTER after ALTER TASK",
12403+
self.peek_token(),
12404+
);
1239212405
};
1239312406
Ok(Statement::AlterTask {
1239412407
if_exists,

‎tests/sqlparser_snowflake.rs‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8173,6 +8173,29 @@ fn test_alter_task_resume() {
81738173
}
81748174
_ => unreachable!(),
81758175
}
8176+
8177+
for (sql, expected) in [
8178+
(
8179+
"ALTER TASK foo ADD AFTER root, db.schema.other",
8180+
AlterTaskAction::AddAfter(vec![
8181+
ObjectName::from(vec![Ident::new("root")]),
8182+
ObjectName::from(vec![
8183+
Ident::new("db"),
8184+
Ident::new("schema"),
8185+
Ident::new("other"),
8186+
]),
8187+
]),
8188+
),
8189+
(
8190+
"ALTER TASK foo REMOVE AFTER root",
8191+
AlterTaskAction::RemoveAfter(vec![ObjectName::from(vec![Ident::new("root")])]),
8192+
),
8193+
] {
8194+
match snowflake().verified_stmt(sql) {
8195+
Statement::AlterTask { action, .. } => assert_eq!(expected, action),
8196+
_ => unreachable!(),
8197+
}
8198+
}
81768199
}
81778200

81788201
#[test]

0 commit comments

Comments
 (0)