mod common;
use common::TestConnection;
use hyperdb_api::Table;
use hyperdb_api_derive::{query_as, FromRow, Table};
#[derive(Debug, PartialEq, FromRow, Table)]
#[hyperdb(table = "ct_users", register)]
struct CtUser {
id: i64,
name: String,
score: Option<f64>,
}
#[derive(Debug, PartialEq, FromRow, Table)]
#[hyperdb(table = "ct_orders", register)]
struct CtOrder {
id: i64,
user_id: i64,
amount: f64,
}
#[test]
fn table_derive_creates_correct_sql() {
assert!(
CtUser::CREATE_SQL.contains("ct_users"),
"CREATE_SQL must contain table name"
);
assert!(
CtUser::CREATE_SQL.contains("id BIGINT"),
"i64 maps to BIGINT"
);
assert!(
CtUser::CREATE_SQL.contains("name TEXT"),
"String maps to TEXT"
);
assert!(
CtUser::CREATE_SQL.contains("score DOUBLE PRECISION"),
"f64 maps to DOUBLE PRECISION"
);
assert!(
!CtUser::CREATE_SQL.contains("score DOUBLE PRECISION NOT NULL"),
"Option<f64> must not have NOT NULL"
);
assert_eq!(CtUser::NAME, "ct_users");
}
#[test]
fn query_as_fetch_all_happy_path() {
let test = TestConnection::new().expect("TestConnection");
test.execute_command(CtUser::CREATE_SQL)
.expect("create ct_users");
test.execute_command("INSERT INTO ct_users VALUES (1, 'Alice', 95.5), (2, 'Bob', NULL)")
.expect("insert");
let users: Vec<CtUser> = query_as!(CtUser, "SELECT id, name, score FROM ct_users ORDER BY id")
.fetch_all(&test.connection)
.expect("fetch_all");
assert_eq!(users.len(), 2);
assert_eq!(users[0].id, 1);
assert_eq!(users[0].name, "Alice");
assert_eq!(users[0].score, Some(95.5));
assert_eq!(users[1].id, 2);
assert_eq!(users[1].score, None);
}
#[test]
fn query_as_fetch_one() {
let test = TestConnection::new().expect("TestConnection");
test.execute_command(CtUser::CREATE_SQL)
.expect("create ct_users");
test.execute_command("INSERT INTO ct_users VALUES (42, 'Charlie', 77.0)")
.expect("insert");
let user: CtUser = query_as!(CtUser, "SELECT id, name, score FROM ct_users WHERE id = 42")
.fetch_one(&test.connection)
.expect("fetch_one");
assert_eq!(user.id, 42);
assert_eq!(user.name, "Charlie");
}
#[test]
fn query_as_fetch_optional_no_rows() {
let test = TestConnection::new().expect("TestConnection");
test.execute_command(CtUser::CREATE_SQL)
.expect("create ct_users");
let result: Option<CtUser> = query_as!(
CtUser,
"SELECT id, name, score FROM ct_users WHERE id = 9999"
)
.fetch_optional(&test.connection)
.expect("fetch_optional");
assert!(result.is_none());
}
#[test]
fn query_as_select_star_extra_columns_ok() {
let test = TestConnection::new().expect("TestConnection");
test.execute_command(CtUser::CREATE_SQL)
.expect("create ct_users");
test.execute_command("INSERT INTO ct_users VALUES (1, 'Dave', 88.0)")
.expect("insert");
let users: Vec<CtUser> = query_as!(CtUser, "SELECT * FROM ct_users")
.fetch_all(&test.connection)
.expect("fetch_all with SELECT *");
assert_eq!(users.len(), 1);
assert_eq!(users[0].name, "Dave");
}
#[test]
fn query_as_join_two_registered_tables() {
let test = TestConnection::new().expect("TestConnection");
test.execute_command(CtUser::CREATE_SQL)
.expect("create ct_users");
test.execute_command(CtOrder::CREATE_SQL)
.expect("create ct_orders");
test.execute_command("INSERT INTO ct_users VALUES (1, 'Eve', 90.0)")
.expect("insert user");
test.execute_command("INSERT INTO ct_orders VALUES (10, 1, 49.99)")
.expect("insert order");
let users: Vec<CtUser> = query_as!(
CtUser,
"SELECT u.id, u.name, u.score \
FROM ct_users u JOIN ct_orders o ON u.id = o.user_id"
)
.fetch_all(&test.connection)
.expect("fetch_all join");
assert_eq!(users.len(), 1);
assert_eq!(users[0].name, "Eve");
}