From 2dd7467a37c969930b575bf4d61fda604f89f2a8 Mon Sep 17 00:00:00 2001 From: Belchior Oliveira Date: Wed, 18 Feb 2026 15:36:42 -0300 Subject: [PATCH] Adds order_by statement for Delete and Update builders in SQLite --- Cargo.toml | 3 +- src/delete/delete.rs | 59 ++++++++++++++++++++--------------- src/delete/delete_internal.rs | 20 ++++++++---- src/structure.rs | 30 +++++++++--------- src/update/update.rs | 48 ++++++++++++++++------------ src/update/update_internal.rs | 20 ++++++++---- tests/clause_order_by_spec.rs | 4 +-- 7 files changed, 109 insertions(+), 75 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index adc05ed..44499a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,11 +4,12 @@ description = "Write SQL queries in a simple and composable way" documentation = "https://docs.rs/sql_query_builder" repository = "https://github.com/belchior/sql_query_builder" authors = ["Belchior Oliveira "] -version = "2.5.2" +version = "2.6.2" edition = "2021" rust-version = "1.62" license = "MIT" keywords = ["sql", "query", "postgres", "sqlite", "mysql"] +exclude = [".github", ".vscode", "scripts"] [features] #! SQL Query Builder comes with the following optional features: diff --git a/src/delete/delete.rs b/src/delete/delete.rs index 6e8cf72..34f817d 100644 --- a/src/delete/delete.rs +++ b/src/delete/delete.rs @@ -368,6 +368,39 @@ impl Delete { } } +#[cfg(any(doc, feature = "sqlite", feature = "mysql"))] +#[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))] +#[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] +impl Delete { + /// The `order by` clause. + /// + /// # Example + /// + /// ``` + /// # #[cfg(any(feature = "sqlite", feature = "mysql"))] + /// # { + /// # use sql_query_builder as sql; + /// let delete = sql::Delete::new() + /// .order_by("created_at asc"); + /// + /// # let expected = "ORDER BY created_at asc"; + /// # assert_eq!(expected, delete.as_string()); + /// # } + /// ``` + /// + /// Output + /// + /// ```sql + /// ORDER BY created_at asc + /// ``` + /// + /// For crate feature `sqlite` you should enable this statement at SQLite before use, [more info](https://sqlite.org/lang_delete.html#optional_limit_and_order_by_clauses). + pub fn order_by(mut self, column: &str) -> Self { + push_unique(&mut self._order_by, column.trim().to_string()); + self + } +} + #[cfg(any(doc, feature = "mysql"))] #[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] impl Delete { @@ -641,32 +674,6 @@ impl Delete { self } - /// The `order by` clause - /// - /// # Example - /// - /// ``` - /// # #[cfg(feature = "mysql")] - /// # { - /// # use sql_query_builder as sql; - /// let delete = sql::Delete::new() - /// .order_by("created_at asc"); - /// - /// # let expected = "ORDER BY created_at asc"; - /// # assert_eq!(expected, delete.as_string()); - /// # } - /// ``` - /// - /// Output - /// - /// ```sql - /// ORDER BY created_at asc - /// ``` - pub fn order_by(mut self, column: &str) -> Self { - push_unique(&mut self._order_by, column.trim().to_string()); - self - } - /// The `partition` clause /// /// # Example diff --git a/src/delete/delete_internal.rs b/src/delete/delete_internal.rs index 589e69b..4a37472 100644 --- a/src/delete/delete_internal.rs +++ b/src/delete/delete_internal.rs @@ -74,6 +74,14 @@ impl Concat for Delete { DeleteClause::Where, &self._where, ); + query = self.concat_order_by( + &self._raw_before, + &self._raw_after, + query, + &fmts, + DeleteClause::OrderBy, + &self._order_by, + ); query = self.concat_returning( &self._raw_before, &self._raw_after, @@ -166,26 +174,28 @@ impl Delete { #[cfg(any(feature = "postgresql", feature = "sqlite", feature = "mysql"))] use crate::concat::non_standard::ConcatWith; - #[cfg(any(feature = "postgresql", feature = "sqlite", feature = "mysql"))] impl ConcatWith for Delete {} #[cfg(any(feature = "postgresql", feature = "sqlite"))] use crate::concat::non_standard::ConcatReturning; - #[cfg(any(feature = "postgresql", feature = "sqlite"))] impl ConcatReturning for Delete {} +#[cfg(any(feature = "sqlite", feature = "mysql"))] +use crate::concat::sql_standard::ConcatOrderBy; +#[cfg(any(feature = "sqlite", feature = "mysql"))] +impl ConcatOrderBy for Delete {} + #[cfg(feature = "mysql")] use crate::{ concat::{ mysql::ConcatPartition, non_standard::ConcatLimit, - sql_standard::{ConcatFrom, ConcatJoin, ConcatOrderBy}, + sql_standard::{ConcatFrom, ConcatJoin}, }, utils, }; - #[cfg(feature = "mysql")] impl ConcatFrom for Delete {} #[cfg(feature = "mysql")] @@ -193,8 +203,6 @@ impl ConcatJoin for Delete {} #[cfg(feature = "mysql")] impl ConcatLimit for Delete {} #[cfg(feature = "mysql")] -impl ConcatOrderBy for Delete {} -#[cfg(feature = "mysql")] impl ConcatPartition for Delete {} #[cfg(feature = "mysql")] diff --git a/src/structure.rs b/src/structure.rs index 256021d..c458820 100644 --- a/src/structure.rs +++ b/src/structure.rs @@ -269,6 +269,9 @@ pub struct Delete { #[cfg(any(feature = "postgresql", feature = "sqlite"))] pub(crate) _returning: Vec, + #[cfg(any(feature = "sqlite", feature = "mysql"))] + pub(crate) _order_by: Vec, + #[cfg(feature = "mysql")] pub(crate) _delete: Vec, @@ -281,9 +284,6 @@ pub struct Delete { #[cfg(feature = "mysql")] pub(crate) _limit: String, - #[cfg(feature = "mysql")] - pub(crate) _order_by: Vec, - #[cfg(feature = "mysql")] pub(crate) _partition: Vec, } @@ -305,6 +305,11 @@ pub enum DeleteClause { #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))] Returning, + #[cfg(any(feature = "sqlite", feature = "mysql"))] + #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))] + #[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] + OrderBy, + #[cfg(feature = "mysql")] #[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] Limit, @@ -321,10 +326,6 @@ pub enum DeleteClause { #[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] Join, - #[cfg(feature = "mysql")] - #[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] - OrderBy, - #[cfg(feature = "mysql")] #[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] Partition, @@ -820,6 +821,9 @@ pub struct Update { #[cfg(any(feature = "postgresql", feature = "sqlite"))] pub(crate) _with: Vec<(String, std::sync::Arc)>, + #[cfg(any(feature = "sqlite", feature = "mysql"))] + pub(crate) _order_by: Vec, + #[cfg(not(feature = "sqlite"))] pub(crate) _update: String, @@ -831,9 +835,6 @@ pub struct Update { #[cfg(feature = "mysql")] pub(crate) _limit: String, - - #[cfg(feature = "mysql")] - pub(crate) _order_by: Vec, } #[cfg(feature = "sqlite")] @@ -866,6 +867,11 @@ pub enum UpdateClause { #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))] With, + #[cfg(any(feature = "sqlite", feature = "mysql"))] + #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))] + #[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] + OrderBy, + #[cfg(feature = "sqlite")] #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))] UpdateOr, @@ -877,10 +883,6 @@ pub enum UpdateClause { #[cfg(feature = "mysql")] #[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] Limit, - - #[cfg(feature = "mysql")] - #[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] - OrderBy, } /// Builder of [Values] command. diff --git a/src/update/update.rs b/src/update/update.rs index 5b71d13..6bffcb9 100644 --- a/src/update/update.rs +++ b/src/update/update.rs @@ -424,6 +424,33 @@ impl Update { } } +#[cfg(any(doc, feature = "sqlite", feature = "mysql"))] +#[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))] +#[cfg_attr(docsrs, doc(cfg(feature = "mysql")))] +impl Update { + /// The `order by` clause + /// + /// # Example + /// + /// ``` + /// # #[cfg(feature = "mysql")] + /// # { + /// # use sql_query_builder as sql; + /// let update = sql::Update::new() + /// .order_by("login asc"); + /// + /// # let expected = "ORDER BY login asc"; + /// # assert_eq!(expected, update.as_string()); + /// # } + /// ``` + /// + /// For crate feature `sqlite` you should enable this statement at SQLite before use, [more info](https://sqlite.org/lang_update.html#optional_limit_and_order_by_clauses). + pub fn order_by(mut self, column: &str) -> Self { + push_unique(&mut self._order_by, column.trim().to_string()); + self + } +} + #[cfg(feature = "sqlite")] use crate::structure::UpdateVars; @@ -626,27 +653,8 @@ impl Update { self._limit = num.trim().to_string(); self } - - /// The `order by` clause - /// - /// # Example - /// - /// ``` - /// # #[cfg(feature = "mysql")] - /// # { - /// # use sql_query_builder as sql; - /// let update = sql::Update::new() - /// .order_by("login asc"); - /// - /// # let expected = "ORDER BY login asc"; - /// # assert_eq!(expected, update.as_string()); - /// # } - /// ``` - pub fn order_by(mut self, column: &str) -> Self { - push_unique(&mut self._order_by, column.trim().to_string()); - self - } } + impl std::fmt::Display for Update { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.as_string()) diff --git a/src/update/update_internal.rs b/src/update/update_internal.rs index 7b67b51..74851d3 100644 --- a/src/update/update_internal.rs +++ b/src/update/update_internal.rs @@ -128,6 +128,14 @@ impl Concat for Update { UpdateClause::Where, &self._where, ); + query = self.concat_order_by( + &self._raw_before, + &self._raw_after, + query, + &fmts, + UpdateClause::OrderBy, + &self._order_by, + ); query = self.concat_returning( &self._raw_before, &self._raw_after, @@ -182,15 +190,18 @@ impl Concat for Update { #[cfg(any(feature = "postgresql", feature = "sqlite"))] use crate::concat::non_standard::{ConcatReturning, ConcatWith}; - #[cfg(any(feature = "postgresql", feature = "sqlite"))] impl ConcatReturning for Update {} #[cfg(any(feature = "postgresql", feature = "sqlite"))] impl ConcatWith for Update {} +#[cfg(any(feature = "sqlite", feature = "mysql"))] +use crate::concat::sql_standard::ConcatOrderBy; +#[cfg(any(feature = "sqlite", feature = "mysql"))] +impl ConcatOrderBy for Update {} + #[cfg(feature = "sqlite")] use crate::concat::sqlite::ConcatUpdate; - #[cfg(feature = "sqlite")] impl ConcatUpdate for Update {} @@ -220,9 +231,6 @@ impl Update { } #[cfg(feature = "mysql")] -use crate::concat::{non_standard::ConcatLimit, sql_standard::ConcatOrderBy}; - +use crate::concat::non_standard::ConcatLimit; #[cfg(feature = "mysql")] impl ConcatLimit for Update {} -#[cfg(feature = "mysql")] -impl ConcatOrderBy for Update {} diff --git a/tests/clause_order_by_spec.rs b/tests/clause_order_by_spec.rs index c7f0ab5..3fdbd65 100644 --- a/tests/clause_order_by_spec.rs +++ b/tests/clause_order_by_spec.rs @@ -91,7 +91,7 @@ mod select_command { } } -#[cfg(feature = "mysql")] +#[cfg(any(feature = "sqlite", feature = "mysql"))] mod delete_command { use pretty_assertions::assert_eq; use sql_query_builder as sql; @@ -188,7 +188,7 @@ mod delete_command { } } -#[cfg(feature = "mysql")] +#[cfg(any(feature = "sqlite", feature = "mysql"))] mod update_command { use pretty_assertions::assert_eq; use sql_query_builder as sql;