chain_builder/
sqlx_mysql.rs

1use crate::builder::ChainBuilder;
2use serde_json::Value;
3use sqlx::{self, mysql::MySqlArguments, Arguments, Row};
4
5impl ChainBuilder {
6    #[cfg(all(feature = "mysql", feature = "sqlx_mysql"))]
7    fn value_to_arguments(&self, binds: &Vec<Value>) -> MySqlArguments {
8        let mut arguments: MySqlArguments = MySqlArguments::default();
9        for bind in binds {
10            match bind {
11                Value::Null => {
12                    // bind NULL อย่างชัดเจน
13                    let _ = arguments.add(Option::<String>::None);
14                }
15                Value::Bool(b) => {
16                    let _ = arguments.add(b);
17                }
18                Value::Number(n) => {
19                    if let Some(i) = n.as_i64() {
20                        let _ = arguments.add(i);
21                    } else if let Some(u) = n.as_u64() {
22                        if u <= i64::MAX as u64 {
23                            let _ = arguments.add(u as i64);
24                        } else {
25                            // ถ้าใหญ่เกิน เก็บเป็น string ปลอดภัยสุด
26                            let _ = arguments.add(u.to_string());
27                        }
28                    } else if let Some(f) = n.as_f64() {
29                        let _ = arguments.add(f);
30                    } else {
31                        let _ = arguments.add(n.to_string());
32                    }
33                }
34                Value::String(s) => {
35                    let _ = arguments.add(s);
36                }
37                Value::Array(arr) => {
38                    // SQLite ไม่มี array type → เก็บเป็น JSON text
39                    let _ = arguments.add(serde_json::to_string(&arr).unwrap_or_default());
40                }
41                Value::Object(obj) => {
42                    // เก็บเป็น JSON text
43                    let _ = arguments.add(serde_json::to_string(&obj).unwrap_or_default());
44                }
45            }
46        }
47        arguments
48    }
49
50    #[cfg(all(feature = "mysql", feature = "sqlx_mysql"))]
51    pub fn to_sqlx_query(
52        &mut self,
53    ) -> sqlx::query::Query<'_, sqlx::MySql, sqlx::mysql::MySqlArguments> {
54        let (_, binds) = self.to_sql();
55        sqlx::query_with(self.sql_str.as_str(), self.value_to_arguments(&binds))
56    }
57
58    #[cfg(all(feature = "mysql", feature = "sqlx_mysql"))]
59    pub fn to_sqlx_query_as<T>(
60        &mut self,
61    ) -> sqlx::query::QueryAs<'_, sqlx::MySql, T, sqlx::mysql::MySqlArguments>
62    where
63        T: for<'r> sqlx::FromRow<'r, sqlx::mysql::MySqlRow>,
64    {
65        let (_, binds) = self.to_sql();
66        sqlx::query_as_with(self.sql_str.as_str(), self.value_to_arguments(&binds))
67    }
68
69    #[cfg(all(feature = "mysql", feature = "sqlx_mysql"))]
70    pub async fn count(
71        &mut self,
72        column: &str,
73        pool: &sqlx::Pool<sqlx::MySql>,
74    ) -> Result<i64, sqlx::Error> {
75        let (_, binds) = self.to_sql();
76        let sql = self.sql_str.as_str();
77        let sql = format!("SELECT COUNT({}) FROM ({}) as count", column, sql);
78        let qb = sqlx::query_with(&sql, self.value_to_arguments(&binds));
79        let query_count = qb.fetch_one(pool).await?;
80        let count: i64 = query_count.try_get(0)?;
81        Ok(count)
82    }
83}