"""add news_headline table Revision ID: n5d6e7f8h9i0 Revises: m4e5f6g7h8i9 Create Date: 2026-04-25 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import postgresql revision: str = "n5d6e7f8h9i0" down_revision: Union[str, Sequence[str], None] = "m4e5f6g7h8i9" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: conn = op.get_bind() if not conn.dialect.has_table(conn, "news_headline"): op.create_table( "news_headline", sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True), sa.Column("source", sa.String(30), nullable=False), sa.Column("source_id", sa.String(100), nullable=False), sa.Column("ticker", sa.String(10), nullable=False), sa.Column("tickers_all", postgresql.ARRAY(sa.String(10)), nullable=True), sa.Column("published_at", postgresql.TIMESTAMP(timezone=True), nullable=False), sa.Column("headline", sa.Text(), nullable=False), sa.Column("summary", sa.Text(), nullable=True), sa.Column("url", sa.Text(), nullable=True), sa.Column("language", sa.String(8), server_default="en"), sa.Column("vendor_categories", postgresql.ARRAY(sa.String(50)), nullable=True), sa.Column("categories", postgresql.ARRAY(sa.String(50)), nullable=True), sa.Column("raw_sentiment", sa.Float(), nullable=True), sa.Column("is_primary", sa.Boolean(), nullable=False, server_default=sa.text("false")), sa.Column("ingested_at", postgresql.TIMESTAMP(timezone=True), nullable=False), sa.Column("created_at", postgresql.TIMESTAMP(timezone=True)), sa.Column("updated_at", postgresql.TIMESTAMP(timezone=True)), sa.UniqueConstraint( "source", "source_id", "ticker", name="uq_news_headline_source_ticker", ), ) op.create_index("idx_news_ticker_published", "news_headline", ["ticker", "published_at"]) op.create_index("idx_news_published", "news_headline", ["published_at"]) op.create_index("idx_news_source_published", "news_headline", ["source", "published_at"]) op.create_index("idx_news_ingested", "news_headline", ["ingested_at"]) def downgrade() -> None: op.drop_table("news_headline")