Skip to content

Commit c7a3ba5

Browse files
committed
add support for := operator-mysql
1 parent 3a8a3bb commit c7a3ba5

File tree

4 files changed

+116
-1
lines changed

4 files changed

+116
-1
lines changed

src/ast/operator.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,9 @@ pub enum BinaryOperator {
321321
/// `~=` Same as? (PostgreSQL/Redshift geometric operator)
322322
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
323323
TildeEq,
324+
/// ':=' Assignment Operator
325+
/// See <https://dev.mysql.com/doc/refman/8.4/en/assignment-operators.html#operator_assign-value>
326+
Assignment,
324327
}
325328

326329
impl fmt::Display for BinaryOperator {
@@ -394,6 +397,7 @@ impl fmt::Display for BinaryOperator {
394397
BinaryOperator::QuestionDoublePipe => f.write_str("?||"),
395398
BinaryOperator::At => f.write_str("@"),
396399
BinaryOperator::TildeEq => f.write_str("~="),
400+
BinaryOperator::Assignment => f.write_str(":="),
397401
}
398402
}
399403
}

src/dialect/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,8 @@ pub trait Dialect: Debug + Any {
620620
Token::Word(w) if w.keyword == Keyword::OPERATOR => Ok(p!(Between)),
621621
Token::Word(w) if w.keyword == Keyword::DIV => Ok(p!(MulDivModOp)),
622622
Token::Period => Ok(p!(Period)),
623-
Token::Eq
623+
Token::Assignment
624+
| Token::Eq
624625
| Token::Lt
625626
| Token::LtEq
626627
| Token::Neq

src/parser/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3233,6 +3233,7 @@ impl<'a> Parser<'a> {
32333233
let regular_binary_operator = match &tok.token {
32343234
Token::Spaceship => Some(BinaryOperator::Spaceship),
32353235
Token::DoubleEq => Some(BinaryOperator::Eq),
3236+
Token::Assignment => Some(BinaryOperator::Assignment),
32363237
Token::Eq => Some(BinaryOperator::Eq),
32373238
Token::Neq => Some(BinaryOperator::NotEq),
32383239
Token::Gt => Some(BinaryOperator::Gt),

tests/sqlparser_mysql.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3454,3 +3454,112 @@ fn parse_cast_integers() {
34543454
.run_parser_method("CAST(foo AS UNSIGNED INTEGER(3))", |p| p.parse_expr())
34553455
.expect_err("CAST doesn't allow display width");
34563456
}
3457+
3458+
#[test]
3459+
fn test_variable_assignment_using_colon_equal() {
3460+
let sql_select = "SELECT @price := price, @tax := price * 0.1 FROM products WHERE id = 1";
3461+
let stmt = mysql().verified_stmt(sql_select);
3462+
match stmt {
3463+
Statement::Query(query) => {
3464+
let select = query.body.as_select().unwrap();
3465+
3466+
assert_eq!(
3467+
select.projection,
3468+
vec![
3469+
SelectItem::UnnamedExpr(Expr::BinaryOp {
3470+
left: Box::new(Expr::Identifier(Ident {
3471+
value: "@price".to_string(),
3472+
quote_style: None,
3473+
span: Span::empty(),
3474+
})),
3475+
op: BinaryOperator::Assignment,
3476+
right: Box::new(Expr::Identifier(Ident {
3477+
value: "price".to_string(),
3478+
quote_style: None,
3479+
span: Span::empty(),
3480+
})),
3481+
}),
3482+
SelectItem::UnnamedExpr(Expr::BinaryOp {
3483+
left: Box::new(Expr::Identifier(Ident {
3484+
value: "@tax".to_string(),
3485+
quote_style: None,
3486+
span: Span::empty(),
3487+
})),
3488+
op: BinaryOperator::Assignment,
3489+
right: Box::new(Expr::BinaryOp {
3490+
left: Box::new(Expr::Identifier(Ident {
3491+
value: "price".to_string(),
3492+
quote_style: None,
3493+
span: Span::empty(),
3494+
})),
3495+
op: BinaryOperator::Multiply,
3496+
right: Box::new(Expr::Value(ValueWithSpan {
3497+
value: Value::Number("0.1".to_string(), false),
3498+
span: Span::empty(),
3499+
})),
3500+
}),
3501+
}),
3502+
]
3503+
);
3504+
3505+
assert_eq!(
3506+
select.selection,
3507+
Some(Expr::BinaryOp {
3508+
left: Box::new(Expr::Identifier(Ident {
3509+
value: "id".to_string(),
3510+
quote_style: None,
3511+
span: Span::empty(),
3512+
})),
3513+
op: BinaryOperator::Eq,
3514+
right: Box::new(Expr::Value(ValueWithSpan {
3515+
value: Value::Number("1".to_string(), false),
3516+
span: Span::empty(),
3517+
})),
3518+
})
3519+
);
3520+
}
3521+
_ => panic!("Unexpected statement {stmt}"),
3522+
}
3523+
3524+
let sql_update =
3525+
"UPDATE products SET price = @new_price := price * 1.1 WHERE category = 'Books'";
3526+
let stmt = mysql().verified_stmt(sql_update);
3527+
3528+
match stmt {
3529+
Statement::Update { assignments, .. } => {
3530+
assert_eq!(
3531+
assignments,
3532+
vec![Assignment {
3533+
target: AssignmentTarget::ColumnName(ObjectName(vec![
3534+
ObjectNamePart::Identifier(Ident {
3535+
value: "price".to_string(),
3536+
quote_style: None,
3537+
span: Span::empty(),
3538+
})
3539+
])),
3540+
value: Expr::BinaryOp {
3541+
left: Box::new(Expr::Identifier(Ident {
3542+
value: "@new_price".to_string(),
3543+
quote_style: None,
3544+
span: Span::empty(),
3545+
})),
3546+
op: BinaryOperator::Assignment,
3547+
right: Box::new(Expr::BinaryOp {
3548+
left: Box::new(Expr::Identifier(Ident {
3549+
value: "price".to_string(),
3550+
quote_style: None,
3551+
span: Span::empty(),
3552+
})),
3553+
op: BinaryOperator::Multiply,
3554+
right: Box::new(Expr::Value(ValueWithSpan {
3555+
value: Value::Number("1.1".to_string(), false),
3556+
span: Span::empty(),
3557+
})),
3558+
}),
3559+
},
3560+
}]
3561+
)
3562+
}
3563+
_ => panic!("Unexpected statement {stmt}"),
3564+
}
3565+
}

0 commit comments

Comments
 (0)