use bsql::Pool;
async fn pool() -> Pool {
Pool::connect("postgres://bsql:bsql@localhost/bsql_test")
.await
.expect("Failed to connect to test database. Is PostgreSQL running?")
}
#[tokio::test]
async fn select_works_without_replicas() {
let pool = pool().await;
assert!(!pool.has_replicas());
let users = bsql::query!("SELECT id, login FROM users ORDER BY id")
.fetch_all(&pool)
.await
.unwrap();
assert!(users.len() >= 2);
}
#[tokio::test]
async fn insert_uses_primary() {
let pool = pool().await;
let title = "rw-split-test";
let uid = 1i32;
let ticket = bsql::query!(
"INSERT INTO tickets (title, status, created_by_user_id)
VALUES ($title: &str, 'new', $uid: i32)
RETURNING id"
)
.fetch_one(&pool)
.await
.unwrap();
assert!(ticket.id > 0);
let ticket_id = ticket.id;
bsql::query!("DELETE FROM tickets WHERE id = $ticket_id: i32")
.execute(&pool)
.await
.unwrap();
}
#[tokio::test]
async fn update_uses_primary() {
let pool = pool().await;
let desc = "rw-split-update";
let id = 1i32;
let affected = bsql::query!("UPDATE tickets SET description = $desc: &str WHERE id = $id: i32")
.execute(&pool)
.await
.unwrap();
assert_eq!(affected, 1);
}
#[tokio::test]
async fn delete_uses_primary() {
let pool = pool().await;
let title = "rw-split-delete";
let uid = 1i32;
let ticket = bsql::query!(
"INSERT INTO tickets (title, status, created_by_user_id)
VALUES ($title: &str, 'new', $uid: i32)
RETURNING id"
)
.fetch_one(&pool)
.await
.unwrap();
let ticket_id = ticket.id;
let affected = bsql::query!("DELETE FROM tickets WHERE id = $ticket_id: i32")
.execute(&pool)
.await
.unwrap();
assert_eq!(affected, 1);
}
#[test]
fn builder_accepts_replicas() {
let builder = Pool::builder()
.host("localhost")
.port(5432)
.dbname("bsql_test")
.user("bsql")
.password("bsql")
.replica("postgres://bsql:bsql@replica1:5432/bsql_test")
.replica("postgres://bsql:bsql@replica2:5432/bsql_test");
let _ = builder;
}
#[tokio::test]
async fn pool_reports_no_replicas() {
let pool = pool().await;
assert!(!pool.has_replicas());
}
#[tokio::test]
async fn builder_with_same_host_replica() {
let pool = Pool::builder()
.host("localhost")
.port(5432)
.dbname("bsql_test")
.user("bsql")
.password("bsql")
.replica("postgres://bsql:bsql@localhost/bsql_test")
.build()
.await
.unwrap();
assert!(pool.has_replicas());
let users = bsql::query!("SELECT id, login FROM users ORDER BY id")
.fetch_all(&pool)
.await
.unwrap();
assert!(users.len() >= 2);
}
#[tokio::test]
async fn transaction_always_uses_primary() {
let pool = Pool::builder()
.host("localhost")
.port(5432)
.dbname("bsql_test")
.user("bsql")
.password("bsql")
.replica("postgres://bsql:bsql@localhost/bsql_test")
.build()
.await
.unwrap();
let txn = pool.begin().await.unwrap();
let users = bsql::query!("SELECT id, login FROM users ORDER BY id")
.fetch_all(&txn)
.await
.unwrap();
assert!(users.len() >= 2);
txn.rollback().await.unwrap();
}
#[tokio::test]
async fn pool_connection_uses_primary() {
let pool = Pool::builder()
.host("localhost")
.port(5432)
.dbname("bsql_test")
.user("bsql")
.password("bsql")
.replica("postgres://bsql:bsql@localhost/bsql_test")
.build()
.await
.unwrap();
let conn = pool.acquire().await.unwrap();
let users = bsql::query!("SELECT id, login FROM users ORDER BY id")
.fetch_all(&conn)
.await
.unwrap();
assert!(users.len() >= 2);
}
#[tokio::test]
async fn execute_always_uses_primary_with_replicas() {
let pool = Pool::builder()
.host("localhost")
.port(5432)
.dbname("bsql_test")
.user("bsql")
.password("bsql")
.replica("postgres://bsql:bsql@localhost/bsql_test")
.build()
.await
.unwrap();
let desc = "rw-split-execute-with-replica";
let id = 1i32;
let affected = bsql::query!("UPDATE tickets SET description = $desc: &str WHERE id = $id: i32")
.execute(&pool)
.await
.unwrap();
assert_eq!(affected, 1);
}
#[tokio::test]
async fn pool_status_reports_metrics() {
let pool = pool().await;
let status = pool.status();
assert!(status.max_size > 0, "max_size should be positive");
assert!(status.max_size >= status.size, "size <= max_size");
}
#[tokio::test]
async fn pool_direct_is_not_pgbouncer() {
let pool = pool().await;
assert!(!pool.is_pgbouncer());
}