rankora-api / app /database.py
Shoaib898's picture
Deploy Rankora API (clean bundle)
53febb9 verified
Raw
History Blame Contribute Delete
5.22 kB
from sqlalchemy import create_engine, text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import os
from app.config import settings
DATABASE_URL = settings.database_url or os.getenv("DATABASE_URL", "sqlite:///./amazon_intel.db")
if DATABASE_URL.startswith("sqlite"):
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
else:
engine = create_engine(DATABASE_URL, pool_pre_ping=True, pool_recycle=300)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
def migrate_schema():
"""Add columns when schema evolves (SQLite + PostgreSQL)."""
user_alters_sqlite = [
"ALTER TABLE users ADD COLUMN token_version INTEGER DEFAULT 0",
"ALTER TABLE users ADD COLUMN auth_provider VARCHAR(20) DEFAULT 'email'",
"ALTER TABLE users ADD COLUMN firebase_uid VARCHAR(128)",
]
user_alters_pg = [
"ALTER TABLE users ADD COLUMN IF NOT EXISTS token_version INTEGER DEFAULT 0",
"ALTER TABLE users ADD COLUMN IF NOT EXISTS auth_provider VARCHAR(20) DEFAULT 'email'",
"ALTER TABLE users ADD COLUMN IF NOT EXISTS firebase_uid VARCHAR(128)",
]
sqlite_product_alters = [
"ALTER TABLE products ADD COLUMN seller_count INTEGER",
"ALTER TABLE products ADD COLUMN buy_box_winner VARCHAR(255)",
"ALTER TABLE products ADD COLUMN buy_box_price NUMERIC(10,2)",
"ALTER TABLE products ADD COLUMN buy_box_is_fba BOOLEAN DEFAULT 1",
"ALTER TABLE products ADD COLUMN is_amazon_sold BOOLEAN DEFAULT 0",
"ALTER TABLE products ADD COLUMN last_data_source VARCHAR(20) DEFAULT 'cached'",
"ALTER TABLE products ADD COLUMN upc VARCHAR(20)",
"ALTER TABLE products ADD COLUMN has_buy_box BOOLEAN DEFAULT 1",
"ALTER TABLE products ADD COLUMN package_weight_lbs NUMERIC(8,3)",
"ALTER TABLE products ADD COLUMN other_sellers_json TEXT",
"ALTER TABLE products ADD COLUMN offers_source VARCHAR(30)",
"ALTER TABLE products ADD COLUMN marketplace VARCHAR(8) DEFAULT 'us'",
"ALTER TABLE products ADD COLUMN currency VARCHAR(8) DEFAULT 'USD'",
]
pg_product_alters = [
"ALTER TABLE products ADD COLUMN IF NOT EXISTS upc VARCHAR(20)",
"ALTER TABLE products ADD COLUMN IF NOT EXISTS has_buy_box BOOLEAN DEFAULT TRUE",
"ALTER TABLE products ADD COLUMN IF NOT EXISTS package_weight_lbs NUMERIC(8,3)",
"ALTER TABLE products ADD COLUMN IF NOT EXISTS other_sellers_json TEXT",
"ALTER TABLE products ADD COLUMN IF NOT EXISTS offers_source VARCHAR(30)",
"ALTER TABLE products ADD COLUMN IF NOT EXISTS marketplace VARCHAR(8) DEFAULT 'us'",
"ALTER TABLE products ADD COLUMN IF NOT EXISTS currency VARCHAR(8) DEFAULT 'USD'",
]
is_pg = DATABASE_URL.startswith("postgresql")
with engine.connect() as conn:
for sql in (user_alters_pg if is_pg else user_alters_sqlite):
try:
conn.execute(text(sql))
conn.commit()
except Exception:
pass
# Google-only accounts may have no password
if is_pg:
try:
conn.execute(text("ALTER TABLE users ALTER COLUMN password_hash DROP NOT NULL"))
conn.commit()
except Exception:
pass
if DATABASE_URL.startswith("sqlite"):
for sql in sqlite_product_alters:
try:
conn.execute(text(sql))
conn.commit()
except Exception:
pass
if is_pg:
for sql in pg_product_alters:
try:
conn.execute(text(sql))
conn.commit()
except Exception:
pass
# Prefer (asin, marketplace) uniqueness so US + AE can coexist
for sql in (
"UPDATE products SET marketplace = 'us' WHERE marketplace IS NULL",
"UPDATE products SET currency = 'USD' WHERE currency IS NULL AND (marketplace = 'us' OR marketplace IS NULL)",
"ALTER TABLE products DROP CONSTRAINT IF EXISTS products_asin_key",
"ALTER TABLE products DROP CONSTRAINT IF EXISTS ix_products_asin",
"CREATE UNIQUE INDEX IF NOT EXISTS uq_products_asin_marketplace ON products (asin, marketplace)",
):
try:
conn.execute(text(sql))
conn.commit()
except Exception:
pass
else:
for sql in (
"UPDATE products SET marketplace = 'us' WHERE marketplace IS NULL",
"UPDATE products SET currency = 'USD' WHERE currency IS NULL",
):
try:
conn.execute(text(sql))
conn.commit()
except Exception:
pass
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()