Repository: SeaQL/sea-query (language: rust)

Issue:
Introduce `md5` SQL function
<!--

Welcome! Thanks for suggesting features!

Do you want to ask a question? Are you looking for support?
Please ask us on
- Discord: https://discord.com/invite/uCPdDXzbdv
- GitHub Discussions: https://github.com/SeaQL/sea-query/discussions/new

Make sure you have a clear feature specification before open an issue. Alternatively, please start an "Idea" thread on GitHub Discussions and let's formulate the solution together.

-->

## Motivation

I would like to call the MD5 SQL function. Both Postgres and MySQL have support for it and have the same function signature. SQLite does not have support.

## Proposed Solutions

Right now I am using `Func::custom`.

## Additional Information

I am willing to make a PR.



Discussion / hints:

Fix patch:
diff --git a/src/backend/query_builder.rs b/src/backend/query_builder.rs
index e3823eae..f95a5d6a 100644
--- a/src/backend/query_builder.rs
+++ b/src/backend/query_builder.rs
@@ -676,6 +676,7 @@ pub trait QueryBuilder:
                     Function::Custom(_) => "",
                     Function::Random => self.random_function(),
                     Function::Round => "ROUND",
+                    Function::Md5 => "MD5",
                     #[cfg(feature = "backend-postgres")]
                     Function::PgFunction(_) => unimplemented!(),
                 }
diff --git a/src/expr.rs b/src/expr.rs
index 165fb09c..9c6f6544 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -1980,7 +1980,7 @@ impl Expr {
         SimpleExpr::FunctionCall(func)
     }
 
-    /// Keyword `CURRENT_TIMESTAMP`.
+    /// Keyword `CURRENT_DATE`.
     ///
     /// # Examples
     ///
diff --git a/src/func.rs b/src/func.rs
index 24b17d19..980b6551 100644
--- a/src/func.rs
+++ b/src/func.rs
@@ -25,6 +25,7 @@ pub enum Function {
     BitOr,
     Random,
     Round,
+    Md5,
     #[cfg(feature = "backend-postgres")]
     PgFunction(PgFunction),
 }
@@ -721,4 +722,33 @@ impl Func {
     pub fn random() -> FunctionCall {
         FunctionCall::new(Function::Random)
     }
+
+    /// Call `MD5` function, this is only available in Postgres and MySQL.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use sea_query::{tests_cfg::*, *};
+    ///
+    /// let query = Query::select()
+    ///     .expr(Func::md5(Expr::col((Char::Table, Char::Character))))
+    ///     .from(Char::Table)
+    ///     .to_owned();
+    ///
+    /// assert_eq!(
+    ///     query.to_string(MysqlQueryBuilder),
+    ///     r#"SELECT MD5(`character`.`character`) FROM `character`"#
+    /// );
+    ///
+    /// assert_eq!(
+    ///     query.to_string(PostgresQueryBuilder),
+    ///     r#"SELECT MD5("character"."character") FROM "character""#
+    /// );
+    /// ```
+    pub fn md5<T>(expr: T) -> FunctionCall
+    where
+        T: Into<SimpleExpr>,
+    {
+        FunctionCall::new(Function::Md5).arg(expr)
+    }
 }


Test patch:
diff --git a/tests/mysql/query.rs b/tests/mysql/query.rs
index a9e46525..c0bb2e7d 100644
--- a/tests/mysql/query.rs
+++ b/tests/mysql/query.rs
@@ -1061,6 +1061,16 @@ fn select_61() {
     );
 }
 
+#[test]
+fn md5_fn() {
+    assert_eq!(
+        Query::select()
+            .expr(Func::md5(Expr::val("test")))
+            .to_string(MysqlQueryBuilder),
+        r#"SELECT MD5('test')"#
+    );
+}
+
 #[test]
 #[allow(clippy::approx_constant)]
 fn insert_2() {
diff --git a/tests/postgres/query.rs b/tests/postgres/query.rs
index a00d5751..fb664692 100644
--- a/tests/postgres/query.rs
+++ b/tests/postgres/query.rs
@@ -1925,6 +1925,16 @@ fn sub_query_with_fn() {
     );
 }
 
+#[test]
+fn md5_fn() {
+    assert_eq!(
+        Query::select()
+            .expr(Func::md5(Expr::val("test")))
+            .to_string(PostgresQueryBuilder),
+        r#"SELECT MD5('test')"#
+    );
+}
+
 #[test]
 fn select_array_contains_bin_oper() {
     assert_eq!(