You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
buffer_platform/app/analysis_db.py

118 lines
3.6 KiB

"""
期货智析数据库 - 独立存储
"""
import logging
from pathlib import Path
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base
from datetime import datetime
from app.mysql_database import MySQLSessionLocal
from app.storage_manager import get_storage_manager
logger = logging.getLogger(__name__)
# 数据目录
DATA_DIR = Path(__file__).resolve().parent.parent / "data"
DATA_DIR.mkdir(parents=True, exist_ok=True)
ANALYSIS_DB_PATH = DATA_DIR / "futures_analysis.db"
analysis_engine = create_engine(
f"sqlite:///{ANALYSIS_DB_PATH}",
connect_args={"check_same_thread": False},
pool_pre_ping=True,
)
AnalysisSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=analysis_engine)
AnalysisBase = declarative_base()
def get_analysis_db():
"""获取期货智析数据库会话。
根据 MySQL 可用性动态选择后端
- MySQL 可用时返回 MySQL Session
- MySQL 不可用时返回 SQLite Session兜底
"""
storage = get_storage_manager()
if MySQLSessionLocal is not None and storage.check_mysql():
db = None
try:
db = MySQLSessionLocal()
yield db
except Exception as e:
logger.warning(f"创建 MySQL analysis session 失败,降级到 SQLite: {e}")
if db is not None:
try:
db.close()
except Exception:
pass
db = AnalysisSessionLocal()
yield db
finally:
if db is not None:
try:
db.close()
except Exception:
pass
else:
db = AnalysisSessionLocal()
try:
yield db
finally:
db.close()
def init_analysis_db():
"""初始化期货智析数据库表SQLite 兜底)。"""
# 确保导入所有模型类,使其注册到 AnalysisBase
from app import analysis_models
# 直接导入 analysis_models 模块中的所有类
from app.analysis_models import (
FuturesAnalysis, WatchedSymbol, AIModelConfig, AnalysisSettings,
AIAnalysisCache, ReviewDate, SymbolRanking, TradingPlan,
SymbolScoreV2, TradingPlanV2, SectorHeat, ReviewPlanV2,
TradeRecord, TradeImportBatch,
)
AnalysisBase.metadata.create_all(bind=analysis_engine)
# 迁移为已有表添加新增列SQLite 不支持 IF NOT EXISTS用异常处理
_migrate_add_columns()
def init_analysis_mysql(mysql_engine):
"""初始化期货智析数据库表MySQL"""
from app import analysis_models
from app.analysis_models import (
FuturesAnalysis, WatchedSymbol, AIModelConfig, AnalysisSettings,
AIAnalysisCache, ReviewDate, SymbolRanking, TradingPlan,
SymbolScoreV2, TradingPlanV2, SectorHeat, ReviewPlanV2,
TradeRecord, TradeImportBatch,
)
AnalysisBase.metadata.create_all(bind=mysql_engine)
logger.info("MySQL analysis 表结构初始化完成")
def _migrate_add_columns():
"""为已有表添加新增列(兼容旧数据库)"""
import sqlite3
conn = sqlite3.connect(str(ANALYSIS_DB_PATH))
cursor = conn.cursor()
migrations = [
("symbol_scores_v2", "data_date", "VARCHAR(16)"),
("review_plans_v2", "actual_data_date", "VARCHAR(16)"),
("review_plans_v2", "data_date_matches", "INTEGER"),
]
for table, column, col_type in migrations:
try:
cursor.execute(f"ALTER TABLE {table} ADD COLUMN {column} {col_type}")
except sqlite3.OperationalError:
pass # 列已存在
conn.commit()
conn.close()