risingwave_common/array/
struct_array.rs

1// Copyright 2025 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::cmp::Ordering;
16use std::fmt::{self, Debug, Write};
17use std::hash::Hash;
18use std::sync::Arc;
19
20use bytes::{Buf, BufMut};
21use either::Either;
22use itertools::Itertools;
23use risingwave_common_estimate_size::EstimateSize;
24use risingwave_pb::data::{PbArray, PbArrayType, StructArrayData};
25
26use super::{Array, ArrayBuilder, ArrayBuilderImpl, ArrayImpl, ArrayResult, DataChunk};
27use crate::array::ArrayRef;
28use crate::bitmap::{Bitmap, BitmapBuilder};
29use crate::error::BoxedError;
30use crate::row::Row;
31use crate::types::{
32    DataType, Datum, DatumRef, DefaultOrd, Scalar, ScalarImpl, StructType, ToDatumRef, ToText,
33    hash_datum,
34};
35use crate::util::iter_util::{ZipEqDebug, ZipEqFast};
36use crate::util::memcmp_encoding;
37use crate::util::value_encoding::estimate_serialize_datum_size;
38
39macro_rules! iter_fields_ref {
40    ($self:expr, $it:ident, { $($body:tt)* }) => {
41        iter_fields_ref!($self, $it, { $($body)* }, { $($body)* })
42    };
43
44    ($self:expr, $it:ident, { $($l_body:tt)* }, { $($r_body:tt)* }) => {
45        match $self {
46            StructRef::Indexed { arr, idx } => {
47                let $it = arr.children.iter().map(move |a| a.value_at(idx));
48                $($l_body)*
49            }
50            StructRef::ValueRef { val } => {
51                let $it = val.fields.iter().map(ToDatumRef::to_datum_ref);
52                $($r_body)*
53            }
54        }
55    }
56}
57
58#[derive(Debug, Clone)]
59pub struct StructArrayBuilder {
60    bitmap: BitmapBuilder,
61    pub(super) children_array: Vec<ArrayBuilderImpl>,
62    type_: StructType,
63    len: usize,
64}
65
66impl ArrayBuilder for StructArrayBuilder {
67    type ArrayType = StructArray;
68
69    #[cfg(not(test))]
70    fn new(_capacity: usize) -> Self {
71        panic!("Must use with_type.")
72    }
73
74    #[cfg(test)]
75    fn new(capacity: usize) -> Self {
76        Self::with_type(capacity, DataType::Struct(StructType::empty()))
77    }
78
79    fn with_type(capacity: usize, ty: DataType) -> Self {
80        let DataType::Struct(ty) = ty else {
81            panic!("must be DataType::Struct");
82        };
83        let children_array = ty
84            .types()
85            .map(|a| a.create_array_builder(capacity))
86            .collect();
87        Self {
88            bitmap: BitmapBuilder::with_capacity(capacity),
89            children_array,
90            type_: ty,
91            len: 0,
92        }
93    }
94
95    fn append_n(&mut self, n: usize, value: Option<StructRef<'_>>) {
96        match value {
97            None => {
98                self.bitmap.append_n(n, false);
99                for child in &mut self.children_array {
100                    child.append_n(n, Datum::None);
101                }
102            }
103            Some(v) => {
104                self.bitmap.append_n(n, true);
105                iter_fields_ref!(v, fields, {
106                    for (child, f) in self.children_array.iter_mut().zip_eq_fast(fields) {
107                        child.append_n(n, f);
108                    }
109                });
110            }
111        }
112        self.len += n;
113    }
114
115    fn append_array(&mut self, other: &StructArray) {
116        self.bitmap.append_bitmap(&other.bitmap);
117        for (a, o) in self
118            .children_array
119            .iter_mut()
120            .zip_eq_fast(other.children.iter())
121        {
122            a.append_array(o);
123        }
124        self.len += other.len();
125    }
126
127    fn pop(&mut self) -> Option<()> {
128        if self.bitmap.pop().is_some() {
129            for child in &mut self.children_array {
130                child.pop().unwrap()
131            }
132            self.len -= 1;
133
134            Some(())
135        } else {
136            None
137        }
138    }
139
140    fn len(&self) -> usize {
141        self.bitmap.len()
142    }
143
144    fn finish(self) -> StructArray {
145        let children = self
146            .children_array
147            .into_iter()
148            .map(|b| Arc::new(b.finish()))
149            .collect::<Vec<ArrayRef>>();
150        StructArray::new(self.type_, children, self.bitmap.finish())
151    }
152}
153
154impl EstimateSize for StructArrayBuilder {
155    fn estimated_heap_size(&self) -> usize {
156        self.bitmap.estimated_heap_size()
157            + self
158                .children_array
159                .iter()
160                .map(|a| a.estimated_heap_size())
161                .sum::<usize>()
162    }
163}
164
165#[derive(Debug, Clone, PartialEq)]
166pub struct StructArray {
167    bitmap: Bitmap,
168    children: Box<[ArrayRef]>,
169    type_: StructType,
170    heap_size: usize,
171}
172
173impl Array for StructArray {
174    type Builder = StructArrayBuilder;
175    type OwnedItem = StructValue;
176    type RefItem<'a> = StructRef<'a>;
177
178    unsafe fn raw_value_at_unchecked(&self, idx: usize) -> StructRef<'_> {
179        StructRef::Indexed { arr: self, idx }
180    }
181
182    fn len(&self) -> usize {
183        self.bitmap.len()
184    }
185
186    fn to_protobuf(&self) -> PbArray {
187        let children_array = self.children.iter().map(|a| a.to_protobuf()).collect();
188        let children_type = self.type_.types().map(|t| t.to_protobuf()).collect();
189        PbArray {
190            array_type: PbArrayType::Struct as i32,
191            struct_array_data: Some(StructArrayData {
192                children_array,
193                children_type,
194            }),
195            list_array_data: None,
196            null_bitmap: Some(self.bitmap.to_protobuf()),
197            values: vec![],
198        }
199    }
200
201    fn null_bitmap(&self) -> &Bitmap {
202        &self.bitmap
203    }
204
205    fn into_null_bitmap(self) -> Bitmap {
206        self.bitmap
207    }
208
209    fn set_bitmap(&mut self, bitmap: Bitmap) {
210        self.bitmap = bitmap;
211    }
212
213    fn data_type(&self) -> DataType {
214        DataType::Struct(self.type_.clone())
215    }
216}
217
218impl StructArray {
219    pub fn new(type_: StructType, children: Vec<ArrayRef>, bitmap: Bitmap) -> Self {
220        let heap_size = bitmap.estimated_heap_size()
221            + children
222                .iter()
223                .map(|c| c.estimated_heap_size())
224                .sum::<usize>();
225
226        Self {
227            bitmap,
228            children: children.into(),
229            type_,
230            heap_size,
231        }
232    }
233
234    pub fn from_protobuf(array: &PbArray) -> ArrayResult<ArrayImpl> {
235        ensure!(
236            array.values.is_empty(),
237            "Must have no buffer in a struct array"
238        );
239        let bitmap: Bitmap = array.get_null_bitmap()?.into();
240        let cardinality = bitmap.len();
241        let array_data = array.get_struct_array_data()?;
242        let children = array_data
243            .children_array
244            .iter()
245            .map(|child| Ok(Arc::new(ArrayImpl::from_protobuf(child, cardinality)?)))
246            .collect::<ArrayResult<Vec<ArrayRef>>>()?;
247        let type_ = StructType::unnamed(
248            array_data
249                .children_type
250                .iter()
251                .map(DataType::from)
252                .collect(),
253        );
254        Ok(Self::new(type_, children, bitmap).into())
255    }
256
257    /// Returns an iterator over the field array.
258    pub fn fields(&self) -> impl ExactSizeIterator<Item = &ArrayRef> {
259        self.children.iter()
260    }
261
262    /// Get the field array at the given index.
263    ///
264    /// Panics if the index is out of bounds.
265    pub fn field_at(&self, index: usize) -> &ArrayRef {
266        &self.children[index]
267    }
268
269    /// Get the field array at the given index.
270    ///
271    /// # Safety
272    /// The caller must ensure that the index is within bounds.
273    pub unsafe fn field_at_unchecked(&self, index: usize) -> &ArrayRef {
274        unsafe { self.children.get_unchecked(index) }
275    }
276
277    #[cfg(test)]
278    pub fn values_vec(&self) -> Vec<Option<StructValue>> {
279        use crate::types::ScalarRef;
280
281        self.iter()
282            .map(|v| v.map(|s| s.to_owned_scalar()))
283            .collect_vec()
284    }
285}
286
287impl EstimateSize for StructArray {
288    fn estimated_heap_size(&self) -> usize {
289        self.heap_size
290    }
291}
292
293impl From<DataChunk> for StructArray {
294    fn from(chunk: DataChunk) -> Self {
295        Self::new(
296            StructType::unnamed(chunk.columns().iter().map(|c| c.data_type()).collect()),
297            chunk.columns().to_vec(),
298            chunk.visibility().clone(),
299        )
300    }
301}
302
303#[derive(Clone, Debug, PartialEq, Eq, Default, Hash)]
304pub struct StructValue {
305    fields: Box<[Datum]>,
306}
307
308impl PartialOrd for StructValue {
309    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
310        Some(self.cmp(other))
311    }
312}
313
314impl Ord for StructValue {
315    fn cmp(&self, other: &Self) -> Ordering {
316        self.as_scalar_ref().cmp(&other.as_scalar_ref())
317    }
318}
319
320impl EstimateSize for StructValue {
321    fn estimated_heap_size(&self) -> usize {
322        // TODO: Try speed up this process.
323        self.fields
324            .iter()
325            .map(|datum| datum.estimated_heap_size())
326            .sum()
327    }
328}
329
330impl StructValue {
331    pub fn new(fields: Vec<Datum>) -> Self {
332        Self {
333            fields: fields.into_boxed_slice(),
334        }
335    }
336
337    /// Returns an empty struct.
338    pub fn empty() -> Self {
339        Self::new(vec![])
340    }
341
342    pub fn fields(&self) -> &[Datum] {
343        &self.fields
344    }
345
346    pub fn memcmp_deserialize<'a>(
347        fields: impl IntoIterator<Item = &'a DataType>,
348        deserializer: &mut memcomparable::Deserializer<impl Buf>,
349    ) -> memcomparable::Result<Self> {
350        fields
351            .into_iter()
352            .map(|field| memcmp_encoding::deserialize_datum_in_composite(field, deserializer))
353            .try_collect()
354            .map(Self::new)
355    }
356
357    /// Construct a struct from literal string.
358    ///
359    /// # Example
360    ///
361    /// ```
362    /// # use risingwave_common::types::{StructValue, StructType, DataType, ScalarImpl};
363    ///
364    /// let ty = StructType::unnamed(vec![DataType::Int32, DataType::Float64]);
365    /// let s = StructValue::from_str("(1, 2.0)", &ty).unwrap();
366    /// assert_eq!(s.fields()[0], Some(ScalarImpl::Int32(1)));
367    /// assert_eq!(s.fields()[1], Some(ScalarImpl::Float64(2.0.into())));
368    ///
369    /// let s = StructValue::from_str("(,)", &ty).unwrap();
370    /// assert_eq!(s.fields()[0], None);
371    /// assert_eq!(s.fields()[1], None);
372    /// ```
373    pub fn from_str(s: &str, ty: &StructType) -> Result<Self, BoxedError> {
374        // FIXME(runji): this is a trivial implementation which does not support nested struct.
375        if !s.starts_with('(') {
376            return Err("Missing left parenthesis".into());
377        }
378        if !s.ends_with(')') {
379            return Err("Missing right parenthesis".into());
380        }
381        let mut fields = Vec::with_capacity(s.len());
382        for (s, ty) in s[1..s.len() - 1].split(',').zip_eq_debug(ty.types()) {
383            let datum = match s.trim() {
384                "" => None,
385                s => Some(ScalarImpl::from_text(s, ty)?),
386            };
387            fields.push(datum);
388        }
389        Ok(StructValue::new(fields))
390    }
391}
392
393#[derive(Copy, Clone)]
394pub enum StructRef<'a> {
395    Indexed { arr: &'a StructArray, idx: usize },
396    ValueRef { val: &'a StructValue },
397}
398
399impl<'a> StructRef<'a> {
400    /// Iterates over the fields of the struct.
401    ///
402    /// Prefer using the macro `iter_fields_ref!` if possible to avoid the cost of enum dispatching.
403    pub fn iter_fields_ref(self) -> impl ExactSizeIterator<Item = DatumRef<'a>> + 'a {
404        iter_fields_ref!(self, it, { Either::Left(it) }, { Either::Right(it) })
405    }
406
407    /// Get the field at the given index.
408    ///
409    /// Panics if the index is out of bounds.
410    pub fn field_at(&self, i: usize) -> DatumRef<'a> {
411        match self {
412            StructRef::Indexed { arr, idx } => arr.field_at(i).value_at(*idx),
413            StructRef::ValueRef { val } => val.fields[i].to_datum_ref(),
414        }
415    }
416
417    /// Get the field at the given index.
418    ///
419    /// # Safety
420    /// The caller must ensure that the index is within bounds.
421    pub unsafe fn field_at_unchecked(&self, i: usize) -> DatumRef<'a> {
422        unsafe {
423            match self {
424                StructRef::Indexed { arr, idx } => {
425                    arr.field_at_unchecked(i).value_at_unchecked(*idx)
426                }
427                StructRef::ValueRef { val } => val.fields.get_unchecked(i).to_datum_ref(),
428            }
429        }
430    }
431
432    pub fn memcmp_serialize(
433        self,
434        serializer: &mut memcomparable::Serializer<impl BufMut>,
435    ) -> memcomparable::Result<()> {
436        iter_fields_ref!(self, it, {
437            for datum_ref in it {
438                memcmp_encoding::serialize_datum_in_composite(datum_ref, serializer)?
439            }
440            Ok(())
441        })
442    }
443
444    pub fn hash_scalar_inner<H: std::hash::Hasher>(self, state: &mut H) {
445        iter_fields_ref!(self, it, {
446            for datum_ref in it {
447                hash_datum(datum_ref, state);
448            }
449        })
450    }
451
452    pub fn estimate_serialize_size_inner(self) -> usize {
453        iter_fields_ref!(self, it, {
454            it.fold(0, |acc, datum_ref| {
455                acc + estimate_serialize_datum_size(datum_ref)
456            })
457        })
458    }
459}
460
461impl PartialEq for StructRef<'_> {
462    fn eq(&self, other: &Self) -> bool {
463        iter_fields_ref!(*self, lhs, {
464            iter_fields_ref!(*other, rhs, { lhs.eq(rhs) })
465        })
466    }
467}
468
469impl Eq for StructRef<'_> {}
470
471impl PartialOrd for StructRef<'_> {
472    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
473        Some(self.cmp(other))
474    }
475}
476
477impl Ord for StructRef<'_> {
478    fn cmp(&self, other: &Self) -> Ordering {
479        iter_fields_ref!(*self, lhs, {
480            iter_fields_ref!(*other, rhs, {
481                assert_eq!(lhs.len(), rhs.len());
482                lhs.cmp_by(rhs, |lv, rv| lv.default_cmp(&rv))
483            })
484        })
485    }
486}
487
488impl Debug for StructRef<'_> {
489    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
490        let mut is_first = true;
491        iter_fields_ref!(*self, it, {
492            for v in it {
493                if is_first {
494                    write!(f, "{:?}", v)?;
495                    is_first = false;
496                } else {
497                    write!(f, ", {:?}", v)?;
498                }
499            }
500            Ok(())
501        })
502    }
503}
504
505impl ToText for StructRef<'_> {
506    fn write<W: std::fmt::Write>(&self, f: &mut W) -> std::fmt::Result {
507        let mut raw_text = String::new();
508        iter_fields_ref!(*self, it, {
509            write!(f, "(")?;
510            let mut is_first = true;
511            for x in it {
512                if is_first {
513                    is_first = false;
514                } else {
515                    write!(f, ",")?;
516                }
517                // print nothing for null
518                if x.is_some() {
519                    raw_text.clear();
520                    x.write(&mut raw_text)?;
521                    quote_if_need(&raw_text, f)?;
522                }
523            }
524            write!(f, ")")
525        })
526    }
527
528    fn write_with_type<W: std::fmt::Write>(&self, ty: &DataType, f: &mut W) -> std::fmt::Result {
529        match ty {
530            DataType::Struct(_) => self.write(f),
531            _ => unreachable!(),
532        }
533    }
534}
535
536/// A struct value can be treated as a row.
537impl Row for StructRef<'_> {
538    fn datum_at(&self, index: usize) -> DatumRef<'_> {
539        self.field_at(index)
540    }
541
542    unsafe fn datum_at_unchecked(&self, index: usize) -> DatumRef<'_> {
543        unsafe { self.field_at_unchecked(index) }
544    }
545
546    fn len(&self) -> usize {
547        self.iter_fields_ref().len()
548    }
549
550    fn iter(&self) -> impl Iterator<Item = DatumRef<'_>> {
551        self.iter_fields_ref()
552    }
553}
554
555/// Double quote a string if it contains any special characters.
556pub fn quote_if_need(input: &str, writer: &mut impl Write) -> std::fmt::Result {
557    // Note: for struct here, 'null' as a string is not quoted, but for list it's quoted:
558    // ```sql
559    // select row('a','a b','null'), array['a','a b','null'];
560    // ----
561    // (a,"a b",null) {a,"a b","null"}
562    // ```
563    if !input.is_empty() // non-empty
564    && !input.contains(
565        [
566    '"', '\\', ',',
567    // whilespace:
568    // PostgreSQL `array_isspace` includes '\x0B' but rust
569    // [`char::is_ascii_whitespace`] does not.
570    ' ', '\t', '\n', '\r', '\x0B', '\x0C',
571    // struct-specific:
572    '(',')'
573]
574    ) {
575        return writer.write_str(input);
576    }
577
578    writer.write_char('"')?;
579
580    for ch in input.chars() {
581        match ch {
582            '"' => writer.write_str("\"\"")?,
583            '\\' => writer.write_str("\\\\")?,
584            _ => writer.write_char(ch)?,
585        }
586    }
587
588    writer.write_char('"')
589}
590
591#[cfg(test)]
592mod tests {
593    use more_asserts::assert_gt;
594
595    use super::*;
596    use crate::try_match_expand;
597    use crate::types::{F32, F64};
598
599    // Empty struct is allowed in postgres.
600    // `CREATE TYPE foo_empty as ();`, e.g.
601    #[test]
602    fn test_struct_new_empty() {
603        let arr = StructArray::new(StructType::empty(), vec![], Bitmap::ones(0));
604        let actual = StructArray::from_protobuf(&arr.to_protobuf()).unwrap();
605        assert_eq!(ArrayImpl::Struct(arr), actual);
606    }
607
608    #[test]
609    fn test_struct_with_fields() {
610        use crate::array::*;
611        let arr = StructArray::new(
612            StructType::unnamed(vec![DataType::Int32, DataType::Float32]),
613            vec![
614                I32Array::from_iter([None, Some(1), None, Some(2)]).into_ref(),
615                F32Array::from_iter([None, Some(3.0), None, Some(4.0)]).into_ref(),
616            ],
617            [false, true, false, true].into_iter().collect(),
618        );
619        let actual = StructArray::from_protobuf(&arr.to_protobuf()).unwrap();
620        assert_eq!(ArrayImpl::Struct(arr), actual);
621
622        let arr = try_match_expand!(actual, ArrayImpl::Struct).unwrap();
623        let struct_values = arr.values_vec();
624        assert_eq!(
625            struct_values,
626            vec![
627                None,
628                Some(StructValue::new(vec![
629                    Some(ScalarImpl::Int32(1)),
630                    Some(ScalarImpl::Float32(3.0.into())),
631                ])),
632                None,
633                Some(StructValue::new(vec![
634                    Some(ScalarImpl::Int32(2)),
635                    Some(ScalarImpl::Float32(4.0.into())),
636                ])),
637            ]
638        );
639
640        let mut builder = StructArrayBuilder::with_type(
641            4,
642            DataType::Struct(StructType::unnamed(vec![
643                DataType::Int32,
644                DataType::Float32,
645            ])),
646        );
647        for v in &struct_values {
648            builder.append(v.as_ref().map(|s| s.as_scalar_ref()));
649        }
650        let arr = builder.finish();
651        assert_eq!(arr.values_vec(), struct_values);
652    }
653
654    // Ensure `create_builder` exactly copies the same metadata.
655    #[test]
656    fn test_struct_create_builder() {
657        use crate::array::*;
658        let arr = StructArray::new(
659            StructType::unnamed(vec![DataType::Int32, DataType::Float32]),
660            vec![
661                I32Array::from_iter([Some(1)]).into_ref(),
662                F32Array::from_iter([Some(2.0)]).into_ref(),
663            ],
664            Bitmap::ones(1),
665        );
666        let builder = arr.create_builder(4);
667        let arr2 = builder.finish();
668        assert_eq!(arr.data_type(), arr2.data_type());
669    }
670
671    #[test]
672    fn test_struct_value_cmp() {
673        // (1, 2.0) > (1, 1.0)
674        assert_gt!(
675            StructValue::new(vec![Some(1.into()), Some(2.0.into())]),
676            StructValue::new(vec![Some(1.into()), Some(1.0.into())]),
677        );
678        // null > 1
679        assert_gt!(
680            StructValue::new(vec![None]),
681            StructValue::new(vec![Some(1.into())]),
682        );
683        // (1, null, 3) > (1, 1.0, 2)
684        assert_gt!(
685            StructValue::new(vec![Some(1.into()), None, Some(3.into())]),
686            StructValue::new(vec![Some(1.into()), Some(1.0.into()), Some(2.into())]),
687        );
688        // (1, null) == (1, null)
689        assert_eq!(
690            StructValue::new(vec![Some(1.into()), None]),
691            StructValue::new(vec![Some(1.into()), None]),
692        );
693    }
694
695    #[test]
696    fn test_serialize_deserialize() {
697        let value = StructValue::new(vec![
698            Some(F32::from(3.2).to_scalar_value()),
699            Some("abcde".into()),
700            Some(
701                StructValue::new(vec![
702                    Some(F64::from(1.3).to_scalar_value()),
703                    Some("a".into()),
704                    None,
705                    Some(StructValue::new(vec![]).to_scalar_value()),
706                ])
707                .to_scalar_value(),
708            ),
709            None,
710            Some("".into()),
711            None,
712            Some(StructValue::new(vec![]).to_scalar_value()),
713            Some(12345.to_scalar_value()),
714        ]);
715        let fields = [
716            DataType::Float32,
717            DataType::Varchar,
718            StructType::unnamed(vec![
719                DataType::Float64,
720                DataType::Varchar,
721                DataType::Varchar,
722                StructType::unnamed(vec![]).into(),
723            ])
724            .into(),
725            DataType::Int64,
726            DataType::Varchar,
727            DataType::Int16,
728            StructType::unnamed(vec![]).into(),
729            DataType::Int32,
730        ];
731        let struct_ref = StructRef::ValueRef { val: &value };
732        let mut serializer = memcomparable::Serializer::new(vec![]);
733        struct_ref.memcmp_serialize(&mut serializer).unwrap();
734        let buf = serializer.into_inner();
735        let mut deserializer = memcomparable::Deserializer::new(&buf[..]);
736        assert_eq!(
737            StructValue::memcmp_deserialize(&fields, &mut deserializer).unwrap(),
738            value
739        );
740
741        let mut builder = StructArrayBuilder::with_type(
742            0,
743            DataType::Struct(StructType::unnamed(fields.to_vec())),
744        );
745
746        builder.append(Some(struct_ref));
747        let array = builder.finish();
748        let struct_ref = array.value_at(0).unwrap();
749        let mut serializer = memcomparable::Serializer::new(vec![]);
750        struct_ref.memcmp_serialize(&mut serializer).unwrap();
751        let buf = serializer.into_inner();
752        let mut deserializer = memcomparable::Deserializer::new(&buf[..]);
753        assert_eq!(
754            StructValue::memcmp_deserialize(&fields, &mut deserializer).unwrap(),
755            value
756        );
757    }
758
759    #[test]
760    fn test_memcomparable() {
761        let cases = [
762            (
763                StructValue::new(vec![
764                    Some(123.to_scalar_value()),
765                    Some(456i64.to_scalar_value()),
766                ]),
767                StructValue::new(vec![
768                    Some(123.to_scalar_value()),
769                    Some(789i64.to_scalar_value()),
770                ]),
771                vec![DataType::Int32, DataType::Int64],
772                Ordering::Less,
773            ),
774            (
775                StructValue::new(vec![
776                    Some(123.to_scalar_value()),
777                    Some(456i64.to_scalar_value()),
778                ]),
779                StructValue::new(vec![
780                    Some(1.to_scalar_value()),
781                    Some(789i64.to_scalar_value()),
782                ]),
783                vec![DataType::Int32, DataType::Int64],
784                Ordering::Greater,
785            ),
786            (
787                StructValue::new(vec![Some("".into())]),
788                StructValue::new(vec![None]),
789                vec![DataType::Varchar],
790                Ordering::Less,
791            ),
792            (
793                StructValue::new(vec![Some("abcd".into()), None]),
794                StructValue::new(vec![
795                    Some("abcd".into()),
796                    Some(StructValue::new(vec![Some("abcdef".into())]).to_scalar_value()),
797                ]),
798                vec![
799                    DataType::Varchar,
800                    StructType::unnamed(vec![DataType::Varchar]).into(),
801                ],
802                Ordering::Greater,
803            ),
804            (
805                StructValue::new(vec![
806                    Some("abcd".into()),
807                    Some(StructValue::new(vec![Some("abcdef".into())]).to_scalar_value()),
808                ]),
809                StructValue::new(vec![
810                    Some("abcd".into()),
811                    Some(StructValue::new(vec![Some("abcdef".into())]).to_scalar_value()),
812                ]),
813                vec![
814                    DataType::Varchar,
815                    StructType::unnamed(vec![DataType::Varchar]).into(),
816                ],
817                Ordering::Equal,
818            ),
819        ];
820
821        for (lhs, rhs, fields, order) in cases {
822            let lhs_serialized = {
823                let mut serializer = memcomparable::Serializer::new(vec![]);
824                StructRef::ValueRef { val: &lhs }
825                    .memcmp_serialize(&mut serializer)
826                    .unwrap();
827                serializer.into_inner()
828            };
829            let rhs_serialized = {
830                let mut serializer = memcomparable::Serializer::new(vec![]);
831                StructRef::ValueRef { val: &rhs }
832                    .memcmp_serialize(&mut serializer)
833                    .unwrap();
834                serializer.into_inner()
835            };
836            assert_eq!(lhs_serialized.cmp(&rhs_serialized), order);
837
838            let mut builder = StructArrayBuilder::with_type(
839                0,
840                DataType::Struct(StructType::unnamed(fields.to_vec())),
841            );
842            builder.append(Some(StructRef::ValueRef { val: &lhs }));
843            builder.append(Some(StructRef::ValueRef { val: &rhs }));
844            let array = builder.finish();
845            let lhs_serialized = {
846                let mut serializer = memcomparable::Serializer::new(vec![]);
847                array
848                    .value_at(0)
849                    .unwrap()
850                    .memcmp_serialize(&mut serializer)
851                    .unwrap();
852                serializer.into_inner()
853            };
854            let rhs_serialized = {
855                let mut serializer = memcomparable::Serializer::new(vec![]);
856                array
857                    .value_at(1)
858                    .unwrap()
859                    .memcmp_serialize(&mut serializer)
860                    .unwrap();
861                serializer.into_inner()
862            };
863            assert_eq!(lhs_serialized.cmp(&rhs_serialized), order);
864        }
865    }
866
867    #[test]
868    fn test_quote() {
869        #[track_caller]
870        fn test(input: &str, quoted: &str) {
871            let mut actual = String::new();
872            quote_if_need(input, &mut actual).unwrap();
873            assert_eq!(quoted, actual);
874        }
875        test("abc", "abc");
876        test("", r#""""#);
877        test(" x ", r#"" x ""#);
878        test("a b", r#""a b""#);
879        test(r#"a"bc"#, r#""a""bc""#);
880        test(r#"a\bc"#, r#""a\\bc""#);
881        test("{1}", "{1}");
882        test("{1,2}", r#""{1,2}""#);
883        test(r#"{"f": 1}"#, r#""{""f"": 1}""#);
884    }
885}