57 lines
2.5 KiB
Plaintext
57 lines
2.5 KiB
Plaintext
---
|
|
description: TradeDB/MariaDB 임시 조회 시 스키마 확인·PyMySQL % 이스케이프 필수 (실패 재시도 금지)
|
|
alwaysApply: true
|
|
---
|
|
|
|
# DB 임시 조회(adhoc) 안전 규칙
|
|
|
|
TradeDB/`database.py`로 SQL을 날릴 때 **추측 쿼리 금지**. 실패하면 같은 가정을 반복하지 말 것(토큰 낭비).
|
|
|
|
## 1. 쿼리 전에 스키마 확인 (필수)
|
|
|
|
모르는 테이블/컬럼이면 **먼저** `SHOW COLUMNS FROM <table>` 또는 `DESCRIBE <table>`.
|
|
|
|
대표 함정:
|
|
|
|
| 테이블 | 주의 |
|
|
|--------|------|
|
|
| `target_candidates` | **전략 컬럼 없음** (code/name/score/price/scan_time/updated_at + market/sector/theme). `strategy_id` SELECT 금지 |
|
|
| `target_candidates_history` | 컬럼은 `SHOW COLUMNS`로 확인 후 사용. CREATE 기본 DDL과 실제 DB가 다를 수 있음 |
|
|
| 전략별 후보 | history의 `strategy_id` 또는 별도 테이블/코드 경로를 문서·스키마로 확인 |
|
|
|
|
## 2. PyMySQL `%` 포맷 충돌 (필수)
|
|
|
|
`TradeDB.conn.execute()`는 pymysql이라 SQL 문자열의 `%`가 포맷으로 해석된다.
|
|
|
|
- ❌ `LIKE '20260712%'` / `LIKE '%BREAK%'` (단독 문자열에 `%`)
|
|
- ✅ 바인딩: `LIKE %s` + params `('20260712%',)`
|
|
- ✅ 또는 `%%` 이스케이프: `LIKE '20260712%%'`
|
|
|
|
`not enough arguments for format string` = 이 문제. 스키마 문제가 아님.
|
|
|
|
## 3. 실패 시 재시도 규칙
|
|
|
|
1. 에러 읽기 → 원인 분류(포맷 vs 컬럼없음 vs 테이블없음)
|
|
2. **스키마/바인딩 고친 뒤 1회만** 재실행
|
|
3. 같은 실패를 다른 날짜·다른 strategy 문자열로 반복 금지
|
|
4. 불확실하면 `database.py`의 CREATE/migrate/`get_*` 헬퍼를 읽고 그걸 쓰거나, 헬퍼에 없는 조회면 스키마 확인 후 작성
|
|
|
|
## 4. 최소 템플릿
|
|
|
|
```python
|
|
from database import TradeDB
|
|
db = TradeDB()
|
|
cols = [r["Field"] for r in db.conn.execute("SHOW COLUMNS FROM target_candidates_history").fetchall()]
|
|
# cols 확인 후 SELECT. LIKE는 반드시 %s 바인딩
|
|
rows = db.conn.execute(
|
|
"SELECT slot_key, COUNT(*) n FROM target_candidates_history WHERE slot_key LIKE %s GROUP BY slot_key",
|
|
("20260712%",),
|
|
).fetchall()
|
|
```
|
|
|
|
## 5. env 신규 키 — “patch했다” ≠ DB에 남음 (`.cursorrules` CRITICAL §4-3)
|
|
|
|
- `MOMENTUM_*` 등은 `config_momentum` 키 목록·컬럼에 없으면 `apply_env_patch` 후에도 `get_env_from_db`가 빈값일 수 있음.
|
|
- 신규 키: ENV_CONFIG_KEYS(또는 전략 키 튜플) + code default + apply 맵 + 저장 후 **재조회 검증**.
|
|
- 캐시 무효: `invalidate_merged_env_cache()` (이름 추측 금지).
|