mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 13:34:53 +08:00
feat(resource): 增加 CAS 诊断与索引过滤优化
补充 doctor cas 只读诊断、校验 CAS 对象分片布局,并将常用 ResourceRepository metadata 查询下推到 SQLite。 Refs G-011
This commit is contained in:
@@ -186,6 +186,39 @@ impl SqliteResourceRepository {
|
||||
)
|
||||
.await?;
|
||||
|
||||
Self::execute_query(
|
||||
&self.pool,
|
||||
sqlx::query(
|
||||
r#"
|
||||
CREATE INDEX IF NOT EXISTS idx_resources_release_id
|
||||
ON resources(json_extract(metadata_json, '$.official_release_id'))
|
||||
"#,
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Self::execute_query(
|
||||
&self.pool,
|
||||
sqlx::query(
|
||||
r#"
|
||||
CREATE INDEX IF NOT EXISTS idx_resources_platform
|
||||
ON resources(json_extract(metadata_json, '$.platform'))
|
||||
"#,
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Self::execute_query(
|
||||
&self.pool,
|
||||
sqlx::query(
|
||||
r#"
|
||||
CREATE INDEX IF NOT EXISTS idx_resources_bundle_path
|
||||
ON resources(json_extract(metadata_json, '$.bundle_path'))
|
||||
"#,
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -340,6 +373,51 @@ impl SqliteResourceRepository {
|
||||
builder.push_bind(destination);
|
||||
}
|
||||
|
||||
if let Some(release_id) = &query.official_release_id {
|
||||
push_condition_prefix(builder, &mut has_where);
|
||||
builder.push("json_extract(metadata_json, '$.official_release_id') = ");
|
||||
builder.push_bind(release_id);
|
||||
}
|
||||
|
||||
if let Some(platform) = &query.platform {
|
||||
push_condition_prefix(builder, &mut has_where);
|
||||
builder.push("json_extract(metadata_json, '$.platform') = ");
|
||||
builder.push_bind(platform);
|
||||
}
|
||||
|
||||
if let Some(bundle_path) = &query.bundle_path {
|
||||
push_condition_prefix(builder, &mut has_where);
|
||||
builder.push("json_extract(metadata_json, '$.bundle_path') = ");
|
||||
builder.push_bind(bundle_path);
|
||||
}
|
||||
|
||||
if let Some(archive_entry) = &query.archive_entry {
|
||||
push_condition_prefix(builder, &mut has_where);
|
||||
builder.push(
|
||||
"EXISTS (SELECT 1 FROM json_each(metadata_json, '$.archive_entries') AS archive_entries WHERE archive_entries.value = ",
|
||||
);
|
||||
builder.push_bind(archive_entry);
|
||||
builder.push(")");
|
||||
}
|
||||
|
||||
if let Some(parse_status) = &query.parse_status {
|
||||
push_condition_prefix(builder, &mut has_where);
|
||||
builder.push(
|
||||
"EXISTS (SELECT 1 FROM json_each(metadata_json, '$.parse_statuses') AS parse_statuses WHERE parse_statuses.value = ",
|
||||
);
|
||||
builder.push_bind(parse_status);
|
||||
builder.push(")");
|
||||
}
|
||||
|
||||
if let Some(text_unit_format) = &query.text_unit_format {
|
||||
push_condition_prefix(builder, &mut has_where);
|
||||
builder.push(
|
||||
"EXISTS (SELECT 1 FROM json_each(metadata_json, '$.text_unit_formats') AS text_unit_formats WHERE text_unit_formats.value = ",
|
||||
);
|
||||
builder.push_bind(text_unit_format);
|
||||
builder.push(")");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -374,10 +452,6 @@ impl SqliteResourceRepository {
|
||||
}
|
||||
|
||||
async fn count_resources(&self, query: &ResourceQuery) -> bat_core::Result<u64> {
|
||||
if query.requires_resource_scan() {
|
||||
return Ok(self.fetch_resources(query, None).await?.len() as u64);
|
||||
}
|
||||
|
||||
let mut builder = QueryBuilder::<Sqlite>::new("SELECT COUNT(*) FROM resources");
|
||||
Self::apply_filters(&mut builder, query)?;
|
||||
|
||||
@@ -801,6 +875,20 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn sqlite_repository_persists_and_filters_resources() {
|
||||
let (_temp_dir, repository) = sqlite_repository().await;
|
||||
let indexes = sqlx::query_scalar::<_, String>(
|
||||
"SELECT name FROM sqlite_master WHERE type = 'index' AND tbl_name = 'resources'",
|
||||
)
|
||||
.fetch_all(&repository.pool)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(indexes
|
||||
.iter()
|
||||
.any(|name| name == "idx_resources_release_id"));
|
||||
assert!(indexes.iter().any(|name| name == "idx_resources_platform"));
|
||||
assert!(indexes
|
||||
.iter()
|
||||
.any(|name| name == "idx_resources_bundle_path"));
|
||||
|
||||
let mut resource = resource(
|
||||
"resource/sqlite-a",
|
||||
"assets/model.bundle",
|
||||
|
||||
Reference in New Issue
Block a user