mirror of
https://github.com/flibusta-apps/book_library_server.git
synced 2026-03-03 07:00:51 +01:00
Add DB migrations and run them on startup
Enable sqlx "migrate" feature and add SQL migrations to create the database schema: pg_trgm extension, sources, genres, authors, sequences, books, junction tables, annotations, and supporting indexes
This commit is contained in:
@@ -42,4 +42,4 @@ rand = "0.9.0"
|
|||||||
|
|
||||||
chrono = { version = "0.4.40", features = ["serde"] }
|
chrono = { version = "0.4.40", features = ["serde"] }
|
||||||
|
|
||||||
sqlx = { version = "0.8.3", features = ["runtime-tokio", "postgres", "macros", "chrono", "json"] }
|
sqlx = { version = "0.8.3", features = ["runtime-tokio", "postgres", "macros", "chrono", "json", "migrate"] }
|
||||||
|
|||||||
2
migrations/20260116092202_create_extensions.sql
Normal file
2
migrations/20260116092202_create_extensions.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
-- Create pg_trgm extension for trigram-based text search
|
||||||
|
CREATE EXTENSION IF NOT EXISTS pg_trgm;
|
||||||
5
migrations/20260116092203_create_sources_table.sql
Normal file
5
migrations/20260116092203_create_sources_table.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
-- Create sources table
|
||||||
|
CREATE TABLE IF NOT EXISTS sources (
|
||||||
|
id SMALLSERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(32) NOT NULL UNIQUE
|
||||||
|
);
|
||||||
11
migrations/20260116092204_create_genres_table.sql
Normal file
11
migrations/20260116092204_create_genres_table.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
-- Create genres table
|
||||||
|
CREATE TABLE IF NOT EXISTS genres (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
source SMALLINT NOT NULL,
|
||||||
|
remote_id INTEGER NOT NULL,
|
||||||
|
code VARCHAR(45) NOT NULL,
|
||||||
|
description VARCHAR(99) NOT NULL,
|
||||||
|
meta VARCHAR(45) NOT NULL,
|
||||||
|
CONSTRAINT uc_genres_source_remote_id UNIQUE (source, remote_id),
|
||||||
|
CONSTRAINT fk_genres_sources_id_source FOREIGN KEY (source) REFERENCES sources(id)
|
||||||
|
);
|
||||||
15
migrations/20260116092205_create_authors_table.sql
Normal file
15
migrations/20260116092205_create_authors_table.sql
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
-- Create authors table
|
||||||
|
CREATE TABLE IF NOT EXISTS authors (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
source SMALLINT NOT NULL,
|
||||||
|
remote_id INTEGER NOT NULL,
|
||||||
|
first_name VARCHAR(256) NOT NULL,
|
||||||
|
last_name VARCHAR(256) NOT NULL,
|
||||||
|
middle_name VARCHAR(256),
|
||||||
|
CONSTRAINT uc_authors_source_remote_id UNIQUE (source, remote_id),
|
||||||
|
CONSTRAINT fk_authors_sources_id_source FOREIGN KEY (source) REFERENCES sources(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create trigram indexes for author search
|
||||||
|
CREATE INDEX IF NOT EXISTS tgrm_authors_lf ON authors USING gin ((last_name || ' ' || first_name) gin_trgm_ops);
|
||||||
|
CREATE INDEX IF NOT EXISTS tgrm_authors_lfm ON authors USING gin ((last_name || ' ' || first_name || ' ' || middle_name) gin_trgm_ops);
|
||||||
9
migrations/20260116092206_create_sequences_table.sql
Normal file
9
migrations/20260116092206_create_sequences_table.sql
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
-- Create sequences table
|
||||||
|
CREATE TABLE IF NOT EXISTS sequences (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
source SMALLINT NOT NULL,
|
||||||
|
remote_id INTEGER NOT NULL,
|
||||||
|
name VARCHAR(256) NOT NULL,
|
||||||
|
CONSTRAINT uc_sequences_source_remote_id UNIQUE (source, remote_id),
|
||||||
|
CONSTRAINT fk_sequences_sources_id_source FOREIGN KEY (source) REFERENCES sources(id)
|
||||||
|
);
|
||||||
20
migrations/20260116092207_create_books_table.sql
Normal file
20
migrations/20260116092207_create_books_table.sql
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
-- Create books table
|
||||||
|
CREATE TABLE IF NOT EXISTS books (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
source SMALLINT NOT NULL,
|
||||||
|
remote_id INTEGER NOT NULL,
|
||||||
|
title VARCHAR(256) NOT NULL,
|
||||||
|
lang VARCHAR(3) NOT NULL,
|
||||||
|
file_type VARCHAR(4) NOT NULL,
|
||||||
|
uploaded DATE NOT NULL,
|
||||||
|
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
pages INTEGER,
|
||||||
|
year SMALLINT NOT NULL DEFAULT 0,
|
||||||
|
CONSTRAINT uc_books_source_remote_id UNIQUE (source, remote_id),
|
||||||
|
CONSTRAINT fk_books_sources_id_source FOREIGN KEY (source) REFERENCES sources(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create indexes for books
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_id_asc__not_is_deleted ON books (id) WHERE NOT is_deleted;
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_id_asc__uploaded__not_is_deleted ON books (id, uploaded) WHERE NOT is_deleted;
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_uploaded__id_asc__not_is_deleted ON books (uploaded, id) WHERE NOT is_deleted;
|
||||||
13
migrations/20260116092208_create_book_authors_table.sql
Normal file
13
migrations/20260116092208_create_book_authors_table.sql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
-- Create book_authors junction table
|
||||||
|
CREATE TABLE IF NOT EXISTS book_authors (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
author INTEGER NOT NULL,
|
||||||
|
book INTEGER NOT NULL,
|
||||||
|
CONSTRAINT uc_book_authors_book_author UNIQUE (book, author),
|
||||||
|
CONSTRAINT fk_book_authors_authors_author_id FOREIGN KEY (author) REFERENCES authors(id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_book_authors_books_book_id FOREIGN KEY (book) REFERENCES books(id) ON UPDATE CASCADE ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create indexes for book_authors
|
||||||
|
CREATE INDEX IF NOT EXISTS book_authors_author ON book_authors (author);
|
||||||
|
CREATE INDEX IF NOT EXISTS book_authors_book ON book_authors (book);
|
||||||
13
migrations/20260116092209_create_book_genres_table.sql
Normal file
13
migrations/20260116092209_create_book_genres_table.sql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
-- Create book_genres junction table
|
||||||
|
CREATE TABLE IF NOT EXISTS book_genres (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
genre INTEGER NOT NULL,
|
||||||
|
book INTEGER NOT NULL,
|
||||||
|
CONSTRAINT uc_book_genres_book_genre UNIQUE (book, genre),
|
||||||
|
CONSTRAINT fk_book_genres_genres_genre_id FOREIGN KEY (genre) REFERENCES genres(id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_book_genres_books_book_id FOREIGN KEY (book) REFERENCES books(id) ON UPDATE CASCADE ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create indexes for book_genres
|
||||||
|
CREATE INDEX IF NOT EXISTS book_genres_genre ON book_genres (genre);
|
||||||
|
CREATE INDEX IF NOT EXISTS book_genres_book ON book_genres (book);
|
||||||
14
migrations/20260116092210_create_book_sequences_table.sql
Normal file
14
migrations/20260116092210_create_book_sequences_table.sql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
-- Create book_sequences junction table
|
||||||
|
CREATE TABLE IF NOT EXISTS book_sequences (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
position SMALLINT NOT NULL,
|
||||||
|
sequence INTEGER NOT NULL,
|
||||||
|
book INTEGER NOT NULL,
|
||||||
|
CONSTRAINT uc_book_sequences_book_sequence UNIQUE (book, sequence),
|
||||||
|
CONSTRAINT fk_book_sequences_sequences_sequence_id FOREIGN KEY (sequence) REFERENCES sequences(id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_book_sequences_books_book_id FOREIGN KEY (book) REFERENCES books(id) ON UPDATE CASCADE ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create indexes for book_sequences
|
||||||
|
CREATE INDEX IF NOT EXISTS book_sequences_sequence ON book_sequences (sequence);
|
||||||
|
CREATE INDEX IF NOT EXISTS book_sequences_book ON book_sequences (book);
|
||||||
14
migrations/20260116092211_create_translations_table.sql
Normal file
14
migrations/20260116092211_create_translations_table.sql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
-- Create translations junction table
|
||||||
|
CREATE TABLE IF NOT EXISTS translations (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
position SMALLINT NOT NULL,
|
||||||
|
author INTEGER NOT NULL,
|
||||||
|
book INTEGER NOT NULL,
|
||||||
|
CONSTRAINT uc_translations_book_author UNIQUE (book, author),
|
||||||
|
CONSTRAINT fk_translations_authors_author_id FOREIGN KEY (author) REFERENCES authors(id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
CONSTRAINT fk_translations_books_book_id FOREIGN KEY (book) REFERENCES books(id) ON UPDATE CASCADE ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create indexes for translations
|
||||||
|
CREATE INDEX IF NOT EXISTS translations_author ON translations (author);
|
||||||
|
CREATE INDEX IF NOT EXISTS translations_book ON translations (book);
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
-- Create author_annotations table
|
||||||
|
CREATE TABLE IF NOT EXISTS author_annotations (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
author INTEGER NOT NULL UNIQUE,
|
||||||
|
title VARCHAR(256) NOT NULL,
|
||||||
|
text TEXT NOT NULL,
|
||||||
|
file VARCHAR(256),
|
||||||
|
CONSTRAINT fk_author_annotations_authors_id_author FOREIGN KEY (author) REFERENCES authors(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create index for author_annotations
|
||||||
|
CREATE INDEX IF NOT EXISTS author_annotation_author_id ON author_annotations (author);
|
||||||
12
migrations/20260116092213_create_book_annotations_table.sql
Normal file
12
migrations/20260116092213_create_book_annotations_table.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
-- Create book_annotations table
|
||||||
|
CREATE TABLE IF NOT EXISTS book_annotations (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
book INTEGER NOT NULL UNIQUE,
|
||||||
|
title VARCHAR(256) NOT NULL,
|
||||||
|
text TEXT NOT NULL,
|
||||||
|
file VARCHAR(256),
|
||||||
|
CONSTRAINT fk_book_annotations_books_id_book FOREIGN KEY (book) REFERENCES books(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create index for book_annotations
|
||||||
|
CREATE INDEX IF NOT EXISTS book_annotation_book_id ON book_annotations (book);
|
||||||
12
src/db.rs
12
src/db.rs
@@ -12,10 +12,18 @@ pub async fn get_postgres_pool() -> PgPool {
|
|||||||
CONFIG.postgres_db
|
CONFIG.postgres_db
|
||||||
);
|
);
|
||||||
|
|
||||||
PgPoolOptions::new()
|
let pool = PgPoolOptions::new()
|
||||||
.max_connections(10)
|
.max_connections(10)
|
||||||
.acquire_timeout(std::time::Duration::from_secs(300))
|
.acquire_timeout(std::time::Duration::from_secs(300))
|
||||||
.connect(&database_url)
|
.connect(&database_url)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap();
|
||||||
|
|
||||||
|
// Run migrations
|
||||||
|
sqlx::migrate!("./migrations")
|
||||||
|
.run(&pool)
|
||||||
|
.await
|
||||||
|
.expect("Failed to run migrations");
|
||||||
|
|
||||||
|
pool
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user