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 Default,
365 Eq,
366 PartialEq,
367 Ord,
368 PartialOrd,
369 Hash,
370 Serialize,
371 Deserialize
372)]
373pub struct StableRow(#[serde(with = "stable_row_proto")] pub Row);
374
375impl From<Row> for StableRow {
376 fn from(row: Row) -> Self {
377 StableRow(row)
378 }
379}
380
381impl Deref for StableRow {
382 type Target = Row;
383
384 fn deref(&self) -> &Row {
385 &self.0
386 }
387}
388
389impl Debug for StableRow {
390 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
391 self.0.fmt(f)
392 }
393}
394
395mod stable_row_proto {
396 use mz_proto::RustType;
397 use prost::Message;
398 use serde::de::Error;
399 use serde::{Deserialize, Deserializer, Serializer};
400
401 use crate::row::{ProtoRow, Row};
402
403 pub fn serialize<S: Serializer>(row: &Row, serializer: S) -> Result<S::Ok, S::Error> {
404 serializer.serialize_bytes(&row.into_proto().encode_to_vec())
405 }
406
407 pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Row, D::Error> {
408 let bytes = serde_bytes::ByteBuf::deserialize(deserializer)?;
409 let proto = ProtoRow::decode(bytes.as_slice()).map_err(D::Error::custom)?;
410 Row::from_proto(proto).map_err(D::Error::custom)
411 }
412}
413
414#[allow(missing_debug_implementations)]
415mod columnation {
416 use columnation::{Columnation, Region};
417 use mz_ore::region::LgAllocRegion;
418
419 use crate::Row;
420
421 pub struct RowStack {
426 region: LgAllocRegion<u8>,
427 }
428
429 impl RowStack {
430 const LIMIT: usize = 2 << 20;
431 }
432
433 impl Default for RowStack {
435 fn default() -> Self {
436 Self {
437 region: LgAllocRegion::with_limit(Self::LIMIT),
439 }
440 }
441 }
442
443 impl Columnation for Row {
444 type InnerRegion = RowStack;
445 }
446
447 impl Region for RowStack {
448 type Item = Row;
449 #[inline]
450 fn clear(&mut self) {
451 self.region.clear();
452 }
453 #[inline(always)]
454 unsafe fn copy(&mut self, item: &Row) -> Row {
455 if item.data.spilled() {
456 let bytes = self.region.copy_slice(&item.data[..]);
457 Row {
458 data: compact_bytes::CompactBytes::from_raw_parts(
459 bytes.as_mut_ptr(),
460 item.data.len(),
461 item.data.capacity(),
462 ),
463 }
464 } else {
465 item.clone()
466 }
467 }
468
469 fn reserve_items<'a, I>(&mut self, items: I)
470 where
471 Self: 'a,
472 I: Iterator<Item = &'a Self::Item> + Clone,
473 {
474 let size = items
475 .filter(|row| row.data.spilled())
476 .map(|row| row.data.len())
477 .sum();
478 let size = std::cmp::min(size, Self::LIMIT);
479 self.region.reserve(size);
480 }
481
482 fn reserve_regions<'a, I>(&mut self, regions: I)
483 where
484 Self: 'a,
485 I: Iterator<Item = &'a Self> + Clone,
486 {
487 let size = regions.map(|r| r.region.len()).sum();
488 let size = std::cmp::min(size, Self::LIMIT);
489 self.region.reserve(size);
490 }
491
492 fn heap_size(&self, callback: impl FnMut(usize, usize)) {
493 self.region.heap_size(callback)
494 }
495 }
496}
497
498mod columnar {
499 use columnar::common::PushIndexAs;
500 use columnar::{
501 AsBytes, Borrow, Clear, Columnar, Container, FromBytes, Index, IndexAs, Len, Push,
502 };
503 use mz_ore::cast::CastFrom;
504 use std::ops::Range;
505
506 use crate::{Row, RowRef};
507
508 #[derive(
509 Copy,
510 Clone,
511 Debug,
512 Default,
513 PartialEq,
514 serde::Serialize,
515 serde::Deserialize
516 )]
517 pub struct Rows<BC = Vec<u64>, VC = Vec<u8>> {
518 bounds: BC,
520 values: VC,
522 }
523
524 impl Columnar for Row {
525 #[inline(always)]
526 fn copy_from(&mut self, other: columnar::Ref<'_, Self>) {
527 self.clear();
528 self.data.extend_from_slice(other.data());
529 }
530 #[inline(always)]
531 fn into_owned(other: columnar::Ref<'_, Self>) -> Self {
532 other.to_owned()
533 }
534 type Container = Rows;
535 #[inline(always)]
536 fn reborrow<'b, 'a: 'b>(thing: columnar::Ref<'a, Self>) -> columnar::Ref<'b, Self>
537 where
538 Self: 'a,
539 {
540 thing
541 }
542 }
543
544 impl<BC: PushIndexAs<u64>> Borrow for Rows<BC, Vec<u8>> {
545 type Ref<'a> = &'a RowRef;
546 type Borrowed<'a>
547 = Rows<BC::Borrowed<'a>, &'a [u8]>
548 where
549 Self: 'a;
550 #[inline(always)]
551 fn borrow<'a>(&'a self) -> Self::Borrowed<'a> {
552 Rows {
553 bounds: self.bounds.borrow(),
554 values: self.values.borrow(),
555 }
556 }
557 #[inline(always)]
558 fn reborrow<'c, 'a: 'c>(item: Self::Borrowed<'a>) -> Self::Borrowed<'c>
559 where
560 Self: 'a,
561 {
562 Rows {
563 bounds: BC::reborrow(item.bounds),
564 values: item.values,
565 }
566 }
567
568 fn reborrow_ref<'b, 'a: 'b>(item: Self::Ref<'a>) -> Self::Ref<'b>
569 where
570 Self: 'a,
571 {
572 item
573 }
574 }
575
576 impl<BC: PushIndexAs<u64>> Container for Rows<BC, Vec<u8>> {
577 fn extend_from_self(&mut self, other: Self::Borrowed<'_>, range: Range<usize>) {
578 if !range.is_empty() {
579 let values_len: u64 = self.values.len().try_into().expect("must fit");
581
582 let other_lower = if range.start == 0 {
584 0
585 } else {
586 other.bounds.index_as(range.start - 1)
587 };
588 let other_upper = other.bounds.index_as(range.end - 1);
589 self.values.extend_from_self(
590 other.values,
591 usize::try_from(other_lower).expect("must fit")
592 ..usize::try_from(other_upper).expect("must fit"),
593 );
594
595 if values_len == other_lower {
597 self.bounds.extend_from_self(other.bounds, range);
598 } else {
599 for index in range {
600 let shifted = other.bounds.index_as(index) - other_lower + values_len;
601 self.bounds.push(&shifted)
602 }
603 }
604 }
605 }
606 fn reserve_for<'a, I>(&mut self, selves: I)
607 where
608 Self: 'a,
609 I: Iterator<Item = Self::Borrowed<'a>> + Clone,
610 {
611 self.bounds.reserve_for(selves.clone().map(|r| r.bounds));
612 self.values.reserve_for(selves.map(|r| r.values));
613 }
614 }
615
616 impl<'a, BC: AsBytes<'a>, VC: AsBytes<'a>> AsBytes<'a> for Rows<BC, VC> {
617 const SLICE_COUNT: usize = BC::SLICE_COUNT + VC::SLICE_COUNT;
618 #[inline(always)]
619 fn get_byte_slice(&self, index: usize) -> (u64, &'a [u8]) {
620 mz_ore::soft_assert_no_log!(index < Self::SLICE_COUNT);
621 if index < BC::SLICE_COUNT {
622 self.bounds.get_byte_slice(index)
623 } else {
624 self.values.get_byte_slice(index - BC::SLICE_COUNT)
625 }
626 }
627 }
628 impl<'a, BC: FromBytes<'a>, VC: FromBytes<'a>> FromBytes<'a> for Rows<BC, VC> {
629 const SLICE_COUNT: usize = BC::SLICE_COUNT + VC::SLICE_COUNT;
630 #[inline(always)]
631 fn from_bytes(bytes: &mut impl Iterator<Item = &'a [u8]>) -> Self {
632 Self {
633 bounds: FromBytes::from_bytes(bytes),
634 values: FromBytes::from_bytes(bytes),
635 }
636 }
637 }
638
639 impl<BC: Len, VC> Len for Rows<BC, VC> {
640 #[inline(always)]
641 fn len(&self) -> usize {
642 self.bounds.len()
643 }
644 }
645
646 impl<'a, BC: Len + IndexAs<u64>> Index for Rows<BC, &'a [u8]> {
647 type Ref = &'a RowRef;
648 #[inline(always)]
649 fn get(&self, index: usize) -> Self::Ref {
650 let lower = if index == 0 {
651 0
652 } else {
653 self.bounds.index_as(index - 1)
654 };
655 let upper = self.bounds.index_as(index);
656 let lower = usize::cast_from(lower);
657 let upper = usize::cast_from(upper);
658 unsafe { RowRef::from_slice(&self.values[lower..upper]) }
661 }
662 }
663 impl<'a, BC: Len + IndexAs<u64>> Index for &'a Rows<BC, Vec<u8>> {
664 type Ref = &'a RowRef;
665 #[inline(always)]
666 fn get(&self, index: usize) -> Self::Ref {
667 let lower = if index == 0 {
668 0
669 } else {
670 self.bounds.index_as(index - 1)
671 };
672 let upper = self.bounds.index_as(index);
673 let lower = usize::cast_from(lower);
674 let upper = usize::cast_from(upper);
675 unsafe { RowRef::from_slice(&self.values[lower..upper]) }
678 }
679 }
680
681 impl<BC: Push<u64>> Push<&Row> for Rows<BC> {
682 #[inline(always)]
683 fn push(&mut self, item: &Row) {
684 self.values.extend_from_slice(item.data.as_slice());
685 self.bounds.push(u64::cast_from(self.values.len()));
686 }
687 }
688 impl<BC: Push<u64>> Push<Row> for Rows<BC> {
689 #[inline(always)]
690 fn push(&mut self, item: Row) {
691 self.push(&item);
692 }
693 }
694 impl<BC: for<'a> Push<&'a u64>> Push<&RowRef> for Rows<BC> {
695 #[inline(always)]
696 fn push(&mut self, item: &RowRef) {
697 self.values.extend_from_slice(item.data());
698 self.bounds.push(&u64::cast_from(self.values.len()));
699 }
700 }
701 impl<BC: Clear, VC: Clear> Clear for Rows<BC, VC> {
702 #[inline(always)]
703 fn clear(&mut self) {
704 self.bounds.clear();
705 self.values.clear();
706 }
707 }
708}
709
710#[derive(PartialEq, Eq, Hash)]
714#[repr(transparent)]
715pub struct RowRef([u8]);
716
717impl RowRef {
718 pub unsafe fn from_slice(row: &[u8]) -> &RowRef {
725 #[allow(clippy::as_conversions)]
726 let ptr = row as *const [u8] as *const RowRef;
727 unsafe { &*ptr }
729 }
730
731 pub fn unpack(&self) -> Vec<Datum<'_>> {
733 let len = self.iter().count();
735 let mut vec = Vec::with_capacity(len);
736 vec.extend(self.iter());
737 vec
738 }
739
740 pub fn unpack_first(&self) -> Datum<'_> {
744 self.iter().next().unwrap()
745 }
746
747 pub fn iter(&self) -> DatumListIter<'_> {
749 DatumListIter { data: &self.0 }
750 }
751
752 pub fn byte_len(&self) -> usize {
754 self.0.len()
755 }
756
757 pub fn data(&self) -> &[u8] {
759 &self.0
760 }
761
762 pub fn is_empty(&self) -> bool {
764 self.0.is_empty()
765 }
766}
767
768impl ToOwned for RowRef {
769 type Owned = Row;
770
771 fn to_owned(&self) -> Self::Owned {
772 unsafe { Row::from_bytes_unchecked(&self.0) }
774 }
775}
776
777impl<'a> IntoIterator for &'a RowRef {
778 type Item = Datum<'a>;
779 type IntoIter = DatumListIter<'a>;
780
781 fn into_iter(self) -> DatumListIter<'a> {
782 DatumListIter { data: &self.0 }
783 }
784}
785
786impl PartialOrd for RowRef {
790 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
791 Some(self.cmp(other))
792 }
793}
794
795impl Ord for RowRef {
796 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
797 match self.0.len().cmp(&other.0.len()) {
798 std::cmp::Ordering::Less => std::cmp::Ordering::Less,
799 std::cmp::Ordering::Greater => std::cmp::Ordering::Greater,
800 std::cmp::Ordering::Equal => self.0.cmp(&other.0),
801 }
802 }
803}
804
805impl fmt::Debug for RowRef {
806 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
808 f.write_str("RowRef{")?;
809 f.debug_list().entries(&*self).finish()?;
810 f.write_str("}")
811 }
812}
813
814#[derive(Debug)]
822pub struct RowPacker<'a> {
823 row: &'a mut Row,
824}
825
826pub trait FromDatum<'a>:
837 Sized + PartialEq + std::borrow::Borrow<Datum<'a>> + sealed::Sealed
838{
839 fn from_datum(datum: Datum<'a>) -> Self;
840}
841
842mod sealed {
843 use crate::Datum;
844
845 pub trait Sealed {}
846 impl<'a> Sealed for Datum<'a> {}
847}
848
849impl<'a> FromDatum<'a> for Datum<'a> {
850 #[inline]
851 fn from_datum(datum: Datum<'a>) -> Self {
852 datum
853 }
854}
855
856#[derive(Debug, Clone)]
857pub struct DatumListIter<'a> {
858 data: &'a [u8],
859}
860
861#[derive(Debug, Clone)]
862pub struct DatumListTypedIter<'a, T> {
863 inner: DatumListIter<'a>,
864 _phantom: PhantomData<fn() -> T>,
865}
866
867#[derive(Debug, Clone)]
868pub struct DatumDictIter<'a> {
869 data: &'a [u8],
870 prev_key: Option<&'a str>,
871}
872
873#[derive(Debug, Clone)]
874pub struct DatumDictTypedIter<'a, T> {
875 inner: DatumDictIter<'a>,
876 _phantom: PhantomData<fn() -> T>,
877}
878
879#[derive(Debug)]
881pub struct RowArena {
882 inner: RefCell<Vec<Vec<u8>>>,
898 scratch: RefCell<Option<Vec<u8>>>,
906 budget: Option<usize>,
917 allocated: Cell<usize>,
918}
919
920pub struct DatumList<'a, T = Datum<'a>> {
934 data: &'a [u8],
936 _phantom: PhantomData<fn() -> T>,
937}
938
939impl<'a, T> DatumList<'a, T> {
940 pub(crate) fn new(data: &'a [u8]) -> Self {
943 DatumList {
944 data,
945 _phantom: PhantomData,
946 }
947 }
948}
949
950impl<'a, T> Clone for DatumList<'a, T> {
951 fn clone(&self) -> Self {
952 *self
953 }
954}
955
956impl<'a, T> Copy for DatumList<'a, T> {}
957
958impl<'a, T> Debug for DatumList<'a, T> {
959 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
960 f.debug_list().entries(self.iter()).finish()
961 }
962}
963
964impl<'a, T> PartialEq for DatumList<'a, T> {
965 #[inline(always)]
966 fn eq(&self, other: &DatumList<'a, T>) -> bool {
967 self.iter().eq(other.iter())
968 }
969}
970
971impl<'a, T> Eq for DatumList<'a, T> {}
972
973impl<'a, T> Hash for DatumList<'a, T> {
974 #[inline(always)]
975 fn hash<H: Hasher>(&self, state: &mut H) {
976 for d in self.iter() {
977 d.hash(state);
978 }
979 }
980}
981
982impl<T> Ord for DatumList<'_, T> {
983 #[inline(always)]
984 fn cmp(&self, other: &DatumList<'_, T>) -> Ordering {
985 mz_ore::stack::maybe_grow(|| self.iter().cmp(other.iter()))
987 }
988}
989
990impl<T> PartialOrd for DatumList<'_, T> {
991 #[inline(always)]
992 fn partial_cmp(&self, other: &DatumList<'_, T>) -> Option<Ordering> {
993 Some(self.cmp(other))
994 }
995}
996
997pub struct DatumMap<'a, T = Datum<'a>> {
1008 data: &'a [u8],
1010 _phantom: PhantomData<fn() -> T>,
1011}
1012
1013impl<'a, T> DatumMap<'a, T> {
1014 pub(crate) fn new(data: &'a [u8]) -> Self {
1017 DatumMap {
1018 data,
1019 _phantom: PhantomData,
1020 }
1021 }
1022}
1023
1024impl<'a, T> Clone for DatumMap<'a, T> {
1025 fn clone(&self) -> Self {
1026 *self
1027 }
1028}
1029
1030impl<'a, T> Copy for DatumMap<'a, T> {}
1031
1032impl<'a, T> PartialEq for DatumMap<'a, T> {
1033 #[inline(always)]
1034 fn eq(&self, other: &DatumMap<'a, T>) -> bool {
1035 self.iter().eq(other.iter())
1036 }
1037}
1038
1039impl<'a, T> Eq for DatumMap<'a, T> {}
1040
1041impl<'a, T> Hash for DatumMap<'a, T> {
1042 #[inline(always)]
1043 fn hash<H: Hasher>(&self, state: &mut H) {
1044 for (k, v) in self.iter() {
1045 k.hash(state);
1046 v.hash(state);
1047 }
1048 }
1049}
1050
1051impl<'a, T> Ord for DatumMap<'a, T> {
1052 #[inline(always)]
1053 fn cmp(&self, other: &DatumMap<'a, T>) -> Ordering {
1054 mz_ore::stack::maybe_grow(|| self.iter().cmp(other.iter()))
1056 }
1057}
1058
1059impl<'a, T> PartialOrd for DatumMap<'a, T> {
1060 #[inline(always)]
1061 fn partial_cmp(&self, other: &DatumMap<'a, T>) -> Option<Ordering> {
1062 Some(self.cmp(other))
1063 }
1064}
1065
1066impl<'a> crate::scalar::SqlContainerType for DatumList<'a, Datum<'a>> {
1067 fn unwrap_element_type(container: &SqlScalarType) -> &SqlScalarType {
1068 container.unwrap_list_element_type()
1069 }
1070 fn wrap_element_type(element: SqlScalarType) -> SqlScalarType {
1071 SqlScalarType::List {
1072 element_type: Box::new(element),
1073 custom_id: None,
1074 }
1075 }
1076}
1077
1078impl<'a> crate::scalar::SqlContainerType for DatumMap<'a, Datum<'a>> {
1079 fn unwrap_element_type(container: &SqlScalarType) -> &SqlScalarType {
1080 container.unwrap_map_value_type()
1081 }
1082 fn wrap_element_type(element: SqlScalarType) -> SqlScalarType {
1083 SqlScalarType::Map {
1084 value_type: Box::new(element),
1085 custom_id: None,
1086 }
1087 }
1088}
1089
1090#[derive(Clone, Copy, Eq, PartialEq, Hash)]
1093pub struct DatumNested<'a> {
1094 val: &'a [u8],
1095}
1096
1097impl<'a> std::fmt::Display for DatumNested<'a> {
1098 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1099 std::fmt::Display::fmt(&self.datum(), f)
1100 }
1101}
1102
1103impl<'a> std::fmt::Debug for DatumNested<'a> {
1104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1105 f.debug_struct("DatumNested")
1106 .field("val", &self.datum())
1107 .finish()
1108 }
1109}
1110
1111impl<'a> DatumNested<'a> {
1112 pub fn extract(data: &mut &'a [u8]) -> DatumNested<'a> {
1116 let prev = *data;
1117 let _ = unsafe { read_datum(data) };
1118 DatumNested {
1119 val: &prev[..(prev.len() - data.len())],
1120 }
1121 }
1122
1123 pub fn datum(&self) -> Datum<'a> {
1125 let mut temp = self.val;
1126 unsafe { read_datum(&mut temp) }
1127 }
1128}
1129
1130impl<'a> Ord for DatumNested<'a> {
1131 fn cmp(&self, other: &Self) -> Ordering {
1132 mz_ore::stack::maybe_grow(|| self.datum().cmp(&other.datum()))
1134 }
1135}
1136
1137impl<'a> PartialOrd for DatumNested<'a> {
1138 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1139 Some(self.cmp(other))
1140 }
1141}
1142
1143#[derive(Debug, Clone, Copy, PartialEq, Eq, IntoPrimitive, TryFromPrimitive)]
1147#[repr(u8)]
1148enum Tag {
1149 Null,
1150 False,
1151 True,
1152 Float32,
1153 Float64,
1154 Date,
1155 Time,
1156 Timestamp,
1157 TimestampTz,
1158 Interval,
1159 BytesTiny,
1164 BytesShort,
1165 BytesLong,
1166 BytesHuge,
1167 StringTiny,
1168 StringShort,
1169 StringLong,
1170 StringHuge,
1171 ListTiny,
1172 ListShort,
1173 ListLong,
1174 ListHuge,
1175 Uuid,
1176 Array,
1177 Dict,
1178 JsonNull,
1179 Dummy,
1180 Numeric,
1181 MzTimestamp,
1182 Range,
1183 MzAclItem,
1184 AclItem,
1185 CheapTimestamp,
1189 CheapTimestampTz,
1193 NonNegativeInt16_0, NegativeInt16_0, NonNegativeInt16_8,
1215 NegativeInt16_8,
1216 Int16,
1217
1218 NonNegativeInt32_0,
1219 NegativeInt32_0,
1220 NonNegativeInt32_8,
1221 NegativeInt32_8,
1222 NonNegativeInt32_16,
1223 NegativeInt32_16,
1224 NonNegativeInt32_24,
1225 NegativeInt32_24,
1226 Int32,
1227
1228 NonNegativeInt64_0,
1229 NegativeInt64_0,
1230 NonNegativeInt64_8,
1231 NegativeInt64_8,
1232 NonNegativeInt64_16,
1233 NegativeInt64_16,
1234 NonNegativeInt64_24,
1235 NegativeInt64_24,
1236 NonNegativeInt64_32,
1237 NegativeInt64_32,
1238 NonNegativeInt64_40,
1239 NegativeInt64_40,
1240 NonNegativeInt64_48,
1241 NegativeInt64_48,
1242 NonNegativeInt64_56,
1243 NegativeInt64_56,
1244 Int64,
1245
1246 UInt8_0, UInt8,
1251
1252 UInt16_0,
1253 UInt16_8,
1254 UInt16,
1255
1256 UInt32_0,
1257 UInt32_8,
1258 UInt32_16,
1259 UInt32_24,
1260 UInt32,
1261
1262 UInt64_0,
1263 UInt64_8,
1264 UInt64_16,
1265 UInt64_24,
1266 UInt64_32,
1267 UInt64_40,
1268 UInt64_48,
1269 UInt64_56,
1270 UInt64,
1271}
1272
1273impl Tag {
1274 #[allow(clippy::as_conversions)]
1276 const fn byte(self) -> u8 {
1277 self as u8
1278 }
1279}
1280
1281macro_rules! assert_consecutive {
1289 ($($tag:ident),+ $(,)?) => {
1290 const _: () = {
1291 let tags: &[u8] = &[$(Tag::$tag.byte()),+];
1292 let mut i = 1;
1293 while i < tags.len() {
1294 assert!(
1295 tags[i] == tags[i - 1] + 1,
1296 concat!("tags are not consecutive: ", stringify!($($tag),+))
1297 );
1298 i += 1;
1299 }
1300 };
1301 };
1302}
1303
1304assert_consecutive!(BytesTiny, BytesShort, BytesLong, BytesHuge);
1305assert_consecutive!(StringTiny, StringShort, StringLong, StringHuge);
1306assert_consecutive!(ListTiny, ListShort, ListLong, ListHuge);
1307assert_consecutive!(
1308 NonNegativeInt16_0,
1309 NegativeInt16_0,
1310 NonNegativeInt16_8,
1311 NegativeInt16_8,
1312 Int16,
1313);
1314assert_consecutive!(
1315 NonNegativeInt32_0,
1316 NegativeInt32_0,
1317 NonNegativeInt32_8,
1318 NegativeInt32_8,
1319 NonNegativeInt32_16,
1320 NegativeInt32_16,
1321 NonNegativeInt32_24,
1322 NegativeInt32_24,
1323 Int32,
1324);
1325assert_consecutive!(
1326 NonNegativeInt64_0,
1327 NegativeInt64_0,
1328 NonNegativeInt64_8,
1329 NegativeInt64_8,
1330 NonNegativeInt64_16,
1331 NegativeInt64_16,
1332 NonNegativeInt64_24,
1333 NegativeInt64_24,
1334 NonNegativeInt64_32,
1335 NegativeInt64_32,
1336 NonNegativeInt64_40,
1337 NegativeInt64_40,
1338 NonNegativeInt64_48,
1339 NegativeInt64_48,
1340 NonNegativeInt64_56,
1341 NegativeInt64_56,
1342 Int64,
1343);
1344assert_consecutive!(UInt8_0, UInt8,);
1345assert_consecutive!(UInt16_0, UInt16_8, UInt16,);
1346assert_consecutive!(UInt32_0, UInt32_8, UInt32_16, UInt32_24, UInt32,);
1347assert_consecutive!(
1348 UInt64_0, UInt64_8, UInt64_16, UInt64_24, UInt64_32, UInt64_40, UInt64_48, UInt64_56, UInt64,
1349);
1350
1351fn read_untagged_bytes<'a>(data: &mut &'a [u8]) -> &'a [u8] {
1358 let len = u64::from_le_bytes(read_byte_array(data));
1359 let len = usize::cast_from(len);
1360 let (bytes, next) = data.split_at(len);
1361 *data = next;
1362 bytes
1363}
1364
1365#[inline(always)]
1376fn read_lengthed_bytes<'a>(data: &mut &'a [u8], tag: Tag, first: Tag) -> &'a [u8] {
1377 let len = match u8::from(tag).wrapping_sub(u8::from(first)) {
1378 0 => usize::from(read_byte(data)),
1379 1 => usize::from(u16::from_le_bytes(read_byte_array(data))),
1380 2 => usize::cast_from(u32::from_le_bytes(read_byte_array(data))),
1381 _ => usize::cast_from(u64::from_le_bytes(read_byte_array(data))),
1382 };
1383 let (bytes, next) = data.split_at(len);
1384 *data = next;
1385 bytes
1386}
1387
1388#[inline(always)]
1389fn read_byte(data: &mut &[u8]) -> u8 {
1390 let byte = data[0];
1391 *data = &data[1..];
1392 byte
1393}
1394
1395#[cold]
1400#[inline(never)]
1401fn read_varint_word_tail(data: &[u8], len: usize) -> u64 {
1402 #[inline(always)]
1403 fn ext<const L: usize>(data: &[u8]) -> u64 {
1404 let mut raw = [0; 8];
1405 raw[..L].copy_from_slice(&data[..L]);
1406 u64::from_le_bytes(raw)
1407 }
1408 match len {
1411 0 => 0,
1412 1 => u64::from(data[0]),
1413 2 => ext::<2>(data),
1414 3 => ext::<3>(data),
1415 4 => ext::<4>(data),
1416 5 => ext::<5>(data),
1417 6 => ext::<6>(data),
1418 7 => ext::<7>(data),
1419 _ => panic!("payload runs past the end of the row"),
1422 }
1423}
1424
1425#[inline(always)]
1432fn read_varint_word(data: &mut &[u8], len: usize) -> u64 {
1433 let word = match data.first_chunk::<8>() {
1434 Some(chunk) => u64::from_le_bytes(*chunk),
1435 None => read_varint_word_tail(data, len),
1436 };
1437 *data = &data[len..];
1438 word
1439}
1440
1441#[inline(always)]
1446fn payload_mask(len: usize) -> u64 {
1447 if len >= 8 {
1448 u64::MAX
1449 } else {
1450 (1u64 << (len * 8)) - 1
1451 }
1452}
1453
1454#[inline(always)]
1456fn truncate<const N: usize>(word: u64) -> [u8; N] {
1457 word.to_le_bytes()[..N].try_into().expect("N <= 8")
1458}
1459
1460#[inline(always)]
1471fn read_signed_varint<const N: usize>(data: &mut &[u8], tag: Tag, first: Tag) -> [u8; N] {
1472 let delta = u8::from(tag).wrapping_sub(u8::from(first));
1473 let len = usize::from(delta >> 1);
1474 let negative = delta & 1 == 1;
1477 read_varint_payload(data, len, negative)
1478}
1479
1480#[inline(always)]
1485fn read_varint_payload<const N: usize>(data: &mut &[u8], len: usize, negative: bool) -> [u8; N] {
1486 let mask = payload_mask(len);
1487 let fill = 0u64.wrapping_sub(u64::from(negative));
1488 truncate((read_varint_word(data, len) & mask) | (fill & !mask))
1489}
1490
1491#[inline(always)]
1499fn read_unsigned_varint<const N: usize>(data: &mut &[u8], tag: Tag, first: Tag) -> [u8; N] {
1500 let len = usize::from(u8::from(tag).wrapping_sub(u8::from(first)));
1501 read_varint_payload(data, len, false)
1502}
1503
1504#[inline(always)]
1505pub(super) fn read_byte_array<const N: usize>(data: &mut &[u8]) -> [u8; N] {
1506 let (prev, next) = data.split_first_chunk().unwrap();
1507 *data = next;
1508 *prev
1509}
1510
1511pub(super) fn read_date(data: &mut &[u8]) -> Date {
1512 let days = i32::from_le_bytes(read_byte_array(data));
1513 Date::from_pg_epoch(days).expect("unexpected date")
1514}
1515
1516pub(super) fn read_naive_date(data: &mut &[u8]) -> NaiveDate {
1517 let year = i32::from_le_bytes(read_byte_array(data));
1518 let ordinal = u32::from_le_bytes(read_byte_array(data));
1519 NaiveDate::from_yo_opt(year, ordinal).unwrap()
1520}
1521
1522pub(super) fn read_time(data: &mut &[u8]) -> NaiveTime {
1523 let secs = u32::from_le_bytes(read_byte_array(data));
1524 let nanos = u32::from_le_bytes(read_byte_array(data));
1525 NaiveTime::from_num_seconds_from_midnight_opt(secs, nanos).unwrap()
1526}
1527
1528pub unsafe fn read_datum<'a>(data: &mut &'a [u8]) -> Datum<'a> {
1537 let tag = Tag::try_from_primitive(read_byte(data)).expect("unknown row tag");
1538 match tag {
1539 Tag::Null => Datum::Null,
1540 Tag::False => Datum::False,
1541 Tag::True => Datum::True,
1542 Tag::NonNegativeInt16_0
1543 | Tag::NegativeInt16_0
1544 | Tag::NonNegativeInt16_8
1545 | Tag::NegativeInt16_8
1546 | Tag::Int16 => Datum::Int16(i16::from_le_bytes(read_signed_varint(
1547 data,
1548 tag,
1549 Tag::NonNegativeInt16_0,
1550 ))),
1551 Tag::NonNegativeInt32_0
1552 | Tag::NegativeInt32_0
1553 | Tag::NonNegativeInt32_8
1554 | Tag::NegativeInt32_8
1555 | Tag::NonNegativeInt32_16
1556 | Tag::NegativeInt32_16
1557 | Tag::NonNegativeInt32_24
1558 | Tag::NegativeInt32_24
1559 | Tag::Int32 => Datum::Int32(i32::from_le_bytes(read_signed_varint(
1560 data,
1561 tag,
1562 Tag::NonNegativeInt32_0,
1563 ))),
1564 Tag::NonNegativeInt64_0
1565 | Tag::NegativeInt64_0
1566 | Tag::NonNegativeInt64_8
1567 | Tag::NegativeInt64_8
1568 | Tag::NonNegativeInt64_16
1569 | Tag::NegativeInt64_16
1570 | Tag::NonNegativeInt64_24
1571 | Tag::NegativeInt64_24
1572 | Tag::NonNegativeInt64_32
1573 | Tag::NegativeInt64_32
1574 | Tag::NonNegativeInt64_40
1575 | Tag::NegativeInt64_40
1576 | Tag::NonNegativeInt64_48
1577 | Tag::NegativeInt64_48
1578 | Tag::NonNegativeInt64_56
1579 | Tag::NegativeInt64_56
1580 | Tag::Int64 => Datum::Int64(i64::from_le_bytes(read_signed_varint(
1581 data,
1582 tag,
1583 Tag::NonNegativeInt64_0,
1584 ))),
1585 Tag::UInt8_0 | Tag::UInt8 => Datum::UInt8(u8::from_le_bytes(read_unsigned_varint(
1586 data,
1587 tag,
1588 Tag::UInt8_0,
1589 ))),
1590 Tag::UInt16_0 | Tag::UInt16_8 | Tag::UInt16 => Datum::UInt16(u16::from_le_bytes(
1591 read_unsigned_varint(data, tag, Tag::UInt16_0),
1592 )),
1593 Tag::UInt32_0 | Tag::UInt32_8 | Tag::UInt32_16 | Tag::UInt32_24 | Tag::UInt32 => {
1594 Datum::UInt32(u32::from_le_bytes(read_unsigned_varint(
1595 data,
1596 tag,
1597 Tag::UInt32_0,
1598 )))
1599 }
1600 Tag::UInt64_0
1601 | Tag::UInt64_8
1602 | Tag::UInt64_16
1603 | Tag::UInt64_24
1604 | Tag::UInt64_32
1605 | Tag::UInt64_40
1606 | Tag::UInt64_48
1607 | Tag::UInt64_56
1608 | Tag::UInt64 => Datum::UInt64(u64::from_le_bytes(read_unsigned_varint(
1609 data,
1610 tag,
1611 Tag::UInt64_0,
1612 ))),
1613
1614 Tag::Float32 => {
1615 let f = f32::from_bits(u32::from_le_bytes(read_byte_array(data)));
1616 Datum::Float32(OrderedFloat::from(f))
1617 }
1618 Tag::Float64 => {
1619 let f = f64::from_bits(u64::from_le_bytes(read_byte_array(data)));
1620 Datum::Float64(OrderedFloat::from(f))
1621 }
1622 Tag::Date => Datum::Date(read_date(data)),
1623 Tag::Time => Datum::Time(read_time(data)),
1624 Tag::CheapTimestamp => {
1625 let ts = i64::from_le_bytes(read_byte_array(data));
1626 let secs = ts.div_euclid(1_000_000_000);
1627 let nsecs: u32 = ts.rem_euclid(1_000_000_000).try_into().unwrap();
1628 let ndt = DateTime::from_timestamp(secs, nsecs)
1629 .expect("We only write round-trippable timestamps")
1630 .naive_utc();
1631 Datum::Timestamp(
1632 CheckedTimestamp::from_timestamplike(ndt).expect("unexpected timestamp"),
1633 )
1634 }
1635 Tag::CheapTimestampTz => {
1636 let ts = i64::from_le_bytes(read_byte_array(data));
1637 let secs = ts.div_euclid(1_000_000_000);
1638 let nsecs: u32 = ts.rem_euclid(1_000_000_000).try_into().unwrap();
1639 let dt = DateTime::from_timestamp(secs, nsecs)
1640 .expect("We only write round-trippable timestamps");
1641 Datum::TimestampTz(
1642 CheckedTimestamp::from_timestamplike(dt).expect("unexpected timestamp"),
1643 )
1644 }
1645 Tag::Timestamp => {
1646 let date = read_naive_date(data);
1647 let time = read_time(data);
1648 Datum::Timestamp(
1649 CheckedTimestamp::from_timestamplike(date.and_time(time))
1650 .expect("unexpected timestamp"),
1651 )
1652 }
1653 Tag::TimestampTz => {
1654 let date = read_naive_date(data);
1655 let time = read_time(data);
1656 Datum::TimestampTz(
1657 CheckedTimestamp::from_timestamplike(DateTime::from_naive_utc_and_offset(
1658 date.and_time(time),
1659 Utc,
1660 ))
1661 .expect("unexpected timestamptz"),
1662 )
1663 }
1664 Tag::Interval => {
1665 let months = i32::from_le_bytes(read_byte_array(data));
1666 let days = i32::from_le_bytes(read_byte_array(data));
1667 let micros = i64::from_le_bytes(read_byte_array(data));
1668 Datum::Interval(Interval {
1669 months,
1670 days,
1671 micros,
1672 })
1673 }
1674 Tag::BytesTiny | Tag::BytesShort | Tag::BytesLong | Tag::BytesHuge => {
1675 Datum::Bytes(read_lengthed_bytes(data, tag, Tag::BytesTiny))
1676 }
1677 Tag::StringTiny | Tag::StringShort | Tag::StringLong | Tag::StringHuge => {
1678 Datum::String(str::from_utf8_unchecked(read_lengthed_bytes(
1680 data,
1681 tag,
1682 Tag::StringTiny,
1683 )))
1684 }
1685 Tag::ListTiny | Tag::ListShort | Tag::ListLong | Tag::ListHuge => Datum::List(
1686 DatumList::new(read_lengthed_bytes(data, tag, Tag::ListTiny)),
1687 ),
1688 Tag::Uuid => Datum::Uuid(Uuid::from_bytes(read_byte_array(data))),
1689 Tag::Array => {
1690 let ndims = read_byte(data);
1693 let dims_size = usize::from(ndims) * size_of::<u64>() * 2;
1694 let (dims, next) = data.split_at(dims_size);
1695 *data = next;
1696 let bytes = read_untagged_bytes(data);
1697 Datum::Array(Array {
1698 dims: ArrayDimensions { data: dims },
1699 elements: DatumList::new(bytes),
1700 })
1701 }
1702 Tag::Dict => {
1703 let bytes = read_untagged_bytes(data);
1704 Datum::Map(DatumMap::new(bytes))
1705 }
1706 Tag::JsonNull => Datum::JsonNull,
1707 Tag::Dummy => Datum::Dummy,
1708 Tag::Numeric => {
1709 let digits = read_byte(data).into();
1710 let exponent = i8::reinterpret_cast(read_byte(data));
1711 let bits = read_byte(data);
1712
1713 let lsu_u16_len = Numeric::digits_to_lsu_elements_len(digits);
1714 let lsu_u8_len = lsu_u16_len * 2;
1715 let (lsu_u8, next) = data.split_at(lsu_u8_len);
1716 *data = next;
1717
1718 let mut lsu = [0; numeric::NUMERIC_DATUM_WIDTH_USIZE];
1722 for (i, c) in lsu_u8.chunks(2).enumerate() {
1723 lsu[i] = u16::from_le_bytes(c.try_into().unwrap());
1724 }
1725
1726 let d = Numeric::from_raw_parts(digits, exponent.into(), bits, lsu);
1727 Datum::from(d)
1728 }
1729 Tag::MzTimestamp => {
1730 let t = Timestamp::decode(read_byte_array(data));
1731 Datum::MzTimestamp(t)
1732 }
1733 Tag::Range => {
1734 let flag_byte = read_byte(data);
1736 let flags = range::InternalFlags::from_bits(flag_byte)
1737 .expect("range flags must be encoded validly");
1738
1739 if flags.contains(range::InternalFlags::EMPTY) {
1740 assert!(
1741 flags == range::InternalFlags::EMPTY,
1742 "empty ranges contain only RANGE_EMPTY flag"
1743 );
1744
1745 return Datum::Range(Range { inner: None });
1746 }
1747
1748 let lower_bound = if flags.contains(range::InternalFlags::LB_INFINITE) {
1749 None
1750 } else {
1751 Some(DatumNested::extract(data))
1752 };
1753
1754 let lower = RangeBound {
1755 inclusive: flags.contains(range::InternalFlags::LB_INCLUSIVE),
1756 bound: lower_bound,
1757 };
1758
1759 let upper_bound = if flags.contains(range::InternalFlags::UB_INFINITE) {
1760 None
1761 } else {
1762 Some(DatumNested::extract(data))
1763 };
1764
1765 let upper = RangeBound {
1766 inclusive: flags.contains(range::InternalFlags::UB_INCLUSIVE),
1767 bound: upper_bound,
1768 };
1769
1770 Datum::Range(Range {
1771 inner: Some(RangeInner { lower, upper }),
1772 })
1773 }
1774 Tag::MzAclItem => {
1775 const N: usize = MzAclItem::binary_size();
1776 let mz_acl_item =
1777 MzAclItem::decode_binary(&read_byte_array::<N>(data)).expect("invalid mz_aclitem");
1778 Datum::MzAclItem(mz_acl_item)
1779 }
1780 Tag::AclItem => {
1781 const N: usize = AclItem::binary_size();
1782 let acl_item =
1783 AclItem::decode_binary(&read_byte_array::<N>(data)).expect("invalid aclitem");
1784 Datum::AclItem(acl_item)
1785 }
1786 }
1787}
1788
1789fn push_untagged_bytes<D>(data: &mut D, bytes: &[u8])
1793where
1794 D: Vector<u8>,
1795{
1796 let len = u64::cast_from(bytes.len());
1797 data.extend_from_slice(&len.to_le_bytes());
1798 data.extend_from_slice(bytes);
1799}
1800
1801fn push_lengthed_bytes<D>(data: &mut D, bytes: &[u8], tag: Tag)
1802where
1803 D: Vector<u8>,
1804{
1805 match tag {
1806 Tag::BytesTiny | Tag::StringTiny | Tag::ListTiny => {
1807 let len = bytes.len().to_le_bytes();
1808 data.push(len[0]);
1809 }
1810 Tag::BytesShort | Tag::StringShort | Tag::ListShort => {
1811 let len = bytes.len().to_le_bytes();
1812 data.extend_from_slice(&len[0..2]);
1813 }
1814 Tag::BytesLong | Tag::StringLong | Tag::ListLong => {
1815 let len = bytes.len().to_le_bytes();
1816 data.extend_from_slice(&len[0..4]);
1817 }
1818 Tag::BytesHuge | Tag::StringHuge | Tag::ListHuge => {
1819 let len = bytes.len().to_le_bytes();
1820 data.extend_from_slice(&len);
1821 }
1822 _ => unreachable!(),
1823 }
1824 data.extend_from_slice(bytes);
1825}
1826
1827pub(super) fn date_to_array(date: Date) -> [u8; size_of::<i32>()] {
1828 i32::to_le_bytes(date.pg_epoch_days())
1829}
1830
1831fn push_date<D>(data: &mut D, date: Date)
1832where
1833 D: Vector<u8>,
1834{
1835 data.extend_from_slice(&date_to_array(date));
1836}
1837
1838pub(super) fn naive_date_to_arrays(
1839 date: NaiveDate,
1840) -> ([u8; size_of::<i32>()], [u8; size_of::<u32>()]) {
1841 (
1842 i32::to_le_bytes(date.year()),
1843 u32::to_le_bytes(date.ordinal()),
1844 )
1845}
1846
1847fn push_naive_date<D>(data: &mut D, date: NaiveDate)
1848where
1849 D: Vector<u8>,
1850{
1851 let (ds1, ds2) = naive_date_to_arrays(date);
1852 data.extend_from_slice(&ds1);
1853 data.extend_from_slice(&ds2);
1854}
1855
1856pub(super) fn time_to_arrays(time: NaiveTime) -> ([u8; size_of::<u32>()], [u8; size_of::<u32>()]) {
1857 (
1858 u32::to_le_bytes(time.num_seconds_from_midnight()),
1859 u32::to_le_bytes(time.nanosecond()),
1860 )
1861}
1862
1863fn push_time<D>(data: &mut D, time: NaiveTime)
1864where
1865 D: Vector<u8>,
1866{
1867 let (ts1, ts2) = time_to_arrays(time);
1868 data.extend_from_slice(&ts1);
1869 data.extend_from_slice(&ts2);
1870}
1871
1872fn checked_timestamp_nanos(dt: NaiveDateTime) -> Option<i64> {
1882 let subsec_nanos = dt.and_utc().timestamp_subsec_nanos();
1883 if subsec_nanos >= 1_000_000_000 {
1884 return None;
1885 }
1886 let as_ns = dt.and_utc().timestamp().checked_mul(1_000_000_000)?;
1887 as_ns.checked_add(i64::from(subsec_nanos))
1888}
1889
1890#[inline(always)]
1896#[allow(clippy::as_conversions)]
1897fn min_bytes_signed<T>(i: T) -> u8
1898where
1899 T: Into<i64>,
1900{
1901 let i: i64 = i.into();
1902
1903 let n_sign_bits = if i.is_negative() {
1907 i.leading_ones() as u8
1908 } else {
1909 i.leading_zeros() as u8
1910 };
1911
1912 (64 - n_sign_bits + 7) / 8
1913}
1914
1915#[inline(always)]
1923#[allow(clippy::as_conversions)]
1924fn min_bytes_unsigned<T>(i: T) -> u8
1925where
1926 T: Into<u64>,
1927{
1928 let i: u64 = i.into();
1929
1930 let n_sign_bits = i.leading_zeros() as u8;
1931
1932 (64 - n_sign_bits + 7) / 8
1933}
1934
1935const TINY: usize = 1 << 8;
1936const SHORT: usize = 1 << 16;
1937const LONG: usize = 1 << 32;
1938
1939fn push_datum<D>(data: &mut D, datum: Datum)
1940where
1941 D: Vector<u8>,
1942{
1943 match datum {
1944 Datum::Null => data.push(Tag::Null.into()),
1945 Datum::False => data.push(Tag::False.into()),
1946 Datum::True => data.push(Tag::True.into()),
1947 Datum::Int16(i) => {
1948 const WIDEST_DELTA: u8 = Tag::Int16.byte() - Tag::NonNegativeInt16_0.byte();
1952 let mbs = min_bytes_signed(i);
1953 let delta = ((mbs << 1) + u8::from(i.is_negative())).min(WIDEST_DELTA);
1954 let tag = u8::from(Tag::NonNegativeInt16_0) + delta;
1955
1956 data.push(tag);
1957 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbs)]);
1958 }
1959 Datum::Int32(i) => {
1960 const WIDEST_DELTA: u8 = Tag::Int32.byte() - Tag::NonNegativeInt32_0.byte();
1964 let mbs = min_bytes_signed(i);
1965 let delta = ((mbs << 1) + u8::from(i.is_negative())).min(WIDEST_DELTA);
1966 let tag = u8::from(Tag::NonNegativeInt32_0) + delta;
1967
1968 data.push(tag);
1969 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbs)]);
1970 }
1971 Datum::Int64(i) => {
1972 const WIDEST_DELTA: u8 = Tag::Int64.byte() - Tag::NonNegativeInt64_0.byte();
1976 let mbs = min_bytes_signed(i);
1977 let delta = ((mbs << 1) + u8::from(i.is_negative())).min(WIDEST_DELTA);
1978 let tag = u8::from(Tag::NonNegativeInt64_0) + delta;
1979
1980 data.push(tag);
1981 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbs)]);
1982 }
1983 Datum::UInt8(i) => {
1984 let mbu = min_bytes_unsigned(i);
1985 let tag = u8::from(Tag::UInt8_0) + mbu;
1986 data.push(tag);
1987 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbu)]);
1988 }
1989 Datum::UInt16(i) => {
1990 let mbu = min_bytes_unsigned(i);
1991 let tag = u8::from(Tag::UInt16_0) + mbu;
1992 data.push(tag);
1993 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbu)]);
1994 }
1995 Datum::UInt32(i) => {
1996 let mbu = min_bytes_unsigned(i);
1997 let tag = u8::from(Tag::UInt32_0) + mbu;
1998 data.push(tag);
1999 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbu)]);
2000 }
2001 Datum::UInt64(i) => {
2002 let mbu = min_bytes_unsigned(i);
2003 let tag = u8::from(Tag::UInt64_0) + mbu;
2004 data.push(tag);
2005 data.extend_from_slice(&i.to_le_bytes()[0..usize::from(mbu)]);
2006 }
2007 Datum::Float32(f) => {
2008 data.push(Tag::Float32.into());
2009 data.extend_from_slice(&f.to_bits().to_le_bytes());
2010 }
2011 Datum::Float64(f) => {
2012 data.push(Tag::Float64.into());
2013 data.extend_from_slice(&f.to_bits().to_le_bytes());
2014 }
2015 Datum::Date(d) => {
2016 data.push(Tag::Date.into());
2017 push_date(data, d);
2018 }
2019 Datum::Time(t) => {
2020 data.push(Tag::Time.into());
2021 push_time(data, t);
2022 }
2023 Datum::Timestamp(t) => {
2024 let datetime = t.to_naive();
2025 if let Some(nanos) = checked_timestamp_nanos(datetime) {
2026 data.push(Tag::CheapTimestamp.into());
2027 data.extend_from_slice(&nanos.to_le_bytes());
2028 } else {
2029 data.push(Tag::Timestamp.into());
2030 push_naive_date(data, datetime.date());
2031 push_time(data, datetime.time());
2032 }
2033 }
2034 Datum::TimestampTz(t) => {
2035 let datetime = t.to_naive();
2036 if let Some(nanos) = checked_timestamp_nanos(datetime) {
2037 data.push(Tag::CheapTimestampTz.into());
2038 data.extend_from_slice(&nanos.to_le_bytes());
2039 } else {
2040 data.push(Tag::TimestampTz.into());
2041 push_naive_date(data, datetime.date());
2042 push_time(data, datetime.time());
2043 }
2044 }
2045 Datum::Interval(i) => {
2046 data.push(Tag::Interval.into());
2047 data.extend_from_slice(&i.months.to_le_bytes());
2048 data.extend_from_slice(&i.days.to_le_bytes());
2049 data.extend_from_slice(&i.micros.to_le_bytes());
2050 }
2051 Datum::Bytes(bytes) => {
2052 let tag = match bytes.len() {
2053 0..TINY => Tag::BytesTiny,
2054 TINY..SHORT => Tag::BytesShort,
2055 SHORT..LONG => Tag::BytesLong,
2056 _ => Tag::BytesHuge,
2057 };
2058 data.push(tag.into());
2059 push_lengthed_bytes(data, bytes, tag);
2060 }
2061 Datum::String(string) => {
2062 let tag = match string.len() {
2063 0..TINY => Tag::StringTiny,
2064 TINY..SHORT => Tag::StringShort,
2065 SHORT..LONG => Tag::StringLong,
2066 _ => Tag::StringHuge,
2067 };
2068 data.push(tag.into());
2069 push_lengthed_bytes(data, string.as_bytes(), tag);
2070 }
2071 Datum::List(list) => {
2072 let tag = match list.data.len() {
2073 0..TINY => Tag::ListTiny,
2074 TINY..SHORT => Tag::ListShort,
2075 SHORT..LONG => Tag::ListLong,
2076 _ => Tag::ListHuge,
2077 };
2078 data.push(tag.into());
2079 push_lengthed_bytes(data, list.data, tag);
2080 }
2081 Datum::Uuid(u) => {
2082 data.push(Tag::Uuid.into());
2083 data.extend_from_slice(u.as_bytes());
2084 }
2085 Datum::Array(array) => {
2086 data.push(Tag::Array.into());
2089 data.push(array.dims.ndims());
2090 data.extend_from_slice(array.dims.data);
2091 push_untagged_bytes(data, array.elements.data);
2092 }
2093 Datum::Map(dict) => {
2094 data.push(Tag::Dict.into());
2095 push_untagged_bytes(data, dict.data);
2096 }
2097 Datum::JsonNull => data.push(Tag::JsonNull.into()),
2098 Datum::MzTimestamp(t) => {
2099 data.push(Tag::MzTimestamp.into());
2100 data.extend_from_slice(&t.encode());
2101 }
2102 Datum::Dummy => data.push(Tag::Dummy.into()),
2103 Datum::Numeric(mut n) => {
2104 numeric::cx_datum().reduce(&mut n.0);
2109 let (digits, exponent, bits, lsu) = n.0.to_raw_parts();
2110 data.push(Tag::Numeric.into());
2111 data.push(u8::try_from(digits).expect("digits to fit within u8; should not exceed 39"));
2112 data.push(
2113 i8::try_from(exponent)
2114 .expect("exponent to fit within i8; should not exceed +/- 39")
2115 .to_le_bytes()[0],
2116 );
2117 data.push(bits);
2118
2119 let lsu = &lsu[..Numeric::digits_to_lsu_elements_len(digits)];
2120
2121 if cfg!(target_endian = "little") {
2123 let (prefix, lsu_bytes, suffix) = unsafe { lsu.align_to::<u8>() };
2126 soft_assert_no_log!(
2129 lsu_bytes.len() == Numeric::digits_to_lsu_elements_len(digits) * 2,
2130 "u8 version of numeric LSU contained the wrong number of elements; expected {}, but got {}",
2131 Numeric::digits_to_lsu_elements_len(digits) * 2,
2132 lsu_bytes.len()
2133 );
2134 soft_assert_no_log!(prefix.is_empty() && suffix.is_empty());
2136 data.extend_from_slice(lsu_bytes);
2137 } else {
2138 for u in lsu {
2139 data.extend_from_slice(&u.to_le_bytes());
2140 }
2141 }
2142 }
2143 Datum::Range(range) => {
2144 data.push(Tag::Range.into());
2146 data.push(range.internal_flag_bits());
2147
2148 if let Some(RangeInner { lower, upper }) = range.inner {
2149 for bound in [lower.bound, upper.bound] {
2150 if let Some(bound) = bound {
2151 match bound.datum() {
2152 Datum::Null => panic!("cannot push Datum::Null into range"),
2153 d => push_datum::<D>(data, d),
2154 }
2155 }
2156 }
2157 }
2158 }
2159 Datum::MzAclItem(mz_acl_item) => {
2160 data.push(Tag::MzAclItem.into());
2161 data.extend_from_slice(&mz_acl_item.encode_binary());
2162 }
2163 Datum::AclItem(acl_item) => {
2164 data.push(Tag::AclItem.into());
2165 data.extend_from_slice(&acl_item.encode_binary());
2166 }
2167 }
2168}
2169
2170pub fn row_size<'a, I>(a: I) -> usize
2172where
2173 I: IntoIterator<Item = Datum<'a>>,
2174{
2175 let sz = datums_size::<_, _>(a);
2180 let size_of_row = std::mem::size_of::<Row>();
2181 if sz > Row::SIZE {
2185 sz + size_of_row
2186 } else {
2187 size_of_row
2188 }
2189}
2190
2191pub fn datum_size(datum: &Datum) -> usize {
2194 match datum {
2195 Datum::Null => 1,
2196 Datum::False => 1,
2197 Datum::True => 1,
2198 Datum::Int16(i) => 1 + usize::from(min_bytes_signed(*i)),
2199 Datum::Int32(i) => 1 + usize::from(min_bytes_signed(*i)),
2200 Datum::Int64(i) => 1 + usize::from(min_bytes_signed(*i)),
2201 Datum::UInt8(i) => 1 + usize::from(min_bytes_unsigned(*i)),
2202 Datum::UInt16(i) => 1 + usize::from(min_bytes_unsigned(*i)),
2203 Datum::UInt32(i) => 1 + usize::from(min_bytes_unsigned(*i)),
2204 Datum::UInt64(i) => 1 + usize::from(min_bytes_unsigned(*i)),
2205 Datum::Float32(_) => 1 + size_of::<f32>(),
2206 Datum::Float64(_) => 1 + size_of::<f64>(),
2207 Datum::Date(_) => 1 + size_of::<i32>(),
2208 Datum::Time(_) => 1 + 8,
2209 Datum::Timestamp(t) => {
2210 1 + if checked_timestamp_nanos(t.to_naive()).is_some() {
2211 8
2212 } else {
2213 16
2214 }
2215 }
2216 Datum::TimestampTz(t) => {
2217 1 + if checked_timestamp_nanos(t.naive_utc()).is_some() {
2218 8
2219 } else {
2220 16
2221 }
2222 }
2223 Datum::Interval(_) => 1 + size_of::<i32>() + size_of::<i32>() + size_of::<i64>(),
2224 Datum::Bytes(bytes) => {
2225 let bytes_for_length = match bytes.len() {
2227 0..TINY => 1,
2228 TINY..SHORT => 2,
2229 SHORT..LONG => 4,
2230 _ => 8,
2231 };
2232 1 + bytes_for_length + bytes.len()
2233 }
2234 Datum::String(string) => {
2235 let bytes_for_length = match string.len() {
2237 0..TINY => 1,
2238 TINY..SHORT => 2,
2239 SHORT..LONG => 4,
2240 _ => 8,
2241 };
2242 1 + bytes_for_length + string.len()
2243 }
2244 Datum::Uuid(_) => 1 + size_of::<uuid::Bytes>(),
2245 Datum::Array(array) => {
2246 1 + size_of::<u8>()
2247 + array.dims.data.len()
2248 + size_of::<u64>()
2249 + array.elements.data.len()
2250 }
2251 Datum::List(list) => 1 + size_of::<u64>() + list.data.len(),
2252 Datum::Map(dict) => 1 + size_of::<u64>() + dict.data.len(),
2253 Datum::JsonNull => 1,
2254 Datum::MzTimestamp(_) => 1 + size_of::<Timestamp>(),
2255 Datum::Dummy => 1,
2256 Datum::Numeric(d) => {
2257 let mut d = d.0.clone();
2258 numeric::cx_datum().reduce(&mut d);
2261 4 + (d.coefficient_units().len() * 2)
2263 }
2264 Datum::Range(Range { inner }) => {
2265 2 + match inner {
2267 None => 0,
2268 Some(RangeInner { lower, upper }) => [lower.bound, upper.bound]
2269 .iter()
2270 .map(|bound| match bound {
2271 None => 0,
2272 Some(bound) => bound.val.len(),
2273 })
2274 .sum(),
2275 }
2276 }
2277 Datum::MzAclItem(_) => 1 + MzAclItem::binary_size(),
2278 Datum::AclItem(_) => 1 + AclItem::binary_size(),
2279 }
2280}
2281
2282pub fn datums_size<'a, I, D>(iter: I) -> usize
2287where
2288 I: IntoIterator<Item = D>,
2289 D: Borrow<Datum<'a>>,
2290{
2291 iter.into_iter().map(|d| datum_size(d.borrow())).sum()
2292}
2293
2294pub fn datum_list_size<'a, I, D>(iter: I) -> usize
2299where
2300 I: IntoIterator<Item = D>,
2301 D: Borrow<Datum<'a>>,
2302{
2303 1 + size_of::<u64>() + datums_size(iter)
2304}
2305
2306impl RowPacker<'_> {
2307 pub fn for_existing_row(row: &mut Row) -> RowPacker<'_> {
2314 RowPacker { row }
2315 }
2316
2317 #[inline]
2319 pub fn push<'a, D>(&mut self, datum: D)
2320 where
2321 D: Borrow<Datum<'a>>,
2322 {
2323 push_datum(&mut self.row.data, *datum.borrow());
2324 }
2325
2326 #[inline]
2328 pub fn extend<'a, I, D>(&mut self, iter: I)
2329 where
2330 I: IntoIterator<Item = D>,
2331 D: Borrow<Datum<'a>>,
2332 {
2333 for datum in iter {
2334 push_datum(&mut self.row.data, *datum.borrow())
2335 }
2336 }
2337
2338 #[inline]
2344 pub fn try_extend<'a, I, E, D>(&mut self, iter: I) -> Result<(), E>
2345 where
2346 I: IntoIterator<Item = Result<D, E>>,
2347 D: Borrow<Datum<'a>>,
2348 {
2349 for datum in iter {
2350 push_datum(&mut self.row.data, *datum?.borrow());
2351 }
2352 Ok(())
2353 }
2354
2355 pub fn extend_by_row(&mut self, row: &Row) {
2357 self.row.data.extend_from_slice(row.data.as_slice());
2358 }
2359
2360 pub fn extend_by_row_ref(&mut self, row: &RowRef) {
2362 self.row.data.extend_from_slice(row.data());
2363 }
2364
2365 #[inline]
2373 pub unsafe fn extend_by_slice_unchecked(&mut self, data: &[u8]) {
2374 self.row.data.extend_from_slice(data)
2375 }
2376
2377 #[inline]
2399 pub fn push_list_with<F, R>(&mut self, f: F) -> R
2400 where
2401 F: FnOnce(&mut RowPacker) -> R,
2402 {
2403 let start = self.row.data.len();
2406 self.row.data.push(Tag::ListTiny.into());
2407 self.row.data.push(0);
2409
2410 let out = f(self);
2411
2412 let len = self.row.data.len() - start - 1 - 1;
2414 if len < TINY {
2416 self.row.data[start + 1] = len.to_le_bytes()[0];
2418 } else {
2419 long_list(&mut self.row.data, start, len);
2422 }
2423
2424 #[cold]
2431 fn long_list(data: &mut CompactBytes, start: usize, len: usize) {
2432 let long_list_inner = |data: &mut CompactBytes, len_len| {
2435 const ZEROS: [u8; 8] = [0; 8];
2438 data.extend_from_slice(&ZEROS[0..len_len - 1]);
2439 data.copy_within(start + 1 + 1..start + 1 + 1 + len, start + 1 + len_len);
2448 data[start + 1..start + 1 + len_len]
2450 .copy_from_slice(&len.to_le_bytes()[0..len_len]);
2451 };
2452 match len {
2453 0..TINY => {
2454 unreachable!()
2455 }
2456 TINY..SHORT => {
2457 data[start] = Tag::ListShort.into();
2458 long_list_inner(data, 2);
2459 }
2460 SHORT..LONG => {
2461 data[start] = Tag::ListLong.into();
2462 long_list_inner(data, 4);
2463 }
2464 _ => {
2465 data[start] = Tag::ListHuge.into();
2466 long_list_inner(data, 8);
2467 }
2468 };
2469 }
2470
2471 out
2472 }
2473
2474 pub fn push_dict_with<F, R>(&mut self, f: F) -> R
2512 where
2513 F: FnOnce(&mut RowPacker) -> R,
2514 {
2515 self.row.data.push(Tag::Dict.into());
2516 let start = self.row.data.len();
2517 self.row.data.extend_from_slice(&[0; size_of::<u64>()]);
2519
2520 let res = f(self);
2521
2522 let len = u64::cast_from(self.row.data.len() - start - size_of::<u64>());
2523 self.row.data[start..start + size_of::<u64>()].copy_from_slice(&len.to_le_bytes());
2525
2526 res
2527 }
2528
2529 pub fn try_push_dict_with<F, E>(&mut self, f: F) -> Result<(), E>
2531 where
2532 F: FnOnce(&mut RowPacker) -> Result<(), E>,
2533 {
2534 self.push_dict_with(f)
2535 }
2536
2537 pub fn try_push_array<'a, I, D>(
2544 &mut self,
2545 dims: &[ArrayDimension],
2546 iter: I,
2547 ) -> Result<(), InvalidArrayError>
2548 where
2549 I: IntoIterator<Item = D>,
2550 D: Borrow<Datum<'a>>,
2551 {
2552 unsafe {
2554 self.push_array_with_unchecked(dims, |packer| {
2555 let mut nelements = 0;
2556 for datum in iter {
2557 packer.push(datum);
2558 nelements += 1;
2559 }
2560 Ok::<_, InvalidArrayError>(nelements)
2561 })
2562 }
2563 }
2564
2565 pub fn try_push_array_fallible<'a, I, D, E>(
2568 &mut self,
2569 dims: &[ArrayDimension],
2570 iter: I,
2571 ) -> Result<Result<(), E>, InvalidArrayError>
2572 where
2573 I: IntoIterator<Item = Result<D, E>>,
2574 D: Borrow<Datum<'a>>,
2575 {
2576 enum Error<E> {
2577 Usage(InvalidArrayError),
2578 Inner(E),
2579 }
2580
2581 impl<E> From<InvalidArrayError> for Error<E> {
2582 fn from(e: InvalidArrayError) -> Self {
2583 Self::Usage(e)
2584 }
2585 }
2586
2587 let result = unsafe {
2589 self.push_array_with_unchecked(dims, |packer| {
2590 let mut nelements = 0;
2591 for datum in iter {
2592 packer.push(datum.map_err(Error::Inner)?);
2593 nelements += 1;
2594 }
2595 Ok(nelements)
2596 })
2597 };
2598 match result {
2599 Ok(()) => Ok(Ok(())),
2600 Err(Error::Usage(e)) => Err(e),
2601 Err(Error::Inner(e)) => Ok(Err(e)),
2602 }
2603 }
2604
2605 pub unsafe fn push_array_with_unchecked<F, E>(
2614 &mut self,
2615 dims: &[ArrayDimension],
2616 f: F,
2617 ) -> Result<(), E>
2618 where
2619 F: FnOnce(&mut RowPacker) -> Result<usize, E>,
2620 E: From<InvalidArrayError>,
2621 {
2622 if dims.len() > usize::from(MAX_ARRAY_DIMENSIONS) {
2634 return Err(InvalidArrayError::TooManyDimensions(dims.len()).into());
2635 }
2636
2637 let start = self.row.data.len();
2638 self.row.data.push(Tag::Array.into());
2639
2640 self.row
2642 .data
2643 .push(dims.len().try_into().expect("ndims verified to fit in u8"));
2644 for dim in dims {
2645 self.row
2646 .data
2647 .extend_from_slice(&i64::cast_from(dim.lower_bound).to_le_bytes());
2648 self.row
2649 .data
2650 .extend_from_slice(&u64::cast_from(dim.length).to_le_bytes());
2651 }
2652
2653 let off = self.row.data.len();
2655 self.row.data.extend_from_slice(&[0; size_of::<u64>()]);
2656 let nelements = match f(self) {
2657 Ok(nelements) => nelements,
2658 Err(e) => {
2659 self.row.data.truncate(start);
2660 return Err(e);
2661 }
2662 };
2663 let len = u64::cast_from(self.row.data.len() - off - size_of::<u64>());
2664 self.row.data[off..off + size_of::<u64>()].copy_from_slice(&len.to_le_bytes());
2665
2666 let cardinality = match dims {
2669 [] => 0,
2670 dims => dims
2678 .iter()
2679 .map(|d| d.length)
2680 .fold(1usize, usize::saturating_mul),
2681 };
2682 if nelements != cardinality {
2683 self.row.data.truncate(start);
2684 return Err(InvalidArrayError::WrongCardinality {
2685 actual: nelements,
2686 expected: cardinality,
2687 }
2688 .into());
2689 }
2690
2691 Ok(())
2692 }
2693
2694 pub fn push_array_with_row_major<F, I>(
2704 &mut self,
2705 dims: I,
2706 f: F,
2707 ) -> Result<(), InvalidArrayError>
2708 where
2709 I: IntoIterator<Item = ArrayDimension>,
2710 F: FnOnce(&mut RowPacker) -> usize,
2711 {
2712 let start = self.row.data.len();
2713 self.row.data.push(Tag::Array.into());
2714
2715 let dims_start = self.row.data.len();
2717 self.row.data.push(42);
2718
2719 let mut num_dims: u8 = 0;
2720 let mut cardinality: usize = 1;
2721 for dim in dims {
2722 num_dims += 1;
2723 cardinality = cardinality.saturating_mul(dim.length);
2727
2728 self.row
2729 .data
2730 .extend_from_slice(&i64::cast_from(dim.lower_bound).to_le_bytes());
2731 self.row
2732 .data
2733 .extend_from_slice(&u64::cast_from(dim.length).to_le_bytes());
2734 }
2735
2736 if num_dims > MAX_ARRAY_DIMENSIONS {
2737 self.row.data.truncate(start);
2739 return Err(InvalidArrayError::TooManyDimensions(usize::from(num_dims)));
2740 }
2741 self.row.data[dims_start..dims_start + size_of::<u8>()]
2743 .copy_from_slice(&num_dims.to_le_bytes());
2744
2745 let off = self.row.data.len();
2747 self.row.data.extend_from_slice(&[0; size_of::<u64>()]);
2748
2749 let nelements = f(self);
2750
2751 let len = u64::cast_from(self.row.data.len() - off - size_of::<u64>());
2752 self.row.data[off..off + size_of::<u64>()].copy_from_slice(&len.to_le_bytes());
2753
2754 let cardinality = match num_dims {
2757 0 => 0,
2758 _ => cardinality,
2759 };
2760 if nelements != cardinality {
2761 self.row.data.truncate(start);
2762 return Err(InvalidArrayError::WrongCardinality {
2763 actual: nelements,
2764 expected: cardinality,
2765 });
2766 }
2767
2768 Ok(())
2769 }
2770
2771 pub fn push_list<'a, I, D>(&mut self, iter: I)
2775 where
2776 I: IntoIterator<Item = D>,
2777 D: Borrow<Datum<'a>>,
2778 {
2779 self.push_list_with(|packer| {
2780 for elem in iter {
2781 packer.push(*elem.borrow())
2782 }
2783 });
2784 }
2785
2786 pub fn push_dict<'a, I, D>(&mut self, iter: I)
2788 where
2789 I: IntoIterator<Item = (&'a str, D)>,
2790 D: Borrow<Datum<'a>>,
2791 {
2792 self.push_dict_with(|packer| {
2793 for (k, v) in iter {
2794 packer.push(Datum::String(k));
2795 packer.push(*v.borrow())
2796 }
2797 })
2798 }
2799
2800 pub fn push_range<'a>(&mut self, mut range: Range<Datum<'a>>) -> Result<(), InvalidRangeError> {
2816 range.canonicalize()?;
2817 match range.inner {
2818 None => {
2819 self.row.data.push(Tag::Range.into());
2820 self.row.data.push(range::InternalFlags::EMPTY.bits());
2822 Ok(())
2823 }
2824 Some(inner) => self.push_range_with(
2825 RangeLowerBound {
2826 inclusive: inner.lower.inclusive,
2827 bound: inner
2828 .lower
2829 .bound
2830 .map(|value| move |row: &mut RowPacker| Ok(row.push(value))),
2831 },
2832 RangeUpperBound {
2833 inclusive: inner.upper.inclusive,
2834 bound: inner
2835 .upper
2836 .bound
2837 .map(|value| move |row: &mut RowPacker| Ok(row.push(value))),
2838 },
2839 ),
2840 }
2841 }
2842
2843 pub fn push_range_with<L, U, E>(
2866 &mut self,
2867 lower: RangeLowerBound<L>,
2868 upper: RangeUpperBound<U>,
2869 ) -> Result<(), E>
2870 where
2871 L: FnOnce(&mut RowPacker) -> Result<(), E>,
2872 U: FnOnce(&mut RowPacker) -> Result<(), E>,
2873 E: From<InvalidRangeError>,
2874 {
2875 let start = self.row.data.len();
2876 self.row.data.push(Tag::Range.into());
2877
2878 let mut flags = range::InternalFlags::empty();
2879
2880 flags.set(range::InternalFlags::LB_INFINITE, lower.bound.is_none());
2881 flags.set(range::InternalFlags::UB_INFINITE, upper.bound.is_none());
2882 flags.set(range::InternalFlags::LB_INCLUSIVE, lower.inclusive);
2883 flags.set(range::InternalFlags::UB_INCLUSIVE, upper.inclusive);
2884
2885 let mut expected_datums = 0;
2886
2887 self.row.data.push(flags.bits());
2888
2889 let datum_check = self.row.data.len();
2890
2891 if let Some(value) = lower.bound {
2892 let start = self.row.data.len();
2893 value(self)?;
2894 assert!(
2895 start < self.row.data.len(),
2896 "finite values must each push exactly one value; expected 1 but got 0"
2897 );
2898 expected_datums += 1;
2899 }
2900
2901 if let Some(value) = upper.bound {
2902 let start = self.row.data.len();
2903 value(self)?;
2904 assert!(
2905 start < self.row.data.len(),
2906 "finite values must each push exactly one value; expected 1 but got 0"
2907 );
2908 expected_datums += 1;
2909 }
2910
2911 let mut actual_datums = 0;
2915 let mut seen = None;
2916 let mut dataz = &self.row.data[datum_check..];
2917 while !dataz.is_empty() {
2918 let d = unsafe { read_datum(&mut dataz) };
2919 if d == Datum::Null {
2923 self.row.data.truncate(start);
2924 return Err(InvalidRangeError::InvalidRangeData.into());
2925 }
2926
2927 match seen {
2928 None => seen = Some(d),
2929 Some(seen) => {
2930 let seen_kind = DatumKind::from(seen);
2931 let d_kind = DatumKind::from(d);
2932 if seen_kind != d_kind {
2933 self.row.data.truncate(start);
2934 return Err(InvalidRangeError::InvalidRangeData.into());
2935 }
2936
2937 if seen > d {
2938 self.row.data.truncate(start);
2939 return Err(InvalidRangeError::MisorderedRangeBounds.into());
2940 }
2941 }
2942 }
2943 actual_datums += 1;
2944 }
2945
2946 if actual_datums != expected_datums {
2947 self.row.data.truncate(start);
2948 return Err(InvalidRangeError::InvalidRangeData.into());
2949 }
2950
2951 Ok(())
2952 }
2953
2954 pub fn clear(&mut self) {
2956 self.row.data.clear();
2957 }
2958
2959 pub unsafe fn truncate(&mut self, pos: usize) {
2972 self.row.data.truncate(pos)
2973 }
2974
2975 pub fn truncate_datums(&mut self, n: usize) {
2977 let prev_len = self.row.data.len();
2978 let mut iter = self.row.iter();
2979 for _ in iter.by_ref().take(n) {}
2980 let next_len = iter.data.len();
2981 unsafe { self.truncate(prev_len - next_len) }
2983 }
2984
2985 pub fn byte_len(&self) -> usize {
2987 self.row.byte_len()
2988 }
2989}
2990
2991impl<'a> IntoIterator for &'a Row {
2992 type Item = Datum<'a>;
2993 type IntoIter = DatumListIter<'a>;
2994 fn into_iter(self) -> DatumListIter<'a> {
2995 self.iter()
2996 }
2997}
2998
2999impl fmt::Debug for Row {
3000 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3002 f.write_str("Row{")?;
3003 f.debug_list().entries(self.iter()).finish()?;
3004 f.write_str("}")
3005 }
3006}
3007
3008impl fmt::Display for Row {
3009 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3011 f.write_str("(")?;
3012 for (i, datum) in self.iter().enumerate() {
3013 if i != 0 {
3014 f.write_str(", ")?;
3015 }
3016 write!(f, "{}", datum)?;
3017 }
3018 f.write_str(")")
3019 }
3020}
3021
3022impl<'a, T> DatumList<'a, T> {
3023 pub fn iter(&self) -> DatumListIter<'a> {
3024 DatumListIter { data: self.data }
3025 }
3026
3027 pub fn typed_iter(&self) -> DatumListTypedIter<'a, T>
3033 where
3034 T: FromDatum<'a>,
3035 {
3036 DatumListTypedIter {
3037 inner: self.iter(),
3038 _phantom: PhantomData,
3039 }
3040 }
3041
3042 pub fn data(&self) -> &'a [u8] {
3044 self.data
3045 }
3046}
3047
3048impl<T> DatumList<'static, T> {
3049 pub fn empty() -> Self {
3050 DatumList::new(&[])
3051 }
3052}
3053
3054impl<'a> IntoIterator for DatumList<'a> {
3055 type Item = Datum<'a>;
3056 type IntoIter = DatumListIter<'a>;
3057 fn into_iter(self) -> DatumListIter<'a> {
3058 self.iter()
3059 }
3060}
3061
3062impl<'a> Iterator for DatumListIter<'a> {
3063 type Item = Datum<'a>;
3064 fn next(&mut self) -> Option<Self::Item> {
3065 if self.data.is_empty() {
3066 None
3067 } else {
3068 Some(unsafe { read_datum(&mut self.data) })
3069 }
3070 }
3071}
3072
3073impl<'a, T: FromDatum<'a>> Iterator for DatumListTypedIter<'a, T> {
3074 type Item = T;
3075 fn next(&mut self) -> Option<Self::Item> {
3076 self.inner.next().map(T::from_datum)
3077 }
3078}
3079
3080impl<'a, T> DatumMap<'a, T> {
3081 pub fn iter(&self) -> DatumDictIter<'a> {
3082 DatumDictIter {
3083 data: self.data,
3084 prev_key: None,
3085 }
3086 }
3087
3088 pub fn typed_iter(&self) -> DatumDictTypedIter<'a, T>
3094 where
3095 T: FromDatum<'a>,
3096 {
3097 DatumDictTypedIter {
3098 inner: self.iter(),
3099 _phantom: PhantomData,
3100 }
3101 }
3102
3103 pub fn data(&self) -> &'a [u8] {
3105 self.data
3106 }
3107}
3108
3109impl<T> DatumMap<'static, T> {
3110 pub fn empty() -> Self {
3111 DatumMap::new(&[])
3112 }
3113}
3114
3115impl<'a, T> Debug for DatumMap<'a, T> {
3116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3117 f.debug_map().entries(self.iter()).finish()
3118 }
3119}
3120
3121impl<'a> IntoIterator for &'a DatumMap<'a> {
3122 type Item = (&'a str, Datum<'a>);
3123 type IntoIter = DatumDictIter<'a>;
3124 fn into_iter(self) -> DatumDictIter<'a> {
3125 self.iter()
3126 }
3127}
3128
3129impl<'a> Iterator for DatumDictIter<'a> {
3130 type Item = (&'a str, Datum<'a>);
3131 fn next(&mut self) -> Option<Self::Item> {
3132 if self.data.is_empty() {
3133 None
3134 } else {
3135 let key_tag =
3136 Tag::try_from_primitive(read_byte(&mut self.data)).expect("unknown row tag");
3137 assert!(
3138 key_tag == Tag::StringTiny
3139 || key_tag == Tag::StringShort
3140 || key_tag == Tag::StringLong
3141 || key_tag == Tag::StringHuge,
3142 "Dict keys must be strings, got {:?}",
3143 key_tag
3144 );
3145 let bytes = read_lengthed_bytes(&mut self.data, key_tag, Tag::StringTiny);
3146 let key = unsafe { str::from_utf8_unchecked(bytes) };
3148 let val = unsafe { read_datum(&mut self.data) };
3149
3150 if mz_ore::assert::soft_assertions_enabled() {
3153 if let Some(prev_key) = self.prev_key {
3154 mz_ore::soft_assert_no_log!(
3155 prev_key < key,
3156 "Dict keys must be unique and given in ascending order: {} came before {}",
3157 prev_key,
3158 key
3159 );
3160 }
3161 self.prev_key = Some(key);
3162 }
3163
3164 Some((key, val))
3165 }
3166 }
3167}
3168
3169impl<'a, T: FromDatum<'a>> Iterator for DatumDictTypedIter<'a, T> {
3170 type Item = (&'a str, T);
3171 fn next(&mut self) -> Option<Self::Item> {
3172 self.inner.next().map(|(k, v)| (k, T::from_datum(v)))
3173 }
3174}
3175
3176impl RowArena {
3177 pub fn new() -> Self {
3178 RowArena {
3179 inner: RefCell::new(vec![]),
3180 scratch: RefCell::new(None),
3181 budget: None,
3182 allocated: Cell::new(0),
3183 }
3184 }
3185
3186 pub fn with_budget(budget: usize) -> Self {
3203 RowArena {
3204 budget: Some(budget),
3205 ..RowArena::new()
3206 }
3207 }
3208
3209 pub fn allocated_bytes(&self) -> usize {
3211 self.allocated.get()
3212 }
3213
3214 pub fn over_budget(&self) -> bool {
3216 self.budget
3217 .is_some_and(|budget| self.allocated.get() > budget)
3218 }
3219
3220 pub fn budget_remaining(&self) -> usize {
3226 match self.budget {
3227 None => usize::MAX,
3228 Some(budget) => budget.saturating_sub(self.allocated.get()),
3229 }
3230 }
3231
3232 pub fn with_capacity(capacity: usize) -> Self {
3235 let mut inner = Vec::new();
3236 if capacity > 0 {
3237 inner.push(Vec::with_capacity(capacity));
3238 }
3239 RowArena {
3240 inner: RefCell::new(inner),
3241 ..RowArena::new()
3242 }
3243 }
3244
3245 pub fn reserve(&self, additional: usize) {
3248 if additional == 0 {
3249 return;
3250 }
3251 let mut inner = self.inner.borrow_mut();
3252 match inner.last_mut() {
3253 Some(active) if active.is_empty() => {
3256 if active.capacity() < additional {
3257 active.reserve_exact(additional);
3258 }
3259 }
3260 Some(active) => {
3265 let new_cap = std::cmp::max(additional, active.capacity().saturating_mul(2));
3266 inner.push(Vec::with_capacity(new_cap));
3267 }
3268 None => inner.push(Vec::with_capacity(additional)),
3269 }
3270 }
3271
3272 #[allow(clippy::transmute_ptr_to_ptr)]
3277 pub fn push_bytes<'a, B: Deref<Target = [u8]>>(&'a self, bytes: B) -> &'a [u8] {
3278 let bytes: &[u8] = &bytes;
3279 let need = bytes.len();
3280 if need == 0 {
3281 return &[];
3282 }
3283 let mut inner = self.inner.borrow_mut();
3284
3285 let has_room = inner
3288 .last()
3289 .map_or(false, |region| region.capacity() - region.len() >= need);
3290 if !has_room {
3291 let last_cap = inner.last().map_or(0, |region| region.capacity());
3292 let new_cap = std::cmp::max(need, last_cap.saturating_mul(2));
3293 inner.push(Vec::with_capacity(new_cap));
3294 }
3295
3296 let region = inner.last_mut().expect("region present");
3297 let start = region.len();
3298 region.extend_from_slice(bytes);
3299 self.allocated.set(self.allocated.get() + need);
3300 let copied = ®ion[start..];
3301 unsafe {
3302 transmute::<&[u8], &'a [u8]>(copied)
3312 }
3313 }
3314
3315 pub fn push_owned_bytes<'a>(&'a self, bytes: Vec<u8>) -> &'a [u8] {
3322 const MIN_ADOPT_BYTES: usize = 4 * 1024;
3326
3327 let need = bytes.len();
3328 if need == 0 {
3329 return &[];
3330 }
3331
3332 let mut inner = self.inner.borrow_mut();
3333 let last_cap = inner.last().map_or(0, |region| region.capacity());
3340 let adopt = need > std::cmp::max(MIN_ADOPT_BYTES, last_cap.saturating_mul(2));
3341 if !adopt {
3342 drop(inner);
3343 return self.push_bytes(&bytes[..]);
3344 }
3345
3346 self.allocated.set(self.allocated.get() + need);
3355 let idx = inner.len().saturating_sub(1);
3356 inner.insert(idx, bytes);
3357 if inner.len() == 1 {
3358 inner.push(Vec::new());
3361 }
3362 let adopted = &inner[idx][..];
3363 unsafe { transmute::<&[u8], &'a [u8]>(adopted) }
3364 }
3365
3366 pub fn push_string<'a>(&'a self, string: String) -> &'a str {
3368 let copied = self.push_owned_bytes(string.into_bytes());
3369 unsafe {
3370 std::str::from_utf8_unchecked(copied)
3372 }
3373 }
3374
3375 pub fn writer(&self) -> RowArenaBuf<'_> {
3387 let mut buf = self.scratch.borrow_mut().take().unwrap_or_default();
3391 buf.clear();
3392 RowArenaBuf { arena: self, buf }
3393 }
3394
3395 pub fn push_unary_row<'a>(&'a self, row: Row) -> Datum<'a> {
3401 let copied = self.push_bytes(row.data());
3402 unsafe {
3403 let datum = read_datum(&mut &copied[..]);
3407 transmute::<Datum<'_>, Datum<'a>>(datum)
3408 }
3409 }
3410
3411 fn push_unary_row_datum_nested<'a>(&'a self, row: Row) -> DatumNested<'a> {
3414 let copied = self.push_bytes(row.data());
3415 unsafe {
3416 let nested = DatumNested::extract(&mut &copied[..]);
3418 transmute::<DatumNested<'_>, DatumNested<'a>>(nested)
3419 }
3420 }
3421
3422 pub fn make_datum<'a, F>(&'a self, f: F) -> Datum<'a>
3434 where
3435 F: FnOnce(&mut RowPacker),
3436 {
3437 let mut row = Row::default();
3438 f(&mut row.packer());
3439 self.push_unary_row(row)
3440 }
3441
3442 pub fn make_datum_list<'a, T: std::borrow::Borrow<Datum<'a>>>(
3449 &'a self,
3450 iter: impl IntoIterator<Item = T>,
3451 ) -> DatumList<'a, T> {
3452 let datum = self.make_datum(|packer| {
3453 packer.push_list_with(|packer| {
3454 for elem in iter {
3455 packer.push(*elem.borrow());
3456 }
3457 });
3458 });
3459 DatumList::new(datum.unwrap_list().data())
3460 }
3461
3462 pub fn make_datum_nested<'a, F>(&'a self, f: F) -> DatumNested<'a>
3465 where
3466 F: FnOnce(&mut RowPacker),
3467 {
3468 let mut row = Row::default();
3469 f(&mut row.packer());
3470 self.push_unary_row_datum_nested(row)
3471 }
3472
3473 pub fn try_make_datum<'a, F, E>(&'a self, f: F) -> Result<Datum<'a>, E>
3475 where
3476 F: FnOnce(&mut RowPacker) -> Result<(), E>,
3477 {
3478 let mut row = Row::default();
3479 f(&mut row.packer())?;
3480 Ok(self.push_unary_row(row))
3481 }
3482
3483 pub fn clear(&mut self) {
3488 let inner = self.inner.get_mut();
3489 if let Some(largest) = (0..inner.len()).max_by_key(|&i| inner[i].capacity()) {
3493 inner.swap(0, largest);
3494 inner.truncate(1);
3495 inner[0].clear();
3496 }
3497 self.allocated.set(0);
3498 }
3499}
3500
3501impl Default for RowArena {
3502 fn default() -> RowArena {
3503 RowArena::new()
3504 }
3505}
3506
3507#[derive(Debug)]
3514pub struct RowArenaBuf<'a> {
3515 arena: &'a RowArena,
3516 buf: Vec<u8>,
3517}
3518
3519impl<'a> RowArenaBuf<'a> {
3520 pub fn push(&mut self, byte: u8) {
3522 self.buf.push(byte);
3523 }
3524
3525 pub fn extend_from_slice(&mut self, bytes: &[u8]) {
3527 self.buf.extend_from_slice(bytes);
3528 }
3529
3530 pub fn as_slice(&self) -> &[u8] {
3532 &self.buf
3533 }
3534
3535 pub fn len(&self) -> usize {
3537 self.buf.len()
3538 }
3539
3540 pub fn is_empty(&self) -> bool {
3542 self.buf.is_empty()
3543 }
3544
3545 pub fn finish(self) -> &'a [u8] {
3547 self.arena.push_bytes(self.buf.as_slice())
3550 }
3551
3552 pub fn finish_str(self) -> &'a str {
3557 let bytes = self.arena.push_bytes(self.buf.as_slice());
3558 std::str::from_utf8(bytes).expect("RowArenaBuf::finish_str on non-UTF-8 contents")
3559 }
3560}
3561
3562impl<'a> Drop for RowArenaBuf<'a> {
3563 fn drop(&mut self) {
3564 let mut slot = self.arena.scratch.borrow_mut();
3569 if slot.is_none() {
3570 *slot = Some(std::mem::take(&mut self.buf));
3571 }
3572 }
3573}
3574
3575impl<'a> std::ops::Deref for RowArenaBuf<'a> {
3576 type Target = [u8];
3577 fn deref(&self) -> &[u8] {
3578 &self.buf
3579 }
3580}
3581
3582impl<'a> std::io::Write for RowArenaBuf<'a> {
3583 fn write(&mut self, bytes: &[u8]) -> std::io::Result<usize> {
3584 self.buf.extend_from_slice(bytes);
3585 Ok(bytes.len())
3586 }
3587
3588 fn flush(&mut self) -> std::io::Result<()> {
3589 Ok(())
3590 }
3591}
3592
3593impl<'a> std::fmt::Write for RowArenaBuf<'a> {
3594 fn write_str(&mut self, s: &str) -> std::fmt::Result {
3595 self.buf.extend_from_slice(s.as_bytes());
3596 Ok(())
3597 }
3598}
3599
3600#[derive(Debug)]
3618pub struct SharedRow(Row);
3619
3620impl SharedRow {
3621 thread_local! {
3622 static SHARED_ROW: Cell<Option<Row>> = const { Cell::new(Some(Row::empty())) }
3627 }
3628
3629 pub fn get() -> Self {
3637 let mut row = Self::SHARED_ROW
3638 .take()
3639 .expect("attempted to borrow already borrowed SharedRow");
3640 row.packer();
3642 Self(row)
3643 }
3644
3645 pub fn pack<'a, I, D>(iter: I) -> Row
3647 where
3648 I: IntoIterator<Item = D>,
3649 D: Borrow<Datum<'a>>,
3650 {
3651 let mut row_builder = Self::get();
3652 let mut row_packer = row_builder.packer();
3653 row_packer.extend(iter);
3654 row_builder.clone()
3655 }
3656}
3657
3658impl std::ops::Deref for SharedRow {
3659 type Target = Row;
3660
3661 fn deref(&self) -> &Self::Target {
3662 &self.0
3663 }
3664}
3665
3666impl std::ops::DerefMut for SharedRow {
3667 fn deref_mut(&mut self) -> &mut Self::Target {
3668 &mut self.0
3669 }
3670}
3671
3672impl Drop for SharedRow {
3673 fn drop(&mut self) {
3674 Self::SHARED_ROW.set(Some(std::mem::take(&mut self.0)))
3677 }
3678}
3679
3680#[cfg(test)]
3681mod tests {
3682 use std::cmp::Ordering;
3683 use std::collections::hash_map::DefaultHasher;
3684 use std::hash::{Hash, Hasher};
3685
3686 use chrono::{DateTime, NaiveDate};
3687 use itertools::Itertools;
3688 use mz_ore::{assert_err, assert_none};
3689 use ordered_float::OrderedFloat;
3690
3691 use crate::SqlScalarType;
3692
3693 use super::*;
3694
3695 proptest! {
3702 #![proptest_config(ProptestConfig::with_cases(1000))]
3703
3704 #[mz_ore::test]
3705 #[cfg_attr(miri, ignore)] fn stable_row_serde_roundtrip(
3707 stable in crate::relation::arb_relation_desc(1..8)
3708 .prop_flat_map(|desc| crate::relation::arb_row_for_relation(&desc))
3709 .prop_map(StableRow)
3710 ) {
3711 let json = serde_json::to_string(&stable).expect("serializes to JSON");
3712 let from_json: StableRow =
3713 serde_json::from_str(&json).expect("deserializes from JSON");
3714 prop_assert_eq!(&stable, &from_json);
3715
3716 let bytes = bincode::serialize(&stable).expect("serializes to bincode");
3717 let from_bincode: StableRow =
3718 bincode::deserialize(&bytes).expect("deserializes from bincode");
3719 prop_assert_eq!(&stable, &from_bincode);
3720 }
3721 }
3722
3723 fn varint_edge_cases() -> Vec<Datum<'static>> {
3726 let mut datums = vec![
3727 Datum::Int16(0),
3728 Datum::Int16(-1),
3729 Datum::Int16(i16::MIN),
3730 Datum::Int16(i16::MAX),
3731 Datum::Int32(0),
3732 Datum::Int32(-1),
3733 Datum::Int32(i32::MIN),
3734 Datum::Int32(i32::MAX),
3735 Datum::Int64(0),
3736 Datum::Int64(-1),
3737 Datum::Int64(i64::MIN),
3738 Datum::Int64(i64::MAX),
3739 Datum::UInt8(0),
3740 Datum::UInt8(u8::MAX),
3741 Datum::UInt16(0),
3742 Datum::UInt16(u16::MAX),
3743 Datum::UInt32(0),
3744 Datum::UInt32(u32::MAX),
3745 Datum::UInt64(0),
3746 Datum::UInt64(u64::MAX),
3747 ];
3748 for bits in 1..64 {
3750 let boundary = 1u64 << bits;
3751 for delta in [-1i64, 0, 1] {
3752 let Some(v) = boundary.checked_add_signed(delta) else {
3753 continue;
3754 };
3755 datums.push(Datum::UInt64(v));
3756 if let Ok(v) = u32::try_from(v) {
3757 datums.push(Datum::UInt32(v));
3758 }
3759 if let Ok(v) = u16::try_from(v) {
3760 datums.push(Datum::UInt16(v));
3761 }
3762 if let Ok(v) = u8::try_from(v) {
3763 datums.push(Datum::UInt8(v));
3764 }
3765 let Ok(v) = i64::try_from(v) else {
3766 continue;
3767 };
3768 datums.push(Datum::Int64(v));
3769 datums.push(Datum::Int64(-v));
3770 if let Ok(v) = i32::try_from(v) {
3771 datums.push(Datum::Int32(v));
3772 datums.push(Datum::Int32(-v));
3773 }
3774 if let Ok(v) = i16::try_from(v) {
3775 datums.push(Datum::Int16(v));
3776 datums.push(Datum::Int16(-v));
3777 }
3778 }
3779 }
3780 datums
3781 }
3782
3783 #[mz_ore::test]
3788 fn varint_tags_land_in_their_family() {
3789 for datum in varint_edge_cases() {
3790 let row = Row::pack_slice(&[datum]);
3791 let tag = Tag::try_from_primitive(row.data[0]).expect("valid tag");
3792 let (first, len, negative, widest) = match datum {
3793 Datum::Int16(i) => (Tag::NonNegativeInt16_0, min_bytes_signed(i), i < 0, 2),
3794 Datum::Int32(i) => (Tag::NonNegativeInt32_0, min_bytes_signed(i), i < 0, 4),
3795 Datum::Int64(i) => (Tag::NonNegativeInt64_0, min_bytes_signed(i), i < 0, 8),
3796 Datum::UInt8(u) => (Tag::UInt8_0, min_bytes_unsigned(u), false, 1),
3797 Datum::UInt16(u) => (Tag::UInt16_0, min_bytes_unsigned(u), false, 2),
3798 Datum::UInt32(u) => (Tag::UInt32_0, min_bytes_unsigned(u), false, 4),
3799 Datum::UInt64(u) => (Tag::UInt64_0, min_bytes_unsigned(u), false, 8),
3800 other => panic!("not a variable-length integer: {other:?}"),
3801 };
3802 let delta = u8::from(tag) - u8::from(first);
3803 let signed = matches!(datum, Datum::Int16(_) | Datum::Int32(_) | Datum::Int64(_));
3804 if signed {
3805 assert_eq!(delta >> 1, len, "wrong payload width in tag for {datum:?}");
3808 let sign_bit = if len == widest { 0 } else { u8::from(negative) };
3809 assert_eq!(delta & 1, sign_bit, "wrong sign in tag for {datum:?}");
3810 } else {
3811 assert_eq!(delta, len, "wrong payload width in tag for {datum:?}");
3812 }
3813 assert_eq!(row.unpack_first(), datum, "did not round-trip: {datum:?}");
3814 }
3815 }
3816
3817 #[mz_ore::test]
3820 fn varint_at_end_of_row_reads_exact_width() {
3821 for datum in varint_edge_cases() {
3822 for prefix in [None, Some(Datum::String("0123456789abcdef"))] {
3824 let row = match prefix {
3825 Some(p) => Row::pack_slice(&[p, datum]),
3826 None => Row::pack_slice(&[datum]),
3827 };
3828 assert_eq!(
3829 row.iter().last(),
3830 Some(datum),
3831 "did not round-trip at end of row: {datum:?}"
3832 );
3833 }
3834 let mut row = Row::default();
3836 let mut packer = row.packer();
3837 packer.push_list_with(|packer| packer.push(datum));
3838 packer.push(Datum::Int64(1));
3839 let list = match row.unpack_first() {
3840 Datum::List(list) => list,
3841 other => panic!("expected a list, got {other:?}"),
3842 };
3843 assert_eq!(list.iter().next(), Some(datum), "did not round-trip nested");
3844 }
3845 }
3846
3847 #[mz_ore::test]
3850 #[cfg_attr(miri, ignore)] fn cmp_deep_nested_list_does_not_overflow() {
3852 fn deep() -> Row {
3853 let mut row = Row::pack_slice(&[Datum::Int64(1)]);
3855 for _ in 0..50_000 {
3856 let mut next = Row::default();
3857 next.packer().push_list([row.unpack_first()]);
3858 row = next;
3859 }
3860 row
3861 }
3862 let a = deep();
3863 let b = deep();
3864 assert_eq!(a.unpack_first().cmp(&b.unpack_first()), Ordering::Equal);
3865 }
3866
3867 fn hash<T: Hash>(t: &T) -> u64 {
3868 let mut hasher = DefaultHasher::new();
3869 t.hash(&mut hasher);
3870 hasher.finish()
3871 }
3872
3873 #[mz_ore::test]
3874 fn test_assumptions() {
3875 assert_eq!(size_of::<Tag>(), 1);
3876 #[cfg(target_endian = "big")]
3877 {
3878 assert!(false);
3880 }
3881 }
3882
3883 #[mz_ore::test]
3884 fn miri_test_arena() {
3885 let arena = RowArena::new();
3886
3887 assert_eq!(arena.push_string("".to_owned()), "");
3888 assert_eq!(arena.push_string("العَرَبِيَّة".to_owned()), "العَرَبِيَّة");
3889
3890 let empty: &[u8] = &[];
3891 assert_eq!(arena.push_bytes(vec![]), empty);
3892 assert_eq!(arena.push_bytes(vec![0, 2, 1, 255]), &[0, 2, 1, 255]);
3893
3894 let mut row = Row::default();
3895 let mut packer = row.packer();
3896 packer.push_dict_with(|row| {
3897 row.push(Datum::String("a"));
3898 row.push_list_with(|row| {
3899 row.push(Datum::String("one"));
3900 row.push(Datum::String("two"));
3901 row.push(Datum::String("three"));
3902 });
3903 row.push(Datum::String("b"));
3904 row.push(Datum::String("c"));
3905 });
3906 assert_eq!(arena.push_unary_row(row.clone()), row.unpack_first());
3907 }
3908
3909 #[mz_ore::test]
3910 fn miri_test_arena_growth_keeps_references() {
3911 let arena = RowArena::new();
3914 let chunks: Vec<Vec<u8>> = (0..128u16)
3915 .map(|i| vec![u8::try_from(i % 256).unwrap(); usize::from(i % 13) + 1])
3916 .collect();
3917 let refs: Vec<&[u8]> = chunks
3918 .iter()
3919 .map(|c| arena.push_bytes(c.as_slice()))
3920 .collect();
3921 for (i, r) in refs.iter().enumerate() {
3922 assert_eq!(*r, chunks[i].as_slice());
3923 }
3924 }
3925
3926 #[mz_ore::test]
3927 fn miri_test_arena_unary_row_at_offset() {
3928 let arena = RowArena::new();
3931 arena.reserve(4096);
3932 let _pad = arena.push_bytes(vec![0xAB; 5]);
3933 let row = Row::pack_slice(&[Datum::String("hello"), Datum::Int64(42), Datum::True]);
3934 assert_eq!(arena.push_unary_row(row.clone()), row.unpack_first());
3935 }
3936
3937 #[mz_ore::test]
3938 fn miri_test_arena_clear_reuse() {
3939 let mut arena = RowArena::new();
3941 for i in 0..100u8 {
3942 let _ = arena.push_bytes(vec![i; 16]);
3943 }
3944 arena.clear();
3945 assert_eq!(arena.push_bytes(vec![7u8; 8]), &[7u8; 8]);
3946 assert_eq!(arena.push_string("after clear".to_owned()), "after clear");
3947 arena.clear();
3948 let empty: &[u8] = &[];
3949 assert_eq!(arena.push_bytes(Vec::<u8>::new()), empty);
3950 }
3951
3952 #[mz_ore::test]
3953 fn miri_test_arena_adopts_owned_bytes_and_keeps_references() {
3954 let arena = RowArena::new();
3958 let before = arena.push_bytes(vec![1u8; 8]);
3959 let adopted = arena.push_owned_bytes(vec![2u8; 64 * 1024]);
3960 let after = arena.push_bytes(vec![3u8; 8]);
3961 let small = arena.push_owned_bytes(vec![4u8; 4]);
3963
3964 assert_eq!(before, &[1u8; 8]);
3965 assert_eq!(adopted, &vec![2u8; 64 * 1024][..]);
3966 assert_eq!(after, &[3u8; 8]);
3967 assert_eq!(small, &[4u8; 4]);
3968
3969 let empty: &[u8] = &[];
3970 assert_eq!(arena.push_owned_bytes(vec![]), empty);
3971 }
3972
3973 #[mz_ore::test]
3974 fn test_arena_owned_pushes_keep_bump_allocating() {
3975 const VALUES: usize = 500;
3984 const VALUE: &str = "0123456789";
3985
3986 let regions = |arena: &RowArena| arena.inner.borrow().len();
3987 let push_all = |arena: &RowArena, owned: bool| {
3988 for _ in 0..VALUES {
3989 match owned {
3990 true => _ = arena.push_string(VALUE.to_string()),
3991 false => _ = arena.push_bytes(VALUE.as_bytes()),
3992 }
3993 }
3994 };
3995
3996 let copied = RowArena::new();
3998 push_all(&copied, false);
3999
4000 let owned = RowArena::new();
4001 push_all(&owned, true);
4002
4003 let seeded = RowArena::new();
4006 let _ = seeded.push_bytes(VALUE.as_bytes());
4007 push_all(&seeded, true);
4008
4009 let (copied, owned, seeded) = (regions(&copied), regions(&owned), regions(&seeded));
4013 assert!(
4014 owned <= copied * 2 && seeded <= copied * 2,
4015 "{VALUES} owned pushes left {owned} regions on an empty arena and {seeded} on a seeded \
4016 one, against {copied} for the same bytes copied",
4017 );
4018 }
4019
4020 #[mz_ore::test]
4021 fn miri_test_arena_budget() {
4022 let arena = RowArena::new();
4024 let _ = arena.push_bytes(vec![0u8; 1024]);
4025 assert!(!arena.over_budget());
4026 assert_eq!(arena.budget_remaining(), usize::MAX);
4027
4028 let arena = RowArena::with_budget(100);
4029 assert!(!arena.over_budget());
4030 assert_eq!(arena.budget_remaining(), 100);
4031
4032 let _ = arena.push_bytes(vec![0u8; 60]);
4035 assert!(!arena.over_budget());
4036 assert_eq!(arena.budget_remaining(), 40);
4037 assert_eq!(arena.allocated_bytes(), 60);
4038
4039 let pushed = arena.push_bytes(vec![7u8; 80]);
4042 assert_eq!(pushed, &[7u8; 80]);
4043 assert!(arena.over_budget());
4044 assert_eq!(arena.budget_remaining(), 0);
4045
4046 let mut arena = RowArena::with_budget(100);
4049 let _ = arena.push_owned_bytes(vec![0u8; 8 * 1024]);
4050 assert!(arena.over_budget());
4051
4052 arena.clear();
4053 assert!(!arena.over_budget());
4054 assert_eq!(arena.allocated_bytes(), 0);
4055 }
4056
4057 #[mz_ore::test]
4058 fn miri_test_arena_writer() {
4059 use std::io::Write;
4060
4061 let arena = RowArena::new();
4062
4063 let mut w = arena.writer();
4065 let mut expected = Vec::new();
4066 for i in 0..1000u16 {
4067 let byte = u8::try_from(i % 256).unwrap();
4068 w.push(byte);
4069 expected.push(byte);
4070 w.extend_from_slice(&[byte, byte]);
4071 expected.extend_from_slice(&[byte, byte]);
4072 }
4073 assert_eq!(w.as_slice(), expected.as_slice());
4074 assert_eq!(w.len(), expected.len());
4075 let first = w.finish();
4076 assert_eq!(first, expected.as_slice());
4077
4078 let mut w2 = arena.writer();
4081 write!(w2, "hello").unwrap();
4082 let second = w2.finish();
4083 assert_eq!(second, b"hello");
4084 assert_eq!(first, expected.as_slice());
4085
4086 let empty: &[u8] = &[];
4088 assert_eq!(arena.writer().finish(), empty);
4089
4090 {
4092 let mut w3 = arena.writer();
4093 w3.extend_from_slice(b"discarded");
4094 }
4095 assert_eq!(arena.writer().as_slice(), empty);
4096 }
4097
4098 #[mz_ore::test]
4099 fn miri_test_arena_writer_nested() {
4100 let arena = RowArena::new();
4104
4105 let mut outer = arena.writer();
4106 outer.extend_from_slice(b"outer-before-");
4107
4108 let inner_bytes = {
4110 let mut inner = arena.writer();
4111 inner.extend_from_slice(b"inner");
4112 assert_eq!(outer.as_slice(), b"outer-before-");
4114 inner.finish()
4115 };
4116 assert_eq!(inner_bytes, b"inner");
4117
4118 outer.extend_from_slice(b"after");
4120 let outer_bytes = outer.finish();
4121 assert_eq!(outer_bytes, b"outer-before-after");
4122 assert_eq!(inner_bytes, b"inner");
4124
4125 let mut again = arena.writer();
4127 again.extend_from_slice(b"reused");
4128 assert_eq!(again.finish(), b"reused");
4129 }
4130
4131 #[mz_ore::test]
4132 fn miri_test_arena_writer_fmt() {
4133 use std::fmt::Write;
4134
4135 let arena = RowArena::new();
4137 let mut w = arena.writer();
4138 for i in 0..5 {
4139 write!(w, "{i},").unwrap();
4140 }
4141 assert_eq!(w.finish_str(), "0,1,2,3,4,");
4142 }
4143
4144 #[mz_ore::test]
4145 fn miri_test_round_trip() {
4146 fn round_trip(datums: Vec<Datum>) {
4147 let row = Row::pack(datums.clone());
4148
4149 println!("{:?}", row.data());
4152
4153 let datums2 = row.iter().collect::<Vec<_>>();
4154 let datums3 = row.unpack();
4155 assert_eq!(datums, datums2);
4156 assert_eq!(datums, datums3);
4157 }
4158
4159 round_trip(vec![]);
4160 round_trip(
4161 SqlScalarType::enumerate()
4162 .iter()
4163 .flat_map(|r#type| r#type.interesting_datums())
4164 .collect(),
4165 );
4166 round_trip(vec![
4167 Datum::Null,
4168 Datum::Null,
4169 Datum::False,
4170 Datum::True,
4171 Datum::Int16(-21),
4172 Datum::Int32(-42),
4173 Datum::Int64(-2_147_483_648 - 42),
4174 Datum::UInt8(0),
4175 Datum::UInt8(1),
4176 Datum::UInt16(0),
4177 Datum::UInt16(1),
4178 Datum::UInt16(1 << 8),
4179 Datum::UInt32(0),
4180 Datum::UInt32(1),
4181 Datum::UInt32(1 << 8),
4182 Datum::UInt32(1 << 16),
4183 Datum::UInt32(1 << 24),
4184 Datum::UInt64(0),
4185 Datum::UInt64(1),
4186 Datum::UInt64(1 << 8),
4187 Datum::UInt64(1 << 16),
4188 Datum::UInt64(1 << 24),
4189 Datum::UInt64(1 << 32),
4190 Datum::UInt64(1 << 40),
4191 Datum::UInt64(1 << 48),
4192 Datum::UInt64(1 << 56),
4193 Datum::Float32(OrderedFloat::from(-42.12)),
4194 Datum::Float64(OrderedFloat::from(-2_147_483_648.0 - 42.12)),
4195 Datum::Date(Date::from_pg_epoch(365 * 45 + 21).unwrap()),
4196 Datum::Timestamp(
4197 CheckedTimestamp::from_timestamplike(
4198 NaiveDate::from_isoywd_opt(2019, 30, chrono::Weekday::Wed)
4199 .unwrap()
4200 .and_hms_opt(14, 32, 11)
4201 .unwrap(),
4202 )
4203 .unwrap(),
4204 ),
4205 Datum::TimestampTz(
4206 CheckedTimestamp::from_timestamplike(DateTime::from_timestamp(61, 0).unwrap())
4207 .unwrap(),
4208 ),
4209 Datum::Interval(Interval {
4210 months: 312,
4211 ..Default::default()
4212 }),
4213 Datum::Interval(Interval::new(0, 0, 1_012_312)),
4214 Datum::Bytes(&[]),
4215 Datum::Bytes(&[0, 2, 1, 255]),
4216 Datum::String(""),
4217 Datum::String("العَرَبِيَّة"),
4218 ]);
4219 }
4220
4221 #[mz_ore::test]
4222 fn test_array() {
4223 const DIM: ArrayDimension = ArrayDimension {
4226 lower_bound: 2,
4227 length: 2,
4228 };
4229 let mut row = Row::default();
4230 let mut packer = row.packer();
4231 packer
4232 .try_push_array(&[DIM], vec![Datum::Int32(1), Datum::Int32(2)])
4233 .unwrap();
4234 let arr1 = row.unpack_first().unwrap_array();
4235 assert_eq!(arr1.dims().into_iter().collect::<Vec<_>>(), vec![DIM]);
4236 assert_eq!(
4237 arr1.elements().into_iter().collect::<Vec<_>>(),
4238 vec![Datum::Int32(1), Datum::Int32(2)]
4239 );
4240
4241 let row = Row::pack_slice(&[Datum::Array(arr1)]);
4244 let arr2 = row.unpack_first().unwrap_array();
4245 assert_eq!(arr1, arr2);
4246 }
4247
4248 #[mz_ore::test]
4249 fn test_multidimensional_array() {
4250 let datums = vec![
4251 Datum::Int32(1),
4252 Datum::Int32(2),
4253 Datum::Int32(3),
4254 Datum::Int32(4),
4255 Datum::Int32(5),
4256 Datum::Int32(6),
4257 Datum::Int32(7),
4258 Datum::Int32(8),
4259 ];
4260
4261 let mut row = Row::default();
4262 let mut packer = row.packer();
4263 packer
4264 .try_push_array(
4265 &[
4266 ArrayDimension {
4267 lower_bound: 1,
4268 length: 1,
4269 },
4270 ArrayDimension {
4271 lower_bound: 1,
4272 length: 4,
4273 },
4274 ArrayDimension {
4275 lower_bound: 1,
4276 length: 2,
4277 },
4278 ],
4279 &datums,
4280 )
4281 .unwrap();
4282 let array = row.unpack_first().unwrap_array();
4283 assert_eq!(array.elements().into_iter().collect::<Vec<_>>(), datums);
4284 }
4285
4286 #[mz_ore::test]
4287 fn test_array_max_dimensions() {
4288 let mut row = Row::default();
4289 let max_dims = usize::from(MAX_ARRAY_DIMENSIONS);
4290
4291 let res = row.packer().try_push_array(
4293 &vec![
4294 ArrayDimension {
4295 lower_bound: 1,
4296 length: 1
4297 };
4298 max_dims + 1
4299 ],
4300 vec![Datum::Int32(4)],
4301 );
4302 assert_eq!(res, Err(InvalidArrayError::TooManyDimensions(max_dims + 1)));
4303 assert!(row.data.is_empty());
4304
4305 row.packer()
4308 .try_push_array(
4309 &vec![
4310 ArrayDimension {
4311 lower_bound: 1,
4312 length: 1
4313 };
4314 max_dims
4315 ],
4316 vec![Datum::Int32(4)],
4317 )
4318 .unwrap();
4319 }
4320
4321 #[mz_ore::test]
4322 fn test_array_wrong_cardinality() {
4323 let mut row = Row::default();
4324 let res = row.packer().try_push_array(
4325 &[
4326 ArrayDimension {
4327 lower_bound: 1,
4328 length: 2,
4329 },
4330 ArrayDimension {
4331 lower_bound: 1,
4332 length: 3,
4333 },
4334 ],
4335 vec![Datum::Int32(1), Datum::Int32(2)],
4336 );
4337 assert_eq!(
4338 res,
4339 Err(InvalidArrayError::WrongCardinality {
4340 actual: 2,
4341 expected: 6,
4342 })
4343 );
4344 assert!(row.data.is_empty());
4345 }
4346
4347 #[mz_ore::test]
4348 fn test_array_cardinality_overflow() {
4349 let mut row = Row::default();
4354 let res = row.packer().try_push_array(
4355 &[
4356 ArrayDimension {
4357 lower_bound: 1,
4358 length: usize::MAX,
4359 },
4360 ArrayDimension {
4361 lower_bound: 1,
4362 length: 2,
4363 },
4364 ],
4365 vec![Datum::Int32(1), Datum::Int32(2)],
4366 );
4367 assert_eq!(
4368 res,
4369 Err(InvalidArrayError::WrongCardinality {
4370 actual: 2,
4371 expected: usize::MAX,
4372 })
4373 );
4374 assert!(row.data.is_empty());
4375 }
4376
4377 #[mz_ore::test]
4378 fn test_nesting() {
4379 let mut row = Row::default();
4380 row.packer().push_dict_with(|row| {
4381 row.push(Datum::String("favourites"));
4382 row.push_list_with(|row| {
4383 row.push(Datum::String("ice cream"));
4384 row.push(Datum::String("oreos"));
4385 row.push(Datum::String("cheesecake"));
4386 });
4387 row.push(Datum::String("name"));
4388 row.push(Datum::String("bob"));
4389 });
4390
4391 let mut iter = row.unpack_first().unwrap_map().iter();
4392
4393 let (k, v) = iter.next().unwrap();
4394 assert_eq!(k, "favourites");
4395 assert_eq!(
4396 v.unwrap_list().iter().collect::<Vec<_>>(),
4397 vec![
4398 Datum::String("ice cream"),
4399 Datum::String("oreos"),
4400 Datum::String("cheesecake"),
4401 ]
4402 );
4403
4404 let (k, v) = iter.next().unwrap();
4405 assert_eq!(k, "name");
4406 assert_eq!(v, Datum::String("bob"));
4407 }
4408
4409 #[mz_ore::test]
4410 fn test_dict_errors() -> Result<(), Box<dyn std::error::Error>> {
4411 let pack = |ok| {
4412 let mut row = Row::default();
4413 row.packer().push_dict_with(|row| {
4414 if ok {
4415 row.push(Datum::String("key"));
4416 row.push(Datum::Int32(42));
4417 Ok(7)
4418 } else {
4419 Err("fail")
4420 }
4421 })?;
4422 Ok(row)
4423 };
4424
4425 assert_eq!(pack(false), Err("fail"));
4426
4427 let row = pack(true)?;
4428 let mut dict = row.unpack_first().unwrap_map().iter();
4429 assert_eq!(dict.next(), Some(("key", Datum::Int32(42))));
4430 assert_eq!(dict.next(), None);
4431
4432 Ok(())
4433 }
4434
4435 #[mz_ore::test]
4436 #[cfg_attr(miri, ignore)] fn test_datum_sizes() {
4438 let arena = RowArena::new();
4439
4440 let values_of_interest = vec![
4442 Datum::Null,
4443 Datum::False,
4444 Datum::Int16(0),
4445 Datum::Int32(0),
4446 Datum::Int64(0),
4447 Datum::UInt8(0),
4448 Datum::UInt8(1),
4449 Datum::UInt16(0),
4450 Datum::UInt16(1),
4451 Datum::UInt16(1 << 8),
4452 Datum::UInt32(0),
4453 Datum::UInt32(1),
4454 Datum::UInt32(1 << 8),
4455 Datum::UInt32(1 << 16),
4456 Datum::UInt32(1 << 24),
4457 Datum::UInt64(0),
4458 Datum::UInt64(1),
4459 Datum::UInt64(1 << 8),
4460 Datum::UInt64(1 << 16),
4461 Datum::UInt64(1 << 24),
4462 Datum::UInt64(1 << 32),
4463 Datum::UInt64(1 << 40),
4464 Datum::UInt64(1 << 48),
4465 Datum::UInt64(1 << 56),
4466 Datum::Float32(OrderedFloat(0.0)),
4467 Datum::Float64(OrderedFloat(0.0)),
4468 Datum::from(numeric::Numeric::from(0)),
4469 Datum::from(numeric::Numeric::from(1000)),
4470 Datum::from(numeric::Numeric::from(9999)),
4471 Datum::Date(
4472 NaiveDate::from_ymd_opt(1, 1, 1)
4473 .unwrap()
4474 .try_into()
4475 .unwrap(),
4476 ),
4477 Datum::Timestamp(
4478 CheckedTimestamp::from_timestamplike(
4479 DateTime::from_timestamp(0, 0).unwrap().naive_utc(),
4480 )
4481 .unwrap(),
4482 ),
4483 Datum::TimestampTz(
4484 CheckedTimestamp::from_timestamplike(DateTime::from_timestamp(0, 0).unwrap())
4485 .unwrap(),
4486 ),
4487 Datum::Interval(Interval::default()),
4488 Datum::Bytes(&[]),
4489 Datum::String(""),
4490 Datum::JsonNull,
4491 Datum::Range(Range { inner: None }),
4492 arena.make_datum(|packer| {
4493 packer
4494 .push_range(Range::new(Some((
4495 RangeLowerBound::new(Datum::Int32(-1), true),
4496 RangeUpperBound::new(Datum::Int32(1), true),
4497 ))))
4498 .unwrap();
4499 }),
4500 ];
4501 for value in values_of_interest {
4502 if datum_size(&value) != Row::pack_slice(&[value]).data.len() {
4503 panic!("Disparity in claimed size for {:?}", value);
4504 }
4505 }
4506 }
4507
4508 #[mz_ore::test]
4509 fn test_range_errors() {
4510 fn test_range_errors_inner<'a>(
4511 datums: Vec<Vec<Datum<'a>>>,
4512 ) -> Result<(), InvalidRangeError> {
4513 let mut row = Row::default();
4514 let row_len = row.byte_len();
4515 let mut packer = row.packer();
4516 let r = packer.push_range_with(
4517 RangeLowerBound {
4518 inclusive: true,
4519 bound: Some(|row: &mut RowPacker| {
4520 for d in &datums[0] {
4521 row.push(d);
4522 }
4523 Ok(())
4524 }),
4525 },
4526 RangeUpperBound {
4527 inclusive: true,
4528 bound: Some(|row: &mut RowPacker| {
4529 for d in &datums[1] {
4530 row.push(d);
4531 }
4532 Ok(())
4533 }),
4534 },
4535 );
4536
4537 assert_eq!(row_len, row.byte_len());
4538
4539 r
4540 }
4541
4542 for panicking_case in [
4547 vec![vec![Datum::Int32(1)], vec![]],
4548 vec![vec![Datum::Int32(1), Datum::Int32(2)], vec![]],
4549 ] {
4550 #[allow(clippy::disallowed_methods)] let result = std::panic::catch_unwind(|| test_range_errors_inner(panicking_case));
4552 assert_err!(result);
4553 }
4554
4555 for error_case in [
4559 vec![
4560 vec![Datum::Int32(1), Datum::Int32(2)],
4561 vec![Datum::Int32(3)],
4562 ],
4563 vec![
4564 vec![Datum::Int32(1)],
4565 vec![Datum::Int32(2), Datum::Int32(3)],
4566 ],
4567 vec![vec![Datum::Int32(1)], vec![Datum::UInt16(2)]],
4568 vec![vec![Datum::Null], vec![Datum::Int32(2)]],
4569 vec![vec![Datum::Int32(1)], vec![Datum::Null]],
4570 ] {
4571 assert_eq!(
4572 test_range_errors_inner(error_case),
4573 Err(InvalidRangeError::InvalidRangeData)
4574 );
4575 }
4576
4577 let e = test_range_errors_inner(vec![vec![Datum::Int32(2)], vec![Datum::Int32(1)]]);
4578 assert_eq!(e, Err(InvalidRangeError::MisorderedRangeBounds));
4579 }
4580
4581 #[mz_ore::test]
4583 #[cfg_attr(miri, ignore)] fn test_list_encoding() {
4585 fn test_list_encoding_inner(len: usize) {
4586 let list_elem = |i: usize| {
4587 if i % 2 == 0 {
4588 Datum::False
4589 } else {
4590 Datum::True
4591 }
4592 };
4593 let mut row = Row::default();
4594 {
4595 let mut packer = row.packer();
4597 packer.push(Datum::String("start"));
4598 packer.push_list_with(|packer| {
4599 for i in 0..len {
4600 packer.push(list_elem(i));
4601 }
4602 });
4603 packer.push(Datum::String("end"));
4604 }
4605 let mut row_it = row.iter();
4607 assert_eq!(row_it.next().unwrap(), Datum::String("start"));
4608 match row_it.next().unwrap() {
4609 Datum::List(list) => {
4610 let mut list_it = list.iter();
4611 for i in 0..len {
4612 assert_eq!(list_it.next().unwrap(), list_elem(i));
4613 }
4614 assert_none!(list_it.next());
4615 }
4616 _ => panic!("expected Datum::List"),
4617 }
4618 assert_eq!(row_it.next().unwrap(), Datum::String("end"));
4619 assert_none!(row_it.next());
4620 }
4621
4622 test_list_encoding_inner(0);
4623 test_list_encoding_inner(1);
4624 test_list_encoding_inner(10);
4625 test_list_encoding_inner(TINY - 1); test_list_encoding_inner(TINY + 1); test_list_encoding_inner(SHORT + 1); }
4632
4633 #[mz_ore::test]
4639 #[cfg_attr(miri, ignore)] fn test_datum_list_eq_ord_consistency() {
4641 let mut row_pos = Row::default();
4643 row_pos.packer().push_list_with(|p| {
4644 p.push(Datum::Float64(OrderedFloat::from(0.0)));
4645 });
4646 let list_pos = row_pos.unpack_first().unwrap_list();
4647
4648 let mut row_neg = Row::default();
4650 row_neg.packer().push_list_with(|p| {
4651 p.push(Datum::Float64(OrderedFloat::from(-0.0)));
4652 });
4653 let list_neg = row_neg.unpack_first().unwrap_list();
4654
4655 assert_eq!(
4658 list_pos, list_neg,
4659 "Eq should see different encodings as equal"
4660 );
4661
4662 assert_eq!(
4664 list_pos.cmp(&list_neg),
4665 Ordering::Equal,
4666 "Ord (datum-by-datum) should see -0.0 and +0.0 as equal"
4667 );
4668 }
4669
4670 #[mz_ore::test]
4673 fn test_datum_map_eq_bytewise_consistency() {
4674 let mut row_pos = Row::default();
4676 row_pos.packer().push_dict_with(|p| {
4677 p.push(Datum::String("k"));
4678 p.push(Datum::Float64(OrderedFloat::from(0.0)));
4679 });
4680 let map_pos = row_pos.unpack_first().unwrap_map();
4681
4682 let mut row_neg = Row::default();
4684 row_neg.packer().push_dict_with(|p| {
4685 p.push(Datum::String("k"));
4686 p.push(Datum::Float64(OrderedFloat::from(-0.0)));
4687 });
4688 let map_neg = row_neg.unpack_first().unwrap_map();
4689
4690 assert_eq!(
4692 map_pos, map_neg,
4693 "DatumMap Eq is semantic; -0.0 and +0.0 have different encodings but are equal"
4694 );
4695 let entries_pos: Vec<_> = map_pos.iter().collect();
4697 let entries_neg: Vec<_> = map_neg.iter().collect();
4698 assert_eq!(entries_pos.len(), entries_neg.len());
4699 for ((k1, v1), (k2, v2)) in entries_pos.iter().zip_eq(entries_neg.iter()) {
4700 assert_eq!(k1, k2);
4701 assert_eq!(
4702 v1, v2,
4703 "Datum-level comparison treats -0.0 and +0.0 as equal"
4704 );
4705 }
4706 }
4707
4708 #[mz_ore::test]
4710 fn test_datum_list_hash_consistency() {
4711 let mut row_pos = Row::default();
4713 row_pos.packer().push_list_with(|p| {
4714 p.push(Datum::Float64(OrderedFloat::from(0.0)));
4715 });
4716 let list_pos = row_pos.unpack_first().unwrap_list();
4717
4718 let mut row_neg = Row::default();
4719 row_neg.packer().push_list_with(|p| {
4720 p.push(Datum::Float64(OrderedFloat::from(-0.0)));
4721 });
4722 let list_neg = row_neg.unpack_first().unwrap_list();
4723
4724 assert_eq!(list_pos, list_neg);
4725 assert_eq!(
4726 hash(&list_pos),
4727 hash(&list_neg),
4728 "equal lists must have same hash"
4729 );
4730
4731 let mut row_a = Row::default();
4733 row_a.packer().push_list_with(|p| {
4734 p.push(Datum::Int32(1));
4735 p.push(Datum::Int32(2));
4736 });
4737 let list_a = row_a.unpack_first().unwrap_list();
4738
4739 let mut row_b = Row::default();
4740 row_b.packer().push_list_with(|p| {
4741 p.push(Datum::Int32(1));
4742 p.push(Datum::Int32(3));
4743 });
4744 let list_b = row_b.unpack_first().unwrap_list();
4745
4746 assert_ne!(list_a, list_b);
4747 assert_ne!(
4748 hash(&list_a),
4749 hash(&list_b),
4750 "unequal lists must have different hashes"
4751 );
4752 }
4753
4754 #[mz_ore::test]
4756 #[cfg_attr(miri, ignore)] fn test_datum_list_ordering() {
4758 let mut row_12 = Row::default();
4759 row_12.packer().push_list_with(|p| {
4760 p.push(Datum::Int32(1));
4761 p.push(Datum::Int32(2));
4762 });
4763 let list_12 = row_12.unpack_first().unwrap_list();
4764
4765 let mut row_13 = Row::default();
4766 row_13.packer().push_list_with(|p| {
4767 p.push(Datum::Int32(1));
4768 p.push(Datum::Int32(3));
4769 });
4770 let list_13 = row_13.unpack_first().unwrap_list();
4771
4772 let mut row_123 = Row::default();
4773 row_123.packer().push_list_with(|p| {
4774 p.push(Datum::Int32(1));
4775 p.push(Datum::Int32(2));
4776 p.push(Datum::Int32(3));
4777 });
4778 let list_123 = row_123.unpack_first().unwrap_list();
4779
4780 assert_eq!(list_12.cmp(&list_13), Ordering::Less);
4782 assert_eq!(list_13.cmp(&list_12), Ordering::Greater);
4783 assert_eq!(list_12.cmp(&list_12), Ordering::Equal);
4784 assert_eq!(list_12.cmp(&list_123), Ordering::Less);
4786 }
4787
4788 #[mz_ore::test]
4790 fn test_datum_map_hash_consistency() {
4791 let mut row_pos = Row::default();
4792 row_pos.packer().push_dict_with(|p| {
4793 p.push(Datum::String("x"));
4794 p.push(Datum::Float64(OrderedFloat::from(0.0)));
4795 });
4796 let map_pos = row_pos.unpack_first().unwrap_map();
4797
4798 let mut row_neg = Row::default();
4799 row_neg.packer().push_dict_with(|p| {
4800 p.push(Datum::String("x"));
4801 p.push(Datum::Float64(OrderedFloat::from(-0.0)));
4802 });
4803 let map_neg = row_neg.unpack_first().unwrap_map();
4804
4805 assert_eq!(map_pos, map_neg);
4806 assert_eq!(
4807 hash(&map_pos),
4808 hash(&map_neg),
4809 "equal maps must have same hash"
4810 );
4811
4812 let mut row_a = Row::default();
4813 row_a.packer().push_dict_with(|p| {
4814 p.push(Datum::String("a"));
4815 p.push(Datum::Int32(1));
4816 });
4817 let map_a = row_a.unpack_first().unwrap_map();
4818
4819 let mut row_b = Row::default();
4820 row_b.packer().push_dict_with(|p| {
4821 p.push(Datum::String("a"));
4822 p.push(Datum::Int32(2));
4823 });
4824 let map_b = row_b.unpack_first().unwrap_map();
4825
4826 assert_ne!(map_a, map_b);
4827 assert_ne!(
4828 hash(&map_a),
4829 hash(&map_b),
4830 "unequal maps must have different hashes"
4831 );
4832 }
4833
4834 #[mz_ore::test]
4836 #[cfg_attr(miri, ignore)] fn test_datum_map_ordering() {
4838 let mut row_a1 = Row::default();
4839 row_a1.packer().push_dict_with(|p| {
4840 p.push(Datum::String("a"));
4841 p.push(Datum::Int32(1));
4842 });
4843 let map_a1 = row_a1.unpack_first().unwrap_map();
4844
4845 let mut row_a2 = Row::default();
4846 row_a2.packer().push_dict_with(|p| {
4847 p.push(Datum::String("a"));
4848 p.push(Datum::Int32(2));
4849 });
4850 let map_a2 = row_a2.unpack_first().unwrap_map();
4851
4852 let mut row_b1 = Row::default();
4853 row_b1.packer().push_dict_with(|p| {
4854 p.push(Datum::String("b"));
4855 p.push(Datum::Int32(1));
4856 });
4857 let map_b1 = row_b1.unpack_first().unwrap_map();
4858
4859 assert_eq!(map_a1.cmp(&map_a2), Ordering::Less);
4860 assert_eq!(map_a2.cmp(&map_a1), Ordering::Greater);
4861 assert_eq!(map_a1.cmp(&map_a1), Ordering::Equal);
4862 assert_eq!(map_a1.cmp(&map_b1), Ordering::Less); }
4864
4865 #[mz_ore::test]
4868 #[cfg_attr(miri, ignore)] fn test_datum_list_and_map_null_sorts_last() {
4870 let mut row_list_1 = Row::default();
4872 row_list_1
4873 .packer()
4874 .push_list_with(|p| p.push(Datum::Int32(1)));
4875 let list_1 = row_list_1.unpack_first().unwrap_list();
4876
4877 let mut row_list_null = Row::default();
4878 row_list_null
4879 .packer()
4880 .push_list_with(|p| p.push(Datum::Null));
4881 let list_null = row_list_null.unpack_first().unwrap_list();
4882
4883 assert_eq!(list_1.cmp(&list_null), Ordering::Less);
4884 assert_eq!(list_null.cmp(&list_1), Ordering::Greater);
4885
4886 let mut row_map_1 = Row::default();
4888 row_map_1.packer().push_dict_with(|p| {
4889 p.push(Datum::String("k"));
4890 p.push(Datum::Int32(1));
4891 });
4892 let map_1 = row_map_1.unpack_first().unwrap_map();
4893
4894 let mut row_map_null = Row::default();
4895 row_map_null.packer().push_dict_with(|p| {
4896 p.push(Datum::String("k"));
4897 p.push(Datum::Null);
4898 });
4899 let map_null = row_map_null.unpack_first().unwrap_map();
4900
4901 assert_eq!(map_1.cmp(&map_null), Ordering::Less);
4902 assert_eq!(map_null.cmp(&map_1), Ordering::Greater);
4903 }
4904}