nodedb_query/geo_functions/
dispatch.rs1use nodedb_types::Value;
6
7use super::catalog;
8use super::{accessors, constructors, indexing, measures, predicates};
9
10pub fn eval_geo_function(name: &str, args: &[Value]) -> Option<Value> {
19 let spec = catalog::lookup(name)?;
20 eval_canonical(spec.canonical, args)
21}
22
23fn eval_canonical(canonical: &str, args: &[Value]) -> Option<Value> {
29 predicates::eval(canonical, args)
30 .or_else(|| measures::eval(canonical, args))
31 .or_else(|| accessors::eval(canonical, args))
32 .or_else(|| constructors::eval(canonical, args))
33 .or_else(|| indexing::eval(canonical, args))
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39 use nodedb_types::geometry::Geometry;
40
41 fn probe_args() -> Vec<Value> {
44 vec![
45 Value::Geometry(Geometry::point(1.0, 2.0)),
46 Value::Geometry(Geometry::point(3.0, 4.0)),
47 Value::Float(5.0),
48 Value::Float(6.0),
49 ]
50 }
51
52 #[test]
57 fn every_catalog_entry_is_evaluable() {
58 for spec in catalog::GEO_FUNCTIONS {
59 assert!(
60 eval_canonical(spec.canonical, &probe_args()).is_some(),
61 "catalog declares '{}' but no evaluator handles it",
62 spec.canonical
63 );
64 }
65 }
66
67 #[test]
70 fn every_alias_evaluates_identically_to_its_canonical_name() {
71 for spec in catalog::GEO_FUNCTIONS {
72 let canonical = eval_geo_function(spec.canonical, &probe_args());
73 for alias in spec.aliases {
74 assert_eq!(
75 eval_geo_function(alias, &probe_args()),
76 canonical,
77 "'{alias}' must behave exactly like '{}'",
78 spec.canonical
79 );
80 }
81 }
82 }
83
84 #[test]
86 fn dispatch_is_case_insensitive() {
87 let args = probe_args();
88 assert_eq!(
89 eval_geo_function("ST_AsText", &args),
90 eval_geo_function("st_astext", &args)
91 );
92 }
93
94 #[test]
95 fn non_geo_function_falls_through() {
96 assert_eq!(eval_geo_function("lower", &probe_args()), None);
97 }
98
99 #[test]
102 fn standard_accessor_names_read_stored_geometry() {
103 use crate::value_ops::to_value_number;
104 let point = vec![Value::Geometry(Geometry::point(1.0, 2.0))];
105 assert_eq!(
106 eval_geo_function("st_x", &point),
107 Some(to_value_number(1.0))
108 );
109 assert_eq!(
110 eval_geo_function("st_y", &point),
111 Some(to_value_number(2.0))
112 );
113 assert!(matches!(
114 eval_geo_function("st_astext", &point),
115 Some(Value::String(_))
116 ));
117 }
118}