use chain_builder::{ChainBuilder, Client, JoinMethods, QueryCommon, Select, WhereClauses};
use serde_json::{self, Value};
use sqlx::Execute;
#[test]
fn test_chain_builder() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .select(Select::Columns(vec!["*".into()]))
.table("users")
.query(|qb| {
qb.where_eq("name", Value::String("John".to_string()));
qb.where_eq("city", Value::String("New York".to_string()));
qb.where_in(
"department",
vec![
Value::String("IT".to_string()),
Value::String("HR".to_string()),
],
);
qb.where_subquery(|sub| {
sub.where_eq("status", Value::String("active".to_string()));
let or_sub = sub.or();
or_sub.where_eq("status", Value::String("pending".to_string()));
or_sub.where_between(
"registered_at",
[
Value::String("2024-01-01".to_string()),
Value::String("2024-01-31".to_string()),
],
);
});
qb.where_raw(
"(latitude BETWEEN ? AND ?) AND (longitude BETWEEN ? AND ?)",
Some(vec![
Value::Number(serde_json::Number::from_f64(40.0).unwrap()),
Value::Number(serde_json::Number::from_f64(41.0).unwrap()),
Value::Number(serde_json::Number::from_f64(70.0).unwrap()),
Value::Number(serde_json::Number::from_f64(71.0).unwrap()),
]),
);
});
builder.add_raw("LIMIT ?", Some(vec![10.into()]));
let sql = builder.to_sql();
assert_eq!(
sql.0,
"SELECT * FROM mydb.users WHERE name = ? AND city = ? AND department IN (?,?) AND (status = ? OR (status = ? AND registered_at BETWEEN ? AND ?)) AND (latitude BETWEEN ? AND ?) AND (longitude BETWEEN ? AND ?) LIMIT ?"
);
assert_eq!(
sql.1,
vec![
Value::String("John".to_string()),
Value::String("New York".to_string()),
Value::String("IT".to_string()),
Value::String("HR".to_string()),
Value::String("active".to_string()),
Value::String("pending".to_string()),
Value::String("2024-01-01".to_string()),
Value::String("2024-01-31".to_string()),
Value::Number(serde_json::Number::from_f64(40.0).unwrap()),
Value::Number(serde_json::Number::from_f64(41.0).unwrap()),
Value::Number(serde_json::Number::from_f64(70.0).unwrap()),
Value::Number(serde_json::Number::from_f64(71.0).unwrap()),
Value::Number(10.into()),
]
);
}
#[test]
fn test_join() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .select(Select::Columns(vec!["*".into()]))
.table("users")
.query(|qb| {
qb.join("details", |join| {
join.on("details.id", "=", "users.d_id");
join.on("details.id_w", "=", "users.d_id_w");
join.or().on("details.id_s", "=", "users.d_id_s").on(
"details.id_w",
"=",
"users.d_id_w",
);
});
qb.where_eq("name", Value::String("John".to_string()));
});
builder.select(Select::Raw(
"(SELECT COUNT(*) FROM `mydb`.`users` WHERE users.id = ?) AS count".into(),
Some(vec![Value::Number(1.into())]),
));
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "SELECT *, (SELECT COUNT(*) FROM `mydb`.`users` WHERE users.id = ?) AS count FROM mydb.users JOIN mydb.details ON details.id = users.d_id AND details.id_w = users.d_id_w OR (details.id_s = users.d_id_s AND details.id_w = users.d_id_w) WHERE name = ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![Value::Number(1.into()), Value::String("John".to_string()),]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_tow_join() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .select(Select::Columns(vec!["*".into()]))
.table("users")
.query(|qb| {
qb.join("details", |join| {
join.on("details.id", "=", "users.d_id");
join.on("details.id_w", "=", "users.d_id_w");
join.or().on("details.id_s", "=", "users.d_id_s").on(
"details.id_w",
"=",
"users.d_id_w",
);
});
qb.join("address", |join| {
join.on("address.id", "=", "users.a_id");
join.on("address.id_w", "=", "users.a_id_w");
join.or().on("address.id_s", "=", "users.a_id_s").on(
"address.id_w",
"=",
"users.a_id_w",
);
});
qb.where_eq("name", Value::String("John".to_string()));
});
builder.select(Select::Raw(
"(SELECT COUNT(*) FROM `mydb`.`users` WHERE users.id = ?) AS count".into(),
Some(vec![Value::Number(1.into())]),
));
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "SELECT *, (SELECT COUNT(*) FROM `mydb`.`users` WHERE users.id = ?) AS count FROM mydb.users JOIN mydb.details ON details.id = users.d_id AND details.id_w = users.d_id_w OR (details.id_s = users.d_id_s AND details.id_w = users.d_id_w) JOIN mydb.address ON address.id = users.a_id AND address.id_w = users.a_id_w OR (address.id_s = users.a_id_s AND address.id_w = users.a_id_w) WHERE name = ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![Value::Number(1.into()), Value::String("John".to_string()),]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_join_raw() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .select(Select::Columns(vec!["*".into()]))
.table("users")
.query(|qb| {
qb.raw_join("LEFT JOIN details ON details.id = users.d_id AND details.id_w = users.d_id_w OR (details.id_s = users.d_id_s AND details.id_w = users.d_id_w)", None);
qb.where_eq("name", Value::String("John".to_string()));
});
builder.select(Select::Raw(
"(SELECT COUNT(*) FROM `mydb`.`users` WHERE users.id = ?) AS count".into(),
Some(vec![Value::Number(1.into())]),
));
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "SELECT *, (SELECT COUNT(*) FROM `mydb`.`users` WHERE users.id = ?) AS count FROM mydb.users LEFT JOIN details ON details.id = users.d_id AND details.id_w = users.d_id_w OR (details.id_s = users.d_id_s AND details.id_w = users.d_id_w) WHERE name = ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![Value::Number(1.into()), Value::String("John".to_string()),]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_insert() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .table("users")
.insert(serde_json::json!({
"name": "John",
"`city`": "New York",
"department": "IT",
}));
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "INSERT INTO mydb.users (`city`, department, name) VALUES (?, ?, ?)";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::String("New York".to_string()),
Value::String("IT".to_string()),
Value::String("John".to_string())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_insert_many() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .table("users")
.insert_many(vec![
serde_json::json!({
"name": "John",
"`city`": "New York",
"department": "IT",
}),
serde_json::json!({
"name": "Jane",
"`city`": "New York",
"department": "HR",
}),
]);
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "INSERT INTO mydb.users (`city`, department, name) VALUES (?, ?, ?), (?, ?, ?)";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::String("New York".to_string()),
Value::String("IT".to_string()),
Value::String("John".to_string()),
Value::String("New York".to_string()),
Value::String("HR".to_string()),
Value::String("Jane".to_string())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_update() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .table("users")
.update(serde_json::json!({
"name": "John",
"`city`": "New York",
"department": "IT",
}))
.query(|qb| {
qb.where_eq("id", Value::Number(1.into()));
});
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "UPDATE mydb.users SET `city` = ?, department = ?, name = ? WHERE id = ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::String("New York".to_string()),
Value::String("IT".to_string()),
Value::String("John".to_string()),
Value::Number(1.into())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_delete() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .table("users")
.delete()
.query(|qb| {
qb.where_eq("id", Value::Number(1.into()));
});
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "DELETE FROM mydb.users WHERE id = ?";
assert_eq!(sql.0, true_sql);
assert_eq!(sql.1, vec![Value::Number(1.into())]);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_with() {
let mut slct = ChainBuilder::new(Client::Mysql);
slct.db("mydb") .table("address")
.select(Select::Columns(vec!["*".into()]))
.query(|qb| {
qb.where_eq("city", Value::String("New York".to_string()));
});
let mut active_users = ChainBuilder::new(Client::Mysql);
active_users
.db("mydb") .table("users")
.select(Select::Columns(vec!["*".into()]))
.select(Select::Builder("address".to_string(), slct))
.query(|qb| {
qb.where_eq("status", Value::String("active".to_string()));
});
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.with("active_users", active_users)
.select(Select::Columns(vec!["*".into()]))
.table("active_users")
.query(|qb| {
qb.where_eq("name", Value::String("John".to_string()));
});
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "WITH active_users AS (SELECT *, (SELECT * FROM mydb.address WHERE city = ?) AS address FROM mydb.users WHERE status = ?) SELECT * FROM active_users WHERE name = ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::String("New York".to_string()),
Value::String("active".to_string()),
Value::String("John".to_string())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_with_recursive() {
let mut slct = ChainBuilder::new(Client::Mysql);
slct.db("mydb") .table("address")
.select(Select::Columns(vec!["*".into()]))
.query(|qb| {
qb.where_eq("city", Value::String("New York".to_string()));
});
let mut active_users = ChainBuilder::new(Client::Mysql);
active_users
.db("mydb") .table("users")
.select(Select::Columns(vec!["*".into()]))
.select(Select::Builder("address".to_string(), slct))
.query(|qb| {
qb.where_eq("status", Value::String("active".to_string()));
});
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.with_recursive("active_users", active_users)
.select(Select::Columns(vec!["*".into()]))
.table("active_users")
.query(|qb| {
qb.where_eq("name", Value::String("John".to_string()));
});
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "WITH RECURSIVE active_users AS (SELECT *, (SELECT * FROM mydb.address WHERE city = ?) AS address FROM mydb.users WHERE status = ?) SELECT * FROM active_users WHERE name = ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::String("New York".to_string()),
Value::String("active".to_string()),
Value::String("John".to_string())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_union() {
let mut pending_users = ChainBuilder::new(Client::Mysql);
pending_users
.db("mydb") .table("users")
.select(Select::Columns(vec!["*".into()]))
.query(|qb| {
qb.where_eq("status", Value::String("pending".to_string()));
});
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.union(pending_users)
.db("mydb") .select(Select::Columns(vec!["*".into()]))
.table("users")
.query(|qb| {
qb.where_eq("name", Value::String("John".to_string()));
});
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql =
"SELECT * FROM mydb.users WHERE name = ? UNION SELECT * FROM mydb.users WHERE status = ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::String("John".to_string()),
Value::String("pending".to_string())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_union_all() {
let mut pending_users = ChainBuilder::new(Client::Mysql);
pending_users
.db("mydb") .table("users")
.select(Select::Columns(vec!["*".into()]))
.query(|qb| {
qb.where_eq("status", Value::String("pending".to_string()));
});
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.union_all(pending_users.clone())
.union_all(pending_users)
.db("mydb") .select(Select::Columns(vec!["*".into()]))
.table("users")
.query(|qb| {
qb.where_eq("name", Value::String("John".to_string()));
});
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql =
"SELECT * FROM mydb.users WHERE name = ? UNION ALL SELECT * FROM mydb.users WHERE status = ? UNION ALL SELECT * FROM mydb.users WHERE status = ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::String("John".to_string()),
Value::String("pending".to_string()),
Value::String("pending".to_string())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_limit_offset() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .select(Select::Columns(vec!["*".into()]))
.table("users")
.query(|qb| {
qb.where_eq("name", Value::String("John".to_string()));
qb.limit(10);
qb.offset(5);
});
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "SELECT * FROM mydb.users WHERE name = ? LIMIT ? OFFSET ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::String("John".to_string()),
Value::Number(10.into()),
Value::Number(5.into())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_group_by() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .select(Select::Columns(vec!["*".into()]))
.table("users")
.query(|qb| {
qb.where_eq("name", Value::String("John".to_string()));
qb.limit(10);
qb.offset(5);
qb.group_by(vec!["name".to_string(), "city".to_string()]);
});
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "SELECT * FROM mydb.users WHERE name = ? GROUP BY name, city LIMIT ? OFFSET ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::String("John".to_string()),
Value::Number(10.into()),
Value::Number(5.into())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_group_by_raw() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .select(Select::Columns(vec!["*".into()]))
.table("users")
.query(|qb| {
qb.where_eq("name", Value::String("John".to_string()));
qb.limit(10);
qb.offset(5);
qb.group_by_raw("name, city", None);
});
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "SELECT * FROM mydb.users WHERE name = ? GROUP BY name, city LIMIT ? OFFSET ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::String("John".to_string()),
Value::Number(10.into()),
Value::Number(5.into())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_order_by() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .select(Select::Columns(vec!["*".into()]))
.table("users")
.query(|qb| {
qb.where_eq("name", Value::String("John".to_string()));
qb.limit(10);
qb.offset(5);
qb.order_by("name", "ASC");
qb.order_by("city", "DESC");
});
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql =
"SELECT * FROM mydb.users WHERE name = ? ORDER BY name ASC, city DESC LIMIT ? OFFSET ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::String("John".to_string()),
Value::Number(10.into()),
Value::Number(5.into())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_order_by_raw() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .select(Select::Columns(vec!["*".into()]))
.table("users")
.query(|qb| {
qb.where_eq("name", Value::String("John".to_string()));
qb.limit(10);
qb.offset(5);
qb.order_by_raw("`count`, `name` order by (`name` is not null) desc", None);
});
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "SELECT * FROM mydb.users WHERE name = ? ORDER BY `count`, `name` order by (`name` is not null) desc LIMIT ? OFFSET ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::String("John".to_string()),
Value::Number(10.into()),
Value::Number(5.into())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}
#[test]
fn test_table_raw() {
let mut builder = ChainBuilder::new(Client::Mysql);
builder
.db("mydb") .table_raw(
"(SELECT * FROM users WHERE id = ?) as pp",
Some(vec![Value::Number(1.into())]),
)
.select(Select::Columns(vec!["*".into()]))
.query(|qb| {
qb.where_eq("name", Value::String("John".to_string()));
qb.where_gt("count", Value::Number(10.into()));
qb.limit(10);
qb.offset(5);
qb.order_by_raw("`count`, `name` order by (`name` is not null) desc", None);
});
let sql = builder.to_sql();
let to_sqlx = builder.to_sqlx_query();
let true_sql = "SELECT * FROM (SELECT * FROM users WHERE id = ?) as pp WHERE name = ? AND count > ? ORDER BY `count`, `name` order by (`name` is not null) desc LIMIT ? OFFSET ?";
assert_eq!(sql.0, true_sql);
assert_eq!(
sql.1,
vec![
Value::Number(1.into()),
Value::String("John".to_string()),
Value::Number(10.into()),
Value::Number(10.into()),
Value::Number(5.into())
]
);
assert_eq!(to_sqlx.sql(), true_sql);
}