pub struct Row {
data: SmallVec<[u8; 24]>,
}
Expand description
A packed representation for Datum
s.
Datum
is easy to work with but very space inefficient. A Datum::Int32(42)
is laid out in memory like this:
tag: 3 padding: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 data: 0 0 0 42 padding: 0 0 0 0 0 0 0 0 0 0 0 0
For a total of 32 bytes! The second set of padding is needed in case we were to write a 16-byte datum into this location. The first set of padding is needed to align that hypothetical decimal to a 16 bytes boundary.
A Row
stores zero or more Datum
s without any padding. We avoid the need
for the first set of padding by only providing access to the Datum
s via
calls to ptr::read_unaligned
, which on modern x86 is barely penalized. We
avoid the need for the second set of padding by not providing mutable access
to the Datum
. Instead, Row
is append-only.
A Row
can be built from a collection of Datum
s using Row::pack
, but it
is more efficient to use Row::pack_slice
so that a right-sized allocation
can be created. If that is not possible, consider using the row buffer
pattern: allocate one row, pack into it, and then call Row::clone
to
receive a copy of that row, leaving behind the original allocation to pack
future rows.
Creating a row via Row::pack_slice
:
let row = Row::pack_slice(&[Datum::Int32(0), Datum::Int32(1), Datum::Int32(2)]);
assert_eq!(row.unpack(), vec![Datum::Int32(0), Datum::Int32(1), Datum::Int32(2)])
Row
s can be unpacked by iterating over them:
let row = Row::pack_slice(&[Datum::Int32(0), Datum::Int32(1), Datum::Int32(2)]);
assert_eq!(row.iter().nth(1).unwrap(), Datum::Int32(1));
If you want random access to the Datum
s in a Row
, use Row::unpack
to create a Vec<Datum>
let row = Row::pack_slice(&[Datum::Int32(0), Datum::Int32(1), Datum::Int32(2)]);
let datums = row.unpack();
assert_eq!(datums[1], Datum::Int32(1));
Performance
Rows are dynamically sized, but up to a fixed size their data is stored in-line.
It is best to re-use a Row
across multiple Row
creation calls, as this
avoids the allocations involved in Row::new()
.
Fields§
§data: SmallVec<[u8; 24]>
Implementations§
source§impl Row
impl Row
sourcepub fn with_capacity(cap: usize) -> Self
pub fn with_capacity(cap: usize) -> Self
Allocate an empty Row
with a pre-allocated capacity.
sourcepub unsafe fn from_bytes_unchecked(data: Vec<u8>) -> Self
pub unsafe fn from_bytes_unchecked(data: Vec<u8>) -> Self
Creates a new row from supplied bytes.
Safety
This method relies on data
being an appropriate row encoding, and can
result in unsafety if this is not the case.
sourcepub fn packer(&mut self) -> RowPacker<'_>
pub fn packer(&mut self) -> RowPacker<'_>
Constructs a RowPacker
that will pack datums into this row’s
allocation.
This method clears the existing contents of the row, but retains the allocation.
sourcepub fn pack<'a, I, D>(iter: I) -> Rowwhere
I: IntoIterator<Item = D>,
D: Borrow<Datum<'a>>,
pub fn pack<'a, I, D>(iter: I) -> Rowwhere I: IntoIterator<Item = D>, D: Borrow<Datum<'a>>,
Take some Datum
s and pack them into a Row
.
This method builds a Row
by repeatedly increasing the backing
allocation. If the contents of the iterator are known ahead of
time, consider Row::with_capacity
to right-size the allocation
first, and then RowPacker::extend
to populate it with Datum
s.
This avoids the repeated allocation resizing and copying.
sourcepub fn try_pack<'a, I, D, E>(iter: I) -> Result<Row, E>where
I: IntoIterator<Item = Result<D, E>>,
D: Borrow<Datum<'a>>,
pub fn try_pack<'a, I, D, E>(iter: I) -> Result<Row, E>where I: IntoIterator<Item = Result<D, E>>, D: Borrow<Datum<'a>>,
Like Row::pack
, but the provided iterator is allowed to produce an
error, in which case the packing operation is aborted and the error
returned.
sourcepub fn pack_slice<'a>(slice: &[Datum<'a>]) -> Row
pub fn pack_slice<'a>(slice: &[Datum<'a>]) -> Row
Pack a slice of Datum
s into a Row
.
This method has the advantage over pack
that it can determine the required
allocation before packing the elements, ensuring only one allocation and no
redundant copies required.
Methods from Deref<Target = RowRef>§
Trait Implementations§
source§impl Arbitrary for Row
impl Arbitrary for Row
§type Parameters = SizeRange
type Parameters = SizeRange
arbitrary_with
accepts for configuration
of the generated Strategy
. Parameters must implement Default
.§type Strategy = BoxedStrategy<Row>
type Strategy = BoxedStrategy<Row>
Strategy
used to generate values of type Self
.source§fn arbitrary_with(size: Self::Parameters) -> Self::Strategy
fn arbitrary_with(size: Self::Parameters) -> Self::Strategy
source§impl Codec for Row
impl Codec for Row
source§fn encode<B>(&self, buf: &mut B)where
B: BufMut,
fn encode<B>(&self, buf: &mut B)where B: BufMut,
Encodes a row into the permanent storage format.
This perfectly round-trips through Row::decode. It’s guaranteed to be readable by future versions of Materialize through v(TODO: Figure out our policy).
source§fn decode(buf: &[u8]) -> Result<Row, String>
fn decode(buf: &[u8]) -> Result<Row, String>
Decodes a row from the permanent storage format.
This perfectly round-trips through Row::encode. It can read rows encoded by historical versions of Materialize back to v(TODO: Figure out our policy).
§type Schema = RelationDesc
type Schema = RelationDesc
source§fn codec_name() -> String
fn codec_name() -> String
source§impl Columnation for Row
impl Columnation for Row
§type InnerRegion = RowStack
type InnerRegion = RowStack
Self
type. Note: not allocations of Self
, but of the
things that it owns.source§impl<'de> Deserialize<'de> for Row
impl<'de> Deserialize<'de> for Row
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where __D: Deserializer<'de>,
source§impl Ord for Row
impl Ord for Row
source§impl<'a> PartDecoder<'a, Row> for RowDecoder<'a>
impl<'a> PartDecoder<'a, Row> for RowDecoder<'a>
source§impl<'a> PartEncoder<'a, Row> for RowEncoder<'a>
impl<'a> PartEncoder<'a, Row> for RowEncoder<'a>
source§impl PartialOrd<Row> for Row
impl PartialOrd<Row> for Row
These implementations order first by length, and then by slice contents. This allows many comparisons to complete without dereferencing memory. Warning: These order by the u8 array representation, and NOT by Datum::cmp.
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self
and other
) and is used by the <=
operator. Read moresource§impl RustType<ProtoRow> for Row
impl RustType<ProtoRow> for Row
source§fn into_proto(&self) -> ProtoRow
fn into_proto(&self) -> ProtoRow
Self
into a Proto
value.source§fn from_proto(proto: ProtoRow) -> Result<Self, TryFromProtoError>
fn from_proto(proto: ProtoRow) -> Result<Self, TryFromProtoError>
source§impl Schema<Row> for RelationDesc
impl Schema<Row> for RelationDesc
§type Encoder<'a> = RowEncoder<'a>
type Encoder<'a> = RowEncoder<'a>
§type Decoder<'a> = RowDecoder<'a>
type Decoder<'a> = RowDecoder<'a>
source§fn columns(&self) -> Vec<(String, DataType, StatsFn)>
fn columns(&self) -> Vec<(String, DataType, StatsFn)>
impl Eq for Row
impl StructuralEq for Row
impl StructuralPartialEq for Row
Auto Trait Implementations§
impl RefUnwindSafe for Row
impl Send for Row
impl Sync for Row
impl Unpin for Row
impl UnwindSafe for Row
Blanket Implementations§
source§impl<Q, K> Equivalent<K> for Qwhere
Q: Eq + ?Sized,
K: Borrow<Q> + ?Sized,
impl<Q, K> Equivalent<K> for Qwhere Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,
source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.source§impl<T> FutureExt for T
impl<T> FutureExt for T
source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T
in a tonic::Request
source§impl<P, R> ProtoType<R> for Pwhere
R: RustType<P>,
impl<P, R> ProtoType<R> for Pwhere R: RustType<P>,
source§fn into_rust(self) -> Result<R, TryFromProtoError>
fn into_rust(self) -> Result<R, TryFromProtoError>
RustType::from_proto
.source§fn from_rust(rust: &R) -> P
fn from_rust(rust: &R) -> P
RustType::into_proto
.