use bevy::prelude::*;
use bevy::prelude::IntoScheduleConfigs;
use bevy::ecs::query::QueryState;
use bevy::ecs::system::QueryLens;
use bevy_persistence_database::{
PersistentQuery,
commit_sync,
persistence_plugin::{PersistencePlugins, PersistenceSystemSet},
};
use bevy_persistence_database::query::immediate_world_ptr::ImmediateWorldPtr;
use bevy_persistence_database_derive::db_matrix_test;
use crate::common::*;
#[db_matrix_test]
fn test_query_lens_join_filtered_world_only() {
let (db, _container) = setup();
let mut app_seed = App::new();
app_seed.add_plugins(PersistencePlugins::new(db.clone()));
app_seed.world_mut().spawn((Health { value: 1 }, Position { x: 0.0, y: 0.0 }, PlayerName { name: "alice".into() }));
app_seed.world_mut().spawn((Health { value: 2 }, Position { x: 1.0, y: 1.0 }));
app_seed.world_mut().spawn(PlayerName { name: "bob".into() });
app_seed.update();
commit_sync(&mut app_seed, db.clone(), TEST_STORE).unwrap();
let mut app = App::new();
app.add_plugins(PersistencePlugins::new(db.clone()));
#[derive(Resource, Default)]
struct JoinState { joined_count: usize }
app.insert_resource(JoinState::default());
fn sys_load(mut pq: PersistentQuery<(&Health, &Position)>) { let _ = pq.ensure_loaded(); }
app.add_systems(Update, sys_load);
fn sys_join(
mut common: PersistentQuery<(&Health, &Position)>,
mut names: Query<&PlayerName>,
mut st: ResMut<JoinState>,
wp: Res<ImmediateWorldPtr>,
) {
let _: QueryLens<(&Health, &Position, &PlayerName), ()> = names.join_filtered(&mut *common);
let world: &World = wp.as_world();
if let Some(mut qs) = QueryState::<(&Health, &Position, &PlayerName), ()>::try_new(world) {
st.joined_count = qs.iter(world).count();
} else {
st.joined_count = 0;
}
}
app.add_systems(PostUpdate, sys_join.after(PersistenceSystemSet::PreCommit));
app.update();
let st = app.world().resource::<JoinState>();
assert_eq!(st.joined_count, 1);
}
#[db_matrix_test]
fn test_join_between_two_persistent_queries_loaded_inline() {
let (db, _container) = setup();
let mut app_seed = App::new();
app_seed.add_plugins(PersistencePlugins::new(db.clone()));
app_seed.world_mut().spawn((Health { value: 1 }, Position { x: 0.0, y: 0.0 }, PlayerName { name: "alice".into() })); app_seed.world_mut().spawn((Health { value: 2 }, Position { x: 1.0, y: 1.0 })); app_seed.world_mut().spawn(PlayerName { name: "bob".into() }); app_seed.update();
commit_sync(&mut app_seed, db.clone(), TEST_STORE).unwrap();
let mut app = App::new();
app.add_plugins(PersistencePlugins::new(db.clone()));
#[derive(Resource, Default)]
struct JoinState {
joined_count: usize,
}
app.insert_resource(JoinState::default());
fn sys_join(
mut common: PersistentQuery<(&Health, &Position)>,
mut names: PersistentQuery<&PlayerName>,
mut st: ResMut<JoinState>,
wp: Res<ImmediateWorldPtr>,
) {
let _: QueryLens<(&Health, &Position, &PlayerName), ()> = names.join_filtered(&mut common);
let world: &World = wp.as_world();
if let Some(mut qs) = QueryState::<(&Health, &Position, &PlayerName), ()>::try_new(world) {
st.joined_count = qs.iter(world).count();
} else {
st.joined_count = 0;
}
}
app.add_systems(PostUpdate, sys_join.after(PersistenceSystemSet::PreCommit));
app.update();
let st = app.world().resource::<JoinState>();
assert_eq!(st.joined_count, 1, "expected exactly one joined result");
let mut q_all = app.world_mut().query::<(&Health, &Position, &PlayerName)>();
assert_eq!(q_all.iter(&app.world()).count(), 1);
let mut q_h = app.world_mut().query::<&Health>();
let mut q_p = app.world_mut().query::<&Position>();
let mut q_n = app.world_mut().query::<&PlayerName>();
assert_eq!(q_h.iter(&app.world()).count(), 1, "no extra Health-only");
assert_eq!(q_p.iter(&app.world()).count(), 1, "no extra Position-only");
assert_eq!(q_n.iter(&app.world()).count(), 1, "no extra PlayerName-only");
}