use chrono::{DateTime, Utc}; use clickhouse::Row; use clickhouse_pool::traits::Model; use serde::{Deserialize, Serialize}; use uuid::Uuid; #[derive(Debug, Clone, PartialEq, PartialOrd, Row, Serialize, Deserialize)] pub struct TrivialPoint { #[serde(with = "clickhouse::serde::uuid")] pub id: Uuid, #[serde(with = "clickhouse::serde::uuid")] pub trivial_id: Uuid, pub user_id: u64, pub points: i64, #[serde(with = "clickhouse::serde::chrono::datetime64::millis")] pub created_at: DateTime, #[serde(with = "clickhouse::serde::chrono::datetime64::millis")] pub updated_at: DateTime, pub updater_id: u64, } impl Model for TrivialPoint { type T = TrivialPoint; fn table_name() -> &'static str { "trivial_point" } fn create_table_sql() -> &'static str { r#" CREATE TABLE IF NOT EXISTS trivial_point ( id UUID PRIMARY KEY, trivial_id UUID, user_id UInt64, points Int64, created_at DateTime64(3), updated_at DateTime64(3), updater_id UInt64 ) ENGINE = MergeTree() ORDER BY (id, trivial_id) "# .trim() } fn column_names() -> Vec<&'static str> { vec![ "id", "trivial_id", "user_id", "points", "created_at", "updated_at", "updater_id", ] } fn to_row(&self) -> (Vec<&'static str>, Vec) { ( Self::column_names(), vec![ self.id.to_string(), self.trivial_id.to_string(), self.user_id.to_string(), self.points.to_string(), self.created_at.to_rfc3339(), self.updated_at.to_rfc3339(), self.updater_id.to_string(), ], ) } fn insert_query(&self) -> String { let (columns, values) = self.to_row(); let columns = columns.join(", "); let values = values.join(", "); format!( "INSERT INTO {} ({}) VALUES ({})", Self::table_name(), columns, values ) } fn batch_insert_query(items: &[Self::T]) -> String { let mut queries = Vec::new(); for item in items { let (columns, values) = item.to_row(); let columns = columns.join(", "); let values = values.join(", "); queries.push(format!( "INSERT INTO {} ({}) VALUES ({})", Self::table_name(), columns, values )); } queries.join("; ") } fn build_select_query( where_clause: Option<&str>, limit: Option, offset: Option, ) -> String { let mut query = format!("SELECT * FROM {}", Self::table_name()); if let Some(where_clause) = where_clause { query.push_str(&format!(" WHERE {}", where_clause)); } if let Some(limit) = limit { query.push_str(&format!(" LIMIT {}", limit)); } if let Some(offset) = offset { query.push_str(&format!(" OFFSET {}", offset)); } query } }