teo_parser/search/
search_availability.rs1use crate::ast::arith_expr::ArithExpr;
2use crate::availability::Availability;
3use crate::ast::config::Config;
4use crate::ast::literals::EnumVariantLiteral;
5use crate::ast::namespace::Namespace;
6use crate::ast::schema::Schema;
7use crate::ast::source::Source;
8use crate::traits::named_identifiable::NamedIdentifiable;
9
10pub(crate) fn search_availability(schema: &Schema, source: &Source, namespace_path: &Vec<&str>) -> Availability {
11 if namespace_path.len() == 0 {
12 find_source_availability(schema, source)
13 } else {
14 if let Some(namespace) = source.find_child_namespace_by_string_path(namespace_path) {
15 find_namespace_availability(namespace, schema, source)
16 } else {
17 Availability::no_database()
18 }
19 }
20}
21
22pub(crate) fn find_source_availability(schema: &Schema, source: &Source) -> Availability {
23 if source.builtin {
24 return Availability::default(); }
26 let connector = find_source_connector(schema, source);
27 let retval = find_availability_in_connector(connector);
28 retval
29}
30
31pub(crate) fn find_source_connector<'a>(schema: &'a Schema, source: &'a Source) -> Option<&'a Config> {
32 if let Some(connector) = source.get_connector() {
33 Some(connector)
34 } else {
35 source.imports().iter().find_map(|import| {
36 if let Some(source) = schema.source_at_path(&import.file_path) {
37 source.get_connector()
38 } else {
39 None
40 }
41 })
42 }
43}
44
45pub(crate) fn find_availability_in_connector(connector: Option<&Config>) -> Availability {
46 if let Some(connector) = connector {
47 if let Some(provider) = connector.items().iter().find(|(key, _)| {
48 if let Some(key) = key.named_key_without_resolving() {
49 key == "provider"
50 } else {
51 false
52 }
53 }) {
54 if let Some(enum_variant_literal) = provider.1.kind.as_enum_variant_literal() {
55 availability_from_enum_variant_literal(enum_variant_literal)
56 } else if let Some(unit) = provider.1.kind.as_unit() {
57 if let Some(enum_variant_literal) = unit.expressions().next().unwrap().kind.as_enum_variant_literal() {
58 availability_from_enum_variant_literal(enum_variant_literal)
59 } else {
60 Availability::no_database()
61 }
62 } else if let Some(arith) = provider.1.kind.as_arith_expr() {
63 match arith {
64 ArithExpr::Expression(e) => {
65 if let Some(unit) = e.kind.as_unit() {
66 if let Some(enum_variant_literal) = unit.expressions().next().unwrap().kind.as_enum_variant_literal() {
67 availability_from_enum_variant_literal(enum_variant_literal)
68 } else {
69 Availability::no_database()
70 }
71 } else if let Some(e) = e.kind.as_enum_variant_literal() {
72 availability_from_enum_variant_literal(e)
73 } else {
74 Availability::no_database()
75 }
76 }
77 _ => Availability::no_database(),
78 }
79 } else {
80 Availability::no_database()
81 }
82 } else {
83 Availability::no_database()
84 }
85 } else {
86 Availability::no_database()
87 }
88}
89
90pub(crate) fn find_namespace_availability(namespace: &Namespace, schema: &Schema, source: &Source) -> Availability {
91 if source.builtin {
92 return Availability::default(); }
94 let connector = find_namespace_connector(namespace, schema, source);
95 find_availability_in_connector(connector)
96}
97
98pub(crate) fn find_namespace_connector<'a>(namespace: &'a Namespace, schema: &'a Schema, source: &'a Source) -> Option<&'a Config> {
99 if let Some(connector) = namespace.get_connector() {
106 Some(connector)
107 } else {
108 let connector = source.imports().iter().find_map(|import| {
109 if let Some(source) = schema.source_at_path(&import.file_path) {
110 if let Some(namespace) = source.find_child_namespace_by_string_path(&namespace.str_path()) {
111 namespace.get_connector()
112 } else {
113 None
114 }
115 } else {
116 None
117 }
118 });
119 if let Some(connector) = connector {
120 return Some(connector);
121 }
122 let mut parent_namespace = source.parent_namespace_for_namespace(namespace);
123 loop {
124 if parent_namespace.is_some() {
125 if let Some(connector) = parent_namespace.unwrap().get_connector() {
126 return Some(connector);
127 } else {
128 let connector = source.imports().iter().find_map(|import| {
129 if let Some(source) = schema.source_at_path(&import.file_path) {
130 if let Some(namespace) = source.find_child_namespace_by_string_path(&namespace.str_path()) {
131 namespace.get_connector()
132 } else {
133 None
134 }
135 } else {
136 None
137 }
138 });
139 if let Some(connector) = connector {
140 return Some(connector);
141 }
142 }
143 parent_namespace = source.parent_namespace_for_namespace(parent_namespace.unwrap());
144 } else {
145 break
146 }
147 }
148 return find_source_connector(schema, source);
149 }
150}
151
152fn availability_from_enum_variant_literal(e: &EnumVariantLiteral) -> Availability {
153 match e.identifier().name() {
154 "mongo" => Availability::mongo(),
155 "mysql" => Availability::mysql(),
156 "postgres" => Availability::postgres(),
157 "sqlite" => Availability::sqlite(),
158 _ => Availability::no_database(),
159 }
160}