(query: &sqlparser::ast::Query, db: Arc<DbHandler>, session: Option<Arc<SessionState>>)
| 209 | } |
| 210 | |
| 211 | async fn handle_catalog_query(query: &sqlparser::ast::Query, db: Arc<DbHandler>, session: Option<Arc<SessionState>>) -> Option<DbResponse> { |
| 212 | debug!("handle_catalog_query called"); |
| 213 | println!("HANDLE_CATALOG_QUERY: called with query"); |
| 214 | // Check if this is a SELECT from pg_catalog tables |
| 215 | if let SetExpr::Select(select) = &*query.body { |
| 216 | println!("HANDLE_CATALOG_QUERY: Is SELECT query, from.len()={}, has_joins={}", |
| 217 | select.from.len(), |
| 218 | !select.from.is_empty() && !select.from[0].joins.is_empty()); |
| 219 | debug!("Is SELECT query, from.len()={}, has_joins={}", |
| 220 | select.from.len(), |
| 221 | !select.from.is_empty() && !select.from[0].joins.is_empty()); |
| 222 | // Check if this is a JOIN query involving catalog tables |
| 223 | if !select.from.is_empty() && !select.from[0].joins.is_empty() { |
| 224 | debug!("Detected as JOIN query"); |
| 225 | println!("HANDLE_CATALOG_QUERY: Detected as JOIN query"); |
| 226 | |
| 227 | // Check if this is a JOIN between information_schema tables |
| 228 | if let TableFactor::Table { name: main_table, .. } = &select.from[0].relation { |
| 229 | let main_table_name = main_table.to_string().to_lowercase(); |
| 230 | println!("HANDLE_CATALOG_QUERY: Main table name: '{}'", main_table_name); |
| 231 | |
| 232 | // Check if main table and all JOINs are information_schema tables |
| 233 | let is_information_schema_join = main_table_name.contains("information_schema") && |
| 234 | select.from[0].joins.iter().all(|j| { |
| 235 | if let TableFactor::Table { name: join_table, .. } = &j.relation { |
| 236 | let join_table_name = join_table.to_string().to_lowercase(); |
| 237 | println!("HANDLE_CATALOG_QUERY: Join table name: '{}'", join_table_name); |
| 238 | join_table_name.contains("information_schema") |
| 239 | } else { |
| 240 | false |
| 241 | } |
| 242 | }); |
| 243 | |
| 244 | println!("HANDLE_CATALOG_QUERY: is_information_schema_join = {}", is_information_schema_join); |
| 245 | |
| 246 | if is_information_schema_join { |
| 247 | debug!("Detected information_schema JOIN query - translating and executing"); |
| 248 | println!("HANDLE_CATALOG_QUERY: Detected information_schema JOIN query"); |
| 249 | |
| 250 | // Information_schema tables exist as views with underscores, not dots |
| 251 | // e.g., information_schema_table_constraints instead of information_schema.table_constraints |
| 252 | // We need to translate the query to use the correct view names |
| 253 | if let Some(ref session) = session { |
| 254 | let session_id = session.id; |
| 255 | let mut query_str = query.to_string(); |
| 256 | |
| 257 | // Replace information_schema.table_name with information_schema_table_name |
| 258 | query_str = query_str.replace("information_schema.table_constraints", "information_schema_table_constraints"); |
| 259 | query_str = query_str.replace("information_schema.key_column_usage", "information_schema_key_column_usage"); |
| 260 | query_str = query_str.replace("information_schema.referential_constraints", "information_schema_referential_constraints"); |
| 261 | query_str = query_str.replace("information_schema.columns", "information_schema_columns"); |
| 262 | query_str = query_str.replace("information_schema.tables", "information_schema_tables"); |
| 263 | query_str = query_str.replace("information_schema.schemata", "information_schema_schemata"); |
| 264 | |
| 265 | println!("HANDLE_CATALOG_QUERY: Translated query: {}", query_str); |
| 266 | |
| 267 | match db.connection_manager().execute_with_session(&session_id, |conn| { |
| 268 | debug!("Executing translated information_schema JOIN query: {}", query_str); |
nothing calls this directly
no test coverage detected