fix(db): executescript в try/except, индексы отдельно от миграций

This commit is contained in:
Repinoid
2026-06-07 09:16:33 +04:00
parent d5e44060d3
commit fd2126c0cb
+88 -73
View File
@@ -39,88 +39,90 @@ class Database:
self.conn = None
def _init_schema(self):
self.conn.executescript("""
CREATE TABLE IF NOT EXISTS sessions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
# Основная схема (может упасть на индексах старых БД — ловим)
try:
self.conn.executescript("""
CREATE TABLE IF NOT EXISTS sessions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
-- Сервер
client_ip TEXT,
real_ip TEXT,
user_agent TEXT,
content_length INTEGER,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
-- Сервер
client_ip TEXT,
real_ip TEXT,
user_agent TEXT,
content_length INTEGER,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
-- Телефон
phone_model TEXT,
phone_maker TEXT,
android_version TEXT,
android_sdk INTEGER,
app_version TEXT,
android_id TEXT,
device_uuid TEXT,
phone_lang TEXT,
phone_tz TEXT,
phone_display TEXT,
-- Телефон
phone_model TEXT,
phone_maker TEXT,
android_version TEXT,
android_sdk INTEGER,
app_version TEXT,
android_id TEXT,
device_uuid TEXT,
phone_lang TEXT,
phone_tz TEXT,
phone_display TEXT,
-- ELM327
elm_mac TEXT,
elm_bt_name TEXT,
obd_protocol TEXT,
-- ELM327
elm_mac TEXT,
elm_bt_name TEXT,
obd_protocol TEXT,
-- Авто
vin TEXT,
dtc_count INTEGER DEFAULT 0,
pid_count INTEGER DEFAULT 0,
-- Авто
vin TEXT,
dtc_count INTEGER DEFAULT 0,
pid_count INTEGER DEFAULT 0,
-- Сессия
duration_ms INTEGER,
response_count INTEGER DEFAULT 0,
error_count INTEGER DEFAULT 0,
retry_count INTEGER DEFAULT 0,
timeout_count INTEGER DEFAULT 0,
script_mode TEXT,
transport TEXT, -- 'bt' | 'tcp'
mock_mode INTEGER DEFAULT 0,
car_info TEXT,
-- Сессия
duration_ms INTEGER,
response_count INTEGER DEFAULT 0,
error_count INTEGER DEFAULT 0,
retry_count INTEGER DEFAULT 0,
timeout_count INTEGER DEFAULT 0,
script_mode TEXT,
transport TEXT,
mock_mode INTEGER DEFAULT 0,
car_info TEXT,
-- LLM
diagnosis_text TEXT,
diagnosis_len INTEGER,
llm_model TEXT,
llm_duration_ms INTEGER,
llm_success INTEGER DEFAULT 0,
-- LLM
diagnosis_text TEXT,
diagnosis_len INTEGER,
llm_model TEXT,
llm_duration_ms INTEGER,
llm_success INTEGER DEFAULT 0,
-- Сырые данные (JSON)
raw_responses TEXT,
-- Сырые данные (JSON)
raw_responses TEXT,
-- Идемпотентность
request_id TEXT UNIQUE,
response_json TEXT
);
-- Идемпотентность
request_id TEXT UNIQUE,
response_json TEXT
);
CREATE INDEX IF NOT EXISTS idx_sessions_created ON sessions(created_at);
CREATE INDEX IF NOT EXISTS idx_sessions_vin ON sessions(vin);
CREATE INDEX IF NOT EXISTS idx_sessions_mac ON sessions(elm_mac);
CREATE INDEX IF NOT EXISTS idx_sessions_aid ON sessions(android_id);
CREATE INDEX IF NOT EXISTS idx_sessions_request_id ON sessions(request_id);
CREATE INDEX IF NOT EXISTS idx_sessions_uuid ON sessions(device_uuid);
CREATE INDEX IF NOT EXISTS idx_sessions_created ON sessions(created_at);
CREATE INDEX IF NOT EXISTS idx_sessions_vin ON sessions(vin);
CREATE INDEX IF NOT EXISTS idx_sessions_mac ON sessions(elm_mac);
-- Профили ELM-устройств
CREATE TABLE IF NOT EXISTS device_profiles (
mac TEXT PRIMARY KEY,
level INTEGER NOT NULL,
elm_version TEXT,
elm_desc TEXT,
protocol TEXT,
voltage TEXT,
supported TEXT,
unsupported TEXT,
errors TEXT,
first_seen TEXT NOT NULL DEFAULT (datetime('now')),
last_seen TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_profiles_level ON device_profiles(level);
""")
except sqlite3.OperationalError:
pass # старая БД без новых колонок — применим миграции ниже
-- Профили ELM-устройств (по BT MAC)
CREATE TABLE IF NOT EXISTS device_profiles (
mac TEXT PRIMARY KEY, -- BT MAC-адрес
level INTEGER NOT NULL, -- 0/1/2 (-1 = нерабочее)
elm_version TEXT, -- ATI ответ
elm_desc TEXT, -- AT@1 (если есть)
protocol TEXT, -- ATDPN
voltage TEXT, -- ATRV
supported TEXT, -- JSON: ["ATE0","ATL0",...]
unsupported TEXT, -- JSON: ["ATAT1",...]
errors TEXT, -- JSON: ["ATCFC1: no response",...]
first_seen TEXT NOT NULL DEFAULT (datetime('now')),
last_seen TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_profiles_level ON device_profiles(level);
""")
self.conn.commit()
# Миграции: добавляем колонки, которых нет в старых БД
@@ -138,7 +140,20 @@ class Database:
try:
self.conn.execute(sql)
except sqlite3.OperationalError:
pass # колонка уже существует
pass
# Индексы для новых колонок (могут отсутствовать в старых БД)
index_migrations = [
"CREATE INDEX IF NOT EXISTS idx_sessions_aid ON sessions(android_id)",
"CREATE INDEX IF NOT EXISTS idx_sessions_uuid ON sessions(device_uuid)",
"CREATE INDEX IF NOT EXISTS idx_sessions_request_id ON sessions(request_id)",
]
for sql in index_migrations:
try:
self.conn.execute(sql)
except sqlite3.OperationalError:
pass
self.conn.commit()
# ── sessions ──────────────────────────────────────────