gitql_core/
environment.rs

1use std::collections::HashMap;
2
3use gitql_ast::types::DataType;
4
5use crate::schema::Schema;
6use crate::signature::AggregationFunction;
7use crate::signature::Signature;
8use crate::signature::StandardFunction;
9use crate::signature::WindowFunction;
10use crate::types_table::TypesTable;
11use crate::values::Value;
12
13/// Environment that track schema, functions, scopes and types
14/// to be used in different places in the query engine
15pub struct Environment {
16    /// Data schema information contains table, fields names and types
17    pub schema: Schema,
18
19    /// Standard function signatures
20    pub std_signatures: HashMap<&'static str, Signature>,
21
22    /// Standard function references
23    pub std_functions: HashMap<&'static str, StandardFunction>,
24
25    /// Aggregation function signatures
26    pub aggregation_signatures: HashMap<&'static str, Signature>,
27
28    /// Aggregation function references
29    pub aggregation_functions: HashMap<&'static str, AggregationFunction>,
30
31    /// Window function signatures
32    pub window_signatures: HashMap<&'static str, Signature>,
33
34    /// Window function references
35    pub window_functions: HashMap<&'static str, WindowFunction>,
36
37    /// All Global Variables values that can life for this program session
38    pub globals: HashMap<String, Box<dyn Value>>,
39
40    /// All Global Variables Types that can life for this program session
41    pub globals_types: HashMap<String, Box<dyn DataType>>,
42
43    /// Local variables types in the current scope, later will be multi layer scopes
44    pub scopes: HashMap<String, Box<dyn DataType>>,
45
46    /// A Table of DataTypes mapped to their original names or aliases
47    pub types_table: TypesTable,
48}
49
50impl Environment {
51    /// Create new [`Environment`] instance with Data Schema
52    pub fn new(schema: Schema) -> Self {
53        Self {
54            schema,
55            std_signatures: HashMap::default(),
56            std_functions: HashMap::default(),
57            aggregation_signatures: HashMap::default(),
58            aggregation_functions: HashMap::default(),
59            window_signatures: HashMap::default(),
60            window_functions: HashMap::default(),
61            globals: HashMap::default(),
62            globals_types: HashMap::default(),
63            scopes: HashMap::default(),
64            types_table: TypesTable::new(),
65        }
66    }
67
68    /// Register standard functions signatures and references
69    pub fn with_standard_functions(
70        &mut self,
71        signatures: &HashMap<&'static str, Signature>,
72        functions: &HashMap<&'static str, StandardFunction>,
73    ) {
74        self.std_signatures.extend(signatures.to_owned());
75        self.std_functions.extend(functions.to_owned());
76    }
77
78    /// Register aggregation functions signatures and references
79    pub fn with_aggregation_functions(
80        &mut self,
81        signatures: &HashMap<&'static str, Signature>,
82        aggregation: &HashMap<&'static str, AggregationFunction>,
83    ) {
84        self.aggregation_signatures.extend(signatures.to_owned());
85        self.aggregation_functions.extend(aggregation.to_owned());
86    }
87
88    /// Register Window functions signatures and references
89    pub fn with_window_functions(
90        &mut self,
91        signatures: &HashMap<&'static str, Signature>,
92        window: &HashMap<&'static str, WindowFunction>,
93    ) {
94        self.window_signatures.extend(signatures.to_owned());
95        self.window_functions.extend(window.to_owned());
96    }
97
98    /// Register new Modified Types table
99    pub fn with_types_table(&mut self, types_table: TypesTable) {
100        self.types_table = types_table
101    }
102
103    /// Return true if this name is a valid standard function
104    pub fn is_std_function(&self, str: &str) -> bool {
105        self.std_functions.contains_key(str)
106    }
107
108    /// Return Standard function signature by name
109    pub fn std_signature(&self, str: &str) -> Option<&Signature> {
110        self.std_signatures.get(str)
111    }
112
113    /// Return Standard function reference by name
114    pub fn std_function(&self, str: &str) -> Option<&StandardFunction> {
115        self.std_functions.get(str)
116    }
117
118    /// Return true if this name is a valid aggregation function
119    pub fn is_aggregation_function(&self, str: &str) -> bool {
120        self.aggregation_signatures.contains_key(str)
121    }
122
123    /// Return Aggregation function signature by name
124    pub fn aggregation_signature(&self, str: &str) -> Option<&Signature> {
125        self.aggregation_signatures.get(str)
126    }
127
128    /// Return Aggregation function reference by name
129    pub fn aggregation_function(&self, str: &str) -> Option<&AggregationFunction> {
130        self.aggregation_functions.get(str)
131    }
132
133    /// Return true if this name is a valid Window function
134    pub fn is_window_function(&self, str: &str) -> bool {
135        self.window_functions.contains_key(str)
136    }
137
138    /// Return Window function signature by name
139    pub fn window_function_signature(&self, str: &str) -> Option<&Signature> {
140        self.window_signatures.get(str)
141    }
142
143    /// Return Window function reference by name
144    pub fn window_function(&self, str: &str) -> Option<&WindowFunction> {
145        self.window_functions.get(str)
146    }
147
148    /// Define in the current scope
149    pub fn define(&mut self, str: String, data_type: Box<dyn DataType>) {
150        self.scopes.insert(str, data_type);
151    }
152
153    /// Define in the global scope
154    pub fn define_global(&mut self, str: String, data_type: Box<dyn DataType>) {
155        self.globals_types.insert(str, data_type);
156    }
157
158    /// Returns true if local or global scopes has contains field
159    pub fn contains(&self, str: &String) -> bool {
160        self.scopes.contains_key(str) || self.globals_types.contains_key(str)
161    }
162
163    /// Resolve Global or Local type using symbol name
164    #[allow(clippy::borrowed_box)]
165    pub fn resolve_type(&self, str: &String) -> Option<&Box<dyn DataType>> {
166        if str.starts_with('@') {
167            return self.globals_types.get(str);
168        }
169        self.scopes.get(str)
170    }
171
172    /// Clear all locals scopes and only save globals
173    pub fn clear_session(&mut self) {
174        self.scopes.clear()
175    }
176}