pub struct CachedDatabaseAdapter<A: DatabaseAdapter> { /* private fields */ }Expand description
Cached database adapter wrapper.
Wraps any DatabaseAdapter implementation with transparent query result caching.
Cache keys include query, variables, WHERE clause, and schema version for security
and correctness.
§Cache Behavior
- Cache Hit: Returns cached result in ~0.1ms (50-200x faster than database)
- Cache Miss: Executes query via underlying adapter, stores result in cache
- Invalidation: Call
invalidate_views()after mutations to clear affected caches
§Thread Safety
This adapter is Send + Sync and can be safely shared across async tasks.
The underlying cache uses Arc<Mutex<>> for thread-safe access.
§Example
use fraiseql_core::cache::{CachedDatabaseAdapter, QueryResultCache, CacheConfig, InvalidationContext};
use fraiseql_core::db::{postgres::PostgresAdapter, DatabaseAdapter};
let db = PostgresAdapter::new("postgresql://localhost/db").await?;
let cache = QueryResultCache::new(CacheConfig::default());
let adapter = CachedDatabaseAdapter::new(db, cache, "1.0.0".to_string());
// First query - cache miss (slower)
let users1 = adapter.execute_where_query("v_user", None, None, None, None).await?;
// Second query - cache hit (fast!)
let users2 = adapter.execute_where_query("v_user", None, None, None, None).await?;
// After mutation, invalidate
let invalidation = InvalidationContext::for_mutation(
"createUser",
vec!["v_user".to_string()]
);
adapter.invalidate_views(&invalidation.modified_views)?;Implementations§
Source§impl<A: DatabaseAdapter> CachedDatabaseAdapter<A>
impl<A: DatabaseAdapter> CachedDatabaseAdapter<A>
Sourcepub fn new(adapter: A, cache: QueryResultCache, schema_version: String) -> Self
pub fn new(adapter: A, cache: QueryResultCache, schema_version: String) -> Self
Create new cached database adapter.
§Arguments
adapter- Underlying database adapter to wrapcache- Query result cache instanceschema_version- Uniquely identifies the compiled schema. Useschema.content_hash()(NOTenv!("CARGO_PKG_VERSION")) so that any schema content change automatically invalidates cached entries across deploys.
§Example
use fraiseql_core::cache::{CachedDatabaseAdapter, QueryResultCache, CacheConfig};
use fraiseql_core::db::postgres::PostgresAdapter;
use fraiseql_core::schema::CompiledSchema;
let db = PostgresAdapter::new("postgresql://localhost/db").await?;
let cache = QueryResultCache::new(CacheConfig::default());
let adapter = CachedDatabaseAdapter::new(
db,
cache,
schema.content_hash() // Use content hash for automatic invalidation
);Sourcepub fn with_view_ttl_overrides(self, overrides: HashMap<String, u64>) -> Self
pub fn with_view_ttl_overrides(self, overrides: HashMap<String, u64>) -> Self
Set per-view TTL overrides.
Maps sql_source (view name) → TTL in seconds. Built at server startup
from compiled QueryDefinition::cache_ttl_seconds entries.
§Example
let overrides = std::collections::HashMap::from([
("v_country".to_string(), 3600_u64), // 1 h for reference data
("v_live_price".to_string(), 0_u64), // no TTL — mutation-invalidated only
]);
let adapter = CachedDatabaseAdapter::new(db, cache, "1.0.0".to_string())
.with_view_ttl_overrides(overrides);Sourcepub fn with_cascade_invalidator(self, invalidator: CascadeInvalidator) -> Self
pub fn with_cascade_invalidator(self, invalidator: CascadeInvalidator) -> Self
Set a cascade invalidator for transitive view dependency expansion.
When set, invalidate_views() uses BFS to expand the initial view list
to include all views that transitively depend on the invalidated views.
§Example
let mut cascade = CascadeInvalidator::new();
cascade.add_dependency("v_user_stats", "v_user")?;
cascade.add_dependency("v_dashboard", "v_user_stats")?;
let adapter = CachedDatabaseAdapter::new(db, cache, "1.0.0".to_string())
.with_cascade_invalidator(cascade);Sourcepub fn with_ttl_overrides_from_schema(self, schema: &CompiledSchema) -> Self
pub fn with_ttl_overrides_from_schema(self, schema: &CompiledSchema) -> Self
Populate per-view TTL overrides from a compiled schema.
For each query that has cache_ttl_seconds set and a non-null sql_source,
this maps the view name → TTL so the cache adapter uses the per-query TTL
instead of the global default.
§Example
let adapter = CachedDatabaseAdapter::new(db, cache, "1.0.0".to_string())
.with_ttl_overrides_from_schema(&schema);Sourcepub fn with_fact_table_config(
adapter: A,
cache: QueryResultCache,
schema_version: String,
fact_table_config: FactTableCacheConfig,
) -> Self
pub fn with_fact_table_config( adapter: A, cache: QueryResultCache, schema_version: String, fact_table_config: FactTableCacheConfig, ) -> Self
Create new cached database adapter with fact table caching configuration.
§Arguments
adapter- Underlying database adapter to wrapcache- Query result cache instanceschema_version- Current schema version (e.g., git hash, semver)fact_table_config- Configuration for fact table aggregation caching
§Example
use fraiseql_core::cache::{
CachedDatabaseAdapter, QueryResultCache, CacheConfig,
FactTableCacheConfig, FactTableVersionStrategy,
};
use fraiseql_core::db::postgres::PostgresAdapter;
let db = PostgresAdapter::new("postgresql://localhost/db").await?;
let cache = QueryResultCache::new(CacheConfig::default());
// Configure fact table caching strategies
let mut ft_config = FactTableCacheConfig::default();
ft_config.set_strategy("tf_sales", FactTableVersionStrategy::VersionTable);
ft_config.set_strategy("tf_events", FactTableVersionStrategy::time_based(300));
let adapter = CachedDatabaseAdapter::with_fact_table_config(
db,
cache,
"1.0.0".to_string(),
ft_config,
);Sourcepub const fn inner(&self) -> &A
pub const fn inner(&self) -> &A
Get reference to underlying adapter.
Useful for accessing adapter-specific methods not in the DatabaseAdapter trait.
§Example
// Access PostgreSQL-specific functionality
let pg_adapter = adapter.inner();Sourcepub fn cache(&self) -> &QueryResultCache
pub fn cache(&self) -> &QueryResultCache
Get reference to cache.
Useful for metrics and monitoring.
§Example
let metrics = adapter.cache().metrics()?;
println!("Cache hit rate: {:.1}%", metrics.hit_rate() * 100.0);Sourcepub fn schema_version(&self) -> &str
pub fn schema_version(&self) -> &str
Sourcepub const fn fact_table_config(&self) -> &FactTableCacheConfig
pub const fn fact_table_config(&self) -> &FactTableCacheConfig
Get fact table cache configuration.
Sourcepub fn version_provider(&self) -> &FactTableVersionProvider
pub fn version_provider(&self) -> &FactTableVersionProvider
Get the version provider for fact tables.
Sourcepub async fn validate_rls_active(&self) -> Result<()>
pub async fn validate_rls_active(&self) -> Result<()>
Verify that Row-Level Security is active on the database connection.
Call this during server initialization when both caching and multi-tenancy
(schema.is_multi_tenant()) are enabled. Without RLS, users sharing the same
query parameters will receive the same cached response regardless of tenant.
§What this checks
Runs SELECT current_setting('row_security', true) AS rls_setting. The result
must be 'on' or 'force' for the check to pass. Non-PostgreSQL databases
(which return an error or unsupported) are treated as “RLS not active”.
§Errors
Returns FraiseQLError::Configuration if RLS appears inactive.
Sourcepub async fn enforce_rls(&self, enforcement: RlsEnforcement) -> Result<()>
pub async fn enforce_rls(&self, enforcement: RlsEnforcement) -> Result<()>
Apply the RLS enforcement policy from CacheConfig.
Runs validate_rls_active and handles the result
according to enforcement:
RlsEnforcement::Error: propagates the error (default)RlsEnforcement::Warn: logs a warning and returnsOk(())RlsEnforcement::Off: skips the check entirely
§Errors
Returns the error from validate_rls_active when enforcement is Error.
Source§impl<A: DatabaseAdapter> CachedDatabaseAdapter<A>
impl<A: DatabaseAdapter> CachedDatabaseAdapter<A>
Sourcepub async fn execute_aggregation_query(
&self,
sql: &str,
) -> Result<Vec<HashMap<String, Value>>>
pub async fn execute_aggregation_query( &self, sql: &str, ) -> Result<Vec<HashMap<String, Value>>>
Execute aggregation query with caching based on fact table versioning strategy.
This method provides transparent caching for aggregation queries on fact tables. The caching behavior depends on the configured strategy for the fact table.
§Arguments
sql- The aggregation SQL query
§Returns
Query results (from cache or database)
§Example
// This query will be cached according to tf_sales strategy
let results = adapter.execute_aggregation_query(
"SELECT SUM(revenue) FROM tf_sales WHERE year = 2024"
).await?;§Errors
Returns FraiseQLError if the underlying database query fails.
Source§impl<A: DatabaseAdapter> CachedDatabaseAdapter<A>
impl<A: DatabaseAdapter> CachedDatabaseAdapter<A>
Sourcepub fn invalidate_views(&self, views: &[String]) -> Result<u64>
pub fn invalidate_views(&self, views: &[String]) -> Result<u64>
Invalidate cache entries that read from specified views.
Call this after mutations to ensure cache consistency. All cache entries that accessed any of the modified views will be removed.
§Arguments
views- List of views/tables that were modified
§Returns
Number of cache entries invalidated
§Errors
Returns error if cache mutex is poisoned (very rare).
§Example
// After creating a user
let count = adapter.invalidate_views(&["v_user".to_string()])?;
println!("Invalidated {} cache entries", count);Sourcepub fn invalidate_cascade_entities(
&self,
cascade_response: &Value,
parser: &CascadeResponseParser,
) -> Result<u64>
pub fn invalidate_cascade_entities( &self, cascade_response: &Value, parser: &CascadeResponseParser, ) -> Result<u64>
Invalidate cache entries based on GraphQL Cascade response entities.
This is the entity-aware invalidation method that provides more precise invalidation. Instead of invalidating all caches reading from a view, only caches that depend on the affected entities are invalidated.
§Arguments
cascade_response- GraphQL mutation response with cascade fieldparser-CascadeResponseParserto extract entities
§Returns
Number of cache entries invalidated
§Example
let cascade_response = json!({
"createPost": {
"cascade": {
"updated": [
{ "__typename": "User", "id": "uuid-1" }
]
}
}
});
let parser = CascadeResponseParser::new();
let count = adapter.invalidate_cascade_entities(&cascade_response, &parser)?;
println!("Invalidated {} cache entries", count);§Note on Performance
This method replaces view-level invalidation with entity-level invalidation.
Instead of clearing all caches that touch a view (e.g., v_user), only caches
that touch the specific entities are cleared (e.g., User:uuid-1).
Expected improvement:
- View-level: 60-70% hit rate (many false positives)
- Entity-level: 90-95% hit rate (only true positives)
§Errors
Returns FraiseQLError if the cascade response cannot be parsed.
Sourcepub fn invalidate_list_queries(&self, views: &[String]) -> Result<u64>
pub fn invalidate_list_queries(&self, views: &[String]) -> Result<u64>
Evict only list (multi-row) cache entries for the given views.
Unlike invalidate_views(), leaves single-entity point-lookup entries
intact. Used for CREATE mutations: creating a new entity does not affect
queries that fetch a different existing entity by UUID.
Expands the view list with transitive dependents when a
CascadeInvalidator is configured (same logic as invalidate_views()).
§Returns
Number of cache entries evicted.
§Errors
Returns error if the cascade invalidator lock is poisoned.
Sourcepub fn invalidate_by_entity(
&self,
entity_type: &str,
entity_id: &str,
) -> Result<u64>
pub fn invalidate_by_entity( &self, entity_type: &str, entity_id: &str, ) -> Result<u64>
Evict cache entries that contain the given entity UUID.
Delegates to QueryResultCache::invalidate_by_entity. Only entries
whose entity-ID index (built at put() time) contains the given UUID
are removed; all other entries remain warm.
§Returns
Number of cache entries evicted.
§Errors
Returns error if the cache mutex is poisoned.
Trait Implementations§
Source§impl<A: DatabaseAdapter + Clone> Clone for CachedDatabaseAdapter<A>
impl<A: DatabaseAdapter + Clone> Clone for CachedDatabaseAdapter<A>
Source§impl<A: DatabaseAdapter> DatabaseAdapter for CachedDatabaseAdapter<A>
impl<A: DatabaseAdapter> DatabaseAdapter for CachedDatabaseAdapter<A>
Source§fn execute_with_projection<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
view: &'life1 str,
projection: Option<&'life2 SqlProjectionHint>,
where_clause: Option<&'life3 WhereClause>,
limit: Option<u32>,
offset: Option<u32>,
_order_by: Option<&'life4 [OrderByClause]>,
) -> Pin<Box<dyn Future<Output = Result<Vec<JsonbValue>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
fn execute_with_projection<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
view: &'life1 str,
projection: Option<&'life2 SqlProjectionHint>,
where_clause: Option<&'life3 WhereClause>,
limit: Option<u32>,
offset: Option<u32>,
_order_by: Option<&'life4 [OrderByClause]>,
) -> Pin<Box<dyn Future<Output = Result<Vec<JsonbValue>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
Source§fn execute_where_query<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
view: &'life1 str,
where_clause: Option<&'life2 WhereClause>,
limit: Option<u32>,
offset: Option<u32>,
_order_by: Option<&'life3 [OrderByClause]>,
) -> Pin<Box<dyn Future<Output = Result<Vec<JsonbValue>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn execute_where_query<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
view: &'life1 str,
where_clause: Option<&'life2 WhereClause>,
limit: Option<u32>,
offset: Option<u32>,
_order_by: Option<&'life3 [OrderByClause]>,
) -> Pin<Box<dyn Future<Output = Result<Vec<JsonbValue>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Source§fn execute_with_projection_arc<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
view: &'life1 str,
projection: Option<&'life2 SqlProjectionHint>,
where_clause: Option<&'life3 WhereClause>,
limit: Option<u32>,
offset: Option<u32>,
_order_by: Option<&'life4 [OrderByClause]>,
) -> Pin<Box<dyn Future<Output = Result<Arc<Vec<JsonbValue>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
fn execute_with_projection_arc<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
view: &'life1 str,
projection: Option<&'life2 SqlProjectionHint>,
where_clause: Option<&'life3 WhereClause>,
limit: Option<u32>,
offset: Option<u32>,
_order_by: Option<&'life4 [OrderByClause]>,
) -> Pin<Box<dyn Future<Output = Result<Arc<Vec<JsonbValue>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
Source§fn execute_where_query_arc<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
view: &'life1 str,
where_clause: Option<&'life2 WhereClause>,
limit: Option<u32>,
offset: Option<u32>,
_order_by: Option<&'life3 [OrderByClause]>,
) -> Pin<Box<dyn Future<Output = Result<Arc<Vec<JsonbValue>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn execute_where_query_arc<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
view: &'life1 str,
where_clause: Option<&'life2 WhereClause>,
limit: Option<u32>,
offset: Option<u32>,
_order_by: Option<&'life3 [OrderByClause]>,
) -> Pin<Box<dyn Future<Output = Result<Arc<Vec<JsonbValue>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Source§fn database_type(&self) -> DatabaseType
fn database_type(&self) -> DatabaseType
Source§fn health_check<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn health_check<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn pool_metrics(&self) -> PoolMetrics
fn pool_metrics(&self) -> PoolMetrics
Source§fn execute_raw_query<'life0, 'life1, 'async_trait>(
&'life0 self,
sql: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<HashMap<String, Value>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn execute_raw_query<'life0, 'life1, 'async_trait>(
&'life0 self,
sql: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<HashMap<String, Value>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn execute_parameterized_aggregate<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
sql: &'life1 str,
params: &'life2 [Value],
) -> Pin<Box<dyn Future<Output = Result<Vec<HashMap<String, Value>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn execute_parameterized_aggregate<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
sql: &'life1 str,
params: &'life2 [Value],
) -> Pin<Box<dyn Future<Output = Result<Vec<HashMap<String, Value>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn execute_function_call<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
function_name: &'life1 str,
args: &'life2 [Value],
) -> Pin<Box<dyn Future<Output = Result<Vec<HashMap<String, Value>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn execute_function_call<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
function_name: &'life1 str,
args: &'life2 [Value],
) -> Pin<Box<dyn Future<Output = Result<Vec<HashMap<String, Value>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn invalidate_views<'life0, 'life1, 'async_trait>(
&'life0 self,
views: &'life1 [String],
) -> Pin<Box<dyn Future<Output = Result<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn invalidate_views<'life0, 'life1, 'async_trait>(
&'life0 self,
views: &'life1 [String],
) -> Pin<Box<dyn Future<Output = Result<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn invalidate_by_entity<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
entity_type: &'life1 str,
entity_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn invalidate_by_entity<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
entity_type: &'life1 str,
entity_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn invalidate_list_queries<'life0, 'life1, 'async_trait>(
&'life0 self,
views: &'life1 [String],
) -> Pin<Box<dyn Future<Output = Result<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn invalidate_list_queries<'life0, 'life1, 'async_trait>(
&'life0 self,
views: &'life1 [String],
) -> Pin<Box<dyn Future<Output = Result<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn bump_fact_table_versions<'life0, 'life1, 'async_trait>(
&'life0 self,
tables: &'life1 [String],
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn bump_fact_table_versions<'life0, 'life1, 'async_trait>(
&'life0 self,
tables: &'life1 [String],
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn execute_row_query<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
view_name: &'life1 str,
columns: &'life2 [ColumnSpec],
where_sql: Option<&'life3 str>,
order_by: Option<&'life4 str>,
limit: Option<u32>,
offset: Option<u32>,
) -> Pin<Box<dyn Future<Output = Result<Vec<Vec<ColumnValue>>, FraiseQLError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
Self: 'async_trait,
fn execute_row_query<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
view_name: &'life1 str,
columns: &'life2 [ColumnSpec],
where_sql: Option<&'life3 str>,
order_by: Option<&'life4 str>,
limit: Option<u32>,
offset: Option<u32>,
) -> Pin<Box<dyn Future<Output = Result<Vec<Vec<ColumnValue>>, FraiseQLError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
Self: 'async_trait,
Source§fn supports_mutations(&self) -> bool
fn supports_mutations(&self) -> bool
true if this adapter supports GraphQL mutation operations. Read moreSource§fn capabilities(&self) -> DatabaseCapabilities
fn capabilities(&self) -> DatabaseCapabilities
Source§fn explain_query<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_sql: &'life1 str,
_params: &'life2 [Value],
) -> Pin<Box<dyn Future<Output = Result<Value, FraiseQLError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn explain_query<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_sql: &'life1 str,
_params: &'life2 [Value],
) -> Pin<Box<dyn Future<Output = Result<Value, FraiseQLError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
EXPLAIN on a SQL statement without executing it. Read moreSource§fn explain_where_query<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_view: &'life1 str,
_where_clause: Option<&'life2 WhereClause>,
_limit: Option<u32>,
_offset: Option<u32>,
) -> Pin<Box<dyn Future<Output = Result<Value, FraiseQLError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn explain_where_query<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_view: &'life1 str,
_where_clause: Option<&'life2 WhereClause>,
_limit: Option<u32>,
_offset: Option<u32>,
) -> Pin<Box<dyn Future<Output = Result<Value, FraiseQLError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) against a view with the
same parameterized WHERE clause that execute_where_query would use. Read moreSource§fn mutation_strategy(&self) -> MutationStrategy
fn mutation_strategy(&self) -> MutationStrategy
Source§fn execute_direct_mutation<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_ctx: &'life1 DirectMutationContext<'life2>,
) -> Pin<Box<dyn Future<Output = Result<Vec<Value>, FraiseQLError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
fn execute_direct_mutation<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_ctx: &'life1 DirectMutationContext<'life2>,
) -> Pin<Box<dyn Future<Output = Result<Vec<Value>, FraiseQLError>> + Send + 'async_trait>>where
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Self: 'async_trait,
Source§impl<A: RelayDatabaseAdapter + DatabaseAdapter> RelayDatabaseAdapter for CachedDatabaseAdapter<A>
impl<A: RelayDatabaseAdapter + DatabaseAdapter> RelayDatabaseAdapter for CachedDatabaseAdapter<A>
Source§async fn execute_relay_page(
&self,
view: &str,
cursor_column: &str,
after: Option<CursorValue>,
before: Option<CursorValue>,
limit: u32,
forward: bool,
where_clause: Option<&WhereClause>,
order_by: Option<&[OrderByClause]>,
include_total_count: bool,
) -> Result<RelayPageResult>
async fn execute_relay_page( &self, view: &str, cursor_column: &str, after: Option<CursorValue>, before: Option<CursorValue>, limit: u32, forward: bool, where_clause: Option<&WhereClause>, order_by: Option<&[OrderByClause]>, include_total_count: bool, ) -> Result<RelayPageResult>
impl<A: SupportsMutations + Send + Sync> SupportsMutations for CachedDatabaseAdapter<A>
Auto Trait Implementations§
impl<A> Freeze for CachedDatabaseAdapter<A>where
A: Freeze,
impl<A> !RefUnwindSafe for CachedDatabaseAdapter<A>
impl<A> Send for CachedDatabaseAdapter<A>
impl<A> Sync for CachedDatabaseAdapter<A>
impl<A> Unpin for CachedDatabaseAdapter<A>where
A: Unpin,
impl<A> UnsafeUnpin for CachedDatabaseAdapter<A>where
A: UnsafeUnpin,
impl<A> !UnwindSafe for CachedDatabaseAdapter<A>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more