1use std::collections::BTreeSet;
16use std::fmt;
17use std::hash::{Hash, Hasher};
18use std::str::FromStr;
19
20use anyhow::{Context, bail};
21use bytes::{Buf, BufMut, Bytes, BytesMut};
22use itertools::Itertools;
23use memcomparable::{Deserializer, Serializer};
24use parquet_variant::{
25 ObjectFieldBuilder, Variant as ParquetVariant, VariantBuilder, VariantBuilderExt,
26 VariantDecimal16,
27};
28use parquet_variant_json::VariantToJson;
29use postgres_types::{FromSql, IsNull, ToSql, Type, accepts, to_sql_checked};
30use risingwave_common_estimate_size::EstimateSize;
31use serde::{Deserialize, Serialize};
32
33use super::jsonb::{JsonbRef, JsonbVal};
34use super::to_binary::ToBinary;
35use super::to_text::ToText;
36use super::{
37 DataType, Decimal, Scalar, ScalarRef, ScalarRefImpl, StructType, scalar_ref_type_match,
38};
39use crate::util::iter_util::ZipEqFast;
40
41const METADATA_LEN_SIZE: usize = size_of::<u32>();
42
43#[derive(Debug, Clone)]
48pub struct VariantVal {
49 data: Box<[u8]>,
50}
51
52#[derive(Debug, Copy, Clone)]
54pub struct VariantRef<'a> {
55 data: &'a [u8],
56}
57
58#[derive(Debug)]
63pub struct VariantPath {
64 tokens: Vec<PathToken>,
65}
66
67impl VariantPath {
68 pub fn parse(path: &str) -> anyhow::Result<Self> {
70 parse_path(path).map(|tokens| Self { tokens })
71 }
72}
73
74impl EstimateSize for VariantVal {
75 fn estimated_heap_size(&self) -> usize {
76 self.data.len()
77 }
78}
79
80impl fmt::Display for VariantVal {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 self.as_scalar_ref().write(f)
83 }
84}
85
86impl fmt::Display for VariantRef<'_> {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 self.write(f)
89 }
90}
91
92impl Scalar for VariantVal {
93 type ScalarRefType<'a> = VariantRef<'a>;
94
95 fn as_scalar_ref(&self) -> Self::ScalarRefType<'_> {
96 VariantRef { data: &self.data }
97 }
98}
99
100impl<'a> ScalarRef<'a> for VariantRef<'a> {
101 type ScalarType = VariantVal;
102
103 fn to_owned_scalar(&self) -> Self::ScalarType {
104 VariantVal {
105 data: self.data.into(),
106 }
107 }
108
109 fn hash_scalar<H: std::hash::Hasher>(&self, state: &mut H) {
110 self.hash(state);
111 }
112}
113
114impl PartialEq for VariantVal {
115 fn eq(&self, other: &Self) -> bool {
116 self.as_scalar_ref() == other.as_scalar_ref()
117 }
118}
119
120impl Eq for VariantVal {}
121
122impl Hash for VariantVal {
123 fn hash<H: Hasher>(&self, state: &mut H) {
124 self.as_scalar_ref().hash(state);
125 }
126}
127
128impl PartialEq for VariantRef<'_> {
129 fn eq(&self, other: &Self) -> bool {
130 self.data == other.data
131 }
132}
133
134impl Eq for VariantRef<'_> {}
135
136impl Hash for VariantRef<'_> {
137 fn hash<H: Hasher>(&self, state: &mut H) {
138 self.data.hash(state);
139 }
140}
141
142impl PartialOrd for VariantVal {
143 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
144 Some(self.cmp(other))
145 }
146}
147
148impl Ord for VariantVal {
149 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
150 self.as_scalar_ref().cmp(&other.as_scalar_ref())
151 }
152}
153
154impl PartialOrd for VariantRef<'_> {
155 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
156 Some(self.cmp(other))
157 }
158}
159
160impl Ord for VariantRef<'_> {
161 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
162 self.data.cmp(other.data)
164 }
165}
166
167impl ToText for VariantRef<'_> {
168 fn write<W: fmt::Write>(&self, f: &mut W) -> fmt::Result {
169 let variant = self.parquet_variant();
170 let json = if contains_non_finite_float(&variant) {
173 variant_to_json_value_lossy(variant)
174 .map_err(|_| fmt::Error)?
175 .to_string()
176 } else {
177 variant.to_json_string().map_err(|_| fmt::Error)?
178 };
179 f.write_str(&json)
180 }
181
182 fn write_with_type<W: fmt::Write>(&self, _ty: &DataType, f: &mut W) -> fmt::Result {
183 self.write(f)
184 }
185}
186
187impl ToBinary for VariantRef<'_> {
188 fn to_binary_with_type(&self, _ty: &DataType) -> super::to_binary::Result<Bytes> {
189 Ok(Bytes::from(self.value_serialize()))
190 }
191}
192
193impl FromStr for VariantVal {
194 type Err = anyhow::Error;
195
196 fn from_str(s: &str) -> Result<Self, Self::Err> {
197 let json = serde_json::Value::from_str(s)?;
198 Self::from_json_value(&json)
199 }
200}
201
202impl VariantVal {
203 pub fn null() -> Self {
204 Self::from_parquet_variant(ParquetVariant::Null).expect("null variant should encode")
205 }
206
207 pub fn from_parts(metadata: &[u8], value: &[u8]) -> anyhow::Result<Self> {
208 let variant =
209 ParquetVariant::try_new(metadata, value).context("invalid variant encoding")?;
210 Self::from_parquet_variant(variant)
211 }
212
213 fn from_canonical_parts(metadata: &[u8], value: &[u8]) -> Self {
214 debug_assert!(
216 ParquetVariant::try_new(metadata, value).is_ok(),
217 "canonical variant parts should be valid"
218 );
219 let metadata_len =
220 u32::try_from(metadata.len()).expect("variant metadata exceeds u32::MAX bytes");
221 let mut data = Vec::with_capacity(METADATA_LEN_SIZE + metadata.len() + value.len());
222 data.put_u32_le(metadata_len);
223 data.extend_from_slice(metadata);
224 data.extend_from_slice(value);
225 Self {
226 data: data.into_boxed_slice(),
227 }
228 }
229
230 pub fn from_parquet_variant(variant: ParquetVariant<'_, '_>) -> anyhow::Result<Self> {
231 let field_names = collect_variant_field_names(variant.clone())?;
232 let mut builder = canonical_builder(&field_names);
233 append_variant_value(variant, &mut builder).context("failed to encode variant")?;
234 let (metadata, value) = builder.finish();
235 Ok(Self::from_canonical_parts(&metadata, &value))
236 }
237
238 pub fn from_json_value(json: &serde_json::Value) -> anyhow::Result<Self> {
239 let mut field_names = BTreeSet::new();
240 collect_json_field_names(json, &mut field_names);
241 let mut builder = canonical_builder(&field_names);
242 append_json_value(json, &mut builder)?;
243 let (metadata, value) = builder.finish();
244 Ok(Self::from_canonical_parts(&metadata, &value))
245 }
246
247 pub fn try_from_scalar_ref(
248 value: Option<ScalarRefImpl<'_>>,
249 data_type: &DataType,
250 ) -> anyhow::Result<Self> {
251 if let Some(ScalarRefImpl::Jsonb(v)) = value
253 && matches!(data_type, DataType::Jsonb)
254 {
255 return Self::from_jsonb(v);
256 }
257 let mut field_names = BTreeSet::new();
258 collect_datum_field_names(value, data_type, &mut field_names)?;
259 let mut builder = canonical_builder(&field_names);
260 append_datum_value(value, data_type, &mut builder)?;
261 let (metadata, value) = builder.finish();
262 Ok(Self::from_canonical_parts(&metadata, &value))
263 }
264
265 pub fn value_deserialize(buf: &[u8]) -> Option<Self> {
269 VariantRef::from_serialized(buf).map(|v| v.to_owned_scalar())
270 }
271
272 pub fn from_serialized_untrusted(buf: &[u8]) -> anyhow::Result<Self> {
276 let (metadata, value) = split_serialized_value(buf).context("invalid variant encoding")?;
277 Self::from_parts(metadata, value)
278 }
279
280 pub fn memcmp_deserialize(
281 deserializer: &mut Deserializer<impl Buf>,
282 ) -> memcomparable::Result<Self> {
283 let bytes = <serde_bytes::ByteBuf as Deserialize>::deserialize(deserializer)?;
284 Self::value_deserialize(&bytes)
285 .ok_or_else(|| memcomparable::Error::Message("invalid variant".into()))
286 }
287
288 pub fn from_jsonb(jsonb: JsonbRef<'_>) -> anyhow::Result<Self> {
289 Self::from_json_value(&jsonb_to_json_value(jsonb)?)
290 }
291
292 pub fn metadata(&self) -> &[u8] {
293 expect_serialized_value(&self.data).0
294 }
295
296 pub fn value(&self) -> &[u8] {
297 expect_serialized_value(&self.data).1
298 }
299
300 pub fn parquet_variant(&self) -> ParquetVariant<'_, '_> {
301 let (metadata, value) = expect_serialized_value(&self.data);
302 ParquetVariant::new(metadata, value)
303 }
304
305 pub fn serialized_len(&self) -> usize {
306 self.data.len()
307 }
308}
309
310impl<'a> VariantRef<'a> {
311 pub fn as_bytes(&self) -> &'a [u8] {
313 debug_assert!(split_serialized_value(self.data).is_some());
314 self.data
315 }
316
317 pub fn value_serialize(&self) -> Vec<u8> {
318 self.as_bytes().to_vec()
319 }
320
321 pub fn memcmp_serialize(
322 &self,
323 serializer: &mut Serializer<impl BufMut>,
324 ) -> memcomparable::Result<()> {
325 Serialize::serialize(&serde_bytes::Bytes::new(self.as_bytes()), serializer)
326 }
327
328 pub fn from_serialized(buf: &'a [u8]) -> Option<Self> {
329 let (metadata, value) = split_serialized_value(buf)?;
330 ParquetVariant::try_new(metadata, value).ok()?;
331 Some(Self { data: buf })
332 }
333
334 pub fn from_serialized_unchecked(buf: &'a [u8]) -> Self {
337 debug_assert!(split_serialized_value(buf).is_some());
338 Self { data: buf }
339 }
340
341 pub fn metadata(&self) -> &'a [u8] {
342 expect_serialized_value(self.data).0
343 }
344
345 pub fn value(&self) -> &'a [u8] {
346 expect_serialized_value(self.data).1
347 }
348
349 pub fn parquet_variant(&self) -> ParquetVariant<'a, 'a> {
350 let (metadata, value) = expect_serialized_value(self.data);
351 ParquetVariant::new(metadata, value)
352 }
353
354 pub fn is_variant_null(&self) -> bool {
355 matches!(self.parquet_variant(), ParquetVariant::Null)
356 }
357
358 pub fn is_array(&self) -> bool {
359 matches!(self.parquet_variant(), ParquetVariant::List(_))
360 }
361
362 pub fn is_object(&self) -> bool {
363 matches!(self.parquet_variant(), ParquetVariant::Object(_))
364 }
365
366 pub fn type_name(&self) -> &'static str {
367 match self.parquet_variant() {
368 ParquetVariant::Null => "null",
369 ParquetVariant::BooleanTrue | ParquetVariant::BooleanFalse => "boolean",
370 ParquetVariant::Int8(_) => "int8",
371 ParquetVariant::Int16(_) => "int16",
372 ParquetVariant::Int32(_) => "int32",
373 ParquetVariant::Int64(_) => "int64",
374 ParquetVariant::Float(_) => "float",
375 ParquetVariant::Double(_) => "double",
376 ParquetVariant::Decimal4(_) => "decimal4",
377 ParquetVariant::Decimal8(_) => "decimal8",
378 ParquetVariant::Decimal16(_) => "decimal16",
379 ParquetVariant::Date(_) => "date",
380 ParquetVariant::TimestampMicros(_) => "timestamp_micros",
381 ParquetVariant::TimestampNtzMicros(_) => "timestamp_ntz_micros",
382 ParquetVariant::TimestampNanos(_) => "timestamp_nanos",
383 ParquetVariant::TimestampNtzNanos(_) => "timestamp_ntz_nanos",
384 ParquetVariant::Binary(_) => "binary",
385 ParquetVariant::String(_) | ParquetVariant::ShortString(_) => "string",
386 ParquetVariant::Time(_) => "time",
387 ParquetVariant::Uuid(_) => "uuid",
388 ParquetVariant::Object(_) => "object",
389 ParquetVariant::List(_) => "array",
390 }
391 }
392
393 pub fn access_path(self, path: &str) -> Option<VariantVal> {
394 self.access_path_strict(path).ok().flatten()
395 }
396
397 pub fn access_path_strict(self, path: &str) -> anyhow::Result<Option<VariantVal>> {
398 self.access_path_parsed(&VariantPath::parse(path)?)
399 }
400
401 pub fn access_path_parsed(self, path: &VariantPath) -> anyhow::Result<Option<VariantVal>> {
403 let mut variant = self.parquet_variant();
406 for token in &path.tokens {
407 let next = match token {
408 PathToken::Field(field) => variant.get_object_field(field),
409 PathToken::Index(index) => match &variant {
412 ParquetVariant::List(list) => {
413 let index = if *index >= 0 {
414 Some(*index as usize)
415 } else {
416 list.len().checked_sub(index.unsigned_abs() as usize)
417 };
418 index.and_then(|index| list.get(index))
419 }
420 _ => None,
421 },
422 };
423 match next {
424 Some(next) => variant = next,
425 None => return Ok(None),
426 }
427 }
428 VariantVal::from_parquet_variant(variant).map(Some)
429 }
430
431 pub fn to_jsonb(self) -> anyhow::Result<JsonbVal> {
432 let json = variant_to_json_value_lossy(self.parquet_variant())
433 .context("failed to convert variant to jsonb")?;
434 Ok(json.into())
435 }
436}
437
438impl From<VariantRef<'_>> for VariantVal {
439 fn from(value: VariantRef<'_>) -> Self {
440 value.to_owned_scalar()
441 }
442}
443
444impl<'a> FromSql<'a> for VariantVal {
445 accepts!(JSON, JSONB);
446
447 fn from_sql(
448 ty: &Type,
449 raw: &'a [u8],
450 ) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
451 Ok(match *ty {
452 Type::JSON => Self::from_str(std::str::from_utf8(raw)?)?,
453 Type::JSONB => {
454 let mut raw = raw;
455 if raw.is_empty() || raw.get_u8() != 1 {
456 return Err("invalid postgres jsonb encoding".into());
457 }
458 Self::from_str(std::str::from_utf8(raw)?)?
459 }
460 _ => {
461 bail_not_implemented!("the VariantVal's postgres decoding for {ty} is unsupported")
462 }
463 })
464 }
465}
466
467impl ToSql for VariantRef<'_> {
468 accepts!(JSON, JSONB);
469
470 to_sql_checked!();
471
472 fn to_sql(
473 &self,
474 ty: &Type,
475 out: &mut BytesMut,
476 ) -> Result<IsNull, Box<dyn std::error::Error + Sync + Send>>
477 where
478 Self: Sized,
479 {
480 if matches!(*ty, Type::JSONB) {
481 out.put_u8(1);
482 }
483 out.extend_from_slice(self.to_text().as_bytes());
484 Ok(IsNull::No)
485 }
486}
487
488fn split_serialized_value(buf: &[u8]) -> Option<(&[u8], &[u8])> {
489 if buf.len() < METADATA_LEN_SIZE {
490 return None;
491 }
492 let metadata_len = u32::from_le_bytes(buf[..METADATA_LEN_SIZE].try_into().unwrap()) as usize;
493 let metadata_end = METADATA_LEN_SIZE.checked_add(metadata_len)?;
494 if metadata_end > buf.len() {
495 return None;
496 }
497 Some((&buf[METADATA_LEN_SIZE..metadata_end], &buf[metadata_end..]))
498}
499
500fn expect_serialized_value(buf: &[u8]) -> (&[u8], &[u8]) {
501 split_serialized_value(buf).expect("variant should use a valid serialized format")
502}
503
504fn canonical_builder(field_names: &BTreeSet<String>) -> VariantBuilder {
505 VariantBuilder::new().with_field_names(field_names.iter().map(String::as_str))
506}
507
508fn jsonb_to_json_value(jsonb: JsonbRef<'_>) -> anyhow::Result<serde_json::Value> {
511 Ok(serde_json::Value::from_str(&jsonb.to_string())?)
512}
513
514fn collect_json_field_names(json: &serde_json::Value, field_names: &mut BTreeSet<String>) {
515 match json {
516 serde_json::Value::Array(values) => {
517 for value in values {
518 collect_json_field_names(value, field_names);
519 }
520 }
521 serde_json::Value::Object(fields) => {
522 for (field, value) in fields {
523 field_names.insert(field.clone());
524 collect_json_field_names(value, field_names);
525 }
526 }
527 _ => {}
528 }
529}
530
531fn collect_variant_field_names(
532 variant: ParquetVariant<'_, '_>,
533) -> anyhow::Result<BTreeSet<String>> {
534 let mut field_names = BTreeSet::new();
535 collect_variant_field_names_inner(variant, &mut field_names)?;
536 Ok(field_names)
537}
538
539fn collect_variant_field_names_inner(
541 variant: ParquetVariant<'_, '_>,
542 field_names: &mut BTreeSet<String>,
543) -> anyhow::Result<()> {
544 match variant {
545 ParquetVariant::Object(object) => {
546 for field in object.iter_try() {
547 let (field_name, value) = field.context("failed to read variant object")?;
548 field_names.insert(field_name.to_owned());
549 collect_variant_field_names_inner(value, field_names)?;
550 }
551 }
552 ParquetVariant::List(list) => {
553 for value in list.iter_try() {
554 collect_variant_field_names_inner(
555 value.context("failed to read variant list")?,
556 field_names,
557 )?;
558 }
559 }
560 _ => {}
561 }
562 Ok(())
563}
564
565fn collect_datum_field_names(
566 value: Option<ScalarRefImpl<'_>>,
567 data_type: &DataType,
568 field_names: &mut BTreeSet<String>,
569) -> anyhow::Result<()> {
570 let Some(value) = value else {
571 return Ok(());
572 };
573
574 match (value, data_type) {
575 (ScalarRefImpl::Jsonb(v), _) => {
576 collect_json_field_names(&jsonb_to_json_value(v)?, field_names);
577 }
578 (ScalarRefImpl::Variant(v), _) => {
579 collect_variant_field_names_inner(v.parquet_variant(), field_names)?;
580 }
581 (ScalarRefImpl::List(v), DataType::List(list_type)) => {
582 for value in v.iter() {
583 collect_datum_field_names(value, list_type.elem(), field_names)?;
584 }
585 }
586 (ScalarRefImpl::Struct(v), DataType::Struct(struct_type)) => {
587 for (value, (field_name, field_type)) in
588 v.iter_fields_ref().zip_eq_fast(struct_type.iter())
589 {
590 field_names.insert(field_name.to_owned());
591 collect_datum_field_names(value, field_type, field_names)?;
592 }
593 }
594 (ScalarRefImpl::Map(v), DataType::Map(map_type)) => {
595 for (key, value) in v.iter() {
596 let field = key.to_text_with_type(map_type.key());
597 field_names.insert(field);
598 collect_datum_field_names(value, map_type.value(), field_names)?;
599 }
600 }
601 (
604 ScalarRefImpl::Bool(_)
605 | ScalarRefImpl::Int16(_)
606 | ScalarRefImpl::Int32(_)
607 | ScalarRefImpl::Int64(_)
608 | ScalarRefImpl::Int256(_)
609 | ScalarRefImpl::Serial(_)
610 | ScalarRefImpl::Float32(_)
611 | ScalarRefImpl::Float64(_)
612 | ScalarRefImpl::Decimal(_)
613 | ScalarRefImpl::Utf8(_)
614 | ScalarRefImpl::Bytea(_)
615 | ScalarRefImpl::Date(_)
616 | ScalarRefImpl::Time(_)
617 | ScalarRefImpl::Timestamp(_)
618 | ScalarRefImpl::Timestamptz(_)
619 | ScalarRefImpl::Interval(_)
620 | ScalarRefImpl::Vector(_)
621 | ScalarRefImpl::List(_)
622 | ScalarRefImpl::Struct(_)
623 | ScalarRefImpl::Map(_),
624 _,
625 ) => {}
626 }
627 Ok(())
628}
629
630fn append_json_value(
631 json: &serde_json::Value,
632 builder: &mut impl VariantBuilderExt,
633) -> anyhow::Result<()> {
634 match json {
635 serde_json::Value::Null => builder.append_value(ParquetVariant::Null),
636 serde_json::Value::Bool(v) => builder.append_value(*v),
637 serde_json::Value::Number(v) => {
638 if let Some(v) = v.as_i64() {
639 builder.append_value(v);
640 } else if let Some(v) = v.as_u64() {
641 builder.append_value(v);
642 } else if let Some(v) = v.as_f64() {
643 append_float64(v, builder);
644 } else {
645 bail!("unsupported JSON number: {v}");
646 }
647 }
648 serde_json::Value::String(v) => builder.append_value(v.as_str()),
649 serde_json::Value::Array(values) => {
650 let mut list = builder
651 .try_new_list()
652 .context("failed to create variant list")?;
653 for value in values {
654 append_json_value(value, &mut list)?;
655 }
656 list.finish();
657 }
658 serde_json::Value::Object(fields) => {
659 let mut object = builder
660 .try_new_object()
661 .context("failed to create variant object")?;
662 for (field, value) in fields.iter().sorted_by(|a, b| a.0.cmp(b.0)) {
663 let mut field_builder = ObjectFieldBuilder::new(field.as_str(), &mut object);
664 append_json_value(value, &mut field_builder)?;
665 }
666 object.finish();
667 }
668 }
669 Ok(())
670}
671
672fn append_datum_value(
673 value: Option<ScalarRefImpl<'_>>,
674 data_type: &DataType,
675 builder: &mut impl VariantBuilderExt,
676) -> anyhow::Result<()> {
677 let Some(value) = value else {
678 builder.append_value(ParquetVariant::Null);
679 return Ok(());
680 };
681 assert!(
682 scalar_ref_type_match(data_type, value),
683 "variant conversion input {} does not match {data_type}",
684 value.get_ident()
685 );
686
687 match (value, data_type) {
690 (ScalarRefImpl::Bool(v), _) => builder.append_value(v),
691 (ScalarRefImpl::Int16(v), _) => builder.append_value(v),
692 (ScalarRefImpl::Int32(v), _) => builder.append_value(v),
693 (ScalarRefImpl::Int64(v), _) => builder.append_value(v),
694 (ScalarRefImpl::Serial(v), _) => builder.append_value(v.into_inner()),
695 (ScalarRefImpl::Float32(v), _) => append_float64(f64::from(v.into_inner()), builder),
696 (ScalarRefImpl::Float64(v), _) => append_float64(v.into_inner(), builder),
697 (ScalarRefImpl::Decimal(v), _) => append_decimal(v, builder)?,
698 (ScalarRefImpl::Utf8(v), _) => builder.append_value(v),
699 (ScalarRefImpl::Bytea(v), _) => builder.append_value(v),
700 (ScalarRefImpl::Date(v), _) => builder.append_value(v.0),
701 (ScalarRefImpl::Time(v), _) => builder.append_value(v.0),
702 (ScalarRefImpl::Timestamp(v), _) => builder.append_value(v.0),
703 (ScalarRefImpl::Timestamptz(v), _) => builder.append_value(v.to_datetime_utc()),
704 (ScalarRefImpl::Jsonb(v), _) => append_json_value(&jsonb_to_json_value(v)?, builder)?,
705 (ScalarRefImpl::Variant(v), _) => builder.append_value(v.parquet_variant()),
706 (ScalarRefImpl::Int256(v), _) => builder.append_value(v.to_text().as_str()),
708 (ScalarRefImpl::Interval(v), _) => builder.append_value(v.to_text().as_str()),
709 (ScalarRefImpl::Vector(v), _) => builder.append_value(v.to_text().as_str()),
710 (ScalarRefImpl::List(v), DataType::List(list_type)) => {
711 let mut list = builder
712 .try_new_list()
713 .context("failed to create variant list")?;
714 for value in v.iter() {
715 append_datum_value(value, list_type.elem(), &mut list)?;
716 }
717 list.finish();
718 }
719 (ScalarRefImpl::Struct(v), DataType::Struct(struct_type)) => {
720 append_struct(v, struct_type, builder)?;
721 }
722 (ScalarRefImpl::Map(v), DataType::Map(map_type)) => {
723 let mut object = builder
724 .try_new_object()
725 .context("failed to create variant map object")?;
726 let entries = v
727 .iter()
728 .map(|(key, value)| {
729 let field = key.to_text_with_type(map_type.key());
730 (field, value)
731 })
732 .sorted_by(|a, b| a.0.cmp(&b.0))
733 .collect_vec();
734 for (field, value) in entries {
735 let mut field_builder = ObjectFieldBuilder::new(field.as_str(), &mut object);
736 append_datum_value(value, map_type.value(), &mut field_builder)?;
737 }
738 object.finish();
739 }
740 (value, ty) => bail!("cannot convert {} as {ty} to variant", value.get_ident()),
741 }
742 Ok(())
743}
744
745fn reject_duplicate_field(previous: Option<&str>, field_name: &str) -> anyhow::Result<()> {
748 if previous == Some(field_name) {
749 bail!("variant object cannot have duplicate field name `{field_name}`");
750 }
751 Ok(())
752}
753
754fn append_struct(
755 value: super::StructRef<'_>,
756 struct_type: &StructType,
757 builder: &mut impl VariantBuilderExt,
758) -> anyhow::Result<()> {
759 let mut object = builder
760 .try_new_object()
761 .context("failed to create variant struct object")?;
762 let fields = value
763 .iter_fields_ref()
764 .zip_eq_fast(struct_type.iter())
765 .sorted_by(|(_, (field_a, _)), (_, (field_b, _))| field_a.cmp(field_b));
766 let mut previous_field_name = None;
767 for (value, (field_name, field_type)) in fields {
768 reject_duplicate_field(previous_field_name, field_name)?;
769 previous_field_name = Some(field_name);
770 let mut field_builder = ObjectFieldBuilder::new(field_name, &mut object);
771 append_datum_value(value, field_type, &mut field_builder)?;
772 }
773 object.finish();
774 Ok(())
775}
776
777const CANONICAL_NAN_F32: u32 = 0x7fc0_0000;
781const CANONICAL_NAN_F64: u64 = 0x7ff8_0000_0000_0000;
782
783fn normalize_float(value: f32) -> f32 {
786 if value.is_nan() {
787 f32::from_bits(CANONICAL_NAN_F32)
788 } else if value == 0.0 {
789 0.0
790 } else {
791 value
792 }
793}
794
795fn normalize_double(value: f64) -> f64 {
797 if value.is_nan() {
798 f64::from_bits(CANONICAL_NAN_F64)
799 } else if value == 0.0 {
800 0.0
801 } else {
802 value
803 }
804}
805
806fn append_float64(value: f64, builder: &mut impl VariantBuilderExt) {
807 builder.append_value(normalize_double(value));
808}
809
810fn append_variant_value(
813 variant: ParquetVariant<'_, '_>,
814 builder: &mut impl VariantBuilderExt,
815) -> anyhow::Result<()> {
816 match variant {
817 ParquetVariant::Object(object) => {
818 let mut object_builder = builder
819 .try_new_object()
820 .context("failed to create variant object")?;
821 let mut previous_field_name = None;
822 for field in object.iter_try() {
823 let (field_name, value) = field.context("failed to read variant object")?;
824 reject_duplicate_field(previous_field_name, field_name)?;
825 previous_field_name = Some(field_name);
826 let mut field_builder = ObjectFieldBuilder::new(field_name, &mut object_builder);
827 append_variant_value(value, &mut field_builder)?;
828 }
829 object_builder.finish();
830 }
831 ParquetVariant::List(list) => {
832 let mut list_builder = builder
833 .try_new_list()
834 .context("failed to create variant list")?;
835 for value in list.iter_try() {
836 append_variant_value(
837 value.context("failed to read variant list")?,
838 &mut list_builder,
839 )?;
840 }
841 list_builder.finish();
842 }
843 ParquetVariant::Float(v) => builder.append_value(normalize_float(v)),
844 ParquetVariant::Double(v) => append_float64(v, builder),
845 other => builder.append_value(other),
846 }
847 Ok(())
848}
849
850fn contains_non_finite_float(variant: &ParquetVariant<'_, '_>) -> bool {
853 match variant {
854 ParquetVariant::Object(object) => object.iter_try().any(|field| match field {
855 Ok((_, value)) => contains_non_finite_float(&value),
856 Err(_) => true,
857 }),
858 ParquetVariant::List(list) => list.iter_try().any(|value| match value {
859 Ok(value) => contains_non_finite_float(&value),
860 Err(_) => true,
861 }),
862 ParquetVariant::Float(v) => !v.is_finite(),
863 ParquetVariant::Double(v) => !v.is_finite(),
864 _ => false,
865 }
866}
867
868fn variant_to_json_value_lossy(
871 variant: ParquetVariant<'_, '_>,
872) -> anyhow::Result<serde_json::Value> {
873 Ok(match variant {
874 ParquetVariant::Object(object) => {
875 let mut fields = serde_json::Map::new();
876 for field in object.iter_try() {
877 let (field_name, value) = field.context("failed to read variant object")?;
878 fields.insert(field_name.to_owned(), variant_to_json_value_lossy(value)?);
879 }
880 serde_json::Value::Object(fields)
881 }
882 ParquetVariant::List(list) => serde_json::Value::Array(
883 list.iter_try()
884 .map(|value| {
885 variant_to_json_value_lossy(value.context("failed to read variant list")?)
886 })
887 .collect::<anyhow::Result<Vec<_>>>()?,
888 ),
889 ParquetVariant::Float(v) if !v.is_finite() => non_finite_to_json(f64::from(v)),
890 ParquetVariant::Double(v) if !v.is_finite() => non_finite_to_json(v),
891 other => other
892 .to_json_value()
893 .context("failed to convert variant to json")?,
894 })
895}
896
897fn non_finite_to_json(value: f64) -> serde_json::Value {
898 let s = if value.is_nan() {
899 "NaN"
900 } else if value == f64::INFINITY {
901 "Infinity"
902 } else {
903 "-Infinity"
904 };
905 serde_json::Value::String(s.to_owned())
906}
907
908fn append_decimal(value: Decimal, builder: &mut impl VariantBuilderExt) -> anyhow::Result<()> {
909 match value {
910 Decimal::Normalized(value) => {
911 let value = value.normalize();
912 let decimal = VariantDecimal16::try_new(value.mantissa(), value.scale() as u8)
913 .context("failed to encode decimal as variant")?;
914 builder.append_value(decimal);
915 }
916 Decimal::NaN | Decimal::PositiveInf | Decimal::NegativeInf => {
917 builder.append_value(value.to_text().as_str());
918 }
919 }
920 Ok(())
921}
922
923#[derive(Debug)]
924enum PathToken {
925 Field(String),
926 Index(i32),
927}
928
929fn parse_path(path: &str) -> anyhow::Result<Vec<PathToken>> {
930 let original_path = path;
931 let path = path.strip_prefix('$').unwrap_or(path);
932 let mut chars = path.chars().peekable();
933 let mut tokens = vec![];
934 while let Some(ch) = chars.next() {
935 match ch {
936 '.' => {
937 let mut field = String::new();
938 while let Some(&c) = chars.peek() {
939 if c == '.' || c == '[' {
940 break;
941 }
942 field.push(c);
943 chars.next();
944 }
945 if field.is_empty() {
946 bail!("invalid variant path `{original_path}`");
947 }
948 tokens.push(PathToken::Field(field));
949 }
950 '[' => {
951 if matches!(chars.peek(), Some('\'') | Some('"')) {
952 let quote = chars.next().unwrap();
953 let mut field = String::new();
954 let mut closed = false;
955 for c in chars.by_ref() {
956 if c == quote {
957 closed = true;
958 break;
959 }
960 field.push(c);
961 }
962 if !closed || chars.next() != Some(']') {
963 bail!("invalid variant path `{original_path}`");
964 }
965 tokens.push(PathToken::Field(field));
966 } else {
967 let mut index = String::new();
968 while let Some(&c) = chars.peek() {
969 if c == ']' {
970 break;
971 }
972 index.push(c);
973 chars.next();
974 }
975 if chars.next() != Some(']') {
976 bail!("invalid variant path `{original_path}`");
977 }
978 tokens.push(PathToken::Index(index.parse().with_context(|| {
979 format!("invalid variant path `{original_path}`")
980 })?));
981 }
982 }
983 _ if tokens.is_empty() => {
984 let mut field = String::from(ch);
985 while let Some(&c) = chars.peek() {
986 if c == '.' || c == '[' {
987 break;
988 }
989 field.push(c);
990 chars.next();
991 }
992 tokens.push(PathToken::Field(field));
993 }
994 _ => bail!("invalid variant path `{original_path}`"),
995 }
996 }
997 Ok(tokens)
998}
999
1000#[cfg(test)]
1001mod tests {
1002 use super::*;
1003 use crate::array::StructValue;
1004 use crate::types::{Date, F32, F64, Int256, Interval, Serial, Time, Timestamptz};
1005
1006 fn scalar_variant(value: ScalarRefImpl<'_>, data_type: &DataType) -> VariantVal {
1007 VariantVal::try_from_scalar_ref(Some(value), data_type).unwrap()
1008 }
1009
1010 fn assert_same_variant(lhs: &VariantVal, rhs: &VariantVal) {
1011 assert_eq!(lhs, rhs);
1012 assert_eq!(
1013 lhs.as_scalar_ref().value_serialize(),
1014 rhs.as_scalar_ref().value_serialize()
1015 );
1016 }
1017
1018 fn assert_variant_parts(
1019 name: &str,
1020 variant: &VariantVal,
1021 expected_metadata_hex: &str,
1022 expected_value_hex: &str,
1023 ) {
1024 assert_eq!(
1025 hex::encode(variant.metadata()),
1026 expected_metadata_hex,
1027 "{name} metadata bytes changed"
1028 );
1029 assert_eq!(
1030 hex::encode(variant.value()),
1031 expected_value_hex,
1032 "{name} value bytes changed"
1033 );
1034 }
1035
1036 #[test]
1037 fn access_path_with_preparsed_path() {
1038 let v: VariantVal = r#"{"a":[{"b":7}]}"#.parse().unwrap();
1039 let path = VariantPath::parse("$.a[0].b").unwrap();
1040 assert_eq!(
1041 v.as_scalar_ref()
1042 .access_path_parsed(&path)
1043 .unwrap()
1044 .unwrap()
1045 .to_string(),
1046 "7"
1047 );
1048 }
1049
1050 #[test]
1051 fn path_access_supports_dot_and_bracket() {
1052 let v: VariantVal = r#"{"a":[{"b":7}]}"#.parse().unwrap();
1053 assert_eq!(
1054 v.as_scalar_ref()
1055 .access_path("$.a[0].b")
1056 .unwrap()
1057 .to_string(),
1058 "7"
1059 );
1060 assert_eq!(
1061 v.as_scalar_ref()
1062 .access_path("a[0]['b']")
1063 .unwrap()
1064 .to_string(),
1065 "7"
1066 );
1067 assert_eq!(
1068 v.as_scalar_ref()
1069 .access_path("$.a[-1].b")
1070 .unwrap()
1071 .to_string(),
1072 "7"
1073 );
1074 assert!(v.as_scalar_ref().access_path("$.a[-2]").is_none());
1075 assert!(v.as_scalar_ref().access_path("$.a[0].b[0]").is_none());
1076 assert!(
1077 v.as_scalar_ref()
1078 .access_path_strict("$.missing")
1079 .unwrap()
1080 .is_none()
1081 );
1082 assert!(v.as_scalar_ref().access_path_strict("$.").is_err());
1083 assert!(v.as_scalar_ref().access_path("$.").is_none());
1084 }
1085
1086 #[test]
1087 fn ord_matches_memcmp_encoding_order() {
1088 fn memcmp_encode(v: &VariantVal) -> Vec<u8> {
1089 let mut serializer = Serializer::new(vec![]);
1090 v.as_scalar_ref().memcmp_serialize(&mut serializer).unwrap();
1091 serializer.into_inner()
1092 }
1093
1094 let mut values: Vec<VariantVal> = [
1096 "1",
1097 r#""short""#,
1098 r#"{"b":1,"c":1}"#,
1099 r#"{"aaaaaaaaaa":1}"#,
1100 r#"{"a":1}"#,
1101 "[1,2,3]",
1102 ]
1103 .iter()
1104 .map(|s| s.parse().unwrap())
1105 .collect();
1106 for f in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY] {
1107 values.push(
1108 VariantVal::try_from_scalar_ref(
1109 Some(ScalarRefImpl::Float64(F64::from(f))),
1110 &DataType::Float64,
1111 )
1112 .unwrap(),
1113 );
1114 }
1115 for a in &values {
1116 for b in &values {
1117 assert_eq!(
1118 a.cmp(b),
1119 memcmp_encode(a).cmp(&memcmp_encode(b)),
1120 "Ord and memcmp encoding disagree for {a} vs {b}"
1121 );
1122 }
1123 }
1124 }
1125
1126 #[test]
1127 fn deep_jsonb_to_variant_returns_error() {
1128 let shallow = JsonbVal::from(serde_json::Value::from(1));
1129 assert!(VariantVal::from_jsonb(shallow.as_scalar_ref()).is_ok());
1130
1131 let mut json = serde_json::Value::from(1);
1133 for _ in 0..200 {
1134 json = serde_json::Value::Array(vec![json]);
1135 }
1136 let deep = JsonbVal::from(json);
1137 assert!(VariantVal::from_jsonb(deep.as_scalar_ref()).is_err());
1138 }
1139
1140 #[test]
1141 fn normalizes_non_finite_floats_to_canonical_bit_patterns() {
1142 let from_double_bits = |bits: u64| {
1143 let mut builder = VariantBuilder::new();
1144 builder.append_value(f64::from_bits(bits));
1145 let (metadata, value) = builder.finish();
1146 VariantVal::from_parts(&metadata, &value).unwrap()
1147 };
1148
1149 let canonical_nan = from_double_bits(CANONICAL_NAN_F64);
1151 assert_same_variant(&canonical_nan, &from_double_bits(0xfff8_0000_0000_0001));
1152 assert_same_variant(&canonical_nan, &from_double_bits(0x7ff0_0000_0000_0001));
1153
1154 let nan = canonical_nan.as_scalar_ref();
1155 assert_eq!(nan.type_name(), "double");
1156 assert_eq!(nan.to_text(), r#""NaN""#);
1157 assert_eq!(nan.to_jsonb().unwrap().to_string(), r#""NaN""#);
1158
1159 let inf = from_double_bits(f64::INFINITY.to_bits());
1161 assert_eq!(inf.as_scalar_ref().type_name(), "double");
1162 assert_eq!(inf.as_scalar_ref().to_text(), r#""Infinity""#);
1163 assert_eq!(
1164 from_double_bits(f64::NEG_INFINITY.to_bits())
1165 .as_scalar_ref()
1166 .to_text(),
1167 r#""-Infinity""#
1168 );
1169
1170 assert_same_variant(
1172 &from_double_bits((-0.0_f64).to_bits()),
1173 &from_double_bits(0.0_f64.to_bits()),
1174 );
1175
1176 let from_float_bits = |bits: u32| {
1178 let mut builder = VariantBuilder::new();
1179 builder.append_value(f32::from_bits(bits));
1180 let (metadata, value) = builder.finish();
1181 VariantVal::from_parts(&metadata, &value).unwrap()
1182 };
1183 let float_nan = from_float_bits(0xffc0_0001);
1184 assert_same_variant(&float_nan, &from_float_bits(CANONICAL_NAN_F32));
1185 assert_eq!(float_nan.as_scalar_ref().type_name(), "float");
1186 assert_eq!(float_nan.as_scalar_ref().to_text(), r#""NaN""#);
1187
1188 let mut builder = VariantBuilder::new();
1190 builder.add_field_name("x");
1191 let mut object = builder.new_object();
1192 object.insert("x", f64::NAN);
1193 object.finish();
1194 let (metadata, value) = builder.finish();
1195 let nested = VariantVal::from_parts(&metadata, &value).unwrap();
1196 assert_eq!(nested.as_scalar_ref().to_text(), r#"{"x":"NaN"}"#);
1197 }
1198
1199 #[test]
1200 fn untrusted_serialized_canonicalizes_non_finite_double() {
1201 let mut builder = VariantBuilder::new();
1202 builder.append_value(f64::from_bits(0xfff8_0000_0000_0001));
1203 let (metadata, value) = builder.finish();
1204 let bytes = VariantVal::from_canonical_parts(&metadata, &value)
1205 .as_scalar_ref()
1206 .value_serialize();
1207
1208 let canonicalized = VariantVal::from_serialized_untrusted(&bytes).unwrap();
1209 assert_eq!(canonicalized.as_scalar_ref().to_text(), r#""NaN""#);
1210 assert_ne!(bytes, canonicalized.as_scalar_ref().value_serialize());
1212 assert!(VariantVal::value_deserialize(&bytes).is_some());
1214 }
1215
1216 #[test]
1217 fn untrusted_serialized_canonicalizes_unsorted_dictionary() {
1218 let mut builder = VariantBuilder::new();
1220 builder.add_field_name("b");
1221 builder.add_field_name("a");
1222 let mut object = builder.new_object();
1223 object.insert("a", 1i64);
1224 object.insert("b", 2i64);
1225 object.finish();
1226 let (metadata, value) = builder.finish();
1227 let non_canonical = VariantVal::from_canonical_parts(&metadata, &value)
1228 .as_scalar_ref()
1229 .value_serialize();
1230
1231 let canonical: VariantVal = r#"{"a":1,"b":2}"#.parse().unwrap();
1232 let canonical_bytes = canonical.as_scalar_ref().value_serialize();
1233
1234 assert_ne!(non_canonical, canonical_bytes);
1235 let recanonicalized = VariantVal::from_serialized_untrusted(&non_canonical).unwrap();
1236 assert_same_variant(&recanonicalized, &canonical);
1237 }
1238
1239 #[test]
1240 fn maps_numeric_scalars_to_variant_types() {
1241 let json_int: VariantVal = "1".parse().unwrap();
1242 let int16 =
1243 VariantVal::try_from_scalar_ref(Some(ScalarRefImpl::Int16(1)), &DataType::Int16)
1244 .unwrap();
1245 let int32 =
1246 VariantVal::try_from_scalar_ref(Some(ScalarRefImpl::Int32(1)), &DataType::Int32)
1247 .unwrap();
1248 let int64 =
1249 VariantVal::try_from_scalar_ref(Some(ScalarRefImpl::Int64(1)), &DataType::Int64)
1250 .unwrap();
1251 let serial = VariantVal::try_from_scalar_ref(
1252 Some(ScalarRefImpl::Serial(Serial::from(1))),
1253 &DataType::Serial,
1254 )
1255 .unwrap();
1256
1257 assert_eq!(json_int.as_scalar_ref().type_name(), "int64");
1258 assert_eq!(int16.as_scalar_ref().type_name(), "int16");
1259 assert_eq!(int32.as_scalar_ref().type_name(), "int32");
1260 assert_eq!(int64.as_scalar_ref().type_name(), "int64");
1261 assert_ne!(json_int, int16);
1262 assert_ne!(json_int, int32);
1263 assert_same_variant(&json_int, &int64);
1264 assert_same_variant(&json_int, &serial);
1265
1266 let json_float: VariantVal = "1.5".parse().unwrap();
1267 let float32 = VariantVal::try_from_scalar_ref(
1268 Some(ScalarRefImpl::Float32(F32::from(1.5))),
1269 &DataType::Float32,
1270 )
1271 .unwrap();
1272 let float64 = VariantVal::try_from_scalar_ref(
1273 Some(ScalarRefImpl::Float64(F64::from(1.5))),
1274 &DataType::Float64,
1275 )
1276 .unwrap();
1277
1278 assert_eq!(json_float.as_scalar_ref().type_name(), "double");
1279 assert_same_variant(&json_float, &float32);
1280 assert_same_variant(&json_float, &float64);
1281
1282 let positive_zero: VariantVal = "0.0".parse().unwrap();
1283 let negative_zero = VariantVal::try_from_scalar_ref(
1284 Some(ScalarRefImpl::Float64(F64::from(-0.0))),
1285 &DataType::Float64,
1286 )
1287 .unwrap();
1288 assert_same_variant(&positive_zero, &negative_zero);
1289
1290 let sql_nan = VariantVal::try_from_scalar_ref(
1292 Some(ScalarRefImpl::Float64(F64::from(f64::NAN))),
1293 &DataType::Float64,
1294 )
1295 .unwrap();
1296 assert_eq!(sql_nan.as_scalar_ref().type_name(), "double");
1297 assert_eq!(sql_nan.as_scalar_ref().to_text(), r#""NaN""#);
1298 }
1299
1300 #[test]
1301 fn stores_sql_only_scalars_as_text() {
1302 let interval = Interval::from_month_day_usec(1, 2, 3);
1303 let text = interval.to_text();
1304 assert_same_variant(
1305 &scalar_variant(ScalarRefImpl::Interval(interval), &DataType::Interval),
1306 &scalar_variant(ScalarRefImpl::Utf8(&text), &DataType::Varchar),
1307 );
1308
1309 let int256 = Int256::from(1);
1310 let text = int256.as_scalar_ref().to_text();
1311 assert_same_variant(
1312 &scalar_variant(int256.as_scalar_ref().into(), &DataType::Int256),
1313 &scalar_variant(ScalarRefImpl::Utf8(&text), &DataType::Varchar),
1314 );
1315 }
1316
1317 #[test]
1318 fn maps_temporal_scalars_to_variant_temporal_types() {
1319 let date = VariantVal::try_from_scalar_ref(
1320 Some(ScalarRefImpl::Date(Date::from_ymd_uncheck(2024, 1, 2))),
1321 &DataType::Date,
1322 )
1323 .unwrap();
1324 let time = VariantVal::try_from_scalar_ref(
1325 Some(ScalarRefImpl::Time(Time::from_hms_micro_uncheck(
1326 3, 4, 5, 6000,
1327 ))),
1328 &DataType::Time,
1329 )
1330 .unwrap();
1331 let timestamp = VariantVal::try_from_scalar_ref(
1332 Some(ScalarRefImpl::Timestamp(
1333 Date::from_ymd_uncheck(2024, 1, 2).and_hms_micro_uncheck(3, 4, 5, 6000),
1334 )),
1335 &DataType::Timestamp,
1336 )
1337 .unwrap();
1338 let timestamptz = VariantVal::try_from_scalar_ref(
1339 Some(ScalarRefImpl::Timestamptz(
1340 Timestamptz::from_micros(1).unwrap(),
1341 )),
1342 &DataType::Timestamptz,
1343 )
1344 .unwrap();
1345
1346 assert_eq!(date.as_scalar_ref().type_name(), "date");
1347 assert_eq!(time.as_scalar_ref().type_name(), "time");
1348 assert_eq!(
1349 timestamp.as_scalar_ref().type_name(),
1350 "timestamp_ntz_micros"
1351 );
1352 assert_eq!(timestamptz.as_scalar_ref().type_name(), "timestamp_micros");
1353 }
1354
1355 #[test]
1356 fn canonicalizes_object_fields_across_construction_paths() {
1357 let json: VariantVal = r#"{"a":1,"c":2}"#.parse().unwrap();
1358 let struct_type = DataType::Struct(StructType::new(vec![
1359 ("c", DataType::Int64),
1360 ("a", DataType::Int64),
1361 ]));
1362 let struct_value = StructValue::new(vec![
1363 Some(ScalarRefImpl::Int64(2).into()),
1364 Some(ScalarRefImpl::Int64(1).into()),
1365 ]);
1366 let variant = VariantVal::try_from_scalar_ref(
1367 Some(ScalarRefImpl::Struct(struct_value.as_scalar_ref())),
1368 &struct_type,
1369 )
1370 .unwrap();
1371
1372 assert_eq!(json, variant);
1373 assert_eq!(
1374 json.as_scalar_ref().value_serialize(),
1375 variant.as_scalar_ref().value_serialize()
1376 );
1377 }
1378
1379 #[test]
1380 fn rejects_duplicate_struct_field_names() {
1381 let struct_type = DataType::Struct(StructType::new(vec![
1382 ("a", DataType::Int32),
1383 ("a", DataType::Varchar),
1384 ]));
1385 let struct_value = StructValue::new(vec![
1386 Some(ScalarRefImpl::Int32(1).into()),
1387 Some(ScalarRefImpl::Utf8("x").into()),
1388 ]);
1389 let err = VariantVal::try_from_scalar_ref(
1390 Some(ScalarRefImpl::Struct(struct_value.as_scalar_ref())),
1391 &struct_type,
1392 )
1393 .unwrap_err();
1394 assert!(
1395 err.to_string().contains("duplicate field name `a`"),
1396 "unexpected error: {err}"
1397 );
1398
1399 let outer_type = DataType::Struct(StructType::new(vec![("s", struct_type)]));
1400 let outer_value = StructValue::new(vec![Some(struct_value.into())]);
1401 assert!(
1402 VariantVal::try_from_scalar_ref(
1403 Some(ScalarRefImpl::Struct(outer_value.as_scalar_ref())),
1404 &outer_type,
1405 )
1406 .is_err()
1407 );
1408 }
1409
1410 #[test]
1411 fn canonicalizes_extracted_subvalues() {
1412 let root: VariantVal = r#"{"a":[{"b":1}]}"#.parse().unwrap();
1413 let extracted = root.as_scalar_ref().access_path("$.a[0]").unwrap();
1414 let parsed: VariantVal = r#"{"b":1}"#.parse().unwrap();
1415
1416 assert_same_variant(&extracted, &parsed);
1417 }
1418
1419 #[test]
1420 fn serializes_canonical_snapshot() {
1421 let v: VariantVal = r#"{"a":1,"c":[true,null]}"#.parse().unwrap();
1422 let bytes = v.as_scalar_ref().value_serialize();
1423 assert_eq!(
1424 hex::encode(&bytes),
1425 "07000000110200010261630202000100091018010000000000000003020001020400"
1426 );
1427 assert_eq!(
1428 u32::from_le_bytes(bytes[..METADATA_LEN_SIZE].try_into().unwrap()),
1429 7
1430 );
1431 assert_eq!(VariantVal::value_deserialize(&bytes).unwrap(), v);
1432 assert!(VariantVal::value_deserialize(&bytes[1..]).is_none());
1433 assert!(VariantRef::from_serialized(&bytes[1..]).is_none());
1434 }
1435
1436 #[test]
1437 fn golden_bytes_for_object_field_order_and_nested_values() {
1438 let ordered_object: VariantVal = r#"{"a":1,"c":2}"#.parse().unwrap();
1439 let reordered_object: VariantVal = r#"{"c":2,"a":1}"#.parse().unwrap();
1440 assert_same_variant(&ordered_object, &reordered_object);
1441 assert_variant_parts(
1442 "object",
1443 &reordered_object,
1444 "11020001026163",
1445 "02020001000912180100000000000000180200000000000000",
1446 );
1447
1448 let nested: VariantVal = r#"{"z":[{"b":true,"a":1},["short",null]],"a":{"c":"longish"}}"#
1449 .parse()
1450 .unwrap();
1451 assert_variant_parts(
1452 "nested",
1453 &nested,
1454 "110400010203046162637a",
1455 "02020003000d2f02010200081d6c6f6e67697368030200111d0202000100090a1801000000000000000403020006071573686f727400",
1456 );
1457 }
1458
1459 #[test]
1460 fn golden_bytes_for_scalar_variant_values() {
1461 assert_variant_parts(
1462 "short_string",
1463 &scalar_variant(ScalarRefImpl::Utf8("short"), &DataType::Varchar),
1464 "010000",
1465 "1573686f7274",
1466 );
1467 assert_variant_parts(
1468 "long_string",
1469 &scalar_variant(
1470 ScalarRefImpl::Utf8(
1471 "0123456789012345678901234567890123456789012345678901234567890123",
1472 ),
1473 &DataType::Varchar,
1474 ),
1475 "010000",
1476 "404000000030313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233",
1477 );
1478 assert_variant_parts(
1479 "int16",
1480 &scalar_variant(ScalarRefImpl::Int16(1), &DataType::Int16),
1481 "010000",
1482 "100100",
1483 );
1484 assert_variant_parts(
1485 "int32",
1486 &scalar_variant(ScalarRefImpl::Int32(1), &DataType::Int32),
1487 "010000",
1488 "1401000000",
1489 );
1490 assert_variant_parts(
1491 "int64",
1492 &scalar_variant(ScalarRefImpl::Int64(1), &DataType::Int64),
1493 "010000",
1494 "180100000000000000",
1495 );
1496 assert_variant_parts(
1497 "decimal",
1498 &scalar_variant(
1499 ScalarRefImpl::Decimal("123.45".parse().unwrap()),
1500 &DataType::Decimal,
1501 ),
1502 "010000",
1503 "280239300000000000000000000000000000",
1504 );
1505 assert_variant_parts(
1506 "date",
1507 &scalar_variant(
1508 ScalarRefImpl::Date(Date::from_ymd_uncheck(2024, 1, 2)),
1509 &DataType::Date,
1510 ),
1511 "010000",
1512 "2c0c4d0000",
1513 );
1514 assert_variant_parts(
1515 "time",
1516 &scalar_variant(
1517 ScalarRefImpl::Time(Time::from_hms_micro_uncheck(3, 4, 5, 6000)),
1518 &DataType::Time,
1519 ),
1520 "010000",
1521 "44b06a559202000000",
1522 );
1523 assert_variant_parts(
1524 "timestamp",
1525 &scalar_variant(
1526 ScalarRefImpl::Timestamp(
1527 Date::from_ymd_uncheck(2024, 1, 2).and_hms_micro_uncheck(3, 4, 5, 6000),
1528 ),
1529 &DataType::Timestamp,
1530 ),
1531 "010000",
1532 "34b0ea4dc0ed0d0600",
1533 );
1534 assert_variant_parts(
1535 "timestamptz",
1536 &scalar_variant(
1537 ScalarRefImpl::Timestamptz(Timestamptz::from_micros(1).unwrap()),
1538 &DataType::Timestamptz,
1539 ),
1540 "010000",
1541 "300100000000000000",
1542 );
1543 assert_variant_parts(
1544 "binary",
1545 &scalar_variant(ScalarRefImpl::Bytea(&[0x12, 0x34, 0xff]), &DataType::Bytea),
1546 "010000",
1547 "3c030000001234ff",
1548 );
1549 }
1550}