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(array_data.children_type.iter().map(DataType::from));
248        Ok(Self::new(type_, children, bitmap).into())
249    }
250
251    /// Returns an iterator over the field array.
252    pub fn fields(&self) -> impl ExactSizeIterator<Item = &ArrayRef> {
253        self.children.iter()
254    }
255
256    /// Get the field array at the given index.
257    ///
258    /// Panics if the index is out of bounds.
259    pub fn field_at(&self, index: usize) -> &ArrayRef {
260        &self.children[index]
261    }
262
263    /// Get the field array at the given index.
264    ///
265    /// # Safety
266    /// The caller must ensure that the index is within bounds.
267    pub unsafe fn field_at_unchecked(&self, index: usize) -> &ArrayRef {
268        unsafe { self.children.get_unchecked(index) }
269    }
270
271    #[cfg(test)]
272    pub fn values_vec(&self) -> Vec<Option<StructValue>> {
273        use crate::types::ScalarRef;
274
275        self.iter()
276            .map(|v| v.map(|s| s.to_owned_scalar()))
277            .collect_vec()
278    }
279}
280
281impl EstimateSize for StructArray {
282    fn estimated_heap_size(&self) -> usize {
283        self.heap_size
284    }
285}
286
287impl From<DataChunk> for StructArray {
288    fn from(chunk: DataChunk) -> Self {
289        Self::new(
290            StructType::unnamed(chunk.columns().iter().map(|c| c.data_type())),
291            chunk.columns().to_vec(),
292            chunk.visibility().clone(),
293        )
294    }
295}
296
297#[derive(Clone, Debug, PartialEq, Eq, Default, Hash)]
298pub struct StructValue {
299    fields: Box<[Datum]>,
300}
301
302impl PartialOrd for StructValue {
303    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
304        Some(self.cmp(other))
305    }
306}
307
308impl Ord for StructValue {
309    fn cmp(&self, other: &Self) -> Ordering {
310        self.as_scalar_ref().cmp(&other.as_scalar_ref())
311    }
312}
313
314impl EstimateSize for StructValue {
315    fn estimated_heap_size(&self) -> usize {
316        // TODO: Try speed up this process.
317        self.fields
318            .iter()
319            .map(|datum| datum.estimated_heap_size())
320            .sum()
321    }
322}
323
324impl StructValue {
325    pub fn new(fields: Vec<Datum>) -> Self {
326        Self {
327            fields: fields.into_boxed_slice(),
328        }
329    }
330
331    /// Returns an empty struct.
332    pub fn empty() -> Self {
333        Self::new(vec![])
334    }
335
336    pub fn fields(&self) -> &[Datum] {
337        &self.fields
338    }
339
340    pub fn memcmp_deserialize<'a>(
341        fields: impl IntoIterator<Item = &'a DataType>,
342        deserializer: &mut memcomparable::Deserializer<impl Buf>,
343    ) -> memcomparable::Result<Self> {
344        fields
345            .into_iter()
346            .map(|field| memcmp_encoding::deserialize_datum_in_composite(field, deserializer))
347            .try_collect()
348            .map(Self::new)
349    }
350
351    /// Construct a struct from literal string.
352    ///
353    /// # Example
354    ///
355    /// ```
356    /// # use risingwave_common::types::{StructValue, StructType, DataType, ScalarImpl};
357    ///
358    /// let ty = StructType::unnamed(vec![DataType::Int32, DataType::Float64]);
359    /// let s = StructValue::from_str("(1, 2.0)", &ty).unwrap();
360    /// assert_eq!(s.fields()[0], Some(ScalarImpl::Int32(1)));
361    /// assert_eq!(s.fields()[1], Some(ScalarImpl::Float64(2.0.into())));
362    ///
363    /// let s = StructValue::from_str("(,)", &ty).unwrap();
364    /// assert_eq!(s.fields()[0], None);
365    /// assert_eq!(s.fields()[1], None);
366    /// ```
367    pub fn from_str(s: &str, ty: &StructType) -> Result<Self, BoxedError> {
368        // FIXME(runji): this is a trivial implementation which does not support nested struct.
369        if !s.starts_with('(') {
370            return Err("Missing left parenthesis".into());
371        }
372        if !s.ends_with(')') {
373            return Err("Missing right parenthesis".into());
374        }
375        let mut fields = Vec::with_capacity(s.len());
376        for (s, ty) in s[1..s.len() - 1].split(',').zip_eq_debug(ty.types()) {
377            let datum = match s.trim() {
378                "" => None,
379                s => Some(ScalarImpl::from_text(s, ty)?),
380            };
381            fields.push(datum);
382        }
383        Ok(StructValue::new(fields))
384    }
385}
386
387#[derive(Copy, Clone)]
388pub enum StructRef<'a> {
389    Indexed { arr: &'a StructArray, idx: usize },
390    ValueRef { val: &'a StructValue },
391}
392
393impl<'a> StructRef<'a> {
394    /// Iterates over the fields of the struct.
395    ///
396    /// Prefer using the macro `iter_fields_ref!` if possible to avoid the cost of enum dispatching.
397    pub fn iter_fields_ref(self) -> impl ExactSizeIterator<Item = DatumRef<'a>> + 'a {
398        iter_fields_ref!(self, it, { Either::Left(it) }, { Either::Right(it) })
399    }
400
401    /// Get the field at the given index.
402    ///
403    /// Panics if the index is out of bounds.
404    pub fn field_at(&self, i: usize) -> DatumRef<'a> {
405        match self {
406            StructRef::Indexed { arr, idx } => arr.field_at(i).value_at(*idx),
407            StructRef::ValueRef { val } => val.fields[i].to_datum_ref(),
408        }
409    }
410
411    /// Get the field at the given index.
412    ///
413    /// # Safety
414    /// The caller must ensure that the index is within bounds.
415    pub unsafe fn field_at_unchecked(&self, i: usize) -> DatumRef<'a> {
416        unsafe {
417            match self {
418                StructRef::Indexed { arr, idx } => {
419                    arr.field_at_unchecked(i).value_at_unchecked(*idx)
420                }
421                StructRef::ValueRef { val } => val.fields.get_unchecked(i).to_datum_ref(),
422            }
423        }
424    }
425
426    pub fn memcmp_serialize(
427        self,
428        serializer: &mut memcomparable::Serializer<impl BufMut>,
429    ) -> memcomparable::Result<()> {
430        iter_fields_ref!(self, it, {
431            for datum_ref in it {
432                memcmp_encoding::serialize_datum_in_composite(datum_ref, serializer)?
433            }
434            Ok(())
435        })
436    }
437
438    pub fn hash_scalar_inner<H: std::hash::Hasher>(self, state: &mut H) {
439        iter_fields_ref!(self, it, {
440            for datum_ref in it {
441                hash_datum(datum_ref, state);
442            }
443        })
444    }
445
446    pub fn estimate_serialize_size_inner(self) -> usize {
447        iter_fields_ref!(self, it, {
448            it.fold(0, |acc, datum_ref| {
449                acc + estimate_serialize_datum_size(datum_ref)
450            })
451        })
452    }
453}
454
455impl PartialEq for StructRef<'_> {
456    fn eq(&self, other: &Self) -> bool {
457        iter_fields_ref!(*self, lhs, {
458            iter_fields_ref!(*other, rhs, { lhs.eq(rhs) })
459        })
460    }
461}
462
463impl Eq for StructRef<'_> {}
464
465impl PartialOrd for StructRef<'_> {
466    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
467        Some(self.cmp(other))
468    }
469}
470
471impl Ord for StructRef<'_> {
472    fn cmp(&self, other: &Self) -> Ordering {
473        iter_fields_ref!(*self, lhs, {
474            iter_fields_ref!(*other, rhs, {
475                assert_eq!(lhs.len(), rhs.len());
476                lhs.cmp_by(rhs, |lv, rv| lv.default_cmp(&rv))
477            })
478        })
479    }
480}
481
482impl Debug for StructRef<'_> {
483    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
484        let mut is_first = true;
485        iter_fields_ref!(*self, it, {
486            for v in it {
487                if is_first {
488                    write!(f, "{:?}", v)?;
489                    is_first = false;
490                } else {
491                    write!(f, ", {:?}", v)?;
492                }
493            }
494            Ok(())
495        })
496    }
497}
498
499impl ToText for StructRef<'_> {
500    fn write<W: std::fmt::Write>(&self, f: &mut W) -> std::fmt::Result {
501        let mut raw_text = String::new();
502        iter_fields_ref!(*self, it, {
503            write!(f, "(")?;
504            let mut is_first = true;
505            for x in it {
506                if is_first {
507                    is_first = false;
508                } else {
509                    write!(f, ",")?;
510                }
511                // print nothing for null
512                if x.is_some() {
513                    raw_text.clear();
514                    x.write(&mut raw_text)?;
515                    quote_if_need(&raw_text, f)?;
516                }
517            }
518            write!(f, ")")
519        })
520    }
521
522    fn write_with_type<W: std::fmt::Write>(&self, ty: &DataType, f: &mut W) -> std::fmt::Result {
523        match ty {
524            DataType::Struct(_) => self.write(f),
525            _ => unreachable!(),
526        }
527    }
528}
529
530/// A struct value can be treated as a row.
531impl Row for StructRef<'_> {
532    fn datum_at(&self, index: usize) -> DatumRef<'_> {
533        self.field_at(index)
534    }
535
536    unsafe fn datum_at_unchecked(&self, index: usize) -> DatumRef<'_> {
537        unsafe { self.field_at_unchecked(index) }
538    }
539
540    fn len(&self) -> usize {
541        self.iter_fields_ref().len()
542    }
543
544    fn iter(&self) -> impl Iterator<Item = DatumRef<'_>> {
545        self.iter_fields_ref()
546    }
547}
548
549/// Double quote a string if it contains any special characters.
550pub fn quote_if_need(input: &str, writer: &mut impl Write) -> std::fmt::Result {
551    // Note: for struct here, 'null' as a string is not quoted, but for list it's quoted:
552    // ```sql
553    // select row('a','a b','null'), array['a','a b','null'];
554    // ----
555    // (a,"a b",null) {a,"a b","null"}
556    // ```
557    if !input.is_empty() // non-empty
558    && !input.contains(
559        [
560    '"', '\\', ',',
561    // whilespace:
562    // PostgreSQL `array_isspace` includes '\x0B' but rust
563    // [`char::is_ascii_whitespace`] does not.
564    ' ', '\t', '\n', '\r', '\x0B', '\x0C',
565    // struct-specific:
566    '(',')'
567]
568    ) {
569        return writer.write_str(input);
570    }
571
572    writer.write_char('"')?;
573
574    for ch in input.chars() {
575        match ch {
576            '"' => writer.write_str("\"\"")?,
577            '\\' => writer.write_str("\\\\")?,
578            _ => writer.write_char(ch)?,
579        }
580    }
581
582    writer.write_char('"')
583}
584
585#[cfg(test)]
586mod tests {
587    use more_asserts::assert_gt;
588
589    use super::*;
590    use crate::try_match_expand;
591    use crate::types::{F32, F64};
592
593    // Empty struct is allowed in postgres.
594    // `CREATE TYPE foo_empty as ();`, e.g.
595    #[test]
596    fn test_struct_new_empty() {
597        let arr = StructArray::new(StructType::empty(), vec![], Bitmap::ones(0));
598        let actual = StructArray::from_protobuf(&arr.to_protobuf()).unwrap();
599        assert_eq!(ArrayImpl::Struct(arr), actual);
600    }
601
602    #[test]
603    fn test_struct_with_fields() {
604        use crate::array::*;
605        let arr = StructArray::new(
606            StructType::unnamed(vec![DataType::Int32, DataType::Float32]),
607            vec![
608                I32Array::from_iter([None, Some(1), None, Some(2)]).into_ref(),
609                F32Array::from_iter([None, Some(3.0), None, Some(4.0)]).into_ref(),
610            ],
611            [false, true, false, true].into_iter().collect(),
612        );
613        let actual = StructArray::from_protobuf(&arr.to_protobuf()).unwrap();
614        assert_eq!(ArrayImpl::Struct(arr), actual);
615
616        let arr = try_match_expand!(actual, ArrayImpl::Struct).unwrap();
617        let struct_values = arr.values_vec();
618        assert_eq!(
619            struct_values,
620            vec![
621                None,
622                Some(StructValue::new(vec![
623                    Some(ScalarImpl::Int32(1)),
624                    Some(ScalarImpl::Float32(3.0.into())),
625                ])),
626                None,
627                Some(StructValue::new(vec![
628                    Some(ScalarImpl::Int32(2)),
629                    Some(ScalarImpl::Float32(4.0.into())),
630                ])),
631            ]
632        );
633
634        let mut builder = StructArrayBuilder::with_type(
635            4,
636            DataType::Struct(StructType::unnamed(vec![
637                DataType::Int32,
638                DataType::Float32,
639            ])),
640        );
641        for v in &struct_values {
642            builder.append(v.as_ref().map(|s| s.as_scalar_ref()));
643        }
644        let arr = builder.finish();
645        assert_eq!(arr.values_vec(), struct_values);
646    }
647
648    // Ensure `create_builder` exactly copies the same metadata.
649    #[test]
650    fn test_struct_create_builder() {
651        use crate::array::*;
652        let arr = StructArray::new(
653            StructType::unnamed(vec![DataType::Int32, DataType::Float32]),
654            vec![
655                I32Array::from_iter([Some(1)]).into_ref(),
656                F32Array::from_iter([Some(2.0)]).into_ref(),
657            ],
658            Bitmap::ones(1),
659        );
660        let builder = arr.create_builder(4);
661        let arr2 = builder.finish();
662        assert_eq!(arr.data_type(), arr2.data_type());
663    }
664
665    #[test]
666    fn test_struct_value_cmp() {
667        // (1, 2.0) > (1, 1.0)
668        assert_gt!(
669            StructValue::new(vec![Some(1.into()), Some(2.0.into())]),
670            StructValue::new(vec![Some(1.into()), Some(1.0.into())]),
671        );
672        // null > 1
673        assert_gt!(
674            StructValue::new(vec![None]),
675            StructValue::new(vec![Some(1.into())]),
676        );
677        // (1, null, 3) > (1, 1.0, 2)
678        assert_gt!(
679            StructValue::new(vec![Some(1.into()), None, Some(3.into())]),
680            StructValue::new(vec![Some(1.into()), Some(1.0.into()), Some(2.into())]),
681        );
682        // (1, null) == (1, null)
683        assert_eq!(
684            StructValue::new(vec![Some(1.into()), None]),
685            StructValue::new(vec![Some(1.into()), None]),
686        );
687    }
688
689    #[test]
690    fn test_serialize_deserialize() {
691        let value = StructValue::new(vec![
692            Some(F32::from(3.2).to_scalar_value()),
693            Some("abcde".into()),
694            Some(
695                StructValue::new(vec![
696                    Some(F64::from(1.3).to_scalar_value()),
697                    Some("a".into()),
698                    None,
699                    Some(StructValue::new(vec![]).to_scalar_value()),
700                ])
701                .to_scalar_value(),
702            ),
703            None,
704            Some("".into()),
705            None,
706            Some(StructValue::new(vec![]).to_scalar_value()),
707            Some(12345.to_scalar_value()),
708        ]);
709        let fields = [
710            DataType::Float32,
711            DataType::Varchar,
712            StructType::unnamed(vec![
713                DataType::Float64,
714                DataType::Varchar,
715                DataType::Varchar,
716                StructType::unnamed(vec![]).into(),
717            ])
718            .into(),
719            DataType::Int64,
720            DataType::Varchar,
721            DataType::Int16,
722            StructType::unnamed(vec![]).into(),
723            DataType::Int32,
724        ];
725        let struct_ref = StructRef::ValueRef { val: &value };
726        let mut serializer = memcomparable::Serializer::new(vec![]);
727        struct_ref.memcmp_serialize(&mut serializer).unwrap();
728        let buf = serializer.into_inner();
729        let mut deserializer = memcomparable::Deserializer::new(&buf[..]);
730        assert_eq!(
731            StructValue::memcmp_deserialize(&fields, &mut deserializer).unwrap(),
732            value
733        );
734
735        let mut builder = StructArrayBuilder::with_type(
736            0,
737            DataType::Struct(StructType::unnamed(fields.to_vec())),
738        );
739
740        builder.append(Some(struct_ref));
741        let array = builder.finish();
742        let struct_ref = array.value_at(0).unwrap();
743        let mut serializer = memcomparable::Serializer::new(vec![]);
744        struct_ref.memcmp_serialize(&mut serializer).unwrap();
745        let buf = serializer.into_inner();
746        let mut deserializer = memcomparable::Deserializer::new(&buf[..]);
747        assert_eq!(
748            StructValue::memcmp_deserialize(&fields, &mut deserializer).unwrap(),
749            value
750        );
751    }
752
753    #[test]
754    fn test_memcomparable() {
755        let cases = [
756            (
757                StructValue::new(vec![
758                    Some(123.to_scalar_value()),
759                    Some(456i64.to_scalar_value()),
760                ]),
761                StructValue::new(vec![
762                    Some(123.to_scalar_value()),
763                    Some(789i64.to_scalar_value()),
764                ]),
765                vec![DataType::Int32, DataType::Int64],
766                Ordering::Less,
767            ),
768            (
769                StructValue::new(vec![
770                    Some(123.to_scalar_value()),
771                    Some(456i64.to_scalar_value()),
772                ]),
773                StructValue::new(vec![
774                    Some(1.to_scalar_value()),
775                    Some(789i64.to_scalar_value()),
776                ]),
777                vec![DataType::Int32, DataType::Int64],
778                Ordering::Greater,
779            ),
780            (
781                StructValue::new(vec![Some("".into())]),
782                StructValue::new(vec![None]),
783                vec![DataType::Varchar],
784                Ordering::Less,
785            ),
786            (
787                StructValue::new(vec![Some("abcd".into()), None]),
788                StructValue::new(vec![
789                    Some("abcd".into()),
790                    Some(StructValue::new(vec![Some("abcdef".into())]).to_scalar_value()),
791                ]),
792                vec![
793                    DataType::Varchar,
794                    StructType::unnamed(vec![DataType::Varchar]).into(),
795                ],
796                Ordering::Greater,
797            ),
798            (
799                StructValue::new(vec![
800                    Some("abcd".into()),
801                    Some(StructValue::new(vec![Some("abcdef".into())]).to_scalar_value()),
802                ]),
803                StructValue::new(vec![
804                    Some("abcd".into()),
805                    Some(StructValue::new(vec![Some("abcdef".into())]).to_scalar_value()),
806                ]),
807                vec![
808                    DataType::Varchar,
809                    StructType::unnamed(vec![DataType::Varchar]).into(),
810                ],
811                Ordering::Equal,
812            ),
813        ];
814
815        for (lhs, rhs, fields, order) in cases {
816            let lhs_serialized = {
817                let mut serializer = memcomparable::Serializer::new(vec![]);
818                StructRef::ValueRef { val: &lhs }
819                    .memcmp_serialize(&mut serializer)
820                    .unwrap();
821                serializer.into_inner()
822            };
823            let rhs_serialized = {
824                let mut serializer = memcomparable::Serializer::new(vec![]);
825                StructRef::ValueRef { val: &rhs }
826                    .memcmp_serialize(&mut serializer)
827                    .unwrap();
828                serializer.into_inner()
829            };
830            assert_eq!(lhs_serialized.cmp(&rhs_serialized), order);
831
832            let mut builder = StructArrayBuilder::with_type(
833                0,
834                DataType::Struct(StructType::unnamed(fields.clone())),
835            );
836            builder.append(Some(StructRef::ValueRef { val: &lhs }));
837            builder.append(Some(StructRef::ValueRef { val: &rhs }));
838            let array = builder.finish();
839            let lhs_serialized = {
840                let mut serializer = memcomparable::Serializer::new(vec![]);
841                array
842                    .value_at(0)
843                    .unwrap()
844                    .memcmp_serialize(&mut serializer)
845                    .unwrap();
846                serializer.into_inner()
847            };
848            let rhs_serialized = {
849                let mut serializer = memcomparable::Serializer::new(vec![]);
850                array
851                    .value_at(1)
852                    .unwrap()
853                    .memcmp_serialize(&mut serializer)
854                    .unwrap();
855                serializer.into_inner()
856            };
857            assert_eq!(lhs_serialized.cmp(&rhs_serialized), order);
858        }
859    }
860
861    #[test]
862    fn test_quote() {
863        #[track_caller]
864        fn test(input: &str, quoted: &str) {
865            let mut actual = String::new();
866            quote_if_need(input, &mut actual).unwrap();
867            assert_eq!(quoted, actual);
868        }
869        test("abc", "abc");
870        test("", r#""""#);
871        test(" x ", r#"" x ""#);
872        test("a b", r#""a b""#);
873        test(r#"a"bc"#, r#""a""bc""#);
874        test(r#"a\bc"#, r#""a\\bc""#);
875        test("{1}", "{1}");
876        test("{1,2}", r#""{1,2}""#);
877        test(r#"{"f": 1}"#, r#""{""f"": 1}""#);
878    }
879}