Skip to main content

diesel/sqlite/types/
json.rs

1//! Support for JSON and JSONB values under SQLite.
2
3use crate::deserialize::{self, FromSql};
4use crate::serialize::{self, IsNull, Output, ToSql};
5use crate::sql_types;
6use crate::sqlite::{Sqlite, SqliteValue};
7use alloc::boxed::Box;
8use alloc::string::{String, ToString};
9use alloc::vec::Vec;
10
11#[cfg(all(feature = "__sqlite-shared", feature = "serde_json"))]
12impl FromSql<sql_types::Json, Sqlite> for serde_json::Value {
13    fn from_sql(mut value: SqliteValue<'_, '_, '_>) -> deserialize::Result<Self> {
14        serde_json::from_str(value.read_text()).map_err(|_| "Invalid Json".into())
15    }
16}
17
18#[cfg(all(feature = "__sqlite-shared", feature = "serde_json"))]
19impl ToSql<sql_types::Json, Sqlite> for serde_json::Value {
20    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
21        out.set_value(serde_json::to_string(self)?);
22        Ok(IsNull::No)
23    }
24}
25
26#[cfg(all(feature = "__sqlite-shared", feature = "serde_json"))]
27impl FromSql<sql_types::Jsonb, Sqlite> for serde_json::Value {
28    fn from_sql(mut value: SqliteValue<'_, '_, '_>) -> deserialize::Result<Self> {
29        use self::jsonb::*;
30
31        let bytes = value.read_blob();
32
33        if bytes.is_empty() {
34            return Err("Empty blob cannot be decoded as JSONB".into());
35        }
36
37        // Read the JSONB value from the byte stream
38        let (jsonb, _size) = read_jsonb_value(bytes)?;
39
40        Ok(jsonb)
41    }
42}
43
44#[cfg(all(feature = "__sqlite-shared", feature = "serde_json"))]
45impl ToSql<sql_types::Jsonb, Sqlite> for serde_json::Value {
46    fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
47        use self::jsonb::*;
48
49        // Create a buffer to hold the binary JSONB encoding
50        let mut buffer = Vec::new();
51
52        // Write the JSON value into the buffer in JSONB format
53        write_jsonb_value(self, &mut buffer)?;
54
55        // Set the serialized binary data to the output
56        out.set_value(buffer);
57
58        Ok(IsNull::No)
59    }
60}
61
62#[cfg(all(feature = "__sqlite-shared", feature = "serde_json"))]
63mod jsonb {
64    extern crate serde_json;
65
66    use super::*;
67
68    pub(super) const JSONB_NULL: u8 = 0x00;
69    pub(super) const JSONB_TRUE: u8 = 0x01;
70    pub(super) const JSONB_FALSE: u8 = 0x02;
71    pub(super) const JSONB_INT: u8 = 0x03;
72    pub(super) const JSONB_INT5: u8 = 0x04;
73    pub(super) const JSONB_FLOAT: u8 = 0x05;
74    pub(super) const JSONB_FLOAT5: u8 = 0x06;
75    pub(super) const JSONB_TEXT: u8 = 0x07;
76    pub(super) const JSONB_TEXTJ: u8 = 0x08;
77    pub(super) const JSONB_TEXT5: u8 = 0x09;
78    pub(super) const JSONB_TEXTRAW: u8 = 0x0A;
79    pub(super) const JSONB_ARRAY: u8 = 0x0B;
80    pub(super) const JSONB_OBJECT: u8 = 0x0C;
81
82    // Helper function to read a JSONB value from the byte stream
83    pub(super) fn read_jsonb_value(
84        bytes: &[u8],
85    ) -> deserialize::Result<(serde_json::Value, usize)> {
86        if bytes.is_empty() {
87            return Err("Empty JSONB data".into());
88        }
89
90        // The first byte contains both the element type and potentially the payload size
91        let first_byte = bytes[0];
92        let element_type = first_byte & 0x0F;
93        let size_hint = (first_byte & 0xF0) >> 4;
94
95        let (payload_size, header_size) = match size_hint {
96            0x00..=0x0B => (size_hint as usize, 1), // Payload size is directly in the upper nibble
97            0x0C => {
98                if bytes.len() < 2 {
99                    return Err("Invalid JSONB data: insufficient bytes for payload size".into());
100                }
101                (bytes[1] as usize, 2) // 1 additional byte for payload size
102            }
103            0x0D => {
104                if bytes.len() < 3 {
105                    return Err("Invalid JSONB data: insufficient bytes for payload size".into());
106                }
107                (u16::from_be_bytes([bytes[1], bytes[2]]) as usize, 3) // 2 additional bytes
108            }
109            0x0E => {
110                if bytes.len() < 5 {
111                    return Err("Invalid JSONB data: insufficient bytes for payload size".into());
112                }
113                (
114                    u32::from_be_bytes([bytes[1], bytes[2], bytes[3], bytes[4]]) as usize,
115                    5,
116                ) // 4 additional bytes
117            }
118            0x0F => {
119                if bytes.len() < 9 {
120                    return Err("Invalid JSONB data: insufficient bytes for payload size".into());
121                }
122                (
123                    usize::try_from(u64::from_be_bytes([
124                        bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
125                        bytes[8],
126                    ]))
127                    .map_err(Box::new)?,
128                    9,
129                ) // 8 additional bytes
130            }
131            _ => return Err("Invalid payload size hint".into()),
132        };
133
134        let total_size = header_size + payload_size;
135        if bytes.len() < total_size {
136            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Invalid JSONB data: insufficient bytes for value of type {0}, expected {1} bytes, got {2}",
                element_type, total_size, bytes.len()))
    })alloc::format!(
137                "Invalid JSONB data: insufficient bytes for value of type {}, expected {} bytes, got {}",
138                element_type,
139                total_size,
140                bytes.len()
141            )
142            .into());
143        }
144
145        let payload_bytes = &bytes[header_size..total_size];
146
147        let value = match element_type {
148            JSONB_NULL => Ok(serde_json::Value::Null),
149            JSONB_TRUE => Ok(serde_json::Value::Bool(true)),
150            JSONB_FALSE => Ok(serde_json::Value::Bool(false)),
151            JSONB_INT => read_jsonb_int(payload_bytes, payload_size),
152            JSONB_INT5 => Err("INT5 is not supported".into()),
153            JSONB_FLOAT => read_jsonb_float(payload_bytes, payload_size),
154            JSONB_FLOAT5 => Err("FLOAT5 is not supported".into()),
155            JSONB_TEXT => read_jsonb_text(payload_bytes, payload_size),
156            JSONB_TEXTJ => read_jsonb_textj(payload_bytes, payload_size),
157            JSONB_TEXTRAW => Err("TEXTRAW is not supported".into()),
158            JSONB_TEXT5 => Err("TEXT5 is not supported".into()),
159            JSONB_ARRAY => read_jsonb_array(payload_bytes, payload_size),
160            JSONB_OBJECT => read_jsonb_object(payload_bytes, payload_size),
161            _ => Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Unsupported or reserved JSONB type: {0}",
                element_type))
    })alloc::format!("Unsupported or reserved JSONB type: {element_type}").into()),
