Skip to main content

sql_fun_sqlast/sem/
base_context.rs

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/// schema informations for Builtin and extensions
29#[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    /// initialize base context
52    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 // BaseContext contains built-in data item, from Non SQL Source
217    }
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}