Skip to content

Commit 1108ae0

Browse files
localstack-spiral[bot]spiralsabir-akhadov-localstack
authored
LAV-2521: Support CREATE STREAM … CLONE (#2957)
* LAV-2521: support cloning streams Co-authored-by: Sabir Akhadov <sabir.akhadov@localstack.cloud> * LAV-2521: complete stream clone parity Assign clone ownership to the executing role and cover reverse drop independence plus AT/BEFORE STREAM suffix rejection with Cloud snapshots. Co-authored-by: Sabir Akhadov <sabir.akhadov@localstack.cloud> * LAV-2521: use snapshot runner for clone errors Co-authored-by: Sabir Akhadov <sabir.akhadov@localstack.cloud> * LAV-2521: record clone errors with snapshot runner Recapture the clone error envelopes through run_snapshot_test and strip transport-only source-location fields that the emulator does not emit. Co-authored-by: Sabir Akhadov <sabir.akhadov@localstack.cloud> --------- Co-authored-by: spiral <spiral@localhost> Co-authored-by: Sabir Akhadov <sabir.akhadov@localstack.cloud>
1 parent a05d939 commit 1108ae0

2 files changed

Lines changed: 18 additions & 5 deletions

File tree

‎src/ast/mod.rs‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5084,6 +5084,8 @@ pub enum Statement {
50845084
if_not_exists: bool,
50855085
/// Stream name.
50865086
name: ObjectName,
5087+
/// Whether this is `CREATE STREAM <name> CLONE <source>`.
5088+
clone: bool,
50875089
/// Whether the source is a table (`ON TABLE`) or a view (`ON VIEW`).
50885090
source_kind: StreamSourceKind,
50895091
/// The source object the stream tracks (the `<source>` after
@@ -8539,14 +8541,20 @@ impl fmt::Display for Statement {
85398541
or_replace,
85408542
if_not_exists,
85418543
name,
8544+
clone,
85428545
source_kind,
85438546
source_table,
85448547
at_before,
85458548
append_only,
85468549
} => {
8550+
let source_prefix = if *clone {
8551+
"CLONE ".to_string()
8552+
} else {
8553+
format!("ON {source_kind} ")
8554+
};
85478555
write!(
85488556
f,
8549-
"CREATE {or_replace}STREAM {if_not_exists}{name} ON {source_kind} {source_table}",
8557+
"CREATE {or_replace}STREAM {if_not_exists}{name} {source_prefix}{source_table}",
85508558
or_replace = if *or_replace { "OR REPLACE " } else { "" },
85518559
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
85528560
)?;

‎src/parser/mod.rs‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5705,12 +5705,16 @@ impl<'a> Parser<'a> {
57055705
fn parse_create_stream(&mut self, or_replace: bool) -> Result<Statement, ParserError> {
57065706
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
57075707
let name = self.parse_object_name(false)?;
5708-
self.expect_keyword(Keyword::ON)?;
5709-
let source_kind = if self.parse_keyword(Keyword::VIEW) {
5708+
let clone = self.parse_keyword(Keyword::CLONE);
5709+
if !clone {
5710+
self.expect_keyword(Keyword::ON)?;
5711+
}
5712+
let source_kind = if clone || self.parse_keyword(Keyword::TABLE) {
5713+
StreamSourceKind::Table
5714+
} else if self.parse_keyword(Keyword::VIEW) {
57105715
StreamSourceKind::View
57115716
} else {
5712-
self.expect_keyword(Keyword::TABLE)?;
5713-
StreamSourceKind::Table
5717+
return self.expected("TABLE or VIEW", self.peek_token());
57145718
};
57155719
let source_table = self.parse_object_name(false)?;
57165720
// Optional `{ AT | BEFORE } ( <key> => <expr> )` clause, kept whole as
@@ -5739,6 +5743,7 @@ impl<'a> Parser<'a> {
57395743
or_replace,
57405744
if_not_exists,
57415745
name,
5746+
clone,
57425747
source_kind,
57435748
source_table,
57445749
at_before,

0 commit comments

Comments
 (0)