File tree Expand file tree Collapse file tree 9 files changed +94
-0
lines changed
Expand file tree Collapse file tree 9 files changed +94
-0
lines changed Original file line number Diff line number Diff line change @@ -387,6 +387,9 @@ pub struct Update {
387387 pub output : Option < OutputClause > ,
388388 /// SQLite-specific conflict resolution clause
389389 pub or : Option < SqliteOnConflict > ,
390+ /// ORDER BY (MySQL extension for single-table UPDATE)
391+ /// See <https://dev.mysql.com/doc/refman/8.4/en/update.html>
392+ pub order_by : Vec < OrderByExpr > ,
390393 /// LIMIT
391394 pub limit : Option < Expr > ,
392395}
@@ -434,6 +437,11 @@ impl Display for Update {
434437 f. write_str ( "RETURNING" ) ?;
435438 indented_list ( f, returning) ?;
436439 }
440+ if !self . order_by . is_empty ( ) {
441+ SpaceOrNewline . fmt ( f) ?;
442+ f. write_str ( "ORDER BY" ) ?;
443+ indented_list ( f, & self . order_by ) ?;
444+ }
437445 if let Some ( limit) = & self . limit {
438446 SpaceOrNewline . fmt ( f) ?;
439447 write ! ( f, "LIMIT {limit}" ) ?;
Original file line number Diff line number Diff line change @@ -952,6 +952,7 @@ impl Spanned for Update {
952952 returning,
953953 output,
954954 or : _,
955+ order_by,
955956 limit,
956957 } = self ;
957958
@@ -963,6 +964,7 @@ impl Spanned for Update {
963964 . chain ( selection. iter ( ) . map ( |i| i. span ( ) ) )
964965 . chain ( returning. iter ( ) . flat_map ( |i| i. iter ( ) . map ( |k| k. span ( ) ) ) )
965966 . chain ( output. iter ( ) . map ( |i| i. span ( ) ) )
967+ . chain ( order_by. iter ( ) . map ( |i| i. span ( ) ) )
966968 . chain ( limit. iter ( ) . map ( |i| i. span ( ) ) ) ,
967969 )
968970 }
Original file line number Diff line number Diff line change @@ -133,6 +133,10 @@ impl Dialect for GenericDialect {
133133 true
134134 }
135135
136+ fn supports_update_order_by ( & self ) -> bool {
137+ true
138+ }
139+
136140 fn supports_from_first_select ( & self ) -> bool {
137141 true
138142 }
Original file line number Diff line number Diff line change @@ -520,6 +520,16 @@ pub trait Dialect: Debug + Any {
520520 false
521521 }
522522
523+ /// Returns true if the dialect supports `ORDER BY` in `UPDATE` statements.
524+ ///
525+ /// ```sql
526+ /// UPDATE foo SET bar = false WHERE foo = true ORDER BY foo ASC;
527+ /// ```
528+ /// See <https://dev.mysql.com/doc/refman/8.4/en/update.html>
529+ fn supports_update_order_by ( & self ) -> bool {
530+ false
531+ }
532+
523533 /// Returns true if the dialect supports an `EXCEPT` clause following a
524534 /// wildcard in a select list.
525535 ///
Original file line number Diff line number Diff line change @@ -179,6 +179,11 @@ impl Dialect for MySqlDialect {
179179 true
180180 }
181181
182+ /// See: <https://dev.mysql.com/doc/refman/8.4/en/update.html>
183+ fn supports_update_order_by ( & self ) -> bool {
184+ true
185+ }
186+
182187 fn supports_data_type_signed_suffix ( & self ) -> bool {
183188 true
184189 }
Original file line number Diff line number Diff line change @@ -17755,6 +17755,13 @@ impl<'a> Parser<'a> {
1775517755 } else {
1775617756 None
1775717757 };
17758+ let order_by = if self.dialect.supports_update_order_by()
17759+ && self.parse_keywords(&[Keyword::ORDER, Keyword::BY])
17760+ {
17761+ self.parse_comma_separated(Parser::parse_order_by_expr)?
17762+ } else {
17763+ vec![]
17764+ };
1775817765 let limit = if self.parse_keyword(Keyword::LIMIT) {
1775917766 Some(self.parse_expr()?)
1776017767 } else {
@@ -17770,6 +17777,7 @@ impl<'a> Parser<'a> {
1777017777 returning,
1777117778 output,
1777217779 or,
17780+ order_by,
1777317781 limit,
1777417782 }
1777517783 .into())
Original file line number Diff line number Diff line change @@ -535,6 +535,7 @@ fn parse_update_set_from() {
535535 returning: None,
536536 output: None,
537537 or: None,
538+ order_by: vec![],
538539 limit: None
539540 })
540541 );
@@ -554,6 +555,7 @@ fn parse_update_with_table_alias() {
554555 selection,
555556 returning,
556557 or: None,
558+ order_by: _,
557559 limit: None,
558560 optimizer_hints,
559561 update_token: _,
Original file line number Diff line number Diff line change @@ -2707,6 +2707,7 @@ fn parse_update_with_joins() {
27072707 selection,
27082708 returning,
27092709 or : None ,
2710+ order_by : _,
27102711 limit : None ,
27112712 optimizer_hints,
27122713 update_token : _,
@@ -2784,6 +2785,59 @@ fn parse_update_with_joins() {
27842785 }
27852786}
27862787
2788+ #[ test]
2789+ fn parse_update_with_order_by ( ) {
2790+ let sql = "UPDATE foo SET bar = false WHERE foo = true ORDER BY foo ASC" ;
2791+ match mysql_and_generic ( ) . verified_stmt ( sql) {
2792+ Statement :: Update ( Update { order_by, .. } ) => {
2793+ assert_eq ! (
2794+ vec![ OrderByExpr {
2795+ expr: Expr :: Identifier ( Ident {
2796+ value: "foo" . to_owned( ) ,
2797+ quote_style: None ,
2798+ span: Span :: empty( ) ,
2799+ } ) ,
2800+ options: OrderByOptions {
2801+ asc: Some ( true ) ,
2802+ nulls_first: None ,
2803+ } ,
2804+ with_fill: None ,
2805+ } ] ,
2806+ order_by
2807+ ) ;
2808+ }
2809+ _ => unreachable ! ( ) ,
2810+ }
2811+ }
2812+
2813+ #[ test]
2814+ fn parse_update_with_order_by_and_limit ( ) {
2815+ let sql = "UPDATE foo SET bar = false WHERE foo = true ORDER BY foo ASC LIMIT 10" ;
2816+ match mysql_and_generic ( ) . verified_stmt ( sql) {
2817+ Statement :: Update ( Update {
2818+ order_by, limit, ..
2819+ } ) => {
2820+ assert_eq ! (
2821+ vec![ OrderByExpr {
2822+ expr: Expr :: Identifier ( Ident {
2823+ value: "foo" . to_owned( ) ,
2824+ quote_style: None ,
2825+ span: Span :: empty( ) ,
2826+ } ) ,
2827+ options: OrderByOptions {
2828+ asc: Some ( true ) ,
2829+ nulls_first: None ,
2830+ } ,
2831+ with_fill: None ,
2832+ } ] ,
2833+ order_by
2834+ ) ;
2835+ assert_eq ! ( Some ( Expr :: value( number( "10" ) ) ) , limit) ;
2836+ }
2837+ _ => unreachable ! ( ) ,
2838+ }
2839+ }
2840+
27872841#[ test]
27882842fn parse_delete_with_order_by ( ) {
27892843 let sql = "DELETE FROM customers ORDER BY id DESC" ;
Original file line number Diff line number Diff line change @@ -497,6 +497,7 @@ fn parse_update_tuple_row_values() {
497497 from: None ,
498498 returning: None ,
499499 output: None ,
500+ order_by: vec![ ] ,
500501 limit: None ,
501502 update_token: AttachedToken :: empty( )
502503 } )
You can’t perform that action at this time.
0 commit comments