1use crate::data::datatable::{DataColumn, DataRow, DataTable, DataType, DataValue};
2use crate::sql::generators::TableGenerator;
3use anyhow::{anyhow, Result};
4use std::collections::HashMap;
5use std::sync::Arc;
6
7pub struct Range;
9
10impl TableGenerator for Range {
11 fn name(&self) -> &str {
12 "RANGE"
13 }
14
15 fn columns(&self) -> Vec<DataColumn> {
16 vec![DataColumn {
17 name: "value".to_string(),
18 data_type: DataType::Integer,
19 nullable: false,
20 unique_values: Some(0),
21 null_count: 0,
22 metadata: HashMap::new(),
23 qualified_name: None,
24 source_table: None,
25 }]
26 }
27
28 fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>> {
29 let (start, end, step) = match args.len() {
30 1 => {
31 let end = match args[0] {
33 DataValue::Integer(n) => n,
34 DataValue::Float(f) => f as i64,
35 _ => return Err(anyhow!("RANGE expects numeric arguments")),
36 };
37 (1, end, 1)
38 }
39 2 => {
40 let start = match args[0] {
42 DataValue::Integer(n) => n,
43 DataValue::Float(f) => f as i64,
44 _ => return Err(anyhow!("RANGE expects numeric arguments")),
45 };
46 let end = match args[1] {
47 DataValue::Integer(n) => n,
48 DataValue::Float(f) => f as i64,
49 _ => return Err(anyhow!("RANGE expects numeric arguments")),
50 };
51 (start, end, 1)
52 }
53 3 => {
54 let start = match args[0] {
56 DataValue::Integer(n) => n,
57 DataValue::Float(f) => f as i64,
58 _ => return Err(anyhow!("RANGE expects numeric arguments")),
59 };
60 let end = match args[1] {
61 DataValue::Integer(n) => n,
62 DataValue::Float(f) => f as i64,
63 _ => return Err(anyhow!("RANGE expects numeric arguments")),
64 };
65 let step = match args[2] {
66 DataValue::Integer(n) => n,
67 DataValue::Float(f) => f as i64,
68 _ => return Err(anyhow!("RANGE expects numeric arguments")),
69 };
70 (start, end, step)
71 }
72 _ => {
73 return Err(anyhow!(
74 "RANGE expects 1-3 arguments (end), (start, end), or (start, end, step)"
75 ))
76 }
77 };
78
79 if step == 0 {
80 return Err(anyhow!("RANGE step cannot be zero"));
81 }
82
83 if (step > 0 && start > end) || (step < 0 && start < end) {
84 return Err(anyhow!(
85 "RANGE parameters invalid: start={}, end={}, step={}",
86 start,
87 end,
88 step
89 ));
90 }
91
92 let mut table = DataTable::new("range");
93 table.add_column(DataColumn::new("value"));
94
95 let mut current = start;
96 while (step > 0 && current <= end) || (step < 0 && current >= end) {
97 table
98 .add_row(DataRow::new(vec![DataValue::Integer(current)]))
99 .map_err(|e| anyhow!(e))?;
100 current += step;
101 }
102
103 Ok(Arc::new(table))
104 }
105
106 fn description(&self) -> &str {
107 "Generate numeric sequence"
108 }
109
110 fn arg_count(&self) -> usize {
111 3 }
113}
114
115pub struct Series;
117
118impl TableGenerator for Series {
119 fn name(&self) -> &str {
120 "SERIES"
121 }
122
123 fn columns(&self) -> Vec<DataColumn> {
124 vec![
125 DataColumn {
126 name: "index".to_string(),
127 data_type: DataType::Integer,
128 nullable: false,
129 unique_values: Some(0),
130 null_count: 0,
131 metadata: HashMap::new(),
132 qualified_name: None,
133 source_table: None,
134 },
135 DataColumn {
136 name: "value".to_string(),
137 data_type: DataType::Integer,
138 nullable: false,
139 unique_values: Some(0),
140 null_count: 0,
141 metadata: HashMap::new(),
142 qualified_name: None,
143 source_table: None,
144 },
145 ]
146 }
147
148 fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>> {
149 if args.is_empty() {
150 return Err(anyhow!("SERIES requires at least 1 argument (count)"));
151 }
152
153 let count = match args[0] {
154 DataValue::Integer(n) => n,
155 DataValue::Float(f) => f as i64,
156 _ => return Err(anyhow!("SERIES count must be numeric")),
157 };
158
159 let start = if args.len() > 1 {
160 match args[1] {
161 DataValue::Integer(n) => n,
162 DataValue::Float(f) => f as i64,
163 _ => 0,
164 }
165 } else {
166 0
167 };
168
169 let mut table = DataTable::new("series");
170 table.add_column(DataColumn::new("index"));
171 table.add_column(DataColumn::new("value"));
172
173 for i in 0..count {
174 table
175 .add_row(DataRow::new(vec![
176 DataValue::Integer(i),
177 DataValue::Integer(start + i),
178 ]))
179 .map_err(|e| anyhow!(e))?;
180 }
181
182 Ok(Arc::new(table))
183 }
184
185 fn description(&self) -> &str {
186 "Generate indexed series (0-based index with values)"
187 }
188
189 fn arg_count(&self) -> usize {
190 2 }
192}
193
194pub struct Dates;
196
197impl TableGenerator for Dates {
198 fn name(&self) -> &str {
199 "DATES"
200 }
201
202 fn columns(&self) -> Vec<DataColumn> {
203 vec![DataColumn {
204 name: "date".to_string(),
205 data_type: DataType::String, nullable: false,
207 unique_values: Some(0),
208 null_count: 0,
209 metadata: HashMap::new(),
210 qualified_name: None,
211 source_table: None,
212 }]
213 }
214
215 fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>> {
216 use chrono::{Duration, NaiveDate};
217
218 if args.len() < 2 {
219 return Err(anyhow!(
220 "DATES requires at least 2 arguments (start_date, end_date)"
221 ));
222 }
223
224 let start_str = match &args[0] {
226 DataValue::String(s) => s,
227 _ => return Err(anyhow!("DATES start_date must be a string")),
228 };
229
230 let start = NaiveDate::parse_from_str(start_str, "%Y-%m-%d")
231 .map_err(|e| anyhow!("Invalid start date format (expected YYYY-MM-DD): {}", e))?;
232
233 let end_str = match &args[1] {
235 DataValue::String(s) => s,
236 _ => return Err(anyhow!("DATES end_date must be a string")),
237 };
238
239 let end = NaiveDate::parse_from_str(end_str, "%Y-%m-%d")
240 .map_err(|e| anyhow!("Invalid end date format (expected YYYY-MM-DD): {}", e))?;
241
242 let step_days = if args.len() > 2 {
244 match args[2] {
245 DataValue::Integer(n) => n,
246 DataValue::Float(f) => f as i64,
247 _ => 1,
248 }
249 } else {
250 1
251 };
252
253 if step_days == 0 {
254 return Err(anyhow!("DATES step cannot be zero"));
255 }
256
257 let mut table = DataTable::new("dates");
258 table.add_column(DataColumn::new("date"));
259
260 let mut current = start;
261 let step = Duration::days(step_days);
262
263 if step_days > 0 {
264 while current <= end {
265 table
266 .add_row(DataRow::new(vec![DataValue::String(
267 current.format("%Y-%m-%d").to_string(),
268 )]))
269 .map_err(|e| anyhow!(e))?;
270 current = current + step;
271 }
272 } else {
273 while current >= end {
274 table
275 .add_row(DataRow::new(vec![DataValue::String(
276 current.format("%Y-%m-%d").to_string(),
277 )]))
278 .map_err(|e| anyhow!(e))?;
279 current = current + step;
280 }
281 }
282
283 Ok(Arc::new(table))
284 }
285
286 fn description(&self) -> &str {
287 "Generate date sequence between two dates"
288 }
289
290 fn arg_count(&self) -> usize {
291 3 }
293}