feat: use diesel-cli instead of hand writing tables

after reading the documentation, crazy right? I figured out i was making my life hard, this makes my life easy again
This commit is contained in:
Radical 2025-05-21 21:49:01 +02:00
parent f1d5b4316e
commit a6d35b0ba2
24 changed files with 323 additions and 206 deletions

9
diesel.toml Normal file
View file

@ -0,0 +1,9 @@
# For documentation on how to configure this file,
# see https://diesel.rs/guides/configuring-diesel-cli
[print_schema]
file = "src/schema.rs"
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
[migrations_directory]
dir = "migrations"

0
migrations/.keep Normal file
View file

View file

@ -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();

View file

@ -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;

View file

@ -0,0 +1,4 @@
-- This file should undo anything in `up.sql`
DROP INDEX idx_unique_username_active;
DROP INDEX idx_unique_email_active;
DROP TABLE users;

View file

@ -0,0 +1,20 @@
-- Your SQL goes here
CREATE TABLE users (
uuid uuid PRIMARY KEY NOT NULL,
username varchar(32) NOT NULL,
display_name varchar(64) DEFAULT NULL,
password varchar(512) NOT NULL,
email varchar(100) NOT NULL,
email_verified boolean NOT NULL DEFAULT FALSE,
is_deleted boolean NOT NULL DEFAULT FALSE,
deleted_at int8 DEFAULT NULL,
CONSTRAINT unique_username_active UNIQUE NULLS NOT DISTINCT (username, is_deleted),
CONSTRAINT unique_email_active UNIQUE NULLS NOT DISTINCT (email, is_deleted)
);
CREATE UNIQUE INDEX idx_unique_username_active
ON users(username)
WHERE is_deleted = FALSE;
CREATE UNIQUE INDEX idx_unique_email_active
ON users(email)
WHERE is_deleted = FALSE;

View file

@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE instance_permissions;

View file

@ -0,0 +1,5 @@
-- Your SQL goes here
CREATE TABLE instance_permissions (
uuid uuid PRIMARY KEY NOT NULL REFERENCES users(uuid),
administrator boolean NOT NULL DEFAULT FALSE
);

View file

@ -0,0 +1,3 @@
-- This file should undo anything in `up.sql`
DROP TABLE access_tokens;
DROP TABLE refresh_tokens;

View file

@ -0,0 +1,13 @@
-- Your SQL goes here
CREATE TABLE refresh_tokens (
token varchar(64) PRIMARY KEY UNIQUE NOT NULL,
uuid uuid NOT NULL REFERENCES users(uuid),
created_at int8 NOT NULL,
device_name varchar(16) NOT NULL
);
CREATE TABLE access_tokens (
token varchar(32) PRIMARY KEY UNIQUE NOT NULL,
refresh_token varchar(64) UNIQUE NOT NULL REFERENCES refresh_tokens(token) ON UPDATE CASCADE ON DELETE CASCADE,
uuid uuid NOT NULL REFERENCES users(uuid),
created_at int8 NOT NULL
);

View file

@ -0,0 +1,3 @@
-- This file should undo anything in `up.sql`
DROP TABLE guild_members;
DROP TABLE guilds;

View file

@ -0,0 +1,13 @@
-- Your SQL goes here
CREATE TABLE guilds (
uuid uuid PRIMARY KEY NOT NULL,
owner_uuid uuid NOT NULL REFERENCES users(uuid),
name VARCHAR(100) NOT NULL,
description VARCHAR(300)
);
CREATE TABLE guild_members (
uuid uuid PRIMARY KEY NOT NULL,
guild_uuid uuid NOT NULL REFERENCES guilds(uuid) ON DELETE CASCADE,
user_uuid uuid NOT NULL REFERENCES users(uuid),
nickname VARCHAR(100) DEFAULT NULL
);

View file

@ -0,0 +1,3 @@
-- This file should undo anything in `up.sql`
DROP TABLE role_members;
DROP TABLE roles;

View file

@ -0,0 +1,15 @@
-- Your SQL goes here
CREATE TABLE roles (
uuid uuid UNIQUE NOT NULL,
guild_uuid uuid NOT NULL REFERENCES guilds(uuid) ON DELETE CASCADE,
name VARCHAR(50) NOT NULL,
color int NOT NULL DEFAULT 16777215,
position int NOT NULL,
permissions int8 NOT NULL DEFAULT 0,
PRIMARY KEY (uuid, guild_uuid)
);
CREATE TABLE role_members (
role_uuid uuid NOT NULL REFERENCES roles(uuid) ON DELETE CASCADE,
member_uuid uuid NOT NULL REFERENCES guild_members(uuid) ON DELETE CASCADE,
PRIMARY KEY (role_uuid, member_uuid)
);