162        }?;
163
164        Ok((value, total_size))
165    }
166
167    // Read a JSON integer in canonical format (INT)
168    pub(super) fn read_jsonb_int(
169        bytes: &[u8],
170        payload_size: usize,
171    ) -> deserialize::Result<serde_json::Value> {
172        // Ensure the bytes are at least as large as the payload size
173        if bytes.len() < payload_size {
174            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Expected payload of size {0}, but got {1}",
                payload_size, bytes.len()))
    })alloc::format!(
175                "Expected payload of size {}, but got {}",
176                payload_size,
177                bytes.len()
178            )
179            .into());
180        }
181
182        // Read only the number of bytes specified by the payload size
183        let int_str = core::str::from_utf8(bytes).map_err(|_| "Invalid ASCII in JSONB integer")?;
184        let int_value = serde_json::from_str(int_str)
185            .map_err(|_| "Failed to parse JSONB")
186            .and_then(|v: serde_json::Value| {
187                v.is_i64()
188                    .then_some(v)
189                    .ok_or("Failed to parse JSONB integer")
190            })?;
191
192        Ok(int_value)
193    }
194
195    // Read a JSON float in canonical format (FLOAT)
196    pub(super) fn read_jsonb_float(
197        bytes: &[u8],
198        payload_size: usize,
199    ) -> deserialize::Result<serde_json::Value> {
200        if bytes.len() < payload_size {
201            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Expected payload of size {0}, but got {1}",
                payload_size, bytes.len()))
    })alloc::format!(
202                "Expected payload of size {}, but got {}",
203                payload_size,
204                bytes.len()
205            )
206            .into());
207        }
208
209        let float_str = core::str::from_utf8(bytes).map_err(|_| "Invalid UTF-8 in JSONB float")?;
210        let float_value = serde_json::from_str(float_str)
211            .map_err(|_| "Failed to parse JSONB")
212            .and_then(|v: serde_json::Value| {
213                v.is_f64()
214                    .then_some(v)
215                    .ok_or("Failed to parse JSONB number")
216            })?;
217
218        Ok(float_value)
219    }
220
221    // Read a JSON string
222    pub(super) fn read_jsonb_text(
223        bytes: &[u8],
224        payload_size: usize,
225    ) -> deserialize::Result<serde_json::Value> {
226        if bytes.len() < payload_size {
227            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Expected payload of size {0}, but got {1}",
                payload_size, bytes.len()))
    })alloc::format!(
228                "Expected payload of size {}, but got {}",
229                payload_size,
230                bytes.len()
231            )
232            .into());
233        }
234
235        let text = core::str::from_utf8(bytes).map_err(|_| "Invalid UTF-8 in JSONB string")?;
236        Ok(serde_json::Value::String(text.to_string()))
237    }
238
239    pub(super) fn read_jsonb_textj(
240        bytes: &[u8],
241        payload_size: usize,
242    ) -> deserialize::Result<serde_json::Value> {
243        if bytes.len() < payload_size {
244            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Expected payload of size {0}, but got {1}",
                payload_size, bytes.len()))
    })alloc::format!(
245                "Expected payload of size {}, but got {}",
246                payload_size,
247                bytes.len()
248            )
249            .into());
250        }
251
252        let text = core::str::from_utf8(bytes).map_err(|_| "Invalid UTF-8 in JSONB string")?;
253
254        // Unescape JSON escape sequences (e.g., "\n", "\u0020")
255        let unescaped_text = serde_json::from_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("\"{0}\"", text))
    })alloc::format!("\"{text}\""))
