1use rigsql_core::{Segment, SegmentType};
2
3pub fn has_as_keyword(children: &[Segment]) -> bool {
5 children.iter().any(|child| {
6 if let Segment::Token(t) = child {
7 t.segment_type == SegmentType::Keyword && t.token.text.eq_ignore_ascii_case("AS")
8 } else {
9 false
10 }
11 })
12}
13
14pub fn first_non_trivia(children: &[Segment]) -> Option<&Segment> {
16 children.iter().find(|c| !c.segment_type().is_trivia())
17}
18
19pub fn last_non_trivia(children: &[Segment]) -> Option<&Segment> {
21 children
22 .iter()
23 .rev()
24 .find(|c| !c.segment_type().is_trivia())
25}
26
27const NOT_ALIAS_KEYWORDS: &[&str] = &[
30 "ALTER",
31 "AND",
32 "BEGIN",
33 "BREAK",
34 "CATCH",
35 "CLOSE",
36 "COMMIT",
37 "CONTINUE",
38 "CREATE",
39 "CROSS",
40 "CURSOR",
41 "DEALLOCATE",
42 "DECLARE",
43 "DELETE",
44 "DROP",
45 "ELSE",
46 "END",
47 "EXCEPT",
48 "EXEC",
49 "EXECUTE",
50 "FETCH",
51 "FOR",
52 "FROM",
53 "FULL",
54 "GO",
55 "GOTO",
56 "GROUP",
57 "HAVING",
58 "IF",
59 "INNER",
60 "INSERT",
61 "INTERSECT",
62 "INTO",
63 "JOIN",
64 "LEFT",
65 "LIMIT",
66 "MERGE",
67 "NATURAL",
68 "NEXT",
69 "OFFSET",
70 "ON",
71 "OPEN",
72 "OR",
73 "ORDER",
74 "OUTPUT",
75 "OVER",
76 "PRINT",
77 "RAISERROR",
78 "RETURN",
79 "RETURNING",
80 "RIGHT",
81 "ROLLBACK",
82 "SELECT",
83 "SET",
84 "TABLE",
85 "THEN",
86 "THROW",
87 "TRUNCATE",
88 "TRY",
89 "UNION",
90 "UPDATE",
91 "VALUES",
92 "WHEN",
93 "WHERE",
94 "WHILE",
95 "WITH",
96];
97
98pub fn is_false_alias(children: &[Segment]) -> bool {
102 if let Some(Segment::Token(t)) = last_non_trivia(children) {
104 let upper = t.token.text.to_ascii_uppercase();
105 return NOT_ALIAS_KEYWORDS.binary_search(&upper.as_str()).is_ok();
106 }
107 false
108}
109
110pub fn find_keyword_in_children<'a>(
112 children: &'a [Segment],
113 name: &str,
114) -> Option<(usize, &'a Segment)> {
115 children.iter().enumerate().find(|(_, c)| {
116 if let Segment::Token(t) = c {
117 t.segment_type == SegmentType::Keyword && t.token.text.eq_ignore_ascii_case(name)
118 } else {
119 false
120 }
121 })
122}