alopex_sql/executor/
result.rs1use crate::planner::ResolvedType;
9use crate::storage::SqlValue;
10
11#[derive(Debug, Clone, PartialEq)]
13pub enum ExecutionResult {
14 Success,
16
17 RowsAffected(u64),
19
20 Query(QueryResult),
22}
23
24#[derive(Debug, Clone, PartialEq)]
26pub struct QueryResult {
27 pub columns: Vec<ColumnInfo>,
29
30 pub rows: Vec<Vec<SqlValue>>,
32}
33
34impl QueryResult {
35 pub fn new(columns: Vec<ColumnInfo>, rows: Vec<Vec<SqlValue>>) -> Self {
37 Self { columns, rows }
38 }
39
40 pub fn empty(columns: Vec<ColumnInfo>) -> Self {
42 Self {
43 columns,
44 rows: Vec::new(),
45 }
46 }
47
48 pub fn row_count(&self) -> usize {
50 self.rows.len()
51 }
52
53 pub fn column_count(&self) -> usize {
55 self.columns.len()
56 }
57
58 pub fn is_empty(&self) -> bool {
60 self.rows.is_empty()
61 }
62}
63
64#[derive(Debug, Clone, PartialEq, Eq)]
66pub struct ColumnInfo {
67 pub name: String,
69
70 pub data_type: ResolvedType,
72}
73
74impl ColumnInfo {
75 pub fn new(name: impl Into<String>, data_type: ResolvedType) -> Self {
77 Self {
78 name: name.into(),
79 data_type,
80 }
81 }
82}
83
84#[derive(Debug, Clone, PartialEq)]
86pub struct Row {
87 pub row_id: u64,
89
90 pub values: Vec<SqlValue>,
92}
93
94impl Row {
95 pub fn new(row_id: u64, values: Vec<SqlValue>) -> Self {
97 Self { row_id, values }
98 }
99
100 pub fn get(&self, index: usize) -> Option<&SqlValue> {
102 self.values.get(index)
103 }
104
105 pub fn len(&self) -> usize {
107 self.values.len()
108 }
109
110 pub fn is_empty(&self) -> bool {
112 self.values.is_empty()
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_execution_result_success() {
122 let result = ExecutionResult::Success;
123 assert!(matches!(result, ExecutionResult::Success));
124 }
125
126 #[test]
127 fn test_execution_result_rows_affected() {
128 let result = ExecutionResult::RowsAffected(5);
129 if let ExecutionResult::RowsAffected(count) = result {
130 assert_eq!(count, 5);
131 } else {
132 panic!("Expected RowsAffected variant");
133 }
134 }
135
136 #[test]
137 fn test_query_result_new() {
138 let columns = vec![
139 ColumnInfo::new("id", ResolvedType::Integer),
140 ColumnInfo::new("name", ResolvedType::Text),
141 ];
142 let rows = vec![
143 vec![SqlValue::Integer(1), SqlValue::Text("Alice".into())],
144 vec![SqlValue::Integer(2), SqlValue::Text("Bob".into())],
145 ];
146 let result = QueryResult::new(columns, rows);
147
148 assert_eq!(result.row_count(), 2);
149 assert_eq!(result.column_count(), 2);
150 assert!(!result.is_empty());
151 }
152
153 #[test]
154 fn test_query_result_empty() {
155 let columns = vec![ColumnInfo::new("id", ResolvedType::Integer)];
156 let result = QueryResult::empty(columns);
157
158 assert_eq!(result.row_count(), 0);
159 assert_eq!(result.column_count(), 1);
160 assert!(result.is_empty());
161 }
162
163 #[test]
164 fn test_row_new() {
165 let row = Row::new(
166 42,
167 vec![SqlValue::Integer(1), SqlValue::Text("test".into())],
168 );
169
170 assert_eq!(row.row_id, 42);
171 assert_eq!(row.len(), 2);
172 assert!(!row.is_empty());
173 assert_eq!(row.get(0), Some(&SqlValue::Integer(1)));
174 assert_eq!(row.get(1), Some(&SqlValue::Text("test".into())));
175 assert_eq!(row.get(2), None);
176 }
177
178 #[test]
179 fn test_column_info_new() {
180 let info = ColumnInfo::new("age", ResolvedType::Integer);
181 assert_eq!(info.name, "age");
182 assert_eq!(info.data_type, ResolvedType::Integer);
183 }
184}