1#![allow(missing_docs)]
2
3use crate::debug::TableEntry;
4use crate::durability::Durability;
5use crate::Cycle;
6use crate::Database;
7use crate::Query;
8use crate::QueryTable;
9use crate::QueryTableMut;
10use std::borrow::Borrow;
11use std::fmt::Debug;
12use std::hash::Hash;
13use triomphe::Arc;
14
15pub use crate::derived::DependencyStorage;
16pub use crate::derived::MemoizedStorage;
17pub use crate::input::InputStorage;
18pub use crate::interned::InternedStorage;
19pub use crate::interned::LookupInternedStorage;
20pub use crate::{revision::Revision, DatabaseKeyIndex, QueryDb, Runtime};
21
22pub trait DatabaseStorageTypes: Database {
27 type DatabaseStorage: Default;
30}
31
32pub trait DatabaseOps {
34 fn ops_database(&self) -> &dyn Database;
36
37 fn ops_salsa_runtime(&self) -> &Runtime;
39
40 fn ops_salsa_runtime_mut(&mut self) -> &mut Runtime;
42
43 fn fmt_index(
45 &self,
46 index: DatabaseKeyIndex,
47 fmt: &mut std::fmt::Formatter<'_>,
48 ) -> std::fmt::Result;
49
50 fn maybe_changed_after(&self, input: DatabaseKeyIndex, revision: Revision) -> bool;
52
53 fn cycle_recovery_strategy(&self, input: DatabaseKeyIndex) -> CycleRecoveryStrategy;
55
56 fn for_each_query(&self, op: &mut dyn FnMut(&dyn QueryStorageMassOps));
58}
59
60pub trait QueryStorageMassOps {
64 fn purge(&self);
65}
66
67pub trait DatabaseKey: Clone + Debug + Eq + Hash {}
68
69pub trait QueryFunction: Query {
70 const CYCLE_STRATEGY: CycleRecoveryStrategy;
72
73 fn execute(db: &<Self as QueryDb<'_>>::DynDb, key: Self::Key) -> Self::Value;
74
75 fn cycle_fallback(
76 db: &<Self as QueryDb<'_>>::DynDb,
77 cycle: &Cycle,
78 key: &Self::Key,
79 ) -> Self::Value {
80 let _ = (db, cycle, key);
81 panic!(
82 "query `{:?}` doesn't support cycle fallback",
83 Self::default()
84 )
85 }
86}
87
88#[derive(Copy, Clone, Debug, PartialEq, Eq)]
91pub enum CycleRecoveryStrategy {
92 Panic,
101
102 Fallback,
107}
108
109pub fn get_query_table<'me, Q>(db: &'me <Q as QueryDb<'me>>::DynDb) -> QueryTable<'me, Q>
112where
113 Q: Query + 'me,
114 Q::Storage: QueryStorageOps<Q>,
115{
116 let group_storage: &Q::GroupStorage = HasQueryGroup::group_storage(db);
117 let query_storage: &Q::Storage = Q::query_storage(group_storage);
118 QueryTable::new(db, query_storage)
119}
120
121pub fn get_query_table_mut<'me, Q>(db: &'me mut <Q as QueryDb<'me>>::DynDb) -> QueryTableMut<'me, Q>
124where
125 Q: Query,
126{
127 let (group_storage, runtime) = HasQueryGroup::group_storage_mut(db);
128 let query_storage = Q::query_storage_mut(group_storage);
129 QueryTableMut::new(runtime, &**query_storage)
130}
131
132pub trait QueryGroup: Sized {
133 type GroupStorage;
134
135 type DynDb: ?Sized + Database + HasQueryGroup<Self>;
137}
138
139pub trait HasQueryGroup<G>: Database
142where
143 G: QueryGroup,
144{
145 fn group_storage(&self) -> &G::GroupStorage;
147
148 fn group_storage_mut(&mut self) -> (&G::GroupStorage, &mut Runtime);
152}
153
154pub trait QueryStorageOps<Q>
156where
157 Self: QueryStorageMassOps,
158 Q: Query,
159{
160 const CYCLE_STRATEGY: CycleRecoveryStrategy;
164
165 fn new(group_index: u16) -> Self;
166
167 fn fmt_index(
169 &self,
170 db: &<Q as QueryDb<'_>>::DynDb,
171 index: DatabaseKeyIndex,
172 fmt: &mut std::fmt::Formatter<'_>,
173 ) -> std::fmt::Result;
174
175 fn maybe_changed_after(
182 &self,
183 db: &<Q as QueryDb<'_>>::DynDb,
184 input: DatabaseKeyIndex,
185 revision: Revision,
186 ) -> bool;
187 fn cycle_recovery_strategy(&self) -> CycleRecoveryStrategy {
190 Self::CYCLE_STRATEGY
191 }
192
193 fn fetch(&self, db: &<Q as QueryDb<'_>>::DynDb, key: &Q::Key) -> Q::Value;
202 fn durability(&self, db: &<Q as QueryDb<'_>>::DynDb, key: &Q::Key) -> Durability;
206
207 fn entries<C>(&self, db: &<Q as QueryDb<'_>>::DynDb) -> C
209 where
210 C: std::iter::FromIterator<TableEntry<Q::Key, Q::Value>>;
211}
212
213pub trait InputQueryStorageOps<Q>
217where
218 Q: Query,
219{
220 fn set(&self, runtime: &mut Runtime, key: &Q::Key, new_value: Q::Value, durability: Durability);
221}
222
223pub trait LruQueryStorageOps {
227 fn set_lru_capacity(&self, new_capacity: usize);
228}
229
230pub trait DerivedQueryStorageOps<Q>
231where
232 Q: Query,
233{
234 fn invalidate<S>(&self, runtime: &mut Runtime, key: &S)
235 where
236 S: Eq + Hash,
237 Q::Key: Borrow<S>;
238}
239
240pub type CycleParticipants = Arc<Vec<DatabaseKeyIndex>>;