use std::sync::Arc;
use super::CachedDatabaseAdapter;
use crate::{
cache::key::{generate_projection_query_key, generate_view_query_key},
db::{
DatabaseAdapter, WhereClause,
types::{JsonbValue, sql_hints::OrderByClause},
},
error::Result,
schema::SqlProjectionHint,
};
pub fn view_name_to_entity_type(view: &str) -> Option<String> {
let after_prefix = view.split_once('_')?.1;
if after_prefix.is_empty() {
return None;
}
let pascal = after_prefix
.split('_')
.map(|segment| {
let mut chars = segment.chars();
match chars.next() {
None => String::new(),
Some(first) => first.to_uppercase().collect::<String>() + chars.as_str(),
}
})
.collect::<String>();
Some(pascal)
}
impl<A: DatabaseAdapter> CachedDatabaseAdapter<A> {
#[tracing::instrument(skip_all, fields(cache.view = view))]
pub(super) async fn execute_with_projection_impl(
&self,
view: &str,
projection: Option<&SqlProjectionHint>,
where_clause: Option<&WhereClause>,
limit: Option<u32>,
offset: Option<u32>,
order_by: Option<&[OrderByClause]>,
) -> Result<Arc<Vec<JsonbValue>>> {
if !self.cache.is_enabled() || (self.opt_in_mode && !self.cacheable_views.contains(view)) {
return self
.adapter
.execute_with_projection(view, projection, where_clause, limit, offset, order_by)
.await
.map(Arc::new);
}
let cache_key = generate_projection_query_key(
view,
projection,
where_clause,
limit,
offset,
order_by,
&self.schema_version,
);
if let Some(cached_arc) = self.cache.get(cache_key)? {
return Ok(cached_arc);
}
let arc = Arc::new(
self.adapter
.execute_with_projection(view, projection, where_clause, limit, offset, order_by)
.await?,
);
let ttl = self.view_ttl_overrides.get(view).copied();
let entity_type = view_name_to_entity_type(view);
self.cache.put_arc(
cache_key,
Arc::clone(&arc),
vec![view.to_string()],
ttl,
entity_type.as_deref(),
)?;
Ok(arc)
}
#[tracing::instrument(skip_all, fields(cache.view = view))]
pub(super) async fn execute_where_query_impl(
&self,
view: &str,
where_clause: Option<&WhereClause>,
limit: Option<u32>,
offset: Option<u32>,
order_by: Option<&[OrderByClause]>,
) -> Result<Arc<Vec<JsonbValue>>> {
if !self.cache.is_enabled() || (self.opt_in_mode && !self.cacheable_views.contains(view)) {
return self
.adapter
.execute_where_query(view, where_clause, limit, offset, order_by)
.await
.map(Arc::new);
}
let cache_key = generate_view_query_key(
view,
where_clause,
limit,
offset,
order_by,
&self.schema_version,
);
if let Some(cached_arc) = self.cache.get(cache_key)? {
return Ok(cached_arc);
}
let arc = Arc::new(
self.adapter
.execute_where_query(view, where_clause, limit, offset, order_by)
.await?,
);
let ttl = self.view_ttl_overrides.get(view).copied();
let entity_type = view_name_to_entity_type(view);
self.cache.put_arc(
cache_key,
Arc::clone(&arc),
vec![view.to_string()],
ttl,
entity_type.as_deref(),
)?;
Ok(arc)
}
}