Unified execution entry point - all queries flow through here
(&self, request: ExecutionRequest)
| 149 | |
| 150 | /// Unified execution entry point - all queries flow through here |
| 151 | pub fn execute_query(&self, request: ExecutionRequest) -> Result<QueryResult, ExecutionError> { |
| 152 | log::debug!( |
| 153 | "EXECUTE_QUERY: Statement type: {:?}", |
| 154 | std::mem::discriminant(&request.statement) |
| 155 | ); |
| 156 | let start_time = std::time::Instant::now(); |
| 157 | |
| 158 | // PHASE 1: Check if this is an UNWIND query that needs preprocessing |
| 159 | if let Some(ref query_text) = request.query_text { |
| 160 | if crate::exec::unwind_preprocessor::UnwindPreprocessor::is_unwind_query(query_text) { |
| 161 | log::debug!("EXECUTOR: Detected UNWIND query, using preprocessor"); |
| 162 | |
| 163 | // Use the preprocessor to handle this query |
| 164 | let executor_fn = |
| 165 | |query: &str| -> Result<crate::exec::result::QueryResult, ExecutionError> { |
| 166 | // Create a new request without the UNWIND (the individual queries won't have UNWIND) |
| 167 | let parsed_query = crate::ast::parser::parse_query(query).map_err(|e| { |
| 168 | ExecutionError::RuntimeError(format!( |
| 169 | "Failed to parse individual query: {}", |
| 170 | e |
| 171 | )) |
| 172 | })?; |
| 173 | |
| 174 | let new_request = ExecutionRequest { |
| 175 | statement: parsed_query.statement, |
| 176 | session: request.session.clone(), |
| 177 | graph_expr: request.graph_expr.clone(), |
| 178 | query_text: Some(query.to_string()), |
| 179 | physical_plan: None, |
| 180 | requires_graph_context: request.requires_graph_context, |
| 181 | }; |
| 182 | |
| 183 | // Execute the individual query normally |
| 184 | self.execute_query(new_request) |
| 185 | }; |
| 186 | |
| 187 | return crate::exec::unwind_preprocessor::UnwindPreprocessor::execute_unwind_query( |
| 188 | query_text, |
| 189 | executor_fn, |
| 190 | ); |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | // Step 1: Resolve execution context based on session and graph requirements |
| 195 | let needs_graph = if let Some(requires_graph) = request.requires_graph_context { |
| 196 | // Use the flag from validator if available (preferred) |
| 197 | requires_graph |
| 198 | } else { |
| 199 | // Fallback to statement-based detection |
| 200 | self.statement_needs_graph_context(&request.statement) |
| 201 | }; |
| 202 | |
| 203 | // Step 2: Resolve graph using PostgreSQL-style precedence: |
| 204 | // 1. Explicit graph expression in query (FROM clause) |
| 205 | // 2. Session's current graph |
| 206 | // 3. Error if needed but not available |
| 207 | let resolved_graph = if needs_graph { |
| 208 | Some(self.resolve_graph_for_execution(&request)?) |
no test coverage detected