Support BigQuery MERGE syntax (#1217)

This commit is contained in:
Ifeanyi Ubah 2024-04-26 20:00:54 +02:00 committed by GitHub
parent b51f2a0c25
commit 0adf4c675c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 556 additions and 142 deletions

View file

@ -7475,19 +7475,32 @@ fn parse_merge() {
assert_eq!(
clauses,
vec![
MergeClause::NotMatched {
MergeClause {
clause_kind: MergeClauseKind::NotMatched,
predicate: None,
columns: vec![Ident::new("A"), Ident::new("B"), Ident::new("C")],
values: Values {
explicit_row: false,
rows: vec![vec![
Expr::CompoundIdentifier(vec![Ident::new("stg"), Ident::new("A")]),
Expr::CompoundIdentifier(vec![Ident::new("stg"), Ident::new("B")]),
Expr::CompoundIdentifier(vec![Ident::new("stg"), Ident::new("C")]),
]]
},
action: MergeAction::Insert(MergeInsertExpr {
columns: vec![Ident::new("A"), Ident::new("B"), Ident::new("C")],
kind: MergeInsertKind::Values(Values {
explicit_row: false,
rows: vec![vec![
Expr::CompoundIdentifier(vec![
Ident::new("stg"),
Ident::new("A")
]),
Expr::CompoundIdentifier(vec![
Ident::new("stg"),
Ident::new("B")
]),
Expr::CompoundIdentifier(vec![
Ident::new("stg"),
Ident::new("C")
]),
]]
}),
}),
},
MergeClause::MatchedUpdate {
MergeClause {
clause_kind: MergeClauseKind::Matched,
predicate: Some(Expr::BinaryOp {
left: Box::new(Expr::CompoundIdentifier(vec![
Ident::new("dest"),
@ -7498,30 +7511,39 @@ fn parse_merge() {
"a".to_string()
))),
}),
assignments: vec![
Assignment {
id: vec![Ident::new("dest"), Ident::new("F")],
value: Expr::CompoundIdentifier(vec![
Ident::new("stg"),
Ident::new("F"),
]),
},
Assignment {
id: vec![Ident::new("dest"), Ident::new("G")],
value: Expr::CompoundIdentifier(vec![
Ident::new("stg"),
Ident::new("G"),
]),
},
],
action: MergeAction::Update {
assignments: vec![
Assignment {
id: vec![Ident::new("dest"), Ident::new("F")],
value: Expr::CompoundIdentifier(vec![
Ident::new("stg"),
Ident::new("F"),
]),
},
Assignment {
id: vec![Ident::new("dest"), Ident::new("G")],
value: Expr::CompoundIdentifier(vec![
Ident::new("stg"),
Ident::new("G"),
]),
},
],
},
},
MergeClause {
clause_kind: MergeClauseKind::Matched,
predicate: None,
action: MergeAction::Delete,
},
MergeClause::MatchedDelete(None),
]
);
assert_eq!(clauses, clauses_no_into);
}
_ => unreachable!(),
}
};
let sql = "MERGE INTO s.bar AS dest USING newArrivals AS S ON false WHEN NOT MATCHED THEN INSERT VALUES (stg.A, stg.B, stg.C)";
verified_stmt(sql);
}
#[test]
@ -7551,6 +7573,31 @@ fn test_merge_with_delimiter() {
}
}
#[test]
fn test_merge_invalid_statements() {
let dialects = all_dialects();
for (sql, err_msg) in [
(
"MERGE INTO T USING U ON TRUE WHEN NOT MATCHED THEN UPDATE SET a = b",
"UPDATE is not allowed in a NOT MATCHED merge clause",
),
(
"MERGE INTO T USING U ON TRUE WHEN NOT MATCHED THEN DELETE",
"DELETE is not allowed in a NOT MATCHED merge clause",
),
(
"MERGE INTO T USING U ON TRUE WHEN MATCHED THEN INSERT(a) VALUES(b)",
"INSERT is not allowed in a MATCHED merge clause",
),
] {
let res = dialects.parse_sql_statements(sql);
assert_eq!(
ParserError::ParserError(err_msg.to_string()),
res.unwrap_err()
);
}
}
#[test]
fn test_lock() {
let sql = "SELECT * FROM student WHERE id = '1' FOR UPDATE";