diff --git a/src/types/column/decimal.rs b/src/types/column/decimal.rs index b23486f..cab49c8 100644 --- a/src/types/column/decimal.rs +++ b/src/types/column/decimal.rs @@ -7,9 +7,11 @@ use crate::{ errors::Result, types::{ column::{ - column_data::BoxColumnData, column_data::ColumnData, list::List, - nullable::NullableColumnData, BoxColumnWrapper, ColumnFrom, ColumnWrapper, - VectorColumnData, + column_data::{BoxColumnData, ColumnData}, + list::List, + nullable::NullableColumnData, + util::extract_nulls_and_values, + BoxColumnWrapper, ColumnFrom, ColumnWrapper, VectorColumnData, }, decimal::{Decimal, NoBits}, from_sql::FromSql, @@ -263,17 +265,7 @@ impl ColumnData for NullableDecimalAdapter { } fn save(&self, encoder: &mut Encoder, start: usize, end: usize) { - let size = end - start; - let mut nulls = vec![0; size]; - let mut values: Vec> = vec![None; size]; - - for (i, index) in (start..end).enumerate() { - values[i] = Option::from_sql(self.at(index)).unwrap(); - if values[i].is_none() { - nulls[i] = 1; - } - } - + let (nulls, values) = extract_nulls_and_values::(self, start, end).unwrap(); encoder.write_bytes(nulls.as_ref()); for value in values { diff --git a/src/types/column/fixed_string.rs b/src/types/column/fixed_string.rs index 4c83fb7..024c433 100644 --- a/src/types/column/fixed_string.rs +++ b/src/types/column/fixed_string.rs @@ -5,8 +5,10 @@ use crate::{ binary::{Encoder, ReadEx}, errors::Result, types::{ - column::column_data::{BoxColumnData, LowCardinalityAccessor}, - from_sql::*, + column::{ + column_data::{BoxColumnData, LowCardinalityAccessor}, + util::extract_nulls_and_values, + }, value::get_str_buffer, Column, ColumnType, SqlType, Value, ValueRef, }, @@ -171,17 +173,7 @@ impl ColumnData for NullableFixedStringAdapter { } fn save(&self, encoder: &mut Encoder, start: usize, end: usize) { - let size = end - start; - let mut nulls = vec![0; size]; - let mut values: Vec> = vec![None; size]; - - for (i, index) in (start..end).enumerate() { - values[i] = Option::from_sql(self.at(index)).unwrap(); - if values[i].is_none() { - nulls[i] = 1; - } - } - + let (nulls, values) = extract_nulls_and_values::<&[u8], Self>(self, start, end).unwrap(); encoder.write_bytes(nulls.as_ref()); let mut buffer = Vec::with_capacity(self.str_len); diff --git a/src/types/column/mod.rs b/src/types/column/mod.rs index e252340..c08439f 100644 --- a/src/types/column/mod.rs +++ b/src/types/column/mod.rs @@ -52,6 +52,7 @@ mod numeric; mod simple_agg_func; mod string; mod string_pool; +mod util; /// Represents Clickhouse Column pub struct Column { diff --git a/src/types/column/util.rs b/src/types/column/util.rs new file mode 100644 index 0000000..7feae39 --- /dev/null +++ b/src/types/column/util.rs @@ -0,0 +1,28 @@ +use crate::{ + types::{column::ColumnData, FromSql}, + Result, +}; + +pub(crate) fn extract_nulls_and_values<'a, T, C>( + column_data: &'a C, + start: usize, + end: usize, +) -> Result<(Vec, Vec>)> +where + C: ColumnData, + T: FromSql<'a>, +{ + let size = end - start; + let mut nulls = vec![0_u8; size]; + let mut values: Vec> = Vec::with_capacity(size); + + for (i, index) in (start..end).enumerate() { + let value = Option::from_sql(column_data.at(index))?; + if value.is_none() { + nulls[i] = 1; + } + values.push(value); + } + + Ok((nulls, values)) +}