AI-News/backend/app/db/migrations/versions/fdf8821871d7_main_tables.py
2025-12-04 10:04:21 +08:00

217 lines
5.5 KiB
Python

"""main tables
Revision ID: fdf8821871d7
Revises:
Create Date: 2019-09-22 01:36:44.791880
"""
from typing import Tuple
import sqlalchemy as sa
from alembic import op
from sqlalchemy import func
revision = "fdf8821871d7"
down_revision = None
branch_labels = None
depends_on = None
def create_updated_at_trigger() -> None:
op.execute(
"""
CREATE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS
$$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';
"""
)
def timestamps() -> Tuple[sa.Column, sa.Column]:
return (
sa.Column(
"created_at",
sa.TIMESTAMP(timezone=True),
nullable=False,
server_default=func.now(),
),
sa.Column(
"updated_at",
sa.TIMESTAMP(timezone=True),
nullable=False,
server_default=func.now(),
onupdate=func.current_timestamp(),
),
)
def create_users_table() -> None:
op.create_table(
"users",
sa.Column("id", sa.Integer, primary_key=True),
sa.Column("username", sa.Text, unique=True, nullable=False, index=True),
sa.Column("email", sa.Text, unique=True, nullable=False, index=True),
sa.Column("salt", sa.Text, nullable=False),
sa.Column("hashed_password", sa.Text),
sa.Column("bio", sa.Text, nullable=False, server_default=""),
sa.Column("image", sa.Text),
*timestamps(),
)
op.execute(
"""
CREATE TRIGGER update_user_modtime
BEFORE UPDATE
ON users
FOR EACH ROW
EXECUTE PROCEDURE update_updated_at_column();
"""
)
def create_followers_to_followings_table() -> None:
op.create_table(
"followers_to_followings",
sa.Column(
"follower_id",
sa.Integer,
sa.ForeignKey("users.id", ondelete="CASCADE"),
nullable=False,
),
sa.Column(
"following_id",
sa.Integer,
sa.ForeignKey("users.id", ondelete="CASCADE"),
nullable=False,
),
)
op.create_primary_key(
"pk_followers_to_followings",
"followers_to_followings",
["follower_id", "following_id"],
)
def create_articles_table() -> None:
op.create_table(
"articles",
sa.Column("id", sa.Integer, primary_key=True),
sa.Column("slug", sa.Text, unique=True, nullable=False, index=True),
sa.Column("title", sa.Text, nullable=False),
sa.Column("description", sa.Text, nullable=False),
sa.Column("body", sa.Text, nullable=False),
sa.Column(
"author_id", sa.Integer, sa.ForeignKey("users.id", ondelete="SET NULL")
),
*timestamps(),
)
op.execute(
"""
CREATE TRIGGER update_article_modtime
BEFORE UPDATE
ON articles
FOR EACH ROW
EXECUTE PROCEDURE update_updated_at_column();
"""
)
def create_tags_table() -> None:
op.create_table("tags", sa.Column("tag", sa.Text, primary_key=True))
def create_articles_to_tags_table() -> None:
op.create_table(
"articles_to_tags",
sa.Column(
"article_id",
sa.Integer,
sa.ForeignKey("articles.id", ondelete="CASCADE"),
nullable=False,
),
sa.Column(
"tag",
sa.Text,
sa.ForeignKey("tags.tag", ondelete="CASCADE"),
nullable=False,
),
)
op.create_primary_key(
"pk_articles_to_tags", "articles_to_tags", ["article_id", "tag"]
)
def create_favorites_table() -> None:
op.create_table(
"favorites",
sa.Column(
"user_id",
sa.Integer,
sa.ForeignKey("users.id", ondelete="CASCADE"),
nullable=False,
),
sa.Column(
"article_id",
sa.Integer,
sa.ForeignKey("articles.id", ondelete="CASCADE"),
nullable=False,
),
)
op.create_primary_key("pk_favorites", "favorites", ["user_id", "article_id"])
def create_commentaries_table() -> None:
op.create_table(
"commentaries",
sa.Column("id", sa.Integer, primary_key=True),
sa.Column("body", sa.Text, nullable=False),
sa.Column(
"author_id",
sa.Integer,
sa.ForeignKey("users.id", ondelete="CASCADE"),
nullable=False,
),
sa.Column(
"article_id",
sa.Integer,
sa.ForeignKey("articles.id", ondelete="CASCADE"),
nullable=False,
),
*timestamps(),
)
op.execute(
"""
CREATE TRIGGER update_comment_modtime
BEFORE UPDATE
ON commentaries
FOR EACH ROW
EXECUTE PROCEDURE update_updated_at_column();
"""
)
def upgrade() -> None:
create_updated_at_trigger()
create_users_table()
create_followers_to_followings_table()
create_articles_table()
create_tags_table()
create_articles_to_tags_table()
create_favorites_table()
create_commentaries_table()
def downgrade() -> None:
op.drop_table("commentaries")
op.drop_table("favorites")
op.drop_table("articles_to_tags")
op.drop_table("tags")
op.drop_table("articles")
op.drop_table("followers_to_followings")
op.drop_table("users")
op.execute("DROP FUNCTION update_updated_at_column")