From 6dde01d7a120ef5b2ac295e0af1163c0bf9e45c4 Mon Sep 17 00:00:00 2001 From: Kappeh Date: Tue, 28 Jan 2025 00:15:26 +0000 Subject: [PATCH] Setup rotom_database crate --- rotom_database/Cargo.toml | 29 +++++++++++++++ rotom_database/build.rs | 3 ++ rotom_database/diesel_mysql.toml | 9 +++++ rotom_database/diesel_postgres.toml | 9 +++++ rotom_database/diesel_sqlite.toml | 9 +++++ rotom_database/migrations/mysql/.keep | 0 rotom_database/migrations/postgres/.keep | 0 .../down.sql | 6 ++++ .../up.sql | 36 +++++++++++++++++++ rotom_database/migrations/sqlite/.keep | 0 rotom_database/src/lib.rs | 36 +++++++++++++++++++ rotom_database/src/mysql/mod.rs | 29 +++++++++++++++ rotom_database/src/mysql/schema.rs | 0 rotom_database/src/postgres/mod.rs | 29 +++++++++++++++ rotom_database/src/postgres/schema.rs | 0 rotom_database/src/sqlite/mod.rs | 29 +++++++++++++++ rotom_database/src/sqlite/schema.rs | 0 17 files changed, 224 insertions(+) create mode 100644 rotom_database/Cargo.toml create mode 100644 rotom_database/build.rs create mode 100644 rotom_database/diesel_mysql.toml create mode 100644 rotom_database/diesel_postgres.toml create mode 100644 rotom_database/diesel_sqlite.toml create mode 100644 rotom_database/migrations/mysql/.keep create mode 100644 rotom_database/migrations/postgres/.keep create mode 100644 rotom_database/migrations/postgres/00000000000000_diesel_initial_setup/down.sql create mode 100644 rotom_database/migrations/postgres/00000000000000_diesel_initial_setup/up.sql create mode 100644 rotom_database/migrations/sqlite/.keep create mode 100644 rotom_database/src/lib.rs create mode 100644 rotom_database/src/mysql/mod.rs create mode 100644 rotom_database/src/mysql/schema.rs create mode 100644 rotom_database/src/postgres/mod.rs create mode 100644 rotom_database/src/postgres/schema.rs create mode 100644 rotom_database/src/sqlite/mod.rs create mode 100644 rotom_database/src/sqlite/schema.rs diff --git a/rotom_database/Cargo.toml b/rotom_database/Cargo.toml new file mode 100644 index 0000000..8b608ad --- /dev/null +++ b/rotom_database/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "rotom_database" +version = "0.1.0" +edition = "2021" + +[dependencies] +diesel = { version = "2.2.6", default_features = false } +diesel-async = { version = "0.5.2", features = ["bb8"] } +diesel_migrations = "2.2.0" +thiserror = "2.0.11" + +[features] +default = ["mysql", "postgres", "sqlite"] +mysql = [ + "diesel/mysql", + "diesel-async/mysql", + "diesel_migrations/mysql", +] +postgres = [ + "diesel/postgres", + "diesel-async/postgres", + "diesel_migrations/postgres", +] +sqlite = [ + "diesel/sqlite", + "diesel/returning_clauses_for_sqlite_3_35", + "diesel-async/sync-connection-wrapper", + "diesel_migrations/sqlite", +] diff --git a/rotom_database/build.rs b/rotom_database/build.rs new file mode 100644 index 0000000..3a8149e --- /dev/null +++ b/rotom_database/build.rs @@ -0,0 +1,3 @@ +fn main() { + println!("cargo:rerun-if-changed=migrations"); +} diff --git a/rotom_database/diesel_mysql.toml b/rotom_database/diesel_mysql.toml new file mode 100644 index 0000000..17da19f --- /dev/null +++ b/rotom_database/diesel_mysql.toml @@ -0,0 +1,9 @@ +# For documentation on how to configure this file, +# see https://diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "src/mysql/schema.rs" +custom_type_derives = ["diesel::query_builder::QueryId", "Clone"] + +[migrations_directory] +dir = "migrations/mysql/" diff --git a/rotom_database/diesel_postgres.toml b/rotom_database/diesel_postgres.toml new file mode 100644 index 0000000..f7596db --- /dev/null +++ b/rotom_database/diesel_postgres.toml @@ -0,0 +1,9 @@ +# For documentation on how to configure this file, +# see https://diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "src/postgres/schema.rs" +custom_type_derives = ["diesel::query_builder::QueryId", "Clone"] + +[migrations_directory] +dir = "migrations/postgres/" diff --git a/rotom_database/diesel_sqlite.toml b/rotom_database/diesel_sqlite.toml new file mode 100644 index 0000000..2094fe5 --- /dev/null +++ b/rotom_database/diesel_sqlite.toml @@ -0,0 +1,9 @@ +# For documentation on how to configure this file, +# see https://diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "src/sqlite/schema.rs" +custom_type_derives = ["diesel::query_builder::QueryId", "Clone"] + +[migrations_directory] +dir = "migrations/sqlite/" diff --git a/rotom_database/migrations/mysql/.keep b/rotom_database/migrations/mysql/.keep new file mode 100644 index 0000000..e69de29 diff --git a/rotom_database/migrations/postgres/.keep b/rotom_database/migrations/postgres/.keep new file mode 100644 index 0000000..e69de29 diff --git a/rotom_database/migrations/postgres/00000000000000_diesel_initial_setup/down.sql b/rotom_database/migrations/postgres/00000000000000_diesel_initial_setup/down.sql new file mode 100644 index 0000000..a9f5260 --- /dev/null +++ b/rotom_database/migrations/postgres/00000000000000_diesel_initial_setup/down.sql @@ -0,0 +1,6 @@ +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + +DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass); +DROP FUNCTION IF EXISTS diesel_set_updated_at(); diff --git a/rotom_database/migrations/postgres/00000000000000_diesel_initial_setup/up.sql b/rotom_database/migrations/postgres/00000000000000_diesel_initial_setup/up.sql new file mode 100644 index 0000000..d68895b --- /dev/null +++ b/rotom_database/migrations/postgres/00000000000000_diesel_initial_setup/up.sql @@ -0,0 +1,36 @@ +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + + + + +-- Sets up a trigger for the given table to automatically set a column called +-- `updated_at` whenever the row is modified (unless `updated_at` was included +-- in the modified columns) +-- +-- # Example +-- +-- ```sql +-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW()); +-- +-- SELECT diesel_manage_updated_at('users'); +-- ``` +CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ +BEGIN + EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s + FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl); +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ +BEGIN + IF ( + NEW IS DISTINCT FROM OLD AND + NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at + ) THEN + NEW.updated_at := current_timestamp; + END IF; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; diff --git a/rotom_database/migrations/sqlite/.keep b/rotom_database/migrations/sqlite/.keep new file mode 100644 index 0000000..e69de29 diff --git a/rotom_database/src/lib.rs b/rotom_database/src/lib.rs new file mode 100644 index 0000000..e6d5287 --- /dev/null +++ b/rotom_database/src/lib.rs @@ -0,0 +1,36 @@ +#[cfg(feature = "mysql")] +pub mod mysql; +#[cfg(feature = "postgres")] +pub mod postgres; +#[cfg(feature = "sqlite")] +pub mod sqlite; + +#[derive(Clone, Debug)] +pub enum DatabaseDialect { + #[cfg(feature = "mysql")] + Mysql, + #[cfg(feature = "postgres")] + Postgres, + #[cfg(feature = "sqlite")] + Sqlite, +} + +#[derive(Debug, thiserror::Error)] +pub enum BackendError { + #[error(transparent)] + DieselConnectionError(#[from] diesel::ConnectionError), + #[error(transparent)] + DieselQueryError(#[from] diesel::result::Error), + #[error(transparent)] + DieselMigrationError(Box), +} + +impl From for BackendError { + fn from(value: diesel_async::pooled_connection::PoolError) -> Self { + use diesel_async::pooled_connection::PoolError as E; + match value { + E::ConnectionError(connection_error) => Self::from(connection_error), + E::QueryError(error) => Self::from(error), + } + } +} diff --git a/rotom_database/src/mysql/mod.rs b/rotom_database/src/mysql/mod.rs new file mode 100644 index 0000000..0b29e28 --- /dev/null +++ b/rotom_database/src/mysql/mod.rs @@ -0,0 +1,29 @@ +use diesel::Connection; +use diesel::MysqlConnection; +use diesel_async::pooled_connection::bb8::Pool; +use diesel_async::pooled_connection::AsyncDieselConnectionManager; +use diesel_async::AsyncMysqlConnection; +use diesel_migrations::embed_migrations; +use diesel_migrations::EmbeddedMigrations; +use diesel_migrations::MigrationHarness; + +use crate::BackendError; + +mod schema; + +const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations/mysql"); + +pub fn run_pending_migrations(database_url: &str) -> Result<(), BackendError> { + let mut connection = MysqlConnection::establish(database_url)?; + connection.run_pending_migrations(MIGRATIONS) + .map_err(BackendError::DieselMigrationError)?; + Ok(()) +} + +pub async fn establish_async_pool( + database_url: &str, +) -> Result, BackendError> { + let config = AsyncDieselConnectionManager::new(database_url); + let pool = Pool::builder().build(config).await?; + Ok(pool) +} diff --git a/rotom_database/src/mysql/schema.rs b/rotom_database/src/mysql/schema.rs new file mode 100644 index 0000000..e69de29 diff --git a/rotom_database/src/postgres/mod.rs b/rotom_database/src/postgres/mod.rs new file mode 100644 index 0000000..244e557 --- /dev/null +++ b/rotom_database/src/postgres/mod.rs @@ -0,0 +1,29 @@ +use diesel::Connection; +use diesel::PgConnection; +use diesel_async::pooled_connection::bb8::Pool; +use diesel_async::pooled_connection::AsyncDieselConnectionManager; +use diesel_async::AsyncPgConnection; +use diesel_migrations::embed_migrations; +use diesel_migrations::EmbeddedMigrations; +use diesel_migrations::MigrationHarness; + +use crate::BackendError; + +mod schema; + +const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations/postgres"); + +pub fn run_pending_migrations(database_url: &str) -> Result<(), BackendError> { + let mut connection = PgConnection::establish(database_url)?; + connection.run_pending_migrations(MIGRATIONS) + .map_err(BackendError::DieselMigrationError)?; + Ok(()) +} + +pub async fn establish_async_pool( + database_url: &str, +) -> Result, BackendError> { + let config = AsyncDieselConnectionManager::new(database_url); + let pool = Pool::builder().build(config).await?; + Ok(pool) +} diff --git a/rotom_database/src/postgres/schema.rs b/rotom_database/src/postgres/schema.rs new file mode 100644 index 0000000..e69de29 diff --git a/rotom_database/src/sqlite/mod.rs b/rotom_database/src/sqlite/mod.rs new file mode 100644 index 0000000..8e16df9 --- /dev/null +++ b/rotom_database/src/sqlite/mod.rs @@ -0,0 +1,29 @@ +use diesel::Connection; +use diesel::SqliteConnection; +use diesel_async::pooled_connection::bb8::Pool; +use diesel_async::pooled_connection::AsyncDieselConnectionManager; +use diesel_async::sync_connection_wrapper::SyncConnectionWrapper; +use diesel_migrations::embed_migrations; +use diesel_migrations::EmbeddedMigrations; +use diesel_migrations::MigrationHarness; + +use crate::BackendError; + +mod schema; + +const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations/sqlite"); + +pub fn run_pending_migrations(database_url: &str) -> Result<(), BackendError> { + let mut connection = SqliteConnection::establish(database_url)?; + connection.run_pending_migrations(MIGRATIONS) + .map_err(BackendError::DieselMigrationError)?; + Ok(()) +} + +pub async fn establish_async_pool( + database_url: &str, +) -> Result>, BackendError> { + let config = AsyncDieselConnectionManager::new(database_url); + let pool = Pool::builder().build(config).await?; + Ok(pool) +} diff --git a/rotom_database/src/sqlite/schema.rs b/rotom_database/src/sqlite/schema.rs new file mode 100644 index 0000000..e69de29