From cc9979086fcc1ed314e85d9e3bd6715d8da176ad Mon Sep 17 00:00:00 2001 From: mykola2312 Date: Fri, 8 Mar 2024 07:01:12 +0200 Subject: [PATCH] begin migrating to postgres --- Cargo.lock | 1 + Cargo.toml | 2 +- migrations/1_init.sql | 82 ++++++++++++++++++++++++++----------------- src/bot.rs | 5 ++- src/bot/bot.rs | 2 +- src/db.rs | 24 +++++++++---- 6 files changed, 71 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 16e8eee..525448c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2018,6 +2018,7 @@ dependencies = [ "sha2", "sqlx-core", "sqlx-mysql", + "sqlx-postgres", "sqlx-sqlite", "syn 1.0.109", "tempfile", diff --git a/Cargo.toml b/Cargo.toml index 061d973..7f7bd83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ anyhow = "1.0.75" dotenv = "0.15.0" tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros", "process"] } teloxide = { version = "0.12.2", git ="https://github.com/teloxide/teloxide", features = ["macros"] } -sqlx = { version = "0.7.3", features = [ "runtime-tokio", "tls-native-tls", "sqlite", "sqlx-sqlite" ] } +sqlx = { version = "0.7.3", features = [ "runtime-tokio", "tls-native-tls", "postgres", "sqlx-postgres" ] } serde = { version = "1.0.196", features = ["derive"] } serde_json = "1.0.113" ordered-float = "4.2.0" diff --git a/migrations/1_init.sql b/migrations/1_init.sql index 1fccd8e..1d25a9e 100644 --- a/migrations/1_init.sql +++ b/migrations/1_init.sql @@ -1,13 +1,13 @@ CREATE TABLE "user" ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - tg_id INTEGER NOT NULL UNIQUE, - username TEXT UNIQUE, - first_name TEXT NOT NULL, - last_name TEXT, - can_download INTEGER NOT NULL, - is_admin INTEGER NOT NULL, - has_private_chat INTEGER NOT NULL + id SERIAL PRIMARY KEY, + tg_id BIGINT NOT NULL UNIQUE, + username VARCHAR UNIQUE, + first_name VARCHAR NOT NULL, + last_name VARCHAR, + can_download BOOLEAN NOT NULL, + is_admin BOOLEAN NOT NULL, + has_private_chat BOOLEAN NOT NULL ); CREATE INDEX idx_user_tg_id @@ -15,11 +15,11 @@ CREATE INDEX idx_user_tg_id CREATE TABLE "chat" ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - tg_id INTEGER NOT NULL UNIQUE, - title TEXT NOT NULL, - username TEXT, - can_download INTEGER NOT NULL + id SERIAL PRIMARY KEY, + tg_id BIGINT NOT NULL UNIQUE, + title VARCHAR NOT NULL, + username VARCHAR, + can_download BOOLEAN NOT NULL ); CREATE INDEX idx_chat_tg_id @@ -27,11 +27,11 @@ CREATE INDEX idx_chat_tg_id CREATE TABLE "link" ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - domain TEXT NOT NULL UNIQUE, - path TEXT, - download_allowed INTEGER NOT NULL, - auto_download INTEGER NOT NULL + id SERIAL PRIMARY KEY, + domain VARCHAR NOT NULL, + path VARCHAR, + download_allowed BOOLEAN NOT NULL, + auto_download BOOLEAN NOT NULL ); CREATE INDEX idx_link_domain @@ -39,40 +39,56 @@ CREATE INDEX idx_link_domain CREATE TABLE "request" ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, requested_by INTEGER NOT NULL UNIQUE, approved_by INTEGER UNIQUE, - message TEXT NOT NULL, - is_approved INTEGER NOT NULL, + message VARCHAR NOT NULL, + is_approved BOOLEAN NOT NULL, FOREIGN KEY(requested_by) REFERENCES "user"(id), FOREIGN KEY(approved_by) REFERENCES "user"(id) ); -CREATE TRIGGER "approve" -AFTER UPDATE OF is_approved ON "request" -WHEN new.is_approved = 1 +CREATE FUNCTION approve() +RETURNS TRIGGER AS $$ BEGIN - UPDATE user SET can_download = 1 WHERE user.id = new.requested_by; + IF new.is_approved THEN + UPDATE "user" SET can_download = TRUE WHERE "user".id = new.requested_by; + END IF; + RETURN new; END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER approve +AFTER UPDATE OF is_approved ON request +FOR EACH ROW +EXECUTE FUNCTION approve(); CREATE TABLE "request_chat" ( - id INTEGER PRIMARY KEY AUTOINCREMENT, + id SERIAL PRIMARY KEY, requested_by INTEGER NOT NULL UNIQUE, requested_for INTEGER NOT NULL UNIQUE, approved_by INTEGER UNIQUE, - message TEXT NOT NULL, - is_approved INTEGER NOT NULL, + message VARCHAR NOT NULL, + is_approved BOOLEAN NOT NULL, FOREIGN KEY(requested_by) REFERENCES "user"(id), FOREIGN KEY(requested_for) REFERENCES "chat"(id), FOREIGN KEY(approved_by) REFERENCES "user"(id) ); -CREATE TRIGGER "approve_chat" -AFTER UPDATE OF is_approved ON "request_chat" -WHEN new.is_approved = 1 +CREATE FUNCTION approve_chat() +RETURNS TRIGGER AS $$ BEGIN - UPDATE chat SET can_download = 1 WHERE chat.id = new.requested_for; -END; \ No newline at end of file + IF new.is_approved THEN + UPDATE "chat" SET can_download = TRUE WHERE "chat".id = new.requested_for; + END IF; + RETURN new; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER approve_chat +AFTER UPDATE OF is_approved ON request_chat +FOR EACH ROW +EXECUTE FUNCTION approve_chat(); \ No newline at end of file diff --git a/src/bot.rs b/src/bot.rs index 8ba1d95..b1d4e10 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -22,12 +22,11 @@ macro_rules! parse_integer { let out: i64 = match $integer.parse() { Ok(integer) => integer, Err(_) => { - $bot.send_message($chat_id, t!("not_valid_integer")) - .await?; + $bot.send_message($chat_id, t!("not_valid_integer")).await?; return Ok(()); } }; out }}; -} \ No newline at end of file +} diff --git a/src/bot/bot.rs b/src/bot/bot.rs index 88d90aa..01ae426 100644 --- a/src/bot/bot.rs +++ b/src/bot/bot.rs @@ -10,7 +10,7 @@ use tracing::{event, Level}; use super::start::handle_new_chat_member; use super::types::*; use crate::db::DbPool; -use crate::util::{unwrap_env, parse_env}; +use crate::util::{parse_env, unwrap_env}; use super::dl::cmd_download; use super::op::cmd_op; diff --git a/src/db.rs b/src/db.rs index 008d384..86881a2 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,10 +1,10 @@ use sqlx::migrate::MigrateDatabase; -use sqlx::{Sqlite, SqlitePool}; +use sqlx::{PgPool, Postgres}; use std::fmt; -use super::util::make_database_url; +use super::util::unwrap_env; -pub type DbPool = SqlitePool; +pub type DbPool = PgPool; #[derive(sqlx::FromRow, Debug)] pub struct User { @@ -83,15 +83,25 @@ pub struct RequestChat { pub is_approved: i64, } -pub async fn db_init() -> SqlitePool { +pub fn make_database_url() -> String { + format!( + "postgres://{}:{}@{}/{}", + unwrap_env("POSTGRES_USER"), + unwrap_env("POSTGRES_PASSWORD"), + unwrap_env("POSTGRES_HOST"), + unwrap_env("POSTGRES_DB") + ) +} + +pub async fn db_init() -> PgPool { let db_url = make_database_url(); - if !Sqlite::database_exists(&db_url).await.unwrap_or(false) { - Sqlite::create_database(&db_url) + if !Postgres::database_exists(&db_url).await.unwrap_or(false) { + Postgres::create_database(&db_url) .await .expect("failed to create database"); } - let db = SqlitePool::connect(&db_url).await.unwrap(); + let db = PgPool::connect(&db_url).await.unwrap(); sqlx::migrate!().run(&db).await.unwrap(); db