1mod builtin_casts;
2mod builtin_fun;
3mod builtin_ope;
4pub use self::{
5 builtin_casts::PgBuiltinCasts, builtin_fun::PgBuiltInFunctions, builtin_ope::PgBuiltinOperators,
6};
7
8use std::{fs::File, io::BufReader, path::Path};
9
10use crate::{
11 StringSpan, TrieMap,
12 sem::{
13 AnalysisError, AnalysisProblem, BaseParseContext, CastDefinition, CreateTable, FullName,
14 IndexInfoRead, LocalName, OperatorDefinition, SchemaName, TypeDefinition, TypeReference,
15 ViewLike, parse_context::SearchPathRead,
16 },
17};
18use serde::de::DeserializeOwned;
19use sql_fun_core::{PostgresBuiltinPaths, SqlFunArgs, SqlFunMetadata};
20
21use super::{
22 FunctionInfoRead, FunctionOverloadCollection,
23 parse_context::{
24 OperatorInfoRead, SequenceInfoRead, TableInfoRead, TypeInfoRead, ViewInfoRead,
25 },
26};
27
28#[derive(Debug)]
30pub struct BaseContext {
31 context_args: SqlFunArgs,
32 types: TrieMap<TypeDefinition>,
33 casts: TrieMap<TrieMap<CastDefinition>>,
34 binary_operators: TrieMap<OperatorDefinition>,
35 left_unary_operators: TrieMap<OperatorDefinition>,
36 right_unary_operators: TrieMap<OperatorDefinition>,
37 extensions: Vec<Box<dyn BaseParseContext>>,
38 statement_span: StringSpan,
39 search_path: Vec<SchemaName>,
40 functions: PgBuiltInFunctions,
41 source_provider: Option<Box<dyn super::SourceAccessService>>,
42 problems: Vec<AnalysisProblem>,
43}
44
45#[derive(serde::Deserialize)]
46struct BuiltinTypeInfo {
47 name: String,
48}
49
50impl BaseContext {
51 pub fn new(context_args: SqlFunArgs) -> Result<Self, AnalysisError> {
53 let metadata = SqlFunMetadata::load_from(context_args.metadata_file()?)?;
54 let paths = PostgresBuiltinPaths::try_from_args(&context_args, &metadata)?;
55 let builtin_functions = paths.functions()?;
56 let function_details = paths.function_details()?;
57 let builtin_type_data = Self::load_builtin_types(&paths)?;
58 let search_path = Self::setup_search_path(&context_args, &metadata)?;
59 let functions = PgBuiltInFunctions::load_from(builtin_functions, function_details)?;
60 let binary_operators = PgBuiltinOperators::load_binary(paths.binary_operators()?)?;
61 let left_unary_operators =
62 PgBuiltinOperators::load_left_unary(paths.left_unary_operators()?)?;
63 let right_unary_operators =
64 PgBuiltinOperators::load_right_unary(paths.right_unary_operators()?)?;
65 let casts = PgBuiltinCasts::load(paths.casts()?)?;
66
67 Ok(Self {
68 context_args,
69 functions,
70 types: builtin_type_data,
71 casts,
72 binary_operators,
73 left_unary_operators,
74 right_unary_operators,
75 extensions: Default::default(),
76 statement_span: Default::default(),
77 source_provider: None,
78 search_path,
79 problems: Default::default(),
80 })
81 }
82
83 fn load_builtin_types(
84 paths: &PostgresBuiltinPaths,
85 ) -> Result<TrieMap<TypeDefinition>, AnalysisError> {
86 let builtin_types_path = paths.types()?;
87 let builtin_types: Vec<BuiltinTypeInfo> =
88 serde_json::from_reader(BufReader::new(File::open(builtin_types_path)?))?;
89 let mut builtin_type_data = TrieMap::new();
90 for builtin_type in builtin_types {
91 let full_name = FullName::new(
92 &None,
93 &Some(SchemaName::from("pg_catalog")),
94 &LocalName::from(&builtin_type.name),
95 );
96 let type_definition = TypeDefinition::builtin(&full_name);
97 builtin_type_data.insert(&full_name.to_string(), type_definition);
98 }
99 Ok(builtin_type_data)
100 }
101
102 fn setup_search_path(
103 context_args: &SqlFunArgs,
104 metadata: &SqlFunMetadata,
105 ) -> Result<Vec<SchemaName>, AnalysisError> {
106 let search_path = context_args
107 .postgres_search_path(metadata)?
108 .into_iter()
109 .map(|v| SchemaName::from(&v))
110 .collect();
111 Ok(search_path)
112 }
113}
114
115impl TypeInfoRead for BaseContext {
116 fn get_type_impl(&self, key: &FullName) -> Option<&TypeDefinition> {
117 tracing::info!("get type {key}");
118 self.types.get(&key.to_string())
119 }
120
121 fn get_array_item_type(&self, _type_name: &TypeReference) -> Option<TypeReference> {
122 todo!()
123 }
124}
125
126impl TableInfoRead for BaseContext {
127 fn get_table_impl(&self, _key: &FullName) -> Option<&CreateTable> {
128 None
129 }
130}
131
132impl ViewInfoRead for BaseContext {
133 fn get_view_impl(&self, key: &FullName) -> Option<&ViewLike> {
134 for ext in &self.extensions {
135 if let Some(t) = ext.get_view_impl(key) {
136 return Some(t);
137 }
138 }
139 None
140 }
141}
142
143impl IndexInfoRead for BaseContext {
144 fn get_index(&self, _index_name: &str) -> Option<&super::CreateIndex> {
145 todo!()
146 }
147}
148
149impl SequenceInfoRead for BaseContext {
150 fn get_sequence_impl(&self, _seq_name: &FullName) -> Option<&super::CreateSequence> {
151 None
152 }
153}
154
155impl FunctionInfoRead for BaseContext {
156 fn get_function_impl(&self, name: &FullName) -> Option<FunctionOverloadCollection> {
157 let create_function = self.functions.find_function_by_name(name)?;
158 Some(create_function.overloads().clone())
159 }
160}
161
162impl OperatorInfoRead for BaseContext {
163 #[tracing::instrument(skip(self))]
164 fn get_operator_op(
165 &self,
166 name: &super::OperatorName,
167 has_left: bool,
168 has_right: bool,
169 ) -> Option<&super::OperatorDefinition> {
170 if !name.is_valid() {
171 return None;
172 }
173
174 match (has_left, has_right) {
175 (true, true) => self.binary_operators.get(&name.to_name_string()),
176 (true, false) => self.left_unary_operators.get(&name.to_name_string()),
177 (false, true) => self.right_unary_operators.get(&name.to_name_string()),
178 _ => panic!("no-param operator lookup"),
179 }
180 }
181}
182
183impl SearchPathRead for BaseContext {
184 fn set_search_path(&mut self, search_path: Vec<SchemaName>) {
185 self.search_path = search_path;
186 }
187
188 fn get_default_schema(&self) -> Option<SchemaName> {
189 self.search_path.first().cloned()
190 }
191
192 fn get_search_path(&self) -> &[SchemaName] {
193 &self.search_path
194 }
195}
196
197impl BaseParseContext for BaseContext {
198 fn get_args(&self) -> &SqlFunArgs {
199 &self.context_args
200 }
201
202 fn report_problem(&mut self, problem: AnalysisProblem) -> Result<(), AnalysisError> {
203 self.problems.push(problem);
204 Ok(())
205 }
206
207 fn extend(&mut self, extension: Box<dyn BaseParseContext>) {
208 self.extensions.push(extension);
209 }
210
211 fn set_statement_span(&mut self, statement_span: StringSpan) {
212 self.statement_span = statement_span;
213 }
214
215 fn get_source_file_path(&self) -> Option<&Path> {
216 None }
218
219 fn set_source_file(&mut self, source_acess_service: Box<dyn super::SourceAccessService>) {
220 self.source_provider = Some(source_acess_service)
221 }
222}
223
224fn deserialize_from_path<P, T>(path: P) -> Result<T, AnalysisError>
225where
226 P: AsRef<Path>,
227 T: DeserializeOwned,
228{
229 Ok(serde_json::from_reader(BufReader::new(File::open(path)?))?)
230}