sql_fun_sqlast/sem/
from_clause.rs1use sql_fun_core::IVec;
2
3use crate::{
4 sem::{
5 AliasSpec, AnalysisError, AnalysisProblem, DataSource, Nullable, ParseContext, WithClause,
6 create_table::ColumnName, data_source::AliasName,
7 },
8 syn::{ListOpt, ScanToken},
9};
10
11#[derive(Debug, Clone, Default, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
13pub struct FromClause(Vec<DataSource>);
14
15impl FromClause {
16 pub fn push(&mut self, source: DataSource) {
18 self.0.push(source);
19 }
20
21 pub fn analyze<TParseContext>(
23 mut context: TParseContext,
24 with_clause: &WithClause,
25 syn: crate::syn::NodeListOpt,
26 tokens: &IVec<ScanToken>,
27 ) -> Result<(FromClause, TParseContext), AnalysisError>
28 where
29 TParseContext: ParseContext,
30 {
31 let Some(nodes) = syn.as_inner() else {
32 AnalysisError::raise_unexpected_none("from_clause.as_inner")?
33 };
34 let mut from_clause = FromClause::default();
35 let mut existing_aliases = Vec::new();
36
37 for node in nodes {
38 let (source, new_context) = DataSource::analyze_from_clause_node(
39 context,
40 with_clause,
41 &from_clause,
42 node,
43 tokens,
44 )?;
45 context = new_context;
46
47 let aliases = source.get_aliases();
48 for alias in aliases {
49 if existing_aliases.contains(&alias) {
50 context.report_problem(AnalysisProblem::duplicate_alias(alias.name()))?;
51 }
52 existing_aliases.push(alias);
53 }
54 from_clause.push(source);
55 }
56 Ok((from_clause, context))
57 }
58
59 #[must_use]
61 pub fn resolve_alias(&self, alias_name: &AliasName) -> Option<(&DataSource, Nullable)> {
62 for source in &self.0 {
63 if let Some(resolved) = source.resolve_alias(alias_name) {
64 return Some(resolved);
65 }
66 }
67 None
68 }
69
70 pub fn find_alias_for_column<TParseContext>(
72 &self,
73 column: &ColumnName,
74 context: &TParseContext,
75 with_clause: &WithClause,
76 ) -> Result<Option<AliasSpec>, Vec<AliasSpec>>
77 where
78 TParseContext: ParseContext,
79 {
80 let mut aliases = Vec::new();
81
82 for source in &self.0 {
83 let mut results = source.get_aliases_for_column(column, context, with_clause);
84 aliases.append(&mut results);
85 }
86
87 if aliases.is_empty() {
88 Ok(None)
89 } else if aliases.len() == 1 {
90 Ok(Some(aliases[0].clone()))
91 } else {
92 Err(aliases)
93 }
94 }
95}