From 34b11e7268b445e9ddc94859b98af0a62fec68b6 Mon Sep 17 00:00:00 2001 From: leiyuou Date: Mon, 15 Dec 2025 00:39:25 -0800 Subject: [PATCH 1/6] fixup --- rust/lance-graph/Cargo.toml | 1 + .../src/datafusion_planner/expression.rs | 88 +++++ .../tests/test_datafusion_pipeline.rs | 308 +++++++++++++++++- 3 files changed, 396 insertions(+), 1 deletion(-) diff --git a/rust/lance-graph/Cargo.toml b/rust/lance-graph/Cargo.toml index 59f28250..d4620c87 100644 --- a/rust/lance-graph/Cargo.toml +++ b/rust/lance-graph/Cargo.toml @@ -32,6 +32,7 @@ nom = "7.1" serde = { version = "1", features = ["derive"] } serde_json = "1" snafu = "0.8" +tokio = "1.46.0" [dev-dependencies] criterion = { version = "0.5", features = ["async", "async_tokio", "html_reports"] } diff --git a/rust/lance-graph/src/datafusion_planner/expression.rs b/rust/lance-graph/src/datafusion_planner/expression.rs index 0468720e..cfe4745b 100644 --- a/rust/lance-graph/src/datafusion_planner/expression.rs +++ b/rust/lance-graph/src/datafusion_planner/expression.rs @@ -9,6 +9,8 @@ use crate::ast::{BooleanExpression, PropertyValue, ValueExpression}; use datafusion::logical_expr::{col, lit, BinaryExpr, Expr, Operator}; use datafusion_functions_aggregate::average::avg; use datafusion_functions_aggregate::count::count; +use datafusion_functions_aggregate::min_max::max; +use datafusion_functions_aggregate::min_max::min; use datafusion_functions_aggregate::sum::sum; /// Convert BooleanExpression to DataFusion Expr @@ -131,6 +133,22 @@ pub(crate) fn to_df_value_expr(expr: &ValueExpression) -> Expr { lit(0) } } + "min" => { + if args.len() == 1 { + let arg_expr = to_df_value_expr(&args[0]); + min(arg_expr) + } else { + lit(0) + } + } + "max" => { + if args.len() == 1 { + let arg_expr = to_df_value_expr(&args[0]); + max(arg_expr) + } else { + lit(0) + } + } _ => { // Unsupported function - return placeholder for now lit(0) @@ -555,6 +573,44 @@ mod tests { assert!(s.contains("p__amount"), "Should contain column reference"); } + #[test] + fn test_value_expr_function_min() { + let expr = ValueExpression::Function { + name: "MIN".into(), + args: vec![ValueExpression::Property(PropertyRef { + variable: "p".into(), + property: "amount".into(), + })], + }; + + let df_expr = to_df_value_expr(&expr); + let s = format!("{:?}", df_expr); + assert!( + s.contains("min") || s.contains("Min"), + "Should be MIN function" + ); + assert!(s.contains("p__amount"), "Should contain column reference"); + } + + #[test] + fn test_value_expr_function_max() { + let expr = ValueExpression::Function { + name: "MAX".into(), + args: vec![ValueExpression::Property(PropertyRef { + variable: "p".into(), + property: "amount".into(), + })], + }; + + let df_expr = to_df_value_expr(&expr); + let s = format!("{:?}", df_expr); + assert!( + s.contains("max") || s.contains("Max"), + "Should be MAX function" + ); + assert!(s.contains("p__amount"), "Should contain column reference"); + } + // ======================================================================== // Unit tests for contains_aggregate() // ======================================================================== @@ -588,6 +644,38 @@ mod tests { ); } + #[test] + fn test_contains_aggregate_min() { + let expr = ValueExpression::Function { + name: "MIN".into(), + args: vec![ValueExpression::Property(PropertyRef { + variable: "p".into(), + property: "value".into(), + })], + }; + + assert!( + contains_aggregate(&expr), + "MIN should be detected as aggregate" + ); + } + + #[test] + fn test_contains_aggregate_max() { + let expr = ValueExpression::Function { + name: "MAX".into(), + args: vec![ValueExpression::Property(PropertyRef { + variable: "p".into(), + property: "value".into(), + })], + }; + + assert!( + contains_aggregate(&expr), + "MAX should be detected as aggregate" + ); + } + #[test] fn test_contains_aggregate_property() { let expr = ValueExpression::Property(PropertyRef { diff --git a/rust/lance-graph/tests/test_datafusion_pipeline.rs b/rust/lance-graph/tests/test_datafusion_pipeline.rs index 1f6669f8..7c2e90cf 100644 --- a/rust/lance-graph/tests/test_datafusion_pipeline.rs +++ b/rust/lance-graph/tests/test_datafusion_pipeline.rs @@ -1,10 +1,10 @@ +use arrow::compute::kernels::numeric::add; use arrow_array::{Array, Float64Array, Int64Array, RecordBatch, StringArray}; use arrow_schema::{DataType, Field, Schema}; use lance_graph::config::GraphConfig; use lance_graph::{CypherQuery, ExecutionStrategy}; use std::collections::HashMap; use std::sync::Arc; - // ============================================================================ // Test Data Structure // ============================================================================ @@ -81,6 +81,72 @@ fn create_person_dataset() -> RecordBatch { .unwrap() } +fn add_new_person_to_dataset( + current_dataset: &RecordBatch, + id: i64, + name: &str, + age: i64, + city: Option<&str>, +) -> RecordBatch { + let schema = current_dataset.schema(); + + let ids_arr = current_dataset + .column_by_name("id") + .unwrap() + .as_any() + .downcast_ref::() + .unwrap(); + let names_arr = current_dataset + .column_by_name("name") + .unwrap() + .as_any() + .downcast_ref::() + .unwrap(); + let ages_arr = current_dataset + .column_by_name("age") + .unwrap() + .as_any() + .downcast_ref::() + .unwrap(); + let cities_arr = current_dataset + .column_by_name("city") + .unwrap() + .as_any() + .downcast_ref::() + .unwrap(); + + let mut ids: Vec = (0..ids_arr.len()).map(|i| ids_arr.value(i)).collect(); + let mut names: Vec = (0..names_arr.len()) + .map(|i| names_arr.value(i).to_string()) + .collect(); + let mut ages: Vec = (0..ages_arr.len()).map(|i| ages_arr.value(i)).collect(); + let mut cities: Vec> = (0..cities_arr.len()) + .map(|i| { + if cities_arr.is_null(i) { + None + } else { + Some(cities_arr.value(i).to_string()) + } + }) + .collect(); + + ids.push(id); + names.push(name.to_string()); + ages.push(age); + cities.push(city.map(|c| c.to_string())); + + RecordBatch::try_new( + schema, + vec![ + Arc::new(Int64Array::from(ids)), + Arc::new(StringArray::from(names)), + Arc::new(Int64Array::from(ages)), + Arc::new(StringArray::from(cities)), + ], + ) + .unwrap() +} + /// Helper function to create a KNOWS relationship dataset fn create_knows_dataset() -> RecordBatch { let schema = Arc::new(Schema::new(vec![ @@ -3123,6 +3189,246 @@ async fn test_avg_without_alias_has_descriptive_name() { ); } +#[tokio::test] +async fn test_min_property() { + let person_batch = create_person_dataset(); + let config = GraphConfig::builder() + .with_node_label("Person", "id") + .build() + .unwrap(); + + let query = CypherQuery::new("MATCH (p:Person) RETURN min(p.age) AS min_age") + .unwrap() + .with_config(config); + + let mut datasets = HashMap::new(); + datasets.insert("Person".to_string(), person_batch); + + let result = query + .execute(datasets, Some(ExecutionStrategy::DataFusion)) + .await + .unwrap(); + + assert_eq!(result.num_rows(), 1); + + let min_col = result + .column_by_name("min_age") + .unwrap() + .as_any() + .downcast_ref::() + .unwrap(); + + // Ages: 25, 35, 30, 40, 28 => min = 25 + assert_eq!(min_col.value(0), 25); +} + +#[tokio::test] +async fn test_min_without_alias_has_descriptive_name() { + let person_batch = create_person_dataset(); + let config = GraphConfig::builder() + .with_node_label("Person", "id") + .build() + .unwrap(); + + let query = CypherQuery::new("MATCH (p:Person) RETURN min(p.age)") + .unwrap() + .with_config(config); + + let mut datasets = HashMap::new(); + datasets.insert("Person".to_string(), person_batch); + + let result = query + .execute(datasets, Some(ExecutionStrategy::DataFusion)) + .await + .unwrap(); + + assert_eq!(result.num_rows(), 1); + + // Column should be named "min(p.age)" + let col = result.column_by_name("min(p.age)"); + assert!( + col.is_some(), + "Expected column named 'min(p.age)' but schema is: {:?}", + result.schema() + ); +} + +#[tokio::test] +async fn test_min_with_grouping() { + let mut person_batch = create_person_dataset(); + person_batch = add_new_person_to_dataset(&person_batch, 6, "Cindy", 10, Some("New York")); + let config = GraphConfig::builder() + .with_node_label("Person", "id") + .build() + .unwrap(); + + // One person per city in this dataset (including NULL), so min(age) == that person's age + let query = + CypherQuery::new("MATCH (p:Person) RETURN p.city, min(p.age) AS min_age ORDER BY p.city") + .unwrap() + .with_config(config); + + let mut datasets = HashMap::new(); + datasets.insert("Person".to_string(), person_batch); + + let result = query + .execute(datasets, Some(ExecutionStrategy::DataFusion)) + .await + .unwrap(); + + assert_eq!(result.num_rows(), 5); + + let city_col = result + .column_by_name("p.city") + .unwrap() + .as_any() + .downcast_ref::() + .unwrap(); + + let min_col = result + .column_by_name("min_age") + .unwrap() + .as_any() + .downcast_ref::() + .unwrap(); + + // ORDER BY p.city, NULL comes first per your other tests + assert!(city_col.is_null(0)); // David city NULL + assert_eq!(min_col.value(0), 40); + + assert_eq!(city_col.value(1), "Chicago"); // Charlie + assert_eq!(min_col.value(1), 30); + + assert_eq!(city_col.value(2), "New York"); // Alice + assert_eq!(min_col.value(2), 10); + + assert_eq!(city_col.value(3), "San Francisco"); // Bob + assert_eq!(min_col.value(3), 35); + + assert_eq!(city_col.value(4), "Seattle"); // Eve + assert_eq!(min_col.value(4), 28); +} + +#[tokio::test] +async fn test_max_property() { + let person_batch = create_person_dataset(); + let config = GraphConfig::builder() + .with_node_label("Person", "id") + .build() + .unwrap(); + + let query = CypherQuery::new("MATCH (p:Person) RETURN max(p.age) AS max_age") + .unwrap() + .with_config(config); + + let mut datasets = HashMap::new(); + datasets.insert("Person".to_string(), person_batch); + + let result = query + .execute(datasets, Some(ExecutionStrategy::DataFusion)) + .await + .unwrap(); + + assert_eq!(result.num_rows(), 1); + + let max_col = result + .column_by_name("max_age") + .unwrap() + .as_any() + .downcast_ref::() + .unwrap(); + + // Ages: 25, 35, 30, 40, 28 => max = 40 + assert_eq!(max_col.value(0), 40); +} + +#[tokio::test] +async fn test_max_without_alias_has_descriptive_name() { + let person_batch = create_person_dataset(); + let config = GraphConfig::builder() + .with_node_label("Person", "id") + .build() + .unwrap(); + + let query = CypherQuery::new("MATCH (p:Person) RETURN max(p.age)") + .unwrap() + .with_config(config); + + let mut datasets = HashMap::new(); + datasets.insert("Person".to_string(), person_batch); + + let result = query + .execute(datasets, Some(ExecutionStrategy::DataFusion)) + .await + .unwrap(); + + assert_eq!(result.num_rows(), 1); + + // Column should be named "max(p.age)" + let col = result.column_by_name("max(p.age)"); + assert!( + col.is_some(), + "Expected column named 'max(p.age)' but schema is: {:?}", + result.schema() + ); +} + +#[tokio::test] +async fn test_max_with_grouping() { + let mut person_batch = create_person_dataset(); + person_batch = add_new_person_to_dataset(&person_batch, 6, "Cindy", 90, Some("New York")); + let config = GraphConfig::builder() + .with_node_label("Person", "id") + .build() + .unwrap(); + + // One person per city in this dataset (including NULL), so min(age) == that person's age + let query = + CypherQuery::new("MATCH (p:Person) RETURN p.city, max(p.age) AS max_age ORDER BY p.city") + .unwrap() + .with_config(config); + + let mut datasets = HashMap::new(); + datasets.insert("Person".to_string(), person_batch); + + let result = query + .execute(datasets, Some(ExecutionStrategy::DataFusion)) + .await + .unwrap(); + + assert_eq!(result.num_rows(), 5); + + let city_col = result + .column_by_name("p.city") + .unwrap() + .as_any() + .downcast_ref::() + .unwrap(); + + let max_col = result + .column_by_name("max_age") + .unwrap() + .as_any() + .downcast_ref::() + .unwrap(); + + // ORDER BY p.city, NULL comes first per your other tests + assert!(city_col.is_null(0)); // David city NULL + assert_eq!(max_col.value(0), 40); + + assert_eq!(city_col.value(1), "Chicago"); // Charlie + assert_eq!(max_col.value(1), 30); + + assert_eq!(city_col.value(2), "New York"); // Alice + assert_eq!(max_col.value(2), 90); + + assert_eq!(city_col.value(3), "San Francisco"); // Bob + assert_eq!(max_col.value(3), 35); + + assert_eq!(city_col.value(4), "Seattle"); // Eve + assert_eq!(max_col.value(4), 28); +} + // ============================================================================ // Disconnected Pattern (Join) Tests // ============================================================================ From fe478dfd53e415179135b6f5c858c53ba6e77f4c Mon Sep 17 00:00:00 2001 From: leiyuou Date: Mon, 15 Dec 2025 00:41:58 -0800 Subject: [PATCH 2/6] fixup --- rust/lance-graph/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/rust/lance-graph/Cargo.toml b/rust/lance-graph/Cargo.toml index d4620c87..59f28250 100644 --- a/rust/lance-graph/Cargo.toml +++ b/rust/lance-graph/Cargo.toml @@ -32,7 +32,6 @@ nom = "7.1" serde = { version = "1", features = ["derive"] } serde_json = "1" snafu = "0.8" -tokio = "1.46.0" [dev-dependencies] criterion = { version = "0.5", features = ["async", "async_tokio", "html_reports"] } From 330f289edec68710ddc7178ce1363a87c6ea8a44 Mon Sep 17 00:00:00 2001 From: leiyuou Date: Mon, 15 Dec 2025 21:07:03 -0800 Subject: [PATCH 3/6] address comment --- .../tests/test_datafusion_pipeline.rs | 247 ++++-------------- 1 file changed, 49 insertions(+), 198 deletions(-) diff --git a/rust/lance-graph/tests/test_datafusion_pipeline.rs b/rust/lance-graph/tests/test_datafusion_pipeline.rs index 7c2e90cf..d0d1d0ba 100644 --- a/rust/lance-graph/tests/test_datafusion_pipeline.rs +++ b/rust/lance-graph/tests/test_datafusion_pipeline.rs @@ -1,10 +1,10 @@ -use arrow::compute::kernels::numeric::add; use arrow_array::{Array, Float64Array, Int64Array, RecordBatch, StringArray}; use arrow_schema::{DataType, Field, Schema}; use lance_graph::config::GraphConfig; use lance_graph::{CypherQuery, ExecutionStrategy}; use std::collections::HashMap; use std::sync::Arc; + // ============================================================================ // Test Data Structure // ============================================================================ @@ -81,72 +81,6 @@ fn create_person_dataset() -> RecordBatch { .unwrap() } -fn add_new_person_to_dataset( - current_dataset: &RecordBatch, - id: i64, - name: &str, - age: i64, - city: Option<&str>, -) -> RecordBatch { - let schema = current_dataset.schema(); - - let ids_arr = current_dataset - .column_by_name("id") - .unwrap() - .as_any() - .downcast_ref::() - .unwrap(); - let names_arr = current_dataset - .column_by_name("name") - .unwrap() - .as_any() - .downcast_ref::() - .unwrap(); - let ages_arr = current_dataset - .column_by_name("age") - .unwrap() - .as_any() - .downcast_ref::() - .unwrap(); - let cities_arr = current_dataset - .column_by_name("city") - .unwrap() - .as_any() - .downcast_ref::() - .unwrap(); - - let mut ids: Vec = (0..ids_arr.len()).map(|i| ids_arr.value(i)).collect(); - let mut names: Vec = (0..names_arr.len()) - .map(|i| names_arr.value(i).to_string()) - .collect(); - let mut ages: Vec = (0..ages_arr.len()).map(|i| ages_arr.value(i)).collect(); - let mut cities: Vec> = (0..cities_arr.len()) - .map(|i| { - if cities_arr.is_null(i) { - None - } else { - Some(cities_arr.value(i).to_string()) - } - }) - .collect(); - - ids.push(id); - names.push(name.to_string()); - ages.push(age); - cities.push(city.map(|c| c.to_string())); - - RecordBatch::try_new( - schema, - vec![ - Arc::new(Int64Array::from(ids)), - Arc::new(StringArray::from(names)), - Arc::new(Int64Array::from(ages)), - Arc::new(StringArray::from(cities)), - ], - ) - .unwrap() -} - /// Helper function to create a KNOWS relationship dataset fn create_knows_dataset() -> RecordBatch { let schema = Arc::new(Schema::new(vec![ @@ -3222,93 +3156,6 @@ async fn test_min_property() { assert_eq!(min_col.value(0), 25); } -#[tokio::test] -async fn test_min_without_alias_has_descriptive_name() { - let person_batch = create_person_dataset(); - let config = GraphConfig::builder() - .with_node_label("Person", "id") - .build() - .unwrap(); - - let query = CypherQuery::new("MATCH (p:Person) RETURN min(p.age)") - .unwrap() - .with_config(config); - - let mut datasets = HashMap::new(); - datasets.insert("Person".to_string(), person_batch); - - let result = query - .execute(datasets, Some(ExecutionStrategy::DataFusion)) - .await - .unwrap(); - - assert_eq!(result.num_rows(), 1); - - // Column should be named "min(p.age)" - let col = result.column_by_name("min(p.age)"); - assert!( - col.is_some(), - "Expected column named 'min(p.age)' but schema is: {:?}", - result.schema() - ); -} - -#[tokio::test] -async fn test_min_with_grouping() { - let mut person_batch = create_person_dataset(); - person_batch = add_new_person_to_dataset(&person_batch, 6, "Cindy", 10, Some("New York")); - let config = GraphConfig::builder() - .with_node_label("Person", "id") - .build() - .unwrap(); - - // One person per city in this dataset (including NULL), so min(age) == that person's age - let query = - CypherQuery::new("MATCH (p:Person) RETURN p.city, min(p.age) AS min_age ORDER BY p.city") - .unwrap() - .with_config(config); - - let mut datasets = HashMap::new(); - datasets.insert("Person".to_string(), person_batch); - - let result = query - .execute(datasets, Some(ExecutionStrategy::DataFusion)) - .await - .unwrap(); - - assert_eq!(result.num_rows(), 5); - - let city_col = result - .column_by_name("p.city") - .unwrap() - .as_any() - .downcast_ref::() - .unwrap(); - - let min_col = result - .column_by_name("min_age") - .unwrap() - .as_any() - .downcast_ref::() - .unwrap(); - - // ORDER BY p.city, NULL comes first per your other tests - assert!(city_col.is_null(0)); // David city NULL - assert_eq!(min_col.value(0), 40); - - assert_eq!(city_col.value(1), "Chicago"); // Charlie - assert_eq!(min_col.value(1), 30); - - assert_eq!(city_col.value(2), "New York"); // Alice - assert_eq!(min_col.value(2), 10); - - assert_eq!(city_col.value(3), "San Francisco"); // Bob - assert_eq!(min_col.value(3), 35); - - assert_eq!(city_col.value(4), "Seattle"); // Eve - assert_eq!(min_col.value(4), 28); -} - #[tokio::test] async fn test_max_property() { let person_batch = create_person_dataset(); @@ -3343,69 +3190,62 @@ async fn test_max_property() { } #[tokio::test] -async fn test_max_without_alias_has_descriptive_name() { +async fn test_min_max_with_grouping() { let person_batch = create_person_dataset(); let config = GraphConfig::builder() .with_node_label("Person", "id") .build() .unwrap(); - let query = CypherQuery::new("MATCH (p:Person) RETURN max(p.age)") - .unwrap() - .with_config(config); + // One person per city in this dataset (including NULL), so min(age) == that person's age + let query_min = + CypherQuery::new("MATCH (p:Person) RETURN p.city, min(p.age) AS min_age ORDER BY p.city") + .unwrap() + .with_config(config); + + let query_max = + CypherQuery::new("MATCH (p:Person) RETURN p.city, max(p.age) AS max_age ORDER BY p.city") + .unwrap() + .with_config(config); let mut datasets = HashMap::new(); datasets.insert("Person".to_string(), person_batch); - let result = query + let result_min = query_min .execute(datasets, Some(ExecutionStrategy::DataFusion)) .await .unwrap(); - assert_eq!(result.num_rows(), 1); - - // Column should be named "max(p.age)" - let col = result.column_by_name("max(p.age)"); - assert!( - col.is_some(), - "Expected column named 'max(p.age)' but schema is: {:?}", - result.schema() - ); -} - -#[tokio::test] -async fn test_max_with_grouping() { - let mut person_batch = create_person_dataset(); - person_batch = add_new_person_to_dataset(&person_batch, 6, "Cindy", 90, Some("New York")); - let config = GraphConfig::builder() - .with_node_label("Person", "id") - .build() + let result_max = query_max + .execute(datasets, Some(ExecutionStrategy::DataFusion)) + .await .unwrap(); - // One person per city in this dataset (including NULL), so min(age) == that person's age - let query = - CypherQuery::new("MATCH (p:Person) RETURN p.city, max(p.age) AS max_age ORDER BY p.city") - .unwrap() - .with_config(config); - - let mut datasets = HashMap::new(); - datasets.insert("Person".to_string(), person_batch); + assert_eq!(result_min.num_rows(), 5); + assert_eq!(result_max.num_rows(), 5); - let result = query - .execute(datasets, Some(ExecutionStrategy::DataFusion)) - .await + let city_col_min = result_min + .column_by_name("p.city") + .unwrap() + .as_any() + .downcast_ref::() .unwrap(); - assert_eq!(result.num_rows(), 5); + let min_col_min = result_min + .column_by_name("min_age") + .unwrap() + .as_any() + .downcast_ref::() + .unwrap(); - let city_col = result + let city_col_max = result_max .column_by_name("p.city") .unwrap() .as_any() .downcast_ref::() .unwrap(); - let max_col = result + let min_col_max = result_max .column_by_name("max_age") .unwrap() .as_any() @@ -3413,20 +3253,31 @@ async fn test_max_with_grouping() { .unwrap(); // ORDER BY p.city, NULL comes first per your other tests - assert!(city_col.is_null(0)); // David city NULL - assert_eq!(max_col.value(0), 40); + assert!(city_col_min.is_null(0)); // David city NULL + assert!(city_col_max.is_null(0)); + assert_eq!(min_col_min.value(0), 40); + assert_eq!(min_col_max.value(0), 40); - assert_eq!(city_col.value(1), "Chicago"); // Charlie - assert_eq!(max_col.value(1), 30); + assert_eq!(city_col_min.value(1), "Chicago"); // Charlie + assert_eq!(city_col_max.value(1), "Chicago"); + assert_eq!(min_col_min.value(1), 30); + assert_eq!(min_col_max.value(1), 30); assert_eq!(city_col.value(2), "New York"); // Alice - assert_eq!(max_col.value(2), 90); + assert_eq!(city_col.value(2), "New York"); + assert_eq!(min_col.value(2), 25); + assert_eq!(min_col.value(2), 25); assert_eq!(city_col.value(3), "San Francisco"); // Bob - assert_eq!(max_col.value(3), 35); + assert_eq!(city_col.value(3), "San Francisco"); + assert_eq!(min_col.value(3), 35); + assert_eq!(min_col.value(3), 35); + assert_eq!(city_col.value(4), "Seattle"); // Eve - assert_eq!(max_col.value(4), 28); + assert_eq!(city_col.value(4), "Seattle"); + assert_eq!(min_col.value(4), 28); + assert_eq!(min_col.value(4), 28); } // ============================================================================ From c0ce4273b9a31ed9392c57c956c28db16bea7d03 Mon Sep 17 00:00:00 2001 From: leiyuou Date: Mon, 15 Dec 2025 21:12:16 -0800 Subject: [PATCH 4/6] fixup --- .../tests/test_datafusion_pipeline.rs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/rust/lance-graph/tests/test_datafusion_pipeline.rs b/rust/lance-graph/tests/test_datafusion_pipeline.rs index d0d1d0ba..6adae700 100644 --- a/rust/lance-graph/tests/test_datafusion_pipeline.rs +++ b/rust/lance-graph/tests/test_datafusion_pipeline.rs @@ -3263,21 +3263,21 @@ async fn test_min_max_with_grouping() { assert_eq!(min_col_min.value(1), 30); assert_eq!(min_col_max.value(1), 30); - assert_eq!(city_col.value(2), "New York"); // Alice - assert_eq!(city_col.value(2), "New York"); - assert_eq!(min_col.value(2), 25); - assert_eq!(min_col.value(2), 25); + assert_eq!(city_col_min.value(2), "New York"); // Alice + assert_eq!(city_col_max.value(2), "New York"); + assert_eq!(min_col_min.value(2), 25); + assert_eq!(min_col_max.value(2), 25); - assert_eq!(city_col.value(3), "San Francisco"); // Bob - assert_eq!(city_col.value(3), "San Francisco"); - assert_eq!(min_col.value(3), 35); - assert_eq!(min_col.value(3), 35); + assert_eq!(city_col_min.value(3), "San Francisco"); // Bob + assert_eq!(city_col_max.value(3), "San Francisco"); + assert_eq!(min_col_min.value(3), 35); + assert_eq!(min_col_max.value(3), 35); - assert_eq!(city_col.value(4), "Seattle"); // Eve - assert_eq!(city_col.value(4), "Seattle"); - assert_eq!(min_col.value(4), 28); - assert_eq!(min_col.value(4), 28); + assert_eq!(city_col_min.value(4), "Seattle"); // Eve + assert_eq!(city_col_max.value(4), "Seattle"); + assert_eq!(min_col_min.value(4), 28); + assert_eq!(min_col_max.value(4), 28); } // ============================================================================ From e69365cd2dcfa37ed0fac15f6f5c5432998c4d50 Mon Sep 17 00:00:00 2001 From: leiyuou Date: Mon, 15 Dec 2025 21:49:55 -0800 Subject: [PATCH 5/6] fixup --- rust/lance-graph/tests/test_datafusion_pipeline.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/lance-graph/tests/test_datafusion_pipeline.rs b/rust/lance-graph/tests/test_datafusion_pipeline.rs index 6adae700..95f6c9d5 100644 --- a/rust/lance-graph/tests/test_datafusion_pipeline.rs +++ b/rust/lance-graph/tests/test_datafusion_pipeline.rs @@ -3201,7 +3201,7 @@ async fn test_min_max_with_grouping() { let query_min = CypherQuery::new("MATCH (p:Person) RETURN p.city, min(p.age) AS min_age ORDER BY p.city") .unwrap() - .with_config(config); + .with_config(config.clone()); let query_max = CypherQuery::new("MATCH (p:Person) RETURN p.city, max(p.age) AS max_age ORDER BY p.city") @@ -3212,7 +3212,7 @@ async fn test_min_max_with_grouping() { datasets.insert("Person".to_string(), person_batch); let result_min = query_min - .execute(datasets, Some(ExecutionStrategy::DataFusion)) + .execute(datasets.clone(), Some(ExecutionStrategy::DataFusion)) .await .unwrap(); From 9448a834d8eaacea11cbe953edaf00525508791b Mon Sep 17 00:00:00 2001 From: leiyuou Date: Mon, 15 Dec 2025 22:14:07 -0800 Subject: [PATCH 6/6] fixup --- rust/lance-graph/tests/test_datafusion_pipeline.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rust/lance-graph/tests/test_datafusion_pipeline.rs b/rust/lance-graph/tests/test_datafusion_pipeline.rs index 95f6c9d5..1d244ea8 100644 --- a/rust/lance-graph/tests/test_datafusion_pipeline.rs +++ b/rust/lance-graph/tests/test_datafusion_pipeline.rs @@ -3273,7 +3273,6 @@ async fn test_min_max_with_grouping() { assert_eq!(min_col_min.value(3), 35); assert_eq!(min_col_max.value(3), 35); - assert_eq!(city_col_min.value(4), "Seattle"); // Eve assert_eq!(city_col_max.value(4), "Seattle"); assert_eq!(min_col_min.value(4), 28);