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 => read_jsonb_text(payload_bytes, payload_size),
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            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [((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            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(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_textraw() {
600        // JSONB_TEXTRAW with payload "foo"
601        let mut data = Vec::new();
602        data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x03).unwrap());
603        data.extend_from_slice(b"foo");
604
605        let result = read_jsonb_value(&data).unwrap().0;
606        assert_eq!(result, json!("foo"));
607    }
608
609    #[diesel_test_helper::test]
610    fn test_read_jsonb_object_with_textraw_key() {
611        // JSONB_OBJECT with a TEXTRAW key and value
612        let mut data = Vec::new();
613        data.extend(create_jsonb_header(JSONB_OBJECT, 0x06).unwrap());
614        data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x01).unwrap());
615        data.extend_from_slice(b"a");
616        data.extend(create_jsonb_header(JSONB_TEXTRAW, 0x03).unwrap());
617        data.extend_from_slice(b"bar");
618
619        let result = read_jsonb_value(&data).unwrap().0;
620        assert_eq!(result, json!({"a": "bar"}));
621    }
622
623    #[diesel_test_helper::test]
624    fn test_read_jsonb_array() {
625        // JSONB_ARRAY with two elements: 1 and true
626        let mut data = Vec::new();
627        data.extend(create_jsonb_header(JSONB_ARRAY, 0x03).unwrap()); // Array header
628
629        // Element 1: integer "1"
630        data.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
631        data.push(b'1');
632
633        // Element 2: true
634        data.extend(create_jsonb_header(JSONB_TRUE, 0x00).unwrap());
635
636        let result = read_jsonb_value(&data).unwrap().0;
637        assert_eq!(result, json!([1, true]));
638    }
639
640    #[diesel_test_helper::test]
641    fn test_read_jsonb_object() {
642        // JSONB_OBJECT with one key-value pair: "key": 42
643        let mut data = Vec::new();
644        data.extend(create_jsonb_header(JSONB_OBJECT, 0x07).unwrap()); // Object header
645
646        // Key: "key"
647        data.extend(create_jsonb_header(JSONB_TEXT, 0x03).unwrap());
648        data.extend_from_slice(b"key"); // Add the key payload
649
650        // Value: 42 (integer)
651        data.extend(create_jsonb_header(JSONB_INT, 0x02).unwrap());
652        data.extend_from_slice(b"42"); // Add the integer payload
653
654        let result = read_jsonb_value(&data).unwrap().0;
655        assert_eq!(result, json!({"key": 42}));
656    }
657
658    #[diesel_test_helper::test]
659    fn test_read_jsonb_nested_object() {
660        let mut data = Vec::new();
661
662        data.extend(create_jsonb_header(JSONB_OBJECT, 42).unwrap());
663
664        data.extend(create_jsonb_header(JSONB_TEXT, 9).unwrap());
665        data.extend_from_slice(b"outer_key");
666
667        data.extend(create_jsonb_header(JSONB_OBJECT, 13).unwrap());
668
669        data.extend(create_jsonb_header(JSONB_TEXT, 9).unwrap());
670        data.extend_from_slice(b"inner_key");
671
672        data.extend(create_jsonb_header(JSONB_INT, 2).unwrap());
673        data.extend_from_slice(b"42");
674
675        data.extend(create_jsonb_header(JSONB_TEXT, 14).unwrap());
676        data.extend_from_slice(b"additional_key");
677
678        data.extend(create_jsonb_header(JSONB_TRUE, 0).unwrap());
679
680        let result = read_jsonb_value(&data).unwrap().0;
681        assert_eq!(
682            result,
683            json!({
684                "additional_key": true,
685                "outer_key": {
686                    "inner_key": 42
687                },
688            })
689        );
690    }
691
692    #[diesel_test_helper::test]
693    fn test_write_jsonb_null() {
694        let value = serde_json::Value::Null;
695        let mut buffer = Vec::new();
696        write_jsonb_value(&value, &mut buffer).unwrap();
697        assert_eq!(buffer, vec![JSONB_NULL]);
698    }
699
700    #[diesel_test_helper::test]
701    fn test_write_jsonb_true() {
702        let value = serde_json::Value::Bool(true);
703        let mut buffer = Vec::new();
704        write_jsonb_value(&value, &mut buffer).unwrap();
705        assert_eq!(buffer, vec![JSONB_TRUE]);
706    }
707
708    #[diesel_test_helper::test]
709    fn test_write_jsonb_false() {
710        let value = serde_json::Value::Bool(false);
711        let mut buffer = Vec::new();
712        write_jsonb_value(&value, &mut buffer).unwrap();
713        assert_eq!(buffer, vec![JSONB_FALSE]);
714    }
715
716    #[diesel_test_helper::test]
717    fn test_write_jsonb_int() {
718        let value = serde_json::Value::Number(serde_json::Number::from(1));
719        let mut buffer = Vec::new();
720        write_jsonb_value(&value, &mut buffer).unwrap();
721
722        let mut expected_buffer = Vec::new();
723        expected_buffer.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap());
724        expected_buffer.push(b'1'); // Payload: integer "1"
725
726        assert_eq!(buffer, expected_buffer);
727    }
728
729    #[diesel_test_helper::test]
730    fn test_write_jsonb_float() {
731        let value = serde_json::Value::Number(serde_json::Number::from_f64(1.5).unwrap());
732        let mut buffer = Vec::new();
733        write_jsonb_value(&value, &mut buffer).unwrap();
734
735        let mut expected_buffer = Vec::new();
736        expected_buffer.extend(create_jsonb_header(JSONB_FLOAT, 0x03).unwrap());
737        expected_buffer.extend_from_slice(b"1.5"); // Payload: float "1.5"
738
739        assert_eq!(buffer, expected_buffer);
740    }
741
742    #[diesel_test_helper::test]
743    fn test_write_jsonb_text() {
744        let mut buffer = Vec::new();
745        let input_string = "hello";
746        write_jsonb_string(input_string, &mut buffer).unwrap();
747
748        let mut expected_buffer = Vec::new();
749        expected_buffer.extend(create_jsonb_header(JSONB_TEXT, 0x05).unwrap());
750        expected_buffer.extend_from_slice(b"hello");
751
752        assert_eq!(buffer, expected_buffer);
753    }
754
755    #[diesel_test_helper::test]
756    fn test_write_jsonb_textj() {
757        let mut buffer = Vec::new();
758        let input_string = "hello\nworld"; // Contains a newline, requires escaping
759        write_jsonb_string(input_string, &mut buffer).unwrap();
760
761        let mut expected_buffer = Vec::new();
762        expected_buffer.extend(create_jsonb_header(JSONB_TEXTJ, 12).unwrap());
763        expected_buffer.extend_from_slice(b"hello\\nworld");
764
765        assert_eq!(buffer, expected_buffer);
766    }
767
768    #[diesel_test_helper::test]
769    fn test_write_jsonb_array() {
770        let value = json!([1, true]);
771        let mut buffer = Vec::new();
772        write_jsonb_value(&value, &mut buffer).unwrap();
773
774        let mut expected_buffer = Vec::new();
775        expected_buffer.extend(create_jsonb_header(JSONB_ARRAY, 0x03).unwrap()); // Array header
776        expected_buffer.extend(create_jsonb_header(JSONB_INT, 0x01).unwrap()); // Integer header
777        expected_buffer.push(b'1'); // Integer payload "1"
778        expected_buffer.extend(create_jsonb_header(JSONB_TRUE, 0x00).unwrap()); // Boolean header for "true"
779
780        assert_eq!(buffer, expected_buffer);
781    }
782
783    #[diesel_test_helper::test]
784    fn test_write_jsonb_object() {
785        let value = json!({"key": 42});
786        let mut buffer = Vec::new();
787        write_jsonb_value(&value, &mut buffer).unwrap();
788
789        let mut expected = Vec::new();
790        expected.extend(create_jsonb_header(JSONB_OBJECT, 7).unwrap());
791        expected.extend(create_jsonb_header(JSONB_TEXT, 3).unwrap());
792        expected.extend_from_slice(b"key");
793        expected.extend(create_jsonb_header(JSONB_INT, 2).unwrap());
794        expected.extend_from_slice(b"42");
795
796        assert_eq!(buffer, expected,);
797    }
798
799    #[diesel_test_helper::test]
800    fn jsonb_to_sql_bool() {
801        let conn = &mut connection();
802        let res = diesel::select(json!(true).into_sql::<Jsonb>().eq(&sql("jsonb('true')")))
803            .get_result::<bool>(conn)
804            .unwrap();
805        assert!(res);
806    }
807
808    #[diesel_test_helper::test]
809    fn jsonb_to_sql_null() {
810        let conn = &mut connection();
811        let res = diesel::select(json!(null).into_sql::<Jsonb>().eq(&sql("jsonb('null')")))
812            .get_result::<bool>(conn)
813            .unwrap();
814        assert!(res);
815    }
816
817    #[diesel_test_helper::test]
818    fn jsonb_to_sql_integer() {
819        let conn = &mut connection();
820        let res = diesel::select(json!(42).into_sql::<Jsonb>().eq(&sql("jsonb('42')")))
821            .get_result::<bool>(conn)
822            .unwrap();
823        assert!(res);
824    }
825
826    #[diesel_test_helper::test]
827    fn jsonb_to_sql_float() {
828        let conn = &mut connection();
829        let res = diesel::select(json!(42.23).into_sql::<Jsonb>().eq(&sql("jsonb('42.23')")))
830            .get_result::<bool>(conn)
831            .unwrap();
832        assert!(res);
833    }
834
835    #[diesel_test_helper::test]
836    fn jsonb_to_sql_text() {
837        let conn = &mut connection();
838
839        // Test for TEXT (simple string)
840        let res = diesel::select(
841            json!("hello")
842                .into_sql::<Jsonb>()
843                .eq(&sql("jsonb('\"hello\"')")),
844        )
845        .get_result::<bool>(conn)
846        .unwrap();
847
848        assert!(res);
849    }
850
851    #[diesel_test_helper::test]
852    fn jsonb_to_sql_textj() {
853        let conn = &mut connection();
854
855        // Test for TEXTJ (JSON-escaped string, e.g., containing \n or \uXXXX)
856        let res = diesel::select(
857            json!("hello\nworld")
858                .into_sql::<Jsonb>()
859                .eq(&sql("jsonb('\"hello\\nworld\"')")), // The string is JSON-escaped
860        )
861        .get_result::<bool>(conn)
862        .unwrap();
863
864        assert!(res);
865    }
866
867    #[diesel_test_helper::test]
868    fn jsonb_to_sql_array() {
869        let conn = &mut connection();
870        let res = diesel::select(
871            json!([1, true, "foo"])
872                .into_sql::<Jsonb>()
873                .eq(&sql("jsonb('[1, true, \"foo\"]')")),
874        )
875        .get_result::<bool>(conn)
876        .unwrap();
877        assert!(res);
878    }
879
880    #[diesel_test_helper::test]
881    fn jsonb_to_sql_object() {
882        let conn = &mut connection();
883        let res = diesel::select(
884            json!({"key": "value"})
885                .into_sql::<Jsonb>()
886                .eq(&sql("jsonb('{\"key\": \"value\"}')")),
887        )
888        .get_result::<bool>(conn)
889        .unwrap();
890        assert!(res);
891    }
892
893    #[diesel_test_helper::test]
894    fn jsonb_to_sql_object_in_object() {
895        let conn = &mut connection();
896        let json_value = json!({
897            "outer_key": {
898                "additional_key": true,
899                "inner_key": {
900                    "nested_key": 42
901                },
902            }
903        });
904        let res = diesel::select(json_value.into_sql::<Jsonb>().eq(&sql(
905            r#"jsonb('{"outer_key": {"additional_key": true, "inner_key": {"nested_key": 42}}}')"#,
906        )))
907        .get_result::<bool>(conn)
908        .unwrap();
909        assert!(res);
910    }
911
912    #[diesel_test_helper::test]
913    fn jsonb_to_sql_array_in_object() {
914        let conn = &mut connection();
915        let json_value = json!({
916            "is_valid": false,
917            "key": [1, 2, 3],
918        });
919        let res = diesel::select(
920            json_value
921                .into_sql::<Jsonb>()
922                .eq(&sql(r#"jsonb('{"is_valid": false, "key": [1, 2, 3]}')"#)),
923        )
924        .get_result::<bool>(conn)
925        .unwrap();
926        assert!(res);
927    }
928
929    #[diesel_test_helper::test]
930    fn jsonb_to_sql_object_in_array() {
931        let conn = &mut connection();
932        let json_value = json!([
933            {
934                "nested_key": "nested_value"
935            },
936            {
937                "int_value": 99
938            }
939        ]);
940        let res = diesel::select(json_value.into_sql::<Jsonb>().eq(&sql(
941            r#"jsonb('[{"nested_key": "nested_value"}, {"int_value": 99}]')"#,
942        )))
943        .get_result::<bool>(conn)
944        .unwrap();
945        assert!(res);
946    }
947
948    #[diesel_test_helper::test]
949    fn jsonb_from_sql_null() {
950        let conn = &mut connection();
951        let res = diesel::select(sql::<Jsonb>("jsonb('null')"))
952            .get_result::<serde_json::Value>(conn)
953            .unwrap();
954        assert_eq!(res, serde_json::json!(null));
955    }
956
957    #[diesel_test_helper::test]
958    fn jsonb_from_sql_true() {
959        let conn = &mut connection();
960        let res = diesel::select(sql::<Jsonb>("jsonb('true')"))
961            .get_result::<serde_json::Value>(conn)
962            .unwrap();
963        assert_eq!(res, serde_json::json!(true));
964    }
965
966    #[diesel_test_helper::test]
967    fn jsonb_from_sql_false() {
968        let conn = &mut connection();
969        let res = diesel::select(sql::<Jsonb>("jsonb('false')"))
970            .get_result::<serde_json::Value>(conn)
971            .unwrap();
972        assert_eq!(res, serde_json::json!(false));
973    }
974
975    #[diesel_test_helper::test]
976    fn jsonb_from_sql_int() {
977        let conn = &mut connection();
978        let res = diesel::select(sql::<Jsonb>("jsonb('42')"))
979            .get_result::<serde_json::Value>(conn)
980            .unwrap();
981        assert_eq!(res, serde_json::json!(42));
982    }
983
984    #[diesel_test_helper::test]
985    fn jsonb_from_sql_float() {
986        let conn = &mut connection();
987        let res = diesel::select(sql::<Jsonb>("jsonb('42.23')"))
988            .get_result::<serde_json::Value>(conn)
989            .unwrap();
990        assert_eq!(res, serde_json::json!(42.23));
991    }
992
993    #[diesel_test_helper::test]
994    fn jsonb_from_sql_object() {
995        let conn = &mut connection();
996        let res = diesel::select(sql::<Jsonb>("jsonb('{\"key\": \"value\"}')"))
997            .get_result::<serde_json::Value>(conn)
998            .unwrap();
999        assert_eq!(res, serde_json::json!({"key": "value"}));
1000    }
1001
1002    #[diesel_test_helper::test]
1003    fn jsonb_from_sql_array() {
1004        let conn = &mut connection();
1005        let res = diesel::select(sql::<Jsonb>("jsonb('[1, 2, 3]')"))
1006            .get_result::<serde_json::Value>(conn)
1007            .unwrap();
1008        assert_eq!(res, serde_json::json!([1, 2, 3]));
1009    }
1010
1011    #[diesel_test_helper::test]
1012    fn jsonb_from_sql_nested_objects() {
1013        let conn = &mut connection();
1014        let res = diesel::select(sql::<Jsonb>("jsonb('{\"outer\": {\"inner\": 42}}')"))
1015            .get_result::<serde_json::Value>(conn)
1016            .unwrap();
1017        assert_eq!(res, serde_json::json!({"outer": {"inner": 42}}));
1018    }
1019
1020    #[diesel_test_helper::test]
1021    fn jsonb_from_sql_nested_arrays() {
1022        let conn = &mut connection();
1023        let res = diesel::select(sql::<Jsonb>("jsonb('[[1, 2], [3, 4]]')"))
1024            .get_result::<serde_json::Value>(conn)
1025            .unwrap();
1026        assert_eq!(res, serde_json::json!([[1, 2], [3, 4]]));
1027    }
1028
1029    #[diesel_test_helper::test]
1030    fn jsonb_from_sql_nested_arrays_in_objects() {
1031        let conn = &mut connection();
1032        let res = diesel::select(sql::<Jsonb>("jsonb('{\"array\": [1, 2, 3]}')"))
1033            .get_result::<serde_json::Value>(conn)
1034            .unwrap();
1035        assert_eq!(res, serde_json::json!({"array": [1, 2, 3]}));
1036    }
1037
1038    #[diesel_test_helper::test]
1039    fn jsonb_from_sql_nested_objects_in_arrays() {
1040        let conn = &mut connection();
1041        let res = diesel::select(sql::<Jsonb>(
1042            "jsonb('[{\"key1\": \"value1\"}, {\"key2\": \"value2\"}]')",
1043        ))
1044        .get_result::<serde_json::Value>(conn)
1045        .unwrap();
1046        assert_eq!(
1047            res,
1048            serde_json::json!([{"key1": "value1"}, {"key2": "value2"}])
1049        );
1050    }
1051
1052    #[diesel_test_helper::test]
1053    fn jsonb_from_sql_text() {
1054        let conn = &mut connection();
1055        let res = diesel::select(sql::<Jsonb>("jsonb('\"hello\"')"))
1056            .get_result::<serde_json::Value>(conn)
1057            .unwrap();
1058        assert_eq!(res, serde_json::json!("hello"));
1059    }
1060
1061    #[diesel_test_helper::test]
1062    fn jsonb_from_sql_textj() {
1063        let conn = &mut connection();
1064        let res = diesel::select(sql::<Jsonb>("jsonb('\"hello\\nworld\"')"))
1065            .get_result::<serde_json::Value>(conn)
1066            .unwrap();
1067        assert_eq!(res, serde_json::json!("hello\nworld"));
1068    }
1069
1070    #[diesel_test_helper::test]
1071    fn bad_json_from_sql() {
1072        let conn = &mut connection();
1073        let res = diesel::select(json!(true).into_sql::<Json>().eq(&sql("json('boom')")))
1074            .get_result::<bool>(conn);
1075        assert_eq!(res.unwrap_err().to_string(), "malformed JSON");
1076    }
1077
1078    #[diesel_test_helper::test]
1079    fn bad_jsonb_from_sql() {
1080        let conn = &mut connection();
1081        let res = diesel::select(json!(true).into_sql::<Jsonb>().eq(&sql("jsonb('boom')")))
1082            .get_result::<bool>(conn);
1083        assert_eq!(res.unwrap_err().to_string(), "malformed JSON");
1084    }
1085
1086    #[diesel_test_helper::test]
1087    fn no_json_from_sql() {
1088        let uuid: Result<serde_json::Value, _> = FromSql::<Json, Sqlite>::from_nullable_sql(None);
1089        assert_eq!(
1090            uuid.unwrap_err().to_string(),
1091            "Unexpected null for non-null column"
1092        );
1093    }
1094
1095    #[diesel_test_helper::test]
1096    fn no_jsonb_from_sql() {
1097        let uuid: Result<serde_json::Value, _> = FromSql::<Jsonb, Sqlite>::from_nullable_sql(None);
1098        assert_eq!(
1099            uuid.unwrap_err().to_string(),
1100            "Unexpected null for non-null column"
1101        );
1102    }
1103}