use std::path::PathBuf;
use tempest_core::tempest_str::TempestStr;
use tempest_core::test_utils::setup_tracing;
use tempest_io::VirtualIo;
use tempest_rt::block_on;
use crate::{Engine, config::EngineConfig, query::QueryResult, types::TempestValue};
async fn setup_schema(engine: &mut Engine<VirtualIo>) {
engine.execute("create database main;").await.unwrap();
engine
.execute("create type main.User struct { id: Int64, username: String };")
.await
.unwrap();
engine
.execute("create table main.users : main.User { primary key (id) };")
.await
.unwrap();
}
pub(super) fn get_rows(result: &QueryResult) -> &Vec<Vec<TempestValue<'static>>> {
let QueryResult::Rows { rows, .. } = result else {
panic!("expected Rows, got {:?}", result)
};
rows
}
pub(super) fn get_columns(result: &QueryResult) -> &Vec<TempestStr<'static>> {
let QueryResult::Rows { columns, .. } = result else {
panic!("expected Rows, got {:?}", result)
};
columns
}
pub(super) async fn open_engine() -> Engine<VirtualIo> {
Engine::<VirtualIo>::open(PathBuf::from("/tempest"), EngineConfig::default())
.await
.unwrap()
}
mod embedded_type_ref;
mod enums;
mod tuple_struct;
#[test]
fn test_create_database() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
let results = engine.execute("create database main;").await.unwrap();
assert!(matches!(results[0], QueryResult::Empty));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_create_type() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
engine.execute("create database main;").await.unwrap();
let results = engine
.execute("create type main.User struct { id: Int64, username: String };")
.await
.unwrap();
assert!(matches!(results[0], QueryResult::Empty));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_create_table() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
engine.execute("create database main;").await.unwrap();
engine
.execute("create type main.User struct { id: Int64, username: String };")
.await
.unwrap();
let results = engine
.execute("create table main.users : main.User { primary key (id) };")
.await
.unwrap();
assert!(matches!(results[0], QueryResult::Empty));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_generic_type_as_table_type() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
engine.execute("create database main;").await.unwrap();
engine
.execute("create type main.Box[T] struct { value: T };")
.await
.unwrap();
engine
.execute("create table main.boxes : main.Box[Int64] { primary key (value) };")
.await
.unwrap();
engine
.execute("insert into main.boxes { value: 42 };")
.await
.unwrap();
let results = engine.execute("select * from main.boxes;").await.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 1);
assert_eq!(rows[0][0], TempestValue::Int64(42));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_insert_single_row() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_schema(&mut engine).await;
let results = engine
.execute(r#"insert into main.users { id: 1, username: "John" };"#)
.await
.unwrap();
assert!(matches!(results[0], QueryResult::Empty));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_insert_multiple_rows() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_schema(&mut engine).await;
engine
.execute(r#"insert into main.users { id: 1, username: "John" };"#)
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 2, username: "Jeff" };"#)
.await
.unwrap();
let results = engine
.execute(r#"insert into main.users { id: 3, username: "Bob" };"#)
.await
.unwrap();
assert!(matches!(results[0], QueryResult::Empty));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_select_all_columns() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_schema(&mut engine).await;
engine
.execute(r#"insert into main.users { id: 1, username: "John" };"#)
.await
.unwrap();
let results = engine.execute("select * from main.users;").await.unwrap();
let cols = get_columns(&results[0]);
let rows = get_rows(&results[0]);
assert_eq!(cols[0], "id".into());
assert_eq!(cols[1], "username".into());
assert_eq!(rows.len(), 1);
assert_eq!(rows[0][0], TempestValue::Int64(1));
assert_eq!(rows[0][1], TempestValue::String("John".into()));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_select_projection() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_schema(&mut engine).await;
engine
.execute(r#"insert into main.users { id: 1, username: "John" };"#)
.await
.unwrap();
let results = engine
.execute("select username from main.users;")
.await
.unwrap();
let cols = get_columns(&results[0]);
let rows = get_rows(&results[0]);
assert_eq!(cols.len(), 1);
assert_eq!(cols[0], "username".into());
assert_eq!(rows[0][0], TempestValue::String("John".into()));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_select_where_eq() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_schema(&mut engine).await;
engine
.execute(r#"insert into main.users { id: 1, username: "John" };"#)
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 2, username: "Jeff" };"#)
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 3, username: "Bob" };"#)
.await
.unwrap();
let results = engine
.execute("select * from main.users where id = 2;")
.await
.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 1);
assert_eq!(rows[0][0], TempestValue::Int64(2));
assert_eq!(rows[0][1], TempestValue::String("Jeff".into()));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_select_where_gte() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_schema(&mut engine).await;
engine
.execute(r#"insert into main.users { id: 1, username: "John" };"#)
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 2, username: "Jeff" };"#)
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 3, username: "Bob" };"#)
.await
.unwrap();
let results = engine
.execute("select username from main.users where id >= 2;")
.await
.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 2);
assert_eq!(rows[0][0], TempestValue::String("Jeff".into()));
assert_eq!(rows[1][0], TempestValue::String("Bob".into()));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_select_empty_table() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_schema(&mut engine).await;
let results = engine.execute("select * from main.users;").await.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 0);
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_delete_all() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_schema(&mut engine).await;
engine
.execute(r#"insert into main.users { id: 1, username: "John" };"#)
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 2, username: "Jeff" };"#)
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 3, username: "Bob" };"#)
.await
.unwrap();
let del_results = engine.execute("delete from main.users;").await.unwrap();
assert!(matches!(del_results[0], QueryResult::RowsChanged(3)));
let results = engine.execute("select * from main.users;").await.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 0, "all rows should have been deleted");
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_delete_where() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_schema(&mut engine).await;
engine
.execute(r#"insert into main.users { id: 1, username: "John" };"#)
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 2, username: "Jeff" };"#)
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 3, username: "Bob" };"#)
.await
.unwrap();
let del_results = engine
.execute("delete from main.users where id = 2;")
.await
.unwrap();
assert!(matches!(del_results[0], QueryResult::RowsChanged(1)));
let results = engine.execute("select * from main.users;").await.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 2, "only id=2 should have been deleted");
assert_eq!(rows[0][0], TempestValue::Int64(1));
assert_eq!(rows[1][0], TempestValue::Int64(3));
engine.shutdown().await.unwrap();
});
}