use std::borrow::Cow;
use tempest_core::test_utils::setup_tracing;
use tempest_io::VirtualIo;
use tempest_rt::block_on;
use crate::{query::QueryResult, types::TempestValue};
use super::{get_columns, get_rows, open_engine};
async fn setup_global_option_schema(engine: &mut crate::Engine<VirtualIo>) {
engine.execute("create database main;").await.unwrap();
engine
.execute("create type main.User struct { id: Int64, name: Option[String] };")
.await
.unwrap();
engine
.execute("create table main.users : main.User { primary key (id) };")
.await
.unwrap();
}
async fn insert_global_option_users(engine: &mut crate::Engine<VirtualIo>) {
engine
.execute("insert into main.users { id: 1, name: Option.None };")
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 2, name: Option.Some("Alice") };"#)
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 3, name: Option.Some("John") };"#)
.await
.unwrap();
}
#[test]
fn test_global_option_in_struct_field() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_global_option_schema(&mut engine).await;
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_insert_option_without_prefix() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_global_option_schema(&mut engine).await;
insert_global_option_users(&mut engine).await;
let results = engine.execute("select * from main.users;").await.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 3);
assert_eq!(rows[0][0], TempestValue::Int64(1));
assert!(matches!(rows[0][1], TempestValue::Enum { variant_id: 0, .. }));
assert_eq!(rows[1][0], TempestValue::Int64(2));
assert!(matches!(&rows[1][1], TempestValue::Enum { variant_id: 1, fields, .. }
if fields[0] == TempestValue::String(Cow::Borrowed("Alice"))));
assert_eq!(rows[2][0], TempestValue::Int64(3));
assert!(matches!(&rows[2][1], TempestValue::Enum { variant_id: 1, fields, .. }
if fields[0] == TempestValue::String(Cow::Borrowed("John"))));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_is_option_none_global() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_global_option_schema(&mut engine).await;
insert_global_option_users(&mut engine).await;
let results = engine
.execute("select * from main.users where name is Option.None;")
.await
.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 1);
assert_eq!(rows[0][0], TempestValue::Int64(1));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_is_option_some_concrete_global() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_global_option_schema(&mut engine).await;
insert_global_option_users(&mut engine).await;
let results = engine
.execute(r#"select * from main.users where name is Option.Some("Alice");"#)
.await
.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 1);
assert_eq!(rows[0][0], TempestValue::Int64(2));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_is_option_some_wildcard_global() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_global_option_schema(&mut engine).await;
insert_global_option_users(&mut engine).await;
let results = engine
.execute(r#"select * from main.users where name is Option.Some(n) and n = "John";"#)
.await
.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 1);
assert_eq!(rows[0][0], TempestValue::Int64(3));
engine.shutdown().await.unwrap();
});
}
async fn setup_status_schema(engine: &mut crate::Engine<VirtualIo>) {
engine.execute("create database main;").await.unwrap();
engine
.execute("create type main.Status enum { Draft, Published, Archived };")
.await
.unwrap();
engine
.execute("create type main.Post struct { id: Int64, status: main.Status };")
.await
.unwrap();
engine
.execute("create table main.posts : main.Post { primary key (id) };")
.await
.unwrap();
}
async fn insert_three_posts(engine: &mut crate::Engine<VirtualIo>) {
engine
.execute("insert into main.posts { id: 1, status: main.Status.Draft };")
.await
.unwrap();
engine
.execute("insert into main.posts { id: 2, status: main.Status.Published };")
.await
.unwrap();
engine
.execute("insert into main.posts { id: 3, status: main.Status.Archived };")
.await
.unwrap();
}
#[test]
fn test_create_unit_enum() {
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.Status enum { Draft, Published, Archived };")
.await
.unwrap();
assert!(matches!(results[0], QueryResult::Empty));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_create_table_with_enum_field() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_status_schema(&mut engine).await;
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_insert_unit_variant() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_status_schema(&mut engine).await;
let results = engine
.execute("insert into main.posts { id: 1, status: main.Status.Draft };")
.await
.unwrap();
assert!(matches!(results[0], QueryResult::Empty));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_select_all_with_enum_field() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_status_schema(&mut engine).await;
insert_three_posts(&mut engine).await;
let results = engine
.execute("select * from main.posts;")
.await
.unwrap();
let cols = get_columns(&results[0]);
let rows = get_rows(&results[0]);
assert_eq!(cols[0], "id".into());
assert_eq!(cols[1], "status".into());
assert_eq!(rows.len(), 3);
assert_eq!(rows[0][0], TempestValue::Int64(1));
assert!(matches!(rows[0][1], TempestValue::Enum { variant_id: 0, .. })); assert_eq!(rows[1][0], TempestValue::Int64(2));
assert!(matches!(rows[1][1], TempestValue::Enum { variant_id: 1, .. })); assert_eq!(rows[2][0], TempestValue::Int64(3));
assert!(matches!(rows[2][1], TempestValue::Enum { variant_id: 2, .. })); engine.shutdown().await.unwrap();
});
}
#[test]
fn test_select_where_enum_is() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_status_schema(&mut engine).await;
insert_three_posts(&mut engine).await;
let results = engine
.execute("select * from main.posts where status is main.Status.Published;")
.await
.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 1);
assert_eq!(rows[0][0], TempestValue::Int64(2));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_delete_where_enum_is() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_status_schema(&mut engine).await;
insert_three_posts(&mut engine).await;
let del_results = engine
.execute("delete from main.posts where status is main.Status.Archived;")
.await
.unwrap();
assert!(matches!(del_results[0], QueryResult::RowsChanged(1)));
let remaining = engine
.execute("select * from main.posts;")
.await
.unwrap();
let rows = get_rows(&remaining[0]);
assert_eq!(rows.len(), 2);
assert_eq!(rows[0][0], TempestValue::Int64(1));
assert_eq!(rows[1][0], TempestValue::Int64(2));
engine.shutdown().await.unwrap();
});
}
async fn setup_option_schema(engine: &mut crate::Engine<VirtualIo>) {
engine.execute("create database main;").await.unwrap();
engine
.execute("create type main.Option[T] enum { None, Some(T) };")
.await
.unwrap();
engine
.execute("create type main.User struct { id: Int64, display_name: main.Option[String] };")
.await
.unwrap();
engine
.execute("create table main.users : main.User { primary key (id) };")
.await
.unwrap();
}
async fn insert_option_users(engine: &mut crate::Engine<VirtualIo>) {
engine
.execute("insert into main.users { id: 1, display_name: main.Option.None };")
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 2, display_name: main.Option.Some("Alice") };"#)
.await
.unwrap();
engine
.execute(r#"insert into main.users { id: 3, display_name: main.Option.Some("John") };"#)
.await
.unwrap();
}
#[test]
fn test_create_generic_option_enum() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_option_schema(&mut engine).await;
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_insert_and_select_option_variants() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_option_schema(&mut engine).await;
insert_option_users(&mut engine).await;
let results = engine.execute("select * from main.users;").await.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 3);
assert_eq!(rows[0][0], TempestValue::Int64(1));
assert!(matches!(rows[0][1], TempestValue::Enum { variant_id: 0, .. }));
assert_eq!(rows[1][0], TempestValue::Int64(2));
assert!(matches!(&rows[1][1], TempestValue::Enum { variant_id: 1, fields, .. }
if fields[0] == TempestValue::String(Cow::Borrowed("Alice"))));
assert_eq!(rows[2][0], TempestValue::Int64(3));
assert!(matches!(&rows[2][1], TempestValue::Enum { variant_id: 1, fields, .. }
if fields[0] == TempestValue::String(Cow::Borrowed("John"))));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_select_where_is_none() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_option_schema(&mut engine).await;
insert_option_users(&mut engine).await;
let results = engine
.execute("select * from main.users where display_name is main.Option.None;")
.await
.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 1);
assert_eq!(rows[0][0], TempestValue::Int64(1));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_select_where_is_some_concrete() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_option_schema(&mut engine).await;
insert_option_users(&mut engine).await;
let results = engine
.execute(r#"select * from main.users where display_name is main.Option.Some("John");"#)
.await
.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 1);
assert_eq!(rows[0][0], TempestValue::Int64(3));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_select_where_is_some_wildcard_and_eq() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_option_schema(&mut engine).await;
insert_option_users(&mut engine).await;
let results = engine
.execute(r#"select * from main.users where display_name is main.Option.Some(d) and d = "John";"#)
.await
.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 1);
assert_eq!(rows[0][0], TempestValue::Int64(3));
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_select_where_is_some_wildcard_no_filter() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_option_schema(&mut engine).await;
insert_option_users(&mut engine).await;
let results = engine
.execute("select * from main.users where display_name is main.Option.Some(d);")
.await
.unwrap();
let rows = get_rows(&results[0]);
assert_eq!(rows.len(), 2);
engine.shutdown().await.unwrap();
});
}
#[test]
fn test_delete_where_is_some_concrete() {
setup_tracing();
block_on(VirtualIo::default(), async {
let mut engine = open_engine().await;
setup_option_schema(&mut engine).await;
insert_option_users(&mut engine).await;
let del = engine
.execute(r#"delete from main.users where display_name is main.Option.Some("Alice");"#)
.await
.unwrap();
assert!(matches!(del[0], QueryResult::RowsChanged(1)));
let remaining = engine.execute("select * from main.users;").await.unwrap();
let rows = get_rows(&remaining[0]);
assert_eq!(rows.len(), 2);
assert_eq!(rows[0][0], TempestValue::Int64(1)); assert_eq!(rows[1][0], TempestValue::Int64(3));
engine.shutdown().await.unwrap();
});
}