jsonb_agg(expression) - Aggregate values into a JSONB array (alias for json_agg)
(conn: &Connection)
| 942 | |
| 943 | /// jsonb_agg(expression) - Aggregate values into a JSONB array (alias for json_agg) |
| 944 | fn register_jsonb_agg(conn: &Connection) -> Result<()> { |
| 945 | use rusqlite::functions::Aggregate; |
| 946 | |
| 947 | #[derive(Default)] |
| 948 | struct JsonbAgg; |
| 949 | |
| 950 | impl Aggregate<Vec<JsonValue>, Option<String>> for JsonbAgg { |
| 951 | fn init(&self, _: &mut rusqlite::functions::Context<'_>) -> Result<Vec<JsonValue>> { |
| 952 | Ok(Vec::new()) |
| 953 | } |
| 954 | |
| 955 | fn step(&self, ctx: &mut rusqlite::functions::Context<'_>, agg: &mut Vec<JsonValue>) -> Result<()> { |
| 956 | let value = ctx.get_raw(0); |
| 957 | |
| 958 | let json_value = match value { |
| 959 | rusqlite::types::ValueRef::Null => JsonValue::Null, |
| 960 | rusqlite::types::ValueRef::Integer(i) => JsonValue::Number(serde_json::Number::from(i)), |
| 961 | rusqlite::types::ValueRef::Real(f) => { |
| 962 | if let Some(num) = serde_json::Number::from_f64(f) { |
| 963 | JsonValue::Number(num) |
| 964 | } else { |
| 965 | JsonValue::Null |
| 966 | } |
| 967 | } |
| 968 | rusqlite::types::ValueRef::Text(s) => { |
| 969 | let text = std::str::from_utf8(s).unwrap_or(""); |
| 970 | // Try to parse as JSON first, if it fails treat as string |
| 971 | serde_json::from_str(text) |
| 972 | .unwrap_or_else(|_| JsonValue::String(text.to_string())) |
| 973 | } |
| 974 | rusqlite::types::ValueRef::Blob(b) => { |
| 975 | // Convert blob to hex string |
| 976 | JsonValue::String(format!("\\x{}", hex::encode(b))) |
| 977 | } |
| 978 | }; |
| 979 | |
| 980 | agg.push(json_value); |
| 981 | Ok(()) |
| 982 | } |
| 983 | |
| 984 | fn finalize(&self, _: &mut rusqlite::functions::Context<'_>, agg: Option<Vec<JsonValue>>) -> Result<Option<String>> { |
| 985 | match agg { |
| 986 | Some(values) => Ok(Some(serde_json::to_string(&values).unwrap_or_else(|_| "[]".to_string()))), |
| 987 | None => Ok(Some("[]".to_string())), // Return empty array for no rows |
| 988 | } |
| 989 | } |
| 990 | } |
| 991 | |
| 992 | conn.create_aggregate_function( |
| 993 | "jsonb_agg", |
| 994 | 1, |
| 995 | FunctionFlags::SQLITE_UTF8, |
| 996 | JsonbAgg, |
| 997 | )?; |
| 998 | |
| 999 | Ok(()) |
| 1000 | } |
| 1001 |
no outgoing calls
no test coverage detected