Skip to content

Commit 71c566d

Browse files
committed
fix: process reference_count right
1 parent 01b5329 commit 71c566d

8 files changed

Lines changed: 262 additions & 14 deletions

File tree

file_classification_core/src/internal/files.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,34 @@ pub fn delete_files_by_conditions(
257257

258258
query.execute(conn)
259259
}
260+
pub fn increase_files_reference_count_by_conditions(
261+
conn: &mut AnyConnection,
262+
conditions: Vec<FileCondition>,
263+
) -> Result<usize, diesel::result::Error> {
264+
let mut query = diesel::update(files::table).into_boxed::<<AnyConnection as Connection>::Backend>();
265+
266+
// 应用所有条件
267+
for condition in conditions {
268+
let boxed_condition = build_file_condition(condition);
269+
query = query.filter(boxed_condition);
270+
}
271+
272+
// 增加引用计数
273+
query.set(files::reference_count.eq(files::reference_count + 1)).execute(conn)
274+
}
275+
276+
pub fn decrease_files_reference_count_by_conditions(
277+
conn: &mut AnyConnection,
278+
conditions: Vec<FileCondition>,
279+
) -> Result<usize, diesel::result::Error> {
280+
let mut query = diesel::update(files::table).into_boxed::<<AnyConnection as Connection>::Backend>();
281+
282+
// 应用所有条件
283+
for condition in conditions {
284+
let boxed_condition = build_file_condition(condition);
285+
query = query.filter(boxed_condition);
286+
}
287+
288+
// 减少引用计数
289+
query.set(files::reference_count.eq(files::reference_count - 1)).execute(conn)
290+
}

file_classification_core/src/internal/groups.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ use super::models::GroupCondition;
124124
use crate::model::models::{GroupOrderBy, GroupQueryOptions, OrderDirection, UpdateGroupDTO};
125125
use diesel::dsl::not;
126126
use diesel::sql_types::Bool;
127-
use diesel::sqlite::Sqlite;
128127
use crate::utils::database::AnyConnection;
129128

130129
// 将 GroupCondition 转换为 diesel 查询条件的辅助函数
@@ -325,3 +324,35 @@ pub fn delete_groups_by_conditions(
325324

326325
query.execute(conn)
327326
}
327+
328+
pub fn increase_groups_reference_count_by_conditions(
329+
conn: &mut AnyConnection,
330+
conditions: Vec<GroupCondition>,
331+
) -> Result<usize, diesel::result::Error> {
332+
let mut query = diesel::update(groups::table).into_boxed::<<AnyConnection as Connection>::Backend>();
333+
334+
// 应用所有条件
335+
for condition in conditions {
336+
let boxed_condition = build_group_condition(condition);
337+
query = query.filter(boxed_condition);
338+
}
339+
340+
// 增加引用计数
341+
query.set(groups::reference_count.eq(groups::reference_count + 1)).execute(conn)
342+
}
343+
344+
pub fn decrease_groups_reference_count_by_conditions(
345+
conn: &mut AnyConnection,
346+
conditions: Vec<GroupCondition>,
347+
) -> Result<usize, diesel::result::Error> {
348+
let mut query = diesel::update(groups::table).into_boxed::<<AnyConnection as Connection>::Backend>();
349+
350+
// 应用所有条件
351+
for condition in conditions {
352+
let boxed_condition = build_group_condition(condition);
353+
query = query.filter(boxed_condition);
354+
}
355+
356+
// 减少引用计数
357+
query.set(groups::reference_count.eq(groups::reference_count - 1)).execute(conn)
358+
}

