gluesql_core/ast_builder/
select_item.rs1use {
2 super::ExprNode,
3 crate::{
4 ast::{Expr, SelectItem, ToSqlUnquoted},
5 ast_builder::ExprWithAliasNode,
6 parse_sql::parse_select_item,
7 result::{Error, Result},
8 translate::{NO_PARAMS, translate_select_item},
9 },
10};
11
12#[derive(Clone, Debug)]
13pub enum SelectItemNode<'a> {
14 SelectItem(SelectItem),
15 Expr(ExprNode<'a>),
16 Text(String),
17 ExprWithAliasNode(ExprWithAliasNode<'a>),
18}
19
20impl From<SelectItem> for SelectItemNode<'_> {
21 fn from(select_item: SelectItem) -> Self {
22 Self::SelectItem(select_item)
23 }
24}
25
26impl<'a> From<ExprNode<'a>> for SelectItemNode<'a> {
27 fn from(expr_node: ExprNode<'a>) -> Self {
28 Self::Expr(expr_node)
29 }
30}
31
32impl From<&str> for SelectItemNode<'_> {
33 fn from(select_item: &str) -> Self {
34 Self::Text(select_item.to_owned())
35 }
36}
37
38impl<'a> From<ExprWithAliasNode<'a>> for SelectItemNode<'a> {
39 fn from(expr_node: ExprWithAliasNode<'a>) -> Self {
40 Self::ExprWithAliasNode(expr_node)
41 }
42}
43
44impl<'a> TryFrom<SelectItemNode<'a>> for SelectItem {
45 type Error = Error;
46
47 fn try_from(select_item_node: SelectItemNode<'a>) -> Result<Self> {
48 match select_item_node {
49 SelectItemNode::SelectItem(select_item) => Ok(select_item),
50 SelectItemNode::Text(select_item) => parse_select_item(select_item)
51 .and_then(|item| translate_select_item(&item, NO_PARAMS)),
52 SelectItemNode::Expr(expr_node) => {
53 let expr = Expr::try_from(expr_node)?;
54 let label = expr.to_sql_unquoted();
55
56 Ok(SelectItem::Expr { expr, label })
57 }
58 SelectItemNode::ExprWithAliasNode(alias_node) => {
59 let (expr, label) = alias_node.try_into()?;
60
61 Ok(SelectItem::Expr { expr, label })
62 }
63 }
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use {
70 crate::{
71 ast::SelectItem,
72 ast_builder::{SelectItemNode, col},
73 parse_sql::parse_select_item,
74 translate::{NO_PARAMS, translate_select_item},
75 },
76 pretty_assertions::assert_eq,
77 };
78
79 fn test(actual: SelectItemNode, expected: &str) {
80 let parsed = &parse_select_item(expected).expect(expected);
81 let expected = translate_select_item(parsed, NO_PARAMS);
82 assert_eq!(actual.try_into(), expected);
83 }
84
85 #[test]
86 fn select_item() {
87 let actual = SelectItem::Wildcard.into();
88 let expected = "*";
89 test(actual, expected);
90
91 let actual = "Foo.*".into();
92 let expected = "Foo.*";
93 test(actual, expected);
94
95 let actual = "id as hello".into();
96 let expected = "id as hello";
97 test(actual, expected);
98
99 let actual = col("id").into();
100 let expected = "id";
101 test(actual, expected);
102 }
103}