reddb_server/runtime/
impl_fast_path.rs1use super::execution_context::entity_visible_under_current_snapshot;
7use super::*;
8
9impl RedDBRuntime {
10 pub(crate) fn try_fast_entity_lookup(
13 &self,
14 query: &str,
15 ) -> Option<RedDBResult<RuntimeQueryResult>> {
16 if self.resource_limits().read_execution_limits_enabled() {
18 return None;
19 }
20 let q = query.trim();
23 if !q.starts_with("SELECT") && !q.starts_with("select") {
24 return None;
25 }
26
27 let where_pos = q
29 .find("WHERE _entity_id")
30 .or_else(|| q.find("where _entity_id"))?;
31 let after_field = &q[where_pos + 16..].trim_start(); let after_eq = after_field.strip_prefix('=')?.trim_start();
33
34 let id_str = after_eq.trim();
36 let entity_id: u64 = id_str.parse().ok()?;
37
38 let from_pos = q.find("FROM ").or_else(|| q.find("from "))? + 5;
40 let table = q[from_pos..where_pos].trim();
41 if table.is_empty()
42 || table.contains(' ') && !table.contains(" AS ") && !table.contains(" as ")
43 {
44 return None; }
46 let table_name = table.split_whitespace().next()?;
47
48 let store = self.inner.db.store();
54 let entity = store
55 .get(
56 table_name,
57 crate::storage::unified::EntityId::new(entity_id),
58 )
59 .filter(entity_visible_under_current_snapshot)
60 .filter(|entity| {
61 self.inner
62 .db
63 .replica_allows_entity_at_read(table_name, entity)
64 });
65
66 let count = if entity.is_some() { 1u64 } else { 0 };
67
68 let records: Vec<crate::storage::query::unified::UnifiedRecord> = entity
74 .as_ref()
75 .and_then(|e| runtime_table_record_from_entity(e.clone()))
76 .into_iter()
77 .collect();
78
79 let json = match entity {
80 Some(ref e) => execute_runtime_serialize_single_entity(e),
81 None => r#"{"columns":[],"record_count":0,"selection":{"scope":"any"},"records":[]}"#
82 .to_string(),
83 };
84
85 Some(Ok(RuntimeQueryResult {
86 query: query.to_string(),
87 mode: reddb_rql::modes::QueryMode::Sql,
88 statement: "select",
89 engine: "fast-entity-lookup",
90 result: crate::storage::query::unified::UnifiedResult {
91 columns: Vec::new(),
92 records,
93 stats: crate::storage::query::unified::QueryStats {
94 rows_scanned: count,
95 ..Default::default()
96 },
97 pre_serialized_json: Some(json),
98 },
99 affected_rows: 0,
100 statement_type: "select",
101 bookmark: None,
102 notice: None,
103 }))
104 }
105
106 pub(crate) fn invalidate_plan_cache(&self) {
107 self.inner.query_cache.write().clear();
108 self.inner
109 .ddl_epoch
110 .fetch_add(1, std::sync::atomic::Ordering::Release);
111 }
112
113 pub fn ddl_epoch(&self) -> u64 {
117 self.inner
118 .ddl_epoch
119 .load(std::sync::atomic::Ordering::Acquire)
120 }
121
122 pub(crate) fn clear_table_planner_stats(&self, table: &str) {
123 let store = self.inner.db.store();
124 crate::storage::query::planner::stats_catalog::clear_table_stats(store.as_ref(), table);
125 self.invalidate_plan_cache();
126 }
127}