#![allow(dead_code)]
use zero_mysql::Opts;
use zero_mysql::r#macro::FromRow;
use zero_mysql::sync::Conn;
include!("common/check.rs");
include!("common/check_eq.rs");
include!("common/check_err.rs");
const TEST_URL: &str = "mysql://test:1234@localhost:3306/test";
fn get_conn() -> Result<Conn, zero_mysql::error::Error> {
let opts = Opts::try_from(TEST_URL)?;
Conn::new(opts)
}
#[derive(Debug, PartialEq, FromRow)]
struct User {
id: i64,
name: String,
age: u8,
}
#[derive(Debug, PartialEq, FromRow)]
struct UserWithOptional {
id: i64,
name: String,
email: Option<String>,
}
#[derive(Debug, PartialEq, FromRow)]
#[from_row(strict)]
struct StrictUser {
id: i64,
name: String,
}
#[derive(Debug, PartialEq, FromRow)]
struct IntTypes {
tiny: i8,
small: i16,
medium: i32,
big: i64,
}
#[derive(Debug, PartialEq, FromRow)]
struct FloatTypes {
float_val: f32,
double_val: f64,
}
#[derive(Debug, PartialEq, FromRow)]
struct PartialUser {
name: String,
}
#[test]
fn exec_collect_basic() -> Result<(), zero_mysql::error::Error> {
let mut conn = get_conn()?;
conn.query_drop("DROP TABLE IF EXISTS test_derive_users")?;
conn.query_drop(
"CREATE TEMPORARY TABLE test_derive_users (
id BIGINT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
age TINYINT UNSIGNED NOT NULL
)",
)?;
let mut stmt1 =
conn.prepare("INSERT INTO test_derive_users (id, name, age) VALUES (?, ?, ?)")?;
conn.exec_drop(&mut stmt1, (1i64, "Alice", 25u8))?;
conn.exec_drop(&mut stmt1, (2i64, "Bob", 30u8))?;
let mut stmt2 = conn.prepare("SELECT id, name, age FROM test_derive_users ORDER BY id")?;
let users: Vec<User> = conn.exec_collect(&mut stmt2, ())?;
check_eq!(users.len(), 2);
check_eq!(
users[0],
User {
id: 1,
name: "Alice".to_string(),
age: 25
}
);
check_eq!(
users[1],
User {
id: 2,
name: "Bob".to_string(),
age: 30
}
);
Ok(())
}
#[test]
fn exec_first() -> Result<(), zero_mysql::error::Error> {
let mut conn = get_conn()?;
conn.query_drop("DROP TABLE IF EXISTS test_derive_first")?;
conn.query_drop(
"CREATE TEMPORARY TABLE test_derive_first (
id BIGINT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
age TINYINT UNSIGNED NOT NULL
)",
)?;
let mut stmt1 =
conn.prepare("INSERT INTO test_derive_first (id, name, age) VALUES (?, ?, ?)")?;
conn.exec_drop(&mut stmt1, (1i64, "Alice", 25u8))?;
let mut stmt2 = conn.prepare("SELECT id, name, age FROM test_derive_first WHERE id = ?")?;
let user: Option<User> = conn.exec_first(&mut stmt2, (1i64,))?;
check_eq!(
user,
Some(User {
id: 1,
name: "Alice".to_string(),
age: 25
})
);
let user2: Option<User> = conn.exec_first(&mut stmt2, (999i64,))?;
check_eq!(user2, None);
Ok(())
}
#[test]
fn exec_foreach() -> Result<(), zero_mysql::error::Error> {
let mut conn = get_conn()?;
conn.query_drop("DROP TABLE IF EXISTS test_derive_foreach")?;
conn.query_drop(
"CREATE TEMPORARY TABLE test_derive_foreach (
id BIGINT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
age TINYINT UNSIGNED NOT NULL
)",
)?;
let mut stmt1 =
conn.prepare("INSERT INTO test_derive_foreach (id, name, age) VALUES (?, ?, ?)")?;
conn.exec_drop(&mut stmt1, (1i64, "Alice", 25u8))?;
conn.exec_drop(&mut stmt1, (2i64, "Bob", 30u8))?;
let mut stmt2 = conn.prepare("SELECT id, name, age FROM test_derive_foreach ORDER BY id")?;
let mut names = Vec::new();
conn.exec_foreach(&mut stmt2, (), |user: User| {
names.push(user.name);
Ok(())
})?;
check_eq!(names, vec!["Alice", "Bob"]);
Ok(())
}
#[test]
fn optional_field() -> Result<(), zero_mysql::error::Error> {
let mut conn = get_conn()?;
conn.query_drop("DROP TABLE IF EXISTS test_derive_optional")?;
conn.query_drop(
"CREATE TEMPORARY TABLE test_derive_optional (
id BIGINT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255)
)",
)?;
let mut stmt1 =
conn.prepare("INSERT INTO test_derive_optional (id, name, email) VALUES (?, ?, ?)")?;
conn.exec_drop(&mut stmt1, (1i64, "Alice", Some("alice@example.com")))?;
conn.exec_drop(&mut stmt1, (2i64, "Bob", None::<String>))?;
let mut stmt2 = conn.prepare("SELECT id, name, email FROM test_derive_optional ORDER BY id")?;
let users: Vec<UserWithOptional> = conn.exec_collect(&mut stmt2, ())?;
check_eq!(users[0].email, Some("alice@example.com".to_string()));
check_eq!(users[1].email, None);
Ok(())
}
#[test]
fn skip_unknown_columns() -> Result<(), zero_mysql::error::Error> {
let mut conn = get_conn()?;
conn.query_drop("DROP TABLE IF EXISTS test_derive_skip")?;
conn.query_drop(
"CREATE TEMPORARY TABLE test_derive_skip (
id BIGINT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
age TINYINT UNSIGNED NOT NULL,
extra_column VARCHAR(255)
)",
)?;
let mut stmt1 = conn.prepare(
"INSERT INTO test_derive_skip (id, name, age, extra_column) VALUES (?, ?, ?, ?)",
)?;
conn.exec_drop(&mut stmt1, (1i64, "Alice", 25u8, "ignored"))?;
let mut stmt2 = conn.prepare("SELECT id, name, age, extra_column FROM test_derive_skip")?;
let users: Vec<PartialUser> = conn.exec_collect(&mut stmt2, ())?;
check_eq!(users.len(), 1);
check_eq!(users[0].name, "Alice");
Ok(())
}
#[test]
fn strict_mode_unknown_column() -> Result<(), zero_mysql::error::Error> {
let mut conn = get_conn()?;
conn.query_drop("DROP TABLE IF EXISTS test_derive_strict")?;
conn.query_drop(
"CREATE TEMPORARY TABLE test_derive_strict (
id BIGINT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
extra VARCHAR(255)
)",
)?;
let mut stmt1 =
conn.prepare("INSERT INTO test_derive_strict (id, name, extra) VALUES (?, ?, ?)")?;
conn.exec_drop(&mut stmt1, (1i64, "Alice", "extra"))?;
let mut stmt2 = conn.prepare("SELECT id, name, extra FROM test_derive_strict")?;
let result: Result<Vec<StrictUser>, _> = conn.exec_collect(&mut stmt2, ());
let err = check_err!(result);
check!(err.to_string().contains("Unknown column"));
Ok(())
}
#[test]
fn missing_column() -> Result<(), zero_mysql::error::Error> {
let mut conn = get_conn()?;
conn.query_drop("DROP TABLE IF EXISTS test_derive_missing")?;
conn.query_drop(
"CREATE TEMPORARY TABLE test_derive_missing (
id BIGINT PRIMARY KEY,
name VARCHAR(255) NOT NULL
)",
)?;
let mut stmt1 = conn.prepare("INSERT INTO test_derive_missing (id, name) VALUES (?, ?)")?;
conn.exec_drop(&mut stmt1, (1i64, "Alice"))?;
let mut stmt2 = conn.prepare("SELECT id, name FROM test_derive_missing")?;
let result: Result<Vec<User>, _> = conn.exec_collect(&mut stmt2, ());
let err = check_err!(result);
check!(err.to_string().contains("Missing column"));
Ok(())
}
#[test]
fn column_order_independence() -> Result<(), zero_mysql::error::Error> {
let mut conn = get_conn()?;
conn.query_drop("DROP TABLE IF EXISTS test_derive_order")?;
conn.query_drop(
"CREATE TEMPORARY TABLE test_derive_order (
id BIGINT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
age TINYINT UNSIGNED NOT NULL
)",
)?;
let mut stmt1 =
conn.prepare("INSERT INTO test_derive_order (id, name, age) VALUES (?, ?, ?)")?;
conn.exec_drop(&mut stmt1, (1i64, "Alice", 25u8))?;
let mut stmt2 = conn.prepare("SELECT age, id, name FROM test_derive_order")?;
let users: Vec<User> = conn.exec_collect(&mut stmt2, ())?;
check_eq!(
users[0],
User {
id: 1,
name: "Alice".to_string(),
age: 25
}
);
Ok(())
}
#[test]
fn int_types() -> Result<(), zero_mysql::error::Error> {
let mut conn = get_conn()?;
conn.query_drop("DROP TABLE IF EXISTS test_derive_ints")?;
conn.query_drop(
"CREATE TEMPORARY TABLE test_derive_ints (
tiny TINYINT,
small SMALLINT,
medium INT,
big BIGINT
)",
)?;
let mut stmt1 = conn
.prepare("INSERT INTO test_derive_ints (tiny, small, medium, big) VALUES (?, ?, ?, ?)")?;
conn.exec_drop(&mut stmt1, (-1i8, -100i16, -10000i32, -1000000i64))?;
let mut stmt2 = conn.prepare("SELECT tiny, small, medium, big FROM test_derive_ints")?;
let rows: Vec<IntTypes> = conn.exec_collect(&mut stmt2, ())?;
check_eq!(
rows[0],
IntTypes {
tiny: -1,
small: -100,
medium: -10000,
big: -1000000
}
);
Ok(())
}
#[test]
fn float_types() -> Result<(), zero_mysql::error::Error> {
let mut conn = get_conn()?;
conn.query_drop("DROP TABLE IF EXISTS test_derive_floats")?;
conn.query_drop(
"CREATE TEMPORARY TABLE test_derive_floats (
float_val FLOAT,
double_val DOUBLE
)",
)?;
let mut stmt1 =
conn.prepare("INSERT INTO test_derive_floats (float_val, double_val) VALUES (?, ?)")?;
conn.exec_drop(&mut stmt1, (3.12f32, 2.81f64))?;
let mut stmt2 = conn.prepare("SELECT float_val, double_val FROM test_derive_floats")?;
let rows: Vec<FloatTypes> = conn.exec_collect(&mut stmt2, ())?;
let close1 = (rows[0].float_val - 3.12).abs() < 0.001;
check!(close1);
let close2 = (rows[0].double_val - 2.81).abs() < 0.00001;
check!(close2);
Ok(())
}