256            .map_err(|_| "Failed to parse JSON-escaped text in TEXTJ")?;
257
258        Ok(unescaped_text)
259    }
260
261    // Read a JSON array
262    pub(super) fn read_jsonb_array(
263        bytes: &[u8],
264        payload_size: usize,
265    ) -> deserialize::Result<serde_json::Value> {
266        let mut elements = Vec::new();
267        let mut total_read = 0;
268
269        while total_read < payload_size {
270            let (element, consumed) = read_jsonb_value(&bytes[total_read..payload_size])?;
271
272            elements.push(element);
273            total_read += consumed;
274        }
275
276        if total_read != payload_size {
277            return Err("Array payload size mismatch".into());
278        }
279
280        Ok(serde_json::Value::Array(elements))
281    }
282
283    pub(super) fn read_jsonb_object(
284        bytes: &[u8],
285        payload_size: usize,
286    ) -> deserialize::Result<serde_json::Value> {
287        let mut object = serde_json::Map::new();
288        let mut total_read = 0;
289
290        while total_read < payload_size {
291            // Read the key (must be a valid JSONB text type)
292            let (key_value, key_consumed) = read_jsonb_value(&bytes[total_read..])?;
293            let key_str = key_value
294                .as_str()
295                .ok_or("Invalid object key in JSONB, must be a string")?
296                .to_string();
297            total_read += key_consumed;
298
299            // Read the value associated with the key
300            let (value, value_consumed) = read_jsonb_value(&bytes[total_read..])?;
301            object.insert(key_str, value);
302            total_read += value_consumed;
303        }
304
305        // Ensure the total bytes read match the payload size
306        if total_read != payload_size {
307            return Err("Object payload size mismatch".into());
308        }
309
310        Ok(serde_json::Value::Object(object))
311    }
312
313    // Helper function to create the correct JsonbHeader based on the payload size
314    pub(super) fn create_jsonb_header(
315        element_type: u8,
316        payload_size: usize,
317    ) -> Result<Vec<u8>, String> {
318        // Check if payload size exceeds the maximum allowed size
319        if payload_size > 2_147_483_647 {
320            return Err("Payload size exceeds the maximum allowed size of 2GB".into());
321        }
322
323        let header = if payload_size <= 0x0B {
324            // Small payloads, 0 additional byte for size
325            <[_]>::into_vec(::alloc::boxed::box_new([((u8::try_from(payload_size).map_err(|e|
                                            e.to_string())?) << 4) | element_type]))alloc::vec![
326                ((u8::try_from(payload_size).map_err(|e| e.to_string())?) << 4) | element_type
327            ]
328        } else if payload_size <= 0xFF {
329            // Medium payloads, 1 additional byte for size
330            <[_]>::into_vec(::alloc::boxed::box_new([(0x0C << 4) | element_type,
                u8::try_from(payload_size).map_err(|e| e.to_string())?]))alloc::vec![
331                (0x0C << 4) | element_type,
332                u8::try_from(payload_size).map_err(|e| e.to_string())?,
333            ]
334        } else if payload_size <= 0xFFFF {
335            let mut header = Vec::with_capacity(3);
336
337            // Larger payloads, 2 additional bytes for size
338            header.push((0x0D << 4) | element_type);
339            header.extend_from_slice(
340                &(u16::try_from(payload_size).map_err(|e| e.to_string())?).to_be_bytes(),
341            );
342
343            header
344        } else {
345            let mut header = Vec::with_capacity(5);
346
347            // Very large payloads, 4 additional bytes for size (up to 2 GiB)
348            header.push((0x0E << 4) | element_type);
349            header.extend_from_slice(
350                &(u32::try_from(payload_size).map_err(|e| e.to_string())?).to_be_bytes(),
351            );
352
353            header
354        };
355
356        Ok(header)
357    }
358
359    pub(super) fn write_jsonb_header(
360        buffer: &mut Vec<u8>,
361        element_type: u8,
362        payload_size: usize,
363    ) -> serialize::Result {
364        // Create the header and append it to the buffer
365        let header = create_jsonb_header(element_type, payload_size)?;
366        buffer.extend(header);
367        Ok(IsNull::No)
368    }
369
370    // Helper function to write a JSON value into a JSONB binary format
371    pub(super) fn write_jsonb_value(
372        value: &serde_json::Value,
373        buffer: &mut Vec<u8>,
374    ) -> serialize::Result {
375        if value.is_null() {
376            write_jsonb_null(buffer)
377        } else if value.is_boolean() {
378            write_jsonb_bool(value.as_bool().ok_or("Failed to read JSONB value")?, buffer)
379        } else if value.is_number() {
380            write_jsonb_number(value, buffer)
381        } else if value.is_string() {
382            write_jsonb_string(value.as_str().ok_or("Failed to read JSONB value")?, buffer)
383        } else if value.is_array() {
384            write_jsonb_array(
385                value.as_array().ok_or("Failed to read JSONB value")?,
386                buffer,
387            )
388        } else if value.is_object() {
389            write_jsonb_object(
390                value.as_object().ok_or("Failed to read JSONB value")?,
391                buffer,
392            )
393        } else {
394            Err("Unsupported JSONB value type".into())
395        }
396    }
397
398    // Write a JSON null
399    pub(super) fn write_jsonb_null(buffer: &mut Vec<u8>) -> serialize::Result {
400        write_jsonb_header(buffer, JSONB_NULL, 0x0)?;
401        Ok(IsNull::No)
402    }
403
404    // Write a JSON boolean
405    pub(super) fn write_jsonb_bool(b: bool, buffer: &mut Vec<u8>) -> serialize::Result {
406        // Use the constants for true and false
407        write_jsonb_header(buffer, if b { JSONB_TRUE } else { JSONB_FALSE }, 0x0)?;
408        Ok(IsNull::No)
409    }
410
411    // Write a JSON number (integers and floats)
412    pub(super) fn write_jsonb_number(
413        n: &serde_json::Value,
414        buffer: &mut Vec<u8>,
415    ) -> serialize::Result {
416        if let Some(i) = n.as_i64() {
417            // Write an integer (INT type)
418            write_jsonb_int(i, buffer)
419        } else if let Some(f) = n.as_f64() {
420            // Write a float (FLOAT type)
421            write_jsonb_float(f, buffer)
422        } else {
423            Err("Invalid JSONB number type".into())
424        }
425    }
426
427    // Write an integer in JSONB format
428    pub(super) fn write_jsonb_int(i: i64, buffer: &mut Vec<u8>) -> serialize::Result {
429        let int_str = i.to_string();
430
431        write_jsonb_header(buffer, JSONB_INT, int_str.len())?;
432
433        // Write the ASCII text representation of the integer as the payload
434        buffer.extend_from_slice(int_str.as_bytes());
435
436        Ok(IsNull::No)
437    }
438
439    // Write a floating-point number in JSONB format
440    pub(super) fn write_jsonb_float(f: f64, buffer: &mut Vec<u8>) -> serialize::Result {
441        let float_str = f.to_string();
442
443        write_jsonb_header(buffer, JSONB_FLOAT, float_str.len())?;
444
445        // Write the ASCII text representation of the float as the payload
446        buffer.extend_from_slice(float_str.as_bytes());
447
448        Ok(IsNull::No)
449    }
450
451    pub(super) fn write_jsonb_string(s: &str, buffer: &mut Vec<u8>) -> serialize::Result {
452        if s.chars().any(|c| c.is_control()) {
453            // If the string contains control characters, treat it as TEXTJ (escaped JSON)
454            write_jsonb_textj(s, buffer)
455        } else {
456            write_jsonb_header(buffer, JSONB_TEXT, s.len())?;
457            // Write the UTF-8 text of the string as the payload (no delimiters)
458            buffer.extend_from_slice(s.as_bytes());
459            Ok(IsNull::No)
460        }
461    }
462
463    pub(super) fn write_jsonb_textj(s: &str, buffer: &mut Vec<u8>) -> serialize::Result {
464        // Escaping the string for JSON (e.g., \n, \uXXXX)
465        let escaped_string = serde_json::to_string(&String::from(s))
466            .map_err(|_| "Failed to serialize string for TEXTJ")?;
467
468        // Remove the surrounding quotes from serde_json::to_string result
469        let escaped_string = &escaped_string[1..escaped_string.len() - 1];
470
471        // Write the header (JSONB_TEXTJ) and the length of the escaped string
472        write_jsonb_header(buffer, JSONB_TEXTJ, escaped_string.len())?;
473
474        // Write the escaped string as the payload
475        buffer.extend_from_slice(escaped_string.as_bytes());
476
477        Ok(IsNull::No)
478    }
479
480    // Write a JSON array
481    pub(super) fn write_jsonb_array(
482        arr: &[serde_json::Value],
483        buffer: &mut Vec<u8>,
484    ) -> serialize::Result {
485        let mut tmp_buffer = Vec::new();
486
487        // Recursively write each element of the array
488        for element in arr {
489            write_jsonb_value(element, &mut tmp_buffer)?;
490        }
491
492        write_jsonb_header(buffer, JSONB_ARRAY, tmp_buffer.len())?;
493
494        buffer.extend_from_slice(&tmp_buffer);
495
496        Ok(IsNull::No)
497    }
498
499    // Write a JSON object
500    pub(super) fn write_jsonb_object(
501        obj: &serde_json::Map<String, serde_json::Value>,
502        buffer: &mut Vec<u8>,
503    ) -> serialize::Result {
504        let mut tmp_buffer = Vec::new();
505
506        // Recursively write each key-value pair of the object
507        for (key, value) in obj {
508            // Write the key (which must be a string)
509            write_jsonb_string(key, &mut tmp_buffer)?;
510
511            // Write the value
512            write_jsonb_value(value, &mut tmp_buffer)?;
513        }
514
515        write_jsonb_header(buffer, JSONB_OBJECT, tmp_buffer.len())?;
516
517        buffer.extend_from_slice(&tmp_buffer);
518
519        Ok(IsNull::No)
520    }
521}
522
523#[cfg(test)]
524#[cfg(all(feature = "__sqlite-shared", feature = "serde_json"))]
525mod tests {
526    use super::jsonb::*;
527    use super::*;
528    use crate::ExpressionMethods;
529    use crate::query_dsl::RunQueryDsl;
530    use crate::test_helpers::connection;
531    use crate::{IntoSql, dsl::sql};
532    use serde_json::{Value, json};
533    use sql_types::{Json, Jsonb};
534
535    #[diesel_test_helper::test]
536    fn json_to_sql() {
537        let conn = &mut connection();
538        let res = diesel::select(json!(true).into_sql::<Json>().eq(&sql("json('true')")))
539            .get_result::<bool>(conn)
540            .unwrap();
541        assert!(res);
542    }
543
544    #[diesel_test_helper::test]
545    fn test_read_jsonb_null() {
546        let data = vec![JSONB_NULL];
547        let result = read_jsonb_value(&data).unwrap().0;
548        assert_eq!(result, Value::Null);
549    }
550
551    #[diesel_test_helper::test]
552    fn test_read_jsonb_true() {
553        let data = vec![JSONB_TRUE];
554        let result = read_jsonb_value(&data).unwrap().0;
555        assert_eq!(result, Value::Bool(true));
556    }
557
558    #[diesel_test_helper::test]
559    fn test_read_jsonb_false() {
560        let data = vec![JSONB_FALSE];
561        let result = read_jsonb_value(&data).unwrap().0;
562        assert_eq!(result, Value::Bool(false));
563    }
564
565    #[diesel_test_helper::test]
566    fn test_read_jsonb_int() {
567        // JSONB_INT with payload "1"
568        let mut data = Vec::new();
569        data.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
570        data.push(b'1'); // Add the payload (integer "1")
571
572        let result = read_jsonb_value(&data).unwrap().0;
573        assert_eq!(result, json!(1));
574    }
575
576    #[diesel_test_helper::test]
577    fn test_read_jsonb_float() {
578        // JSONB_FLOAT with payload "1.5"
579        let mut data = Vec::new();
580        data.extend(create_jsonb_header(JSONB_FLOAT, 0x03).unwrap());
581        data.extend_from_slice(b"1.5"); // Add the payload (float "1.5")
582
583        let result = read_jsonb_value(&data).unwrap().0;
584        assert_eq!(result, json!(1.5));
585    }
586
587    #[diesel_test_helper::test]
588    fn test_read_jsonb_text() {
589        // JSONB_TEXT with payload "foo"
590        let mut data = Vec::new();
591        data.extend(create_jsonb_header(JSONB_TEXT, 0x03).unwrap());
592        data.extend_from_slice(b"foo"); // Add the payload (text "foo")
593
594        let result = read_jsonb_value(&data).unwrap().0;
595        assert_eq!(result, json!("foo"));
596    }
597
598    #[diesel_test_helper::test]
599    fn test_read_jsonb_array() {
600        // JSONB_ARRAY with two elements: 1 and true
601        let mut data = Vec::new();
602        data.extend(create_jsonb_header(JSONB_ARRAY, 0x03).unwrap()); // Array header
603
604        // Element 1: integer "1"
605        data.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
606        data.push(b'1');
607
608        // Element 2: true
609        data.extend(create_jsonb_header(JSONB_TRUE, 0x00).unwrap());
610
611        let result = read_jsonb_value(&data).unwrap().0;
612        assert_eq!(result, json!([1, true]));
613    }
614
615    #[diesel_test_helper::test]
616    fn test_read_jsonb_object() {
617        // JSONB_OBJECT with one key-value pair: "key": 42
618        let mut data = Vec::new();
619        data.extend(create_jsonb_header(JSONB_OBJECT, 0x07).unwrap()); // Object header
620
621        // Key: "key"
622        data.extend(create_jsonb_header(JSONB_TEXT, 0x03).unwrap());
623        data.extend_from_slice(b"key"); // Add the key payload
624
625        // Value: 42 (integer)
626        data.extend(create_jsonb_header(JSONB_INT, 0x02).unwrap());
627        data.extend_from_slice(b"42"); // Add the integer payload
628
629        let result = read_jsonb_value(&data).unwrap().0;
630        assert_eq!(result, json!({"key": 42}));
631    }
632
633    #[diesel_test_helper::test]
634    fn test_read_jsonb_nested_object() {
635        let mut data = Vec::new();
636
637        data.extend(create_jsonb_header(JSONB_OBJECT, 42).unwrap());
638
639        data.extend(create_jsonb_header(JSONB_TEXT, 9).unwrap());
640        data.extend_from_slice(b"outer_key");
641
642        data.extend(create_jsonb_header(JSONB_OBJECT, 13).unwrap());
643
644        data.extend(create_jsonb_header(JSONB_TEXT, 9).unwrap());
645        data.extend_from_slice(b"inner_key");
646
647        data.extend(create_jsonb_header(JSONB_INT, 2).unwrap());
648        data.extend_from_slice(b"42");
649
650        data.extend(create_jsonb_header(JSONB_TEXT, 14).unwrap());
651        data.extend_from_slice(b"additional_key");
652
653        data.extend(create_jsonb_header(JSONB_TRUE, 0).unwrap());
654
655        let result = read_jsonb_value(&data).unwrap().0;
656        assert_eq!(
657            result,
658            json!({
659                "additional_key": true,
660                "outer_key": {
661                    "inner_key": 42
662                },
663            })
664        );
665    }
666
667    #[diesel_test_helper::test]
668    fn test_write_jsonb_null() {
669        let value = serde_json::Value::Null;
670        let mut buffer = Vec::new();
671        write_jsonb_value(&value, &mut buffer).unwrap();
672        assert_eq!(buffer, vec![JSONB_NULL]);
673    }
674
675    #[diesel_test_helper::test]
676    fn test_write_jsonb_true() {
677        let value = serde_json::Value::Bool(true);
678        let mut buffer = Vec::new();
679        write_jsonb_value(&value, &mut buffer).unwrap();
680        assert_eq!(buffer, vec![JSONB_TRUE]);
681    }
682
683    #[diesel_test_helper::test]
684    fn test_write_jsonb_false() {
685        let value = serde_json::Value::Bool(false);
686        let mut buffer = Vec::new();
687        write_jsonb_value(&value, &mut buffer).unwrap();
688        assert_eq!(buffer, vec![JSONB_FALSE]);
689    }
690
691    #[diesel_test_helper::test]
692    fn test_write_jsonb_int() {
693        let value = serde_json::Value::Number(serde_json::Number::from(1));
694        let mut buffer = Vec::new();
695        write_jsonb_value(&value, &mut buffer).unwrap();
696
697        let mut expected_buffer = Vec::new();
698        expected_buffer.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
699        expected_buffer.push(b'1'); // Payload: integer "1"
700
701        assert_eq!(buffer, expected_buffer);
702    }
703
704    #[diesel_test_helper::test]
705    fn test_write_jsonb_float() {
706        let value = serde_json::Value::Number(serde_json::Number::from_f64(1.5).unwrap());
707        let mut buffer = Vec::new();
708        write_jsonb_value(&value, &mut buffer).unwrap();
709
710        let mut expected_buffer = Vec::new();
711        expected_buffer.extend(create_jsonb_header(JSONB_FLOAT, 0x03).unwrap());
712        expected_buffer.extend_from_slice(b"1.5"); // Payload: float "1.5"
713
714        assert_eq!(buffer, expected_buffer);
715    }
716
717    #[diesel_test_helper::test]
718    fn test_write_jsonb_text() {
719        let mut buffer = Vec::new();
720        let input_string = "hello";
721        write_jsonb_string(input_string, &mut buffer).unwrap();
722
723        let mut expected_buffer = Vec::new();
724        expected_buffer.extend(create_jsonb_header(JSONB_TEXT, 0x05).unwrap());
725        expected_buffer.extend_from_slice(b"hello");
726
727        assert_eq!(buffer, expected_buffer);
728    }
729
730    #[diesel_test_helper::test]
731    fn test_write_jsonb_textj() {
732        let mut buffer = Vec::new();
733        let input_string = "hello\nworld"; // Contains a newline, requires escaping
734        write_jsonb_string(input_string, &mut buffer).unwrap();
735
736        let mut expected_buffer = Vec::new();
737        expected_buffer.extend(create_jsonb_header(JSONB_TEXTJ, 12).unwrap());
738        expected_buffer.extend_from_slice(b"hello\\nworld");
739
740        assert_eq!(buffer, expected_buffer);
741    }
742
743    #[diesel_test_helper::test]
744    fn test_write_jsonb_array() {
745        let value = json!([1, true]);
746        let mut buffer = Vec::new();
747        write_jsonb_value(&value, &mut buffer).unwrap();
748
749        let mut expected_buffer = Vec::new();
750        expected_buffer.extend(create_jsonb_header(JSONB_ARRAY, 0x03).unwrap()); // Array header
751        expected_buffer.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap()); // Integer header
752        expected_buffer.push(b'1'); // Integer payload "1"
753        expected_buffer.extend(create_jsonb_header(JSONB_TRUE, 0x00).unwrap()); // Boolean header for "true"
754
755        assert_eq!(buffer, expected_buffer);
756    }
757
758    #[diesel_test_helper::test]
759    fn test_write_jsonb_object() {
760        let value = json!({"key": 42});
761        let mut buffer = Vec::new();
762        write_jsonb_value(&value, &mut buffer).unwrap();
763
764        let mut expected = Vec::new();
765        expected.extend(create_jsonb_header(JSONB_OBJECT, 7).unwrap());
766        expected.extend(create_jsonb_header(JSONB_TEXT, 3).unwrap());
767        expected.extend_from_slice(b"key");
768        expected.extend(create_jsonb_header(JSONB_INT, 2).unwrap());
769        expected.extend_from_slice(b"42");
770
771        assert_eq!(buffer, expected,);
772    }
773
774    #[diesel_test_helper::test]
775    fn jsonb_to_sql_bool() {
776        let conn = &mut connection();
777        let res = diesel::select(json!(true).into_sql::<Jsonb>().eq(&sql("jsonb('true')")))
778            .get_result::<bool>(conn)
779            .unwrap();
780        assert!(res);
781    }
782
783    #[diesel_test_helper::test]
784    fn jsonb_to_sql_null() {
785        let conn = &mut connection();
786        let res = diesel::select(json!(null).into_sql::<Jsonb>().eq(&sql("jsonb('null')")))
787            .get_result::<bool>(conn)
788            .unwrap();
789        assert!(res);
790    }
791
792    #[diesel_test_helper::test]
793    fn jsonb_to_sql_integer() {
794        let conn = &mut connection();
795        let res = diesel::select(json!(42).into_sql::<Jsonb>().eq(&sql("jsonb('42')")))
796            .get_result::<bool>(conn)
797            .unwrap();
798        assert!(res);
799    }
800
801    #[diesel_test_helper::test]
802    fn jsonb_to_sql_float() {
803        let conn = &mut connection();
804        let res = diesel::select(json!(42.23).into_sql::<Jsonb>().eq(&sql("jsonb('42.23')")))
805            .get_result::<bool>(conn)
806            .unwrap();
807        assert!(res);
808    }
809
810    #[diesel_test_helper::test]
811    fn jsonb_to_sql_text() {
812        let conn = &mut connection();
813
814        // Test for TEXT (simple string)
815        let res = diesel::select(
816            json!("hello")
817                .into_sql::<Jsonb>()
818                .eq(&sql("jsonb('\"hello\"')")),
819        )
820        .get_result::<bool>(conn)
821        .unwrap();
822
823        assert!(res);
824    }
825
826    #[diesel_test_helper::test]
827    fn jsonb_to_sql_textj() {
828        let conn = &mut connection();
829
830        // Test for TEXTJ (JSON-escaped string, e.g., containing \n or \uXXXX)
831        let res = diesel::select(
832            json!("hello\nworld")
833                .into_sql::<Jsonb>()
834                .eq(&sql("jsonb('\"hello\\nworld\"')")), // The string is JSON-escaped
835        )
836        .get_result::<bool>(conn)
837        .unwrap();
838
839        assert!(res);
840    }
841
842    #[diesel_test_helper::test]
843    fn jsonb_to_sql_array() {
844        let conn = &mut connection();
845        let res = diesel::select(
846            json!([1, true, "foo"])
847                .into_sql::<Jsonb>()
848                .eq(&sql("jsonb('[1, true, \"foo\"]')")),
849        )
850        .get_result::<bool>(conn)
851        .unwrap();
852        assert!(res);
853    }
854
855    #[diesel_test_helper::test]
856    fn jsonb_to_sql_object() {
857        let conn = &mut connection();
858        let res = diesel::select(
859            json!({"key": "value"})
860                .into_sql::<Jsonb>()
861                .eq(&sql("jsonb('{\"key\": \"value\"}')")),
862        )
863        .get_result::<bool>(conn)
864        .unwrap();
865        assert!(res);
866    }
867
868    #[diesel_test_helper::test]
869    fn jsonb_to_sql_object_in_object() {
870        let conn = &mut connection();
871        let json_value = json!({
872            "outer_key": {
873                "additional_key": true,
874                "inner_key": {
875                    "nested_key": 42
876                },
877            }
878        });
879        let res = diesel::select(json_value.into_sql::<Jsonb>().eq(&sql(
880            r#"jsonb('{"outer_key": {"additional_key": true, "inner_key": {"nested_key": 42}}}')"#,
881        )))
882        .get_result::<bool>(conn)
883        .unwrap();
884        assert!(res);
885    }
886
887    #[diesel_test_helper::test]
888    fn jsonb_to_sql_array_in_object() {
889        let conn = &mut connection();
890        let json_value = json!({
891            "is_valid": false,
892            "key": [1, 2, 3],
893        });
894        let res = diesel::select(
895            json_value
896                .into_sql::<Jsonb>()
897                .eq(&sql(r#"jsonb('{"is_valid": false, "key": [1, 2, 3]}')"#)),
898        )
899        .get_result::<bool>(conn)
900        .unwrap();
901        assert!(res);
902    }
903
904    #[diesel_test_helper::test]
905    fn jsonb_to_sql_object_in_array() {
906        let conn = &mut connection();
907        let json_value = json!([
908            {
909                "nested_key": "nested_value"
910            },
911            {
912                "int_value": 99
913            }
914        ]);
915        let res = diesel::select(json_value.into_sql::<Jsonb>().eq(&sql(
916            r#"jsonb('[{"nested_key": "nested_value"}, {"int_value": 99}]')"#,
917        )))
918        .get_result::<bool>(conn)
919        .unwrap();
920        assert!(res);
921    }
922
923    #[diesel_test_helper::test]
924    fn jsonb_from_sql_null() {
925        let conn = &mut connection();
926        let res = diesel::select(sql::<Jsonb>("jsonb('null')"))
927            .get_result::<serde_json::Value>(conn)
928            .unwrap();
929        assert_eq!(res, serde_json::json!(null));
930    }
931
932    #[diesel_test_helper::test]
933    fn jsonb_from_sql_true() {
934        let conn = &mut connection();
935        let res = diesel::select(sql::<Jsonb>("jsonb('true')"))
936            .get_result::<serde_json::Value>(conn)
937            .unwrap();
938        assert_eq!(res, serde_json::json!(true));
939    }
940
941    #[diesel_test_helper::test]
942    fn jsonb_from_sql_false() {
943        let conn = &mut connection();
944        let res = diesel::select(sql::<Jsonb>("jsonb('false')"))
945            .get_result::<serde_json::Value>(conn)
946            .unwrap();
947        assert_eq!(res, serde_json::json!(false));
948    }
949
950    #[diesel_test_helper::test]
951    fn jsonb_from_sql_int() {
952        let conn = &mut connection();
953        let res = diesel::select(sql::<Jsonb>("jsonb('42')"))
954            .get_result::<serde_json::Value>(conn)
955            .unwrap();
956        assert_eq!(res, serde_json::json!(42));
957    }
958
959    #[diesel_test_helper::test]
960    fn jsonb_from_sql_float() {
961        let conn = &mut connection();
962        let res = diesel::select(sql::<Jsonb>("jsonb('42.23')"))
963            .get_result::<serde_json::Value>(conn)
964            .unwrap();
965        assert_eq!(res, serde_json::json!(42.23));
966    }
967
968    #[diesel_test_helper::test]
969    fn jsonb_from_sql_object() {
970        let conn = &mut connection();
971        let res = diesel::select(sql::<Jsonb>("jsonb('{\"key\": \"value\"}')"))
972            .get_result::<serde_json::Value>(conn)
973            .unwrap();
974        assert_eq!(res, serde_json::json!({"key": "value"}));
975    }
976
977    #[diesel_test_helper::test]
978    fn jsonb_from_sql_array() {
979        let conn = &mut connection();
980        let res = diesel::select(sql::<Jsonb>("jsonb('[1, 2, 3]')"))
981            .get_result::<serde_json::Value>(conn)
982            .unwrap();
983        assert_eq!(res, serde_json::json!([1, 2, 3]));
984    }
985
986    #[diesel_test_helper::test]
987    fn jsonb_from_sql_nested_objects() {
988        let conn = &mut connection();
989        let res = diesel::select(sql::<Jsonb>("jsonb('{\"outer\": {\"inner\": 42}}')"))
990            .get_result::<serde_json::Value>(conn)
991            .unwrap();
992        assert_eq!(res, serde_json::json!({"outer": {"inner": 42}}));
993    }
994
995    #[diesel_test_helper::test]
996    fn jsonb_from_sql_nested_arrays() {
997        let conn = &mut connection();
998        let res = diesel::select(sql::<Jsonb>("jsonb('[[1, 2], [3, 4]]')"))
999            .get_result::<serde_json::Value>(conn)
1000            .unwrap();
1001        assert_eq!(res, serde_json::json!([[1, 2], [3, 4]]));
1002    }
1003
1004    #[diesel_test_helper::test]
1005    fn jsonb_from_sql_nested_arrays_in_objects() {
1006        let conn = &mut connection();
1007        let res = diesel::select(sql::<Jsonb>("jsonb('{\"array\": [1, 2, 3]}')"))
1008            .get_result::<serde_json::Value>(conn)
1009            .unwrap();
1010        assert_eq!(res, serde_json::json!({"array": [1, 2, 3]}));
1011    }
1012
1013    #[diesel_test_helper::test]
1014    fn jsonb_from_sql_nested_objects_in_arrays() {
1015        let conn = &mut connection();
1016        let res = diesel::select(sql::<Jsonb>(
1017            "jsonb('[{\"key1\": \"value1\"}, {\"key2\": \"value2\"}]')",
1018        ))
1019        .get_result::<serde_json::Value>(conn)
1020        .unwrap();
1021        assert_eq!(
1022            res,
1023            serde_json::json!([{"key1": "value1"}, {"key2": "value2"}])
1024        );
1025    }
1026
1027    #[diesel_test_helper::test]
1028    fn jsonb_from_sql_text() {
1029        let conn = &mut connection();
1030        let res = diesel::select(sql::<Jsonb>("jsonb('\"hello\"')"))
1031            .get_result::<serde_json::Value>(conn)
1032            .unwrap();
1033        assert_eq!(res, serde_json::json!("hello"));
1034    }
1035
1036    #[diesel_test_helper::test]
1037    fn jsonb_from_sql_textj() {
1038        let conn = &mut connection();
1039        let res = diesel::select(sql::<Jsonb>("jsonb('\"hello\\nworld\"')"))
1040            .get_result::<serde_json::Value>(conn)
1041            .unwrap();
1042        assert_eq!(res, serde_json::json!("hello\nworld"));
1043    }
1044
1045    #[diesel_test_helper::test]
1046    fn bad_json_from_sql() {
1047        let conn = &mut connection();
1048        let res = diesel::select(json!(true).into_sql::<Json>().eq(&sql("json('boom')")))
1049            .get_result::<bool>(conn);
1050        assert_eq!(res.unwrap_err().to_string(), "malformed JSON");
1051    }
1052
1053    #[diesel_test_helper::test]
1054    fn bad_jsonb_from_sql() {
1055        let conn = &mut connection();
1056        let res = diesel::select(json!(true).into_sql::<Jsonb>().eq(&sql("jsonb('boom')")))
1057            .get_result::<bool>(conn);
1058        assert_eq!(res.unwrap_err().to_string(), "malformed JSON");
1059    }
1060
1061    #[diesel_test_helper::test]
1062    fn no_json_from_sql() {
1063        let uuid: Result<serde_json::Value, _> = FromSql::<Json, Sqlite>::from_nullable_sql(None);
1064        assert_eq!(
1065            uuid.unwrap_err().to_string(),
1066            "Unexpected null for non-null column"
1067        );
1068    }
1069
1070    #[diesel_test_helper::test]
1071    fn no_jsonb_from_sql() {
1072        let uuid: Result<serde_json::Value, _> = FromSql::<Jsonb, Sqlite>::from_nullable_sql(None);
1073        assert_eq!(
1074            uuid.unwrap_err().to_string(),
1075            "Unexpected null for non-null column"
1076        );
1077    }
1078}