A Claude-written graph database in Rust. Use at your own risk.
1use crate::cypher::planner::{QueryPlan, ScanPlan, CreatePlan, ProjectPlan};
2use crate::cypher::ast::{CypherQuery, MatchClause, CreateClause, ReturnClause, Expression, PatternElement};
3use crate::core::{Graph, PropertyValue};
4use crate::index::{IndexQuery, IndexType};
5use crate::{Result, GigabrainError, NodeId, RelationshipId};
6use std::sync::Arc;
7use std::collections::HashMap;
8use tracing::{debug, info};
9
10pub struct QueryExecutor {
11 graph: Arc<Graph>,
12}
13
14impl QueryExecutor {
15 pub fn new(graph: Arc<Graph>) -> Self {
16 Self { graph }
17 }
18
19 pub async fn execute_query(&self, query: &CypherQuery) -> Result<QueryResult> {
20 match query {
21 CypherQuery::Match(match_clause) => self.execute_match(match_clause).await,
22 CypherQuery::Create(create_clause) => self.execute_create_query(create_clause).await,
23 CypherQuery::Return(return_clause) => self.execute_return(return_clause).await,
24 CypherQuery::Compound(queries) => {
25 let mut context = ExecutionContext::new();
26 for query in queries {
27 let _result = self.execute_query_with_context(query, &mut context).await?;
28 // Store intermediate results in context for compound queries
29 }
30 Ok(context.into_result())
31 },
32 _ => Err(GigabrainError::Query("Query type not supported yet".to_string())),
33 }
34 }
35
36 fn execute_query_with_context<'a>(&'a self, query: &'a CypherQuery, context: &'a mut ExecutionContext) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<QueryResult>> + 'a>> {
37 Box::pin(async move {
38 match query {
39 CypherQuery::Match(match_clause) => {
40 let result = self.execute_match_with_context(match_clause, context).await?;
41 context.merge_result(result);
42 Ok(QueryResult::empty())
43 },
44 CypherQuery::Return(return_clause) => {
45 self.execute_return_with_context(return_clause, context).await
46 },
47 _ => self.execute_query(query).await,
48 }
49 })
50 }
51
52 async fn execute_match(&self, match_clause: &MatchClause) -> Result<QueryResult> {
53 let mut context = ExecutionContext::new();
54 self.execute_match_with_context(match_clause, &mut context).await?;
55
56 // Return all matched nodes directly
57 let all_nodes = self.graph.get_all_nodes();
58 let columns = vec!["n".to_string()];
59 let mut rows = Vec::new();
60
61 for node_id in all_nodes {
62 rows.push(Row {
63 values: vec![Value::Node(node_id)]
64 });
65 }
66
67 Ok(QueryResult { rows, columns })
68 }
69
70 async fn execute_match_with_context(&self, match_clause: &MatchClause, context: &mut ExecutionContext) -> Result<QueryResult> {
71 // Simple pattern matching for demonstration
72 // In reality, this would use a sophisticated query planner
73
74 let pattern = &match_clause.pattern;
75
76 // Process pattern elements sequentially
77 let mut i = 0;
78 while i < pattern.elements.len() {
79 match &pattern.elements[i] {
80 PatternElement::Node(node_pattern) => {
81 if let Some(variable) = &node_pattern.variable {
82 // Get nodes matching the pattern
83 let matching_nodes = self.find_matching_nodes(node_pattern).await?;
84 context.bind_variable(variable.clone(), VariableBinding::Nodes(matching_nodes));
85 }
86 i += 1;
87 },
88 PatternElement::Relationship(rel_pattern) => {
89 // Handle relationship patterns
90 if let Some(variable) = &rel_pattern.variable {
91 // For now, get all relationships
92 // TODO: Implement proper relationship matching based on type and direction
93 let all_relationships = self.get_all_relationships().await?;
94 context.bind_variable(variable.clone(), VariableBinding::Relationships(all_relationships));
95 }
96 i += 1;
97 },
98 _ => {
99 i += 1;
100 }
101 }
102 }
103
104 // Apply WHERE clause filtering if present
105 if let Some(where_expr) = &match_clause.where_clause {
106 self.apply_where_filter(context, where_expr).await?;
107 }
108
109 Ok(QueryResult::empty())
110 }
111
112 async fn apply_where_filter(&self, context: &mut ExecutionContext, where_expr: &Expression) -> Result<()> {
113 // Create a new context to store filtered results
114 let mut filtered_context = ExecutionContext::new();
115
116 // For each variable binding, evaluate the WHERE clause
117 let variable_names: Vec<String> = context.variables.keys().cloned().collect();
118
119 if variable_names.is_empty() {
120 return Ok(());
121 }
122
123 // Get all possible combinations of variable bindings
124 let combinations = self.generate_binding_combinations(context).await?;
125
126 // Filter combinations based on WHERE clause
127 let mut filtered_combinations = Vec::new();
128 for combination in combinations {
129 // Create a temporary context with this specific binding combination
130 let mut temp_context = ExecutionContext::new();
131 for (var_name, binding) in &combination {
132 temp_context.bind_variable(var_name.clone(), binding.clone());
133 }
134
135 // Evaluate WHERE clause with this binding
136 let result = self.evaluate_expression(where_expr, &temp_context, None).await?;
137
138 if self.is_truthy(&result) {
139 filtered_combinations.push(combination);
140 }
141 }
142
143 // Rebuild the context with filtered results
144 self.rebuild_context_from_combinations(context, filtered_combinations);
145
146 Ok(())
147 }
148
149 async fn generate_binding_combinations(&self, context: &ExecutionContext) -> Result<Vec<HashMap<String, VariableBinding>>> {
150 let mut combinations = Vec::new();
151 let variable_names: Vec<String> = context.variables.keys().cloned().collect();
152
153 if variable_names.is_empty() {
154 return Ok(combinations);
155 }
156
157 // Generate all combinations of variable bindings
158 // This is a simplified approach - for performance, we'd use join algorithms
159 if variable_names.len() == 1 {
160 let var_name = &variable_names[0];
161 if let Some(binding) = context.variables.get(var_name) {
162 match binding {
163 VariableBinding::Nodes(node_ids) => {
164 for &node_id in node_ids {
165 let mut combination = HashMap::new();
166 combination.insert(var_name.clone(), VariableBinding::Nodes(vec![node_id]));
167 combinations.push(combination);
168 }
169 },
170 VariableBinding::Relationships(rel_ids) => {
171 for &rel_id in rel_ids {
172 let mut combination = HashMap::new();
173 combination.insert(var_name.clone(), VariableBinding::Relationships(vec![rel_id]));
174 combinations.push(combination);
175 }
176 }
177 }
178 }
179 } else {
180 // For multiple variables, generate cartesian product
181 // This is simplified - real implementation would be more efficient
182 self.generate_cartesian_product(context, &variable_names, 0, &mut HashMap::new(), &mut combinations);
183 }
184
185 Ok(combinations)
186 }
187
188 fn generate_cartesian_product(
189 &self,
190 context: &ExecutionContext,
191 variable_names: &[String],
192 index: usize,
193 current_combination: &mut HashMap<String, VariableBinding>,
194 combinations: &mut Vec<HashMap<String, VariableBinding>>
195 ) {
196 if index >= variable_names.len() {
197 combinations.push(current_combination.clone());
198 return;
199 }
200
201 let var_name = &variable_names[index];
202 if let Some(binding) = context.variables.get(var_name) {
203 match binding {
204 VariableBinding::Nodes(node_ids) => {
205 for &node_id in node_ids {
206 current_combination.insert(var_name.clone(), VariableBinding::Nodes(vec![node_id]));
207 self.generate_cartesian_product(context, variable_names, index + 1, current_combination, combinations);
208 }
209 },
210 VariableBinding::Relationships(rel_ids) => {
211 for &rel_id in rel_ids {
212 current_combination.insert(var_name.clone(), VariableBinding::Relationships(vec![rel_id]));
213 self.generate_cartesian_product(context, variable_names, index + 1, current_combination, combinations);
214 }
215 }
216 }
217 }
218 }
219
220 fn rebuild_context_from_combinations(&self, context: &mut ExecutionContext, combinations: Vec<HashMap<String, VariableBinding>>) {
221 // Clear current context
222 context.variables.clear();
223
224 // Group combinations back into variable bindings
225 let mut var_to_nodes: HashMap<String, Vec<NodeId>> = HashMap::new();
226 let mut var_to_rels: HashMap<String, Vec<RelationshipId>> = HashMap::new();
227
228 for combination in combinations {
229 for (var_name, binding) in combination {
230 match binding {
231 VariableBinding::Nodes(node_ids) => {
232 var_to_nodes.entry(var_name).or_insert_with(Vec::new).extend(node_ids);
233 },
234 VariableBinding::Relationships(rel_ids) => {
235 var_to_rels.entry(var_name).or_insert_with(Vec::new).extend(rel_ids);
236 }
237 }
238 }
239 }
240
241 // Rebuild context with filtered bindings
242 for (var_name, node_ids) in var_to_nodes {
243 context.bind_variable(var_name, VariableBinding::Nodes(node_ids));
244 }
245
246 for (var_name, rel_ids) in var_to_rels {
247 context.bind_variable(var_name, VariableBinding::Relationships(rel_ids));
248 }
249 }
250
251 async fn find_matching_nodes(&self, node_pattern: &crate::cypher::ast::NodePattern) -> Result<Vec<NodeId>> {
252 debug!("Finding nodes matching pattern: labels={:?}, properties={:?}",
253 node_pattern.labels, node_pattern.properties);
254
255 let mut candidate_nodes: Option<Vec<NodeId>> = None;
256
257 // Use label indexes if labels are specified
258 if !node_pattern.labels.is_empty() {
259 debug!("Using label indexes for labels: {:?}", node_pattern.labels);
260 let mut label_matches = Vec::new();
261
262 for label_name in &node_pattern.labels {
263 match self.graph.find_nodes_by_label(label_name) {
264 Ok(nodes) => {
265 if label_matches.is_empty() {
266 label_matches = nodes;
267 } else {
268 // Intersect with previous results (AND logic for multiple labels)
269 label_matches.retain(|node_id| nodes.contains(node_id));
270 }
271 },
272 Err(e) => {
273 debug!("Failed to use label index for '{}': {}", label_name, e);
274 // Fall back to scanning all nodes
275 label_matches = self.graph.get_all_nodes();
276 break;
277 }
278 }
279 }
280
281 candidate_nodes = Some(label_matches);
282 info!("Label index returned {} candidate nodes", candidate_nodes.as_ref().unwrap().len());
283 }
284
285 // Use property indexes if properties are specified
286 if let Some(ref properties) = node_pattern.properties {
287 debug!("Using property indexes for {} properties", properties.len());
288 let mut property_matches: Option<Vec<NodeId>> = None;
289
290 for (prop_name, value_expr) in properties {
291 // For now, only handle literal values in property patterns
292 if let Expression::Literal(prop_value) = value_expr {
293 match self.graph.find_nodes_by_property(prop_name, prop_value) {
294 Ok(nodes) => {
295 if let Some(ref mut existing_matches) = property_matches {
296 // Intersect with previous property matches
297 existing_matches.retain(|node_id| nodes.contains(node_id));
298 } else {
299 property_matches = Some(nodes);
300 }
301 },
302 Err(e) => {
303 debug!("Failed to use property index for '{}': {}", prop_name, e);
304 // Continue with other properties or fall back to scanning
305 }
306 }
307 }
308 }
309
310 if let Some(prop_nodes) = property_matches {
311 if let Some(ref mut candidates) = candidate_nodes {
312 // Intersect label matches with property matches
313 candidates.retain(|node_id| prop_nodes.contains(node_id));
314 } else {
315 candidate_nodes = Some(prop_nodes);
316 }
317 info!("Property index intersection returned {} candidate nodes",
318 candidate_nodes.as_ref().unwrap().len());
319 }
320 }
321
322 // If no indexes were used, scan all nodes
323 let result_nodes = candidate_nodes.unwrap_or_else(|| {
324 debug!("No indexes available, scanning all nodes");
325 self.graph.get_all_nodes()
326 });
327
328 // TODO: Apply additional filtering for complex property expressions
329 // that couldn't be handled by indexes
330
331 debug!("Final result: {} nodes matched the pattern", result_nodes.len());
332 Ok(result_nodes)
333 }
334
335 async fn get_all_relationships(&self) -> Result<Vec<RelationshipId>> {
336 // Get all relationships in the graph
337 // This is a simplified implementation - normally we'd iterate through the graph structure
338 let mut all_relationships = Vec::new();
339
340 // For each node, get its relationships
341 for node_id in self.graph.get_all_nodes() {
342 let relationships = self.graph.get_node_relationships(
343 node_id,
344 crate::core::relationship::Direction::Both,
345 None
346 );
347
348 for rel in relationships {
349 if !all_relationships.contains(&rel.id) {
350 all_relationships.push(rel.id);
351 }
352 }
353 }
354
355 Ok(all_relationships)
356 }
357
358 async fn execute_create_query(&self, create_clause: &CreateClause) -> Result<QueryResult> {
359 // Create new nodes/relationships based on pattern
360 let mut created_nodes = Vec::new();
361 let mut created_relationships = Vec::new();
362 let mut node_variables = HashMap::new();
363
364 // First pass: create all nodes
365 for element in &create_clause.pattern.elements {
366 if let PatternElement::Node(node_pattern) = element {
367 // Create a new node
368 let node_id = self.graph.create_node();
369
370 // Add labels and properties using update_node
371 self.graph.update_node(node_id, |node| {
372 // Add labels if specified
373 if !node_pattern.labels.is_empty() {
374 let schema = self.graph.schema();
375 for label_name in &node_pattern.labels {
376 let label_id = {
377 let mut schema_guard = schema.write();
378 schema_guard.get_or_create_label(label_name)
379 };
380 node.add_label(label_id);
381 }
382 }
383
384 // Add properties if specified
385 if let Some(ref properties) = node_pattern.properties {
386 let schema = self.graph.schema();
387 for (key, value_expr) in properties {
388 let property_key_id = {
389 let mut schema_guard = schema.write();
390 schema_guard.get_or_create_property_key(key)
391 };
392
393 // Convert expression to property value (simplified)
394 let property_value = match value_expr {
395 Expression::Literal(literal) => literal.clone(),
396 _ => PropertyValue::String("unknown".to_string()),
397 };
398
399 node.properties.insert(property_key_id, property_value);
400 }
401 }
402 })?;
403
404 created_nodes.push(node_id);
405
406 // Add to indexes after creating the node
407 if let Some(node) = self.graph.get_node(node_id) {
408 let labels: Vec<_> = node.labels.iter().cloned().collect();
409 let properties = node.properties.clone();
410
411 // Ensure indexes exist for any new labels
412 for &label_id in &labels {
413 let index_type = IndexType::Label(label_id);
414 if let Err(e) = self.graph.index_manager().create_index(index_type, None, false) {
415 debug!("Label index may already exist or failed to create: {}", e);
416 }
417 }
418
419 // Ensure indexes exist for any new properties
420 for &property_key_id in properties.keys() {
421 let index_type = IndexType::Property(property_key_id);
422 if let Err(e) = self.graph.index_manager().create_index(index_type, None, false) {
423 debug!("Property index may already exist or failed to create: {}", e);
424 }
425 }
426
427 // Add node to indexes
428 if let Err(e) = self.graph.index_manager().add_node(node_id, &labels, &properties) {
429 debug!("Failed to add created node to indexes: {}", e);
430 } else {
431 debug!("Added newly created node {} to indexes", node_id.0);
432 }
433 }
434
435 // Store node variable mapping for relationships
436 if let Some(var_name) = &node_pattern.variable {
437 node_variables.insert(var_name.clone(), node_id);
438 }
439 }
440 }
441
442 // Second pass: create relationships between nodes
443 let mut i = 0;
444 while i < create_clause.pattern.elements.len() {
445 if i + 2 < create_clause.pattern.elements.len() {
446 if let (PatternElement::Node(start_node), PatternElement::Relationship(rel_pattern), PatternElement::Node(end_node)) =
447 (&create_clause.pattern.elements[i], &create_clause.pattern.elements[i + 1], &create_clause.pattern.elements[i + 2]) {
448
449 // Get start and end node IDs
450 let start_id = if let Some(var_name) = &start_node.variable {
451 node_variables.get(var_name).copied()
452 } else {
453 created_nodes.first().copied()
454 };
455
456 let end_id = if let Some(var_name) = &end_node.variable {
457 node_variables.get(var_name).copied()
458 } else {
459 created_nodes.last().copied()
460 };
461
462 if let (Some(start_id), Some(end_id)) = (start_id, end_id) {
463 // Create the relationship
464 let rel_type_id = if let Some(rel_type_name) = rel_pattern.types.first() {
465 let schema = self.graph.schema();
466 let mut schema_guard = schema.write();
467 schema_guard.get_or_create_relationship_type(rel_type_name)
468 } else {
469 0 // Default relationship type
470 };
471
472 let rel_id = self.graph.create_relationship(start_id, end_id, rel_type_id)?;
473 created_relationships.push(rel_id);
474
475 // Add relationship properties if specified
476 if let Some(ref properties) = rel_pattern.properties {
477 // TODO: Implement relationship property setting
478 // This would require extending the graph API to update relationship properties
479 }
480 }
481
482 i += 3; // Skip the relationship pattern and end node
483 } else {
484 i += 1;
485 }
486 } else {
487 i += 1;
488 }
489 }
490
491 // Return result indicating what was created
492 let mut columns = Vec::new();
493 let mut values = Vec::new();
494
495 if !created_nodes.is_empty() {
496 columns.push("nodes_created".to_string());
497 values.push(Value::Integer(created_nodes.len() as i64));
498 }
499
500 if !created_relationships.is_empty() {
501 columns.push("relationships_created".to_string());
502 values.push(Value::Integer(created_relationships.len() as i64));
503 }
504
505 let rows = if !values.is_empty() {
506 vec![Row { values }]
507 } else {
508 vec![Row { values: vec![Value::Integer(0)] }]
509 };
510
511 Ok(QueryResult { rows, columns })
512 }
513
514 async fn execute_return(&self, return_clause: &ReturnClause) -> Result<QueryResult> {
515 let mut context = ExecutionContext::new();
516 self.execute_return_with_context(return_clause, &mut context).await
517 }
518
519 async fn execute_return_with_context(&self, return_clause: &ReturnClause, context: &ExecutionContext) -> Result<QueryResult> {
520 let mut columns = Vec::new();
521 let mut rows = Vec::new();
522
523 // Extract column names
524 for item in &return_clause.items {
525 let column_name = if let Some(alias) = &item.alias {
526 alias.clone()
527 } else {
528 self.expression_to_string(&item.expression)
529 };
530 columns.push(column_name);
531 }
532
533 // Generate result rows based on variable bindings
534 if let Some(first_binding) = context.variables.values().next() {
535 match first_binding {
536 VariableBinding::Nodes(node_ids) => {
537 for node_id in node_ids {
538 let mut values = Vec::new();
539 for item in &return_clause.items {
540 values.push(self.evaluate_expression(&item.expression, context, Some(*node_id)).await?);
541 }
542 rows.push(Row { values });
543 }
544 },
545 _ => {}
546 }
547 }
548
549 Ok(QueryResult { rows, columns })
550 }
551
552 fn evaluate_expression<'a>(&'a self, expr: &'a Expression, context: &'a ExecutionContext, current_node: Option<NodeId>) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Value>> + 'a>> {
553 Box::pin(async move {
554 match expr {
555 Expression::Variable(var_name) => {
556 if let Some(binding) = context.variables.get(var_name) {
557 match binding {
558 VariableBinding::Nodes(nodes) => {
559 if let Some(node_id) = current_node {
560 Ok(Value::Node(node_id))
561 } else if let Some(&first_node) = nodes.first() {
562 Ok(Value::Node(first_node))
563 } else {
564 Ok(Value::Null)
565 }
566 },
567 VariableBinding::Relationships(rels) => {
568 if let Some(&first_rel) = rels.first() {
569 Ok(Value::Relationship(first_rel))
570 } else {
571 Ok(Value::Null)
572 }
573 }
574 }
575 } else {
576 Ok(Value::Null)
577 }
578 },
579 Expression::Property(prop_expr) => {
580 let base_value = self.evaluate_expression(&prop_expr.expression, context, current_node).await?;
581 self.get_property_value(base_value, &prop_expr.property).await
582 },
583 Expression::Literal(literal) => {
584 Ok(self.property_value_to_executor_value(literal))
585 },
586 Expression::Equal(left, right) => {
587 let left_val = self.evaluate_expression(left, context, current_node).await?;
588 let right_val = self.evaluate_expression(right, context, current_node).await?;
589 Ok(Value::Boolean(self.values_equal(&left_val, &right_val)))
590 },
591 Expression::NotEqual(left, right) => {
592 let left_val = self.evaluate_expression(left, context, current_node).await?;
593 let right_val = self.evaluate_expression(right, context, current_node).await?;
594 Ok(Value::Boolean(!self.values_equal(&left_val, &right_val)))
595 },
596 Expression::And(left, right) => {
597 let left_val = self.evaluate_expression(left, context, current_node).await?;
598 let right_val = self.evaluate_expression(right, context, current_node).await?;
599 Ok(Value::Boolean(self.is_truthy(&left_val) && self.is_truthy(&right_val)))
600 },
601 Expression::Or(left, right) => {
602 let left_val = self.evaluate_expression(left, context, current_node).await?;
603 let right_val = self.evaluate_expression(right, context, current_node).await?;
604 Ok(Value::Boolean(self.is_truthy(&left_val) || self.is_truthy(&right_val)))
605 },
606 Expression::Not(expr) => {
607 let val = self.evaluate_expression(expr, context, current_node).await?;
608 Ok(Value::Boolean(!self.is_truthy(&val)))
609 },
610 Expression::LessThan(left, right) => {
611 let left_val = self.evaluate_expression(left, context, current_node).await?;
612 let right_val = self.evaluate_expression(right, context, current_node).await?;
613 Ok(Value::Boolean(self.compare_values(&left_val, &right_val) < 0))
614 },
615 Expression::LessThanOrEqual(left, right) => {
616 let left_val = self.evaluate_expression(left, context, current_node).await?;
617 let right_val = self.evaluate_expression(right, context, current_node).await?;
618 Ok(Value::Boolean(self.compare_values(&left_val, &right_val) <= 0))
619 },
620 Expression::GreaterThan(left, right) => {
621 let left_val = self.evaluate_expression(left, context, current_node).await?;
622 let right_val = self.evaluate_expression(right, context, current_node).await?;
623 Ok(Value::Boolean(self.compare_values(&left_val, &right_val) > 0))
624 },
625 Expression::GreaterThanOrEqual(left, right) => {
626 let left_val = self.evaluate_expression(left, context, current_node).await?;
627 let right_val = self.evaluate_expression(right, context, current_node).await?;
628 Ok(Value::Boolean(self.compare_values(&left_val, &right_val) >= 0))
629 },
630 _ => Ok(Value::Null), // TODO: Implement remaining expression types
631 }
632 })
633 }
634
635 async fn get_property_value(&self, base_value: Value, property_name: &str) -> Result<Value> {
636 match base_value {
637 Value::Node(node_id) => {
638 if let Some(node) = self.graph.get_node(node_id) {
639 // Get property value from node
640 let schema = self.graph.schema();
641 let schema_guard = schema.read();
642 for (prop_key, _) in &schema_guard.property_keys {
643 if prop_key == property_name {
644 let prop_key_id = schema_guard.property_keys[prop_key];
645 if let Some(prop_value) = node.properties.get(&prop_key_id) {
646 return Ok(self.property_value_to_executor_value(prop_value));
647 }
648 }
649 }
650 }
651 Ok(Value::Null)
652 },
653 Value::Relationship(_rel_id) => {
654 // TODO: Implement relationship property access
655 Ok(Value::Null)
656 },
657 _ => Ok(Value::Null),
658 }
659 }
660
661 fn property_value_to_executor_value(&self, prop_val: &PropertyValue) -> Value {
662 match prop_val {
663 PropertyValue::String(s) => Value::String(s.clone()),
664 PropertyValue::Integer(i) => Value::Integer(*i),
665 PropertyValue::Float(f) => Value::Float(*f),
666 PropertyValue::Boolean(b) => Value::Boolean(*b),
667 PropertyValue::List(list) => {
668 let converted_list: Vec<Value> = list.iter()
669 .map(|item| self.property_value_to_executor_value(item))
670 .collect();
671 Value::List(converted_list)
672 },
673 PropertyValue::Null => Value::Null,
674 PropertyValue::Map(_) => Value::Null, // TODO: Implement map support
675 }
676 }
677
678 fn values_equal(&self, left: &Value, right: &Value) -> bool {
679 match (left, right) {
680 (Value::String(a), Value::String(b)) => a == b,
681 (Value::Integer(a), Value::Integer(b)) => a == b,
682 (Value::Float(a), Value::Float(b)) => (a - b).abs() < f64::EPSILON,
683 (Value::Boolean(a), Value::Boolean(b)) => a == b,
684 (Value::Node(a), Value::Node(b)) => a == b,
685 (Value::Relationship(a), Value::Relationship(b)) => a == b,
686 (Value::Null, Value::Null) => true,
687 // Type coercion for numbers
688 (Value::Integer(a), Value::Float(b)) => (*a as f64 - b).abs() < f64::EPSILON,
689 (Value::Float(a), Value::Integer(b)) => (a - *b as f64).abs() < f64::EPSILON,
690 _ => false,
691 }
692 }
693
694 fn is_truthy(&self, value: &Value) -> bool {
695 match value {
696 Value::Boolean(b) => *b,
697 Value::Null => false,
698 Value::Integer(i) => *i != 0,
699 Value::Float(f) => *f != 0.0,
700 Value::String(s) => !s.is_empty(),
701 Value::List(list) => !list.is_empty(),
702 Value::Node(_) => true,
703 Value::Relationship(_) => true,
704 }
705 }
706
707 fn compare_values(&self, left: &Value, right: &Value) -> i32 {
708 match (left, right) {
709 (Value::Integer(a), Value::Integer(b)) => a.cmp(b) as i32,
710 (Value::Float(a), Value::Float(b)) => a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal) as i32,
711 (Value::Integer(a), Value::Float(b)) => (*a as f64).partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal) as i32,
712 (Value::Float(a), Value::Integer(b)) => a.partial_cmp(&(*b as f64)).unwrap_or(std::cmp::Ordering::Equal) as i32,
713 (Value::String(a), Value::String(b)) => a.cmp(b) as i32,
714 _ => 0, // Incomparable types are considered equal
715 }
716 }
717
718 fn expression_to_string(&self, expr: &Expression) -> String {
719 match expr {
720 Expression::Variable(name) => name.clone(),
721 _ => "expr".to_string(),
722 }
723 }
724
725 pub async fn execute(&self, plan: QueryPlan) -> Result<QueryResult> {
726 match plan {
727 QueryPlan::Scan(scan_plan) => self.execute_scan(scan_plan).await,
728 QueryPlan::Create(create_plan) => self.execute_create(create_plan).await,
729 QueryPlan::Project(project_plan) => self.execute_project(project_plan).await,
730 _ => Err(GigabrainError::Query("Execution not implemented for this plan type".to_string())),
731 }
732 }
733
734 async fn execute_scan(&self, _scan_plan: ScanPlan) -> Result<QueryResult> {
735 Ok(QueryResult::empty())
736 }
737
738 async fn execute_create(&self, _create_plan: CreatePlan) -> Result<QueryResult> {
739 Ok(QueryResult::empty())
740 }
741
742 async fn execute_project(&self, _project_plan: ProjectPlan) -> Result<QueryResult> {
743 Ok(QueryResult::empty())
744 }
745}
746
747#[derive(Debug)]
748pub struct ExecutionContext {
749 variables: HashMap<String, VariableBinding>,
750}
751
752impl ExecutionContext {
753 fn new() -> Self {
754 Self {
755 variables: HashMap::new(),
756 }
757 }
758
759 fn bind_variable(&mut self, name: String, binding: VariableBinding) {
760 self.variables.insert(name, binding);
761 }
762
763 fn merge_result(&mut self, _result: QueryResult) {
764 // Merge results from previous query steps
765 }
766
767 fn into_result(self) -> QueryResult {
768 // If we have variable bindings, create a result from them
769 if let Some((var_name, binding)) = self.variables.iter().next() {
770 match binding {
771 VariableBinding::Nodes(node_ids) => {
772 let columns = vec![var_name.clone()];
773 let mut rows = Vec::new();
774 for node_id in node_ids {
775 rows.push(Row {
776 values: vec![Value::Node(*node_id)]
777 });
778 }
779 QueryResult { rows, columns }
780 },
781 VariableBinding::Relationships(rel_ids) => {
782 let columns = vec![var_name.clone()];
783 let mut rows = Vec::new();
784 for rel_id in rel_ids {
785 rows.push(Row {
786 values: vec![Value::Relationship(*rel_id)]
787 });
788 }
789 QueryResult { rows, columns }
790 },
791 }
792 } else {
793 QueryResult::empty()
794 }
795 }
796}
797
798#[derive(Debug, Clone)]
799enum VariableBinding {
800 Nodes(Vec<NodeId>),
801 Relationships(Vec<RelationshipId>),
802}
803
804#[derive(Debug)]
805pub struct QueryResult {
806 pub rows: Vec<Row>,
807 pub columns: Vec<String>,
808}
809
810impl QueryResult {
811 fn empty() -> Self {
812 Self {
813 rows: Vec::new(),
814 columns: Vec::new(),
815 }
816 }
817}
818
819#[derive(Debug)]
820pub struct Row {
821 pub values: Vec<Value>,
822}
823
824#[derive(Debug)]
825pub enum Value {
826 Null,
827 Node(crate::NodeId),
828 Relationship(crate::RelationshipId),
829 Integer(i64),
830 Float(f64),
831 String(String),
832 Boolean(bool),
833 List(Vec<Value>),
834}