Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ quanta = { version = "0.12", optional = true }
replace_with = { version = "0.1.7" }
polonius-the-crab = "0.5.0"

bnum = "0.13.0"

[dev-dependencies]
clickhouse-macros = { version = "0.3.0", path = "macros" }
criterion = "0.6"
Expand Down
12 changes: 11 additions & 1 deletion examples/data_types_derive_simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use rand::{Rng, distr::Alphanumeric};
use std::str::FromStr;
use time::{Date, Month, OffsetDateTime, Time};

use clickhouse::types::{Int256, UInt256};
use clickhouse::{Client, error::Result, sql::Identifier};

// This example covers derivation of _simpler_ ClickHouse data types.
// See also: https://clickhouse.com/docs/en/sql-reference/data-types

Expand Down Expand Up @@ -131,6 +131,10 @@ pub struct MyRow {
pub decimal32_9_4: Decimal32,
pub decimal64_18_8: Decimal64,
pub decimal128_38_12: Decimal128,

pub int256: Int256,
pub uint256: UInt256,

#[serde(with = "clickhouse::serde::time::date")]
pub time_date: Date,
#[serde(with = "clickhouse::serde::time::date32")]
Expand Down Expand Up @@ -230,6 +234,12 @@ impl MyRow {
decimal64_18_8: Decimal64::from_str("9999999999.99999999").unwrap(),
decimal128_38_12: Decimal128::from_str("99999999999999999999999999.999999999999")
.unwrap(),

// `Int256` and `UInt256` are intended for input and output only,
// so they don't support `rand` directly.
int256: rng.random::<i128>().into(),
uint256: rng.random::<u128>().into(),

// Allowed values ranges:
// - Date = [1970-01-01, 2149-06-06]
// - Date32 = [1900-01-01, 2299-12-31]
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ pub mod sql;
#[cfg(feature = "test-util")]
pub mod test;

pub mod types;

mod bytes_ext;
mod compression;
mod cursors;
Expand Down
14 changes: 12 additions & 2 deletions src/rowbinary/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ use crate::error::{Error, Result};
use crate::row_metadata::RowMetadata;
use crate::rowbinary::utils::{ensure_size, get_unsigned_leb128};
use crate::rowbinary::validation::{DataTypeValidator, SchemaValidator, SerdeType};
use crate::types::int256;
use bytes::Buf;
use core::mem::size_of;
use serde::de::MapAccess;
use serde::de::value::BytesDeserializer;
use serde::{
Deserialize,
de::{DeserializeSeed, Deserializer, EnumAccess, SeqAccess, VariantAccess, Visitor},
Expand Down Expand Up @@ -296,10 +298,18 @@ where
#[inline(always)]
fn deserialize_newtype_struct<V: Visitor<'data>>(
self,
_name: &str,
name: &str,
visitor: V,
) -> Result<V::Value> {
visitor.visit_newtype_struct(self)
if name.starts_with(int256::MODULE_PATH) {
self.validator
.validate(SerdeType::Bytes(int256::BYTE_LEN))?;

let slice = self.read_slice(int256::BYTE_LEN)?;
BytesDeserializer::new(slice).deserialize_bytes(visitor)
} else {
visitor.visit_newtype_struct(self)
}
}

#[inline(always)]
Expand Down
203 changes: 201 additions & 2 deletions src/rowbinary/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::error::Error::SequenceMustHaveLength;
use crate::error::{Error, Result};
use crate::row_metadata::RowMetadata;
use crate::rowbinary::validation::{DataTypeValidator, SchemaValidator, SerdeType};
use crate::types::int256;
use bytes::BufMut;
use clickhouse_types::put_leb128;
use serde::ser::SerializeMap;
Expand Down Expand Up @@ -179,10 +180,19 @@ impl<'ser, B: BufMut, R: Row, V: SchemaValidator<R>> Serializer
#[inline]
fn serialize_newtype_struct<T: Serialize + ?Sized>(
self,
_name: &'static str,
name: &'static str,
value: &T,
) -> Result<()> {
value.serialize(self)
if name.starts_with(int256::MODULE_PATH) {
self.validator
.validate(SerdeType::Bytes(int256::BYTE_LEN))?;

value.serialize(WithoutLenPrefix {
buffer: &mut self.buffer,
})
} else {
value.serialize(self)
}
}

#[inline]
Expand Down Expand Up @@ -362,3 +372,192 @@ impl<'ser, B: BufMut, R: Row, V: SchemaValidator<R>> SerializeMap
Ok(())
}
}

