mod common;
use qbrs::prelude::*;
use qbrs_sqlx::prelude::*;
#[derive(Table)]
#[table(name = "grants")]
#[allow(dead_code)]
struct Grants {
#[column(primary_key, generated)]
id: i64,
account: String,
authorization_url: Option<String>,
}
#[tokio::test]
async fn a_conditional_do_update_leaves_the_rows_it_rejects_uncounted() {
let (pool, guard) = common::test_pool("qbrs_do_update_where").await;
sqlx::query("DROP TABLE IF EXISTS grants")
.execute(&pool)
.await
.expect("drop grants");
sqlx::query(
"CREATE TABLE grants (
id BIGSERIAL PRIMARY KEY,
account TEXT NOT NULL UNIQUE,
authorization_url TEXT
)",
)
.execute(&pool)
.await
.expect("create grants");
let grant_once = |url: &'static str| {
qbrs::insert::insert(grants::Table)
.values(
GrantsInsert::builder()
.account("ada")
.authorization_url(url)
.build(),
)
.on_conflict_do_update(
grants::account,
ConflictUpdate::set_to(
grants::authorization_url,
excluded(grants::authorization_url),
)
.filter(grants::authorization_url.is_null()),
)
};
assert_eq!(
grant_once("https://first")
.execute(&pool)
.await
.expect("the first grant"),
1
);
assert_eq!(
grant_once("https://second")
.execute(&pool)
.await
.expect("the second grant"),
0
);
let held: Option<String> = select(grants::authorization_url)
.from(grants::Table)
.load_one(&pool)
.await
.expect("read the row back")
.expect("one row");
assert_eq!(held, Some("https://first".to_string()));
qbrs::update::update(grants::Table)
.set_to(grants::authorization_url, qbrs::expr::null())
.execute(&pool)
.await
.expect("clear the url");
assert_eq!(
grant_once("https://third")
.execute(&pool)
.await
.expect("the third grant"),
1
);
sqlx::query("DROP INDEX IF EXISTS grants_open")
.execute(&pool)
.await
.expect("drop the index");
sqlx::query("CREATE UNIQUE INDEX grants_open ON grants (account) WHERE id > 0")
.execute(&pool)
.await
.expect("create the partial unique index");
assert_eq!(
qbrs::insert::insert(grants::Table)
.values(
GrantsInsert::builder()
.account("ada")
.authorization_url("https://fourth")
.build(),
)
.on_conflict_do_update(
qbrs::insert::partial_index(grants::account, grants::id.gt(0i64)),
ConflictUpdate::set_to(
grants::authorization_url,
excluded(grants::authorization_url),
)
.filter(grants::authorization_url.is_null()),
)
.execute(&pool)
.await
.expect("both clauses in one statement"),
0
);
let mixed = qbrs::insert::insert(grants::Table)
.values(
GrantsInsert::builder()
.account("ada")
.authorization_url("https://fifth")
.build(),
)
.values(
GrantsInsert::builder()
.account("grace")
.authorization_url("https://grace")
.build(),
)
.on_conflict_do_update(
grants::account,
ConflictUpdate::set_to(
grants::authorization_url,
excluded(grants::authorization_url),
)
.filter(grants::authorization_url.is_null()),
)
.execute(&pool)
.await
.expect("one insert and one refusal");
assert_eq!(mixed, 1);
common::shutdown(pool, guard).await;
}