use crate::database::versions::ops::backfill::batch_sql;
use crate::database::versions::ops::trigger::NEEDS_BACKFILL_COLUMN;
fn id_key() -> Vec<String> {
vec!["id".to_string()]
}
#[test]
fn first_batch_selects_unprocessed_rows_only() {
let sql = batch_sql("users", &id_key(), 1000, None);
assert!(sql.contains(&format!(r#"WHERE "{NEEDS_BACKFILL_COLUMN}" = true"#)));
assert!(sql.contains("LIMIT 1000"));
assert!(!sql.contains('>'));
}
#[test]
fn batch_locks_only_its_own_rows() {
let sql = batch_sql("users", &id_key(), 1000, None);
assert!(sql.contains("FOR NO KEY UPDATE"));
}
#[test]
fn later_batches_resume_after_the_cursor() {
let last = vec!["500".to_string()];
let sql = batch_sql("users", &id_key(), 1000, Some(&last));
assert!(sql.contains(r#"AND ("id") > ('500')"#));
assert!(!sql.contains("OFFSET"));
}
#[test]
fn cursor_values_are_quoted() {
let last = vec!["o'brien".to_string()];
let sql = batch_sql("users", &id_key(), 10, Some(&last));
assert!(sql.contains("'o''brien'"));
}
#[test]
fn composite_keys_are_compared_as_tuples() {
let keys = vec!["tenant_id".to_string(), "id".to_string()];
let last = vec!["7".to_string(), "500".to_string()];
let sql = batch_sql("events", &keys, 100, Some(&last));
assert!(sql.contains(r#"("tenant_id", "id") > ('7', '500')"#));
assert!(sql.contains(r#""events"."tenant_id" = batch."tenant_id""#));
assert!(sql.contains(r#""events"."id" = batch."id""#));
}
#[test]
fn update_returns_the_next_cursor() {
let sql = batch_sql("users", &id_key(), 1000, None);
assert!(sql.contains("RETURNING"));
assert!(sql.ends_with(r#"SELECT "id"::text FROM updated ORDER BY "id" DESC LIMIT 1"#));
}