Skip to content

Commit f47a892

Browse files
committed
chore: test driven development
1 parent 69b2cb3 commit f47a892

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

rust/cubesql/cubesql/src/compile/engine/df/optimizers/plan_normalize.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,3 +1393,64 @@ fn evaluate_expr(optimizer: &PlanNormalize, expr: Expr) -> Result<Expr> {
13931393
let mut const_evaluator = ConstEvaluator::new(execution_props);
13941394
expr.rewrite(&mut const_evaluator)
13951395
}
1396+
1397+
#[cfg(test)]
1398+
mod tests {
1399+
use super::*;
1400+
use crate::compile::test::{
1401+
get_test_tenant_ctx, rewrite_engine::create_test_postgresql_cube_context,
1402+
};
1403+
use datafusion::{
1404+
arrow::datatypes::{DataType, Field, Schema},
1405+
logical_plan::{col, lit, LogicalPlanBuilder},
1406+
};
1407+
1408+
/// Helper function to create a deeply nested OR expression.
1409+
/// This creates a chain like: col = 1 OR col = 2 OR col = 3 OR ... OR col = depth
1410+
fn create_deeply_nested_or_expr(column_name: &str, depth: usize) -> Expr {
1411+
if depth == 0 {
1412+
return col(column_name).eq(lit(0i32));
1413+
}
1414+
1415+
let mut expr = col(column_name).eq(lit(0i32));
1416+
1417+
for i in 1..depth {
1418+
expr = expr.or(col(column_name).eq(lit(i as i32)));
1419+
}
1420+
1421+
expr
1422+
}
1423+
1424+
#[tokio::test]
1425+
async fn test_stack_overflow_deeply_nested_or() -> Result<()> {
1426+
let meta = get_test_tenant_ctx();
1427+
let cube_ctx = create_test_postgresql_cube_context(meta)
1428+
.await
1429+
.expect("Failed to create cube context");
1430+
1431+
// Create a simple table
1432+
let schema = Schema::new(vec![
1433+
Field::new("id", DataType::Int32, false),
1434+
Field::new("value", DataType::Int32, true),
1435+
]);
1436+
1437+
let table_scan = LogicalPlanBuilder::scan_empty(Some("test_table"), &schema, None)
1438+
.expect("Failed to create table scan")
1439+
.build()
1440+
.expect("Failed to build plan");
1441+
1442+
// Create a deeply nested OR expression (should cause stack overflow)
1443+
let deeply_nested_filter = create_deeply_nested_or_expr("value", 1_000);
1444+
1445+
let plan = LogicalPlanBuilder::from(table_scan)
1446+
.filter(deeply_nested_filter)
1447+
.expect("Failed to add filter")
1448+
.build()
1449+
.expect("Failed to build plan");
1450+
1451+
let optimizer = PlanNormalize::new(&cube_ctx);
1452+
optimizer.optimize(&plan, &OptimizerConfig::new())?;
1453+
1454+
Ok(())
1455+
}
1456+
}

0 commit comments

Comments
 (0)