use vibesql_parser::Parser;
use vibesql_storage::Database;
use crate::{CreateTableExecutor, InsertExecutor, SelectExecutor};
fn exec_sql(db: &mut Database, sql: &str) {
let stmt = Parser::parse_sql(sql).unwrap();
match stmt {
vibesql_ast::Statement::CreateTable(s) => {
CreateTableExecutor::execute(&s, db).unwrap();
}
vibesql_ast::Statement::Insert(s) => {
InsertExecutor::execute(db, &s).unwrap();
}
_ => panic!("Unexpected statement type in test"),
}
}
#[test]
fn test_where_equijoin_applied_during_join() {
let mut db = Database::new();
exec_sql(&mut db, "CREATE TABLE t1 (a INTEGER)");
for i in 1..=10 {
exec_sql(&mut db, &format!("INSERT INTO t1 VALUES ({})", i));
}
exec_sql(&mut db, "CREATE TABLE t2 (b INTEGER)");
for i in 1..=10 {
exec_sql(&mut db, &format!("INSERT INTO t2 VALUES ({})", i));
}
let executor = SelectExecutor::new(&db);
let select_stmt = Parser::parse_sql("SELECT * FROM t1, t2 WHERE t1.a = t2.b").unwrap();
let result = if let vibesql_ast::Statement::Select(s) = select_stmt {
executor.execute(&s).unwrap()
} else {
panic!("Expected SELECT statement")
};
assert_eq!(result.len(), 10);
for row in &result {
assert_eq!(row.values[0], row.values[1]);
}
}
#[test]
fn test_where_equijoin_with_additional_filter() {
let mut db = Database::new();
exec_sql(&mut db, "CREATE TABLE t1 (a INTEGER, x INTEGER)");
for i in 1..=10 {
exec_sql(&mut db, &format!("INSERT INTO t1 VALUES ({}, {})", i, i * 10));
}
exec_sql(&mut db, "CREATE TABLE t2 (b INTEGER, y INTEGER)");
for i in 1..=10 {
exec_sql(&mut db, &format!("INSERT INTO t2 VALUES ({}, {})", i, i * 5));
}
let executor = SelectExecutor::new(&db);
let select_stmt =
Parser::parse_sql("SELECT * FROM t1, t2 WHERE t1.a = t2.b AND t1.x > 50").unwrap();
let result = if let vibesql_ast::Statement::Select(s) = select_stmt {
executor.execute(&s).unwrap()
} else {
panic!("Expected SELECT statement")
};
assert_eq!(result.len(), 5);
}
#[test]
fn test_multiple_table_where_equijoins() {
let mut db = Database::new();
for table_num in 1..=4 {
exec_sql(&mut db, &format!("CREATE TABLE t{} (a INTEGER)", table_num));
for i in 1..=10 {
exec_sql(&mut db, &format!("INSERT INTO t{} VALUES ({})", table_num, i));
}
}
let executor = SelectExecutor::new(&db);
let select_stmt = Parser::parse_sql(
"SELECT * FROM t1, t2, t3, t4 WHERE t1.a = t2.a AND t2.a = t3.a AND t3.a = t4.a",
)
.unwrap();
let result = if let vibesql_ast::Statement::Select(s) = select_stmt {
executor.execute(&s).unwrap()
} else {
panic!("Expected SELECT statement")
};
assert_eq!(result.len(), 10);
for row in &result {
let first_val = &row.values[0];
for val in &row.values[1..4] {
assert_eq!(val, first_val);
}
}
}
#[test]
fn test_where_equijoin_no_matches() {
let mut db = Database::new();
exec_sql(&mut db, "CREATE TABLE t1 (a INTEGER)");
exec_sql(&mut db, "INSERT INTO t1 VALUES (1)");
exec_sql(&mut db, "INSERT INTO t1 VALUES (2)");
exec_sql(&mut db, "CREATE TABLE t2 (b INTEGER)");
exec_sql(&mut db, "INSERT INTO t2 VALUES (3)");
exec_sql(&mut db, "INSERT INTO t2 VALUES (4)");
let executor = SelectExecutor::new(&db);
let select_stmt = Parser::parse_sql("SELECT * FROM t1, t2 WHERE t1.a = t2.b").unwrap();
let result = if let vibesql_ast::Statement::Select(s) = select_stmt {
executor.execute(&s).unwrap()
} else {
panic!("Expected SELECT statement")
};
assert_eq!(result.len(), 0);
}
#[test]
fn test_where_equijoin_partial_matches() {
let mut db = Database::new();
exec_sql(&mut db, "CREATE TABLE t1 (a INTEGER)");
for i in 1..=5 {
exec_sql(&mut db, &format!("INSERT INTO t1 VALUES ({})", i));
}
exec_sql(&mut db, "CREATE TABLE t2 (b INTEGER)");
for i in 3..=7 {
exec_sql(&mut db, &format!("INSERT INTO t2 VALUES ({})", i));
}
let executor = SelectExecutor::new(&db);
let select_stmt = Parser::parse_sql("SELECT * FROM t1, t2 WHERE t1.a = t2.b").unwrap();
let result = if let vibesql_ast::Statement::Select(s) = select_stmt {
executor.execute(&s).unwrap()
} else {
panic!("Expected SELECT statement")
};
assert_eq!(result.len(), 3);
}