sqlx_model/curd/
mod.rs

1#[macro_use]
2mod macros;
3mod delete;
4mod insert;
5mod select;
6mod update;
7
8use sqlx::database::HasArguments;
9use sqlx::query::{Query, QueryAs};
10use sqlx::{Database, FromRow};
11use std::any::TypeId;
12use std::fmt::Display;
13
14/// 统一表前缀
15static mut TABLE_PREFIX: String = String::new();
16/// 表名
17pub struct TableName {
18    db: String,
19    name: String,
20}
21impl Display for TableName {
22    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        unsafe { write!(f, "{}{}{}", self.db, TABLE_PREFIX, self.name) }
24    }
25}
26impl SqlQuote<String> for TableName {
27    fn sql_quote(&self) -> String {
28        unsafe { format!("{}{}{}", self.db, TABLE_PREFIX, self.name) }
29    }
30}
31impl TableName {
32    /// 设置表前缀
33    pub fn set_prefix(str: String) {
34        unsafe {
35            TABLE_PREFIX = str;
36        }
37    }
38    /// 新建表名
39    pub fn new(name: &str) -> Self {
40        let (db, name) = match name.rfind('.') {
41            Some(index) => name.split_at(index + 1),
42            None => ("", name),
43        };
44        Self {
45            db: db.to_string(),
46            name: name.to_owned(),
47        }
48    }
49    /// 得到完整表名
50    pub fn full_name(&self) -> String {
51        unsafe { format!("{}{}{}", self.db, TABLE_PREFIX, self.name) }
52    }
53}
54#[derive(PartialEq, Eq)]
55pub enum DbType {
56    Mysql,
57    Sqlite,
58    Postgres,
59    MsSql,
60}
61impl DbType {
62    pub fn type_new<DB: sqlx::Database>() -> Self {
63        #[cfg(feature = "sqlx-mysql")]
64        if TypeId::of::<DB>() == TypeId::of::<sqlx::MySql>() {
65            return DbType::Mysql;
66        }
67        #[cfg(feature = "sqlx-sqlite")]
68        if TypeId::of::<DB>() == TypeId::of::<sqlx::Sqlite>() {
69            return DbType::Mysql;
70        }
71        #[cfg(feature = "sqlx-postgres")]
72        if TypeId::of::<DB>() == TypeId::of::<sqlx::Postgres>() {
73            return DbType::Postgres;
74        }
75        #[cfg(feature = "sqlx-mssql")]
76        if TypeId::of::<DB>() == TypeId::of::<sqlx::Mssql>() {
77            return DbType::MsSql;
78        }
79        unimplemented!()
80    }
81    /// 得到不同数据库的绑定字符
82    pub fn mark(&self, pos: usize) -> String {
83        match self {
84            DbType::Mysql => "?".to_string(),
85            DbType::Sqlite => {
86                format!("${pos}")
87            }
88            DbType::Postgres => {
89                format!("${}", pos + 1)
90            }
91            DbType::MsSql => "?".to_string(),
92        }
93    }
94}
95
96/// model实现得到表名trait
97pub trait ModelTableName {
98    fn table_name() -> TableName;
99}
100/// model实现得到表字段和字段值绑定 trait
101pub trait ModelTableField<DB>
102where
103    DB: Database,
104{
105    fn table_pk() -> TableFields;
106    fn table_column() -> TableFields;
107    fn query_sqlx_bind<'t>(
108        &'t self,
109        table_field_val: &FieldItem,
110        res: Query<'t, DB, <DB as HasArguments<'t>>::Arguments>,
111    ) -> Query<'t, DB, <DB as HasArguments<'t>>::Arguments>;
112    fn query_as_sqlx_bind<'t, M>(
113        &'t self,
114        table_field_val: &FieldItem,
115        res: QueryAs<'t, DB, M, <DB as HasArguments<'t>>::Arguments>,
116    ) -> QueryAs<'t, DB, M, <DB as HasArguments<'t>>::Arguments>
117    where
118        for<'r> M: FromRow<'r, DB::Row> + Send + Unpin;
119}
120
121/// 表字段
122#[derive(Clone, PartialEq, Eq)]
123pub struct FieldItem {
124    pub name: String,
125    pub column_name: String,
126}
127impl Display for FieldItem {
128    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129        write!(f, "{}", self.name)
130    }
131}
132impl FieldItem {
133    pub fn new(name: &str, column_name: &str) -> Self {
134        FieldItem {
135            name: name.to_string(),
136            column_name: column_name.to_string(),
137        }
138    }
139}
140
141/// 表字段容器
142pub struct TableFields(Vec<FieldItem>);
143impl Display for TableFields {
144    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145        let fileds = self
146            .0
147            .iter()
148            .map(|e| format!("{e}"))
149            .collect::<Vec<String>>()
150            .join(",");
151        write!(f, "{fileds}")
152    }
153}
154impl TableFields {
155    pub fn new(fields: Vec<FieldItem>) -> Self {
156        TableFields(fields)
157    }
158    /// 合并一批外部的表字段列表,去除重复
159    pub fn marge(&mut self, field: &[FieldItem]) {
160        for val in field.iter() {
161            if !self.0.iter().any(|e| e.name == val.name) {
162                self.0.push(val.to_owned())
163            }
164        }
165    }
166    /// 跟指定表字段列表取并集
167    pub fn intersect(&mut self, field: &[FieldItem]) {
168        self.0 = self
169            .0
170            .iter()
171            .filter_map(|e| {
172                if field.contains(e) {
173                    Some(e.to_owned())
174                } else {
175                    None
176                }
177            })
178            .collect();
179    }
180    /// 删除表指定字段
181    pub fn del(&mut self, name: &str) {
182        self.0 = self
183            .0
184            .iter()
185            .filter_map(|e| {
186                if name == e.name {
187                    None
188                } else {
189                    Some(e.to_owned())
190                }
191            })
192            .collect();
193    }
194    /// 得到字段列表
195    pub fn to_vec(&self) -> Vec<String> {
196        let field = self.0.iter();
197        field
198            .map(|e| e.column_name.clone())
199            .collect::<Vec<String>>()
200    }
201}
202
203pub enum WhereOption {
204    None,            //无WHERE条件,且无排序等
205    Where(String),   //有WHERE条件
206    NoWhere(String), //无WHERE条件,但有排序等后续SQL
207}
208
209pub use delete::*;
210pub use insert::*;
211pub use select::*;
212pub use update::*;
213
214use crate::SqlQuote;