#![cfg(feature = "postgres-native")]
use dbkit::{ConnectionManager, DbValue, PgHandler};
use sqlx::Row;
const COLS: [&str; 3] = ["id", "name", "val"];
fn row(id: i64, name: &str, val: f64) -> Vec<DbValue> {
vec![DbValue::Int(id), DbValue::Text(name.into()), DbValue::Float(val)]
}
async fn count(pool: &sqlx::PgPool) -> i64 {
sqlx::query_scalar("SELECT count(*) FROM dbkit_upsert_test")
.fetch_one(pool)
.await
.unwrap()
}
async fn fetch(pool: &sqlx::PgPool, id: i64) -> (String, f64) {
let r = sqlx::query("SELECT name, val FROM dbkit_upsert_test WHERE id = $1")
.bind(id)
.fetch_one(pool)
.await
.unwrap();
(r.get::<String, _>("name"), r.get::<f64, _>("val"))
}
#[tokio::test]
async fn copy_upsert_inserts_updates_and_ignores() {
let Ok(url) = std::env::var("DATABASE_URL") else {
eprintln!("DATABASE_URL not set — skipping copy_upsert test");
return;
};
let conn = ConnectionManager::new(&url).await.expect("connect");
let pg = PgHandler::new(conn.pg_native_pool().await.expect("native pool"));
let pool = pg.pool().clone();
sqlx::query("DROP TABLE IF EXISTS dbkit_upsert_test")
.execute(&pool)
.await
.unwrap();
sqlx::query(
"CREATE TABLE dbkit_upsert_test (id BIGINT PRIMARY KEY, name TEXT, val DOUBLE PRECISION)",
)
.execute(&pool)
.await
.unwrap();
let rows = vec![row(1, "a", 1.0), row(2, "b", 2.0), row(3, "c", 3.0)];
let n = pg
.copy_upsert("dbkit_upsert_test", &COLS, &["id"], &["name", "val"], &rows)
.await
.unwrap();
assert_eq!(n, 3, "3 rows inserted");
assert_eq!(count(&pool).await, 3);
let rows = vec![row(2, "B", 22.0), row(3, "C", 33.0), row(4, "d", 4.0)];
let n = pg
.copy_upsert("dbkit_upsert_test", &COLS, &["id"], &["name", "val"], &rows)
.await
.unwrap();
assert_eq!(n, 3, "2 updated + 1 inserted = 3 affected");
assert_eq!(count(&pool).await, 4, "exactly one new row");
assert_eq!(fetch(&pool, 2).await, ("B".to_string(), 22.0));
assert_eq!(fetch(&pool, 1).await, ("a".to_string(), 1.0));
let rows = vec![row(2, "ignored", 999.0), row(5, "e", 5.0)];
pg.copy_upsert("dbkit_upsert_test", &COLS, &["id"], &[], &rows)
.await
.unwrap();
assert_eq!(count(&pool).await, 5, "only id=5 added");
assert_eq!(
fetch(&pool, 2).await,
("B".to_string(), 22.0),
"DO NOTHING must not overwrite the existing row"
);
sqlx::query("DROP TABLE IF EXISTS dbkit_upsert_test")
.execute(&pool)
.await
.unwrap();
}