Skip to main content

gluesql_core/plan/statement/query/
source.rs

1mod 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}