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