mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-22 23:14:07 +00:00
update on conflict method (#735)
This commit is contained in:
parent
a422116b89
commit
042effdf14
3 changed files with 94 additions and 18 deletions
|
@ -2702,7 +2702,16 @@ pub struct OnConflict {
|
|||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum OnConflictAction {
|
||||
DoNothing,
|
||||
DoUpdate(Vec<Assignment>),
|
||||
DoUpdate(DoUpdate),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub struct DoUpdate {
|
||||
/// Column assignments
|
||||
pub assignments: Vec<Assignment>,
|
||||
/// WHERE
|
||||
pub selection: Option<Expr>,
|
||||
}
|
||||
|
||||
impl fmt::Display for OnInsert {
|
||||
|
@ -2730,7 +2739,20 @@ impl fmt::Display for OnConflictAction {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::DoNothing => write!(f, "DO NOTHING"),
|
||||
Self::DoUpdate(a) => write!(f, "DO UPDATE SET {}", display_comma_separated(a)),
|
||||
Self::DoUpdate(do_update) => {
|
||||
write!(f, "DO UPDATE")?;
|
||||
if !do_update.assignments.is_empty() {
|
||||
write!(
|
||||
f,
|
||||
" SET {}",
|
||||
display_comma_separated(&do_update.assignments)
|
||||
)?;
|
||||
}
|
||||
if let Some(selection) = &do_update.selection {
|
||||
write!(f, " WHERE {}", selection)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5351,8 +5351,16 @@ impl<'a> Parser<'a> {
|
|||
} else {
|
||||
self.expect_keyword(Keyword::UPDATE)?;
|
||||
self.expect_keyword(Keyword::SET)?;
|
||||
let l = self.parse_comma_separated(Parser::parse_assignment)?;
|
||||
OnConflictAction::DoUpdate(l)
|
||||
let assignments = self.parse_comma_separated(Parser::parse_assignment)?;
|
||||
let selection = if self.parse_keyword(Keyword::WHERE) {
|
||||
Some(self.parse_expr()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
OnConflictAction::DoUpdate(DoUpdate {
|
||||
assignments,
|
||||
selection,
|
||||
})
|
||||
};
|
||||
|
||||
Some(OnInsert::OnConflict(OnConflict {
|
||||
|
|
|
@ -1117,10 +1117,13 @@ fn parse_pg_on_conflict() {
|
|||
} => {
|
||||
assert_eq!(vec![Ident::from("did")], conflict_target);
|
||||
assert_eq!(
|
||||
OnConflictAction::DoUpdate(vec![Assignment {
|
||||
OnConflictAction::DoUpdate(DoUpdate {
|
||||
assignments: vec![Assignment {
|
||||
id: vec!["dname".into()],
|
||||
value: Expr::CompoundIdentifier(vec!["EXCLUDED".into(), "dname".into()])
|
||||
},]),
|
||||
},],
|
||||
selection: None
|
||||
}),
|
||||
action
|
||||
);
|
||||
}
|
||||
|
@ -1147,16 +1150,22 @@ fn parse_pg_on_conflict() {
|
|||
conflict_target
|
||||
);
|
||||
assert_eq!(
|
||||
OnConflictAction::DoUpdate(vec![
|
||||
OnConflictAction::DoUpdate(DoUpdate {
|
||||
assignments: vec![
|
||||
Assignment {
|
||||
id: vec!["dname".into()],
|
||||
value: Expr::CompoundIdentifier(vec!["EXCLUDED".into(), "dname".into()])
|
||||
value: Expr::CompoundIdentifier(vec![
|
||||
"EXCLUDED".into(),
|
||||
"dname".into()
|
||||
])
|
||||
},
|
||||
Assignment {
|
||||
id: vec!["area".into()],
|
||||
value: Expr::CompoundIdentifier(vec!["EXCLUDED".into(), "area".into()])
|
||||
},
|
||||
]),
|
||||
],
|
||||
selection: None
|
||||
}),
|
||||
action
|
||||
);
|
||||
}
|
||||
|
@ -1182,6 +1191,43 @@ fn parse_pg_on_conflict() {
|
|||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let stmt = pg_and_generic().verified_stmt(
|
||||
"INSERT INTO distributors (did, dname, dsize) \
|
||||
VALUES (5, 'Gizmo Transglobal', 1000), (6, 'Associated Computing, Inc', 1010) \
|
||||
ON CONFLICT(did) \
|
||||
DO UPDATE SET dname = $1 WHERE dsize > $2",
|
||||
);
|
||||
match stmt {
|
||||
Statement::Insert {
|
||||
on:
|
||||
Some(OnInsert::OnConflict(OnConflict {
|
||||
conflict_target,
|
||||
action,
|
||||
})),
|
||||
..
|
||||
} => {
|
||||
assert_eq!(vec![Ident::from("did")], conflict_target);
|
||||
assert_eq!(
|
||||
OnConflictAction::DoUpdate(DoUpdate {
|
||||
assignments: vec![Assignment {
|
||||
id: vec!["dname".into()],
|
||||
value: Expr::Value(Value::Placeholder("$1".to_string()))
|
||||
},],
|
||||
selection: Some(Expr::BinaryOp {
|
||||
left: Box::new(Expr::Identifier(Ident {
|
||||
value: "dsize".to_string(),
|
||||
quote_style: None
|
||||
})),
|
||||
op: BinaryOperator::Gt,
|
||||
right: Box::new(Expr::Value(Value::Placeholder("$2".to_string())))
|
||||
})
|
||||
}),
|
||||
action
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue