gluesql_core/plan/statement/query/
source.rs1mod derived;
2mod dictionary;
3mod series;
4mod table;
5mod table_access;
6
7pub use {
8 derived::DerivedSourcePlan,
9 dictionary::DictionarySourcePlan,
10 series::SeriesSourcePlan,
11 table::TableSourcePlan,
12 table_access::{IndexPredicatePlan, TableAccessPlan},
13};
14
15use {
16 crate::ast,
17 serde::{Deserialize, Serialize},
18};
19
20#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
21pub enum SourcePlan {
22 Table(TableSourcePlan),
23 Derived(DerivedSourcePlan),
24 Series(SeriesSourcePlan),
25 Dictionary(DictionarySourcePlan),
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
29pub struct TableAliasPlan {
30 pub name: String,
31 pub columns: Vec<String>,
32}
33
34impl SourcePlan {
35 pub fn alias_name(&self) -> &str {
36 match self {
37 Self::Table(TableSourcePlan { name, alias, .. }) => alias
38 .as_ref()
39 .map_or(name.as_str(), |alias| alias.name.as_str()),
40 Self::Derived(DerivedSourcePlan {
41 alias: TableAliasPlan { name, .. },
42 ..
43 })
44 | Self::Series(SeriesSourcePlan {
45 alias: TableAliasPlan { name, .. },
46 ..
47 })
48 | Self::Dictionary(DictionarySourcePlan {
49 alias: TableAliasPlan { name, .. },
50 ..
51 }) => name.as_str(),
52 }
53 }
54}
55
56impl From<ast::TableFactor> for SourcePlan {
57 fn from(source: ast::TableFactor) -> Self {
58 match source {
59 ast::TableFactor::Table { name, alias } => Self::Table(TableSourcePlan {
60 name,
61 alias: alias.map(Into::into),
62 access: TableAccessPlan::FullScan,
63 }),
64 ast::TableFactor::Derived { subquery, alias } => Self::Derived(DerivedSourcePlan {
65 query: Box::new(subquery.into()),
66 alias: alias.into(),
67 }),
68 ast::TableFactor::Series { alias, size } => Self::Series(SeriesSourcePlan {
69 alias: alias.into(),
70 size: size.into(),
71 }),
72 ast::TableFactor::Dictionary { dict, alias } => {
73 Self::Dictionary(DictionarySourcePlan {
74 dictionary: dict,
75 alias: alias.into(),
76 })
77 }
78 }
79 }
80}
81
82impl From<ast::TableAlias> for TableAliasPlan {
83 fn from(alias: ast::TableAlias) -> Self {
84 let ast::TableAlias { name, columns } = alias;
85
86 Self { name, columns }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use {
93 super::{
94 DerivedSourcePlan, DictionarySourcePlan, SeriesSourcePlan, SourcePlan, TableAccessPlan,
95 TableAliasPlan, TableSourcePlan,
96 },
97 crate::{
98 ast::{self, Dictionary, Expr, Literal, Query, SetExpr, Values},
99 plan::{ExprPlan, QueryPlan},
100 },
101 pretty_assertions::assert_eq,
102 };
103
104 fn alias(name: &str) -> ast::TableAlias {
105 ast::TableAlias {
106 name: name.to_owned(),
107 columns: Vec::new(),
108 }
109 }
110
111 #[test]
112 fn converts_each_ast_source_to_typed_plan() {
113 let actual = SourcePlan::from(ast::TableFactor::Table {
114 name: "Item".to_owned(),
115 alias: Some(alias("i")),
116 });
117 let expected = SourcePlan::Table(TableSourcePlan {
118 name: "Item".to_owned(),
119 alias: Some(TableAliasPlan {
120 name: "i".to_owned(),
121 columns: Vec::new(),
122 }),
123 access: TableAccessPlan::FullScan,
124 });
125 assert_eq!(actual, expected);
126
127 let query = Query {
128 body: SetExpr::Values(Values(vec![vec![Expr::Literal(Literal::Number(1.into()))]])),
129 order_by: Vec::new(),
130 limit: None,
131 offset: None,
132 };
133 let actual = SourcePlan::from(ast::TableFactor::Derived {
134 subquery: query.clone(),
135 alias: alias("derived"),
136 });
137 let expected = SourcePlan::Derived(DerivedSourcePlan {
138 query: Box::new(QueryPlan::from(query)),
139 alias: TableAliasPlan {
140 name: "derived".to_owned(),
141 columns: Vec::new(),
142 },
143 });
144 assert_eq!(actual, expected);
145
146 let actual = SourcePlan::from(ast::TableFactor::Series {
147 alias: alias("series"),
148 size: Expr::Literal(Literal::Number(3.into())),
149 });
150 let expected = SourcePlan::Series(SeriesSourcePlan {
151 alias: TableAliasPlan {
152 name: "series".to_owned(),
153 columns: Vec::new(),
154 },
155 size: ExprPlan::Literal(Literal::Number(3.into())),
156 });
157 assert_eq!(actual, expected);
158
159 let actual = SourcePlan::from(ast::TableFactor::Dictionary {
160 dict: Dictionary::GlueTables,
161 alias: alias("tables"),
162 });
163 let expected = SourcePlan::Dictionary(DictionarySourcePlan {
164 dictionary: Dictionary::GlueTables,
165 alias: TableAliasPlan {
166 name: "tables".to_owned(),
167 columns: Vec::new(),
168 },
169 });
170 assert_eq!(actual, expected);
171 }
172}