feat: Model are created
This commit is contained in:
parent
37c5c7235e
commit
49419cbc4c
@ -1,6 +1,6 @@
|
|||||||
use config::parse_local_config;
|
use config::parse_local_config;
|
||||||
use poise::serenity_prelude as serenity;
|
use poise::serenity_prelude as serenity;
|
||||||
use tracing::{error, info};
|
use tracing::{error, info, instrument};
|
||||||
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod dotenv;
|
pub mod dotenv;
|
||||||
@ -11,6 +11,7 @@ type Error = Box<dyn std::error::Error + Send + Sync>;
|
|||||||
type Context<'a> = poise::Context<'a, Data, Error>;
|
type Context<'a> = poise::Context<'a, Data, Error>;
|
||||||
|
|
||||||
/// Displays your or another user's account creation date
|
/// Displays your or another user's account creation date
|
||||||
|
#[instrument(skip(ctx), level = "info", fields(channel_id = ctx.channel_id().get() , guild_id = ?ctx.guild_id(), user_id = ?ctx.author().id.get(), user_name = ctx.author().name))]
|
||||||
#[poise::command(slash_command, prefix_command)]
|
#[poise::command(slash_command, prefix_command)]
|
||||||
async fn age(
|
async fn age(
|
||||||
ctx: Context<'_>,
|
ctx: Context<'_>,
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use std::{error::Error, sync::Arc};
|
use std::{error::Error, sync::Arc};
|
||||||
|
|
||||||
pub mod trivial;
|
pub mod trivial;
|
||||||
|
pub mod trivial_point;
|
||||||
|
pub mod trivial_question;
|
||||||
|
pub mod trivial_round;
|
||||||
|
|
||||||
use clickhouse_pool::{
|
use clickhouse_pool::{
|
||||||
config::{ClickhouseConfig, DatalakeConfig, RetryConfig},
|
config::{ClickhouseConfig, DatalakeConfig, RetryConfig},
|
||||||
@ -9,6 +12,9 @@ use clickhouse_pool::{
|
|||||||
};
|
};
|
||||||
use tracing::{error, info, instrument};
|
use tracing::{error, info, instrument};
|
||||||
use trivial::Trivial;
|
use trivial::Trivial;
|
||||||
|
use trivial_point::TrivialPoint;
|
||||||
|
use trivial_question::TrivialQuestion;
|
||||||
|
use trivial_round::TrivialRound;
|
||||||
|
|
||||||
use crate::config::PersistenceConfig;
|
use crate::config::PersistenceConfig;
|
||||||
|
|
||||||
@ -37,20 +43,51 @@ pub fn create_pool_manager(db_config: PersistenceConfig) -> Result<Arc<DatalakeC
|
|||||||
pub async fn create_manager_and_init(
|
pub async fn create_manager_and_init(
|
||||||
datalake_config: Arc<DatalakeConfig>,
|
datalake_config: Arc<DatalakeConfig>,
|
||||||
) -> Result<Arc<PoolManager>, Box<dyn Error>> {
|
) -> Result<Arc<PoolManager>, Box<dyn Error>> {
|
||||||
let manager = PoolManager::new(datalake_config, None).await;
|
let mut manager = PoolManager::new(datalake_config, None).await;
|
||||||
|
|
||||||
let _ = match manager
|
manager = match create_table::<Trivial>(manager).await {
|
||||||
.execute_with_retry(Trivial::create_table_sql())
|
Ok(manager) => manager,
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => {
|
|
||||||
info!("Table {} created successfully", Trivial::table_name());
|
|
||||||
}
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Failed to create table {} : {}", Trivial::table_name(), e);
|
return Err(e);
|
||||||
return Err(Box::new(e));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
manager = match create_table::<TrivialQuestion>(manager).await {
|
||||||
|
Ok(manager) => manager,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
manager = match create_table::<TrivialRound>(manager).await {
|
||||||
|
Ok(manager) => manager,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
manager = match create_table::<TrivialPoint>(manager).await {
|
||||||
|
Ok(manager) => manager,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("All tables created successfully");
|
||||||
|
|
||||||
Ok(Arc::new(manager))
|
Ok(Arc::new(manager))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(manager))]
|
||||||
|
pub async fn create_table<T: Model>(manager: PoolManager) -> Result<PoolManager, Box<dyn Error>> {
|
||||||
|
let _ = match manager.execute_with_retry(T::create_table_sql()).await {
|
||||||
|
Ok(_) => {
|
||||||
|
info!("Table {} created successfully", T::table_name());
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Failed to create table {} : {}", T::table_name(), e);
|
||||||
|
return Err(Box::new(e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(manager)
|
||||||
|
}
|
||||||
|
121
apps/bot/src/model/trivial_point.rs
Normal file
121
apps/bot/src/model/trivial_point.rs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
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<Utc>,
|
||||||
|
#[serde(with = "clickhouse::serde::chrono::datetime64::millis")]
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
|
||||||
|
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<String>) {
|
||||||
|
(
|
||||||
|
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<u64>,
|
||||||
|
offset: Option<u64>,
|
||||||
|
) -> 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
|
||||||
|
}
|
||||||
|
}
|
119
apps/bot/src/model/trivial_question.rs
Normal file
119
apps/bot/src/model/trivial_question.rs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use clickhouse::Row;
|
||||||
|
use clickhouse_pool::traits::Model;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug, Row, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub struct TrivialQuestion {
|
||||||
|
#[serde(with = "clickhouse::serde::uuid")]
|
||||||
|
pub id: Uuid,
|
||||||
|
#[serde(with = "clickhouse::serde::uuid")]
|
||||||
|
pub trivial_id: Uuid,
|
||||||
|
|
||||||
|
pub question: String,
|
||||||
|
pub answer: String,
|
||||||
|
|
||||||
|
#[serde(with = "clickhouse::serde::chrono::datetime64::millis")]
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
#[serde(with = "clickhouse::serde::chrono::datetime64::millis")]
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
|
||||||
|
pub creator_id: u64,
|
||||||
|
pub updater_id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Model for TrivialQuestion {
|
||||||
|
type T = TrivialQuestion;
|
||||||
|
|
||||||
|
fn table_name() -> &'static str {
|
||||||
|
"trivial_question"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_table_sql() -> &'static str {
|
||||||
|
r#"
|
||||||
|
CREATE TABLE IF NOT EXISTS trivial_question (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
trivial_id UUID,
|
||||||
|
question String,
|
||||||
|
answer String,
|
||||||
|
created_at DateTime64(3),
|
||||||
|
updated_at DateTime64(3),
|
||||||
|
creator_id UInt64,
|
||||||
|
updater_id UInt64
|
||||||
|
) ENGINE = MergeTree()
|
||||||
|
ORDER BY (id, trivial_id)
|
||||||
|
"#
|
||||||
|
.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn column_names() -> Vec<&'static str> {
|
||||||
|
vec![
|
||||||
|
"id",
|
||||||
|
"trivial_id",
|
||||||
|
"question",
|
||||||
|
"answer",
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
"creator_id",
|
||||||
|
"updater_id",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_row(&self) -> (Vec<&'static str>, Vec<String>) {
|
||||||
|
(
|
||||||
|
Self::column_names(),
|
||||||
|
vec![
|
||||||
|
self.id.to_string(),
|
||||||
|
self.trivial_id.to_string(),
|
||||||
|
self.question.clone(),
|
||||||
|
self.answer.clone(),
|
||||||
|
self.created_at.to_string(),
|
||||||
|
self.updated_at.to_string(),
|
||||||
|
self.creator_id.to_string(),
|
||||||
|
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!("({}, {})", columns, values));
|
||||||
|
}
|
||||||
|
queries.join(", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_select_query(
|
||||||
|
where_clause: Option<&str>,
|
||||||
|
limit: Option<u64>,
|
||||||
|
offset: Option<u64>,
|
||||||
|
) -> 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
|
||||||
|
}
|
||||||
|
}
|
116
apps/bot/src/model/trivial_round.rs
Normal file
116
apps/bot/src/model/trivial_round.rs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
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 TrivialRound {
|
||||||
|
#[serde(with = "clickhouse::serde::uuid")]
|
||||||
|
pub id: Uuid,
|
||||||
|
#[serde(with = "clickhouse::serde::uuid")]
|
||||||
|
pub trivial_id: Uuid,
|
||||||
|
#[serde(with = "clickhouse::serde::uuid")]
|
||||||
|
pub question_id: Uuid,
|
||||||
|
pub answer: Vec<(u64, String, DateTime<Utc>)>,
|
||||||
|
|
||||||
|
#[serde(with = "clickhouse::serde::chrono::datetime64::millis")]
|
||||||
|
pub created_at: DateTime<Utc>,
|
||||||
|
#[serde(with = "clickhouse::serde::chrono::datetime64::millis")]
|
||||||
|
pub updated_at: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Model for TrivialRound {
|
||||||
|
type T = TrivialRound;
|
||||||
|
|
||||||
|
fn table_name() -> &'static str {
|
||||||
|
"trivial_round"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_table_sql() -> &'static str {
|
||||||
|
r#"
|
||||||
|
CREATE TABLE IF NOT EXISTS trivial_round (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
trivial_id UUID,
|
||||||
|
question_id UUID,
|
||||||
|
answer Array(Tuple(UInt64, String, DateTime64(3))),
|
||||||
|
created_at DateTime64(3),
|
||||||
|
updated_at DateTime64(3)
|
||||||
|
) ENGINE = MergeTree()
|
||||||
|
ORDER BY (id, trivial_id)
|
||||||
|
"#
|
||||||
|
.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn column_names() -> Vec<&'static str> {
|
||||||
|
vec![
|
||||||
|
"id",
|
||||||
|
"trivial_id",
|
||||||
|
"question_id",
|
||||||
|
"answer",
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_row(&self) -> (Vec<&'static str>, Vec<String>) {
|
||||||
|
(
|
||||||
|
Self::column_names(),
|
||||||
|
vec![
|
||||||
|
self.id.to_string(),
|
||||||
|
self.trivial_id.to_string(),
|
||||||
|
self.question_id.to_string(),
|
||||||
|
format!("{:?}", self.answer),
|
||||||
|
self.created_at.to_string(),
|
||||||
|
self.updated_at.to_string(),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_query(&self) -> String {
|
||||||
|
let (columns, values) = self.to_row();
|
||||||
|
let columns_str = columns.join(", ");
|
||||||
|
let values_str = values.join(", ");
|
||||||
|
|
||||||
|
format!(
|
||||||
|
"INSERT INTO {} ({}) VALUES ({})",
|
||||||
|
Self::table_name(),
|
||||||
|
columns_str,
|
||||||
|
values_str
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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_str = columns.join(", ");
|
||||||
|
let values_str = values.join(", ");
|
||||||
|
queries.push(format!(
|
||||||
|
"INSERT INTO {} ({}) VALUES ({})",
|
||||||
|
Self::table_name(),
|
||||||
|
columns_str,
|
||||||
|
values_str
|
||||||
|
));
|
||||||
|
}
|
||||||
|
queries.join("; ")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_select_query(
|
||||||
|
where_clause: Option<&str>,
|
||||||
|
limit: Option<u64>,
|
||||||
|
offset: Option<u64>,
|
||||||
|
) -> 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
|
||||||
|
}
|
||||||
|
}
|
@ -35,7 +35,7 @@ services:
|
|||||||
SERVER_click: database
|
SERVER_click: database
|
||||||
USER_click: default
|
USER_click: default
|
||||||
PASSWORD_click: password
|
PASSWORD_click: password
|
||||||
PORT_click: 9000
|
PORT_click: 8123
|
||||||
ENGINE_click: clickhouse@dbgate-plugin-clickhouse
|
ENGINE_click: clickhouse@dbgate-plugin-clickhouse
|
||||||
DATABASE_click: default
|
DATABASE_click: default
|
||||||
depends_on:
|
depends_on:
|
||||||
|
Loading…
Reference in New Issue
Block a user