mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-07-08 01:15:00 +00:00
Implement ON CONFLICT and RETURNING (#666)
* Implement RETURNING on INSERT/UPDATE/DELETE * Implement INSERT ... ON CONFLICT * Fix tests * cargo fmt * tests: on conflict and returning Co-authored-by: gamife <gamife9886@gmail.com>
This commit is contained in:
parent
ae1c69034e
commit
814367a6ab
6 changed files with 250 additions and 8 deletions
|
@ -564,6 +564,7 @@ fn parse_update_set_from() {
|
|||
Ident::new("id")
|
||||
])),
|
||||
}),
|
||||
returning: None,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -1177,6 +1178,143 @@ fn parse_prepare() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_pg_on_conflict() {
|
||||
let stmt = pg_and_generic().verified_stmt(
|
||||
"INSERT INTO distributors (did, dname) \
|
||||
VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc') \
|
||||
ON CONFLICT(did) \
|
||||
DO UPDATE SET dname = EXCLUDED.dname",
|
||||
);
|
||||
match stmt {
|
||||
Statement::Insert {
|
||||
on:
|
||||
Some(OnInsert::OnConflict(OnConflict {
|
||||
conflict_target,
|
||||
action,
|
||||
})),
|
||||
..
|
||||
} => {
|
||||
assert_eq!(vec![Ident::from("did")], conflict_target);
|
||||
assert_eq!(
|
||||
OnConflictAction::DoUpdate(vec![Assignment {
|
||||
id: vec!["dname".into()],
|
||||
value: Expr::CompoundIdentifier(vec!["EXCLUDED".into(), "dname".into()])
|
||||
},]),
|
||||
action
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let stmt = pg_and_generic().verified_stmt(
|
||||
"INSERT INTO distributors (did, dname, area) \
|
||||
VALUES (5, 'Gizmo Transglobal', 'Mars'), (6, 'Associated Computing, Inc', 'Venus') \
|
||||
ON CONFLICT(did, area) \
|
||||
DO UPDATE SET dname = EXCLUDED.dname, area = EXCLUDED.area",
|
||||
);
|
||||
match stmt {
|
||||
Statement::Insert {
|
||||
on:
|
||||
Some(OnInsert::OnConflict(OnConflict {
|
||||
conflict_target,
|
||||
action,
|
||||
})),
|
||||
..
|
||||
} => {
|
||||
assert_eq!(
|
||||
vec![Ident::from("did"), Ident::from("area"),],
|
||||
conflict_target
|
||||
);
|
||||
assert_eq!(
|
||||
OnConflictAction::DoUpdate(vec![
|
||||
Assignment {
|
||||
id: vec!["dname".into()],
|
||||
value: Expr::CompoundIdentifier(vec!["EXCLUDED".into(), "dname".into()])
|
||||
},
|
||||
Assignment {
|
||||
id: vec!["area".into()],
|
||||
value: Expr::CompoundIdentifier(vec!["EXCLUDED".into(), "area".into()])
|
||||
},
|
||||
]),
|
||||
action
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let stmt = pg_and_generic().verified_stmt(
|
||||
"INSERT INTO distributors (did, dname) \
|
||||
VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc') \
|
||||
ON CONFLICT DO NOTHING",
|
||||
);
|
||||
match stmt {
|
||||
Statement::Insert {
|
||||
on:
|
||||
Some(OnInsert::OnConflict(OnConflict {
|
||||
conflict_target,
|
||||
action,
|
||||
})),
|
||||
..
|
||||
} => {
|
||||
assert_eq!(Vec::<Ident>::new(), conflict_target);
|
||||
assert_eq!(OnConflictAction::DoNothing, action);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_pg_returning() {
|
||||
let stmt = pg_and_generic().verified_stmt(
|
||||
"INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') RETURNING did",
|
||||
);
|
||||
match stmt {
|
||||
Statement::Insert { returning, .. } => {
|
||||
assert_eq!(
|
||||
Some(vec![SelectItem::UnnamedExpr(Expr::Identifier(
|
||||
"did".into()
|
||||
)),]),
|
||||
returning
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let stmt = pg_and_generic().verified_stmt(
|
||||
"UPDATE weather SET temp_lo = temp_lo + 1, temp_hi = temp_lo + 15, prcp = DEFAULT \
|
||||
WHERE city = 'San Francisco' AND date = '2003-07-03' \
|
||||
RETURNING temp_lo AS lo, temp_hi AS hi, prcp",
|
||||
);
|
||||
match stmt {
|
||||
Statement::Update { returning, .. } => {
|
||||
assert_eq!(
|
||||
Some(vec![
|
||||
SelectItem::ExprWithAlias {
|
||||
expr: Expr::Identifier("temp_lo".into()),
|
||||
alias: "lo".into()
|
||||
},
|
||||
SelectItem::ExprWithAlias {
|
||||
expr: Expr::Identifier("temp_hi".into()),
|
||||
alias: "hi".into()
|
||||
},
|
||||
SelectItem::UnnamedExpr(Expr::Identifier("prcp".into())),
|
||||
]),
|
||||
returning
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let stmt =
|
||||
pg_and_generic().verified_stmt("DELETE FROM tasks WHERE status = 'DONE' RETURNING *");
|
||||
match stmt {
|
||||
Statement::Delete { returning, .. } => {
|
||||
assert_eq!(Some(vec![SelectItem::Wildcard,]), returning);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_pg_bitwise_binary_ops() {
|
||||
let bitwise_ops = &[
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue