diff --git a/src/quant_engine/snapshot_admin.db b/src/quant_engine/snapshot_admin.db index 25ecc8b..d618e2b 100644 Binary files a/src/quant_engine/snapshot_admin.db and b/src/quant_engine/snapshot_admin.db differ diff --git a/tools/fix_settings_schema.py b/tools/fix_settings_schema.py new file mode 100644 index 0000000..2e47078 --- /dev/null +++ b/tools/fix_settings_schema.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +""" +settings 테이블 스키마 수정 +올바른 스키마: ordinal, key, value_json, note, updated_at +""" + +import sqlite3 +import json +from pathlib import Path +from datetime import datetime + +def fix_settings_schema(): + """settings 테이블 스키마 수정""" + + db_path = Path('src/quant_engine/snapshot_admin.db') + conn = sqlite3.connect(db_path) + cursor = conn.cursor() + + # 현재 settings 데이터 백업 + cursor.execute("SELECT * FROM settings") + current_rows = cursor.fetchall() + + print(f"현재 settings: {len(current_rows)}개 행") + + # 현재 컬럼 확인 + cursor.execute("PRAGMA table_info(settings)") + current_cols = cursor.fetchall() + print(f"현재 컬럼: {[col[1] for col in current_cols]}") + + # 기존 테이블 삭제 + cursor.execute("DROP TABLE IF EXISTS settings") + + # 올바른 스키마로 생성 + cursor.execute(""" + CREATE TABLE settings ( + ordinal INTEGER PRIMARY KEY, + key TEXT NOT NULL, + value_json TEXT NOT NULL, + note TEXT DEFAULT '', + updated_at TEXT NOT NULL + ) + """) + + print("\n새 스키마 생성:") + print(" ordinal INTEGER PRIMARY KEY") + print(" key TEXT NOT NULL") + print(" value_json TEXT NOT NULL") + print(" note TEXT DEFAULT ''") + print(" updated_at TEXT NOT NULL") + + # 데이터 복원 + # 현재 컬럼: [key, value] + timestamp = datetime.now().isoformat() + + inserted = 0 + for ordinal, (key, value) in enumerate(current_rows, start=1): + # value를 JSON으로 변환 + try: + value_json = json.dumps(str(value), ensure_ascii=False) + except: + value_json = json.dumps("", ensure_ascii=False) + + cursor.execute( + """INSERT INTO settings (ordinal, key, value_json, note, updated_at) + VALUES (?, ?, ?, ?, ?)""", + (ordinal, key, value_json, "", timestamp) + ) + inserted += 1 + + conn.commit() + + # 검증 + cursor.execute("SELECT COUNT(*) FROM settings") + count = cursor.fetchone()[0] + print(f"\n복원된 settings: {count}개 행") + + # 샘플 확인 + cursor.execute("SELECT ordinal, key, value_json FROM settings LIMIT 3") + print("\n샘플 데이터:") + for ordinal, key, value_json in cursor.fetchall(): + value = json.loads(value_json) + print(f" {ordinal}. {key} = {value}") + + conn.close() + + print("\n[OK] settings 테이블 스키마 수정 완료") + +if __name__ == "__main__": + fix_settings_schema() diff --git a/tools/load_from_xlsx_correct.py b/tools/load_from_xlsx_correct.py index 3eae912..7f1d87c 100644 --- a/tools/load_from_xlsx_correct.py +++ b/tools/load_from_xlsx_correct.py @@ -49,7 +49,13 @@ class CorrectXLSXLoader: header_param = header_row_1based - 1 # pandas는 0-indexed try: - df = pd.read_excel(self.xlsx_file, sheet_name=sheet_name, header=header_param) + # settings 특수 처리: 헤더가 없음 (key-value 쌍) + if sheet_name == 'settings': + df = pd.read_excel(self.xlsx_file, sheet_name=sheet_name, header=None) + df.columns = ['key', 'value', 'note1', 'note2'] + df = df[['key', 'value']] # 필요한 컬럼만 + else: + df = pd.read_excel(self.xlsx_file, sheet_name=sheet_name, header=header_param) # NaN을 None으로 변환 df = df.where(pd.notna(df), None)