const MAX_JSONB_BUILD_OBJECT_PAIRS: usize = 50;
pub(crate) fn merge_jsonb_build_object_expr(pairs: &[String]) -> String {
if pairs.is_empty() {
return "jsonb_build_object()".to_string();
}
let chunks: Vec<String> = pairs
.chunks(MAX_JSONB_BUILD_OBJECT_PAIRS)
.map(|chunk| format!("jsonb_build_object({})", chunk.join(", ")))
.collect();
match chunks.len() {
1 => chunks[0].clone(),
_ => format!("({})", chunks.join(" || ")),
}
}
#[cfg(test)]
mod tests {
use super::merge_jsonb_build_object_expr;
fn sample_pairs(n: usize) -> Vec<String> {
(0..n).map(|i| format!("'c{i}', t.c{i}")).collect()
}
#[test]
fn single_chunk_no_merge_operator() {
let pairs = sample_pairs(50);
let expr = merge_jsonb_build_object_expr(&pairs);
assert!(expr.starts_with("jsonb_build_object("));
assert!(!expr.contains("||"));
assert_eq!(expr.matches("jsonb_build_object").count(), 1);
}
#[test]
fn fifty_one_pairs_merge_two_objects() {
let pairs = sample_pairs(51);
let expr = merge_jsonb_build_object_expr(&pairs);
assert!(expr.starts_with('('));
assert!(expr.contains("||"));
assert_eq!(expr.matches("jsonb_build_object").count(), 2);
}
#[test]
fn one_pair_single_call() {
let pairs = sample_pairs(1);
let expr = merge_jsonb_build_object_expr(&pairs);
assert_eq!(expr, "jsonb_build_object('c0', t.c0)");
}
}