Skip to main content

sql_fun_sqlast/
schema_dump_file.rs

1use std::path::Path;
2
3use crate::{
4    AstAndContextPair, StringSpan, parse, read_sql_file, scan,
5    sem::{
6        AnalysisError, AnalysisProblem, BaseParseContext, CastDefinition, CastInfoRead,
7        CreateIndex, CreateSequence, CreateTable, FullName, FunctionInfoRead,
8        FunctionOverloadCollection, IndexInfoRead, OperatorDefinition, OperatorInfoRead,
9        OperatorName, SchemaFileContext, SchemaName, SearchPathRead, SemAst, SequenceInfoRead,
10        SourceAccessService, TableInfoRead, TypeDefinition, TypeInfoRead, TypeReference,
11        ViewInfoRead, ViewLike, semantic_analysis,
12    },
13};
14/// Error for reading schema dump
15#[derive(Debug, thiserror::Error)]
16pub enum ParseDumpFileError {
17    /// IO Error
18    #[error(transparent)]
19    Io(#[from] std::io::Error),
20
21    /// Syntax Error
22    #[error(transparent)]
23    Syn(#[from] ::pg_query::Error),
24
25    /// Semantic Analysis Error
26    ///
27    /// # Note
28    ///
29    /// Semantic analysis normaly continues semantic error and reports to [`crate::sem::ParseContext`].
30    ///
31    /// Semantic Analysis Error indicates Analyzer Bug.(Unexpected syntax AST structure)
32    ///
33    #[error(transparent)]
34    Sem(#[from] AnalysisError),
35}
36
37/// load schema dump file
38///
39/// # Errors
40///
41/// - [`ParseDumpFileError`]
42///
43pub fn parse_schema_file<TContext>(
44    dump_file: &Path,
45    input_context: TContext,
46) -> Result<ParsedSchemaDump<TContext>, ParseDumpFileError>
47where
48    TContext: BaseParseContext + std::fmt::Debug,
49{
50    let sql_statements = read_sql_file(dump_file)?;
51
52    let statements = ::pg_query::split_with_parser(&sql_statements)?;
53    let mut context = SchemaFileContext::new(dump_file, input_context);
54    let mut sem_results = Vec::new();
55    for statement in statements {
56        context.set_statement_span(StringSpan::from_str_in_str(&sql_statements, statement));
57        let syn = parse(statement)?;
58        let tokens = scan(statement)?;
59        let AstAndContextPair(sem, rcontext) = semantic_analysis(context, syn, &tokens)?;
60        sem_results.push(sem);
61        context = rcontext;
62    }
63    Ok(ParsedSchemaDump(sem_results, context))
64}
65
66///  schema dump file context
67#[expect(dead_code)]
68#[derive(Debug)]
69pub struct ParsedSchemaDump<TContext>(Vec<SemAst>, SchemaFileContext<TContext>)
70where
71    TContext: BaseParseContext + std::fmt::Debug;
72
73impl<TContext> TypeInfoRead for ParsedSchemaDump<TContext>
74where
75    TContext: BaseParseContext + std::fmt::Debug,
76{
77    fn get_type_impl(&self, key: &FullName) -> Option<&TypeDefinition> {
78        self.1.get_type_impl(key)
79    }
80
81    fn get_array_item_type(&self, _type_name: &TypeReference) -> Option<TypeReference> {
82        todo!()
83    }
84}
85
86impl<TContext> TableInfoRead for ParsedSchemaDump<TContext>
87where
88    TContext: BaseParseContext + std::fmt::Debug,
89{
90    fn get_table_impl(&self, key: &FullName) -> Option<&CreateTable> {
91        self.1.get_table_impl(key)
92    }
93}
94
95impl<TContext> ViewInfoRead for ParsedSchemaDump<TContext>
96where
97    TContext: BaseParseContext + std::fmt::Debug,
98{
99    fn get_view_impl(&self, key: &FullName) -> Option<&ViewLike> {
100        self.1.get_view_impl(key)
101    }
102}
103
104impl<TContext> IndexInfoRead for ParsedSchemaDump<TContext>
105where
106    TContext: BaseParseContext + std::fmt::Debug,
107{
108    fn get_index(&self, index_name: &str) -> Option<&CreateIndex> {
109        self.1.get_index(index_name)
110    }
111}
112
113impl<TContext> SequenceInfoRead for ParsedSchemaDump<TContext>
114where
115    TContext: BaseParseContext + std::fmt::Debug,
116{
117    fn get_sequence_impl(&self, key: &FullName) -> Option<&CreateSequence> {
118        self.1.get_sequence_impl(key)
119    }
120}
121
122impl<TContext> FunctionInfoRead for ParsedSchemaDump<TContext>
123where
124    TContext: BaseParseContext + std::fmt::Debug,
125{
126    fn get_function_impl(&self, name: &FullName) -> Option<FunctionOverloadCollection> {
127        self.1.get_function_impl(name)
128    }
129}
130
131impl<TContext> CastInfoRead for ParsedSchemaDump<TContext>
132where
133    TContext: BaseParseContext + std::fmt::Debug,
134{
135    fn get_explicit_cast(
136        &self,
137        source_type: &TypeReference,
138        target_type: &TypeReference,
139    ) -> Option<CastDefinition> {
140        self.1.get_explicit_cast(source_type, target_type)
141    }
142
143    fn get_implicit_cast(
144        &self,
145        source_type: &TypeReference,
146        target_type: &TypeReference,
147    ) -> Option<CastDefinition> {
148        self.1.get_implicit_cast(source_type, target_type)
149    }
150
151    fn get_implicit_castable(
152        &self,
153        source_type: &TypeReference,
154    ) -> std::collections::HashSet<TypeReference> {
155        self.1.get_implicit_castable(source_type)
156    }
157}
158
159impl<TContext> OperatorInfoRead for ParsedSchemaDump<TContext>
160where
161    TContext: BaseParseContext + std::fmt::Debug,
162{
163    fn get_operator_op(
164        &self,
165        name: &OperatorName,
166        has_left: bool,
167        has_right: bool,
168    ) -> Option<&OperatorDefinition> {
169        self.1.get_operator_op(name, has_left, has_right)
170    }
171}
172
173impl<TContext> SearchPathRead for ParsedSchemaDump<TContext>
174where
175    TContext: BaseParseContext + std::fmt::Debug,
176{
177    fn set_search_path(&mut self, search_path: Vec<SchemaName>) {
178        self.1.set_search_path(search_path);
179    }
180
181    fn get_default_schema(&self) -> Option<SchemaName> {
182        self.1.get_default_schema()
183    }
184
185    fn get_search_path(&self) -> &[SchemaName] {
186        self.1.get_search_path()
187    }
188}
189
190impl<TContext> BaseParseContext for ParsedSchemaDump<TContext>
191where
192    TContext: BaseParseContext + std::fmt::Debug,
193{
194    fn report_problem(&mut self, problem: AnalysisProblem) -> Result<(), AnalysisError> {
195        self.1.report_problem(problem)?;
196        Ok(())
197    }
198
199    fn extend(&mut self, extension: Box<dyn BaseParseContext>) {
200        self.1.extend(extension);
201    }
202
203    fn set_statement_span(&mut self, statement_span: StringSpan) {
204        self.1.set_statement_span(statement_span);
205    }
206
207    fn get_args(&self) -> &sql_fun_core::SqlFunArgs {
208        self.1.get_args()
209    }
210
211    fn get_source_file_path(&self) -> Option<&Path> {
212        self.1.get_source_file_path()
213    }
214
215    fn set_source_file(&mut self, source_acess_service: Box<dyn SourceAccessService>) {
216        self.1.set_source_file(source_acess_service);
217    }
218}