mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 13:34:53 +08:00
fix(repository): 扩展资源索引查询面
This commit is contained in:
@@ -326,6 +326,12 @@ impl SqliteResourceRepository {
|
||||
.push(" ESCAPE '\\'");
|
||||
}
|
||||
|
||||
if let Some(destination) = &query.destination {
|
||||
push_condition_prefix(builder, &mut has_where);
|
||||
builder.push("path = ");
|
||||
builder.push_bind(destination);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -349,10 +355,21 @@ impl SqliteResourceRepository {
|
||||
.await
|
||||
.map_err(|error| bat_core::Error::Other(error.into()))?;
|
||||
|
||||
rows.into_iter().map(Self::resource_from_row).collect()
|
||||
let resources = rows
|
||||
.into_iter()
|
||||
.map(Self::resource_from_row)
|
||||
.collect::<bat_core::Result<Vec<_>>>()?;
|
||||
Ok(resources
|
||||
.into_iter()
|
||||
.filter(|resource| query_matches(query, resource))
|
||||
.collect())
|
||||
}
|
||||
|
||||
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)?;
|
||||
|
||||
@@ -536,6 +553,63 @@ fn query_matches(query: &ResourceQuery, resource: &Resource) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(release_id) = &query.official_release_id {
|
||||
if resource.metadata.official_release_id.as_deref() != Some(release_id.as_str()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(platform) = &query.platform {
|
||||
if resource.metadata.platform.as_deref() != Some(platform.as_str()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(destination) = &query.destination {
|
||||
if resource.entry.path != *destination {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(bundle_path) = &query.bundle_path {
|
||||
if resource.metadata.bundle_path.as_deref() != Some(bundle_path.as_str()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(archive_entry) = &query.archive_entry {
|
||||
if !resource
|
||||
.metadata
|
||||
.archive_entries
|
||||
.iter()
|
||||
.any(|entry| entry == archive_entry)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(parse_status) = &query.parse_status {
|
||||
if !resource
|
||||
.metadata
|
||||
.parse_statuses
|
||||
.iter()
|
||||
.any(|status| status == parse_status)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(text_unit_format) = &query.text_unit_format {
|
||||
if !resource
|
||||
.metadata
|
||||
.text_unit_formats
|
||||
.iter()
|
||||
.any(|format| format == text_unit_format)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
@@ -641,6 +715,7 @@ mod tests {
|
||||
resource_type: Some(ResourceType::AssetBundle),
|
||||
hash: Some("hash-a".to_string()),
|
||||
path_pattern: Some("synthetic-*.bundle".to_string()),
|
||||
..ResourceQuery::all()
|
||||
};
|
||||
|
||||
let results = repository.list(query).await.unwrap();
|
||||
@@ -653,6 +728,52 @@ mod tests {
|
||||
assert_eq!(repository.count(ResourceQuery::all()).await.unwrap(), 2);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn list_filters_by_release_parse_and_textunit_metadata() {
|
||||
let repository = InMemoryResourceRepository::new();
|
||||
let mut matching = resource(
|
||||
"resource/text-a",
|
||||
"TextAssets/a.json",
|
||||
"hash-a",
|
||||
ResourceType::TextAsset,
|
||||
);
|
||||
matching.metadata.official_release_id = Some("v-current".to_string());
|
||||
matching.metadata.platform = Some("windows".to_string());
|
||||
matching.metadata.bundle_path = Some("Bundles/story.bundle".to_string());
|
||||
matching.metadata.archive_entries = vec!["story/Scenario.json".to_string()];
|
||||
matching.metadata.parse_statuses = vec!["parsed".to_string()];
|
||||
matching.metadata.text_unit_formats = vec!["json".to_string()];
|
||||
repository.add(matching).await.unwrap();
|
||||
|
||||
let mut stale = resource(
|
||||
"resource/text-b",
|
||||
"TextAssets/b.json",
|
||||
"hash-b",
|
||||
ResourceType::TextAsset,
|
||||
);
|
||||
stale.metadata.official_release_id = Some("v-old".to_string());
|
||||
stale.metadata.platform = Some("android".to_string());
|
||||
stale.metadata.parse_statuses = vec!["failed".to_string()];
|
||||
stale.metadata.text_unit_formats = vec!["plain".to_string()];
|
||||
repository.add(stale).await.unwrap();
|
||||
|
||||
let query = ResourceQuery {
|
||||
official_release_id: Some("v-current".to_string()),
|
||||
platform: Some("windows".to_string()),
|
||||
destination: Some("TextAssets/a.json".to_string()),
|
||||
bundle_path: Some("Bundles/story.bundle".to_string()),
|
||||
archive_entry: Some("story/Scenario.json".to_string()),
|
||||
parse_status: Some("parsed".to_string()),
|
||||
text_unit_format: Some("json".to_string()),
|
||||
..ResourceQuery::all()
|
||||
};
|
||||
|
||||
let results = repository.list(query.clone()).await.unwrap();
|
||||
assert_eq!(results.len(), 1);
|
||||
assert_eq!(results[0].id, "resource/text-a");
|
||||
assert_eq!(repository.count(query).await.unwrap(), 1);
|
||||
}
|
||||
|
||||
async fn sqlite_repository() -> (tempfile::TempDir, SqliteResourceRepository) {
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let repository = SqliteResourceRepository::new(temp_dir.path().join("resources.sqlite"))
|
||||
@@ -677,8 +798,12 @@ mod tests {
|
||||
.push("assets/shared.bundle".to_string());
|
||||
resource.metadata.official_release_id = Some("release-1".to_string());
|
||||
resource.metadata.platform = Some("windows".to_string());
|
||||
resource.metadata.bundle_path = Some("assets/model.bundle".to_string());
|
||||
resource.metadata.archive_entries = vec!["serialized/Scenario".to_string()];
|
||||
resource.metadata.parse_statuses = vec!["parsed".to_string()];
|
||||
resource.metadata.text_assets = vec!["Scenario".to_string()];
|
||||
resource.metadata.text_unit_count = 3;
|
||||
resource.metadata.text_unit_formats = vec!["json".to_string()];
|
||||
|
||||
repository.add(resource.clone()).await.unwrap();
|
||||
|
||||
@@ -693,8 +818,18 @@ mod tests {
|
||||
Some("release-1")
|
||||
);
|
||||
assert_eq!(by_id.metadata.platform.as_deref(), Some("windows"));
|
||||
assert_eq!(
|
||||
by_id.metadata.bundle_path.as_deref(),
|
||||
Some("assets/model.bundle")
|
||||
);
|
||||
assert_eq!(
|
||||
by_id.metadata.archive_entries,
|
||||
vec!["serialized/Scenario".to_string()]
|
||||
);
|
||||
assert_eq!(by_id.metadata.parse_statuses, vec!["parsed".to_string()]);
|
||||
assert_eq!(by_id.metadata.text_assets, vec!["Scenario".to_string()]);
|
||||
assert_eq!(by_id.metadata.text_unit_count, 3);
|
||||
assert_eq!(by_id.metadata.text_unit_formats, vec!["json".to_string()]);
|
||||
assert_eq!(
|
||||
repository.find_by_hash("hash-sqlite-a").await.unwrap().id,
|
||||
resource.id
|
||||
@@ -709,6 +844,28 @@ mod tests {
|
||||
let count = repository.count(ResourceQuery::all()).await.unwrap();
|
||||
assert_eq!(count, 1);
|
||||
|
||||
let query = ResourceQuery {
|
||||
official_release_id: Some("release-1".to_string()),
|
||||
platform: Some("windows".to_string()),
|
||||
destination: Some("assets/model.bundle".to_string()),
|
||||
bundle_path: Some("assets/model.bundle".to_string()),
|
||||
archive_entry: Some("serialized/Scenario".to_string()),
|
||||
parse_status: Some("parsed".to_string()),
|
||||
text_unit_format: Some("json".to_string()),
|
||||
..ResourceQuery::all()
|
||||
};
|
||||
let filtered = repository.list(query.clone()).await.unwrap();
|
||||
assert_eq!(filtered.len(), 1);
|
||||
assert_eq!(filtered[0].id, resource.id);
|
||||
assert_eq!(repository.count(query).await.unwrap(), 1);
|
||||
|
||||
let missing = ResourceQuery {
|
||||
official_release_id: Some("release-missing".to_string()),
|
||||
..ResourceQuery::all()
|
||||
};
|
||||
assert!(repository.list(missing.clone()).await.unwrap().is_empty());
|
||||
assert_eq!(repository.count(missing).await.unwrap(), 0);
|
||||
|
||||
repository.delete(&resource.id).await.unwrap();
|
||||
assert!(matches!(
|
||||
repository.find_by_id(&resource.id).await,
|
||||
|
||||
Reference in New Issue
Block a user