file_classification_core/src/internal/tags.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,3 +248,35 @@ pub fn delete_tags_by_conditions(
248248

249249
query.execute(conn)
250250
}
251+
252+
pub fn increase_tags_reference_count_by_conditions(
253+
conn: &mut AnyConnection,
254+
conditions: Vec<TagCondition>,
255+
) -> Result<usize, diesel::result::Error> {
256+
let mut query = diesel::update(tags::table).into_boxed::<<AnyConnection as Connection>::Backend>();
257+
258+
// 应用所有条件
259+
for condition in conditions {
260+
let boxed_condition = build_tag_condition(condition);
261+
query = query.filter(boxed_condition);
262+
}
263+
264+
// 增加引用计数
265+
query.set(tags::reference_count.eq(tags::reference_count + 1)).execute(conn)
266+
}
267+
268+
pub fn decrease_tags_reference_count_by_conditions(
269+
conn: &mut AnyConnection,
270+
conditions: Vec<TagCondition>,
271+
) -> Result<usize, diesel::result::Error> {
272+
let mut query = diesel::update(tags::table).into_boxed::<<AnyConnection as Connection>::Backend>();
273+
274+
// 应用所有条件
275+
for condition in conditions {
276+
let boxed_condition = build_tag_condition(condition);
277+
query = query.filter(boxed_condition);
278+
}
279+
280+
// 减少引用计数
281+
query.set(tags::reference_count.eq(tags::reference_count - 1)).execute(conn)
282+
}

file_classification_core/src/service/file_group.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use diesel::result::Error;
77
use diesel::Connection;
88
use crate::utils::database::AnyConnection;
99

10+
// 创建文件组关联(不允许使用于主组绑定)
1011
pub fn create_file_group(
1112
conn: &mut AnyConnection,
1213
file_group_dto: FileGroupDTO,

file_classification_core/src/service/files.rs

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::internal::file_group::select_file_groups_by_conditions;
22
use crate::internal::groups::select_groups_by_conditions;
3-
use crate::model::models::{CreateFileDTO, File, FileCondition, FileFilter, FileGroupCondition, FileGroupDTO, GroupCondition, GroupTagCondition, UpdateFileDTO, UpdateGroupDTO};
3+
use crate::model::models::{CreateFileDTO, File, FileCondition, FileFilter, FileGroupCondition, FileGroupDTO, GroupCondition, GroupTagCondition, TagCondition, UpdateFileDTO, UpdateGroupDTO};
44
use crate::service::groups::update_groups_by_conditions;
55
use crate::service::AppError;
6-
use crate::utils::errors::AppError::CannotBindToPrimaryGroup;
6+
use crate::utils::errors::AppError::{FuturePrimaryGroupShouldBeEmpty};
77
use crate::{internal, service};
88
use diesel::Connection;
99
use crate::utils::database::AnyConnection;
@@ -57,7 +57,7 @@ pub fn create_file(conn: &mut AnyConnection, create_file_dto: CreateFileDTO) ->
5757
)?;
5858

5959
if file_groups.len() != 0 {
60-
return Err(CannotBindToPrimaryGroup);
60+
return Err(FuturePrimaryGroupShouldBeEmpty);
6161
}
6262
let mut count = 0;
6363
count += internal::files::create_file(conn, &create_file_dto)?;
@@ -100,20 +100,46 @@ pub fn delete_file(conn: &mut AnyConnection, file_id: i32) -> Result<(), AppErro
100100
let file_required_to_delete = internal::files::find_file_by_id(conn, file_id)?
101101
.ok_or_else(|| diesel::result::Error::NotFound)?;
102102

103-
// 删除与文件关联的组标签
103+
// 查找与该文件关联的所有文件组关系(包括主组和其他组)
104+
let file_groups = select_file_groups_by_conditions(
105+
conn,
106+
vec![FileGroupCondition::FileId(file_required_to_delete.id)],
107+
None,
108+
)?;
109+
110+
// 对于每个文件组关系,减少对应组的引用计数
111+
for file_group in &file_groups {
112+
internal::groups::decrease_group_reference_count(conn, file_group.group_id)?;
113+
}
114+
115+
// 仅对主组关联的标签减少引用计数
116+
let tag_list = internal::group_tag::select_group_tags_by_conditions(
117+
conn,
118+
vec![GroupTagCondition::GroupId(file_required_to_delete.group_id)],
119+
None,
120+
)?;
121+
122+
if !tag_list.is_empty() {
123+
internal::tags::decrease_tags_reference_count_by_conditions(
124+
conn,
125+
vec![TagCondition::IdIn(tag_list.iter().map(|tag| tag.tag_id).collect::<Vec<_>>())],
126+
)?;
127+
}
128+
129+
// 删除与文件主组关联的所有组标签关系
104130
internal::group_tag::delete_group_tags_by_conditions(
105131
conn,
106132
vec![GroupTagCondition::GroupId(file_required_to_delete.group_id)],
107133
)?;
108134

