1use crate::*;
2use async_trait::async_trait;
3
4use bevy_ecs::query::{QueryItem, ROQueryItem, WorldQuery};
5use bevy_ecs::{
6 component::Component, prelude::*, system::SystemParam,
7 world::unsafe_world_cell::UnsafeWorldCell,
8};
9use bevy_mod_index::prelude::*;
10use bevy_utils::hashbrown::HashSet;
11use casey::lower;
12
13#[async_trait]
14pub trait CustomDatabaseQuery<DbResource: DatabaseResource, DerefItem: Send>: Sync {
15 async fn query(
16 &self,
17 tr: DatabaseTransaction<DbResource>,
18 ) -> Result<Vec<(DatabaseEntity, DerefItem)>, ()>;
19}
20
21pub trait ReturnSelector<'w> {
22 type ReturnItem;
23
24 fn load_components_from_entities(
25 world: UnsafeWorldCell<'w>,
26 entities: Vec<Entity>,
27 ) -> Vec<Self::ReturnItem>;
28}
29
30pub type DatabaseTransaction<'a, D> = <D as DatabaseResource>::Transaction;
31
32pub type ReadOnlyItem<'a, Q, DbResource> =
35 ROQueryItem<'a, <Q as DBQueryInfo<DbResource>>::WorldQuery<'a>>;
36pub type Item<'a, Q, DbResource> = QueryItem<'a, <Q as DBQueryInfo<DbResource>>::WorldQuery<'a>>;
37#[async_trait]
38pub trait DBQueryInfo<DbResource: DatabaseResource> {
39 type WorldQuery<'a>: WorldQuery;
44 type DerefItem: Send;
45 type ReadOnlyItem<'a>: Send + From<ReadOnlyItem<'a, Self, DbResource>>;
46 type Item<'a>: Send;
47
48 async fn get<'w, D: DatabaseEntityWithRequest>(
49 db: &DbResource,
50 world: UnsafeWorldCell<'w>,
51 db_entity: &D,
52 ) -> Result<Self::ReadOnlyItem<'w>, ()>;
53 async fn get_mut<'w, D: DatabaseEntityWithRequest>(
54 db: &DbResource,
55 world: UnsafeWorldCell<'w>,
56 db_entity: &D,
57 ) -> Result<Self::Item<'w>, ()>;
58 async fn update_component<'w>(
59 db: &DbResource,
60 world: UnsafeWorldCell<'w>,
61 db_entity: &DatabaseEntity,
62 component: Self::ReadOnlyItem<'w>,
63 ) -> Result<(), ()>;
64 async fn insert_component<'w>(
65 db: &DbResource,
66 world: UnsafeWorldCell<'w>,
67 db_entity: &DatabaseEntity,
68 component: Self::ReadOnlyItem<'w>,
69 ) -> Result<(), ()>;
70 async fn load_components<'w, R: ReturnSelector<'w>, CDQ>(
71 db: &DbResource,
72 world: UnsafeWorldCell<'w>,
73 request: RequestId,
74 get_comp_from_db: CDQ,
75 ) -> Result<Vec<<R as ReturnSelector<'w>>::ReturnItem>, ()>
76 where
77 CDQ: CustomDatabaseQuery<DbResource, Self::DerefItem> + Send;
78 async fn create(
79 db: &DbResource,
80 world: UnsafeWorldCell<'_>,
81 component: Self::DerefItem,
82 request: RequestId,
83 ) -> Result<(), ()>;
84}
85
86pub struct QueryFetchState<'w, 's, DbResource: DatabaseResource> {
87 db_state: <Res<'w, DbResource> as SystemParam>::State,
88 phantom: std::marker::PhantomData<&'s ()>,
89}
90
91pub struct DatabaseQuery<'world, 'state, Q: DBQueryInfo<DbResource>, DbResource: DatabaseResource> {
92 db: Res<'world, DbResource>,
94 world: UnsafeWorldCell<'world>,
95 phantom2: std::marker::PhantomData<(&'state (), Q)>,
96}
97
98pub trait B {}
99
100pub trait A<B> {}
101
102unsafe impl<'w, 's, I: DBQueryInfo<DbResource>, DbResource: DatabaseResource> SystemParam
104 for DatabaseQuery<'w, 's, I, DbResource>
105where
106 I: DBQueryInfo<DbResource> + 'static,
107{
108 type State = QueryFetchState<'static, 'static, DbResource>;
109
110 type Item<'world, 'state> = DatabaseQuery<'world, 'state, I, DbResource>;
111
112 fn init_state(
113 world: &mut World,
114 system_meta: &mut bevy_ecs::system::SystemMeta,
115 ) -> Self::State {
116 if !world.contains_resource::<DbResource>() {
118 world.init_resource::<DbResource>();
119 }
120
121 QueryFetchState {
122 db_state: <Res<'w, DbResource>>::init_state(world, system_meta),
123 phantom: std::marker::PhantomData,
124 }
125 }
126
127 unsafe fn get_param<'w2, 's2>(
128 state: &'s2 mut Self::State,
129 system_meta: &bevy_ecs::system::SystemMeta,
130 world: UnsafeWorldCell<'w2>,
131 change_tick: bevy_ecs::component::Tick,
132 ) -> Self::Item<'w2, 's2> {
133 let db_query = DatabaseQuery {
134 db: <Res<'w2, DbResource>>::get_param(
135 &mut state.db_state,
136 system_meta,
137 world,
138 change_tick,
139 ),
140 world,
141 phantom2: std::marker::PhantomData,
142 };
143
144 db_query
145 }
146}
147
148pub trait DatabaseEntityWithRequest: Sync + Send {
149 fn request(&self) -> &RequestId;
150 fn id(&self) -> &DatabaseEntityId;
151}
152
153impl<'w, 's, Q: DBQueryInfo<DbResource>, DbResource: DatabaseResource>
154 DatabaseQuery<'w, 's, Q, DbResource>
155{
156 pub async fn get<D: DatabaseEntityWithRequest>(
157 &self,
158 db_entity: &D,
159 ) -> Result<Q::ReadOnlyItem<'w>, ()> {
160 Q::get(self.db.as_ref(), self.world, db_entity).await
161 }
162
163 pub async fn get_mut<D: DatabaseEntityWithRequest>(
164 &self,
165 db_entity: &D,
166 ) -> Result<Q::Item<'w>, ()> {
167 Q::get_mut(self.db.as_ref(), self.world, db_entity).await
168 }
169
170 pub async fn update_component(
171 &self,
172 db_entity: &DatabaseEntity,
173 component: Q::ReadOnlyItem<'w>,
174 ) -> Result<(), ()> {
175 Q::update_component(self.db.as_ref(), self.world, db_entity, component).await
176 }
177
178 pub async fn insert_component(
179 &self,
180 db_entity: &DatabaseEntity,
181 component: Q::ReadOnlyItem<'w>,
182 ) -> Result<(), ()> {
183 Q::insert_component(self.db.as_ref(), self.world, db_entity, component).await
184 }
185
186 pub async fn load_components<R: ReturnSelector<'w>, CDQ>(
187 &self,
188 request: RequestId,
189 get_comp_from_db: CDQ,
190 ) -> Result<Vec<<R as ReturnSelector<'w>>::ReturnItem>, ()>
191 where
192 CDQ: CustomDatabaseQuery<DbResource, Q::DerefItem> + Send,
193 {
194 Q::load_components::<R, CDQ>(self.db.as_ref(), self.world, request, get_comp_from_db).await
195 }
196
197 pub async fn create(&self, component: Q::DerefItem, request: RequestId) -> Result<(), ()> {
198 Q::create(self.db.as_ref(), self.world, component, request).await
199 }
200
201 pub async fn update_or_insert_component(&self, entity: Entity) -> Result<(), ()> {
202 unsafe {
203 let mut q = self
204 .world
205 .world_mut()
206 .query::<(&DatabaseEntity, Q::WorldQuery<'w>)>();
207 let (db_entity, comp) = q.get(self.world.world(), entity).unwrap();
208
209 if db_entity.persisted.into() {
210 if db_entity.dirty {
211 Q::update_component(self.db.as_ref(), self.world, db_entity, comp.into()).await
212 } else {
213 Ok(())
214 }
215 } else {
216 Q::insert_component(self.db.as_ref(), self.world, db_entity, comp.into()).await
217 }
218 }
219 }
220
221 pub fn commit(&self, request: RequestId) -> Result<(), ()> {
222 self.db.commit_transaction(request);
223
224 Ok(())
225 }
226}
227
228#[async_trait]
229pub trait ComponentMapper {
230 type Component;
231 type Executor: Send;
232
233 async fn get<'c>(
234 e: &mut Self::Executor,
235 db_entity: &DatabaseEntityId,
236 ) -> Result<Self::Component, ()>;
237
238 async fn update_component<'c>(
239 tr: &mut Self::Executor,
240 db_entity: &DatabaseEntityId,
241 component: &Self::Component,
242 ) -> Result<(), ()>;
243
244 async fn insert_component<'c>(
245 tr: &mut Self::Executor,
246 db_entity: &DatabaseEntityId,
247 component: &Self::Component,
248 ) -> Result<(), ()>;
249}
250
251#[derive(Component)]
252pub struct NullComponent();
253
254impl RequestIdIndexInfo for NullComponent {}
255
256impl IndexInfo for NullComponent {
258 type Component = NullComponent;
259 type Value = RequestId;
260 type Storage = NoStorage<Self>;
261
262 fn value(_c: &Self::Component) -> Self::Value {
263 RequestId(generational_arena::Index::from_raw_parts(0, 0))
264 }
265}
266
267pub struct NullMapper;
268#[async_trait]
269impl ComponentMapper for NullMapper {
270 type Component = NullComponent;
271 type Executor = ();
272
273 async fn get<'c>(
274 _e: &mut Self::Executor,
275 _db_entity: &DatabaseEntityId,
276 ) -> Result<Self::Component, ()> {
277 unimplemented!()
278 }
279
280 async fn update_component<'c>(
281 _tr: &mut Self::Executor,
282 _db_entity: &DatabaseEntityId,
283 _component: &Self::Component,
284 ) -> Result<(), ()> {
285 unimplemented!()
286 }
287
288 async fn insert_component<'c>(
289 _tr: &mut Self::Executor,
290 _db_entity: &DatabaseEntityId,
291 _component: &Self::Component,
292 ) -> Result<(), ()> {
293 unimplemented!()
294 }
295}
296
297pub trait ReadMarker<DbResource: DatabaseResource>: DBQueryInfo<DbResource> {}
299
300pub trait TupleMarker<DbResource: DatabaseResource>: DBQueryInfo<DbResource> {}
303
304impl<T: DBQueryInfo<DbResource>, DbResource: DatabaseResource> TupleMarker<DbResource> for Option<T> where
305 for<'a> Option<<T as DBQueryInfo<DbResource>>::ReadOnlyItem<'a>>:
306 From<Option<ReadOnlyItem<'a, T, DbResource>>>
307{
308}
309
310#[async_trait]
311impl<T: DBQueryInfo<DbResource>, DbResource: DatabaseResource> DBQueryInfo<DbResource> for Option<T>
312where
313 for<'a> Option<<T as DBQueryInfo<DbResource>>::ReadOnlyItem<'a>>:
314 From<Option<ReadOnlyItem<'a, T, DbResource>>>,
315{
316 type DerefItem = Option<<T as DBQueryInfo<DbResource>>::DerefItem>;
317
318 type WorldQuery<'a> = Option<<T as DBQueryInfo<DbResource>>::WorldQuery<'a>>;
321
322 type ReadOnlyItem<'a> = Option<<T as DBQueryInfo<DbResource>>::ReadOnlyItem<'a>>;
323
324 type Item<'a> = Option<<T as DBQueryInfo<DbResource>>::Item<'a>>;
325
326 async fn get<'w, D: DatabaseEntityWithRequest>(
327 db: &DbResource,
328 world: UnsafeWorldCell<'w>,
329 db_entity: &D,
330 ) -> Result<Self::ReadOnlyItem<'w>, ()> {
331 T::get(db, world, db_entity).await.map(Some)
332 }
333
334 async fn get_mut<'w, D: DatabaseEntityWithRequest>(
335 db: &DbResource,
336 world: UnsafeWorldCell<'w>,
337 db_entity: &D,
338 ) -> Result<Self::Item<'w>, ()> {
339 T::get_mut(db, world, db_entity).await.map(Some)
340 }
341
342 async fn update_component<'w>(
343 db: &DbResource,
344 world: UnsafeWorldCell<'w>,
345 db_entity: &DatabaseEntity,
346 component: Self::ReadOnlyItem<'w>,
347 ) -> Result<(), ()> {
348 if let Some(component) = component {
349 T::update_component(db, world, db_entity, component).await
350 } else {
351 Ok(())
352 }
353 }
354
355 async fn insert_component<'w>(
356 db: &DbResource,
357 world: UnsafeWorldCell<'w>,
358 db_entity: &DatabaseEntity,
359 component: Self::ReadOnlyItem<'w>,
360 ) -> Result<(), ()> {
361 if let Some(component) = component {
362 T::insert_component(db, world, db_entity, component).await
363 } else {
364 Ok(())
365 }
366 }
367
368 async fn load_components<'w, R: ReturnSelector<'w>, CDQ>(
369 _db: &DbResource,
370 _world: UnsafeWorldCell<'w>,
371 _request: RequestId,
372 _get_comp_from_db: CDQ,
373 ) -> Result<Vec<<R as ReturnSelector<'w>>::ReturnItem>, ()>
374 where
375 CDQ: CustomDatabaseQuery<DbResource, Self::DerefItem> + Send,
376 {
377 Err(())
378 }
379
380 async fn create(
381 db: &DbResource,
382 world: UnsafeWorldCell<'_>,
383 component: Self::DerefItem,
384 request: RequestId,
385 ) -> Result<(), ()> {
386 if let Some(component) = component {
387 T::create(db, world, component, request).await
388 } else {
389 Ok(())
390 }
391 }
392}
393
394impl<'a, T: ComponentMapper, DbResource: DatabaseResource<Transaction = T::Executor>>
395 TupleMarker<DbResource> for &T
396where
397 <T as ComponentMapper>::Component: Component,
398{
399}
400
401impl<'a, T: ComponentMapper, DbResource: DatabaseResource<Transaction = T::Executor>>
402 ReadMarker<DbResource> for &T
403where
404 <T as ComponentMapper>::Component: Component,
405{
406}
407
408#[async_trait]
409impl<'b, T: ComponentMapper, DbResource: DatabaseResource<Transaction = T::Executor>>
410 DBQueryInfo<DbResource> for &T
411where
412 <T as ComponentMapper>::Component: Component,
413{
414 type DerefItem = <T as ComponentMapper>::Component;
415 type WorldQuery<'a> = &'a <T as ComponentMapper>::Component;
417
418 type ReadOnlyItem<'a> = &'a <T as ComponentMapper>::Component;
419
420 type Item<'a> = &'a <T as ComponentMapper>::Component;
421
422 async fn get<'w, D: DatabaseEntityWithRequest>(
423 db: &DbResource,
424 world: UnsafeWorldCell<'w>,
425 db_entity: &D,
426 ) -> Result<Self::ReadOnlyItem<'w>, ()> {
427 SingleComponentRetriever::<T, DbResource>::get(db, world, db_entity).await
428 }
429
430 async fn get_mut<'w, D: DatabaseEntityWithRequest>(
431 db: &DbResource,
432 world: UnsafeWorldCell<'w>,
433 db_entity: &D,
434 ) -> Result<Self::Item<'w>, ()> {
435 SingleComponentRetriever::<T, DbResource>::get(db, world, db_entity).await
436 }
437
438 async fn update_component<'w>(
439 db: &DbResource,
440 world: UnsafeWorldCell<'w>,
441 db_entity: &DatabaseEntity,
442 component: Self::ReadOnlyItem<'w>,
443 ) -> Result<(), ()> {
444 SingleComponentRetriever::<T, DbResource>::update_component(db, world, db_entity, component)
445 .await
446 }
447
448 async fn insert_component<'w>(
449 db: &DbResource,
450 world: UnsafeWorldCell<'w>,
451 db_entity: &DatabaseEntity,
452 component: Self::ReadOnlyItem<'w>,
453 ) -> Result<(), ()> {
454 SingleComponentRetriever::<T, DbResource>::insert_component(db, world, db_entity, component)
455 .await
456 }
457
458 async fn load_components<'w, R: ReturnSelector<'w>, CDQ>(
459 db: &DbResource,
460 world: UnsafeWorldCell<'w>,
461 request: RequestId,
462 get_comp_from_db: CDQ,
463 ) -> Result<Vec<<R as ReturnSelector<'w>>::ReturnItem>, ()>
464 where
465 CDQ: CustomDatabaseQuery<DbResource, Self::DerefItem> + Send,
466 {
467 SingleComponentRetriever::<T, DbResource>::load_components::<R, CDQ>(
468 db,
469 world,
470 request,
471 get_comp_from_db,
472 )
473 .await
474 }
475
476 async fn create(
477 db: &DbResource,
478 world: UnsafeWorldCell<'_>,
479 component: Self::DerefItem,
480 request: RequestId,
481 ) -> Result<(), ()> {
482 SingleComponentRetriever::<T, DbResource>::create(db, world, component, request).await
483 }
484}
485
486impl<'b, T: ComponentMapper, DbResource: DatabaseResource<Transaction = T::Executor>>
487 ReadMarker<DbResource> for &mut T
488where
489 <T as ComponentMapper>::Component: Component,
490{
491}
492
493#[async_trait]
494impl<'b, T: ComponentMapper, DbResource: DatabaseResource<Transaction = T::Executor>>
495 DBQueryInfo<DbResource> for &mut T
496where
497 <T as ComponentMapper>::Component: Component,
498{
499 type DerefItem = <T as ComponentMapper>::Component;
500 type WorldQuery<'a> = &'a mut <T as ComponentMapper>::Component;
502
503 type ReadOnlyItem<'a> = &'a <T as ComponentMapper>::Component;
504
505 type Item<'a> = Mut<'a, <T as ComponentMapper>::Component>;
506
507 async fn get<'w, D: DatabaseEntityWithRequest>(
508 db: &DbResource,
509 world: UnsafeWorldCell<'w>,
510 db_entity: &D,
511 ) -> Result<Self::ReadOnlyItem<'w>, ()> {
512 SingleComponentRetriever::<T, DbResource>::get(db, world, db_entity).await
513 }
514
515 async fn get_mut<'w, D: DatabaseEntityWithRequest>(
516 db: &DbResource,
517 world: UnsafeWorldCell<'w>,
518 db_entity: &D,
519 ) -> Result<Self::Item<'w>, ()> {
520 SingleComponentRetriever::<T, DbResource>::get_mut(db, world, db_entity).await
521 }
522
523 async fn update_component<'w>(
524 db: &DbResource,
525 world: UnsafeWorldCell<'w>,
526 db_entity: &DatabaseEntity,
527 component: Self::ReadOnlyItem<'w>,
528 ) -> Result<(), ()> {
529 SingleComponentRetriever::<T, DbResource>::update_component(db, world, db_entity, component)
530 .await
531 }
532
533 async fn insert_component<'w>(
534 db: &DbResource,
535 world: UnsafeWorldCell<'w>,
536 db_entity: &DatabaseEntity,
537 component: Self::ReadOnlyItem<'w>,
538 ) -> Result<(), ()> {
539 SingleComponentRetriever::<T, DbResource>::insert_component(db, world, db_entity, component)
540 .await
541 }
542
543 async fn load_components<'w, R: ReturnSelector<'w>, CDQ>(
544 db: &DbResource,
545 world: UnsafeWorldCell<'w>,
546 request: RequestId,
547 get_comp_from_db: CDQ,
548 ) -> Result<Vec<<R as ReturnSelector<'w>>::ReturnItem>, ()>
549 where
550 CDQ: CustomDatabaseQuery<DbResource, Self::DerefItem> + Send,
551 {
552 SingleComponentRetriever::<T, DbResource>::load_components::<R, CDQ>(
553 db,
554 world,
555 request,
556 get_comp_from_db,
557 )
558 .await
559 }
560
561 async fn create(
562 db: &DbResource,
563 world: UnsafeWorldCell<'_>,
564 component: Self::DerefItem,
565 request: RequestId,
566 ) -> Result<(), ()> {
567 SingleComponentRetriever::<T, DbResource>::create(db, world, component, request).await
568 }
569}
570
571macro_rules! simple_composition_of_db_queries {
577 ( $( $name:ident )* ) => {
578 #[async_trait]
581 impl<Z: TupleMarker<DbResource>, $($name: TupleMarker<DbResource>, )* DbResource: DatabaseResource> DBQueryInfo<DbResource> for (Z, $($name,)*)
582 where
583 for<'a>
584 (
585 <Z as DBQueryInfo<DbResource>>::ReadOnlyItem<'a>,
586 $(<$name as DBQueryInfo<DbResource>>::ReadOnlyItem<'a>, )*
587 )
588 :
589 From<(
590 ReadOnlyItem<'a, Z, DbResource>,
591 $(ReadOnlyItem<'a, $name, DbResource>,)*
592 )>
593 {
594 type DerefItem = (Z::DerefItem, $($name::DerefItem,)*);
595 type WorldQuery<'a> = (Z::WorldQuery<'a>, $($name::WorldQuery<'a>,)*);
597
598 type ReadOnlyItem<'a> = (Z::ReadOnlyItem<'a>, $($name::ReadOnlyItem<'a>,)*);
599
600 type Item<'a> = (Z::Item<'a>, $($name::Item<'a>,)*);
601
602 async fn get<'w, DbEntity: DatabaseEntityWithRequest>(db: &DbResource, world: UnsafeWorldCell<'w>, db_entity: &DbEntity) -> Result<Self::ReadOnlyItem<'w>, ()> {
603 Ok((
605 Z::get(db, world, db_entity).await?,
606 $(
607 {
608 $name::get(db, world, db_entity).await?
609 },
610 )*))
611 }
612
613 async fn get_mut<'w, DbEntity: DatabaseEntityWithRequest>(db: &DbResource, world: UnsafeWorldCell<'w>, db_entity: &DbEntity) -> Result<Self::Item<'w>, ()> {
614 Ok((
616 Z::get_mut(db, world, db_entity).await?,
617
618 $(
619 {
620 $name::get_mut(db, world, db_entity).await?
621 },
622 )*))
623 }
624
625 async fn update_component<'w>(db: &DbResource, world: UnsafeWorldCell<'w>, db_entity: &DatabaseEntity, component: Self::ReadOnlyItem<'w>) -> Result<(), ()> {
626
627 let (z, $(lower!($name),)*) = component;
628
629 Z::update_component(db, world, db_entity, z).await?;
630 $($name::update_component(db, world, db_entity, lower!($name)).await?;)*
631
632 Ok(())
633 }
634
635 async fn insert_component<'w>(db: &DbResource, world: UnsafeWorldCell<'w>, db_entity: &DatabaseEntity, component: Self::ReadOnlyItem<'w>) -> Result<(), ()> {
636 let (z, $(lower!($name),)*) = component;
637
638 Z::insert_component(db, world, db_entity, z).await?;
639 $($name::insert_component(db, world, db_entity, lower!($name)).await?;)*
640
641 Ok(())
642 }
643
644 async fn load_components<'w, R : ReturnSelector<'w>, CDQ>(
646 _db: &DbResource,
647 _world: UnsafeWorldCell<'w>,
648 _request: RequestId,
649 _get_comp_from_db: CDQ
650 ) -> Result<Vec<<R as ReturnSelector<'w>>::ReturnItem>, ()>
651 where
652 CDQ: CustomDatabaseQuery<DbResource, Self::DerefItem> + Send
653 {
654 unimplemented!()
655 }
656
657 async fn create(db: &DbResource, world: UnsafeWorldCell<'_>, component: Self::DerefItem, request: RequestId) -> Result<(), ()> {
658 let (z, $(lower!($name),)*) = component;
659
660 Z::create(db, world, z, request).await?;
661 $($name::create(db, world, lower!($name), request).await?;)*
662
663 Ok(())
664 }
665 }
666 }
667}
668
669simple_composition_of_db_queries! {A}
674simple_composition_of_db_queries! {A B}
675simple_composition_of_db_queries! {A B C}
676simple_composition_of_db_queries! {A B C D}
677#[derive(Default)]
686pub struct SingleComponentRetriever<Mapper, DbResource> {
687 phantom: std::marker::PhantomData<(Mapper, DbResource)>,
688}
689
690impl<
691 'a,
692 MyMapper: ComponentMapper,
693 DbResource: DatabaseResource<Transaction = <MyMapper as ComponentMapper>::Executor>,
694 > SingleComponentRetriever<MyMapper, DbResource>
695where
696 <MyMapper as ComponentMapper>::Component: Component,
697{
698 pub async fn get_internal<D: DatabaseEntityWithRequest>(
699 db: &DbResource,
700 world: UnsafeWorldCell<'_>,
701 db_entity: &D,
702 component_preloaded: Option<<MyMapper as ComponentMapper>::Component>,
703 ) -> Entity {
704 let mut tr = db.get_transaction(*db_entity.request());
705
706 let db_entity_id = *db_entity.id();
707
708 let mut reader = IntoSystem::into_system(
709 move |mut index: Index<DatabaseEntityIndex>| -> HashSet<Entity> {
710 index.lookup(&db_entity_id)
711 },
712 );
713
714 let entity_set: HashSet<Entity> = unsafe {
715 reader.initialize(world.world_mut());
716 reader.run((), world.world_mut())
717 };
718
719 match entity_set.iter().next() {
720 Some(entity) => {
722 match unsafe {
723 world
724 .world_mut()
725 .get::<<MyMapper as ComponentMapper>::Component>(*entity)
726 } {
727 Some(_) => *entity,
729 None => {
731 let db_component = match component_preloaded {
732 Some(component) => component,
733 None => MyMapper::get(&mut tr, db_entity.id()).await.unwrap(),
734 };
735 unsafe {
737 let w = world.world_mut();
738 w.entity_mut(*entity).insert(db_component);
739 *entity
740 }
741 }
742 }
743 }
744 None => {
746 let component = match component_preloaded {
747 Some(component) => component,
748 None => MyMapper::get(&mut tr, db_entity.id()).await.unwrap(),
749 };
750 unsafe {
751 let w = world.world_mut();
752 let entity = w
753 .spawn((
754 DatabaseEntity {
755 id: *db_entity.id(),
756 persisted: true.into(),
757 dirty: false,
758 request: *db_entity.request(),
759 },
760 component,
761 ))
762 .id();
763 entity
764 }
765 }
766 }
767 }
768
769 pub async fn load_entities_for_components<CDQ>(
770 db: &DbResource,
771 world: UnsafeWorldCell<'_>,
772 request: RequestId,
773 get_comp_from_db: CDQ,
774 ) -> Result<Vec<Entity>, ()>
775 where
776 CDQ: CustomDatabaseQuery<DbResource, <MyMapper as ComponentMapper>::Component>,
777 {
778 let components = {
779 let tr = db.get_transaction(request);
780
781 get_comp_from_db.query(tr).await?
782 };
783
784 let mut entities = vec![];
785
786 for (db_entity, component) in components {
787 entities.push(Self::get_internal(db, world, &db_entity, Some(component)).await);
788 }
789
790 Ok(entities)
791 }
792
793 pub async fn update_or_insert_component(
794 db: &DbResource,
795 world: UnsafeWorldCell<'_>,
796 db_entity: &DatabaseEntity,
797 component: &MyMapper::Component,
798 ) -> Result<(), ()> {
799 if db_entity.persisted.into() {
800 if db_entity.dirty {
801 Self::update_component(db, world, db_entity, component).await
802 } else {
803 Ok(())
804 }
805 } else {
806 Self::insert_component(db, world, db_entity, component).await
807 }
808 }
809}
810
811impl<'w, C: WorldQuery> ReturnSelector<'w> for C {
812 type ReturnItem = C::Item<'w>;
813
814 fn load_components_from_entities(
815 world: UnsafeWorldCell<'w>,
816 entities: Vec<Entity>,
817 ) -> Vec<Self::ReturnItem> {
818 entities
819 .into_iter()
820 .map(|entity| unsafe {
821 let world = world.world_mut();
822 let mut q = world.query::<C>();
823 q.get_mut(world, entity).unwrap()
824 })
825 .collect()
826 }
827}
828
829#[async_trait]
830impl<
831 'b,
832 MyMapper: ComponentMapper,
833 DbResource: DatabaseResource<Transaction = <MyMapper as ComponentMapper>::Executor>,
834 > DBQueryInfo<DbResource> for SingleComponentRetriever<MyMapper, DbResource>
835where
836 <MyMapper as ComponentMapper>::Component: Component,
837{
838 type DerefItem = MyMapper::Component;
839 type WorldQuery<'a> = &'a mut MyMapper::Component;
840 type ReadOnlyItem<'a> = &'a MyMapper::Component;
841 type Item<'a> = Mut<'a, MyMapper::Component>;
842
843 async fn get<'w, D: DatabaseEntityWithRequest>(
844 db: &DbResource,
845 world: UnsafeWorldCell<'w>,
846 db_entity: &D,
847 ) -> Result<Self::ReadOnlyItem<'w>, ()> {
848 let entity = Self::get_internal(db, world, db_entity, None).await;
849
850 unsafe {
851 Ok(world
852 .world()
853 .get::<<MyMapper as ComponentMapper>::Component>(entity)
854 .unwrap())
855 }
856 }
857
858 async fn get_mut<'w, D: DatabaseEntityWithRequest>(
859 db: &DbResource,
860 world: UnsafeWorldCell<'w>,
861 db_entity: &D,
862 ) -> Result<Self::Item<'w>, ()> {
863 let entity = Self::get_internal(db, world, db_entity, None).await;
864
865 unsafe {
866 world
868 .get_entity(entity)
869 .unwrap()
870 .get_mut::<DatabaseEntity>()
871 .unwrap()
872 .dirty = true;
873
874 Ok(world
875 .get_entity(entity)
876 .unwrap()
877 .get_mut::<<MyMapper as ComponentMapper>::Component>()
878 .unwrap())
879 }
880 }
881
882 async fn update_component<'w>(
883 db: &DbResource,
884 _world: UnsafeWorldCell<'w>,
885 db_entity: &DatabaseEntity,
886 component: ReadOnlyItem<'w, Self, DbResource>,
887 ) -> Result<(), ()> {
888 let mut tr = db.get_transaction(*db_entity.request());
889
890 MyMapper::update_component(&mut tr, db_entity.id(), component).await
891 }
892
893 async fn insert_component<'w>(
894 db: &DbResource,
895 _world: UnsafeWorldCell<'w>,
896 db_entity: &DatabaseEntity,
897 component: ReadOnlyItem<'w, Self, DbResource>,
898 ) -> Result<(), ()> {
899 let mut tr = db.get_transaction(*db_entity.request());
900 MyMapper::insert_component(&mut tr, db_entity.id(), component).await
901 }
902
903 async fn load_components<'w, R: ReturnSelector<'w>, CDQ>(
904 db: &DbResource,
905 world: UnsafeWorldCell<'w>,
906 request: RequestId,
907 get_comp_from_db: CDQ,
908 ) -> Result<Vec<<R as ReturnSelector<'w>>::ReturnItem>, ()>
909 where
910 CDQ: CustomDatabaseQuery<DbResource, Self::DerefItem> + Send,
911 {
912 let entities =
913 Self::load_entities_for_components::<CDQ>(db, world, request, get_comp_from_db).await?;
914
915 let components = R::load_components_from_entities(world, entities);
916 Ok(components)
917 }
918
919 async fn create(
920 db: &DbResource,
921 world: UnsafeWorldCell<'_>,
922 component: Self::DerefItem,
923 request: RequestId,
924 ) -> Result<(), ()> {
925 unsafe {
926 let w = world.world_mut();
927 w.spawn((
928 component,
929 DatabaseEntity {
930 id: db.get_key(),
931 persisted: false.into(),
932 dirty: false,
933 request,
934 },
935 ));
936 }
937
938 Ok(())
939 }
940}