diff --git a/src/session_analytics/storage.py b/src/session_analytics/storage.py index 1c8d1af..02f9514 100644 --- a/src/session_analytics/storage.py +++ b/src/session_analytics/storage.py @@ -166,7 +166,7 @@ class BusEvent: DEFAULT_DB_PATH = Path.home() / ".claude" / "contrib" / "analytics" / "data.db" # Schema version for migrations -SCHEMA_VERSION = 6 +SCHEMA_VERSION = 7 # Migration functions: dict of version -> (migration_name, migration_func) # Each migration upgrades FROM version-1 TO version @@ -379,6 +379,17 @@ def migrate_v6(conn): conn.execute("CREATE INDEX IF NOT EXISTS idx_bus_events_repo ON bus_events(repo)") +@migration(7, "add_tool_id_index") +def migrate_v7(conn): + """Add index on tool_id for faster self-joins. + + The query_error_details() function joins events to itself on tool_id + to correlate tool_result errors with their tool_use parameters. + Without this index, queries took ~25s on 160K events. + """ + conn.execute("CREATE INDEX IF NOT EXISTS idx_events_tool_id ON events(tool_id)") + + class SQLiteStorage: """SQLite-backed storage for session analytics.""" @@ -705,6 +716,9 @@ def _init_db(self): conn.execute("CREATE INDEX IF NOT EXISTS idx_events_parent_uuid ON events(parent_uuid)") conn.execute("CREATE INDEX IF NOT EXISTS idx_events_agent_id ON events(agent_id)") + # Performance index for tool_use ↔ tool_result self-joins (migration v7) + conn.execute("CREATE INDEX IF NOT EXISTS idx_events_tool_id ON events(tool_id)") + # Event operations def add_event(self, event: Event) -> Event: diff --git a/tests/test_storage.py b/tests/test_storage.py index f2cc54c..18e80c5 100644 --- a/tests/test_storage.py +++ b/tests/test_storage.py @@ -982,3 +982,9 @@ def test_index_on_agent_id(self, storage): rows = storage.execute_query("PRAGMA index_list(events)") indexes = {row[1] for row in rows} assert "idx_events_agent_id" in indexes + + def test_index_on_tool_id(self, storage): + """Verify that idx_events_tool_id index exists for self-join performance.""" + rows = storage.execute_query("PRAGMA index_list(events)") + indexes = {row[1] for row in rows} + assert "idx_events_tool_id" in indexes