nirv_engine/utils/
types.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use std::time::Duration;
4
5/// Internal representation of a parsed SQL query
6#[derive(Debug, Clone, PartialEq)]
7pub struct InternalQuery {
8    pub operation: QueryOperation,
9    pub sources: Vec<DataSource>,
10    pub projections: Vec<Column>,
11    pub predicates: Vec<Predicate>,
12    pub joins: Vec<Join>,
13    pub ordering: Option<OrderBy>,
14    pub limit: Option<u64>,
15}
16
17/// Types of SQL operations supported
18#[derive(Debug, Clone, PartialEq)]
19pub enum QueryOperation {
20    Select,
21    Insert,
22    Update,
23    Delete,
24}
25
26/// Data source specification in a query
27#[derive(Debug, Clone, PartialEq)]
28pub struct DataSource {
29    pub object_type: String,      // e.g., "postgres", "file", "api"
30    pub identifier: String,       // e.g., "users", "data.csv", "endpoint"
31    pub alias: Option<String>,
32}
33
34/// Column specification in projections
35#[derive(Debug, Clone, PartialEq)]
36pub struct Column {
37    pub name: String,
38    pub alias: Option<String>,
39    pub source: Option<String>,   // Source table/object alias
40}
41
42/// WHERE clause predicates
43#[derive(Debug, Clone, PartialEq)]
44pub struct Predicate {
45    pub column: String,
46    pub operator: PredicateOperator,
47    pub value: PredicateValue,
48}
49
50/// Predicate operators
51#[derive(Debug, Clone, PartialEq)]
52pub enum PredicateOperator {
53    Equal,
54    NotEqual,
55    GreaterThan,
56    GreaterThanOrEqual,
57    LessThan,
58    LessThanOrEqual,
59    Like,
60    In,
61    IsNull,
62    IsNotNull,
63}
64
65/// Values in predicates
66#[derive(Debug, Clone, PartialEq)]
67pub enum PredicateValue {
68    String(String),
69    Number(f64),
70    Integer(i64),
71    Boolean(bool),
72    Null,
73    List(Vec<PredicateValue>),
74}
75
76/// JOIN specifications
77#[derive(Debug, Clone, PartialEq)]
78pub struct Join {
79    pub join_type: JoinType,
80    pub left_source: String,
81    pub right_source: String,
82    pub on_condition: Vec<JoinCondition>,
83}
84
85/// Types of JOINs
86#[derive(Debug, Clone, PartialEq)]
87pub enum JoinType {
88    Inner,
89    Left,
90    Right,
91    Full,
92}
93
94/// JOIN conditions
95#[derive(Debug, Clone, PartialEq)]
96pub struct JoinCondition {
97    pub left_column: String,
98    pub right_column: String,
99}
100
101/// ORDER BY specification
102#[derive(Debug, Clone, PartialEq)]
103pub struct OrderBy {
104    pub columns: Vec<OrderColumn>,
105}
106
107/// Column ordering specification
108#[derive(Debug, Clone, PartialEq)]
109pub struct OrderColumn {
110    pub column: String,
111    pub direction: OrderDirection,
112}
113
114/// Sort direction
115#[derive(Debug, Clone, PartialEq)]
116pub enum OrderDirection {
117    Ascending,
118    Descending,
119}
120
121/// Query execution result
122#[derive(Debug, Clone)]
123pub struct QueryResult {
124    pub columns: Vec<ColumnMetadata>,
125    pub rows: Vec<Row>,
126    pub affected_rows: Option<u64>,
127    pub execution_time: Duration,
128}
129
130/// Metadata for result columns
131#[derive(Debug, Clone, PartialEq)]
132pub struct ColumnMetadata {
133    pub name: String,
134    pub data_type: DataType,
135    pub nullable: bool,
136}
137
138/// Supported data types
139#[derive(Debug, Clone, PartialEq)]
140pub enum DataType {
141    Text,
142    Integer,
143    Float,
144    Boolean,
145    Date,
146    DateTime,
147    Json,
148    Binary,
149}
150
151/// A row of data in query results
152#[derive(Debug, Clone)]
153pub struct Row {
154    pub values: Vec<Value>,
155}
156
157/// Individual cell values
158#[derive(Debug, Clone, PartialEq)]
159pub enum Value {
160    Text(String),
161    Integer(i64),
162    Float(f64),
163    Boolean(bool),
164    Date(String),      // ISO 8601 format
165    DateTime(String),  // ISO 8601 format
166    Json(String),
167    Binary(Vec<u8>),
168    Null,
169}
170
171/// Schema information for data objects
172#[derive(Debug, Clone)]
173pub struct Schema {
174    pub name: String,
175    pub columns: Vec<ColumnMetadata>,
176    pub primary_key: Option<Vec<String>>,
177    pub indexes: Vec<Index>,
178}
179
180/// Index information
181#[derive(Debug, Clone)]
182pub struct Index {
183    pub name: String,
184    pub columns: Vec<String>,
185    pub unique: bool,
186}
187
188/// Connector types
189#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
190pub enum ConnectorType {
191    Mock,
192    PostgreSQL,
193    MySQL,
194    SQLite,
195    SqlServer,
196    File,
197    Rest,
198    LLM,
199    Custom(String),
200}
201
202/// Query to be executed by a specific connector
203#[derive(Debug, Clone)]
204pub struct ConnectorQuery {
205    pub connector_type: ConnectorType,
206    pub query: InternalQuery,
207    pub connection_params: HashMap<String, String>,
208}
209
210impl InternalQuery {
211    /// Create a new empty query
212    pub fn new(operation: QueryOperation) -> Self {
213        Self {
214            operation,
215            sources: Vec::new(),
216            projections: Vec::new(),
217            predicates: Vec::new(),
218            joins: Vec::new(),
219            ordering: None,
220            limit: None,
221        }
222    }
223}
224
225impl QueryResult {
226    /// Create a new empty result
227    pub fn new() -> Self {
228        Self {
229            columns: Vec::new(),
230            rows: Vec::new(),
231            affected_rows: None,
232            execution_time: Duration::from_millis(0),
233        }
234    }
235    
236    /// Get the number of rows in the result
237    pub fn row_count(&self) -> usize {
238        self.rows.len()
239    }
240    
241    /// Check if the result is empty
242    pub fn is_empty(&self) -> bool {
243        self.rows.is_empty()
244    }
245}
246
247impl Row {
248    /// Create a new row with the given values
249    pub fn new(values: Vec<Value>) -> Self {
250        Self { values }
251    }
252    
253    /// Get a value by column index
254    pub fn get(&self, index: usize) -> Option<&Value> {
255        self.values.get(index)
256    }
257}
258
259impl Default for QueryResult {
260    fn default() -> Self {
261        Self::new()
262    }
263}
264#[cfg(test)]
265mod tests {
266    use super::*;
267
268    #[test]
269    fn test_internal_query_creation() {
270        let query = InternalQuery::new(QueryOperation::Select);
271        assert_eq!(query.operation, QueryOperation::Select);
272        assert!(query.sources.is_empty());
273        assert!(query.projections.is_empty());
274        assert!(query.predicates.is_empty());
275        assert!(query.joins.is_empty());
276        assert!(query.ordering.is_none());
277        assert!(query.limit.is_none());
278    }
279
280    #[test]
281    fn test_data_source_creation() {
282        let source = DataSource {
283            object_type: "postgres".to_string(),
284            identifier: "users".to_string(),
285            alias: Some("u".to_string()),
286        };
287        assert_eq!(source.object_type, "postgres");
288        assert_eq!(source.identifier, "users");
289        assert_eq!(source.alias, Some("u".to_string()));
290    }
291
292    #[test]
293    fn test_query_result_creation() {
294        let result = QueryResult::new();
295        assert!(result.is_empty());
296        assert_eq!(result.row_count(), 0);
297        assert!(result.columns.is_empty());
298        assert!(result.rows.is_empty());
299        assert!(result.affected_rows.is_none());
300    }
301
302    #[test]
303    fn test_row_creation_and_access() {
304        let values = vec![
305            Value::Text("John".to_string()),
306            Value::Integer(25),
307            Value::Boolean(true),
308        ];
309        let row = Row::new(values);
310        
311        assert_eq!(row.get(0), Some(&Value::Text("John".to_string())));
312        assert_eq!(row.get(1), Some(&Value::Integer(25)));
313        assert_eq!(row.get(2), Some(&Value::Boolean(true)));
314        assert_eq!(row.get(3), None);
315    }
316
317    #[test]
318    fn test_predicate_value_types() {
319        let string_val = PredicateValue::String("test".to_string());
320        let number_val = PredicateValue::Number(3.14);
321        let int_val = PredicateValue::Integer(42);
322        let bool_val = PredicateValue::Boolean(true);
323        let null_val = PredicateValue::Null;
324        
325        match string_val {
326            PredicateValue::String(s) => assert_eq!(s, "test"),
327            _ => panic!("Expected string value"),
328        }
329        
330        match number_val {
331            PredicateValue::Number(n) => assert_eq!(n, 3.14),
332            _ => panic!("Expected number value"),
333        }
334        
335        match int_val {
336            PredicateValue::Integer(i) => assert_eq!(i, 42),
337            _ => panic!("Expected integer value"),
338        }
339        
340        match bool_val {
341            PredicateValue::Boolean(b) => assert!(b),
342            _ => panic!("Expected boolean value"),
343        }
344        
345        match null_val {
346            PredicateValue::Null => {},
347            _ => panic!("Expected null value"),
348        }
349    }
350
351    #[test]
352    fn test_connector_type_serialization() {
353        let mock_type = ConnectorType::Mock;
354        let postgres_type = ConnectorType::PostgreSQL;
355        let custom_type = ConnectorType::Custom("MyConnector".to_string());
356        
357        assert_eq!(mock_type, ConnectorType::Mock);
358        assert_eq!(postgres_type, ConnectorType::PostgreSQL);
359        assert_eq!(custom_type, ConnectorType::Custom("MyConnector".to_string()));
360    }
361}