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#[derive(Debug, thiserror::Error)]
16pub enum ParseDumpFileError {
17 #[error(transparent)]
19 Io(#[from] std::io::Error),
20
21 #[error(transparent)]
23 Syn(#[from] ::pg_query::Error),
24
25 #[error(transparent)]
34 Sem(#[from] AnalysisError),
35}
36
37pub 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#[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}