import sqlite3, os, shutil from datetime import datetime THIRD = '/home/hmo/.hermes/profiles/position-analyst/scripts/data/mofin.db' MAIN = '/home/hmo/MoFin/data/mofin.db' BACKUP = f'/home/hmo/MoFin/archive/third-db-backup-{datetime.now().strftime("%Y%m%d-%H%M")}' os.makedirs(BACKUP, exist_ok=True) shutil.copy(THIRD, os.path.join(BACKUP, 'mofin.db')) print('backup:', BACKUP) t = sqlite3.connect(THIRD, timeout=10) m = sqlite3.connect(MAIN, timeout=30) m.execute('PRAGMA busy_timeout=30000') # 1. sector_snapshots: dedup by (snapshot_id, name) existing = set() for r in m.execute("SELECT snapshot_id, name FROM sector_snapshots"): existing.add((r[0], r[1])) print(f'main sector_snapshots keys: {len(existing)}') cols = ['snapshot_id', 'name', 'change_pct', 'up_count', 'down_count', 'net_inflow', 'lead_stock', 'lead_stock_change', 'volume', 'turnover'] ins = 0 skip = 0 for r in t.execute(f"SELECT {', '.join(cols)} FROM sector_snapshots"): if (r[0], r[1]) in existing: skip += 1 continue m.execute(f"INSERT INTO sector_snapshots ({', '.join(cols)}) VALUES ({','.join('?'*len(cols))})", r) existing.add((r[0], r[1])) ins += 1 m.commit() print(f'sector_snapshots: inserted {ins}, skipped {skip}') # 2. market_snapshots: dedup by (timestamp, source) existing2 = set() for r in m.execute("SELECT timestamp, source FROM market_snapshots"): existing2.add((r[0], r[1])) cols2 = ['timestamp', 'source', 'up_ratio', 'mood', 'created_at'] ins2 = 0 skip2 = 0 for r in t.execute(f"SELECT {', '.join(cols2)} FROM market_snapshots"): if (r[0], r[1]) in existing2: skip2 += 1 continue m.execute(f"INSERT INTO market_snapshots ({', '.join(cols2)}) VALUES ({','.join('?'*len(cols2))})", r) existing2.add((r[0], r[1])) ins2 += 1 m.commit() print(f'market_snapshots: inserted {ins2}, skipped {skip2}') # 3. todos: third has 4 rows, main has 94 — check by title, insert missing (map to main schema) todos_t = t.execute("SELECT title, description, status, priority, source, fix_action, retry_count, note, created_at, updated_at FROM todos").fetchall() ins3 = 0 for r in todos_t: ex = m.execute("SELECT id FROM todos WHERE title=?", (r[0],)).fetchone() if ex: continue m.execute("INSERT INTO todos (title, description, status, priority, source, fix_action, retry_count, note, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?)", r) ins3 += 1 m.commit() print(f'todos: inserted {ins3}, skipped {len(todos_t)-ins3}') # 4. capital_flow_cache: keep whichever is newer t_row = t.execute("SELECT cache_json, updated_at FROM capital_flow_cache ORDER BY id DESC LIMIT 1").fetchone() m_row = m.execute("SELECT cache_json, updated_at FROM capital_flow_cache ORDER BY id DESC LIMIT 1").fetchone() if t_row and (not m_row or (t_row[1] or '') > (m_row[1] or '')): m.execute("DELETE FROM capital_flow_cache") m.execute("INSERT INTO capital_flow_cache (cache_json, updated_at) VALUES (?,?)", t_row) m.commit() print('capital_flow_cache: replaced with third (newer)') else: print('capital_flow_cache: main is newer/equal, kept') # verify total = m.execute("SELECT COUNT(*) FROM sector_snapshots").fetchone()[0] total2 = m.execute("SELECT COUNT(*) FROM market_snapshots").fetchone()[0] print(f'after merge: sector_snapshots={total}, market_snapshots={total2}') m.close() t.close() # 5. 删除第三库(连同 data 目录里的其他残留) third_dir = os.path.dirname(THIRD) trash = '/home/hmo/trashbox/third-db-retired-20260720' os.makedirs(trash, exist_ok=True) shutil.move(THIRD, os.path.join(trash, 'mofin.db')) print('third db moved to', trash) for f in os.listdir(third_dir): src = os.path.join(third_dir, f) if os.path.isfile(src): shutil.move(src, os.path.join(trash, f)) print(' also moved:', f) print('DONE')