1use std::borrow::Borrow;
16use std::cell::{Cell, RefCell};
17use std::cmp::Ordering;
18use std::convert::{TryFrom, TryInto};
19use std::fmt::{self, Debug};
20use std::hash::{Hash, Hasher};
21use std::marker::PhantomData;
22use std::mem::{size_of, transmute};
23use std::ops::Deref;
24use std::str;
25
26use chrono::{DateTime, Datelike, NaiveDate, NaiveDateTime, NaiveTime, Timelike, Utc};
27use compact_bytes::CompactBytes;
28use mz_ore::cast::{CastFrom, ReinterpretCast};
29use mz_ore::soft_assert_no_log;
30use mz_ore::vec::Vector;
31use mz_persist_types::Codec64;
32use num_enum::{IntoPrimitive, TryFromPrimitive};
33use ordered_float::OrderedFloat;
34#[cfg(any(test, feature = "proptest"))]
35use proptest::prelude::*;
36#[cfg(any(test, feature = "proptest"))]
37use proptest::strategy::{BoxedStrategy, Strategy};
38use serde::{Deserialize, Serialize};
39use uuid::Uuid;
40
41use crate::adt::array::{
42 Array, ArrayDimension, ArrayDimensions, InvalidArrayError, MAX_ARRAY_DIMENSIONS,
43};
44use crate::adt::date::Date;
45use crate::adt::interval::Interval;
46use crate::adt::mz_acl_item::{AclItem, MzAclItem};
47use crate::adt::numeric;
48use crate::adt::numeric::Numeric;
49use crate::adt::range::{
50 self, InvalidRangeError, Range, RangeBound, RangeInner, RangeLowerBound, RangeUpperBound,
51};
52use crate::adt::timestamp::CheckedTimestamp;
53#[cfg(any(test, feature = "proptest"))]
54use crate::scalar::arb_datum;
55use crate::scalar::{DatumKind, SqlScalarType};
56use crate::{Datum, RelationDesc, Timestamp};
57
58pub(crate) mod encode;
59pub mod iter;
60
61include!(concat!(env!("OUT_DIR"), "/mz_repr.row.rs"));
62
63#[derive(Default, Eq, PartialEq, Serialize, Deserialize)]
120pub struct Row {
121 data: CompactBytes,
122}
123
124impl Row {
125 const SIZE: usize = CompactBytes::MAX_INLINE;
126
127 pub fn decode_from_proto(
130 &mut self,
131 proto: &ProtoRow,
132 desc: &RelationDesc,
133 ) -> Result<(), String> {
134 let mut packer = self.packer();
135 for (col_idx, _, _) in desc.iter_all() {
136 let d = match proto.datums.get(col_idx.to_raw()) {
137 Some(x) => x,
138 None => {
139 packer.push(Datum::Null);
140 continue;
141 }
142 };
143 packer.try_push_proto(d)?;
144 }
145
146 Ok(())
147 }
148
149 #[inline]
151 pub fn with_capacity(cap: usize) -> Self {
152 Self {
153 data: CompactBytes::with_capacity(cap),
154 }
155 }
156
157 #[inline]
159 pub const fn empty() -> Self {
160 Self {
161 data: CompactBytes::empty(),
162 }
163 }
164
165 pub unsafe fn from_bytes_unchecked(data: &[u8]) -> Self {
172 Row {
173 data: CompactBytes::new(data),
174 }
175 }
176
177 pub fn packer(&mut self) -> RowPacker<'_> {
183 self.clear();
184 RowPacker { row: self }
185 }
186
187 pub fn pack<'a, I, D>(iter: I) -> Row
195 where
196 I: IntoIterator<Item = D>,
197 D: Borrow<Datum<'a>>,
198 {
199 let mut row = Row::default();
200 row.packer().extend(iter);
201 row
202 }
203
204 pub fn pack_using<'a, I, D>(&mut self, iter: I) -> Row
209 where
210 I: IntoIterator<Item = D>,
211 D: Borrow<Datum<'a>>,
212 {
213 self.packer().extend(iter);
214 self.clone()
215 }
216
217 pub fn try_pack<'a, I, D, E>(iter: I) -> Result<Row, E>
221 where
222 I: IntoIterator<Item = Result<D, E>>,
223 D: Borrow<Datum<'a>>,
224 {
225 let mut row = Row::default();
226 row.packer().try_extend(iter)?;
227 Ok(row)
228 }
229
230 pub fn pack_slice<'a>(slice: &[Datum<'a>]) -> Row {
236 let mut row = Row::with_capacity(datums_size(slice.iter()));
238 row.packer().extend(slice.iter());
239 row
240 }
241
242 pub fn byte_len(&self) -> usize {
244 let heap_size = if self.data.spilled() {
245 self.data.len()
246 } else {
247 0
248 };
249 let inline_size = std::mem::size_of::<Self>();
250 inline_size.saturating_add(heap_size)
251 }
252
253 pub fn data_len(&self) -> usize {
255 self.data.len()
256 }
257
258 pub fn byte_capacity(&self) -> usize {
260 self.data.capacity()
261 }
262
263 #[inline]
265 pub fn as_row_ref(&self) -> &RowRef {
266 unsafe { RowRef::from_slice(self.data.as_slice()) }
268 }
269
270 #[inline]
272 fn clear(&mut self) {
273 self.data.clear();
274 }
275}
276
277impl Borrow<RowRef> for Row {
278 #[inline]
279 fn borrow(&self) -> &RowRef {
280 self.as_row_ref()
281 }
282}
283
284impl AsRef<RowRef> for Row {
285 #[inline]
286 fn as_ref(&self) -> &RowRef {
287 self.as_row_ref()
288 }
289}
290
291impl Deref for Row {
292 type Target = RowRef;
293
294 #[inline]
295 fn deref(&self) -> &Self::Target {
296 self.as_row_ref()
297 }
298}
299
300static_assertions::const_assert_eq!(std::mem::size_of::<Row>(), 24);
302
303impl Clone for Row {
304 fn clone(&self) -> Self {
305 Row {
306 data: self.data.clone(),
307 }
308 }
309
310 fn clone_from(&mut self, source: &Self) {
311 self.data.clone_from(&source.data);
312 }
313}
314
315impl std::hash::Hash for Row {
317 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
318 self.as_row_ref().hash(state)
319 }
320}
321
322#[cfg(any(test, feature = "proptest"))]
323impl Arbitrary for Row {
324 type Parameters = prop::collection::SizeRange;
325 type Strategy = BoxedStrategy<Row>;
326
327 fn arbitrary_with(size: Self::Parameters) -> Self::Strategy {
328 prop::collection::vec(arb_datum(true), size)
329 .prop_map(|items| {
330 let mut row = Row::default();
331 let mut packer = row.packer();
332 for item in items.iter() {
333 let datum: Datum<'_> = item.into();
334 packer.push(datum);
335 }
336 row
337 })
338 .boxed()
339 }
340}
341
342impl PartialOrd for Row {
343 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
344 Some(self.cmp(other))
345 }
346}
347
348impl Ord for Row {
349 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
350 self.as_ref().cmp(other.as_ref())
351 }
352}
353
354#[derive(
363 Clone,
364 Debug,
365 Default,
366 Eq,
367 PartialEq,
368 Ord,
369 PartialOrd,
370 Hash,
371 Serialize,
372 Deserialize
373)]
374pub struct StableRow(#[serde(with = "stable_row_proto")] pub Row);
375
376impl From<Row> for StableRow {
377 fn from(row: Row) -> Self {
378 StableRow(row)
379 }
380}
381
382impl Deref for StableRow {
383 type Target = Row;
384
385 fn deref(&self) -> &Row {
386 &self.0
387 }
388}
389
390mod stable_row_proto {
391 use mz_proto::RustType;
392 use prost::Message;
393 use serde::de::Error;
394 use serde::{Deserialize, Deserializer, Serializer};
395
396 use crate::row::{ProtoRow, Row};
397
398 pub fn serialize<S: Serializer>(row: &Row, serializer: S) -> Result<S::Ok, S::Error> {
399 serializer.serialize_bytes(&row.into_proto().encode_to_vec())
400 }
401
402 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Row, D::Error> {
403 let bytes = serde_bytes::ByteBuf::deserialize(deserializer)?;
404 let proto = ProtoRow::decode(bytes.as_slice()).map_err(D::Error::custom)?;
405 Row::from_proto(proto).map_err(D::Error::custom)
406 }
407}
408
409#[allow(missing_debug_implementations)]
410mod columnation {
411 use columnation::{Columnation, Region};
412 use mz_ore::region::LgAllocRegion;
413
414 use crate::Row;
415
416 pub struct RowStack {
421 region: LgAllocRegion<u8>,
422 }
423
424 impl RowStack {
425 const LIMIT: usize = 2 << 20;
426 }
427
428 impl Default for RowStack {
430 fn default() -> Self {
431 Self {
432 region: LgAllocRegion::with_limit(Self::LIMIT),
434 }
435 }
436 }
437
438 impl Columnation for Row {
439 type InnerRegion = RowStack;
440 }
441
442 impl Region for RowStack {
443 type Item = Row;
444 #[inline]
445 fn clear(&mut self) {
446 self.region.clear();
447 }
448 #[inline(always)]
449 unsafe fn copy(&mut self, item: &Row) -> Row {
450 if item.data.spilled() {
451 let bytes = self.region.copy_slice(&item.data[..]);
452 Row {
453 data: compact_bytes::CompactBytes::from_raw_parts(
454 bytes.as_mut_ptr(),
455 item.data.len(),
456 item.data.capacity(),
457 ),
458 }
459 } else {
460 item.clone()
461 }
462 }
463
464 fn reserve_items<'a, I>(&mut self, items: I)
465 where
466 Self: 'a,
467 I: Iterator<Item = &'a Self::Item> + Clone,
468 {
469 let size = items
470 .filter(|row| row.data.spilled())
471 .map(|row| row.data.len())
472 .sum();
473 let size = std::cmp::min(size, Self::LIMIT);
474 self.region.reserve(size);
475 }
476
477 fn reserve_regions<'a, I>(&mut self, regions: I)
478 where
479 Self: 'a,
480 I: Iterator<Item = &'a Self> + Clone,
481 {
482 let size = regions.map(|r| r.region.len()).sum();
483 let size = std::cmp::min(size, Self::LIMIT);
484 self.region.reserve(size);
485 }
486
487 fn heap_size(&self, callback: impl FnMut(usize, usize)) {
488 self.region.heap_size(callback)
489 }
490 }
491}
492
493mod columnar {
494 use columnar::common::PushIndexAs;
495 use columnar::{
496 AsBytes, Borrow, Clear, Columnar, Container, FromBytes, Index, IndexAs, Len, Push,
497 };
498 use mz_ore::cast::CastFrom;
499 use std::ops::Range;
500
501 use crate::{Row, RowRef};
502
503 #[derive(
504 Copy,
505 Clone,
506 Debug,
507 Default,
508 PartialEq,
509 serde::Serialize,
510 serde::Deserialize
511 )]
512 pub struct Rows<BC = Vec<u64>, VC = Vec<u8>> {
513 bounds: BC,
515 values: VC,
517 }
518
519 impl Columnar for Row {
520 #[inline(always)]
521 fn copy_from(&mut self, other: columnar::Ref<'_, Self>) {
522 self.clear();
523 self.data.extend_from_slice(other.data());
524 }
525 #[inline(always)]
526 fn into_owned(other: columnar::Ref<'_, Self>) -> Self {
527 other.to_owned()
528 }
529 type Container = Rows;
530 #[inline(always)]
531 fn reborrow<'b, 'a: 'b>(thing: columnar::Ref<'a, Self>) -> columnar::Ref<'b, Self>
532 where
533 Self: 'a,
534 {
535 thing
536 }
537 }
538
539 impl<BC: PushIndexAs<u64>> Borrow for Rows<BC, Vec<u8>> {
540 type Ref<'a> = &'a RowRef;
541 type Borrowed<'a>
542 = Rows<BC::Borrowed<'a>, &'a [u8]>
543 where
544 Self: 'a;
545 #[inline(always)]
546 fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
547 Rows {
548 bounds: self.bounds.borrow(),
549 values: self.values.borrow(),
550 }
551 }
552 #[inline(always)]
553 fn reborrow<'c, 'a: 'c>(item: Self::Borrowed<'a>) -> Self::Borrowed<'c>
554 where
555 Self: 'a,
556 {
557 Rows {
558 bounds: BC::reborrow(item.bounds),
559 values: item.values,
560 }
561 }
562
563 fn reborrow_ref<'b, 'a: 'b>(item: Self::Ref<'a>) -> Self::Ref<'b>
564 where
565 Self: 'a,
566 {
567 item
568 }
569 }
570
571 impl<BC: PushIndexAs<u64>> Container for Rows<BC, Vec<u8>> {
572 fn extend_from_self(&mut self, other: Self::Borrowed<'_>, range: Range<usize>) {
573 if !range.is_empty() {
574 let values_len: u64 = self.values.len().try_into().expect("must fit");
576
577 let other_lower = if range.start == 0 {
579 0
580 } else {
581 other.bounds.index_as(range.start - 1)
582 };
583 let other_upper = other.bounds.index_as(range.end - 1);
584 self.values.extend_from_self(
585 other.values,
586 usize::try_from(other_lower).expect("must fit")
587 ..usize::try_from(other_upper).expect("must fit"),
588 );
589
590 if values_len == other_lower {
592 self.bounds.extend_from_self(other.bounds, range);
593 } else {
594 for index in range {
595 let shifted = other.bounds.index_as(index) - other_lower + values_len;
596 self.bounds.push(&shifted)
597 }
598 }
599 }
600 }
601 fn reserve_for<'a, I>(&mut self, selves: I)
602 where
603 Self: 'a,
604 I: Iterator<Item = Self::Borrowed<'a>> + Clone,
605 {
606 self.bounds.reserve_for(selves.clone().map(|r| r.bounds));
607 self.values.reserve_for(selves.map(|r| r.values));
608 }
609 }
610
611 impl<'a, BC: AsBytes<'a>, VC: AsBytes<'a>> AsBytes<'a> for Rows<BC, VC> {
612 const SLICE_COUNT: usize = BC::SLICE_COUNT + VC::SLICE_COUNT;
613 #[inline(always)]
614 fn get_byte_slice(&self, index: usize) -> (u64, &'a [u8]) {
615 mz_ore::soft_assert_no_log!(index < Self::SLICE_COUNT);
616 if index < BC::SLICE_COUNT {
617 self.bounds.get_byte_slice(index)
618 } else {
619 self.values.get_byte_slice(index - BC::SLICE_COUNT)
620 }
621 }
622 }
623 impl<'a, BC: FromBytes<'a>, VC: FromBytes<'a>> FromBytes<'a> for Rows<BC, VC> {
624 const SLICE_COUNT: usize = BC::SLICE_COUNT + VC::SLICE_COUNT;
625 #[inline(always)]
626 fn from_bytes(bytes: &mut impl Iterator<Item = &'a [u8]>) -> Self {
627 Self {
628 bounds: FromBytes::from_bytes(bytes),
629 values: FromBytes::from_bytes(bytes),
630 }
631 }
632 }
633
634 impl<BC: Len, VC> Len for Rows<BC, VC> {
635 #[inline(always)]
636 fn len(&self) -> usize {
637 self.bounds.len()
638 }
639 }
640
641 impl<'a, BC: Len + IndexAs<u64>> Index for Rows<BC, &'a [u8]> {
642 type Ref = &'a RowRef;
643 #[inline(always)]
644 fn get(&self, index: usize) -> Self::Ref {
645 let lower = if index == 0 {
646 0
647 } else {
648 self.bounds.index_as(index - 1)
649 };
650 let upper = self.bounds.index_as(index);
651 let lower = usize::cast_from(lower);
652 let upper = usize::cast_from(upper);
653 unsafe { RowRef::from_slice(&self.values[lower..upper]) }
656 }
657 }
658 impl<'a, BC: Len + IndexAs<u64>> Index for &'a Rows<BC, Vec<u8>> {
659 type Ref = &'a RowRef;
660 #[inline(always)]
661 fn get(&self, index: usize) -> Self::Ref {
662 let lower = if index == 0 {
663 0
664 } else {
665 self.bounds.index_as(index - 1)
666 };
667 let upper = self.bounds.index_as(index);
668 let lower = usize::cast_from(lower);
669 let upper = usize::cast_from(upper);
670 unsafe { RowRef::from_slice(&self.values[lower..upper]) }
673 }
674 }
675
676 impl<BC: Push<u64>> Push<&Row> for Rows<BC> {
677 #[inline(always)]
678 fn push(&mut self, item: &Row) {
679 self.values.extend_from_slice(item.data.as_slice());
680 self.bounds.push(u64::cast_from(self.values.len()));
681 }
682 }
683 impl<BC: for<'a> Push<&'a u64>> Push<&RowRef> for Rows<BC> {
684 #[inline(always)]
685 fn push(&mut self, item: &RowRef) {
686 self.values.extend_from_slice(item.data());
687 self.bounds.push(&u64::cast_from(self.values.len()));
688 }
689 }
690 impl<BC: Clear, VC: Clear> Clear for Rows<BC, VC> {
691 #[inline(always)]
692 fn clear(&mut self) {
693 self.bounds.clear();
694 self.values.clear();
695 }
696 }
697}
698
699#[derive(PartialEq, Eq, Hash)]
703#[repr(transparent)]
704pub struct RowRef([u8]);
705
706impl RowRef {
707 pub unsafe fn from_slice(row: &[u8]) -> &RowRef {
714 #[allow(clippy::as_conversions)]
715 let ptr = row as *const [u8] as *const RowRef;
716 unsafe { &*ptr }
718 }
719
720 pub fn unpack(&self) -> Vec<Datum<'_>> {
722 let len = self.iter().count();
724 let mut vec = Vec::with_capacity(len);
725 vec.extend(self.iter());
726 vec
727 }
728
729 pub fn unpack_first(&self) -> Datum<'_> {
733 self.iter().next().unwrap()
734 }
735
736 pub fn iter(&self) -> DatumListIter<'_> {
738 DatumListIter { data: &self.0 }
739 }
740
741 pub fn byte_len(&self) -> usize {
743 self.0.len()
744 }
745
746 pub fn data(&self) -> &[u8] {
748 &self.0
749 }
750
751 pub fn is_empty(&self) -> bool {
753 self.0.is_empty()
754 }
755}
756
757impl ToOwned for RowRef {
758 type Owned = Row;
759
760 fn to_owned(&self) -> Self::Owned {
761 unsafe { Row::from_bytes_unchecked(&self.0) }
763 }
764}
765
766impl<'a> IntoIterator for &'a RowRef {
767 type Item = Datum<'a>;
768 type IntoIter = DatumListIter<'a>;
769
770 fn into_iter(self) -> DatumListIter<'a> {
771 DatumListIter { data: &self.0 }
772 }
773}
774
775impl PartialOrd for RowRef {
779 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
780 Some(self.cmp(other))
781 }
782}
783
784impl Ord for RowRef {
785 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
786 match self.0.len().cmp(&other.0.len()) {
787 std::cmp::Ordering::Less => std::cmp::Ordering::Less,
788 std::cmp::Ordering::Greater => std::cmp::Ordering::Greater,
789 std::cmp::Ordering::Equal => self.0.cmp(&other.0),
790 }
791 }
792}
793
794impl fmt::Debug for RowRef {
795 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
797 f.write_str("RowRef{")?;
798 f.debug_list().entries(&*self).finish()?;
799 f.write_str("}")
800 }
801}
802
803#[derive(Debug)]
811pub struct RowPacker<'a> {
812 row: &'a mut Row,
813}
814
815pub trait FromDatum<'a>:
826 Sized + PartialEq + std::borrow::Borrow<Datum<'a>> + sealed::Sealed
827{
828 fn from_datum(datum: Datum<'a>) -> Self;
829}
830
831mod sealed {
832 use crate::Datum;
833
834 pub trait Sealed {}
835 impl<'a> Sealed for Datum<'a> {}
836}
837
838impl<'a> FromDatum<'a> for Datum<'a> {
839 #[inline]
840 fn from_datum(datum: Datum<'a>) -> Self {
841 datum
842 }
843}
844
845#[derive(Debug, Clone)]
846pub struct DatumListIter<'a> {
847 data: &'a [u8],
848}
849
850#[derive(Debug, Clone)]
851pub struct DatumListTypedIter<'a, T> {
852 inner: DatumListIter<'a>,
853 _phantom: PhantomData<fn() -> T>,
854}
855
856#[derive(Debug, Clone)]
857pub struct DatumDictIter<'a> {
858 data: &'a [u8],
859 prev_key: Option<&'a str>,
860}
861
862#[derive(Debug, Clone)]
863pub struct DatumDictTypedIter<'a, T> {
864 inner: DatumDictIter<'a>,
865 _phantom: PhantomData<fn() -> T>,
866}
867
868#[derive(Debug)]
870pub struct RowArena {
871 inner: RefCell<Vec<Vec<u8>>>,
887 scratch: RefCell<Option<Vec<u8>>>,
895 budget: Option<usize>,
906 allocated: Cell<usize>,
907}
908
909pub struct DatumList<'a, T = Datum<'a>> {
923 data: &'a [u8],
925 _phantom: PhantomData<fn() -> T>,
926}
927
928impl<'a, T> DatumList<'a, T> {
929 pub(crate) fn new(data: &'a [u8]) -> Self {
932 DatumList {
933 data,
934 _phantom: PhantomData,
935 }
936 }
937}
938
939impl<'a, T> Clone for DatumList<'a, T> {
940 fn clone(&self) -> Self {
941 *self
942 }
943}
944
945impl<'a, T> Copy for DatumList<'a, T> {}
946
947impl<'a, T> Debug for DatumList<'a, T> {
948 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
949 f.debug_list().entries(self.iter()).finish()
950 }
951}
952
953impl<'a, T> PartialEq for DatumList<'a, T> {
954 #[inline(always)]
955 fn eq(&self, other: &DatumList<'a, T>) -> bool {
956 self.iter().eq(other.iter())
957 }
958}
959
960impl<'a, T> Eq for DatumList<'a, T> {}
961
962impl<'a, T> Hash for DatumList<'a, T> {
963 #[inline(always)]
964 fn hash<H: Hasher>(&self, state: &mut H) {
965 for d in self.iter() {
966 d.hash(state);
967 }
968 }
969}
970
971impl<T> Ord for DatumList<'_, T> {
972 #[inline(always)]
973 fn cmp(&self, other: &DatumList<'_, T>) -> Ordering {
974 mz_ore::stack::maybe_grow(|| self.iter().cmp(other.iter()))
976 }
977}
978
979impl<T> PartialOrd for DatumList<'_, T> {
980 #[inline(always)]
981 fn partial_cmp(&self, other: &DatumList<'_, T>) -> Option<Ordering> {
982 Some(self.cmp(other))
983 }
984}
985
986pub struct DatumMap<'a, T = Datum<'a>> {
997 data: &'a [u8],
999 _phantom: PhantomData<fn() -> T>,
1000}
1001
1002impl<'a, T> DatumMap<'a, T> {
1003 pub(crate) fn new(data: &'a [u8]) -> Self {
1006 DatumMap {
1007 data,
1008 _phantom: PhantomData,
1009 }
1010 }
1011}
1012
1013impl<'a, T> Clone for DatumMap<'a, T> {
1014 fn clone(&self) -> Self {
1015 *self
1016 }
1017}
1018
1019impl<'a, T> Copy for DatumMap<'a, T> {}
1020
1021impl<'a, T> PartialEq for DatumMap<'a, T> {
1022 #[inline(always)]
1023 fn eq(&self, other: &DatumMap<'a, T>) -> bool {
1024 self.iter().eq(other.iter())
1025 }
1026}
1027
1028impl<'a, T> Eq for DatumMap<'a, T> {}
1029
1030impl<'a, T> Hash for DatumMap<'a, T> {
1031 #[inline(always)]
1032 fn hash<H: Hasher>(&self, state: &mut H) {
1033 for (k, v) in self.iter() {
1034 k.hash(state);
1035 v.hash(state);
1036 }
1037 }
1038}
1039
1040impl<'a, T> Ord for DatumMap<'a, T> {
1041 #[inline(always)]
1042 fn cmp(&self, other: &DatumMap<'a, T>) -> Ordering {
1043 mz_ore::stack::maybe_grow(|| self.iter().cmp(other.iter()))
1045 }
1046}
1047
1048impl<'a, T> PartialOrd for DatumMap<'a, T> {
1049 #[inline(always)]
1050 fn partial_cmp(&self, other: &DatumMap<'a, T>) -> Option<Ordering> {
1051 Some(self.cmp(other))
1052 }
1053}
1054
1055impl<'a> crate::scalar::SqlContainerType for DatumList<'a, Datum<'a>> {
1056 fn unwrap_element_type(container: &SqlScalarType) -> &SqlScalarType {
1057 container.unwrap_list_element_type()
1058 }
1059 fn wrap_element_type(element: SqlScalarType) -> SqlScalarType {
1060 SqlScalarType::List {
1061 element_type: Box::new(element),
1062 custom_id: None,
1063 }
1064 }
1065}
1066
1067impl<'a> crate::scalar::SqlContainerType for DatumMap<'a, Datum<'a>> {
1068 fn unwrap_element_type(container: &SqlScalarType) -> &SqlScalarType {
1069 container.unwrap_map_value_type()
1070 }
1071 fn wrap_element_type(element: SqlScalarType) -> SqlScalarType {
1072 SqlScalarType::Map {
1073 value_type: Box::new(element),
1074 custom_id: None,
1075 }
1076 }
1077}
1078
1079#[derive(Clone, Copy, Eq, PartialEq, Hash)]
1082pub struct DatumNested<'a> {
1083 val: &'a [u8],
1084}
1085
1086impl<'a> std::fmt::Display for DatumNested<'a> {
1087 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1088 std::fmt::Display::fmt(&self.datum(), f)
1089 }
1090}
1091
1092impl<'a> std::fmt::Debug for DatumNested<'a> {
1093 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1094 f.debug_struct("DatumNested")
1095 .field("val", &self.datum())
1096 .finish()
1097 }
1098}
1099
1100impl<'a> DatumNested<'a> {
1101 pub fn extract(data: &mut &'a [u8]) -> DatumNested<'a> {
1105 let prev = *data;
1106 let _ = unsafe { read_datum(data) };
1107 DatumNested {
1108 val: &prev[..(prev.len() - data.len())],
1109 }
1110 }
1111
1112 pub fn datum(&self) -> Datum<'a> {
1114 let mut temp = self.val;
1115 unsafe { read_datum(&mut temp) }
1116 }
1117}
1118
1119impl<'a> Ord for DatumNested<'a> {
1120 fn cmp(&self, other: &Self) -> Ordering {
1121 mz_ore::stack::maybe_grow(|| self.datum().cmp(&other.datum()))
1123 }
1124}
1125
1126impl<'a> PartialOrd for DatumNested<'a> {
1127 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1128 Some(self.cmp(other))
1129 }
1130}
1131
1132#[derive(Debug, Clone, Copy, PartialEq, Eq, IntoPrimitive, TryFromPrimitive)]
1136#[repr(u8)]
1137enum Tag {
1138 Null,
1139 False,
1140 True,
1141 Int16,
1142 Int32,
1143 Int64,
1144 UInt8,
1145 UInt32,
1146 Float32,
1147 Float64,
1148 Date,
1149 Time,
1150 Timestamp,
1151 TimestampTz,
1152 Interval,
1153 BytesTiny,
1154 BytesShort,
1155 BytesLong,
1156 BytesHuge,
1157 StringTiny,
1158 StringShort,
1159 StringLong,
1160 StringHuge,
1161 Uuid,
1162 Array,
1163 ListTiny,
1164 ListShort,
1165 ListLong,
1166 ListHuge,
1167 Dict,
1168 JsonNull,
1169 Dummy,
1170 Numeric,
1171 UInt16,
1172 UInt64,
1173 MzTimestamp,
1174 Range,
1175 MzAclItem,
1176 AclItem,
1177 CheapTimestamp,
1181 CheapTimestampTz,
1185 NonNegativeInt16_0, NonNegativeInt16_8,
1198 NonNegativeInt16_16,
1199
1200 NonNegativeInt32_0,
1201 NonNegativeInt32_8,
1202 NonNegativeInt32_16,
1203 NonNegativeInt32_24,
1204 NonNegativeInt32_32,
1205
1206 NonNegativeInt64_0,
1207 NonNegativeInt64_8,
1208 NonNegativeInt64_16,
1209 NonNegativeInt64_24,
1210 NonNegativeInt64_32,
1211 NonNegativeInt64_40,
1212 NonNegativeInt64_48,
1213 NonNegativeInt64_56,
1214 NonNegativeInt64_64,
1215
1216 NegativeInt16_0, NegativeInt16_8,
1218 NegativeInt16_16,
1219
1220 NegativeInt32_0,
1221 NegativeInt32_8,
1222 NegativeInt32_16,
1223 NegativeInt32_24,
1224 NegativeInt32_32,
1225
1226 NegativeInt64_0,
1227 NegativeInt64_8,
1228 NegativeInt64_16,
1229 NegativeInt64_24,
1230 NegativeInt64_32,
1231 NegativeInt64_40,
1232 NegativeInt64_48,
1233 NegativeInt64_56,
1234 NegativeInt64_64,
1235
1236 UInt8_0, UInt8_8,
1240
1241 UInt16_0,
1242 UInt16_8,
1243 UInt16_16,
1244
1245 UInt32_0,
1246 UInt32_8,
1247 UInt32_16,
1248 UInt32_24,
1249 UInt32_32,
1250
1251 UInt64_0,
1252 UInt64_8,
1253 UInt64_16,
1254 UInt64_24,
1255 UInt64_32,
1256 UInt64_40,
1257 UInt64_48,
1258 UInt64_56,
1259 UInt64_64,
1260}
1261
1262impl Tag {
1263 fn actual_int_length(self) -> Option<usize> {
1264 use Tag::*;
1265 let val = match self {
1266 NonNegativeInt16_0 | NonNegativeInt32_0 | NonNegativeInt64_0 | UInt8_0 | UInt16_0
1267 | UInt32_0 | UInt64_0 => 0,
1268 NonNegativeInt16_8 | NonNegativeInt32_8 | NonNegativeInt64_8 | UInt8_8 | UInt16_8
1269 | UInt32_8 | UInt64_8 => 1,
1270 NonNegativeInt16_16 | NonNegativeInt32_16 | NonNegativeInt64_16 | UInt16_16
1271 | UInt32_16 | UInt64_16 => 2,
1272 NonNegativeInt32_24 | NonNegativeInt64_24 | UInt32_24 | UInt64_24 => 3,
1273 NonNegativeInt32_32 | NonNegativeInt64_32 | UInt32_32 | UInt64_32 => 4,
1274 NonNegativeInt64_40 | UInt64_40 => 5,
1275 NonNegativeInt64_48 | UInt64_48 => 6,
1276 NonNegativeInt64_56 | UInt64_56 => 7,
1277 NonNegativeInt64_64 | UInt64_64 => 8,
1278 NegativeInt16_0 | NegativeInt32_0 | NegativeInt64_0 => 0,
1279 NegativeInt16_8 | NegativeInt32_8 | NegativeInt64_8 => 1,
1280 NegativeInt16_16 | NegativeInt32_16 | NegativeInt64_16 => 2,
1281 NegativeInt32_24 | NegativeInt64_24 => 3,
1282 NegativeInt32_32 | NegativeInt64_32 => 4,
1283 NegativeInt64_40 => 5,
1284 NegativeInt64_48 => 6,
1285 NegativeInt64_56 => 7,
1286 NegativeInt64_64 => 8,
1287
1288 _ => return None,
1289 };
1290 Some(val)
1291 }
1292}
1293
1294fn read_untagged_bytes<'a>(data: &mut &'a [u8]) -> &'a [u8] {
1301 let len = u64::from_le_bytes(read_byte_array(data));
1302 let len = usize::cast_from(len);
1303 let (bytes, next) = data.split_at(len);
1304 *data = next;
1305 bytes
1306}
1307
1308unsafe fn read_lengthed_datum<'a>(data: &mut &'a [u8], tag: Tag) -> Datum<'a> {
1317 let len = match tag {
1318 Tag::BytesTiny | Tag::StringTiny | Tag::ListTiny => usize::from(read_byte(data)),
1319 Tag::BytesShort | Tag::StringShort | Tag::ListShort => {
1320 usize::from(u16::from_le_bytes(read_byte_array(data)))
1321 }
1322 Tag::BytesLong | Tag::StringLong | Tag::ListLong => {
1323 usize::cast_from(u32::from_le_bytes(read_byte_array(data)))
1324 }
1325 Tag::BytesHuge | Tag::StringHuge | Tag::ListHuge => {
1326 usize::cast_from(u64::from_le_bytes(read_byte_array(data)))
1327 }
1328 _ => unreachable!(),
1329 };
1330 let (bytes, next) = data.split_at(len);
1331 *data = next;
1332 match tag {
1333 Tag::BytesTiny | Tag::BytesShort | Tag::BytesLong | Tag::BytesHuge => Datum::Bytes(bytes),
1334 Tag::StringTiny | Tag::StringShort | Tag::StringLong | Tag::StringHuge => {
1335 Datum::String(str::from_utf8_unchecked(bytes))
1336 }
1337 Tag::ListTiny | Tag::ListShort | Tag::ListLong | Tag::ListHuge => {
1338 Datum::List(DatumList::new(bytes))
1339 }
1340 _ => unreachable!(),
1341 }
1342}
1343
1344fn read_byte(data: &mut &[u8]) -> u8 {
1345 let byte = data[0];
1346 *data = &data[1..];
1347 byte
1348}
1349
1350fn read_byte_array_sign_extending<const N: usize, const FILL: u8>(
1358 data: &mut &[u8],
1359 length: usize,
1360) -> [u8; N] {
1361 let mut raw = [FILL; N];
1362 let (prev, next) = data.split_at(length);
1363 (raw[..prev.len()]).copy_from_slice(prev);
1364 *data = next;
1365 raw
1366}
1367fn read_byte_array_extending_negative<const N: usize>(data: &mut &[u8], length: usize) -> [u8; N] {
1375 read_byte_array_sign_extending::<N, 255>(data, length)
1376}
1377
1378fn read_byte_array_extending_nonnegative<const N: usize>(
1386 data: &mut &[u8],
1387 length: usize,
1388) -> [u8; N] {
1389 read_byte_array_sign_extending::<N, 0>(data, length)
1390}
1391
1392pub(super) fn read_byte_array<const N: usize>(data: &mut &[u8]) -> [u8; N] {
1393 let (prev, next) = data.split_first_chunk().unwrap();
1394 *data = next;
1395 *prev
1396}
1397
1398pub(super) fn read_date(data: &mut &[u8]) -> Date {
1399 let days = i32::from_le_bytes(read_byte_array(data));
1400 Date::from_pg_epoch(days).expect("unexpected date")
1401}
1402
1403pub(super) fn read_naive_date(data: &mut &[u8]) -> NaiveDate {
1404 let year = i32::from_le_bytes(read_byte_array(data));
1405 let ordinal = u32::from_le_bytes(read_byte_array(data));
1406 NaiveDate::from_yo_opt(year, ordinal).unwrap()
1407}
1408
1409pub(super) fn read_time(data: &mut &[u8]) -> NaiveTime {
1410 let secs = u32::from_le_bytes(read_byte_array(data));
1411 let nanos = u32::from_le_bytes(read_byte_array(data));
1412 NaiveTime::from_num_seconds_from_midnight_opt(secs, nanos).unwrap()
1413}
1414
1415pub unsafe fn read_datum<'a>(data: &mut &'a [u8]) -> Datum<'a> {
1424 let tag = Tag::try_from_primitive(read_byte(data)).expect("unknown row tag");
1425 match tag {
1426 Tag::Null => Datum::Null,
1427 Tag::False => Datum::False,
1428 Tag::True => Datum::True,
1429 Tag::UInt8_0 | Tag::UInt8_8 => {
1430 let i = u8::from_le_bytes(read_byte_array_extending_nonnegative(
1431 data,
1432 tag.actual_int_length()
1433 .expect("returns a value for variable-length-encoded integer tags"),
1434 ));
1435 Datum::UInt8(i)
1436 }
1437 Tag::Int16 => {
1438 let i = i16::from_le_bytes(read_byte_array(data));
1439 Datum::Int16(i)
1440 }
1441 Tag::NonNegativeInt16_0 | Tag::NonNegativeInt16_16 | Tag::NonNegativeInt16_8 => {
1442 let i = i16::from_le_bytes(read_byte_array_extending_nonnegative(
1446 data,
1447 tag.actual_int_length()
1448 .expect("returns a value for variable-length-encoded integer tags"),
1449 ));
1450 Datum::Int16(i)
1451 }
1452 Tag::UInt16_0 | Tag::UInt16_8 | Tag::UInt16_16 => {
1453 let i = u16::from_le_bytes(read_byte_array_extending_nonnegative(
1454 data,
1455 tag.actual_int_length()
1456 .expect("returns a value for variable-length-encoded integer tags"),
1457 ));
1458 Datum::UInt16(i)
1459 }
1460 Tag::Int32 => {
1461 let i = i32::from_le_bytes(read_byte_array(data));
1462 Datum::Int32(i)
1463 }
1464 Tag::NonNegativeInt32_0
1465 | Tag::NonNegativeInt32_32
1466 | Tag::NonNegativeInt32_8
1467 | Tag::NonNegativeInt32_16
1468 | Tag::NonNegativeInt32_24 => {
1469 let i = i32::from_le_bytes(read_byte_array_extending_nonnegative(
1473 data,
1474 tag.actual_int_length()
1475 .expect("returns a value for variable-length-encoded integer tags"),
1476 ));
1477 Datum::Int32(i)
1478 }
1479 Tag::UInt32_0 | Tag::UInt32_8 | Tag::UInt32_16 | Tag::UInt32_24 | Tag::UInt32_32 => {
1480 let i = u32::from_le_bytes(read_byte_array_extending_nonnegative(
1481 data,
1482 tag.actual_int_length()
1483 .expect("returns a value for variable-length-encoded integer tags"),
1484 ));
1485 Datum::UInt32(i)
1486 }
1487 Tag::Int64 => {
1488 let i = i64::from_le_bytes(read_byte_array(data));
1489 Datum::Int64(i)
1490 }
1491 Tag::NonNegativeInt64_0
1492 | Tag::NonNegativeInt64_64
1493 | Tag::NonNegativeInt64_8
1494 | Tag::NonNegativeInt64_16
1495 | Tag::NonNegativeInt64_24
1496 | Tag::NonNegativeInt64_32
1497 | Tag::NonNegativeInt64_40
1498 | Tag::NonNegativeInt64_48
1499 | Tag::NonNegativeInt64_56 => {
1500 let i = i64::from_le_bytes(read_byte_array_extending_nonnegative(
1505 data,
1506 tag.actual_int_length()
1507 .expect("returns a value for variable-length-encoded integer tags"),
1508 ));
1509 Datum::Int64(i)
1510 }
1511 Tag::UInt64_0
1512 | Tag::UInt64_8
1513 | Tag::UInt64_16
1514 | Tag::UInt64_24
1515 | Tag::UInt64_32
1516 | Tag::UInt64_40
1517 | Tag::UInt64_48
1518 | Tag::UInt64_56
1519 | Tag::UInt64_64 => {
1520 let i = u64::from_le_bytes(read_byte_array_extending_nonnegative(
1521 data,
1522 tag.actual_int_length()
1523 .expect("returns a value for variable-length-encoded integer tags"),
1524 ));
1525 Datum::UInt64(i)
1526 }
1527 Tag::NegativeInt16_0 | Tag::NegativeInt16_16 | Tag::NegativeInt16_8 => {
1528 let i = i16::from_le_bytes(read_byte_array_extending_negative(
1532 data,
1533 tag.actual_int_length()
1534 .expect("returns a value for variable-length-encoded integer tags"),
1535 ));
1536 Datum::Int16(i)
1537 }
1538 Tag::NegativeInt32_0
1539 | Tag::NegativeInt32_32
1540 | Tag::NegativeInt32_8
1541 | Tag::NegativeInt32_16
1542 | Tag::NegativeInt32_24 => {
1543 let i = i32::from_le_bytes(read_byte_array_extending_negative(
1547 data,
1548 tag.actual_int_length()
1549 .expect("returns a value for variable-length-encoded integer tags"),
1550 ));
1551 Datum::Int32(i)
1552 }
1553 Tag::NegativeInt64_0
1554 | Tag::NegativeInt64_64
1555 | Tag::NegativeInt64_8
1556 | Tag::NegativeInt64_16
1557 | Tag::NegativeInt64_24
1558 | Tag::NegativeInt64_32
1559 | Tag::NegativeInt64_40
1560 | Tag::NegativeInt64_48
1561 | Tag::NegativeInt64_56 => {
1562 let i = i64::from_le_bytes(read_byte_array_extending_negative(
1566 data,
1567 tag.actual_int_length()
1568 .expect("returns a value for variable-length-encoded integer tags"),
1569 ));
1570 Datum::Int64(i)
1571 }
1572
1573 Tag::UInt8 => {
1574 let i = u8::from_le_bytes(read_byte_array(data));
1575 Datum::UInt8(i)
1576 }
1577 Tag::UInt16 => {
1578 let i = u16::from_le_bytes(read_byte_array(data));
1579 Datum::UInt16(i)
1580 }
1581 Tag::UInt32 => {
1582 let i = u32::from_le_bytes(read_byte_array(data));
1583 Datum::UInt32(i)
1584 }
1585 Tag::UInt64 => {
1586 let i = u64::from_le_bytes(read_byte_array(data));
1587 Datum::UInt64(i)
1588 }
1589 Tag::Float32 => {
1590 let f = f32::from_bits(u32::from_le_bytes(read_byte_array(data)));
1591 Datum::Float32(OrderedFloat::from(f))
1592 }
1593 Tag::Float64 => {
1594 let f = f64::from_bits(u64::from_le_bytes(read_byte_array(data)));
1595 Datum::Float64(OrderedFloat::from(f))
1596 }
1597 Tag::Date => Datum::Date(read_date(data)),
1598 Tag::Time => Datum::Time(read_time(data)),
1599 Tag::CheapTimestamp => {
1600 let ts = i64::from_le_bytes(read_byte_array(data));
1601 let secs = ts.div_euclid(1_000_000_000);
1602 let nsecs: u32 = ts.rem_euclid(1_000_000_000).try_into().unwrap();
1603 let ndt = DateTime::from_timestamp(secs, nsecs)
1604 .expect("We only write round-trippable timestamps")
1605 .naive_utc();
1606 Datum::Timestamp(
1607 CheckedTimestamp::from_timestamplike(ndt).expect("unexpected timestamp"),
1608 )
1609 }
1610 Tag::CheapTimestampTz => {
1611 let ts = i64::from_le_bytes(read_byte_array(data));
1612 let secs = ts.div_euclid(1_000_000_000);
1613 let nsecs: u32 = ts.rem_euclid(1_000_000_000).try_into().unwrap();
1614 let dt = DateTime::from_timestamp(secs, nsecs)
1615 .expect("We only write round-trippable timestamps");
1616 Datum::TimestampTz(
1617 CheckedTimestamp::from_timestamplike(dt).expect("unexpected timestamp"),
1618 )
1619 }
1620 Tag::Timestamp => {
1621 let date = read_naive_date(data);
1622 let time = read_time(data);
1623 Datum::Timestamp(
1624 CheckedTimestamp::from_timestamplike(date.and_time(time))
1625 .expect("unexpected timestamp"),
1626 )
1627 }
1628 Tag::TimestampTz => {
1629 let date = read_naive_date(data);
1630 let time = read_time(data);
1631 Datum::TimestampTz(
1632 CheckedTimestamp::from_timestamplike(DateTime::from_naive_utc_and_offset(
1633 date.and_time(time),
1634 Utc,
1635 ))
1636 .expect("unexpected timestamptz"),
1637 )
1638 }
1639 Tag::Interval => {
1640 let months = i32::from_le_bytes(read_byte_array(data));
1641 let days = i32::from_le_bytes(read_byte_array(data));
1642 let micros = i64::from_le_bytes(read_byte_array(data));
1643 Datum::Interval(Interval {
1644 months,
1645 days,
1646 micros,
1647 })
1648 }
1649 Tag::BytesTiny
1650 | Tag::BytesShort
1651 | Tag::BytesLong
1652 | Tag::BytesHuge
1653 | Tag::StringTiny
1654 | Tag::StringShort
1655 | Tag::StringLong
1656 | Tag::StringHuge
1657 | Tag::ListTiny
1658 | Tag::ListShort
1659 | Tag::ListLong
1660 | Tag::ListHuge => read_lengthed_datum(data, tag),
1661 Tag::Uuid => Datum::Uuid(Uuid::from_bytes(read_byte_array(data))),
1662 Tag::Array => {
1663 let ndims = read_byte(data);
1666 let dims_size = usize::from(ndims) * size_of::<u64>() * 2;
1667 let (dims, next) = data.split_at(dims_size);
1668 *data = next;
1669 let bytes = read_untagged_bytes(data);
1670 Datum::Array(Array {
1671 dims: ArrayDimensions { data: dims },
1672 elements: DatumList::new(bytes),
1673 })
1674 }
1675 Tag::Dict => {
1676 let bytes = read_untagged_bytes(data);
1677 Datum::Map(DatumMap::new(bytes))
1678 }
1679 Tag::JsonNull => Datum::JsonNull,
1680 Tag::Dummy => Datum::Dummy,
1681 Tag::Numeric => {
1682 let digits = read_byte(data).into();
1683 let exponent = i8::reinterpret_cast(read_byte(data));
1684 let bits = read_byte(data);
1685
1686 let lsu_u16_len = Numeric::digits_to_lsu_elements_len(digits);
1687 let lsu_u8_len = lsu_u16_len * 2;
1688 let (lsu_u8, next) = data.split_at(lsu_u8_len);
1689 *data = next;
1690
1691 let mut lsu = [0; numeric::NUMERIC_DATUM_WIDTH_USIZE];
1695 for (i, c) in lsu_u8.chunks(2).enumerate() {
1696 lsu[i] = u16::from_le_bytes(c.try_into().unwrap());
1697 }
1698
1699 let d = Numeric::from_raw_parts(digits, exponent.into(), bits, lsu);
1700 Datum::from(d)
1701 }
1702 Tag::MzTimestamp => {
1703 let t = Timestamp::decode(read_byte_array(data));
1704 Datum::MzTimestamp(t)
1705 }
1706 Tag::Range => {
1707 let flag_byte = read_byte(data);
1709 let flags = range::InternalFlags::from_bits(flag_byte)
1710 .expect("range flags must be encoded validly");
1711
1712 if flags.contains(range::InternalFlags::EMPTY) {
1713 assert!(
1714 flags == range::InternalFlags::EMPTY,
1715 "empty ranges contain only RANGE_EMPTY flag"
1716 );
1717
1718 return Datum::Range(Range { inner: None });
1719 }
1720
1721 let lower_bound = if flags.contains(range::InternalFlags::LB_INFINITE) {
1722 None
1723 } else {
1724 Some(DatumNested::extract(data))
1725 };
1726
1727 let lower = RangeBound {
1728 inclusive: flags.contains(range::InternalFlags::LB_INCLUSIVE),
1729 bound: lower_bound,
1730 };
1731
1732 let upper_bound = if flags.contains(range::InternalFlags::UB_INFINITE) {
1733 None
1734 } else {
1735 Some(DatumNested::extract(data))
1736 };
1737
1738 let upper = RangeBound {
1739 inclusive: flags.contains(range::InternalFlags::UB_INCLUSIVE),
1740 bound: upper_bound,
1741 };
1742
1743 Datum::Range(Range {
1744 inner: Some(RangeInner { lower, upper }),
1745 })
1746 }
1747 Tag::MzAclItem => {
1748 const N: usize = MzAclItem::binary_size();
1749 let mz_acl_item =
1750 MzAclItem::decode_binary(&read_byte_array::<N>(data)).expect("invalid mz_aclitem");
1751 Datum::MzAclItem(mz_acl_item)
1752 }
1753 Tag::AclItem => {
1754 const N: usize = AclItem::binary_size();
1755 let acl_item =
1756 AclItem::decode_binary(&read_byte_array::<N>(data)).expect("invalid aclitem");
1757 Datum::AclItem(acl_item)
1758 }
1759 }
1760}
1761
1762fn push_untagged_bytes<D>(data: &mut D, bytes: &[u8])
1766where
1767 D: Vector<u8>,
1768{
1769 let len = u64::cast_from(bytes.len());
1770 data.extend_from_slice(&len.to_le_bytes());
1771 data.extend_from_slice(bytes);
1772}
1773
1774fn push_lengthed_bytes<D>(data: &mut D, bytes: &[u8], tag: Tag)
1775where
1776 D: Vector<u8>,
1777{
1778 match tag {
1779 Tag::BytesTiny | Tag::StringTiny | Tag::ListTiny => {
1780 let len = bytes.len().to_le_bytes();
1781 data.push(len[0]);
1782 }
1783 Tag::BytesShort | Tag::StringShort | Tag::ListShort => {
1784 let len = bytes.len().to_le_bytes();
1785 data.extend_from_slice(&len[0..2]);
1786 }
1787 Tag::BytesLong | Tag::StringLong | Tag::ListLong => {
1788 let len = bytes.len().to_le_bytes();
1789 data.extend_from_slice(&len[0..4]);
1790 }
1791 Tag::BytesHuge | Tag::StringHuge | Tag::ListHuge => {
1792 let len = bytes.len().to_le_bytes();
1793 data.extend_from_slice(&len);
1794 }
1795 _ => unreachable!(),
1796 }
1797 data.extend_from_slice(bytes);
1798}
1799
1800pub(super) fn date_to_array(date: Date) -> [u8; size_of::<i32>()] {
1801 i32::to_le_bytes(date.pg_epoch_days())
1802}
1803
1804fn push_date<D>(data: &mut D, date: Date)
1805where
1806 D: Vector<u8>,
1807{
1808 data.extend_from_slice(&date_to_array(date));
1809}
1810
1811pub(super) fn naive_date_to_arrays(
1812 date: NaiveDate,
1813) -> ([u8; size_of::<i32>()], [u8; size_of::<u32>()]) {
1814 (
1815 i32::to_le_bytes(date.year()),
1816 u32::to_le_bytes(date.ordinal()),
1817 )
1818}
1819
1820fn push_naive_date<D>(data: &mut D, date: NaiveDate)
1821where
1822 D: Vector<u8>,
1823{
1824 let (ds1, ds2) = naive_date_to_arrays(date);
1825 data.extend_from_slice(&ds1);
1826 data.extend_from_slice(&ds2);
1827}
1828
1829pub(super) fn time_to_arrays(time: NaiveTime) -> ([u8; size_of::<u32>()], [u8; size_of::<u32>()]) {
1830 (
1831 u32::to_le_bytes(time.num_seconds_from_midnight()),
1832 u32::to_le_bytes(time.nanosecond()),
1833 )
1834}
1835
1836fn push_time<D>(data: &mut D, time: NaiveTime)
1837where
1838 D: Vector<u8>,
1839{
1840 let (ts1, ts2) = time_to_arrays(time);
1841 data.extend_from_slice(&ts1);
1842 data.extend_from_slice(&ts2);
1843}
1844
1845fn checked_timestamp_nanos(dt: NaiveDateTime) -> Option<i64> {
1855 let subsec_nanos = dt.and_utc().timestamp_subsec_nanos();
1856 if subsec_nanos >= 1_000_000_000 {
1857 return None;
1858 }
1859 let as_ns = dt.and_utc().timestamp().checked_mul(1_000_000_000)?;
1860 as_ns.checked_add(i64::from(subsec_nanos))
1861}
1862
1863#[inline(always)]
1869#[allow(clippy::as_conversions)]
1870fn min_bytes_signed<T>(i: T) -> u8
1871where
1872 T: Into<i64>,
1873{
1874 let i: i64 = i.into();
1875
1876 let n_sign_bits = if i.is_negative() {
1880 i.leading_ones() as u8
1881 } else {
1882 i.leading_zeros() as u8
1883 };
1884
1885 (64 - n_sign_bits + 7) / 8
1886}
1887
1888#[inline(always)]
1896#[allow(clippy::as_conversions)]
1897fn min_bytes_unsigned<T>(i: T) -> u8
1898where
1899 T: Into<u64>,
1900{
1901 let i: u64 = i.into();
1902
1903 let n_sign_bits = i.leading_zeros() as u8;
1904
1905 (64 - n_sign_bits + 7) / 8
1906}
1907
1908const TINY: usize = 1 << 8;
1909const SHORT: usize = 1 << 16;
1910const LONG: usize = 1 << 32;
1911
1912fn push_datum<D>(data: &mut D, datum: Datum)
1913where
1914 D: Vector<u8>,
1915{
1916 match datum {
1917 Datum::Null => data.push(Tag::Null.into()),
1918 Datum::False => data.push(Tag::False.into()),
1919 Datum::True => data.push(Tag::True.into()),
1920 Datum::Int16(i) => {
1921 let mbs = min_bytes_signed(i);
1922 let tag = u8::from(if i.is_negative() {
1923 Tag::NegativeInt16_0
1924 } else {
1925 Tag::NonNegativeInt16_0
1926 }) + mbs;
1927
1928 data.push(tag);
1929 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbs)]);
1930 }
1931 Datum::Int32(i) => {
1932 let mbs = min_bytes_signed(i);
1933 let tag = u8::from(if i.is_negative() {
1934 Tag::NegativeInt32_0
1935 } else {
1936 Tag::NonNegativeInt32_0
1937 }) + mbs;
1938
1939 data.push(tag);
1940 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbs)]);
1941 }
1942 Datum::Int64(i) => {
1943 let mbs = min_bytes_signed(i);
1944 let tag = u8::from(if i.is_negative() {
1945 Tag::NegativeInt64_0
1946 } else {
1947 Tag::NonNegativeInt64_0
1948 }) + mbs;
1949
1950 data.push(tag);
1951 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbs)]);
1952 }
1953 Datum::UInt8(i) => {
1954 let mbu = min_bytes_unsigned(i);
1955 let tag = u8::from(Tag::UInt8_0) + mbu;
1956 data.push(tag);
1957 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbu)]);
1958 }
1959 Datum::UInt16(i) => {
1960 let mbu = min_bytes_unsigned(i);
1961 let tag = u8::from(Tag::UInt16_0) + mbu;
1962 data.push(tag);
1963 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbu)]);
1964 }
1965 Datum::UInt32(i) => {
1966 let mbu = min_bytes_unsigned(i);
1967 let tag = u8::from(Tag::UInt32_0) + mbu;
1968 data.push(tag);
1969 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbu)]);
1970 }
1971 Datum::UInt64(i) => {
1972 let mbu = min_bytes_unsigned(i);
1973 let tag = u8::from(Tag::UInt64_0) + mbu;
1974 data.push(tag);
1975 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbu)]);
1976 }
1977 Datum::Float32(f) => {
1978 data.push(Tag::Float32.into());
1979 data.extend_from_slice(&f.to_bits().to_le_bytes());
1980 }
1981 Datum::Float64(f) => {
1982 data.push(Tag::Float64.into());
1983 data.extend_from_slice(&f.to_bits().to_le_bytes());
1984 }
1985 Datum::Date(d) => {
1986 data.push(Tag::Date.into());
1987 push_date(data, d);
1988 }
1989 Datum::Time(t) => {
1990 data.push(Tag::Time.into());
1991 push_time(data, t);
1992 }
1993 Datum::Timestamp(t) => {
1994 let datetime = t.to_naive();
1995 if let Some(nanos) = checked_timestamp_nanos(datetime) {
1996 data.push(Tag::CheapTimestamp.into());
1997 data.extend_from_slice(&nanos.to_le_bytes());
1998 } else {
1999 data.push(Tag::Timestamp.into());
2000 push_naive_date(data, datetime.date());
2001 push_time(data, datetime.time());
2002 }
2003 }
2004 Datum::TimestampTz(t) => {
2005 let datetime = t.to_naive();
2006 if let Some(nanos) = checked_timestamp_nanos(datetime) {
2007 data.push(Tag::CheapTimestampTz.into());
2008 data.extend_from_slice(&nanos.to_le_bytes());
2009 } else {
2010 data.push(Tag::TimestampTz.into());
2011 push_naive_date(data, datetime.date());
2012 push_time(data, datetime.time());
2013 }
2014 }
2015 Datum::Interval(i) => {
2016 data.push(Tag::Interval.into());
2017 data.extend_from_slice(&i.months.to_le_bytes());
2018 data.extend_from_slice(&i.days.to_le_bytes());
2019 data.extend_from_slice(&i.micros.to_le_bytes());
2020 }
2021 Datum::Bytes(bytes) => {
2022 let tag = match bytes.len() {
2023 0..TINY => Tag::BytesTiny,
2024 TINY..SHORT => Tag::BytesShort,
2025 SHORT..LONG => Tag::BytesLong,
2026 _ => Tag::BytesHuge,
2027 };
2028 data.push(tag.into());
2029 push_lengthed_bytes(data, bytes, tag);
2030 }
2031 Datum::String(string) => {
2032 let tag = match string.len() {
2033 0..TINY => Tag::StringTiny,
2034 TINY..SHORT => Tag::StringShort,
2035 SHORT..LONG => Tag::StringLong,
2036 _ => Tag::StringHuge,
2037 };
2038 data.push(tag.into());
2039 push_lengthed_bytes(data, string.as_bytes(), tag);
2040 }
2041 Datum::List(list) => {
2042 let tag = match list.data.len() {
2043 0..TINY => Tag::ListTiny,
2044 TINY..SHORT => Tag::ListShort,
2045 SHORT..LONG => Tag::ListLong,
2046 _ => Tag::ListHuge,
2047 };
2048 data.push(tag.into());
2049 push_lengthed_bytes(data, list.data, tag);
2050 }
2051 Datum::Uuid(u) => {
2052 data.push(Tag::Uuid.into());
2053 data.extend_from_slice(u.as_bytes());
2054 }
2055 Datum::Array(array) => {
2056 data.push(Tag::Array.into());
2059 data.push(array.dims.ndims());
2060 data.extend_from_slice(array.dims.data);
2061 push_untagged_bytes(data, array.elements.data);
2062 }
2063 Datum::Map(dict) => {
2064 data.push(Tag::Dict.into());
2065 push_untagged_bytes(data, dict.data);
2066 }
2067 Datum::JsonNull => data.push(Tag::JsonNull.into()),
2068 Datum::MzTimestamp(t) => {
2069 data.push(Tag::MzTimestamp.into());
2070 data.extend_from_slice(&t.encode());
2071 }
2072 Datum::Dummy => data.push(Tag::Dummy.into()),
2073 Datum::Numeric(mut n) => {
2074 numeric::cx_datum().reduce(&mut n.0);
2079 let (digits, exponent, bits, lsu) = n.0.to_raw_parts();
2080 data.push(Tag::Numeric.into());
2081 data.push(u8::try_from(digits).expect("digits to fit within u8; should not exceed 39"));
2082 data.push(
2083 i8::try_from(exponent)
2084 .expect("exponent to fit within i8; should not exceed +/- 39")
2085 .to_le_bytes()[0],
2086 );
2087 data.push(bits);
2088
2089 let lsu = &lsu[..Numeric::digits_to_lsu_elements_len(digits)];
2090
2091 if cfg!(target_endian = "little") {
2093 let (prefix, lsu_bytes, suffix) = unsafe { lsu.align_to::<u8>() };
2096 soft_assert_no_log!(
2099 lsu_bytes.len() == Numeric::digits_to_lsu_elements_len(digits) * 2,
2100 "u8 version of numeric LSU contained the wrong number of elements; expected {}, but got {}",
2101 Numeric::digits_to_lsu_elements_len(digits) * 2,
2102 lsu_bytes.len()
2103 );
2104 soft_assert_no_log!(prefix.is_empty() && suffix.is_empty());
2106 data.extend_from_slice(lsu_bytes);
2107 } else {
2108 for u in lsu {
2109 data.extend_from_slice(&u.to_le_bytes());
2110 }
2111 }
2112 }
2113 Datum::Range(range) => {
2114 data.push(Tag::Range.into());
2116 data.push(range.internal_flag_bits());
2117
2118 if let Some(RangeInner { lower, upper }) = range.inner {
2119 for bound in [lower.bound, upper.bound] {
2120 if let Some(bound) = bound {
2121 match bound.datum() {
2122 Datum::Null => panic!("cannot push Datum::Null into range"),
2123 d => push_datum::<D>(data, d),
2124 }
2125 }
2126 }
2127 }
2128 }
2129 Datum::MzAclItem(mz_acl_item) => {
2130 data.push(Tag::MzAclItem.into());
2131 data.extend_from_slice(&mz_acl_item.encode_binary());
2132 }
2133 Datum::AclItem(acl_item) => {
2134 data.push(Tag::AclItem.into());
2135 data.extend_from_slice(&acl_item.encode_binary());
2136 }
2137 }
2138}
2139
2140pub fn row_size<'a, I>(a: I) -> usize
2142where
2143 I: IntoIterator<Item = Datum<'a>>,
2144{
2145 let sz = datums_size::<_, _>(a);
2150 let size_of_row = std::mem::size_of::<Row>();
2151 if sz > Row::SIZE {
2155 sz + size_of_row
2156 } else {
2157 size_of_row
2158 }
2159}
2160
2161pub fn datum_size(datum: &Datum) -> usize {
2164 match datum {
2165 Datum::Null => 1,
2166 Datum::False => 1,
2167 Datum::True => 1,
2168 Datum::Int16(i) => 1 + usize::from(min_bytes_signed(*i)),
2169 Datum::Int32(i) => 1 + usize::from(min_bytes_signed(*i)),
2170 Datum::Int64(i) => 1 + usize::from(min_bytes_signed(*i)),
2171 Datum::UInt8(i) => 1 + usize::from(min_bytes_unsigned(*i)),
2172 Datum::UInt16(i) => 1 + usize::from(min_bytes_unsigned(*i)),
2173 Datum::UInt32(i) => 1 + usize::from(min_bytes_unsigned(*i)),
2174 Datum::UInt64(i) => 1 + usize::from(min_bytes_unsigned(*i)),
2175 Datum::Float32(_) => 1 + size_of::<f32>(),
2176 Datum::Float64(_) => 1 + size_of::<f64>(),
2177 Datum::Date(_) => 1 + size_of::<i32>(),
2178 Datum::Time(_) => 1 + 8,
2179 Datum::Timestamp(t) => {
2180 1 + if checked_timestamp_nanos(t.to_naive()).is_some() {
2181 8
2182 } else {
2183 16
2184 }
2185 }
2186 Datum::TimestampTz(t) => {
2187 1 + if checked_timestamp_nanos(t.naive_utc()).is_some() {
2188 8
2189 } else {
2190 16
2191 }
2192 }
2193 Datum::Interval(_) => 1 + size_of::<i32>() + size_of::<i32>() + size_of::<i64>(),
2194 Datum::Bytes(bytes) => {
2195 let bytes_for_length = match bytes.len() {
2197 0..TINY => 1,
2198 TINY..SHORT => 2,
2199 SHORT..LONG => 4,
2200 _ => 8,
2201 };
2202 1 + bytes_for_length + bytes.len()
2203 }
2204 Datum::String(string) => {
2205 let bytes_for_length = match string.len() {
2207 0..TINY => 1,
2208 TINY..SHORT => 2,
2209 SHORT..LONG => 4,
2210 _ => 8,
2211 };
2212 1 + bytes_for_length + string.len()
2213 }
2214 Datum::Uuid(_) => 1 + size_of::<uuid::Bytes>(),
2215 Datum::Array(array) => {
2216 1 + size_of::<u8>()
2217 + array.dims.data.len()
2218 + size_of::<u64>()
2219 + array.elements.data.len()
2220 }
2221 Datum::List(list) => 1 + size_of::<u64>() + list.data.len(),
2222 Datum::Map(dict) => 1 + size_of::<u64>() + dict.data.len(),
2223 Datum::JsonNull => 1,
2224 Datum::MzTimestamp(_) => 1 + size_of::<Timestamp>(),
2225 Datum::Dummy => 1,
2226 Datum::Numeric(d) => {
2227 let mut d = d.0.clone();
2228 numeric::cx_datum().reduce(&mut d);
2231 4 + (d.coefficient_units().len() * 2)
2233 }
2234 Datum::Range(Range { inner }) => {
2235 2 + match inner {
2237 None => 0,
2238 Some(RangeInner { lower, upper }) => [lower.bound, upper.bound]
2239 .iter()
2240 .map(|bound| match bound {
2241 None => 0,
2242 Some(bound) => bound.val.len(),
2243 })
2244 .sum(),
2245 }
2246 }
2247 Datum::MzAclItem(_) => 1 + MzAclItem::binary_size(),
2248 Datum::AclItem(_) => 1 + AclItem::binary_size(),
2249 }
2250}
2251
2252pub fn datums_size<'a, I, D>(iter: I) -> usize
2257where
2258 I: IntoIterator<Item = D>,
2259 D: Borrow<Datum<'a>>,
2260{
2261 iter.into_iter().map(|d| datum_size(d.borrow())).sum()
2262}
2263
2264pub fn datum_list_size<'a, I, D>(iter: I) -> usize
2269where
2270 I: IntoIterator<Item = D>,
2271 D: Borrow<Datum<'a>>,
2272{
2273 1 + size_of::<u64>() + datums_size(iter)
2274}
2275
2276impl RowPacker<'_> {
2277 pub fn for_existing_row(row: &mut Row) -> RowPacker<'_> {
2284 RowPacker { row }
2285 }
2286
2287 #[inline]
2289 pub fn push<'a, D>(&mut self, datum: D)
2290 where
2291 D: Borrow<Datum<'a>>,
2292 {
2293 push_datum(&mut self.row.data, *datum.borrow());
2294 }
2295
2296 #[inline]
2298 pub fn extend<'a, I, D>(&mut self, iter: I)
2299 where
2300 I: IntoIterator<Item = D>,
2301 D: Borrow<Datum<'a>>,
2302 {
2303 for datum in iter {
2304 push_datum(&mut self.row.data, *datum.borrow())
2305 }
2306 }
2307
2308 #[inline]
2314 pub fn try_extend<'a, I, E, D>(&mut self, iter: I) -> Result<(), E>
2315 where
2316 I: IntoIterator<Item = Result<D, E>>,
2317 D: Borrow<Datum<'a>>,
2318 {
2319 for datum in iter {
2320 push_datum(&mut self.row.data, *datum?.borrow());
2321 }
2322 Ok(())
2323 }
2324
2325 pub fn extend_by_row(&mut self, row: &Row) {
2327 self.row.data.extend_from_slice(row.data.as_slice());
2328 }
2329
2330 pub fn extend_by_row_ref(&mut self, row: &RowRef) {
2332 self.row.data.extend_from_slice(row.data());
2333 }
2334
2335 #[inline]
2343 pub unsafe fn extend_by_slice_unchecked(&mut self, data: &[u8]) {
2344 self.row.data.extend_from_slice(data)
2345 }
2346
2347 #[inline]
2369 pub fn push_list_with<F, R>(&mut self, f: F) -> R
2370 where
2371 F: FnOnce(&mut RowPacker) -> R,
2372 {
2373 let start = self.row.data.len();
2376 self.row.data.push(Tag::ListTiny.into());
2377 self.row.data.push(0);
2379
2380 let out = f(self);
2381
2382 let len = self.row.data.len() - start - 1 - 1;
2384 if len < TINY {
2386 self.row.data[start + 1] = len.to_le_bytes()[0];
2388 } else {
2389 long_list(&mut self.row.data, start, len);
2392 }
2393
2394 #[cold]
2401 fn long_list(data: &mut CompactBytes, start: usize, len: usize) {
2402 let long_list_inner = |data: &mut CompactBytes, len_len| {
2405 const ZEROS: [u8; 8] = [0; 8];
2408 data.extend_from_slice(&ZEROS[0..len_len - 1]);
2409 data.copy_within(start + 1 + 1..start + 1 + 1 + len, start + 1 + len_len);
2418 data[start + 1..start + 1 + len_len]
2420 .copy_from_slice(&len.to_le_bytes()[0..len_len]);
2421 };
2422 match len {
2423 0..TINY => {
2424 unreachable!()
2425 }
2426 TINY..SHORT => {
2427 data[start] = Tag::ListShort.into();
2428 long_list_inner(data, 2);
2429 }
2430 SHORT..LONG => {
2431 data[start] = Tag::ListLong.into();
2432 long_list_inner(data, 4);
2433 }
2434 _ => {
2435 data[start] = Tag::ListHuge.into();
2436 long_list_inner(data, 8);
2437 }
2438 };
2439 }
2440
2441 out
2442 }
2443
2444 pub fn push_dict_with<F, R>(&mut self, f: F) -> R
2482 where
2483 F: FnOnce(&mut RowPacker) -> R,
2484 {
2485 self.row.data.push(Tag::Dict.into());
2486 let start = self.row.data.len();
2487 self.row.data.extend_from_slice(&[0; size_of::<u64>()]);
2489
2490 let res = f(self);
2491
2492 let len = u64::cast_from(self.row.data.len() - start - size_of::<u64>());
2493 self.row.data[start..start + size_of::<u64>()].copy_from_slice(&len.to_le_bytes());
2495
2496 res
2497 }
2498
2499 pub fn try_push_dict_with<F, E>(&mut self, f: F) -> Result<(), E>
2501 where
2502 F: FnOnce(&mut RowPacker) -> Result<(), E>,
2503 {
2504 self.push_dict_with(f)
2505 }
2506
2507 pub fn try_push_array<'a, I, D>(
2514 &mut self,
2515 dims: &[ArrayDimension],
2516 iter: I,
2517 ) -> Result<(), InvalidArrayError>
2518 where
2519 I: IntoIterator<Item = D>,
2520 D: Borrow<Datum<'a>>,
2521 {
2522 unsafe {
2524 self.push_array_with_unchecked(dims, |packer| {
2525 let mut nelements = 0;
2526 for datum in iter {
2527 packer.push(datum);
2528 nelements += 1;
2529 }
2530 Ok::<_, InvalidArrayError>(nelements)
2531 })
2532 }
2533 }
2534
2535 pub fn try_push_array_fallible<'a, I, D, E>(
2538 &mut self,
2539 dims: &[ArrayDimension],
2540 iter: I,
2541 ) -> Result<Result<(), E>, InvalidArrayError>
2542 where
2543 I: IntoIterator<Item = Result<D, E>>,
2544 D: Borrow<Datum<'a>>,
2545 {
2546 enum Error<E> {
2547 Usage(InvalidArrayError),
2548 Inner(E),
2549 }
2550
2551 impl<E> From<InvalidArrayError> for Error<E> {
2552 fn from(e: InvalidArrayError) -> Self {
2553 Self::Usage(e)
2554 }
2555 }
2556
2557 let result = unsafe {
2559 self.push_array_with_unchecked(dims, |packer| {
2560 let mut nelements = 0;
2561 for datum in iter {
2562 packer.push(datum.map_err(Error::Inner)?);
2563 nelements += 1;
2564 }
2565 Ok(nelements)
2566 })
2567 };
2568 match result {
2569 Ok(()) => Ok(Ok(())),
2570 Err(Error::Usage(e)) => Err(e),
2571 Err(Error::Inner(e)) => Ok(Err(e)),
2572 }
2573 }
2574
2575 pub unsafe fn push_array_with_unchecked<F, E>(
2584 &mut self,
2585 dims: &[ArrayDimension],
2586 f: F,
2587 ) -> Result<(), E>
2588 where
2589 F: FnOnce(&mut RowPacker) -> Result<usize, E>,
2590 E: From<InvalidArrayError>,
2591 {
2592 if dims.len() > usize::from(MAX_ARRAY_DIMENSIONS) {
2604 return Err(InvalidArrayError::TooManyDimensions(dims.len()).into());
2605 }
2606
2607 let start = self.row.data.len();
2608 self.row.data.push(Tag::Array.into());
2609
2610 self.row
2612 .data
2613 .push(dims.len().try_into().expect("ndims verified to fit in u8"));
2614 for dim in dims {
2615 self.row
2616 .data
2617 .extend_from_slice(&i64::cast_from(dim.lower_bound).to_le_bytes());
2618 self.row
2619 .data
2620 .extend_from_slice(&u64::cast_from(dim.length).to_le_bytes());
2621 }
2622
2623 let off = self.row.data.len();
2625 self.row.data.extend_from_slice(&[0; size_of::<u64>()]);
2626 let nelements = match f(self) {
2627 Ok(nelements) => nelements,
2628 Err(e) => {
2629 self.row.data.truncate(start);
2630 return Err(e);
2631 }
2632 };
2633 let len = u64::cast_from(self.row.data.len() - off - size_of::<u64>());
2634 self.row.data[off..off + size_of::<u64>()].copy_from_slice(&len.to_le_bytes());
2635
2636 let cardinality = match dims {
2639 [] => 0,
2640 dims => dims
2648 .iter()
2649 .map(|d| d.length)
2650 .fold(1usize, usize::saturating_mul),
2651 };
2652 if nelements != cardinality {
2653 self.row.data.truncate(start);
2654 return Err(InvalidArrayError::WrongCardinality {
2655 actual: nelements,
2656 expected: cardinality,
2657 }
2658 .into());
2659 }
2660
2661 Ok(())
2662 }
2663
2664 pub fn push_array_with_row_major<F, I>(
2674 &mut self,
2675 dims: I,
2676 f: F,
2677 ) -> Result<(), InvalidArrayError>
2678 where
2679 I: IntoIterator<Item = ArrayDimension>,
2680 F: FnOnce(&mut RowPacker) -> usize,
2681 {
2682 let start = self.row.data.len();
2683 self.row.data.push(Tag::Array.into());
2684
2685 let dims_start = self.row.data.len();
2687 self.row.data.push(42);
2688
2689 let mut num_dims: u8 = 0;
2690 let mut cardinality: usize = 1;
2691 for dim in dims {
2692 num_dims += 1;
2693 cardinality = cardinality.saturating_mul(dim.length);
2697
2698 self.row
2699 .data
2700 .extend_from_slice(&i64::cast_from(dim.lower_bound).to_le_bytes());
2701 self.row
2702 .data
2703 .extend_from_slice(&u64::cast_from(dim.length).to_le_bytes());
2704 }
2705
2706 if num_dims > MAX_ARRAY_DIMENSIONS {
2707 self.row.data.truncate(start);
2709 return Err(InvalidArrayError::TooManyDimensions(usize::from(num_dims)));
2710 }
2711 self.row.data[dims_start..dims_start + size_of::<u8>()]
2713 .copy_from_slice(&num_dims.to_le_bytes());
2714
2715 let off = self.row.data.len();
2717 self.row.data.extend_from_slice(&[0; size_of::<u64>()]);
2718
2719 let nelements = f(self);
2720
2721 let len = u64::cast_from(self.row.data.len() - off - size_of::<u64>());
2722 self.row.data[off..off + size_of::<u64>()].copy_from_slice(&len.to_le_bytes());
2723
2724 let cardinality = match num_dims {
2727 0 => 0,
2728 _ => cardinality,
2729 };
2730 if nelements != cardinality {
2731 self.row.data.truncate(start);
2732 return Err(InvalidArrayError::WrongCardinality {
2733 actual: nelements,
2734 expected: cardinality,
2735 });
2736 }
2737
2738 Ok(())
2739 }
2740
2741 pub fn push_list<'a, I, D>(&mut self, iter: I)
2745 where
2746 I: IntoIterator<Item = D>,
2747 D: Borrow<Datum<'a>>,
2748 {
2749 self.push_list_with(|packer| {
2750 for elem in iter {
2751 packer.push(*elem.borrow())
2752 }
2753 });
2754 }
2755
2756 pub fn push_dict<'a, I, D>(&mut self, iter: I)
2758 where
2759 I: IntoIterator<Item = (&'a str, D)>,
2760 D: Borrow<Datum<'a>>,
2761 {
2762 self.push_dict_with(|packer| {
2763 for (k, v) in iter {
2764 packer.push(Datum::String(k));
2765 packer.push(*v.borrow())
2766 }
2767 })
2768 }
2769
2770 pub fn push_range<'a>(&mut self, mut range: Range<Datum<'a>>) -> Result<(), InvalidRangeError> {
2786 range.canonicalize()?;
2787 match range.inner {
2788 None => {
2789 self.row.data.push(Tag::Range.into());
2790 self.row.data.push(range::InternalFlags::EMPTY.bits());
2792 Ok(())
2793 }
2794 Some(inner) => self.push_range_with(
2795 RangeLowerBound {
2796 inclusive: inner.lower.inclusive,
2797 bound: inner
2798 .lower
2799 .bound
2800 .map(|value| move |row: &mut RowPacker| Ok(row.push(value))),
2801 },
2802 RangeUpperBound {
2803 inclusive: inner.upper.inclusive,
2804 bound: inner
2805 .upper
2806 .bound
2807 .map(|value| move |row: &mut RowPacker| Ok(row.push(value))),
2808 },
2809 ),
2810 }
2811 }
2812
2813 pub fn push_range_with<L, U, E>(
2836 &mut self,
2837 lower: RangeLowerBound<L>,
2838 upper: RangeUpperBound<U>,
2839 ) -> Result<(), E>
2840 where
2841 L: FnOnce(&mut RowPacker) -> Result<(), E>,
2842 U: FnOnce(&mut RowPacker) -> Result<(), E>,
2843 E: From<InvalidRangeError>,
2844 {
2845 let start = self.row.data.len();
2846 self.row.data.push(Tag::Range.into());
2847
2848 let mut flags = range::InternalFlags::empty();
2849
2850 flags.set(range::InternalFlags::LB_INFINITE, lower.bound.is_none());
2851 flags.set(range::InternalFlags::UB_INFINITE, upper.bound.is_none());
2852 flags.set(range::InternalFlags::LB_INCLUSIVE, lower.inclusive);
2853 flags.set(range::InternalFlags::UB_INCLUSIVE, upper.inclusive);
2854
2855 let mut expected_datums = 0;
2856
2857 self.row.data.push(flags.bits());
2858
2859 let datum_check = self.row.data.len();
2860
2861 if let Some(value) = lower.bound {
2862 let start = self.row.data.len();
2863 value(self)?;
2864 assert!(
2865 start < self.row.data.len(),
2866 "finite values must each push exactly one value; expected 1 but got 0"
2867 );
2868 expected_datums += 1;
2869 }
2870
2871 if let Some(value) = upper.bound {
2872 let start = self.row.data.len();
2873 value(self)?;
2874 assert!(
2875 start < self.row.data.len(),
2876 "finite values must each push exactly one value; expected 1 but got 0"
2877 );
2878 expected_datums += 1;
2879 }
2880
2881 let mut actual_datums = 0;
2885 let mut seen = None;
2886 let mut dataz = &self.row.data[datum_check..];
2887 while !dataz.is_empty() {
2888 let d = unsafe { read_datum(&mut dataz) };
2889 if d == Datum::Null {
2893 self.row.data.truncate(start);
2894 return Err(InvalidRangeError::InvalidRangeData.into());
2895 }
2896
2897 match seen {
2898 None => seen = Some(d),
2899 Some(seen) => {
2900 let seen_kind = DatumKind::from(seen);
2901 let d_kind = DatumKind::from(d);
2902 if seen_kind != d_kind {
2903 self.row.data.truncate(start);
2904 return Err(InvalidRangeError::InvalidRangeData.into());
2905 }
2906
2907 if seen > d {
2908 self.row.data.truncate(start);
2909 return Err(InvalidRangeError::MisorderedRangeBounds.into());
2910 }
2911 }
2912 }
2913 actual_datums += 1;
2914 }
2915
2916 if actual_datums != expected_datums {
2917 self.row.data.truncate(start);
2918 return Err(InvalidRangeError::InvalidRangeData.into());
2919 }
2920
2921 Ok(())
2922 }
2923
2924 pub fn clear(&mut self) {
2926 self.row.data.clear();
2927 }
2928
2929 pub unsafe fn truncate(&mut self, pos: usize) {
2942 self.row.data.truncate(pos)
2943 }
2944
2945 pub fn truncate_datums(&mut self, n: usize) {
2947 let prev_len = self.row.data.len();
2948 let mut iter = self.row.iter();
2949 for _ in iter.by_ref().take(n) {}
2950 let next_len = iter.data.len();
2951 unsafe { self.truncate(prev_len - next_len) }
2953 }
2954
2955 pub fn byte_len(&self) -> usize {
2957 self.row.byte_len()
2958 }
2959}
2960
2961impl<'a> IntoIterator for &'a Row {
2962 type Item = Datum<'a>;
2963 type IntoIter = DatumListIter<'a>;
2964 fn into_iter(self) -> DatumListIter<'a> {
2965 self.iter()
2966 }
2967}
2968
2969impl fmt::Debug for Row {
2970 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2972 f.write_str("Row{")?;
2973 f.debug_list().entries(self.iter()).finish()?;
2974 f.write_str("}")
2975 }
2976}
2977
2978impl fmt::Display for Row {
2979 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2981 f.write_str("(")?;
2982 for (i, datum) in self.iter().enumerate() {
2983 if i != 0 {
2984 f.write_str(", ")?;
2985 }
2986 write!(f, "{}", datum)?;
2987 }
2988 f.write_str(")")
2989 }
2990}
2991
2992impl<'a, T> DatumList<'a, T> {
2993 pub fn iter(&self) -> DatumListIter<'a> {
2994 DatumListIter { data: self.data }
2995 }
2996
2997 pub fn typed_iter(&self) -> DatumListTypedIter<'a, T>
3003 where
3004 T: FromDatum<'a>,
3005 {
3006 DatumListTypedIter {
3007 inner: self.iter(),
3008 _phantom: PhantomData,
3009 }
3010 }
3011
3012 pub fn data(&self) -> &'a [u8] {
3014 self.data
3015 }
3016}
3017
3018impl<T> DatumList<'static, T> {
3019 pub fn empty() -> Self {
3020 DatumList::new(&[])
3021 }
3022}
3023
3024impl<'a> IntoIterator for DatumList<'a> {
3025 type Item = Datum<'a>;
3026 type IntoIter = DatumListIter<'a>;
3027 fn into_iter(self) -> DatumListIter<'a> {
3028 self.iter()
3029 }
3030}
3031
3032impl<'a> Iterator for DatumListIter<'a> {
3033 type Item = Datum<'a>;
3034 fn next(&mut self) -> Option<Self::Item> {
3035 if self.data.is_empty() {
3036 None
3037 } else {
3038 Some(unsafe { read_datum(&mut self.data) })
3039 }
3040 }
3041}
3042
3043impl<'a, T: FromDatum<'a>> Iterator for DatumListTypedIter<'a, T> {
3044 type Item = T;
3045 fn next(&mut self) -> Option<Self::Item> {
3046 self.inner.next().map(T::from_datum)
3047 }
3048}
3049
3050impl<'a, T> DatumMap<'a, T> {
3051 pub fn iter(&self) -> DatumDictIter<'a> {
3052 DatumDictIter {
3053 data: self.data,
3054 prev_key: None,
3055 }
3056 }
3057
3058 pub fn typed_iter(&self) -> DatumDictTypedIter<'a, T>
3064 where
3065 T: FromDatum<'a>,
3066 {
3067 DatumDictTypedIter {
3068 inner: self.iter(),
3069 _phantom: PhantomData,
3070 }
3071 }
3072
3073 pub fn data(&self) -> &'a [u8] {
3075 self.data
3076 }
3077}
3078
3079impl<T> DatumMap<'static, T> {
3080 pub fn empty() -> Self {
3081 DatumMap::new(&[])
3082 }
3083}
3084
3085impl<'a, T> Debug for DatumMap<'a, T> {
3086 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3087 f.debug_map().entries(self.iter()).finish()
3088 }
3089}
3090
3091impl<'a> IntoIterator for &'a DatumMap<'a> {
3092 type Item = (&'a str, Datum<'a>);
3093 type IntoIter = DatumDictIter<'a>;
3094 fn into_iter(self) -> DatumDictIter<'a> {
3095 self.iter()
3096 }
3097}
3098
3099impl<'a> Iterator for DatumDictIter<'a> {
3100 type Item = (&'a str, Datum<'a>);
3101 fn next(&mut self) -> Option<Self::Item> {
3102 if self.data.is_empty() {
3103 None
3104 } else {
3105 let key_tag =
3106 Tag::try_from_primitive(read_byte(&mut self.data)).expect("unknown row tag");
3107 assert!(
3108 key_tag == Tag::StringTiny
3109 || key_tag == Tag::StringShort
3110 || key_tag == Tag::StringLong
3111 || key_tag == Tag::StringHuge,
3112 "Dict keys must be strings, got {:?}",
3113 key_tag
3114 );
3115 let key = unsafe { read_lengthed_datum(&mut self.data, key_tag).unwrap_str() };
3116 let val = unsafe { read_datum(&mut self.data) };
3117
3118 if mz_ore::assert::soft_assertions_enabled() {
3121 if let Some(prev_key) = self.prev_key {
3122 mz_ore::soft_assert_no_log!(
3123 prev_key < key,
3124 "Dict keys must be unique and given in ascending order: {} came before {}",
3125 prev_key,
3126 key
3127 );
3128 }
3129 self.prev_key = Some(key);
3130 }
3131
3132 Some((key, val))
3133 }
3134 }
3135}
3136
3137impl<'a, T: FromDatum<'a>> Iterator for DatumDictTypedIter<'a, T> {
3138 type Item = (&'a str, T);
3139 fn next(&mut self) -> Option<Self::Item> {
3140 self.inner.next().map(|(k, v)| (k, T::from_datum(v)))
3141 }
3142}
3143
3144impl RowArena {
3145 pub fn new() -> Self {
3146 RowArena {
3147 inner: RefCell::new(vec![]),
3148 scratch: RefCell::new(None),
3149 budget: None,
3150 allocated: Cell::new(0),
3151 }
3152 }
3153
3154 pub fn with_budget(budget: usize) -> Self {
3171 RowArena {
3172 budget: Some(budget),
3173 ..RowArena::new()
3174 }
3175 }
3176
3177 pub fn allocated_bytes(&self) -> usize {
3179 self.allocated.get()
3180 }
3181
3182 pub fn over_budget(&self) -> bool {
3184 self.budget
3185 .is_some_and(|budget| self.allocated.get() > budget)
3186 }
3187
3188 pub fn budget_remaining(&self) -> usize {
3194 match self.budget {
3195 None => usize::MAX,
3196 Some(budget) => budget.saturating_sub(self.allocated.get()),
3197 }
3198 }
3199
3200 pub fn with_capacity(capacity: usize) -> Self {
3203 let mut inner = Vec::new();
3204 if capacity > 0 {
3205 inner.push(Vec::with_capacity(capacity));
3206 }
3207 RowArena {
3208 inner: RefCell::new(inner),
3209 ..RowArena::new()
3210 }
3211 }
3212
3213 pub fn reserve(&self, additional: usize) {
3216 if additional == 0 {
3217 return;
3218 }
3219 let mut inner = self.inner.borrow_mut();
3220 match inner.last_mut() {
3221 Some(active) if active.is_empty() => {
3224 if active.capacity() < additional {
3225 active.reserve_exact(additional);
3226 }
3227 }
3228 Some(active) => {
3233 let new_cap = std::cmp::max(additional, active.capacity().saturating_mul(2));
3234 inner.push(Vec::with_capacity(new_cap));
3235 }
3236 None => inner.push(Vec::with_capacity(additional)),
3237 }
3238 }
3239
3240 #[allow(clippy::transmute_ptr_to_ptr)]
3245 pub fn push_bytes<'a, B: Deref<Target = [u8]>>(&'a self, bytes: B) -> &'a [u8] {
3246 let bytes: &[u8] = &bytes;
3247 let need = bytes.len();
3248 if need == 0 {
3249 return &[];
3250 }
3251 let mut inner = self.inner.borrow_mut();
3252
3253 let has_room = inner
3256 .last()
3257 .map_or(false, |region| region.capacity() - region.len() >= need);
3258 if !has_room {
3259 let last_cap = inner.last().map_or(0, |region| region.capacity());
3260 let new_cap = std::cmp::max(need, last_cap.saturating_mul(2));
3261 inner.push(Vec::with_capacity(new_cap));
3262 }
3263
3264 let region = inner.last_mut().expect("region present");
3265 let start = region.len();
3266 region.extend_from_slice(bytes);
3267 self.allocated.set(self.allocated.get() + need);
3268 let copied = ®ion[start..];
3269 unsafe {
3270 transmute::<&[u8], &'a [u8]>(copied)
3280 }
3281 }
3282
3283 pub fn push_owned_bytes<'a>(&'a self, bytes: Vec<u8>) -> &'a [u8] {
3290 const MIN_ADOPT_BYTES: usize = 4 * 1024;
3294
3295 let need = bytes.len();
3296 if need == 0 {
3297 return &[];
3298 }
3299
3300 let mut inner = self.inner.borrow_mut();
3301 let last_cap = inner.last().map_or(0, |region| region.capacity());
3308 let adopt = need > std::cmp::max(MIN_ADOPT_BYTES, last_cap.saturating_mul(2));
3309 if !adopt {
3310 drop(inner);
3311 return self.push_bytes(&bytes[..]);
3312 }
3313
3314 self.allocated.set(self.allocated.get() + need);
3323 let idx = inner.len().saturating_sub(1);
3324 inner.insert(idx, bytes);
3325 if inner.len() == 1 {
3326 inner.push(Vec::new());
3329 }
3330 let adopted = &inner[idx][..];
3331 unsafe { transmute::<&[u8], &'a [u8]>(adopted) }
3332 }
3333
3334 pub fn push_string<'a>(&'a self, string: String) -> &'a str {
3336 let copied = self.push_owned_bytes(string.into_bytes());
3337 unsafe {
3338 std::str::from_utf8_unchecked(copied)
3340 }
3341 }
3342
3343 pub fn writer(&self) -> RowArenaBuf<'_> {
3355 let mut buf = self.scratch.borrow_mut().take().unwrap_or_default();
3359 buf.clear();
3360 RowArenaBuf { arena: self, buf }
3361 }
3362
3363 pub fn push_unary_row<'a>(&'a self, row: Row) -> Datum<'a> {
3369 let copied = self.push_bytes(row.data());
3370 unsafe {
3371 let datum = read_datum(&mut &copied[..]);
3375 transmute::<Datum<'_>, Datum<'a>>(datum)
3376 }
3377 }
3378
3379 fn push_unary_row_datum_nested<'a>(&'a self, row: Row) -> DatumNested<'a> {
3382 let copied = self.push_bytes(row.data());
3383 unsafe {
3384 let nested = DatumNested::extract(&mut &copied[..]);
3386 transmute::<DatumNested<'_>, DatumNested<'a>>(nested)
3387 }
3388 }
3389
3390 pub fn make_datum<'a, F>(&'a self, f: F) -> Datum<'a>
3402 where
3403 F: FnOnce(&mut RowPacker),
3404 {
3405 let mut row = Row::default();
3406 f(&mut row.packer());
3407 self.push_unary_row(row)
3408 }
3409
3410 pub fn make_datum_list<'a, T: std::borrow::Borrow<Datum<'a>>>(
3417 &'a self,
3418 iter: impl IntoIterator<Item = T>,
3419 ) -> DatumList<'a, T> {
3420 let datum = self.make_datum(|packer| {
3421 packer.push_list_with(|packer| {
3422 for elem in iter {
3423 packer.push(*elem.borrow());
3424 }
3425 });
3426 });
3427 DatumList::new(datum.unwrap_list().data())
3428 }
3429
3430 pub fn make_datum_nested<'a, F>(&'a self, f: F) -> DatumNested<'a>
3433 where
3434 F: FnOnce(&mut RowPacker),
3435 {
3436 let mut row = Row::default();
3437 f(&mut row.packer());
3438 self.push_unary_row_datum_nested(row)
3439 }
3440
3441 pub fn try_make_datum<'a, F, E>(&'a self, f: F) -> Result<Datum<'a>, E>
3443 where
3444 F: FnOnce(&mut RowPacker) -> Result<(), E>,
3445 {
3446 let mut row = Row::default();
3447 f(&mut row.packer())?;
3448 Ok(self.push_unary_row(row))
3449 }
3450
3451 pub fn clear(&mut self) {
3456 let inner = self.inner.get_mut();
3457 if let Some(largest) = (0..inner.len()).max_by_key(|&i| inner[i].capacity()) {
3461 inner.swap(0, largest);
3462 inner.truncate(1);
3463 inner[0].clear();
3464 }
3465 self.allocated.set(0);
3466 }
3467}
3468
3469impl Default for RowArena {
3470 fn default() -> RowArena {
3471 RowArena::new()
3472 }
3473}
3474
3475#[derive(Debug)]
3482pub struct RowArenaBuf<'a> {
3483 arena: &'a RowArena,
3484 buf: Vec<u8>,
3485}
3486
3487impl<'a> RowArenaBuf<'a> {
3488 pub fn push(&mut self, byte: u8) {
3490 self.buf.push(byte);
3491 }
3492
3493 pub fn extend_from_slice(&mut self, bytes: &[u8]) {
3495 self.buf.extend_from_slice(bytes);
3496 }
3497
3498 pub fn as_slice(&self) -> &[u8] {
3500 &self.buf
3501 }
3502
3503 pub fn len(&self) -> usize {
3505 self.buf.len()
3506 }
3507
3508 pub fn is_empty(&self) -> bool {
3510 self.buf.is_empty()
3511 }
3512
3513 pub fn finish(self) -> &'a [u8] {
3515 self.arena.push_bytes(self.buf.as_slice())
3518 }
3519
3520 pub fn finish_str(self) -> &'a str {
3525 let bytes = self.arena.push_bytes(self.buf.as_slice());
3526 std::str::from_utf8(bytes).expect("RowArenaBuf::finish_str on non-UTF-8 contents")
3527 }
3528}
3529
3530impl<'a> Drop for RowArenaBuf<'a> {
3531 fn drop(&mut self) {
3532 let mut slot = self.arena.scratch.borrow_mut();
3537 if slot.is_none() {
3538 *slot = Some(std::mem::take(&mut self.buf));
3539 }
3540 }
3541}
3542
3543impl<'a> std::ops::Deref for RowArenaBuf<'a> {
3544 type Target = [u8];
3545 fn deref(&self) -> &[u8] {
3546 &self.buf
3547 }
3548}
3549
3550impl<'a> std::io::Write for RowArenaBuf<'a> {
3551 fn write(&mut self, bytes: &[u8]) -> std::io::Result<usize> {
3552 self.buf.extend_from_slice(bytes);
3553 Ok(bytes.len())
3554 }
3555
3556 fn flush(&mut self) -> std::io::Result<()> {
3557 Ok(())
3558 }
3559}
3560
3561impl<'a> std::fmt::Write for RowArenaBuf<'a> {
3562 fn write_str(&mut self, s: &str) -> std::fmt::Result {
3563 self.buf.extend_from_slice(s.as_bytes());
3564 Ok(())
3565 }
3566}
3567
3568#[derive(Debug)]
3586pub struct SharedRow(Row);
3587
3588impl SharedRow {
3589 thread_local! {
3590 static SHARED_ROW: Cell<Option<Row>> = const { Cell::new(Some(Row::empty())) }
3595 }
3596
3597 pub fn get() -> Self {
3605 let mut row = Self::SHARED_ROW
3606 .take()
3607 .expect("attempted to borrow already borrowed SharedRow");
3608 row.packer();
3610 Self(row)
3611 }
3612
3613 pub fn pack<'a, I, D>(iter: I) -> Row
3615 where
3616 I: IntoIterator<Item = D>,
3617 D: Borrow<Datum<'a>>,
3618 {
3619 let mut row_builder = Self::get();
3620 let mut row_packer = row_builder.packer();
3621 row_packer.extend(iter);
3622 row_builder.clone()
3623 }
3624}
3625
3626impl std::ops::Deref for SharedRow {
3627 type Target = Row;
3628
3629 fn deref(&self) -> &Self::Target {
3630 &self.0
3631 }
3632}
3633
3634impl std::ops::DerefMut for SharedRow {
3635 fn deref_mut(&mut self) -> &mut Self::Target {
3636 &mut self.0
3637 }
3638}
3639
3640impl Drop for SharedRow {
3641 fn drop(&mut self) {
3642 Self::SHARED_ROW.set(Some(std::mem::take(&mut self.0)))
3645 }
3646}
3647
3648#[cfg(test)]
3649mod tests {
3650 use std::cmp::Ordering;
3651 use std::collections::hash_map::DefaultHasher;
3652 use std::hash::{Hash, Hasher};
3653
3654 use chrono::{DateTime, NaiveDate};
3655 use itertools::Itertools;
3656 use mz_ore::{assert_err, assert_none};
3657 use ordered_float::OrderedFloat;
3658
3659 use crate::SqlScalarType;
3660
3661 use super::*;
3662
3663 proptest! {
3670 #![proptest_config(ProptestConfig::with_cases(1000))]
3671
3672 #[mz_ore::test]
3673 #[cfg_attr(miri, ignore)] fn stable_row_serde_roundtrip(
3675 stable in crate::relation::arb_relation_desc(1..8)
3676 .prop_flat_map(|desc| crate::relation::arb_row_for_relation(&desc))
3677 .prop_map(StableRow)
3678 ) {
3679 let json = serde_json::to_string(&stable).expect("serializes to JSON");
3680 let from_json: StableRow =
3681 serde_json::from_str(&json).expect("deserializes from JSON");
3682 prop_assert_eq!(&stable, &from_json);
3683
3684 let bytes = bincode::serialize(&stable).expect("serializes to bincode");
3685 let from_bincode: StableRow =
3686 bincode::deserialize(&bytes).expect("deserializes from bincode");
3687 prop_assert_eq!(&stable, &from_bincode);
3688 }
3689 }
3690
3691 #[mz_ore::test]
3694 #[cfg_attr(miri, ignore)] fn cmp_deep_nested_list_does_not_overflow() {
3696 fn deep() -> Row {
3697 let mut row = Row::pack_slice(&[Datum::Int64(1)]);
3699 for _ in 0..50_000 {
3700 let mut next = Row::default();
3701 next.packer().push_list([row.unpack_first()]);
3702 row = next;
3703 }
3704 row
3705 }
3706 let a = deep();
3707 let b = deep();
3708 assert_eq!(a.unpack_first().cmp(&b.unpack_first()), Ordering::Equal);
3709 }
3710
3711 fn hash<T: Hash>(t: &T) -> u64 {
3712 let mut hasher = DefaultHasher::new();
3713 t.hash(&mut hasher);
3714 hasher.finish()
3715 }
3716
3717 #[mz_ore::test]
3718 fn test_assumptions() {
3719 assert_eq!(size_of::<Tag>(), 1);
3720 #[cfg(target_endian = "big")]
3721 {
3722 assert!(false);
3724 }
3725 }
3726
3727 #[mz_ore::test]
3728 fn miri_test_arena() {
3729 let arena = RowArena::new();
3730
3731 assert_eq!(arena.push_string("".to_owned()), "");
3732 assert_eq!(arena.push_string("العَرَبِيَّة".to_owned()), "العَرَبِيَّة");
3733
3734 let empty: &[u8] = &[];
3735 assert_eq!(arena.push_bytes(vec![]), empty);
3736 assert_eq!(arena.push_bytes(vec![0, 2, 1, 255]), &[0, 2, 1, 255]);
3737
3738 let mut row = Row::default();
3739 let mut packer = row.packer();
3740 packer.push_dict_with(|row| {
3741 row.push(Datum::String("a"));
3742 row.push_list_with(|row| {
3743 row.push(Datum::String("one"));
3744 row.push(Datum::String("two"));
3745 row.push(Datum::String("three"));
3746 });
3747 row.push(Datum::String("b"));
3748 row.push(Datum::String("c"));
3749 });
3750 assert_eq!(arena.push_unary_row(row.clone()), row.unpack_first());
3751 }
3752
3753 #[mz_ore::test]
3754 fn miri_test_arena_growth_keeps_references() {
3755 let arena = RowArena::new();
3758 let chunks: Vec<Vec<u8>> = (0..128u16)
3759 .map(|i| vec![u8::try_from(i % 256).unwrap(); usize::from(i % 13) + 1])
3760 .collect();
3761 let refs: Vec<&[u8]> = chunks
3762 .iter()
3763 .map(|c| arena.push_bytes(c.as_slice()))
3764 .collect();
3765 for (i, r) in refs.iter().enumerate() {
3766 assert_eq!(*r, chunks[i].as_slice());
3767 }
3768 }
3769
3770 #[mz_ore::test]
3771 fn miri_test_arena_unary_row_at_offset() {
3772 let arena = RowArena::new();
3775 arena.reserve(4096);
3776 let _pad = arena.push_bytes(vec![0xAB; 5]);
3777 let row = Row::pack_slice(&[Datum::String("hello"), Datum::Int64(42), Datum::True]);
3778 assert_eq!(arena.push_unary_row(row.clone()), row.unpack_first());
3779 }
3780
3781 #[mz_ore::test]
3782 fn miri_test_arena_clear_reuse() {
3783 let mut arena = RowArena::new();
3785 for i in 0..100u8 {
3786 let _ = arena.push_bytes(vec![i; 16]);
3787 }
3788 arena.clear();
3789 assert_eq!(arena.push_bytes(vec![7u8; 8]), &[7u8; 8]);
3790 assert_eq!(arena.push_string("after clear".to_owned()), "after clear");
3791 arena.clear();
3792 let empty: &[u8] = &[];
3793 assert_eq!(arena.push_bytes(Vec::<u8>::new()), empty);
3794 }
3795
3796 #[mz_ore::test]
3797 fn miri_test_arena_adopts_owned_bytes_and_keeps_references() {
3798 let arena = RowArena::new();
3802 let before = arena.push_bytes(vec![1u8; 8]);
3803 let adopted = arena.push_owned_bytes(vec![2u8; 64 * 1024]);
3804 let after = arena.push_bytes(vec![3u8; 8]);
3805 let small = arena.push_owned_bytes(vec![4u8; 4]);
3807
3808 assert_eq!(before, &[1u8; 8]);
3809 assert_eq!(adopted, &vec![2u8; 64 * 1024][..]);
3810 assert_eq!(after, &[3u8; 8]);
3811 assert_eq!(small, &[4u8; 4]);
3812
3813 let empty: &[u8] = &[];
3814 assert_eq!(arena.push_owned_bytes(vec![]), empty);
3815 }
3816
3817 #[mz_ore::test]
3818 fn test_arena_owned_pushes_keep_bump_allocating() {
3819 const VALUES: usize = 500;
3828 const VALUE: &str = "0123456789";
3829
3830 let regions = |arena: &RowArena| arena.inner.borrow().len();
3831 let push_all = |arena: &RowArena, owned: bool| {
3832 for _ in 0..VALUES {
3833 match owned {
3834 true => _ = arena.push_string(VALUE.to_string()),
3835 false => _ = arena.push_bytes(VALUE.as_bytes()),
3836 }
3837 }
3838 };
3839
3840 let copied = RowArena::new();
3842 push_all(&copied, false);
3843
3844 let owned = RowArena::new();
3845 push_all(&owned, true);
3846
3847 let seeded = RowArena::new();
3850 let _ = seeded.push_bytes(VALUE.as_bytes());
3851 push_all(&seeded, true);
3852
3853 let (copied, owned, seeded) = (regions(&copied), regions(&owned), regions(&seeded));
3857 assert!(
3858 owned <= copied * 2 && seeded <= copied * 2,
3859 "{VALUES} owned pushes left {owned} regions on an empty arena and {seeded} on a seeded \
3860 one, against {copied} for the same bytes copied",
3861 );
3862 }
3863
3864 #[mz_ore::test]
3865 fn miri_test_arena_budget() {
3866 let arena = RowArena::new();
3868 let _ = arena.push_bytes(vec![0u8; 1024]);
3869 assert!(!arena.over_budget());
3870 assert_eq!(arena.budget_remaining(), usize::MAX);
3871
3872 let arena = RowArena::with_budget(100);
3873 assert!(!arena.over_budget());
3874 assert_eq!(arena.budget_remaining(), 100);
3875
3876 let _ = arena.push_bytes(vec![0u8; 60]);
3879 assert!(!arena.over_budget());
3880 assert_eq!(arena.budget_remaining(), 40);
3881 assert_eq!(arena.allocated_bytes(), 60);
3882
3883 let pushed = arena.push_bytes(vec![7u8; 80]);
3886 assert_eq!(pushed, &[7u8; 80]);
3887 assert!(arena.over_budget());
3888 assert_eq!(arena.budget_remaining(), 0);
3889
3890 let mut arena = RowArena::with_budget(100);
3893 let _ = arena.push_owned_bytes(vec![0u8; 8 * 1024]);
3894 assert!(arena.over_budget());
3895
3896 arena.clear();
3897 assert!(!arena.over_budget());
3898 assert_eq!(arena.allocated_bytes(), 0);
3899 }
3900
3901 #[mz_ore::test]
3902 fn miri_test_arena_writer() {
3903 use std::io::Write;
3904
3905 let arena = RowArena::new();
3906
3907 let mut w = arena.writer();
3909 let mut expected = Vec::new();
3910 for i in 0..1000u16 {
3911 let byte = u8::try_from(i % 256).unwrap();
3912 w.push(byte);
3913 expected.push(byte);
3914 w.extend_from_slice(&[byte, byte]);
3915 expected.extend_from_slice(&[byte, byte]);
3916 }
3917 assert_eq!(w.as_slice(), expected.as_slice());
3918 assert_eq!(w.len(), expected.len());
3919 let first = w.finish();
3920 assert_eq!(first, expected.as_slice());
3921
3922 let mut w2 = arena.writer();
3925 write!(w2, "hello").unwrap();
3926 let second = w2.finish();
3927 assert_eq!(second, b"hello");
3928 assert_eq!(first, expected.as_slice());
3929
3930 let empty: &[u8] = &[];
3932 assert_eq!(arena.writer().finish(), empty);
3933
3934 {
3936 let mut w3 = arena.writer();
3937 w3.extend_from_slice(b"discarded");
3938 }
3939 assert_eq!(arena.writer().as_slice(), empty);
3940 }
3941
3942 #[mz_ore::test]
3943 fn miri_test_arena_writer_nested() {
3944 let arena = RowArena::new();
3948
3949 let mut outer = arena.writer();
3950 outer.extend_from_slice(b"outer-before-");
3951
3952 let inner_bytes = {
3954 let mut inner = arena.writer();
3955 inner.extend_from_slice(b"inner");
3956 assert_eq!(outer.as_slice(), b"outer-before-");
3958 inner.finish()
3959 };
3960 assert_eq!(inner_bytes, b"inner");
3961
3962 outer.extend_from_slice(b"after");
3964 let outer_bytes = outer.finish();
3965 assert_eq!(outer_bytes, b"outer-before-after");
3966 assert_eq!(inner_bytes, b"inner");
3968
3969 let mut again = arena.writer();
3971 again.extend_from_slice(b"reused");
3972 assert_eq!(again.finish(), b"reused");
3973 }
3974
3975 #[mz_ore::test]
3976 fn miri_test_arena_writer_fmt() {
3977 use std::fmt::Write;
3978
3979 let arena = RowArena::new();
3981 let mut w = arena.writer();
3982 for i in 0..5 {
3983 write!(w, "{i},").unwrap();
3984 }
3985 assert_eq!(w.finish_str(), "0,1,2,3,4,");
3986 }
3987
3988 #[mz_ore::test]
3989 fn miri_test_round_trip() {
3990 fn round_trip(datums: Vec<Datum>) {
3991 let row = Row::pack(datums.clone());
3992
3993 println!("{:?}", row.data());
3996
3997 let datums2 = row.iter().collect::<Vec<_>>();
3998 let datums3 = row.unpack();
3999 assert_eq!(datums, datums2);
4000 assert_eq!(datums, datums3);
4001 }
4002
4003 round_trip(vec![]);
4004 round_trip(
4005 SqlScalarType::enumerate()
4006 .iter()
4007 .flat_map(|r#type| r#type.interesting_datums())
4008 .collect(),
4009 );
4010 round_trip(vec![
4011 Datum::Null,
4012 Datum::Null,
4013 Datum::False,
4014 Datum::True,
4015 Datum::Int16(-21),
4016 Datum::Int32(-42),
4017 Datum::Int64(-2_147_483_648 - 42),
4018 Datum::UInt8(0),
4019 Datum::UInt8(1),
4020 Datum::UInt16(0),
4021 Datum::UInt16(1),
4022 Datum::UInt16(1 << 8),
4023 Datum::UInt32(0),
4024 Datum::UInt32(1),
4025 Datum::UInt32(1 << 8),
4026 Datum::UInt32(1 << 16),
4027 Datum::UInt32(1 << 24),
4028 Datum::UInt64(0),
4029 Datum::UInt64(1),
4030 Datum::UInt64(1 << 8),
4031 Datum::UInt64(1 << 16),
4032 Datum::UInt64(1 << 24),
4033 Datum::UInt64(1 << 32),
4034 Datum::UInt64(1 << 40),
4035 Datum::UInt64(1 << 48),
4036 Datum::UInt64(1 << 56),
4037 Datum::Float32(OrderedFloat::from(-42.12)),
4038 Datum::Float64(OrderedFloat::from(-2_147_483_648.0 - 42.12)),
4039 Datum::Date(Date::from_pg_epoch(365 * 45 + 21).unwrap()),
4040 Datum::Timestamp(
4041 CheckedTimestamp::from_timestamplike(
4042 NaiveDate::from_isoywd_opt(2019, 30, chrono::Weekday::Wed)
4043 .unwrap()
4044 .and_hms_opt(14, 32, 11)
4045 .unwrap(),
4046 )
4047 .unwrap(),
4048 ),
4049 Datum::TimestampTz(
4050 CheckedTimestamp::from_timestamplike(DateTime::from_timestamp(61, 0).unwrap())
4051 .unwrap(),
4052 ),
4053 Datum::Interval(Interval {
4054 months: 312,
4055 ..Default::default()
4056 }),
4057 Datum::Interval(Interval::new(0, 0, 1_012_312)),
4058 Datum::Bytes(&[]),
4059 Datum::Bytes(&[0, 2, 1, 255]),
4060 Datum::String(""),
4061 Datum::String("العَرَبِيَّة"),
4062 ]);
4063 }
4064
4065 #[mz_ore::test]
4066 fn test_array() {
4067 const DIM: ArrayDimension = ArrayDimension {
4070 lower_bound: 2,
4071 length: 2,
4072 };
4073 let mut row = Row::default();
4074 let mut packer = row.packer();
4075 packer
4076 .try_push_array(&[DIM], vec![Datum::Int32(1), Datum::Int32(2)])
4077 .unwrap();
4078 let arr1 = row.unpack_first().unwrap_array();
4079 assert_eq!(arr1.dims().into_iter().collect::<Vec<_>>(), vec![DIM]);
4080 assert_eq!(
4081 arr1.elements().into_iter().collect::<Vec<_>>(),
4082 vec![Datum::Int32(1), Datum::Int32(2)]
4083 );
4084
4085 let row = Row::pack_slice(&[Datum::Array(arr1)]);
4088 let arr2 = row.unpack_first().unwrap_array();
4089 assert_eq!(arr1, arr2);
4090 }
4091
4092 #[mz_ore::test]
4093 fn test_multidimensional_array() {
4094 let datums = vec![
4095 Datum::Int32(1),
4096 Datum::Int32(2),
4097 Datum::Int32(3),
4098 Datum::Int32(4),
4099 Datum::Int32(5),
4100 Datum::Int32(6),
4101 Datum::Int32(7),
4102 Datum::Int32(8),
4103 ];
4104
4105 let mut row = Row::default();
4106 let mut packer = row.packer();
4107 packer
4108 .try_push_array(
4109 &[
4110 ArrayDimension {
4111 lower_bound: 1,
4112 length: 1,
4113 },
4114 ArrayDimension {
4115 lower_bound: 1,
4116 length: 4,
4117 },
4118 ArrayDimension {
4119 lower_bound: 1,
4120 length: 2,
4121 },
4122 ],
4123 &datums,
4124 )
4125 .unwrap();
4126 let array = row.unpack_first().unwrap_array();
4127 assert_eq!(array.elements().into_iter().collect::<Vec<_>>(), datums);
4128 }
4129
4130 #[mz_ore::test]
4131 fn test_array_max_dimensions() {
4132 let mut row = Row::default();
4133 let max_dims = usize::from(MAX_ARRAY_DIMENSIONS);
4134
4135 let res = row.packer().try_push_array(
4137 &vec![
4138 ArrayDimension {
4139 lower_bound: 1,
4140 length: 1
4141 };
4142 max_dims + 1
4143 ],
4144 vec![Datum::Int32(4)],
4145 );
4146 assert_eq!(res, Err(InvalidArrayError::TooManyDimensions(max_dims + 1)));
4147 assert!(row.data.is_empty());
4148
4149 row.packer()
4152 .try_push_array(
4153 &vec![
4154 ArrayDimension {
4155 lower_bound: 1,
4156 length: 1
4157 };
4158 max_dims
4159 ],
4160 vec![Datum::Int32(4)],
4161 )
4162 .unwrap();
4163 }
4164
4165 #[mz_ore::test]
4166 fn test_array_wrong_cardinality() {
4167 let mut row = Row::default();
4168 let res = row.packer().try_push_array(
4169 &[
4170 ArrayDimension {
4171 lower_bound: 1,
4172 length: 2,
4173 },
4174 ArrayDimension {
4175 lower_bound: 1,
4176 length: 3,
4177 },
4178 ],
4179 vec![Datum::Int32(1), Datum::Int32(2)],
4180 );
4181 assert_eq!(
4182 res,
4183 Err(InvalidArrayError::WrongCardinality {
4184 actual: 2,
4185 expected: 6,
4186 })
4187 );
4188 assert!(row.data.is_empty());
4189 }
4190
4191 #[mz_ore::test]
4192 fn test_array_cardinality_overflow() {
4193 let mut row = Row::default();
4198 let res = row.packer().try_push_array(
4199 &[
4200 ArrayDimension {
4201 lower_bound: 1,
4202 length: usize::MAX,
4203 },
4204 ArrayDimension {
4205 lower_bound: 1,
4206 length: 2,
4207 },
4208 ],
4209 vec![Datum::Int32(1), Datum::Int32(2)],
4210 );
4211 assert_eq!(
4212 res,
4213 Err(InvalidArrayError::WrongCardinality {
4214 actual: 2,
4215 expected: usize::MAX,
4216 })
4217 );
4218 assert!(row.data.is_empty());
4219 }
4220
4221 #[mz_ore::test]
4222 fn test_nesting() {
4223 let mut row = Row::default();
4224 row.packer().push_dict_with(|row| {
4225 row.push(Datum::String("favourites"));
4226 row.push_list_with(|row| {
4227 row.push(Datum::String("ice cream"));
4228 row.push(Datum::String("oreos"));
4229 row.push(Datum::String("cheesecake"));
4230 });
4231 row.push(Datum::String("name"));
4232 row.push(Datum::String("bob"));
4233 });
4234
4235 let mut iter = row.unpack_first().unwrap_map().iter();
4236
4237 let (k, v) = iter.next().unwrap();
4238 assert_eq!(k, "favourites");
4239 assert_eq!(
4240 v.unwrap_list().iter().collect::<Vec<_>>(),
4241 vec![
4242 Datum::String("ice cream"),
4243 Datum::String("oreos"),
4244 Datum::String("cheesecake"),
4245 ]
4246 );
4247
4248 let (k, v) = iter.next().unwrap();
4249 assert_eq!(k, "name");
4250 assert_eq!(v, Datum::String("bob"));
4251 }
4252
4253 #[mz_ore::test]
4254 fn test_dict_errors() -> Result<(), Box<dyn std::error::Error>> {
4255 let pack = |ok| {
4256 let mut row = Row::default();
4257 row.packer().push_dict_with(|row| {
4258 if ok {
4259 row.push(Datum::String("key"));
4260 row.push(Datum::Int32(42));
4261 Ok(7)
4262 } else {
4263 Err("fail")
4264 }
4265 })?;
4266 Ok(row)
4267 };
4268
4269 assert_eq!(pack(false), Err("fail"));
4270
4271 let row = pack(true)?;
4272 let mut dict = row.unpack_first().unwrap_map().iter();
4273 assert_eq!(dict.next(), Some(("key", Datum::Int32(42))));
4274 assert_eq!(dict.next(), None);
4275
4276 Ok(())
4277 }
4278
4279 #[mz_ore::test]
4280 #[cfg_attr(miri, ignore)] fn test_datum_sizes() {
4282 let arena = RowArena::new();
4283
4284 let values_of_interest = vec![
4286 Datum::Null,
4287 Datum::False,
4288 Datum::Int16(0),
4289 Datum::Int32(0),
4290 Datum::Int64(0),
4291 Datum::UInt8(0),
4292 Datum::UInt8(1),
4293 Datum::UInt16(0),
4294 Datum::UInt16(1),
4295 Datum::UInt16(1 << 8),
4296 Datum::UInt32(0),
4297 Datum::UInt32(1),
4298 Datum::UInt32(1 << 8),
4299 Datum::UInt32(1 << 16),
4300 Datum::UInt32(1 << 24),
4301 Datum::UInt64(0),
4302 Datum::UInt64(1),
4303 Datum::UInt64(1 << 8),
4304 Datum::UInt64(1 << 16),
4305 Datum::UInt64(1 << 24),
4306 Datum::UInt64(1 << 32),
4307 Datum::UInt64(1 << 40),
4308 Datum::UInt64(1 << 48),
4309 Datum::UInt64(1 << 56),
4310 Datum::Float32(OrderedFloat(0.0)),
4311 Datum::Float64(OrderedFloat(0.0)),
4312 Datum::from(numeric::Numeric::from(0)),
4313 Datum::from(numeric::Numeric::from(1000)),
4314 Datum::from(numeric::Numeric::from(9999)),
4315 Datum::Date(
4316 NaiveDate::from_ymd_opt(1, 1, 1)
4317 .unwrap()
4318 .try_into()
4319 .unwrap(),
4320 ),
4321 Datum::Timestamp(
4322 CheckedTimestamp::from_timestamplike(
4323 DateTime::from_timestamp(0, 0).unwrap().naive_utc(),
4324 )
4325 .unwrap(),
4326 ),
4327 Datum::TimestampTz(
4328 CheckedTimestamp::from_timestamplike(DateTime::from_timestamp(0, 0).unwrap())
4329 .unwrap(),
4330 ),
4331 Datum::Interval(Interval::default()),
4332 Datum::Bytes(&[]),
4333 Datum::String(""),
4334 Datum::JsonNull,
4335 Datum::Range(Range { inner: None }),
4336 arena.make_datum(|packer| {
4337 packer
4338 .push_range(Range::new(Some((
4339 RangeLowerBound::new(Datum::Int32(-1), true),
4340 RangeUpperBound::new(Datum::Int32(1), true),
4341 ))))
4342 .unwrap();
4343 }),
4344 ];
4345 for value in values_of_interest {
4346 if datum_size(&value) != Row::pack_slice(&[value]).data.len() {
4347 panic!("Disparity in claimed size for {:?}", value);
4348 }
4349 }
4350 }
4351
4352 #[mz_ore::test]
4353 fn test_range_errors() {
4354 fn test_range_errors_inner<'a>(
4355 datums: Vec<Vec<Datum<'a>>>,
4356 ) -> Result<(), InvalidRangeError> {
4357 let mut row = Row::default();
4358 let row_len = row.byte_len();
4359 let mut packer = row.packer();
4360 let r = packer.push_range_with(
4361 RangeLowerBound {
4362 inclusive: true,
4363 bound: Some(|row: &mut RowPacker| {
4364 for d in &datums[0] {
4365 row.push(d);
4366 }
4367 Ok(())
4368 }),
4369 },
4370 RangeUpperBound {
4371 inclusive: true,
4372 bound: Some(|row: &mut RowPacker| {
4373 for d in &datums[1] {
4374 row.push(d);
4375 }
4376 Ok(())
4377 }),
4378 },
4379 );
4380
4381 assert_eq!(row_len, row.byte_len());
4382
4383 r
4384 }
4385
4386 for panicking_case in [
4391 vec![vec![Datum::Int32(1)], vec![]],
4392 vec![vec![Datum::Int32(1), Datum::Int32(2)], vec![]],
4393 ] {
4394 #[allow(clippy::disallowed_methods)] let result = std::panic::catch_unwind(|| test_range_errors_inner(panicking_case));
4396 assert_err!(result);
4397 }
4398
4399 for error_case in [
4403 vec![
4404 vec![Datum::Int32(1), Datum::Int32(2)],
4405 vec![Datum::Int32(3)],
4406 ],
4407 vec![
4408 vec![Datum::Int32(1)],
4409 vec![Datum::Int32(2), Datum::Int32(3)],
4410 ],
4411 vec![vec![Datum::Int32(1)], vec![Datum::UInt16(2)]],
4412 vec![vec![Datum::Null], vec![Datum::Int32(2)]],
4413 vec![vec![Datum::Int32(1)], vec![Datum::Null]],
4414 ] {
4415 assert_eq!(
4416 test_range_errors_inner(error_case),
4417 Err(InvalidRangeError::InvalidRangeData)
4418 );
4419 }
4420
4421 let e = test_range_errors_inner(vec![vec![Datum::Int32(2)], vec![Datum::Int32(1)]]);
4422 assert_eq!(e, Err(InvalidRangeError::MisorderedRangeBounds));
4423 }
4424
4425 #[mz_ore::test]
4427 #[cfg_attr(miri, ignore)] fn test_list_encoding() {
4429 fn test_list_encoding_inner(len: usize) {
4430 let list_elem = |i: usize| {
4431 if i % 2 == 0 {
4432 Datum::False
4433 } else {
4434 Datum::True
4435 }
4436 };
4437 let mut row = Row::default();
4438 {
4439 let mut packer = row.packer();
4441 packer.push(Datum::String("start"));
4442 packer.push_list_with(|packer| {
4443 for i in 0..len {
4444 packer.push(list_elem(i));
4445 }
4446 });
4447 packer.push(Datum::String("end"));
4448 }
4449 let mut row_it = row.iter();
4451 assert_eq!(row_it.next().unwrap(), Datum::String("start"));
4452 match row_it.next().unwrap() {
4453 Datum::List(list) => {
4454 let mut list_it = list.iter();
4455 for i in 0..len {
4456 assert_eq!(list_it.next().unwrap(), list_elem(i));
4457 }
4458 assert_none!(list_it.next());
4459 }
4460 _ => panic!("expected Datum::List"),
4461 }
4462 assert_eq!(row_it.next().unwrap(), Datum::String("end"));
4463 assert_none!(row_it.next());
4464 }
4465
4466 test_list_encoding_inner(0);
4467 test_list_encoding_inner(1);
4468 test_list_encoding_inner(10);
4469 test_list_encoding_inner(TINY - 1); test_list_encoding_inner(TINY + 1); test_list_encoding_inner(SHORT + 1); }
4476
4477 #[mz_ore::test]
4483 #[cfg_attr(miri, ignore)] fn test_datum_list_eq_ord_consistency() {
4485 let mut row_pos = Row::default();
4487 row_pos.packer().push_list_with(|p| {
4488 p.push(Datum::Float64(OrderedFloat::from(0.0)));
4489 });
4490 let list_pos = row_pos.unpack_first().unwrap_list();
4491
4492 let mut row_neg = Row::default();
4494 row_neg.packer().push_list_with(|p| {
4495 p.push(Datum::Float64(OrderedFloat::from(-0.0)));
4496 });
4497 let list_neg = row_neg.unpack_first().unwrap_list();
4498
4499 assert_eq!(
4502 list_pos, list_neg,
4503 "Eq should see different encodings as equal"
4504 );
4505
4506 assert_eq!(
4508 list_pos.cmp(&list_neg),
4509 Ordering::Equal,
4510 "Ord (datum-by-datum) should see -0.0 and +0.0 as equal"
4511 );
4512 }
4513
4514 #[mz_ore::test]
4517 fn test_datum_map_eq_bytewise_consistency() {
4518 let mut row_pos = Row::default();
4520 row_pos.packer().push_dict_with(|p| {
4521 p.push(Datum::String("k"));
4522 p.push(Datum::Float64(OrderedFloat::from(0.0)));
4523 });
4524 let map_pos = row_pos.unpack_first().unwrap_map();
4525
4526 let mut row_neg = Row::default();
4528 row_neg.packer().push_dict_with(|p| {
4529 p.push(Datum::String("k"));
4530 p.push(Datum::Float64(OrderedFloat::from(-0.0)));
4531 });
4532 let map_neg = row_neg.unpack_first().unwrap_map();
4533
4534 assert_eq!(
4536 map_pos, map_neg,
4537 "DatumMap Eq is semantic; -0.0 and +0.0 have different encodings but are equal"
4538 );
4539 let entries_pos: Vec<_> = map_pos.iter().collect();
4541 let entries_neg: Vec<_> = map_neg.iter().collect();
4542 assert_eq!(entries_pos.len(), entries_neg.len());
4543 for ((k1, v1), (k2, v2)) in entries_pos.iter().zip_eq(entries_neg.iter()) {
4544 assert_eq!(k1, k2);
4545 assert_eq!(
4546 v1, v2,
4547 "Datum-level comparison treats -0.0 and +0.0 as equal"
4548 );
4549 }
4550 }
4551
4552 #[mz_ore::test]
4554 fn test_datum_list_hash_consistency() {
4555 let mut row_pos = Row::default();
4557 row_pos.packer().push_list_with(|p| {
4558 p.push(Datum::Float64(OrderedFloat::from(0.0)));
4559 });
4560 let list_pos = row_pos.unpack_first().unwrap_list();
4561
4562 let mut row_neg = Row::default();
4563 row_neg.packer().push_list_with(|p| {
4564 p.push(Datum::Float64(OrderedFloat::from(-0.0)));
4565 });
4566 let list_neg = row_neg.unpack_first().unwrap_list();
4567
4568 assert_eq!(list_pos, list_neg);
4569 assert_eq!(
4570 hash(&list_pos),
4571 hash(&list_neg),
4572 "equal lists must have same hash"
4573 );
4574
4575 let mut row_a = Row::default();
4577 row_a.packer().push_list_with(|p| {
4578 p.push(Datum::Int32(1));
4579 p.push(Datum::Int32(2));
4580 });
4581 let list_a = row_a.unpack_first().unwrap_list();
4582
4583 let mut row_b = Row::default();
4584 row_b.packer().push_list_with(|p| {
4585 p.push(Datum::Int32(1));
4586 p.push(Datum::Int32(3));
4587 });
4588 let list_b = row_b.unpack_first().unwrap_list();
4589
4590 assert_ne!(list_a, list_b);
4591 assert_ne!(
4592 hash(&list_a),
4593 hash(&list_b),
4594 "unequal lists must have different hashes"
4595 );
4596 }
4597
4598 #[mz_ore::test]
4600 #[cfg_attr(miri, ignore)] fn test_datum_list_ordering() {
4602 let mut row_12 = Row::default();
4603 row_12.packer().push_list_with(|p| {
4604 p.push(Datum::Int32(1));
4605 p.push(Datum::Int32(2));
4606 });
4607 let list_12 = row_12.unpack_first().unwrap_list();
4608
4609 let mut row_13 = Row::default();
4610 row_13.packer().push_list_with(|p| {
4611 p.push(Datum::Int32(1));
4612 p.push(Datum::Int32(3));
4613 });
4614 let list_13 = row_13.unpack_first().unwrap_list();
4615
4616 let mut row_123 = Row::default();
4617 row_123.packer().push_list_with(|p| {
4618 p.push(Datum::Int32(1));
4619 p.push(Datum::Int32(2));
4620 p.push(Datum::Int32(3));
4621 });
4622 let list_123 = row_123.unpack_first().unwrap_list();
4623
4624 assert_eq!(list_12.cmp(&list_13), Ordering::Less);
4626 assert_eq!(list_13.cmp(&list_12), Ordering::Greater);
4627 assert_eq!(list_12.cmp(&list_12), Ordering::Equal);
4628 assert_eq!(list_12.cmp(&list_123), Ordering::Less);
4630 }
4631
4632 #[mz_ore::test]
4634 fn test_datum_map_hash_consistency() {
4635 let mut row_pos = Row::default();
4636 row_pos.packer().push_dict_with(|p| {
4637 p.push(Datum::String("x"));
4638 p.push(Datum::Float64(OrderedFloat::from(0.0)));
4639 });
4640 let map_pos = row_pos.unpack_first().unwrap_map();
4641
4642 let mut row_neg = Row::default();
4643 row_neg.packer().push_dict_with(|p| {
4644 p.push(Datum::String("x"));
4645 p.push(Datum::Float64(OrderedFloat::from(-0.0)));
4646 });
4647 let map_neg = row_neg.unpack_first().unwrap_map();
4648
4649 assert_eq!(map_pos, map_neg);
4650 assert_eq!(
4651 hash(&map_pos),
4652 hash(&map_neg),
4653 "equal maps must have same hash"
4654 );
4655
4656 let mut row_a = Row::default();
4657 row_a.packer().push_dict_with(|p| {
4658 p.push(Datum::String("a"));
4659 p.push(Datum::Int32(1));
4660 });
4661 let map_a = row_a.unpack_first().unwrap_map();
4662
4663 let mut row_b = Row::default();
4664 row_b.packer().push_dict_with(|p| {
4665 p.push(Datum::String("a"));
4666 p.push(Datum::Int32(2));
4667 });
4668 let map_b = row_b.unpack_first().unwrap_map();
4669
4670 assert_ne!(map_a, map_b);
4671 assert_ne!(
4672 hash(&map_a),
4673 hash(&map_b),
4674 "unequal maps must have different hashes"
4675 );
4676 }
4677
4678 #[mz_ore::test]
4680 #[cfg_attr(miri, ignore)] fn test_datum_map_ordering() {
4682 let mut row_a1 = Row::default();
4683 row_a1.packer().push_dict_with(|p| {
4684 p.push(Datum::String("a"));
4685 p.push(Datum::Int32(1));
4686 });
4687 let map_a1 = row_a1.unpack_first().unwrap_map();
4688
4689 let mut row_a2 = Row::default();
4690 row_a2.packer().push_dict_with(|p| {
4691 p.push(Datum::String("a"));
4692 p.push(Datum::Int32(2));
4693 });
4694 let map_a2 = row_a2.unpack_first().unwrap_map();
4695
4696 let mut row_b1 = Row::default();
4697 row_b1.packer().push_dict_with(|p| {
4698 p.push(Datum::String("b"));
4699 p.push(Datum::Int32(1));
4700 });
4701 let map_b1 = row_b1.unpack_first().unwrap_map();
4702
4703 assert_eq!(map_a1.cmp(&map_a2), Ordering::Less);
4704 assert_eq!(map_a2.cmp(&map_a1), Ordering::Greater);
4705 assert_eq!(map_a1.cmp(&map_a1), Ordering::Equal);
4706 assert_eq!(map_a1.cmp(&map_b1), Ordering::Less); }
4708
4709 #[mz_ore::test]
4712 #[cfg_attr(miri, ignore)] fn test_datum_list_and_map_null_sorts_last() {
4714 let mut row_list_1 = Row::default();
4716 row_list_1
4717 .packer()
4718 .push_list_with(|p| p.push(Datum::Int32(1)));
4719 let list_1 = row_list_1.unpack_first().unwrap_list();
4720
4721 let mut row_list_null = Row::default();
4722 row_list_null
4723 .packer()
4724 .push_list_with(|p| p.push(Datum::Null));
4725 let list_null = row_list_null.unpack_first().unwrap_list();
4726
4727 assert_eq!(list_1.cmp(&list_null), Ordering::Less);
4728 assert_eq!(list_null.cmp(&list_1), Ordering::Greater);
4729
4730 let mut row_map_1 = Row::default();
4732 row_map_1.packer().push_dict_with(|p| {
4733 p.push(Datum::String("k"));
4734 p.push(Datum::Int32(1));
4735 });
4736 let map_1 = row_map_1.unpack_first().unwrap_map();
4737
4738 let mut row_map_null = Row::default();
4739 row_map_null.packer().push_dict_with(|p| {
4740 p.push(Datum::String("k"));
4741 p.push(Datum::Null);
4742 });
4743 let map_null = row_map_null.unpack_first().unwrap_map();
4744
4745 assert_eq!(map_1.cmp(&map_null), Ordering::Less);
4746 assert_eq!(map_null.cmp(&map_1), Ordering::Greater);
4747 }
4748}