struct WithoutLenPrefix<B> {
buffer: B,
}

impl<B: BufMut> Serializer for WithoutLenPrefix<B> {
type Ok = ();
type Error = Error;
type SerializeSeq = Impossible<Self::Ok, Self::Error>;
type SerializeTuple = Impossible<Self::Ok, Self::Error>;
type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
type SerializeMap = Impossible<Self::Ok, Self::Error>;
type SerializeStruct = Impossible<Self::Ok, Self::Error>;
type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;

fn is_human_readable(&self) -> bool {
false
}

fn serialize_bool(self, _v: bool) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_i8(self, _v: i8) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_i16(self, _v: i16) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_i32(self, _v: i32) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_i64(self, _v: i64) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_u8(self, _v: u8) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_u16(self, _v: u16) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_u32(self, _v: u32) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_u64(self, _v: u64) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_f32(self, _v: f32) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_f64(self, _v: f64) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_char(self, _v: char) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_str(self, _v: &str) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_bytes(mut self, v: &[u8]) -> std::result::Result<Self::Ok, Self::Error> {
self.buffer.put_slice(v);
Ok(())
}

fn serialize_none(self) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_some<T>(self, _value: &T) -> std::result::Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize,
{
unimplemented!()
}

fn serialize_unit(self) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_unit_struct(
self,
_name: &'static str,
) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
) -> std::result::Result<Self::Ok, Self::Error> {
unimplemented!()
}

fn serialize_newtype_struct<T>(
self,
_name: &'static str,
_value: &T,
) -> std::result::Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize,
{
unimplemented!()
}

fn serialize_newtype_variant<T>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> std::result::Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize,
{
unimplemented!()
}

fn serialize_seq(
self,
_len: Option<usize>,
) -> std::result::Result<Self::SerializeSeq, Self::Error> {
unimplemented!()
}

fn serialize_tuple(
self,
_len: usize,
) -> std::result::Result<Self::SerializeTuple, Self::Error> {
unimplemented!()
}

fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> std::result::Result<Self::SerializeTupleStruct, Self::Error> {
unimplemented!()
}

fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> std::result::Result<Self::SerializeTupleVariant, Self::Error> {
unimplemented!()
}

fn serialize_map(
self,
_len: Option<usize>,
) -> std::result::Result<Self::SerializeMap, Self::Error> {
unimplemented!()
}

fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> std::result::Result<Self::SerializeStruct, Self::Error> {
unimplemented!()
}

fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> std::result::Result<Self::SerializeStructVariant, Self::Error> {
unimplemented!()
}
}
7 changes: 7 additions & 0 deletions src/rowbinary/validation.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::error::{Error, Result};
use crate::types::int256;
use crate::{Row, row::RowKind, row_metadata::RowMetadata};
use clickhouse_types::data_types::{Column, DataTypeNode, DecimalType, EnumType};
use std::collections::HashMap;
Expand Down Expand Up @@ -530,6 +531,12 @@ fn validate_impl<'serde, 'caller, R: Row>(
SerdeType::Bytes(_) | SerdeType::ByteBuf(_) if data_type == &DataTypeNode::String => {
Ok(None)
}
// Serde's data model doesn't have `(u)int256` so instead we just try to deserialize `[u8; 32]`
SerdeType::Bytes(int256::BYTE_LEN)
if data_type == &DataTypeNode::Int256 || data_type == &DataTypeNode::UInt256 =>
{
Ok(None)
}
SerdeType::Option => {
if let DataTypeNode::Nullable(inner_type) = data_type {
Ok(Some(InnerDataTypeValidator {
Expand Down
Loading