Skip to content

Commit 9d85412

Browse files
committed
chore: add comments
1 parent d150f5d commit 9d85412

18 files changed

Lines changed: 1702 additions & 103 deletions

File tree

file_classification_core/src/internal/file_group.rs

Lines changed: 110 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// file_group.rs
2+
//! 文件与分组关联管理模块
3+
//!
4+
//! 提供对文件-分组关系表 (`file_groups`) 的增删查操作支持。
5+
16
use super::models::{FileGroupCondition, FileGroupDTO};
27
use crate::model::schema::{file_groups, files};
38
use diesel::prelude::*;
@@ -6,6 +11,14 @@ use crate::model::models::{File, FileGroupOrderBy, FileGroupQueryOptions, OrderD
611
use crate::utils::errors::AppError;
712
use crate::utils::errors::AppError::CannotUnbindPrimaryGroup;
813

14+
/// 插入一个新的文件-分组关联记录
15+
///
16+
/// 参数:
17+
/// - `conn`: 数据库连接对象
18+
/// - `file_group_dto`: 包含待插入数据的 DTO 对象
19+
///
20+
/// 返回值:
21+
/// 成功时返回影响的行数(通常应为1),失败则返回数据库错误
922
pub fn insert_file_group(
1023
conn: &mut AnyConnection,
1124
file_group_dto: &FileGroupDTO,
@@ -15,11 +28,21 @@ pub fn insert_file_group(
1528
.execute(conn)
1629
}
1730

31+
/// 根据 DTO 中的信息删除一个文件-分组关联记录
32+
///
33+
/// 注意:若尝试解除文件与其主分组的关系,则会抛出 `CannotUnbindPrimaryGroup` 错误。
34+
///
35+
/// 参数:
36+
/// - `conn`: 数据库连接对象
37+
/// - `file_group_dto`: 包含要删除记录信息的 DTO 对象
38+
///
39+
/// 返回值:
40+
/// 成功时返回影响的行数(通常应为1),失败则返回自定义错误或数据库错误
1841
pub fn delete_file_group_by_id(
1942
conn: &mut AnyConnection,
2043
file_group_dto: &FileGroupDTO,
2144
) -> Result<usize, AppError> {
22-
// 判断是否是文件-主组关系 若是则抛异常
45+
// 检查是否试图解绑文件的主分组
2346
let file = files::table
2447
.select(File::as_select())
2548
.filter(files::id.eq(file_group_dto.file_id))
@@ -29,7 +52,7 @@ pub fn delete_file_group_by_id(
2952
return Err(CannotUnbindPrimaryGroup);
3053
}
3154

32-
// 删除关联记录
55+
// 执行实际的删除操作
3356
diesel::delete(
3457
file_groups::table
3558
.filter(file_groups::group_id.eq(file_group_dto.group_id))
@@ -39,7 +62,13 @@ pub fn delete_file_group_by_id(
3962
.map_err(AppError::from) // 将 QueryResult 转换为 AppError
4063
}
4164

42-
// 将 FileGroupCondition 转换为 diesel 查询条件的辅助函数
65+
/// 构建符合 Diesel 查询语法的条件表达式
66+
///
67+
/// 参数:
68+
/// - `condition`: 表达查询条件的数据结构
69+
///
70+
/// 返回值:
71+
/// 符合 Diesel 查询条件类型的动态表达式盒子
4372
fn build_file_group_condition(condition: FileGroupCondition) -> Box<dyn BoxableExpression<file_groups::table, <AnyConnection as Connection>::Backend, SqlType=diesel::sql_types::Bool>> {
4473
match condition {
4574
FileGroupCondition::FileId(id) => Box::new(file_groups::file_id.eq(id)),
@@ -63,7 +92,7 @@ fn build_file_group_condition(condition: FileGroupCondition) -> Box<dyn BoxableE
6392
}
6493
}
6594
result.unwrap_or_else(|| Box::new(true.into_sql::<diesel::sql_types::Bool>()))
66-
}
95+
},
6796
FileGroupCondition::Or(conditions) => {
6897
let mut result: Option<Box<dyn BoxableExpression<file_groups::table, <AnyConnection as Connection>::Backend, SqlType=diesel::sql_types::Bool>>> = None;
6998
for cond in conditions {
@@ -74,28 +103,37 @@ fn build_file_group_condition(condition: FileGroupCondition) -> Box<dyn BoxableE
74103
}
75104
}
76105
result.unwrap_or_else(|| Box::new(false.into_sql::<diesel::sql_types::Bool>()))
77-
}
106+
},
78107
FileGroupCondition::Not(condition) => {
79108
let expr = build_file_group_condition(*condition);
80109
Box::new(diesel::dsl::not(expr))
81110
}
82111
}
83112
}
84113

