Impact radius via SQLite recursive CTE. Faster than NetworkX for large graphs because it avoids materialising the full graph in Python.
(
self,
changed_files: list[str],
max_depth: int = MAX_IMPACT_DEPTH,
max_nodes: int = MAX_IMPACT_NODES,
)
| 638 | # -- SQLite recursive CTE version (default) --------------------------- |
| 639 | |
| 640 | def get_impact_radius_sql( |
| 641 | self, |
| 642 | changed_files: list[str], |
| 643 | max_depth: int = MAX_IMPACT_DEPTH, |
| 644 | max_nodes: int = MAX_IMPACT_NODES, |
| 645 | ) -> dict[str, Any]: |
| 646 | """Impact radius via SQLite recursive CTE. |
| 647 | |
| 648 | Faster than NetworkX for large graphs because it avoids |
| 649 | materialising the full graph in Python. |
| 650 | """ |
| 651 | if not changed_files: |
| 652 | return { |
| 653 | "changed_nodes": [], |
| 654 | "impacted_nodes": [], |
| 655 | "impacted_files": [], |
| 656 | "edges": [], |
| 657 | "truncated": False, |
| 658 | "total_impacted": 0, |
| 659 | } |
| 660 | |
| 661 | # Seed qualified names |
| 662 | seeds: set[str] = set() |
| 663 | for f in changed_files: |
| 664 | nodes = self.get_nodes_by_file(f) |
| 665 | for n in nodes: |
| 666 | seeds.add(n.qualified_name) |
| 667 | |
| 668 | if not seeds: |
| 669 | return { |
| 670 | "changed_nodes": [], |
| 671 | "impacted_nodes": [], |
| 672 | "impacted_files": [], |
| 673 | "edges": [], |
| 674 | "truncated": False, |
| 675 | "total_impacted": 0, |
| 676 | } |
| 677 | |
| 678 | # Build recursive CTE — use a temp table for the seed set to |
| 679 | # keep the query plan efficient and stay under variable limits. |
| 680 | self._conn.execute( |
| 681 | "CREATE TEMP TABLE IF NOT EXISTS _impact_seeds " |
| 682 | "(qn TEXT PRIMARY KEY)" |
| 683 | ) |
| 684 | self._conn.execute("DELETE FROM _impact_seeds") |
| 685 | batch_size = 450 |
| 686 | seed_list = list(seeds) |
| 687 | for i in range(0, len(seed_list), batch_size): |
| 688 | batch = seed_list[i:i + batch_size] |
| 689 | placeholders = ",".join("(?)" for _ in batch) |
| 690 | self._conn.execute( # nosec B608 |
| 691 | f"INSERT OR IGNORE INTO _impact_seeds (qn) VALUES {placeholders}", |
| 692 | batch, |
| 693 | ) |
| 694 | |
| 695 | cte_sql = """ |
| 696 | WITH RECURSIVE impacted(node_qn, depth) AS ( |
| 697 | SELECT qn, 0 FROM _impact_seeds |