MCPcopy Create free account
hub / github.com/erans/pgsqlite / register_json_object_agg

Function register_json_object_agg

src/functions/json_functions.rs:1003–1073  ·  view source on GitHub ↗

json_object_agg(key, value) - Aggregate key-value pairs into a JSON object

(conn: &Connection)

Source from the content-addressed store, hash-verified

1001
1002/// json_object_agg(key, value) - Aggregate key-value pairs into a JSON object
1003fn register_json_object_agg(conn: &Connection) -> Result<()> {
1004 use rusqlite::functions::Aggregate;
1005 use std::collections::HashMap;
1006
1007 #[derive(Default)]
1008 struct JsonObjectAgg;
1009
1010 impl Aggregate<HashMap<String, JsonValue>, Option<String>> for JsonObjectAgg {
1011 fn init(&self, _: &mut rusqlite::functions::Context<'_>) -> Result<HashMap<String, JsonValue>> {
1012 Ok(HashMap::new())
1013 }
1014
1015 fn step(&self, ctx: &mut rusqlite::functions::Context<'_>, agg: &mut HashMap<String, JsonValue>) -> Result<()> {
1016 // Get the key (first argument)
1017 let key_value = ctx.get_raw(0);
1018 let key = match key_value {
1019 rusqlite::types::ValueRef::Text(s) => std::str::from_utf8(s).unwrap_or("").to_string(),
1020 rusqlite::types::ValueRef::Integer(i) => i.to_string(),
1021 rusqlite::types::ValueRef::Real(f) => f.to_string(),
1022 rusqlite::types::ValueRef::Null => "null".to_string(),
1023 rusqlite::types::ValueRef::Blob(_) => return Ok(()), // Skip blob keys
1024 };
1025
1026 // Get the value (second argument)
1027 let value_raw = ctx.get_raw(1);
1028 let json_value = match value_raw {
1029 rusqlite::types::ValueRef::Null => JsonValue::Null,
1030 rusqlite::types::ValueRef::Integer(i) => JsonValue::Number(serde_json::Number::from(i)),
1031 rusqlite::types::ValueRef::Real(f) => {
1032 if let Some(num) = serde_json::Number::from_f64(f) {
1033 JsonValue::Number(num)
1034 } else {
1035 JsonValue::Null
1036 }
1037 }
1038 rusqlite::types::ValueRef::Text(s) => {
1039 let text = std::str::from_utf8(s).unwrap_or("");
1040 // For json_object_agg, treat text as literal strings (not JSON)
1041 JsonValue::String(text.to_string())
1042 }
1043 rusqlite::types::ValueRef::Blob(b) => {
1044 // Convert blob to hex string
1045 JsonValue::String(format!("\\x{}", hex::encode(b)))
1046 }
1047 };
1048
1049 agg.insert(key, json_value);
1050 Ok(())
1051 }
1052
1053 fn finalize(&self, _: &mut rusqlite::functions::Context<'_>, agg: Option<HashMap<String, JsonValue>>) -> Result<Option<String>> {
1054 match agg {
1055 Some(map) => {
1056 let json_map: serde_json::Map<String, JsonValue> = map.into_iter().collect();
1057 let json_object = JsonValue::Object(json_map);
1058 Ok(Some(serde_json::to_string(&json_object).unwrap_or_else(|_| "{}".to_string())))
1059 }
1060 None => Ok(Some("{}".to_string())), // Return empty object for no rows

Callers 1

register_json_functionsFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected