use vibesql_executor::SelectExecutor;
use vibesql_storage::Database;
fn parse_select(sql: &str) -> vibesql_ast::SelectStmt {
match vibesql_parser::Parser::parse_sql(sql) {
Ok(vibesql_ast::Statement::Select(select_stmt)) => *select_stmt,
_ => panic!("Failed to parse SELECT statement: {}", sql),
}
}
fn setup_large_test_db(num_rows: usize) -> Database {
let mut db = Database::new();
let schema = vibesql_catalog::TableSchema::new(
"TEST_PARALLEL".to_string(),
vec![
vibesql_catalog::ColumnSchema::new(
"id".to_string(),
vibesql_types::DataType::Integer,
false,
),
vibesql_catalog::ColumnSchema::new(
"value".to_string(),
vibesql_types::DataType::Integer,
false,
),
],
);
db.create_table(schema).unwrap();
for i in 0..num_rows {
let row = vibesql_storage::Row::new(vec![
vibesql_types::SqlValue::Integer(i as i64),
vibesql_types::SqlValue::Integer((i % 100) as i64),
]);
db.insert_row("TEST_PARALLEL", row).unwrap();
}
db
}
#[test]
fn test_parallel_filter_produces_correct_results() {
let db = setup_large_test_db(15_000);
let executor = SelectExecutor::new(&db);
let stmt = parse_select("SELECT id FROM TEST_PARALLEL WHERE value < 10");
let result = executor.execute(&stmt).unwrap();
assert_eq!(result.len(), 1500);
let stmt2 = parse_select("SELECT id FROM TEST_PARALLEL WHERE value >= 20 AND value < 30");
let result2 = executor.execute(&stmt2).unwrap();
assert_eq!(result2.len(), 1500);
std::env::set_var("PARALLEL_THRESHOLD", "max");
let result3 = executor.execute(&stmt).unwrap();
std::env::remove_var("PARALLEL_THRESHOLD");
assert_eq!(result3.len(), 1500);
}
#[test]
fn test_parallel_filter_below_threshold_uses_sequential() {
let db = setup_large_test_db(1_000);
let executor = SelectExecutor::new(&db);
let stmt = parse_select("SELECT id FROM TEST_PARALLEL WHERE value < 10");
let result = executor.execute(&stmt).unwrap();
assert_eq!(result.len(), 100);
}
#[test]
fn test_parallel_filter_with_null_values() {
let mut db = Database::new();
let schema = vibesql_catalog::TableSchema::new(
"TEST_NULLS".to_string(),
vec![
vibesql_catalog::ColumnSchema::new(
"id".to_string(),
vibesql_types::DataType::Integer,
false,
),
vibesql_catalog::ColumnSchema::new(
"value".to_string(),
vibesql_types::DataType::Integer,
true,
),
],
);
db.create_table(schema).unwrap();
for i in 0..12_000 {
let value = if i % 10 == 0 {
vibesql_types::SqlValue::Null
} else {
vibesql_types::SqlValue::Integer((i % 100) as i64)
};
let row =
vibesql_storage::Row::new(vec![vibesql_types::SqlValue::Integer(i as i64), value]);
db.insert_row("TEST_NULLS", row).unwrap();
}
let executor = SelectExecutor::new(&db);
let stmt = parse_select("SELECT id FROM TEST_NULLS WHERE value IS NOT NULL AND value < 10");
let result_auto = executor.execute(&stmt).unwrap();
std::env::set_var("PARALLEL_THRESHOLD", "max");
let result_seq = executor.execute(&stmt).unwrap();
std::env::remove_var("PARALLEL_THRESHOLD");
assert_eq!(result_auto.len(), result_seq.len());
}
#[test]
fn test_parallel_automatic_on_modern_hardware() {
let db = setup_large_test_db(11_000); let executor = SelectExecutor::new(&db);
let stmt = parse_select("SELECT id FROM TEST_PARALLEL WHERE id < 100");
let result = executor.execute(&stmt).unwrap();
assert_eq!(result.len(), 100);
std::env::set_var("PARALLEL_THRESHOLD", "max");
let result_seq = executor.execute(&stmt).unwrap();
std::env::remove_var("PARALLEL_THRESHOLD");
assert_eq!(result_seq.len(), 100);
}
#[test]
fn test_parallel_execution_integration_with_executor() {
let db = setup_large_test_db(15_000); let executor = SelectExecutor::new(&db);
let stmt = parse_select("SELECT id FROM TEST_PARALLEL WHERE value < 10");
let result_auto = executor.execute(&stmt).unwrap();
assert_eq!(result_auto.len(), 1500);
std::env::set_var("PARALLEL_THRESHOLD", "max");
let result_seq = executor.execute(&stmt).unwrap();
std::env::remove_var("PARALLEL_THRESHOLD");
assert_eq!(result_seq.len(), 1500);
let stmt_agg = parse_select("SELECT COUNT(*) FROM TEST_PARALLEL WHERE value < 10");
let result_agg = executor.execute(&stmt_agg).unwrap();
assert_eq!(result_agg.len(), 1);
assert_eq!(result_agg[0].values[0], vibesql_types::SqlValue::Integer(1500));
std::env::set_var("PARALLEL_THRESHOLD", "1000");
let result_custom = executor.execute(&stmt).unwrap();
std::env::remove_var("PARALLEL_THRESHOLD");
assert_eq!(result_custom.len(), 1500);
}