109-
// 删除与文件关联的文件组关系
135+
// 删除与文件关联的所有文件组关系
110136
internal::file_group::delete_file_groups_by_conditions(
111137
conn,
112138
vec![FileGroupCondition::FileId(file_required_to_delete.id)],
113139
)?;
114140

115-
// 删除组和文件本身
116-
service::groups::delete_group(conn, file_required_to_delete.group_id)?;
141+
// 删除主组和文件本身
142+
internal::groups::delete_group(conn, file_required_to_delete.group_id)?;
117143
internal::files::delete_file_by_id(conn, file_id)?;
118144

119145
Ok(())
@@ -168,7 +194,7 @@ pub fn delete_files_by_conditions(
168194

169195
// 对于每个要删除的文件,处理相关的引用关系
170196
for file in &files_to_delete {
171-
// 查找与该文件关联的所有文件组关系
197+
// 查找与该文件关联的所有文件组关系(包括主组和其他组)
172198
let file_groups = select_file_groups_by_conditions(
173199
conn,
174200
vec![FileGroupCondition::FileId(file.id)],
@@ -180,13 +206,34 @@ pub fn delete_files_by_conditions(
180206
internal::groups::decrease_group_reference_count(conn, file_group.group_id)?;
181207
}
182208

209+
// 仅对主组关联的标签减少引用计数
210+
let tag_list = internal::group_tag::select_group_tags_by_conditions(
211+
conn,
212+
vec![GroupTagCondition::GroupId(file.group_id)],
213+
None,
214+
)?;
215+
216+
if !tag_list.is_empty() {
217+
internal::tags::decrease_tags_reference_count_by_conditions(
218+
conn,
219+
vec![TagCondition::IdIn(tag_list.iter().map(|tag| tag.tag_id).collect::<Vec<_>>())],
220+
)?;
221+
}
222+
223+
// 删除与文件主组关联的所有组标签关系
224+
internal::group_tag::delete_group_tags_by_conditions(
225+
conn,
226+
vec![GroupTagCondition::GroupId(file.group_id)],
227+
)?;
228+
183229
// 删除与该文件关联的所有文件组关系
184230
internal::file_group::delete_file_groups_by_conditions(
185231
conn,
186232
vec![FileGroupCondition::FileId(file.id)],
187233
)?;
188234

189-
// 删除文件本身
235+
// 删除主组和文件本身
236+
internal::groups::delete_group(conn, file.group_id)?;
190237
let deleted_count = internal::files::delete_file_by_id(conn, file.id)?;
191238
total_deleted += deleted_count;
192239
}

file_classification_core/src/service/groups.rs

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,62 @@ pub fn delete_group(
2222
group_id: i32,
2323
) -> Result<usize, Error> {
2424
// 1.判断是否是primary
25-
// 若是primary 则直接删除对应的File,删除GroupTag
25+
// 若是primary 则先删除对应的File,删除GroupTag,删除FileGroup
2626
// 若不是primary 则先删除GroupTag,再删除FileGroup
2727
conn.transaction::<usize, Error, _>(|conn| {
2828
let group = groups::find_group_by_id(conn, group_id)?.ok_or(AppError::GroupNotFound)?;
29+
2930
if group.is_primary {
31+
// 删除主组时,先处理关联的文件
3032
crate::internal::files::delete_files_by_conditions(conn, vec![
3133
FileCondition::GroupId(group_id)
3234
])?;
35+
36+
// 显式删除文件组关系(作为额外保障)
37+
crate::internal::file_group::delete_file_groups_by_conditions(conn, vec![
38+
FileGroupCondition::GroupId(group_id)
39+
])?;
3340
} else {
41+
// 对于非主组,需要先减少关联文件的引用计数
42+
let file_groups = crate::internal::file_group::select_file_groups_by_conditions(
43+
conn,
44+
vec![FileGroupCondition::GroupId(group_id)],
45+
None,
46+
)?;
47+
48+
// 减少每个关联文件的引用计数
49+
for file_group in &file_groups {
50+
crate::internal::files::decrease_file_reference_count(conn, file_group.file_id)?;
51+
}
52+
53+
// 删除文件组关系
3454
crate::internal::file_group::delete_file_groups_by_conditions(conn, vec![
3555
FileGroupCondition::GroupId(group_id)
3656
])?;
3757
}
58+
59+
// 减少组关联标签的引用计数
60+
let group_tags = crate::internal::group_tag::select_group_tags_by_conditions(
61+
conn,
62+
vec![GroupTagCondition::GroupId(group_id)],
63+
None,
64+
)?;
65+
66+
// 减少每个关联标签的引用计数
67+
for group_tag in &group_tags {
68+
crate::internal::tags::decrease_tag_reference_count(conn, group_tag.tag_id)?;
69+
}
70+
71+
// 删除组标签关系
3872
crate::internal::group_tag::delete_group_tags_by_conditions(conn, vec![
3973
GroupTagCondition::GroupId(group_id)
4074
])?;
75+
76+
// 最后删除组本身
4177
groups::delete_group(conn, group_id)
4278
})
4379
}
80+
4481
#[allow(deprecated)]
4582
#[deprecated]
4683
pub fn select_groups(
@@ -94,22 +131,52 @@ pub fn delete_groups_by_conditions(
94131
conn,
95132
vec![FileCondition::GroupId(group.id)]
96133
)?;
134+
135+
// 显式删除文件组关系(作为额外保障)
136+
crate::internal::file_group::delete_file_groups_by_conditions(
137+
conn,
138+
vec![FileGroupCondition::GroupId(group.id)]
139+
)?;
97140
} else {
98-
// 如果不是主组,则删除文件组关联
141+
// 如果不是主组,则先减少关联文件的引用计数
142+
let file_groups = crate::internal::file_group::select_file_groups_by_conditions(
143+
conn,
144+
vec![FileGroupCondition::GroupId(group.id)],
145+
None,
146+
)?;
147+
148+
// 减少每个关联文件的引用计数
149+
for file_group in &file_groups {
150+
crate::internal::files::decrease_file_reference_count(conn, file_group.file_id)?;
151+
}
152+
153+
// 删除文件组关联
99154
crate::internal::file_group::delete_file_groups_by_conditions(
100155
conn,
101156
vec![FileGroupCondition::GroupId(group.id)]
102157
)?;
103158
}
104159

160+
// 减少组关联标签的引用计数
161+
let group_tags = crate::internal::group_tag::select_group_tags_by_conditions(
162+
conn,
163+
vec![GroupTagCondition::GroupId(group.id)],
164+
None,
165+
)?;
166+
167+
// 减少每个关联标签的引用计数
168+
for group_tag in &group_tags {
169+
crate::internal::tags::decrease_tag_reference_count(conn, group_tag.tag_id)?;
170+
}
171+
105172
// 删除组标签关联
106173
crate::internal::group_tag::delete_group_tags_by_conditions(
107174
conn,
108175
vec![GroupTagCondition::GroupId(group.id)]
109176
)?;
110177

111178
// 删除组本身
112-
let deleted_count = groups::delete_group(conn, group.id)?;
179+
let deleted_count = crate::internal::groups::delete_group(conn, group.id)?;
113180
total_deleted += deleted_count;
114181
}
115182

0 commit comments

Comments
 (0)