use std::fmt;
use uuid::Uuid;
use crate::Result;
use crate::io::ClickHouseWrite;
use crate::prelude::SettingValue;
use crate::settings::SETTING_FLAG_CUSTOM;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Qid(Uuid);
impl Default for Qid {
fn default() -> Self { Self::new() }
}
impl Qid {
pub fn new() -> Self { Self(Uuid::new_v4()) }
pub fn into_inner(self) -> Uuid { self.0 }
pub(crate) async fn write_id<W: ClickHouseWrite>(&self, writer: &mut W) -> Result<()> {
let mut buffer = [0u8; 32];
let hex = self.0.as_simple().encode_lower(&mut buffer);
writer.write_string(hex).await
}
#[cfg_attr(not(feature = "inner_pool"), expect(unused))]
pub(crate) fn key(self) -> usize {
self.into_inner().as_bytes().iter().copied().map(usize::from).sum::<usize>()
}
}
impl<T: Into<Qid>> From<Option<T>> for Qid {
fn from(value: Option<T>) -> Self {
match value {
Some(v) => v.into(),
None => Qid::default(),
}
}
}
impl From<Uuid> for Qid {
fn from(id: Uuid) -> Self { Self(id) }
}
impl fmt::Display for Qid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0.as_simple())
}
}
pub type ParamValue = SettingValue;
#[derive(Debug, Clone, Default, PartialEq)]
pub struct QueryParams(pub Vec<(String, ParamValue)>);
impl<T, K, S> From<T> for QueryParams
where
T: IntoIterator<Item = (K, S)>,
K: Into<String>,
ParamValue: From<S>,
{
fn from(value: T) -> Self {
Self(value.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
}
}
impl<K, S> FromIterator<(K, S)> for QueryParams
where
K: Into<String>,
ParamValue: From<S>,
{
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = (K, S)>,
{
iter.into_iter().collect()
}
}
impl QueryParams {
pub(crate) fn len(&self) -> usize { self.0.len() }
pub(crate) async fn encode<W: ClickHouseWrite>(
&self,
writer: &mut W,
_revision: u64,
) -> Result<()> {
for (key, value) in &self.0 {
writer.write_string(key).await?;
writer.write_var_uint(SETTING_FLAG_CUSTOM).await?;
let field_dump = encode_field_dump(value);
writer.write_string(&field_dump).await?;
}
Ok(())
}
}
fn encode_field_dump(value: &SettingValue) -> String {
match value {
SettingValue::String(s) => format!("'{}'", s.replace('\'', "\\'")),
SettingValue::Int(i) => format!("'{i}'"),
SettingValue::Float(f) => format!("'{f}'"),
SettingValue::Bool(b) => format!("'{b}'"),
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ParsedQuery(pub(crate) String);
impl std::ops::Deref for ParsedQuery {
type Target = String;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl fmt::Display for ParsedQuery {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) }
}
impl From<String> for ParsedQuery {
fn from(q: String) -> ParsedQuery { ParsedQuery(q.trim().to_string()) }
}
impl From<&str> for ParsedQuery {
fn from(q: &str) -> ParsedQuery { ParsedQuery(q.trim().to_string()) }
}
impl From<&String> for ParsedQuery {
fn from(q: &String) -> ParsedQuery { ParsedQuery(q.trim().to_string()) }
}