nodedb_sql/optimizer/
point_get.rs1use crate::types::*;
6
7pub fn optimize(plan: SqlPlan) -> SqlPlan {
9 match plan {
10 SqlPlan::Scan {
11 ref collection,
12 ref alias,
13 ref engine,
14 ref filters,
15 ref projection,
16 ref temporal,
17 ..
18 } if filters.len() == 1
19 && !temporal.is_temporal()
20 && !projection
21 .iter()
22 .any(|p| matches!(p, Projection::Computed { .. })) =>
23 {
24 if let Some((key_col, key_val)) = extract_pk_equality(&filters[0]) {
25 return SqlPlan::PointGet {
26 collection: collection.clone(),
27 alias: alias.clone(),
28 engine: *engine,
29 key_column: key_col,
30 key_value: key_val,
31 };
32 }
33 plan
34 }
35 _ => plan,
36 }
37}
38
39fn extract_pk_equality(filter: &Filter) -> Option<(String, SqlValue)> {
41 match &filter.expr {
42 FilterExpr::Comparison {
43 field,
44 op: CompareOp::Eq,
45 value,
46 } => {
47 let f = field.to_lowercase();
49 if f == "id" || f == "document_id" || f == "key" {
50 Some((f, value.clone()))
51 } else {
52 None
53 }
54 }
55 FilterExpr::Expr(SqlExpr::BinaryOp {
56 left,
57 op: BinaryOp::Eq,
58 right,
59 }) => {
60 let col = match left.as_ref() {
61 SqlExpr::Column { name, .. } => name.to_lowercase(),
62 _ => return None,
63 };
64 if col != "id" && col != "document_id" && col != "key" {
65 return None;
66 }
67 let val = match right.as_ref() {
68 SqlExpr::Literal(v) => v.clone(),
69 _ => return None,
70 };
71 Some((col, val))
72 }
73 _ => None,
74 }
75}