sqruff_lib_core/parser/segments/
from.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use smol_str::SmolStr;

use crate::dialects::common::AliasInfo;
use crate::dialects::syntax::{SyntaxKind, SyntaxSet};
use crate::parser::segments::base::ErasedSegment;
use crate::parser::segments::join::JoinClauseSegment;

pub struct FromExpressionElementSegment(pub ErasedSegment);
pub struct FromClauseSegment(pub ErasedSegment);

impl FromClauseSegment {
    pub fn eventual_aliases(&self) -> Vec<(ErasedSegment, AliasInfo)> {
        let mut buff = Vec::new();
        let mut direct_table_children = Vec::new();
        let mut join_clauses = Vec::new();

        for from_expression in self
            .0
            .children(const { &SyntaxSet::new(&[SyntaxKind::FromExpression]) })
        {
            direct_table_children.extend(
                from_expression
                    .children(const { &SyntaxSet::new(&[SyntaxKind::FromExpressionElement]) }),
            );
            join_clauses.extend(
                from_expression.children(const { &SyntaxSet::new(&[SyntaxKind::JoinClause]) }),
            );
        }

        for &clause in &direct_table_children {
            let tmp;

            let alias = FromExpressionElementSegment(clause.clone()).eventual_alias();

            let table_expr = if direct_table_children.contains(&clause) {
                clause
            } else {
                tmp = clause
                    .child(const { &SyntaxSet::new(&[SyntaxKind::FromExpressionElement]) })
                    .unwrap();
                &tmp
            };

            buff.push((table_expr.clone(), alias));
        }

        for clause in join_clauses {
            let aliases = JoinClauseSegment(clause.clone()).eventual_aliases();

            if !aliases.is_empty() {
                buff.extend(aliases);
            }
        }

        buff
    }
}

impl FromExpressionElementSegment {
    pub fn eventual_alias(&self) -> AliasInfo {
        let mut tbl_expression = self
            .0
            .child(const { &SyntaxSet::new(&[SyntaxKind::TableExpression]) })
            .or_else(|| {
                self.0
                    .child(const { &SyntaxSet::new(&[SyntaxKind::Bracketed]) })
                    .and_then(|bracketed| {
                        bracketed.child(const { &SyntaxSet::new(&[SyntaxKind::TableExpression]) })
                    })
            });

        if let Some(tbl_expression_inner) = &tbl_expression {
            if tbl_expression_inner
                    .child(const { &SyntaxSet::new(&[SyntaxKind::ObjectReference, SyntaxKind::TableReference]) })
                    .is_none()
                {
                    if let Some(bracketed) = tbl_expression_inner.child(const { &SyntaxSet::new(&[SyntaxKind::Bracketed]) }) {
                        tbl_expression = bracketed.child(const { &SyntaxSet::new(&[SyntaxKind::TableExpression]) });
                    }
                }
        }

        let reference = tbl_expression.and_then(|tbl_expression| {
            tbl_expression.child(const { &SyntaxSet::new(&[SyntaxKind::ObjectReference, SyntaxKind::TableReference]) })
        });

        let reference = reference.as_ref().map(|reference| reference.reference());

        let alias_expression = self
            .0
            .child(const { &SyntaxSet::new(&[SyntaxKind::AliasExpression]) });
        if let Some(alias_expression) = alias_expression {
            let segment = alias_expression.child(
                const { &SyntaxSet::new(&[SyntaxKind::Identifier, SyntaxKind::NakedIdentifier]) },
            );
            if let Some(segment) = segment {
                return AliasInfo {
                    ref_str: segment.raw().clone(),
                    segment: segment.into(),
                    aliased: true,
                    from_expression_element: self.0.clone(),
                    alias_expression: alias_expression.into(),
                    object_reference: reference.map(|it| it.clone().0),
                };
            }
        }

        if let Some(reference) = &reference {
            let references = reference.iter_raw_references();

            if !references.is_empty() {
                let penultimate_ref = references.last().unwrap();
                return AliasInfo {
                    ref_str: penultimate_ref.part.clone().into(),
                    segment: penultimate_ref.segments[0].clone().into(),
                    aliased: false,
                    from_expression_element: self.0.clone(),
                    alias_expression: None,
                    object_reference: reference.clone().0.into(),
                };
            }
        }

        AliasInfo {
            ref_str: SmolStr::new_static(""),
            segment: None,
            aliased: false,
            from_expression_element: self.0.clone(),
            alias_expression: None,
            object_reference: reference.map(|it| it.clone().0),
        }
    }
}