View file

@ -0,0 +1,3 @@
-- This file should undo anything in `up.sql`
DROP TABLE channel_permissions;
DROP TABLE channels;

View file

@ -0,0 +1,13 @@
-- Your SQL goes here
CREATE TABLE channels (
uuid uuid PRIMARY KEY NOT NULL,
guild_uuid uuid NOT NULL REFERENCES guilds(uuid) ON DELETE CASCADE,
name varchar(32) NOT NULL,
description varchar(500) NOT NULL
);
CREATE TABLE channel_permissions (
channel_uuid uuid NOT NULL REFERENCES channels(uuid) ON DELETE CASCADE,
role_uuid uuid NOT NULL REFERENCES roles(uuid) ON DELETE CASCADE,
permissions int8 NOT NULL DEFAULT 0,
PRIMARY KEY (channel_uuid, role_uuid)
);

View file

@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE messages;

View file

@ -0,0 +1,7 @@
-- Your SQL goes here
CREATE TABLE messages (
uuid uuid PRIMARY KEY NOT NULL,
channel_uuid uuid NOT NULL REFERENCES channels(uuid) ON DELETE CASCADE,
user_uuid uuid NOT NULL REFERENCES users(uuid),
message varchar(4000) NOT NULL
);

View file

@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE invites;

View file

@ -0,0 +1,6 @@
-- Your SQL goes here
CREATE TABLE invites (
id varchar(32) PRIMARY KEY NOT NULL,
guild_uuid uuid NOT NULL REFERENCES guilds(uuid) ON DELETE CASCADE,
user_uuid uuid NOT NULL REFERENCES users(uuid)
);

View file

