Query with optimized statement caching
(
&self,
conn: &Connection,
query: &str,
params: P,
)
| 71 | |
| 72 | /// Query with optimized statement caching |
| 73 | pub fn query_with_optimization<P: rusqlite::Params>( |
| 74 | &self, |
| 75 | conn: &Connection, |
| 76 | query: &str, |
| 77 | params: P, |
| 78 | ) -> Result<(Vec<String>, crate::session::db_handler::DbRows), rusqlite::Error> { |
| 79 | if !self.enabled { |
| 80 | return self.execute_basic_query(conn, query, params); |
| 81 | } |
| 82 | |
| 83 | // Analyze query for optimization opportunities |
| 84 | let optimization_result = self.optimization_manager |
| 85 | .analyze_query(query) |
| 86 | .map_err(|e| rusqlite::Error::SqliteFailure( |
| 87 | rusqlite::ffi::Error::new(rusqlite::ffi::SQLITE_MISUSE), |
| 88 | Some(format!("Query optimization failed: {e}")) |
| 89 | ))?; |
| 90 | |
| 91 | // Use enhanced statement pool for SELECT queries that benefit from caching |
| 92 | // and don't require binary protocol support |
| 93 | debug!("Query analysis result for '{}': pattern={:?}, cache_result={}, supports_binary={}", |
| 94 | query, optimization_result.pattern, optimization_result.hints.cache_result, |
| 95 | self.supports_binary_protocol(query)); |
| 96 | |
| 97 | if optimization_result.hints.cache_result && |
| 98 | self.supports_binary_protocol(query) && |
| 99 | matches!(optimization_result.pattern, |
| 100 | QueryPattern::SimpleSelect | |
| 101 | QueryPattern::CountQuery | |
| 102 | QueryPattern::MaxMinQuery | |
| 103 | QueryPattern::OrderByLimit |
| 104 | ) { |
| 105 | debug!("Using enhanced statement cache for SELECT query pattern: {:?}", optimization_result.pattern); |
| 106 | let (mut stmt, metadata) = self.statement_pool.prepare_and_cache_enhanced(conn, query)?; |
| 107 | |
| 108 | // Execute query and collect results |
| 109 | let mut results = Vec::new(); |
| 110 | let column_names = metadata.column_names.clone(); |
| 111 | info!("Statement metadata - column_names: {:?}, column_types: {:?}", column_names, metadata.column_types); |
| 112 | |
| 113 | let rows = stmt.query_map(params, |row| { |
| 114 | let mut row_data = Vec::new(); |
| 115 | for i in 0..column_names.len() { |
| 116 | match row.get_ref(i)? { |
| 117 | rusqlite::types::ValueRef::Null => row_data.push(None), |
| 118 | rusqlite::types::ValueRef::Integer(val) => { |
| 119 | // Check if this column is a boolean type |
| 120 | let is_boolean = metadata.column_types.get(i) |
| 121 | .and_then(|opt| opt.as_ref()) |
| 122 | .map(|pg_type| { |
| 123 | let type_lower = pg_type.to_lowercase(); |
| 124 | type_lower == "boolean" || type_lower == "bool" |
| 125 | }) |
| 126 | .unwrap_or(false); |
| 127 | |
| 128 | if is_boolean { |
| 129 | // Convert integer 0/1 to PostgreSQL f/t format |
| 130 | let bool_str = if val == 0 { "f" } else { "t" }; |
nothing calls this directly
no test coverage detected