pg_query/
summary_result.rs1use std::collections::HashMap;
2use std::collections::HashSet;
3use std::iter::FromIterator;
4use std::string::String;
5
6use crate::protobuf::summary_result::Context;
7use crate::*;
8
9#[derive(Debug, PartialEq)]
23pub struct SummaryResult {
24 pub protobuf: protobuf::SummaryResult,
25 pub warnings: Vec<String>,
26 pub tables: Vec<Table>,
27 pub aliases: HashMap<String, String>,
28 pub cte_names: Vec<String>,
29 pub functions: Vec<Function>,
30 pub filter_columns: Vec<FilterColumn>,
31 pub truncated_query: String,
32 pub statement_types: Vec<String>,
33}
34
35impl SummaryResult {
36 pub fn new(protobuf: protobuf::SummaryResult, stderr: String) -> Self {
37 let warnings = stderr.lines().filter_map(|l| if l.starts_with("WARNING") { Some(l.trim().into()) } else { None }).collect();
38 let mut tables: HashSet<Table> = HashSet::new();
39 let aliases = protobuf.aliases.clone();
40 let cte_names: HashSet<String> = HashSet::from_iter(protobuf.cte_names.to_owned());
41 let mut functions: HashSet<Function> = HashSet::new();
42 let mut filter_columns: HashSet<FilterColumn> = HashSet::new();
43 let truncated_query = protobuf.truncated_query.to_owned();
44 let statement_types = protobuf.statement_types.clone();
45
46 for table in &protobuf.tables {
47 tables.insert(Table::from(table));
48 }
49
50 for function in &protobuf.functions {
51 functions.insert(Function::from(function));
52 }
53
54 for filter_column in &protobuf.filter_columns {
55 filter_columns.insert(FilterColumn::from(filter_column));
56 }
57
58 Self {
59 protobuf,
60 warnings,
61 tables: Vec::from_iter(tables),
62 aliases,
63 cte_names: Vec::from_iter(cte_names),
64 functions: Vec::from_iter(functions),
65 filter_columns: Vec::from_iter(filter_columns),
66 truncated_query,
67 statement_types,
68 }
69 }
70
71 pub fn tables(&self) -> Vec<String> {
73 let mut tables = HashSet::new();
74 self.tables.iter().for_each(|table| {
75 tables.insert(table.name.clone());
76 });
77 Vec::from_iter(tables)
78 }
79
80 pub fn select_tables(&self) -> Vec<String> {
82 self.tables
83 .iter()
84 .filter_map(|table| match &table.context {
85 Context::Select => Some(table.name.to_string()),
86 _ => None,
87 })
88 .collect()
89 }
90
91 pub fn dml_tables(&self) -> Vec<String> {
93 self.tables
94 .iter()
95 .filter_map(|table| match &table.context {
96 Context::Dml => Some(table.name.to_string()),
97 _ => None,
98 })
99 .collect()
100 }
101
102 pub fn ddl_tables(&self) -> Vec<String> {
104 self.tables
105 .iter()
106 .filter_map(|table| match &table.context {
107 Context::Ddl => Some(table.name.to_string()),
108 _ => None,
109 })
110 .collect()
111 }
112
113 pub fn functions(&self) -> Vec<String> {
115 let mut functions = HashSet::new();
116 self.functions.iter().for_each(|f| {
117 functions.insert(f.name.to_string());
118 });
119 Vec::from_iter(functions)
120 }
121
122 pub fn ddl_functions(&self) -> Vec<String> {
124 self.functions
125 .iter()
126 .filter_map(|function| match &function.context {
127 Context::Ddl => Some(function.name.to_string()),
128 _ => None,
129 })
130 .collect()
131 }
132
133 pub fn call_functions(&self) -> Vec<String> {
135 self.functions
136 .iter()
137 .filter_map(|function| match &function.context {
138 Context::Call => Some(function.name.to_string()),
139 _ => None,
140 })
141 .collect()
142 }
143
144 pub fn statement_types(&self) -> Vec<&str> {
146 self.statement_types.iter().map(AsRef::as_ref).collect()
149 }
150}
151
152#[derive(Debug, Eq, Hash, PartialEq)]
153pub struct Table {
154 pub name: String,
155 pub schema_name: String,
156 pub table_name: String,
157 pub context: Context,
158}
159
160impl From<&protobuf::summary_result::Table> for Table {
161 fn from(v: &protobuf::summary_result::Table) -> Self {
162 Self {
163 name: v.name.to_owned(),
164 schema_name: v.schema_name.to_owned(),
165 table_name: v.table_name.to_owned(),
166 context: Context::try_from(v.context).unwrap_or(Context::None),
167 }
168 }
169}
170
171#[derive(Debug, Eq, Hash, PartialEq)]
172pub struct Function {
173 pub name: String,
174 pub function_name: String,
175 pub schema_name: Option<String>,
176 pub context: Context,
177}
178
179impl From<&protobuf::summary_result::Function> for Function {
180 fn from(v: &protobuf::summary_result::Function) -> Self {
181 let schema_name = (!v.schema_name.is_empty()).then(|| v.schema_name.to_owned());
182
183 Function {
184 name: v.name.to_owned(),
185 function_name: v.function_name.to_owned(),
186 schema_name: schema_name,
187 context: Context::try_from(v.context).unwrap_or(Context::None),
188 }
189 }
190}
191
192#[derive(Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
193pub struct FilterColumn {
194 pub schema_name: Option<String>,
195 pub table_name: Option<String>,
196 pub column: String,
197}
198
199impl From<&protobuf::summary_result::FilterColumn> for FilterColumn {
200 fn from(v: &protobuf::summary_result::FilterColumn) -> Self {
201 let schema_name = (!v.schema_name.is_empty()).then(|| v.schema_name.to_owned());
202 let table_name = (!v.table_name.is_empty()).then(|| v.table_name.to_owned());
203 let column = v.column.to_owned();
204
205 Self { schema_name, table_name, column }
206 }
207}