use oxisql_core::{Connection, Value};
use oxisql_sqlite_compat::SqliteConnection;
#[tokio::test]
async fn test_date_text_roundtrip() {
let conn = SqliteConnection::open_memory()
.await
.expect("open_memory failed");
conn.execute("CREATE TABLE t_date (d DATE)", &[])
.await
.expect("create table");
conn.execute("INSERT INTO t_date VALUES ('2024-01-15')", &[])
.await
.expect("insert");
let rows = conn
.query("SELECT d FROM t_date", &[])
.await
.expect("select");
assert_eq!(rows.len(), 1);
match rows[0].get_by_index(0) {
Some(Value::Date(days)) => {
assert_eq!(
*days, 19737,
"expected 19737 days for 2024-01-15, got {days}"
);
}
other => panic!("expected Value::Date, got {other:?}"),
}
}
#[tokio::test]
async fn test_date_integer_roundtrip() {
let conn = SqliteConnection::open_memory()
.await
.expect("open_memory failed");
conn.execute("CREATE TABLE t_date_int (d DATE)", &[])
.await
.expect("create table");
conn.execute("INSERT INTO t_date_int VALUES (19737)", &[])
.await
.expect("insert");
let rows = conn
.query("SELECT d FROM t_date_int", &[])
.await
.expect("select");
assert_eq!(rows.len(), 1);
match rows[0].get_by_index(0) {
Some(Value::Date(days)) => {
assert_eq!(*days, 19737, "expected 19737 days, got {days}");
}
other => panic!("expected Value::Date, got {other:?}"),
}
}
#[tokio::test]
async fn test_timestamp_text_roundtrip() {
let conn = SqliteConnection::open_memory()
.await
.expect("open_memory failed");
conn.execute("CREATE TABLE t_ts (ts TIMESTAMP)", &[])
.await
.expect("create table");
conn.execute("INSERT INTO t_ts VALUES ('1970-01-01 00:00:00')", &[])
.await
.expect("insert epoch");
let rows = conn
.query("SELECT ts FROM t_ts", &[])
.await
.expect("select");
assert_eq!(rows.len(), 1);
match rows[0].get_by_index(0) {
Some(Value::Timestamp(us)) => {
assert_eq!(*us, 0, "epoch should be 0 µs, got {us}");
}
other => panic!("expected Value::Timestamp, got {other:?}"),
}
}
#[tokio::test]
async fn test_datetime_text_roundtrip() {
let conn = SqliteConnection::open_memory()
.await
.expect("open_memory failed");
conn.execute("CREATE TABLE t_dt (ts DATETIME)", &[])
.await
.expect("create table");
conn.execute("INSERT INTO t_dt VALUES ('1970-01-01 00:00:01')", &[])
.await
.expect("insert");
let rows = conn
.query("SELECT ts FROM t_dt", &[])
.await
.expect("select");
assert_eq!(rows.len(), 1);
match rows[0].get_by_index(0) {
Some(Value::Timestamp(us)) => {
assert_eq!(*us, 1_000_000, "1 sec = 1_000_000 µs, got {us}");
}
other => panic!("expected Value::Timestamp, got {other:?}"),
}
}
#[tokio::test]
async fn test_time_text_roundtrip() {
let conn = SqliteConnection::open_memory()
.await
.expect("open_memory failed");
conn.execute("CREATE TABLE t_time (t TIME)", &[])
.await
.expect("create table");
conn.execute("INSERT INTO t_time VALUES ('01:00:00')", &[])
.await
.expect("insert");
let rows = conn
.query("SELECT t FROM t_time", &[])
.await
.expect("select");
assert_eq!(rows.len(), 1);
match rows[0].get_by_index(0) {
Some(Value::Time(us)) => {
let expected = 3_600_000_000i64;
assert_eq!(*us, expected, "01:00:00 = {expected} µs, got {us}");
}
other => panic!("expected Value::Time, got {other:?}"),
}
}
#[tokio::test]
async fn test_uuid_text_roundtrip() {
let conn = SqliteConnection::open_memory()
.await
.expect("open_memory failed");
conn.execute("CREATE TABLE t_uuid (u UUID)", &[])
.await
.expect("create table");
let uuid_str = "550e8400-e29b-41d4-a716-446655440000";
conn.execute(&format!("INSERT INTO t_uuid VALUES ('{uuid_str}')"), &[])
.await
.expect("insert");
let rows = conn
.query("SELECT u FROM t_uuid", &[])
.await
.expect("select");
assert_eq!(rows.len(), 1);
match rows[0].get_by_index(0) {
Some(Value::Uuid(u)) => {
let expected: u128 =
u128::from_str_radix("550e8400e29b41d4a716446655440000", 16).expect("valid hex");
assert_eq!(*u, expected, "uuid value mismatch: got {u:#034x}");
}
other => panic!("expected Value::Uuid, got {other:?}"),
}
}
#[tokio::test]
async fn test_plain_text_no_false_retyping() {
let conn = SqliteConnection::open_memory()
.await
.expect("open_memory failed");
conn.execute("CREATE TABLE t_text (s TEXT)", &[])
.await
.expect("create table");
conn.execute("INSERT INTO t_text VALUES ('2024-01-15')", &[])
.await
.expect("insert");
let rows = conn
.query("SELECT s FROM t_text", &[])
.await
.expect("select");
assert_eq!(rows.len(), 1);
match rows[0].get_by_index(0) {
Some(Value::Text(s)) => {
assert_eq!(s.as_str(), "2024-01-15", "text value should be unchanged");
}
other => panic!("expected Value::Text, got {other:?}"),
}
}
#[tokio::test]
async fn test_plain_integer_no_false_retyping() {
let conn = SqliteConnection::open_memory()
.await
.expect("open_memory failed");
conn.execute("CREATE TABLE t_int (n INTEGER)", &[])
.await
.expect("create table");
conn.execute("INSERT INTO t_int VALUES (42)", &[])
.await
.expect("insert");
let rows = conn
.query("SELECT n FROM t_int", &[])
.await
.expect("select");
assert_eq!(rows.len(), 1);
match rows[0].get_by_index(0) {
Some(Value::I64(n)) => {
assert_eq!(*n, 42, "integer value should be unchanged");
}
other => panic!("expected Value::I64, got {other:?}"),
}
}
#[tokio::test]
async fn test_typed_column_null() {
let conn = SqliteConnection::open_memory()
.await
.expect("open_memory failed");
conn.execute(
"CREATE TABLE t_null_typed (d DATE, ts TIMESTAMP, u UUID)",
&[],
)
.await
.expect("create table");
conn.execute("INSERT INTO t_null_typed VALUES (NULL, NULL, NULL)", &[])
.await
.expect("insert");
let rows = conn
.query("SELECT d, ts, u FROM t_null_typed", &[])
.await
.expect("select");
assert_eq!(rows.len(), 1);
assert_eq!(rows[0].get_by_index(0), Some(&Value::Null));
assert_eq!(rows[0].get_by_index(1), Some(&Value::Null));
assert_eq!(rows[0].get_by_index(2), Some(&Value::Null));
}