uqa_sql/catalog/resolution/
candidates.rs1#[cfg(test)]
9mod tests;
10use std::ops::Deref;
11use uqa_core::RelationIdentity;
12pub type SearchPathRead<'a> = Box<dyn Deref<Target = Vec<String>> + 'a>;
13pub trait RelationCandidateState {
14 fn temporary_schema_name(&self) -> String;
15 fn search_path(&self) -> SearchPathRead<'_>;
16}
17pub fn relation_lookup_candidates(
18 state: &dyn RelationCandidateState,
19 name: &str,
20) -> Result<Vec<RelationIdentity>, String> {
21 let (schema, relation) = RelationIdentity::parse_reference(name)?;
22 if let Some(schema) = schema {
23 if schema == "pg_temp" {
24 return Ok(vec![RelationIdentity::new(
25 state.temporary_schema_name(),
26 relation,
27 )]);
28 }
29 return Ok(vec![RelationIdentity::new(schema, relation)]);
30 }
31 let temporary = state.temporary_schema_name();
32 let path = state.search_path();
33 Ok(unqualified_candidates(&temporary, &path, &relation))
34}
35
36pub(super) fn unqualified_candidates(
37 temporary: &str,
38 path: &[String],
39 relation: &str,
40) -> Vec<RelationIdentity> {
41 let mut candidates = Vec::new();
42 if !path
43 .iter()
44 .any(|schema| schema == "pg_temp" || schema == temporary)
45 {
46 candidates.push(RelationIdentity::new(temporary, relation));
47 }
48 if !path.iter().any(|schema| schema == "pg_catalog") {
49 candidates.push(RelationIdentity::new("pg_catalog", relation));
50 }
51 candidates.extend(path.iter().map(|schema| {
52 RelationIdentity::new(
53 if schema == "pg_temp" {
54 temporary
55 } else {
56 schema
57 },
58 relation,
59 )
60 }));
61 candidates
62}