sql_cli/sql/functions/
constants.rs

1use anyhow::Result;
2
3use super::{ArgCount, FunctionCategory, FunctionSignature, SqlFunction};
4use crate::data::datatable::DataValue;
5
6/// PI constant function
7pub struct PiFunction;
8
9impl SqlFunction for PiFunction {
10    fn signature(&self) -> FunctionSignature {
11        FunctionSignature {
12            name: "PI",
13            category: FunctionCategory::Constant,
14            arg_count: ArgCount::Fixed(0),
15            description: "Returns the value of π (pi)",
16            returns: "FLOAT",
17            examples: vec!["SELECT PI()", "SELECT radius * 2 * PI() AS circumference"],
18        }
19    }
20
21    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
22        self.validate_args(args)?;
23        Ok(DataValue::Float(std::f64::consts::PI))
24    }
25}
26
27/// E (Euler's number) constant function
28pub struct EFunction;
29
30impl SqlFunction for EFunction {
31    fn signature(&self) -> FunctionSignature {
32        FunctionSignature {
33            name: "E",
34            category: FunctionCategory::Constant,
35            arg_count: ArgCount::Fixed(0),
36            description: "Returns Euler's number (e ≈ 2.71828)",
37            returns: "FLOAT",
38            examples: vec!["SELECT E()", "SELECT POW(E(), x) AS exp_x"],
39        }
40    }
41
42    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
43        self.validate_args(args)?;
44        Ok(DataValue::Float(std::f64::consts::E))
45    }
46}
47
48/// Mass of electron in kg
49pub struct MeFunction;
50
51/// Alias for ME function
52pub struct MassElectronFunction;
53
54impl SqlFunction for MeFunction {
55    fn signature(&self) -> FunctionSignature {
56        FunctionSignature {
57            name: "ME",
58            category: FunctionCategory::Constant,
59            arg_count: ArgCount::Fixed(0),
60            description: "Returns the mass of an electron in kg (9.10938356 × 10^-31)",
61            returns: "FLOAT",
62            examples: vec!["SELECT ME()", "SELECT mass / ME() AS electron_masses"],
63        }
64    }
65
66    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
67        self.validate_args(args)?;
68        Ok(DataValue::Float(9.1093837015e-31))
69    }
70}
71
72impl SqlFunction for MassElectronFunction {
73    fn signature(&self) -> FunctionSignature {
74        FunctionSignature {
75            name: "MASS_ELECTRON",
76            category: FunctionCategory::Constant,
77            arg_count: ArgCount::Fixed(0),
78            description: "Alias for ME() - Returns the mass of an electron in kg",
79            returns: "FLOAT",
80            examples: vec!["SELECT MASS_ELECTRON()"],
81        }
82    }
83
84    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
85        self.validate_args(args)?;
86        Ok(DataValue::Float(9.1093837015e-31))
87    }
88}
89
90/// TAU constant (2π)
91pub struct TauFunction;
92
93impl SqlFunction for TauFunction {
94    fn signature(&self) -> FunctionSignature {
95        FunctionSignature {
96            name: "TAU",
97            category: FunctionCategory::Constant,
98            arg_count: ArgCount::Fixed(0),
99            description: "Returns tau (τ = 2π = 6.28318...)",
100            returns: "FLOAT",
101            examples: vec!["SELECT TAU()", "SELECT radius * TAU() as circumference"],
102        }
103    }
104
105    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
106        self.validate_args(args)?;
107        Ok(DataValue::Float(2.0 * std::f64::consts::PI))
108    }
109}
110
111/// PHI constant (Golden ratio)
112pub struct PhiFunction;
113
114impl SqlFunction for PhiFunction {
115    fn signature(&self) -> FunctionSignature {
116        FunctionSignature {
117            name: "PHI",
118            category: FunctionCategory::Constant,
119            arg_count: ArgCount::Fixed(0),
120            description: "Returns the golden ratio φ (1.61803...)",
121            returns: "FLOAT",
122            examples: vec!["SELECT PHI()", "SELECT width * PHI() as golden_height"],
123        }
124    }
125
126    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
127        self.validate_args(args)?;
128        Ok(DataValue::Float(1.618033988749895)) // (1 + sqrt(5)) / 2
129    }
130}
131
132/// HBAR constant (Reduced Planck constant)
133pub struct HbarFunction;
134
135impl SqlFunction for HbarFunction {
136    fn signature(&self) -> FunctionSignature {
137        FunctionSignature {
138            name: "HBAR",
139            category: FunctionCategory::Constant,
140            arg_count: ArgCount::Fixed(0),
141            description: "Returns the reduced Planck constant ħ in J⋅s (1.055 × 10⁻³⁴)",
142            returns: "FLOAT",
143            examples: vec!["SELECT HBAR()", "SELECT HBAR() / (2 * PI()) as h_bar"],
144        }
145    }
146
147    fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
148        self.validate_args(args)?;
149        Ok(DataValue::Float(1.054571817e-34))
150    }
151}
152
153#[cfg(test)]
154mod tests {
155    use super::*;
156
157    #[test]
158    fn test_pi_function() {
159        let func = PiFunction;
160        let result = func.evaluate(&[]).unwrap();
161        match result {
162            DataValue::Float(val) => assert!((val - std::f64::consts::PI).abs() < 1e-10),
163            _ => panic!("Expected Float"),
164        }
165    }
166
167    #[test]
168    fn test_pi_with_args_fails() {
169        let func = PiFunction;
170        let result = func.evaluate(&[DataValue::Float(1.0)]);
171        assert!(result.is_err());
172    }
173
174    #[test]
175    fn test_e_function() {
176        let func = EFunction;
177        let result = func.evaluate(&[]).unwrap();
178        match result {
179            DataValue::Float(val) => assert!((val - std::f64::consts::E).abs() < 1e-10),
180            _ => panic!("Expected Float"),
181        }
182    }
183
184    #[test]
185    fn test_me_function() {
186        let func = MeFunction;
187        let result = func.evaluate(&[]).unwrap();
188        match result {
189            DataValue::Float(val) => assert!((val - 9.1093837015e-31).abs() < 1e-40),
190            _ => panic!("Expected Float"),
191        }
192    }
193}