85-
// 根据 FileGroupCondition 向量查询文件组关联
114+
/// 根据多个条件查询文件-分组关联记录,并可设置最大返回数量
115+
///
116+
/// 参数:
117+
/// - `conn`: 数据库连接对象
118+
/// - `conditions`: 查询条件集合,各条件之间采用 AND 连接
119+
/// - `limit`: 最大返回记录数限制(可选)
120+
///
121+
/// 返回值:
122+
/// 查询成功的记录列表或数据库错误
86123
pub fn select_file_groups_by_conditions(
87124
conn: &mut AnyConnection,
88125
conditions: Vec<FileGroupCondition>,
89126
limit: Option<i64>,
90127
) -> Result<Vec<FileGroupDTO>, diesel::result::Error> {
91128
let mut query = file_groups::table.into_boxed::<<AnyConnection as Connection>::Backend>();
92129

93-
// 对每个条件应用 AND 逻辑
130+
// 应用所有条件
94131
for condition in conditions {
95132
let boxed_condition = build_file_group_condition(condition);
96133
query = query.filter(boxed_condition);
97134
}
98135

136+
// 设置返回条目上限
99137
if let Some(limit) = limit {
100138
query = query.limit(limit)
101139
}
@@ -105,6 +143,17 @@ pub fn select_file_groups_by_conditions(
105143
.load(conn)
106144
}
107145

146+
/// 根据多个条件和高级选项查询文件-分组关联记录
147+
///
148+
/// 支持分页、排序等复杂查询需求
149+
///
150+
/// 参数:
151+
/// - `conn`: 数据库连接对象
152+
/// - `conditions`: 查询条件集合,各条件之间采用 AND 连接
153+
/// - `options`: 查询选项,包括分页和排序配置
154+
///
155+
/// 返回值:
156+
/// 查询成功的记录列表或数据库错误
108157
#[allow(dead_code)]
109158
pub fn select_file_groups_by_conditions_with_options(
110159
conn: &mut AnyConnection,
@@ -113,13 +162,13 @@ pub fn select_file_groups_by_conditions_with_options(
113162
) -> Result<Vec<FileGroupDTO>, diesel::result::Error> {
114163
let mut query = file_groups::table.into_boxed::<<AnyConnection as Connection>::Backend>();
115164

116-
// 对每个条件应用 AND 逻辑
165+
// 应用所有条件
117166
for condition in conditions {
118167
let boxed_condition = build_file_group_condition(condition);
119168
query = query.filter(boxed_condition);
120169
}
121170

122-
// 应用查询选项(排序、限制等)
171+
// 分页设置
123172
if let Some(limit) = options.limit {
124173
query = query.limit(limit);
125174
}
@@ -128,7 +177,7 @@ pub fn select_file_groups_by_conditions_with_options(
128177
query = query.offset(offset);
129178
}
130179

131-
// 应用排序
180+
// 排序设置
132181
for order_by in options.order_by {
133182
query = match order_by {
134183
FileGroupOrderBy::FileId(direction) => {
@@ -150,18 +199,60 @@ pub fn select_file_groups_by_conditions_with_options(
150199
.select(FileGroupDTO::as_select())
151200
.load(conn)
152201
}
153-
202+
/// 根据给定条件批量删除文件-分组关联记录
203+
///
204+
/// 注意:若尝试解除文件与其主分组的关系,则会抛出 `CannotUnbindPrimaryGroup` 错误。
205+
/// 该操作在事务中执行,任何一个删除失败都会导致整个操作回滚。
206+
///
207+
/// 参数:
208+
/// - `conn`: 数据库连接对象
209+
/// - `conditions`: 删除条件集合,各条件之间采用 AND 连接
210+
///
211+
/// 返回值:
212+
/// 成功删除的记录数目或数据库错误
154213
pub fn delete_file_groups_by_conditions(
155214
conn: &mut AnyConnection,
156215
conditions: Vec<FileGroupCondition>,
157-
) -> Result<usize, diesel::result::Error> {
158-
let mut query = diesel::delete(file_groups::table).into_boxed::<<AnyConnection as Connection>::Backend>();
216+
) -> Result<usize, AppError> {
217+
// 开始事务
218+
conn.transaction::<usize, AppError, _>(|conn| {
219+
// 首先查询将要删除的所有记录
220+
let mut select_query = file_groups::table.into_boxed::<<AnyConnection as Connection>::Backend>();
159221

160-
// 对每个条件应用 AND 逻辑
161-
for condition in conditions {
162-
let boxed_condition = build_file_group_condition(condition);
163-
query = query.filter(boxed_condition);
164-
}
222+
// 应用所有条件到查询
223+
for condition in &conditions {
224+
let boxed_condition = build_file_group_condition(condition.clone());
225+
select_query = select_query.filter(boxed_condition);
226+
}
227+
228+
// 获取将要删除的记录
229+
let records_to_delete: Vec<FileGroupDTO> = select_query
230+
.select(FileGroupDTO::as_select())
231+
.load(conn)?;
232+
233+
// 检查每条记录是否是文件的主分组关联
234+
for record in &records_to_delete {
235+
let file = files::table
236+
.select(File::as_select())
237+
.filter(files::id.eq(record.file_id))
238+
.first(conn);
239+
240+
// 如果文件存在且该分组是其主分组,则不允许删除
241+
if file.is_ok() && file?.group_id == record.group_id {
242+
return Err(CannotUnbindPrimaryGroup);
243+
}
244+
}
245+
246+
// 执行实际的删除操作
247+
let mut delete_query = diesel::delete(file_groups::table).into_boxed::<<AnyConnection as Connection>::Backend>();
248+
249+
// 应用所有删除条件
250+
for condition in conditions {
251+
let boxed_condition = build_file_group_condition(condition);
252+
delete_query = delete_query.filter(boxed_condition);
253+
}
165254

166-
query.execute(conn)
255+
let deleted_count = delete_query.execute(conn)?;
256+
Ok(deleted_count)
257+
})
167258
}

0 commit comments

Comments
 (0)