sql_cli/data/
virtual_table_generator.rs

1use anyhow::{anyhow, Result};
2use std::collections::HashMap;
3use std::sync::Arc;
4
5use crate::data::datatable::{DataColumn, DataRow, DataTable, DataType, DataValue};
6
7pub struct VirtualTableGenerator;
8
9impl VirtualTableGenerator {
10    pub fn generate_range(
11        start: i64,
12        end: i64,
13        step: Option<i64>,
14        column_name: Option<String>,
15    ) -> Result<Arc<DataTable>> {
16        let step = step.unwrap_or(1);
17        let column_name = column_name.unwrap_or_else(|| "value".to_string());
18
19        if step == 0 {
20            return Err(anyhow!("RANGE step cannot be zero"));
21        }
22
23        if (step > 0 && start > end) || (step < 0 && start < end) {
24            return Err(anyhow!(
25                "RANGE parameters invalid: start={}, end={}, step={}",
26                start,
27                end,
28                step
29            ));
30        }
31
32        let mut table = DataTable::new("range_table");
33
34        let column = DataColumn {
35            name: column_name,
36            data_type: DataType::Integer,
37            nullable: false,
38            unique_values: Some(0),
39            null_count: 0,
40            metadata: HashMap::new(),
41        };
42        table.add_column(column);
43
44        let mut current = start;
45        while (step > 0 && current <= end) || (step < 0 && current >= end) {
46            let row = DataRow {
47                values: vec![DataValue::Integer(current)],
48            };
49            table.add_row(row);
50            current += step;
51        }
52
53        Ok(Arc::new(table))
54    }
55
56    pub fn generate_series(count: i64, start: Option<i64>) -> Result<Arc<DataTable>> {
57        let start = start.unwrap_or(1);
58        Self::generate_range(start, start + count - 1, Some(1), Some("index".to_string()))
59    }
60
61    /// Generate a virtual table from a split string
62    pub fn generate_split(
63        text: &str,
64        delimiter: Option<&str>,
65        column_name: Option<String>,
66    ) -> Result<Arc<DataTable>> {
67        let delimiter = delimiter.unwrap_or(" ");
68        let column_name = column_name.unwrap_or_else(|| "value".to_string());
69
70        let mut table = DataTable::new("split_table");
71
72        let column = DataColumn {
73            name: column_name,
74            data_type: DataType::String,
75            nullable: false,
76            unique_values: Some(0),
77            null_count: 0,
78            metadata: HashMap::new(),
79        };
80        table.add_column(column);
81
82        // Add index column for position tracking
83        let index_column = DataColumn {
84            name: "index".to_string(),
85            data_type: DataType::Integer,
86            nullable: false,
87            unique_values: Some(0),
88            null_count: 0,
89            metadata: HashMap::new(),
90        };
91        table.add_column(index_column);
92
93        // Split the string and create rows
94        let parts: Vec<String> = if delimiter.is_empty() {
95            // If delimiter is empty, split into individual characters
96            text.chars().map(|c| c.to_string()).collect()
97        } else {
98            text.split(delimiter).map(|s| s.to_string()).collect()
99        };
100
101        for (i, part) in parts.iter().enumerate() {
102            // Skip empty parts unless they're meaningful
103            if part.is_empty() && delimiter != "" {
104                continue;
105            }
106
107            let row = DataRow {
108                values: vec![
109                    DataValue::String(part.clone()),
110                    DataValue::Integer((i + 1) as i64),
111                ],
112            };
113            table.add_row(row);
114        }
115
116        Ok(Arc::new(table))
117    }
118}