@ -15,7 +15,7 @@ type Conn = deadpool::managed::Object<AsyncDieselConnectionManager<diesel_async:
pub mod structs;
pub mod utils;
pub mod tables;
pub mod schema;
type Error = Box<dyn std::error::Error>;
@ -57,101 +57,6 @@ async fn main() -> Result<(), Error> {
let mut conn = pool.get().await?;
/*
TODO: Figure out if a table should be used here and if not then what.
Also figure out if these should be different types from what they currently are and if we should add more "constraints"
TODO: References to time should be removed in favor of using the timestamp built in to UUIDv7 (apart from deleted_at in users)
*/
diesel::sql_query(
r#"
CREATE TABLE IF NOT EXISTS users (
uuid uuid PRIMARY KEY NOT NULL,
username varchar(32) NOT NULL,
display_name varchar(64) DEFAULT NULL,
password varchar(512) NOT NULL,
email varchar(100) NOT NULL,
email_verified boolean NOT NULL DEFAULT FALSE,
is_deleted boolean NOT NULL DEFAULT FALSE,
deleted_at int8 DEFAULT NULL,
CONSTRAINT unique_username_active UNIQUE NULLS NOT DISTINCT (username, is_deleted),
CONSTRAINT unique_email_active UNIQUE NULLS NOT DISTINCT (email, is_deleted)
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_unique_username_active
ON users(username)
WHERE is_deleted = FALSE;
CREATE UNIQUE INDEX IF NOT EXISTS idx_unique_email_active
ON users(email)
WHERE is_deleted = FALSE;
CREATE TABLE IF NOT EXISTS instance_permissions (
uuid uuid NOT NULL REFERENCES users(uuid),
administrator boolean NOT NULL DEFAULT FALSE
);
CREATE TABLE IF NOT EXISTS refresh_tokens (
token varchar(64) PRIMARY KEY UNIQUE NOT NULL,
uuid uuid NOT NULL REFERENCES users(uuid),
created_at int8 NOT NULL,
device_name varchar(16) NOT NULL
);
CREATE TABLE IF NOT EXISTS access_tokens (
token varchar(32) PRIMARY KEY UNIQUE NOT NULL,
refresh_token varchar(64) UNIQUE NOT NULL REFERENCES refresh_tokens(token) ON UPDATE CASCADE ON DELETE CASCADE,
uuid uuid NOT NULL REFERENCES users(uuid),
created_at int8 NOT NULL
);
CREATE TABLE IF NOT EXISTS guilds (
uuid uuid PRIMARY KEY NOT NULL,
owner_uuid uuid NOT NULL REFERENCES users(uuid),
name VARCHAR(100) NOT NULL,
description VARCHAR(300)
);
CREATE TABLE IF NOT EXISTS guild_members (
uuid uuid PRIMARY KEY NOT NULL,
guild_uuid uuid NOT NULL REFERENCES guilds(uuid) ON DELETE CASCADE,
user_uuid uuid NOT NULL REFERENCES users(uuid),
nickname VARCHAR(100) DEFAULT NULL
);
CREATE TABLE IF NOT EXISTS roles (
uuid uuid UNIQUE NOT NULL,
guild_uuid uuid NOT NULL REFERENCES guilds(uuid) ON DELETE CASCADE,
name VARCHAR(50) NOT NULL,
color int NOT NULL DEFAULT 16777215,
position int NOT NULL,
permissions int8 NOT NULL DEFAULT 0,
PRIMARY KEY (uuid, guild_uuid)
);
CREATE TABLE IF NOT EXISTS role_members (
role_uuid uuid NOT NULL REFERENCES roles(uuid) ON DELETE CASCADE,
member_uuid uuid NOT NULL REFERENCES guild_members(uuid) ON DELETE CASCADE,
PRIMARY KEY (role_uuid, member_uuid)
);
CREATE TABLE IF NOT EXISTS channels (
uuid uuid PRIMARY KEY NOT NULL,
guild_uuid uuid NOT NULL REFERENCES guilds(uuid) ON DELETE CASCADE,
name varchar(32) NOT NULL,
description varchar(500) NOT NULL
);
CREATE TABLE IF NOT EXISTS channel_permissions (
channel_uuid uuid NOT NULL REFERENCES channels(uuid) ON DELETE CASCADE,
role_uuid uuid NOT NULL REFERENCES roles(uuid) ON DELETE CASCADE,
permissions int8 NOT NULL DEFAULT 0,
PRIMARY KEY (channel_uuid, role_uuid)
);
CREATE TABLE IF NOT EXISTS messages (
uuid uuid PRIMARY KEY NOT NULL,
channel_uuid uuid NOT NULL REFERENCES channels(uuid) ON DELETE CASCADE,
user_uuid uuid NOT NULL REFERENCES users(uuid),
message varchar(4000) NOT NULL
);
CREATE TABLE IF NOT EXISTS invites (
id varchar(32) PRIMARY KEY NOT NULL,
guild_uuid uuid NOT NULL REFERENCES guilds(uuid) ON DELETE CASCADE,
user_uuid uuid NOT NULL REFERENCES users(uuid)
);
"#,
)
.execute(&mut conn)
.await?;
/*
**Stored for later possible use**

156
src/schema.rs Normal file
View file

@ -0,0 +1,156 @@
// @generated automatically by Diesel CLI.
diesel::table! {
access_tokens (token) {
#[max_length = 32]
token -> Varchar,
#[max_length = 64]
refresh_token -> Varchar,
uuid -> Uuid,
created_at -> Int8,
}
}
diesel::table! {
channel_permissions (channel_uuid, role_uuid) {
channel_uuid -> Uuid,
role_uuid -> Uuid,
permissions -> Int8,
}
}
diesel::table! {
channels (uuid) {
uuid -> Uuid,
guild_uuid -> Uuid,
#[max_length = 32]
name -> Varchar,
#[max_length = 500]
description -> Varchar,
}
}
diesel::table! {
guild_members (uuid) {
uuid -> Uuid,
guild_uuid -> Uuid,
user_uuid -> Uuid,
#[max_length = 100]
nickname -> Nullable<Varchar>,
}
}
diesel::table! {
guilds (uuid) {
uuid -> Uuid,
owner_uuid -> Uuid,
#[max_length = 100]
name -> Varchar,
#[max_length = 300]
description -> Nullable<Varchar>,
}
}
diesel::table! {
instance_permissions (uuid) {
uuid -> Uuid,
administrator -> Bool,
}
}
diesel::table! {
invites (id) {
#[max_length = 32]
id -> Varchar,
guild_uuid -> Uuid,
user_uuid -> Uuid,
}
}
diesel::table! {
messages (uuid) {
uuid -> Uuid,
channel_uuid -> Uuid,
user_uuid -> Uuid,
#[max_length = 4000]
message -> Varchar,
}
}
diesel::table! {
refresh_tokens (token) {
#[max_length = 64]
token -> Varchar,
uuid -> Uuid,
created_at -> Int8,
#[max_length = 16]
device_name -> Varchar,
}
}
diesel::table! {
role_members (role_uuid, member_uuid) {
role_uuid -> Uuid,
member_uuid -> Uuid,
}
}
diesel::table! {
roles (uuid, guild_uuid) {
uuid -> Uuid,
guild_uuid -> Uuid,
#[max_length = 50]
name -> Varchar,
color -> Int4,
position -> Int4,
permissions -> Int8,
}
}
diesel::table! {
users (uuid) {
uuid -> Uuid,
#[max_length = 32]
username -> Varchar,
#[max_length = 64]
display_name -> Nullable<Varchar>,
#[max_length = 512]
password -> Varchar,
#[max_length = 100]
email -> Varchar,
email_verified -> Bool,
is_deleted -> Bool,
deleted_at -> Nullable<Int8>,
}
}
diesel::joinable!(access_tokens -> refresh_tokens (refresh_token));
diesel::joinable!(access_tokens -> users (uuid));
diesel::joinable!(channel_permissions -> channels (channel_uuid));
diesel::joinable!(channels -> guilds (guild_uuid));
diesel::joinable!(guild_members -> guilds (guild_uuid));
diesel::joinable!(guild_members -> users (user_uuid));
diesel::joinable!(guilds -> users (owner_uuid));
diesel::joinable!(instance_permissions -> users (uuid));
diesel::joinable!(invites -> guilds (guild_uuid));
diesel::joinable!(invites -> users (user_uuid));
diesel::joinable!(messages -> channels (channel_uuid));
diesel::joinable!(messages -> users (user_uuid));
diesel::joinable!(refresh_tokens -> users (uuid));
diesel::joinable!(role_members -> guild_members (member_uuid));
diesel::joinable!(roles -> guilds (guild_uuid));
diesel::allow_tables_to_appear_in_same_query!(
access_tokens,
channel_permissions,
channels,
guild_members,
guilds,
instance_permissions,
invites,
messages,
refresh_tokens,
role_members,
roles,
users,
);

View file

@ -6,7 +6,7 @@ use log::error;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::{Conn, Data, tables::*};
use crate::{Conn, Data, schema::*};
#[derive(Serialize, Deserialize, Clone, Selectable)]
#[diesel(table_name = channels)]

View file

@ -1,109 +0,0 @@
use diesel::table;
table! {
users (uuid) {
uuid -> Uuid,
username -> VarChar,
display_name -> Nullable<VarChar>,
password -> VarChar,
email -> VarChar,
email_verified -> Bool,
is_deleted -> Bool,
deleted_at -> Int8,
}
}
table! {
instance_permissions (uuid) {
uuid -> Uuid,
administrator -> Bool,
}
}
table! {
refresh_tokens (token) {
token -> VarChar,
uuid -> Uuid,
created_at -> Int8,
device_name -> VarChar,
}
}
table! {
access_tokens (token) {
token -> VarChar,
refresh_token -> VarChar,
uuid -> Uuid,
created_at -> Int8
}
}
table! {
guilds (uuid) {
uuid -> Uuid,
owner_uuid -> Uuid,
name -> VarChar,
description -> VarChar
}
}
table! {
guild_members (uuid) {
uuid -> Uuid,
guild_uuid -> Uuid,
user_uuid -> Uuid,
nickname -> VarChar,
}
}
table! {
roles (uuid, guild_uuid) {
uuid -> Uuid,
guild_uuid -> Uuid,
name -> VarChar,
color -> Int4,
position -> Int4,
permissions -> Int8,
}
}
table! {
role_members (role_uuid, member_uuid) {
role_uuid -> Uuid,
member_uuid -> Uuid,
}
}
table! {
channels (uuid) {
uuid -> Uuid,
guild_uuid -> Uuid,
name -> VarChar,
description -> VarChar,
}
}
table! {
channel_permissions (channel_uuid, role_uuid) {
channel_uuid -> Uuid,
role_uuid -> Uuid,
permissions -> Int8,
}
}
table! {
messages (uuid) {
uuid -> Uuid,
channel_uuid -> Uuid,
user_uuid -> Uuid,
message -> VarChar,
}
}
table! {
invites (id) {
id -> VarChar,
guild_uuid -> Uuid,
user_uuid -> Uuid,
}
}