Skip to content

Commit

Permalink
SerializeRow: Add is_empty method
Browse files Browse the repository at this point in the history
Currently ongoing serialization refactor requires to only perform
queries with values using prepared statements. Session interface still
allows to pass values in query* methods, so we need a way to know if we
can perform unprepared query or not.

One way is to always perform prepared queries, but that is not optimal.
Before ongoing refactor we could serialize values and check if they are
empty. This will no longer be possible soon, because serializing will
require knowing column types, which in this case means having a prepared
statement.

This commit implements third way - additional method on SerializeRow
trait that allows us to check if values are empty (in which case we can
skip the prepare).
  • Loading branch information
Lorak-mmk committed Dec 6, 2023
1 parent bdcf349 commit eb10f3b
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
6 changes: 6 additions & 0 deletions scylla-cql/src/frame/value_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1000,11 +1000,14 @@ fn serialize_values<T: ValueList + SerializeRow>(
let mut writer = BufBackedRowWriter::new(&mut new_serialized);
<T as SerializeRow>::serialize(&vl, &ctx, &mut writer).unwrap();
let value_count: u16 = writer.value_count().try_into().unwrap();
let is_empty = writer.value_count() == 0;

// Prepend with value count, like `ValueList` does
new_serialized[0..2].copy_from_slice(&value_count.to_be_bytes());

assert_eq!(old_serialized, new_serialized);
assert_eq!(<T as SerializeRow>::is_empty(&vl), is_empty);
assert_eq!(serialized.is_empty(), is_empty);

serialized
}
Expand All @@ -1016,10 +1019,13 @@ fn serialize_values_only_new<T: SerializeRow>(vl: T, columns: &[ColumnSpec]) ->
let mut writer = BufBackedRowWriter::new(&mut serialized);
<T as SerializeRow>::serialize(&vl, &ctx, &mut writer).unwrap();
let value_count: u16 = writer.value_count().try_into().unwrap();
let is_empty = writer.value_count() == 0;

// Prepend with value count, like `ValueList` does
serialized[0..2].copy_from_slice(&value_count.to_be_bytes());

assert_eq!(<T as SerializeRow>::is_empty(&vl), is_empty);

serialized
}

Expand Down
39 changes: 39 additions & 0 deletions scylla-cql/src/types/serialize/row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ pub trait SerializeRow {
ctx: &RowSerializationContext<'_>,
writer: &mut W,
) -> Result<(), SerializationError>;

fn is_empty(&self) -> bool;
}

macro_rules! fallback_impl_contents {
Expand All @@ -69,6 +71,10 @@ macro_rules! fallback_impl_contents {
) -> Result<(), SerializationError> {
serialize_legacy_row(self, ctx, writer)
}
#[inline]
fn is_empty(&self) -> bool {
SerializedValues::is_empty(self)
}
};
}

Expand Down Expand Up @@ -96,6 +102,11 @@ macro_rules! impl_serialize_row_for_unit {
// Row is empty - do nothing
Ok(())
}

#[inline]
fn is_empty(&self) -> bool {
true
}
};
}

Expand Down Expand Up @@ -152,6 +163,11 @@ macro_rules! impl_serialize_row_for_slice {
}
Ok(())
}

#[inline]
fn is_empty(&self) -> bool {
<[T]>::is_empty(self.as_ref())
}
};
}

Expand Down Expand Up @@ -227,6 +243,11 @@ macro_rules! impl_serialize_row_for_map {

Ok(())
}

#[inline]
fn is_empty(&self) -> bool {
Self::is_empty(self)
}
};
}

Expand Down Expand Up @@ -258,6 +279,11 @@ impl<T: SerializeRow> SerializeRow for &T {
) -> Result<(), SerializationError> {
<T as SerializeRow>::serialize(self, ctx, writer)
}

#[inline]
fn is_empty(&self) -> bool {
<T as SerializeRow>::is_empty(self)
}
}

impl SerializeRow for SerializedValues {
Expand Down Expand Up @@ -325,6 +351,11 @@ macro_rules! impl_tuple {
)*
Ok(())
}

#[inline]
fn is_empty(&self) -> bool {
$length == 0
}
}
};
}
Expand Down Expand Up @@ -428,6 +459,14 @@ macro_rules! impl_serialize_row_via_value_list {
) -> ::std::result::Result<(), $crate::types::serialize::SerializationError> {
$crate::types::serialize::row::serialize_legacy_row(self, ctx, writer)
}

#[inline]
fn is_empty(&self) -> bool {
match $crate::frame::value::ValueList::serialized(self) {
Ok(s) => s.is_empty(),
Err(e) => false
}
}
}
};
}
Expand Down

0 comments on commit eb10f3b

Please sign in to comment.