recce-nightly 1.8.0.20250615__py3-none-any.whl → 1.8.0.20250617__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of recce-nightly might be problematic. Click here for more details.

Files changed (76) hide show
  1. recce/VERSION +1 -1
  2. recce/adapter/dbt_adapter/__init__.py +213 -102
  3. recce/cli.py +4 -4
  4. recce/data/404.html +2 -2
  5. recce/data/_next/static/6pJWLeTWseySFL3ozLQBi/_buildManifest.js +1 -0
  6. recce/data/_next/static/chunks/{1bff33f1-39d26ad38ba4fe06.js → 1bff33f1-1ef85cf5e658a751.js} +1 -1
  7. recce/data/_next/static/chunks/217-879a84d70f7a907c.js +2 -0
  8. recce/data/_next/static/chunks/29e3cc0d-60045b2e47aa3916.js +1 -0
  9. recce/data/_next/static/chunks/36e1c10d-35e36448f4f83961.js +1 -0
  10. recce/data/_next/static/chunks/{3998a672-0426e04aa28a4198.js → 3998a672-03adacad07b346ac.js} +1 -1
  11. recce/data/_next/static/chunks/{3a92ee20-146003bc9f4294f5.js → 3a92ee20-1081c360214f9602.js} +1 -1
  12. recce/data/_next/static/chunks/450c323b-fd94e7ffaa4a5efa.js +1 -0
  13. recce/data/_next/static/chunks/47d8844f-929aed9b1c73a905.js +1 -0
  14. recce/data/_next/static/chunks/608-3b079b544e5d5f5e.js +15 -0
  15. recce/data/_next/static/chunks/{6dc81886-e6963cc22929fc61.js → 6dc81886-adbfa45836061d79.js} +1 -1
  16. recce/data/_next/static/chunks/7a8a3e83-edf6dc64b5d5f0a5.js +1 -0
  17. recce/data/_next/static/chunks/7f27ae6c-d5f0438edd5c2a5b.js +1 -0
  18. recce/data/_next/static/chunks/826-1fdc111c49b34b0f.js +43 -0
  19. recce/data/_next/static/chunks/{0d0b8943-1c8ef4728d0e645b.js → 86730205-cfb14e3f051bab35.js} +1 -1
  20. recce/data/_next/static/chunks/{8d700b6a.ebb3dd15a8cd3f2b.js → 8d700b6a.8bb140898499c512.js} +1 -1
  21. recce/data/_next/static/chunks/92-bd5f33f1c3cb9d93.js +1 -0
  22. recce/data/_next/static/chunks/960-49d66f0cbac6af8a.js +9 -0
  23. recce/data/_next/static/chunks/9746af58-a42b7d169cacadf0.js +1 -0
  24. recce/data/_next/static/chunks/a30376cd-de84559016d7e133.js +1 -0
  25. recce/data/_next/static/chunks/app/_not-found/{page-2ab757d7e27193ec.js → page-01ed58b7f971d311.js} +1 -1
  26. recce/data/_next/static/chunks/app/layout-af033601bf81ed53.js +1 -0
  27. recce/data/_next/static/chunks/app/page-f1048e1fe24111f8.js +1 -0
  28. recce/data/_next/static/chunks/b63b1b3f-4282bdcf459e075c.js +1 -0
  29. recce/data/_next/static/chunks/bbda5537-9ec25eb1dd62348a.js +1 -0
  30. recce/data/_next/static/chunks/c132bf7d-08cb668a789d6afd.js +1 -0
  31. recce/data/_next/static/chunks/ce84277d-2e5d1d46910cf052.js +1 -0
  32. recce/data/_next/static/chunks/{febdd86e-d96ff090bf0a928d.js → febdd86e-c6b525341634b860.js} +3 -3
  33. recce/data/_next/static/chunks/fee69bc6-2dbccaf9b90474e6.js +1 -0
  34. recce/data/_next/static/chunks/main-app-39061b0166c47f55.js +1 -0
  35. recce/data/_next/static/chunks/main-b5b3ae20a1405261.js +1 -0
  36. recce/data/_next/static/chunks/pages/_app-437c455677d62394.js +1 -0
  37. recce/data/_next/static/chunks/pages/_error-e7650df18ca04bde.js +1 -0
  38. recce/data/_next/static/chunks/{webpack-c84693803e08b48b.js → webpack-7b49d5ba7e3a434d.js} +1 -1
  39. recce/data/index.html +2 -2
  40. recce/data/index.txt +6 -6
  41. recce/models/types.py +7 -13
  42. recce/server.py +17 -0
  43. recce/util/lineage.py +29 -50
  44. {recce_nightly-1.8.0.20250615.dist-info → recce_nightly-1.8.0.20250617.dist-info}/METADATA +1 -1
  45. {recce_nightly-1.8.0.20250615.dist-info → recce_nightly-1.8.0.20250617.dist-info}/RECORD +51 -51
  46. tests/adapter/dbt_adapter/test_dbt_cll.py +180 -35
  47. recce/data/_next/static/chunks/184-dc0879f75e9506c3.js +0 -15
  48. recce/data/_next/static/chunks/249-aeaf2fd44b7d8946.js +0 -1
  49. recce/data/_next/static/chunks/29e3cc0d-e95ebef603672925.js +0 -1
  50. recce/data/_next/static/chunks/33-27f5a26fea26baf4.js +0 -43
  51. recce/data/_next/static/chunks/36e1c10d-6d59e8aae9eec8b4.js +0 -1
  52. recce/data/_next/static/chunks/42-3dc869b8f2a75e9c.js +0 -2
  53. recce/data/_next/static/chunks/450c323b-3dd665b028d8e184.js +0 -1
  54. recce/data/_next/static/chunks/47d8844f-57ea99282765dce5.js +0 -1
  55. recce/data/_next/static/chunks/627-1b5619ef0c492f2b.js +0 -9
  56. recce/data/_next/static/chunks/7a8a3e83-933490bb996ac49b.js +0 -1
  57. recce/data/_next/static/chunks/7f27ae6c-f6aa983aa05b83cd.js +0 -1
  58. recce/data/_next/static/chunks/9746af58-ac9a4d1b8160c197.js +0 -1
  59. recce/data/_next/static/chunks/a30376cd-2d324b6b8687d57b.js +0 -1
  60. recce/data/_next/static/chunks/app/layout-83da1e1a59dea607.js +0 -1
  61. recce/data/_next/static/chunks/app/page-3404ed4ba8cffb0b.js +0 -1
  62. recce/data/_next/static/chunks/b63b1b3f-a380b9fe5be938d3.js +0 -1
  63. recce/data/_next/static/chunks/bbda5537-10da060bd56d475e.js +0 -1
  64. recce/data/_next/static/chunks/c132bf7d-d6e713672e7030a1.js +0 -1
  65. recce/data/_next/static/chunks/ce84277d-7f0a33888bf731d9.js +0 -1
  66. recce/data/_next/static/chunks/fee69bc6-288939bd73e3e49c.js +0 -1
  67. recce/data/_next/static/chunks/main-0276cd0c41be4ef4.js +0 -1
  68. recce/data/_next/static/chunks/main-app-2e08b38d48f6a731.js +0 -1
  69. recce/data/_next/static/chunks/pages/_app-ddb94f741a61a490.js +0 -1
  70. recce/data/_next/static/chunks/pages/_error-9e738ac1fd923095.js +0 -1
  71. recce/data/_next/static/clUnQD2xUsy2WK43RKblq/_buildManifest.js +0 -1
  72. /recce/data/_next/static/{clUnQD2xUsy2WK43RKblq → 6pJWLeTWseySFL3ozLQBi}/_ssgManifest.js +0 -0
  73. {recce_nightly-1.8.0.20250615.dist-info → recce_nightly-1.8.0.20250617.dist-info}/WHEEL +0 -0
  74. {recce_nightly-1.8.0.20250615.dist-info → recce_nightly-1.8.0.20250617.dist-info}/entry_points.txt +0 -0
  75. {recce_nightly-1.8.0.20250615.dist-info → recce_nightly-1.8.0.20250617.dist-info}/licenses/LICENSE +0 -0
  76. {recce_nightly-1.8.0.20250615.dist-info → recce_nightly-1.8.0.20250617.dist-info}/top_level.txt +0 -0
recce/server.py CHANGED
@@ -355,6 +355,23 @@ async def column_level_lineage_by_node(cll_input: CllIn):
355
355
  return CllOutput(current=cll)
356
356
 
357
357
 
358
+ class ImpactRadiusIn(BaseModel):
359
+ node_id: str
360
+
361
+
362
+ @app.post("/api/impact-radius", response_model=CllOutput)
363
+ async def impact_radius_by_node(impact_input: ImpactRadiusIn):
364
+ from recce.adapter.dbt_adapter import DbtAdapter
365
+
366
+ context = default_context()
367
+ dbt_adapter: DbtAdapter = context.adapter
368
+ node_id = impact_input.node_id
369
+
370
+ cll = dbt_adapter.get_impact_radius(node_id)
371
+
372
+ return CllOutput(current=cll)
373
+
374
+
358
375
  class SelectNodesInput(BaseModel):
359
376
  select: Optional[str] = None
360
377
  exclude: Optional[str] = None
recce/util/lineage.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from typing import Dict, Set, Tuple
2
2
 
3
- from recce.models.types import CllData
3
+ from recce.models.types import CllColumn, CllNode
4
4
 
5
5
 
6
6
  def find_upstream(node, parent_map):
@@ -39,61 +39,40 @@ def find_downstream(node, child_map):
39
39
  return downstream
40
40
 
41
41
 
42
- def build_dependency_maps(cll_data: CllData) -> Tuple[Dict[str, Set], Dict[str, Set]]:
43
- parent_map = {}
44
- child_map = {}
45
-
46
- for node_id, node_data in cll_data.nodes.items():
47
- for col_name, col_data in node_data.columns.items():
48
- current_col_id = f"{node_id}_{col_name}"
49
-
50
- for dep in col_data.depends_on:
51
- dep_col_id = f"{dep.node}_{dep.column}"
52
-
53
- if current_col_id not in parent_map:
54
- parent_map[current_col_id] = set()
55
- parent_map[current_col_id].add(dep_col_id)
56
-
57
- if dep_col_id not in child_map:
58
- child_map[dep_col_id] = set()
59
- child_map[dep_col_id].add(current_col_id)
60
-
61
- for dep in node_data.depends_on.columns:
62
- dep_col_id = f"{dep.node}_{dep.column}"
63
-
64
- if node_id not in parent_map:
65
- parent_map[node_id] = set()
66
- parent_map[node_id].add(dep_col_id)
67
-
68
- if dep_col_id not in child_map:
69
- child_map[dep_col_id] = set()
70
- child_map[dep_col_id].add(node_id)
71
-
72
- return parent_map, child_map
42
+ def find_column_dependencies(node_column_id: str, parent_map: Dict, child_map: Dict) -> Tuple[Set, Set]:
43
+ upstream_cols = find_upstream(node_column_id, parent_map)
44
+ downstream_cols = find_downstream(node_column_id, child_map)
45
+ return upstream_cols, downstream_cols
73
46
 
74
47
 
75
- def find_column_dependencies(node_id: str, node_column_id: str, parent_map: Dict, child_map: Dict) -> Tuple[Set, Set]:
76
- upstream_cols = set()
77
- downstream_cols = set()
78
- upstream_cols.update(find_upstream(node_id, parent_map), find_upstream(node_column_id, parent_map))
79
- downstream_cols.update(find_downstream(node_id, child_map), find_downstream(node_column_id, child_map))
48
+ def filter_lineage_vertices(
49
+ lineage_nodes: Dict[str, CllNode], lineage_columns: Dict[str, CllColumn], relevant_columns: Set[str]
50
+ ) -> Tuple[Dict[str, CllNode], Dict[str, CllColumn]]:
51
+ nodes = {}
52
+ columns = {}
80
53
 
81
- return upstream_cols, downstream_cols
54
+ for node_id, node in lineage_nodes.items():
55
+ if node_id in relevant_columns:
56
+ nodes[node_id] = node
82
57
 
58
+ for col_id, column in lineage_columns.items():
59
+ if col_id in relevant_columns:
60
+ columns[col_id] = column
83
61
 
84
- def filter_column_lineage(cll_data: CllData, relevant_columns: Set) -> CllData:
62
+ return nodes, columns
85
63
 
86
- for node_id, node_obj in cll_data.nodes.items():
87
- filtered_node_columns = {}
88
64
 
89
- for col_name, col_data in node_obj.columns.items():
90
- full_col_id = f"{node_id}_{col_name}"
91
- if full_col_id in relevant_columns:
92
- filtered_node_columns[col_name] = col_data
65
+ def filter_dependency_maps(
66
+ parent_map: Dict, child_map: Dict, relevant_columns: Set
67
+ ) -> Tuple[Dict[str, Set], Dict[str, Set]]:
68
+ p_map = {}
69
+ c_map = {}
70
+ for node_id, parents in parent_map.items():
71
+ if node_id in relevant_columns:
72
+ p_map[node_id] = {p for p in parents if p in relevant_columns}
93
73
 
94
- node_obj.columns = filtered_node_columns
95
- node_obj.depends_on.columns = [
96
- dep for dep in node_obj.depends_on.columns if f"{dep.node}_{dep.column}" in relevant_columns
97
- ]
74
+ for node_id, children in child_map.items():
75
+ if node_id in relevant_columns:
76
+ c_map[node_id] = {c for c in children if c in relevant_columns}
98
77
 
99
- return cll_data
78
+ return p_map, c_map
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: recce-nightly
3
- Version: 1.8.0.20250615
3
+ Version: 1.8.0.20250617
4
4
  Summary: Environment diff tool for dbt
5
5
  Home-page: https://github.com/InfuseAI/recce
6
6
  Author: InfuseAI Dev Team
@@ -1,7 +1,7 @@
1
- recce/VERSION,sha256=7IecPgA3NrCUcIa006n43Xzkir-0PnbXZfU3-vxCAc0,15
1
+ recce/VERSION,sha256=ltz6cUsgm5IBGWDn7lThqfQs2lJBUdcQZtAydHsu2-Y,15
2
2
  recce/__init__.py,sha256=yNb0QT-yoStex0VZALNJvUwtPLommoVCStcow31guqo,2392
3
3
  recce/artifact.py,sha256=tKQAHSrLRjiR3ppOI4sym8SxYiiLTuD3DPMYh4DWQdA,6506
4
- recce/cli.py,sha256=hNUy20Yk5e_iDv_gpCJ6LI5q3SzKZPAd3LQ-UNw1CcU,39725
4
+ recce/cli.py,sha256=bhnVGR7K6cU3tyP-GbX2QHJgi4gFX_5xH4XqKWOOSY0,39710
5
5
  recce/config.py,sha256=fs22mpFj8CFIxftGbhFAV5xIsPLX2xNTwWSer3UYn5k,4658
6
6
  recce/core.py,sha256=3Nv2QWBGz3yj1QI0wyPNRaDj1rH80DsX2qRQn9ydpg0,10747
7
7
  recce/diff.py,sha256=L2_bzQ3__PO-0aeir8PHF8FvSOUmQ8WcDXgML1-mHdY,748
@@ -10,60 +10,60 @@ recce/git.py,sha256=8Eg-6NzL-KjA3rT-ibbAyaCwGlzV0JqH3yGikrJNMDA,2344
10
10
  recce/github.py,sha256=PEpM6ZRiinsPbXSWj4aJCKbZrN1jUXzpzAfJq_CGah4,7420
11
11
  recce/pull_request.py,sha256=aW0B1NE2LUKTam1S4TQ7smXB9KLE1DV8GnyBqNXA6j8,3832
12
12
  recce/run.py,sha256=LAjbWUF8loZ9cL25d_maQELwROHHmfaFn7iqFRy5O1o,13567
13
- recce/server.py,sha256=7m75CWfPqhb1IQp-23tv3Me-KSvL82ZLVoPInd_3_Pw,20240
13
+ recce/server.py,sha256=Nr5y4jTk4CnHCTtcPHdJkWXjRybmSYBFAmxJ1t74Zlg,20667
14
14
  recce/state.py,sha256=VPzKyEdmyBeZ45BQArB587QN5C3Sfr7O5Oh_JRBcKrc,30616
15
15
  recce/summary.py,sha256=Mbxvxr9KazR5o9icqhhjiGHsoAiWxQU4PdN7HytBJ1c,19154
16
16
  recce/adapter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  recce/adapter/base.py,sha256=T_JNeLHgiHSaegw-DbrvHOaYjMyZcjj2Qtg5cWh_fco,3548
18
18
  recce/adapter/sqlmesh_adapter.py,sha256=IU3N-F6ToDoO7_bV5vsG8pmTuDcbFtewTIuCxedTaRM,5046
19
- recce/adapter/dbt_adapter/__init__.py,sha256=YZP9odKH2_wAQ1BAzp_QqMGemvyM9tYdKtkDuab7Yr0,55401
19
+ recce/adapter/dbt_adapter/__init__.py,sha256=Bnh-6ZRO5k1yxJxjGJcf50NcMMTe6or2DoLaeFFMaZM,60211
20
20
  recce/adapter/dbt_adapter/dbt_version.py,sha256=M7aedZIWslXnJsryK8Ki4OL_t2oAKxy4uE2pRwfWIkk,1228
21
21
  recce/apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  recce/apis/check_api.py,sha256=KMCXSMl1qqzx2jQgRqCrD4j_cY3EHBbM3H2-t-6saAU,6227
23
23
  recce/apis/check_func.py,sha256=gktbCcyk3WGvWRJJ-wDnwv7NrIny2nTHWLl1-kdiVRo,4183
24
24
  recce/apis/run_api.py,sha256=eOaxOxXDkH59uqGCd4blld7edavUx7JU_DCd2WAYrL8,3416
25
25
  recce/apis/run_func.py,sha256=6wC8TDU-h7TLr2VZH7HNsWaUVlQ9HBN5N_dwqfi4lMY,7440
26
- recce/data/404.html,sha256=LJv_Ln4ywc1yf-orq68PMUA20TB_Iwt2mbQED0IG42Q,26579
26
+ recce/data/404.html,sha256=1c7f-iNoRD9q5VGjCnxXSo4iyaxKEds_H4YejuZNeiE,26577
27
27
  recce/data/favicon.ico,sha256=B2mBumUOnzvUrXrqNkrc5QfdDXjzEXRcWkWur0fJ6sM,2565
28
- recce/data/index.html,sha256=yx9Po-NfO2ddQG9FmdfhO8SF8IQEcYvTHv2s93iQcQQ,42162
29
- recce/data/index.txt,sha256=KGPkwzrbBkZL3Rqy3lGbh5FNgDfGD_HFxUolpoJOuy8,4469
30
- recce/data/_next/static/chunks/0d0b8943-1c8ef4728d0e645b.js,sha256=wJfK5fVnS1kuhkU9mpzg9BPhdc2UUIOqqVchtaMU-PA,172837
31
- recce/data/_next/static/chunks/184-dc0879f75e9506c3.js,sha256=D60eEdD_Oqlk2CtuvIknSQOiJ1vNkZqVZ32HUdwnouw,97873
32
- recce/data/_next/static/chunks/1bff33f1-39d26ad38ba4fe06.js,sha256=ldwDhIDmr8JhhNm6xffwe0HEm4Xs4e9lDkwTWKxJW7E,153777
33
- recce/data/_next/static/chunks/249-aeaf2fd44b7d8946.js,sha256=v3k00CqJya4YSPVP3eLVLGn090jmPM-xJLHaq9sgdVM,72737
34
- recce/data/_next/static/chunks/29e3cc0d-e95ebef603672925.js,sha256=fMLYhtqIaY8Y-65IUcOuf8QzUOeAUnRMZYtyMjGMUi8,699
35
- recce/data/_next/static/chunks/33-27f5a26fea26baf4.js,sha256=021bnyupb0khZYiEeMFLCKqhv9UaD_jTHqNBDaZEDWI,318315
36
- recce/data/_next/static/chunks/36e1c10d-6d59e8aae9eec8b4.js,sha256=qaqfFeBs_fSPdy7XMT_g6ZS362JYCpn8hjvh4CD_NbU,7796
37
- recce/data/_next/static/chunks/3998a672-0426e04aa28a4198.js,sha256=lyHK4acPVxj-GJrdSgZZxaqvWcRfg9yC0zNjNqglAiE,9023
38
- recce/data/_next/static/chunks/3a92ee20-146003bc9f4294f5.js,sha256=HNoR4Pp3onvRGGztPprP9Mo6abFq03IE-dfDAUOcFcQ,177688
39
- recce/data/_next/static/chunks/42-3dc869b8f2a75e9c.js,sha256=Swc-KpLJQsFi4cPoVeXRQKXW8j7uqIv3rw4J4Z1z930,124111
40
- recce/data/_next/static/chunks/450c323b-3dd665b028d8e184.js,sha256=usaI26FZT18CUleDN83JouuucTe-kBVMg9y-CoAQfDI,2204
41
- recce/data/_next/static/chunks/47d8844f-57ea99282765dce5.js,sha256=ZBP3mKQm5mctHkIjt6cgvFk-Z_f7TveERLgLgb0Zrfc,696
42
- recce/data/_next/static/chunks/627-1b5619ef0c492f2b.js,sha256=fYfdqv6N2isEEF79USUsUZckuDbHbTrOGYBCc2IOAoY,1032342
43
- recce/data/_next/static/chunks/6dc81886-e6963cc22929fc61.js,sha256=USEm9yAWLQVic4O5MrSw_vp94e1Z0HUOkB0lIxLPz40,69733
44
- recce/data/_next/static/chunks/7a8a3e83-933490bb996ac49b.js,sha256=c73gEwdhLgIXNLLFnHKfyURi2wL-SKnD8-3voJilWnw,1648
45
- recce/data/_next/static/chunks/7f27ae6c-f6aa983aa05b83cd.js,sha256=EeGyzRHP1SMg45f08C_GkOICZaQz_olnhHdEsBxbqCc,778
46
- recce/data/_next/static/chunks/8d700b6a.ebb3dd15a8cd3f2b.js,sha256=kwUCVyEdI_dpwJ6TqjjMvv5bd3nJixHpk2wJPsTI044,119972
47
- recce/data/_next/static/chunks/9746af58-ac9a4d1b8160c197.js,sha256=QV1lcwNPwDPwLsM-cooCF2wr_Cp_pG7K4Ry1LvWhcPM,4176
48
- recce/data/_next/static/chunks/a30376cd-2d324b6b8687d57b.js,sha256=dH9sHqNXj7rNK-HuxWJ2FoTXWXTSy1Mw_mnv3-ftSsw,863
49
- recce/data/_next/static/chunks/b63b1b3f-a380b9fe5be938d3.js,sha256=cf7v4ob8f_rtz4-bWeyO6e5Px1j8-bYsr-spQD3Jd40,571
50
- recce/data/_next/static/chunks/bbda5537-10da060bd56d475e.js,sha256=BVXrVyAg9_ZkC81aZTtzrZPomnugTM86DhcSjb44ccg,81302
51
- recce/data/_next/static/chunks/c132bf7d-d6e713672e7030a1.js,sha256=HbBkA5h5WtWtdhCplPwlIjGFCwZnscm7IOs5khmcLiY,198537
52
- recce/data/_next/static/chunks/ce84277d-7f0a33888bf731d9.js,sha256=Ter45PzyhQO8CNpPO3_cVQPC1HxKK4xcyiUKPtmZFUQ,2561
53
- recce/data/_next/static/chunks/febdd86e-d96ff090bf0a928d.js,sha256=FVzg7y7YkF9zQQQkItYkIayqajqpMdCS0oENl1CdcIA,82989
54
- recce/data/_next/static/chunks/fee69bc6-288939bd73e3e49c.js,sha256=aVHqK-GHhnM1mqvF644SX9sw9BMM-PjpBi4JrVBEkeY,483
28
+ recce/data/index.html,sha256=OMtlf-j5V6bVQ9RAWC_npvLwTTUtccb2NKsC1QZ5YcI,42160
29
+ recce/data/index.txt,sha256=QYVG1wCI3SGWpuAj_FuvoWgp07qX3LJsM68RLP0v9sQ,4466
30
+ recce/data/_next/static/6pJWLeTWseySFL3ozLQBi/_buildManifest.js,sha256=sjy6FmOqWlkXWmod2oXwqKv7L582_MTycs9THCE6G-c,224
31
+ recce/data/_next/static/6pJWLeTWseySFL3ozLQBi/_ssgManifest.js,sha256=Z49s4suAsf5y_GfnQSvm4qtq2ggxEbZPfEDTXjy6XgA,80
32
+ recce/data/_next/static/chunks/1bff33f1-1ef85cf5e658a751.js,sha256=wTH-_PbE1XdP-wmGaQStF5y2yH6XcZXeYX_hDaGMfh4,153777
33
+ recce/data/_next/static/chunks/217-879a84d70f7a907c.js,sha256=kNJkLcwaIlWnQY7akbrFimbcHHdK6lMVTbTYCNKXIjc,124102
34
+ recce/data/_next/static/chunks/29e3cc0d-60045b2e47aa3916.js,sha256=2MNGdoQ0DUmEJz-JdcgJVIPDdaVHp2963E0luqJ-TTE,700
35
+ recce/data/_next/static/chunks/36e1c10d-35e36448f4f83961.js,sha256=c1opscOEnObn5EMLvhl4Z__wL2-4ALEuKIhZSJK4YT0,7797
36
+ recce/data/_next/static/chunks/3998a672-03adacad07b346ac.js,sha256=yIo9J3TT-1rQQISuIbB_ZYdI952YiOazkpiXxkza6tI,9023
37
+ recce/data/_next/static/chunks/3a92ee20-1081c360214f9602.js,sha256=-XiclPOo-Au8pcnledxOGxajRoYoJ-4rtBdJ7kHZNN8,177688
38
+ recce/data/_next/static/chunks/450c323b-fd94e7ffaa4a5efa.js,sha256=9msncqWrh8MQrmXLZEA9W2_5WZP4Fmvlaw9Vrv737XI,2205
39
+ recce/data/_next/static/chunks/47d8844f-929aed9b1c73a905.js,sha256=VIKCVeheQGrNsNkyF6agc_38Yess4KJsFJz8Vbe598U,697
40
+ recce/data/_next/static/chunks/608-3b079b544e5d5f5e.js,sha256=uvQzpIdvupXx_k2aIX4C-KfP4QEXqlbHuP6XNQVK-0s,97872
41
+ recce/data/_next/static/chunks/6dc81886-adbfa45836061d79.js,sha256=9X1H0RjERGExNdWSzbslObd050Iwd8bqTJQuuGW6wq4,69733
42
+ recce/data/_next/static/chunks/7a8a3e83-edf6dc64b5d5f0a5.js,sha256=NfgBK9op5SzWm4Ehg1xI-_HChQuqosdklsifGTNH-rE,1649
43
+ recce/data/_next/static/chunks/7f27ae6c-d5f0438edd5c2a5b.js,sha256=ewMLioJbTUUDeqV0J9NDKE0Bj-XCFg8QqMLOmLPgpcc,777
44
+ recce/data/_next/static/chunks/826-1fdc111c49b34b0f.js,sha256=tCBVOyBAFUDLd9iv1xyTk3hDGMSvkbtHAnaHizxp27s,318338
45
+ recce/data/_next/static/chunks/86730205-cfb14e3f051bab35.js,sha256=qKkzgWsNqSrn-PUGBloZopIlacGCy8hH0BZA9tpqQoQ,172837
46
+ recce/data/_next/static/chunks/8d700b6a.8bb140898499c512.js,sha256=NPGWvqv8Y_rbNaKxYnoq16mi6FDoQHxOOjpH4tJnUkE,119972
47
+ recce/data/_next/static/chunks/92-bd5f33f1c3cb9d93.js,sha256=lPlEl2V4L8SFEfwNRYfZKj5CvHZDu_Otubu2Du6anXA,71799
48
+ recce/data/_next/static/chunks/960-49d66f0cbac6af8a.js,sha256=oFMSQdXW5b9pXz_QcTAZ8JWgSYcI9Ac3VjeDlSSEYD0,1032469
49
+ recce/data/_next/static/chunks/9746af58-a42b7d169cacadf0.js,sha256=lV-V6BYpd4HEt-pFtT03G6qQD2Wa-2L_jp6aH9VgoeM,4177
50
+ recce/data/_next/static/chunks/a30376cd-de84559016d7e133.js,sha256=qzgyjrX5PdPKGeSwb-Gh0RfM_NEF2zjMvMK14ixq228,864
51
+ recce/data/_next/static/chunks/b63b1b3f-4282bdcf459e075c.js,sha256=s2EZ59zDBJDmy2kh0cHkQ_pAWxiQr_yCPlnttCj0x_k,572
52
+ recce/data/_next/static/chunks/bbda5537-9ec25eb1dd62348a.js,sha256=jB7gyvrur-GMqD3Yi2X6jiFfFGCb0_zYyxJJXrh3mpw,81301
53
+ recce/data/_next/static/chunks/c132bf7d-08cb668a789d6afd.js,sha256=bvbKe0denpFS_bPYD58ip9TE5OSooIZNrog39AWjf_I,198536
54
+ recce/data/_next/static/chunks/ce84277d-2e5d1d46910cf052.js,sha256=uv79hdbY7j79k4hQQDiz9OAML-RqZRj8N3-SBFV17-k,2562
55
+ recce/data/_next/static/chunks/febdd86e-c6b525341634b860.js,sha256=DYG6gZ6Ia5VLZRGYgJHZz28_Eie9eyIctRcmGBQuVTY,82988
56
+ recce/data/_next/static/chunks/fee69bc6-2dbccaf9b90474e6.js,sha256=kN9jpjqnvfPqP_00RVf0CdWLTGnU1HEAYxjPuXca_Pk,484
55
57
  recce/data/_next/static/chunks/framework-ded83d71b51ce901.js,sha256=0Xsxxnmw5fjRHz8ni6vlaF9tQjfjNGZcZv2oMy7A_T4,140000
56
- recce/data/_next/static/chunks/main-0276cd0c41be4ef4.js,sha256=yYylI8WZkb7-WlJiDWA69arnflnMoGujcHOiyVlPQ6A,116699
57
- recce/data/_next/static/chunks/main-app-2e08b38d48f6a731.js,sha256=47lP340M-JgQlFo11BlranOv2uvmXZmI31aHp4qDSKo,471
58
+ recce/data/_next/static/chunks/main-app-39061b0166c47f55.js,sha256=NE6gZMaxmkLWS-unRTaSJm_1GGGb5ld-TP7UQMot2TY,471
59
+ recce/data/_next/static/chunks/main-b5b3ae20a1405261.js,sha256=28hJH2VsiTdxZGZrQsyRO-YBwfgJArUHYGGuy7ZAD7s,116715
58
60
  recce/data/_next/static/chunks/polyfills-42372ed130431b0a.js,sha256=CXPB1kyIrcjjyVBBDLWLKI9yEY1ZZbeASUON648vloM,112594
59
- recce/data/_next/static/chunks/webpack-c84693803e08b48b.js,sha256=Dx_RNi9iE-d0yqI7gDLVTB2V5-_ks0gwNHxe_TCxTws,3927
60
- recce/data/_next/static/chunks/app/layout-83da1e1a59dea607.js,sha256=yPuKDmW2hynBXPfGl7xpq7H4ZOBQo1gLFFmR-Cdj5o8,1730
61
- recce/data/_next/static/chunks/app/page-3404ed4ba8cffb0b.js,sha256=ok6bYpSlaNPYCUMDWEq2zCGWZO-fp5B1xgfXNauM6eg,162614
62
- recce/data/_next/static/chunks/app/_not-found/page-2ab757d7e27193ec.js,sha256=RVYek09PLFETVLlmOwsUytWhwqXTtx9_-FgPjXFoKEg,1750
63
- recce/data/_next/static/chunks/pages/_app-ddb94f741a61a490.js,sha256=sdivRkiwP7Bf9PFMifsTBtl-NEjsdw7NpZLhVmcz7_g,284
64
- recce/data/_next/static/chunks/pages/_error-9e738ac1fd923095.js,sha256=kG9SrMKWvc7Zab2qq-836dxyQ99IzsywmSR8NdB8DcY,249
65
- recce/data/_next/static/clUnQD2xUsy2WK43RKblq/_buildManifest.js,sha256=RtyFkoNcorOw40S27S4Dvq7EWYCPgIlcyfK1fypRxkY,224
66
- recce/data/_next/static/clUnQD2xUsy2WK43RKblq/_ssgManifest.js,sha256=Z49s4suAsf5y_GfnQSvm4qtq2ggxEbZPfEDTXjy6XgA,80
61
+ recce/data/_next/static/chunks/webpack-7b49d5ba7e3a434d.js,sha256=lcK59Juk4EZqi3jIsY35lQqAlB5TLTPy-neri0BIZL0,3929
62
+ recce/data/_next/static/chunks/app/layout-af033601bf81ed53.js,sha256=oPbgXJeb1DX635Agej8yYBLrKfxBMUJ5eFfAW25mO2k,1732
63
+ recce/data/_next/static/chunks/app/page-f1048e1fe24111f8.js,sha256=YXFPkh3WZcUipO1WypRn8HWxJDI2mp3Gc8WL3RuUo2Y,162655
64
+ recce/data/_next/static/chunks/app/_not-found/page-01ed58b7f971d311.js,sha256=_l3JSAaIJxInWqyqdDsobkhJ3JP6DZuwXkw-MsRakQA,1751
65
+ recce/data/_next/static/chunks/pages/_app-437c455677d62394.js,sha256=FaxURD1wuAmnMU1zJlsQKT9rRdfuspR7yx7BckcoCLY,284
66
+ recce/data/_next/static/chunks/pages/_error-e7650df18ca04bde.js,sha256=0Vzx_hCqw4RcptsFzHfUigpI13sToBnFw38owTP7ruo,250
67
67
  recce/data/_next/static/css/17a96168e3a9db13.css,sha256=aojwuNbF38RSCVYal2iL4Qkz6jsO0FNEs6qfeYwXY5k,1205
68
68
  recce/data/_next/static/css/1b121dc4d36aeb4d.css,sha256=fJcUlx0zOECmST2uFkAB-VzBrp53E-5KEShUcnO16aE,7949
69
69
  recce/data/_next/static/css/35c6679a098e1e34.css,sha256=VaNEUFJj9NKOihehwlAgzdPRbmww7bi0xKh8hRfxhn0,12706
@@ -91,7 +91,7 @@ recce/event/track.py,sha256=xDyDWblhR6mp0tezEYhkA0aOyZLqXBpJyHZwhI2xhU8,4803
91
91
  recce/models/__init__.py,sha256=F7cgALtdWnwv37R0eEgKZ_yBsMwxWnUfo3jAZ3u6qyU,209
92
92
  recce/models/check.py,sha256=jjR1SGyczjrqyK-0Zas6ikLIGSgVp54lvfcQA19AniI,1588
93
93
  recce/models/run.py,sha256=QK2gvOWvko9YYhd2NLs3BPt5l4MSCZGwpzTAiqx9zJw,1161
94
- recce/models/types.py,sha256=ljRKqaTMpKD9gi_8NnVFvtR2XNOBiQy5PgRbdnnfKiQ,4253
94
+ recce/models/types.py,sha256=g4w5RNNeeNRUDyLWd1Sqv7wPvt0ue4d0-_-KZ585GJI,4193
95
95
  recce/tasks/__init__.py,sha256=b553AtDHjYROgmMePv_Hv_X3fjh4iEn11gzzpUJz6_o,610
96
96
  recce/tasks/core.py,sha256=JFYa1CfgOiRPQ7KVTwMuxJjhMB-pvCwB-xezVt-h3RU,4080
97
97
  recce/tasks/dataframe.py,sha256=03UBWwt0DFTXlaEOtnV5i_mxdRKD7UbRayewEL2Ub48,3650
@@ -109,13 +109,13 @@ recce/util/breaking.py,sha256=evT-xlDWMgIbuPQH6w5yNoDjOqopKzBXnCF9_xTn1S0,12591
109
109
  recce/util/cache.py,sha256=QB6wzxe0M3jNTwP0M27Ys8F2hF-oda4-LyXXG9THuZQ,646
110
110
  recce/util/cll.py,sha256=VXhtyoPIcPEW3_SmNUTbZWwOmmv8_JRfAB9CLJ4S2Wg,13315
111
111
  recce/util/io.py,sha256=fNiIafNxPlTF6NNXlugzeJjfVGGrP3RXb39ERzRWD3Q,3459
112
- recce/util/lineage.py,sha256=XQy6dE-9qzmcTLoPqqx5YyyVRS0wNFCNmeIGMh7MlsE,2962
112
+ recce/util/lineage.py,sha256=IF1CNrYt0u_bNkB4XQaueteD1JqGKDEnNQV-Qba26ZE,2090
113
113
  recce/util/logger.py,sha256=6UgLFkRiur9jJfu2ZRdo4LUvMw4f75V-l-1HT1-sgKo,747
114
114
  recce/util/pydantic_model.py,sha256=KumKuyCjbTzEMsKLE4-b-eZfp0gLhYDdmVtw1-hxiJw,587
115
115
  recce/util/recce_cloud.py,sha256=g7uhWkknR9ulTuGxaz14erOGiUwIv3q3C0mfCEG3gl8,7925
116
116
  recce/util/singleton.py,sha256=1cU99I0f9tjuMQLMJyLsK1oK3fZJMsO5-TbRHAMXqds,627
117
117
  recce/yaml/__init__.py,sha256=EgXYlFeJZchatUClRDXbIC5Oqb2_nBvB2NqItYVihio,1292
118
- recce_nightly-1.8.0.20250615.dist-info/licenses/LICENSE,sha256=CQjjMy9aYPhfe8xG_bcpIfKtNkdxLZ5IOb8oPygtUhY,11343
118
+ recce_nightly-1.8.0.20250617.dist-info/licenses/LICENSE,sha256=CQjjMy9aYPhfe8xG_bcpIfKtNkdxLZ5IOb8oPygtUhY,11343
119
119
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
120
120
  tests/test_cli.py,sha256=_ikuZW4bYEGyj5A_V7nDSyBa1tVZqc0TVm-TJ0rEYVo,5467
121
121
  tests/test_config.py,sha256=ODDFe_XF6gphmSmmc422dGLBaCCmG-IjDzTkD5SJsJE,1557
@@ -130,7 +130,7 @@ tests/adapter/dbt_adapter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
130
130
  tests/adapter/dbt_adapter/conftest.py,sha256=WlMVytJcyfLJlMBeYhpk8Q-nyCDR9x_7qgsy6Uh9ECw,386
131
131
  tests/adapter/dbt_adapter/dbt_test_helper.py,sha256=o_7m0cnVeGwPwEFXBCx3Me5QqLzQMOBR3dXD-MS2eaM,10406
132
132
  tests/adapter/dbt_adapter/test_dbt_adapter.py,sha256=Y5TSlqkXGjJC6hC7YYs45bnRht5aou_KLjPMjpAGxNM,830
133
- tests/adapter/dbt_adapter/test_dbt_cll.py,sha256=nJySbczrcr7Gbq4wGwC-HCYzOXybukeNc1JjOmKWY7E,9191
133
+ tests/adapter/dbt_adapter/test_dbt_cll.py,sha256=W3VKg6GKUMGyR_qomwbOpVcSyOTpYBb_KMhS4NfGvS8,14249
134
134
  tests/adapter/dbt_adapter/test_selector.py,sha256=uKFm0QxrxG-xyUEXGobCMueCRUssgnZMyo-S1Nlk3_s,6856
135
135
  tests/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
136
136
  tests/tasks/conftest.py,sha256=lyZFx4jEY3To3xVhfMQ-G45egYOCttKN2lxeyExACkY,157
@@ -143,8 +143,8 @@ tests/tasks/test_row_count.py,sha256=21PaP2aq-x8-pqwzWHRT1sixhQ8g3CQNRWOZTTmbK0s
143
143
  tests/tasks/test_schema.py,sha256=7ds4Vx8ixaiIWDR49Lvjem4xlPkRP1cXazDRY3roUak,3121
144
144
  tests/tasks/test_top_k.py,sha256=YR_GS__DJsbDlQVaEEdJvNQ3fh1VmV5Nb3G7lb0r6YM,1779
145
145
  tests/tasks/test_valuediff.py,sha256=_xQJGgxsXoy2NYk_Z6Hsw2FlVh6zk2nN_iUueyRN1e8,2046
146
- recce_nightly-1.8.0.20250615.dist-info/METADATA,sha256=EJGVmxmQ7wrrF3vbj-rHuh5m1HlvLd5N6MMOMfA-sj8,9397
147
- recce_nightly-1.8.0.20250615.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
148
- recce_nightly-1.8.0.20250615.dist-info/entry_points.txt,sha256=oqoY_IiwIqXbgrIsPnlqUqao2eiIeP2dprowkOlmeyg,40
149
- recce_nightly-1.8.0.20250615.dist-info/top_level.txt,sha256=6PKGVpf75idP0C6KEaldDzzZUauIxNu1ZDstau1pI4I,12
150
- recce_nightly-1.8.0.20250615.dist-info/RECORD,,
146
+ recce_nightly-1.8.0.20250617.dist-info/METADATA,sha256=4EexyjtFWkNTMBjlAlt7J_i1ljjqLpdwGlwNJG4np6c,9397
147
+ recce_nightly-1.8.0.20250617.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
148
+ recce_nightly-1.8.0.20250617.dist-info/entry_points.txt,sha256=oqoY_IiwIqXbgrIsPnlqUqao2eiIeP2dprowkOlmeyg,40
149
+ recce_nightly-1.8.0.20250617.dist-info/top_level.txt,sha256=6PKGVpf75idP0C6KEaldDzzZUauIxNu1ZDstau1pI4I,12
150
+ recce_nightly-1.8.0.20250617.dist-info/RECORD,,
@@ -3,36 +3,32 @@ from recce.models.types import CllData
3
3
 
4
4
 
5
5
  def assert_column(result: CllData, node_name, column_name, transformation_type, depends_on):
6
- assert result.nodes.get(node_name) is not None, f"Node {node_name} not found in result"
7
- entry = result.nodes[node_name].columns.get(column_name)
8
- assert entry is not None, f"Column {column_name} not found in result"
6
+ column_id = f"{node_name}_{column_name}"
7
+ entry = result.columns.get(column_id)
8
+ assert entry is not None, f"Column {column_id} not found in result"
9
9
  assert (
10
10
  entry.transformation_type == transformation_type
11
11
  ), f"Column {column_name} type mismatch: expected {transformation_type}, got {entry.transformation_type}"
12
- assert len(entry.depends_on) == len(depends_on), "depends_on length mismatch"
12
+ parents = result.parent_map.get(column_id)
13
+
14
+ assert len(parents) == len(depends_on), "depends_on length mismatch"
13
15
  for i in range(len(depends_on)):
14
16
  node, column = depends_on[i]
15
- anode = entry.depends_on[i].node
16
- acolumn = entry.depends_on[i].column
17
+ parent_column_id = f"{node}_{column}"
17
18
 
18
- assert (
19
- anode == node and acolumn == column
20
- ), f"depends_on mismatch at index {i}: expected ({node}, {column}), got ({anode}, {acolumn})"
19
+ assert parent_column_id in parents, f"Column {parent_column_id} not found in {column_id}'s parent list"
21
20
 
22
21
 
23
22
  def assert_model(result: CllData, node_name, depends_on):
24
23
  assert result.nodes.get(node_name) is not None, f"Node {node_name} not found in result"
25
- entry = result.nodes.get(node_name)
26
-
27
- assert len(entry.depends_on.columns) == len(depends_on), "depends_on length mismatch"
24
+ parent_map = result.parent_map.get(node_name)
25
+ assert parent_map is not None, f"Parent map {node_name} not found in result"
26
+ # assert len(parent_map) == len(depends_on), "depends_on length mismatch"
28
27
  for i in range(len(depends_on)):
29
28
  node, column = depends_on[i]
30
- anode = entry.depends_on.columns[i].node
31
- acolumn = entry.depends_on.columns[i].column
29
+ column_id = f"{node}_{column}"
32
30
 
33
- assert (
34
- anode == node and acolumn == column
35
- ), f"depends_on mismatch at index {i}: expected ({node}, {column}), got ({anode}, {acolumn})"
31
+ assert column_id in parent_map, f"Parent map {node_name} does not contain {column_id}"
36
32
 
37
33
 
38
34
  def test_cll_basic(dbt_test_helper):
@@ -186,6 +182,21 @@ def test_model_without_catalog(dbt_test_helper):
186
182
  assert not result.nodes["model1"].columns
187
183
 
188
184
 
185
+ def assert_lineage_model(cll_data: CllData, nodes):
186
+ assert len(nodes) == len(cll_data.nodes), "Model count mismatch"
187
+ for node in nodes:
188
+ assert node in cll_data.nodes, f"Model {node} not found in lineage"
189
+
190
+
191
+ def assert_lineage_column(cll_data: CllData, columns):
192
+ assert len(columns) == len(cll_data.columns), "Column count mismatch"
193
+ for column in columns:
194
+ column_key = f"{column[0]}_{column[1]}"
195
+ assert column_key in cll_data.columns, f"Column {column} not found in lineage"
196
+ assert column[0] == cll_data.columns[column_key].table_id, f"Column {column[0]} node mismatch"
197
+ assert column[1] == cll_data.columns[column_key].name, f"Column {column[1]} name mismatch"
198
+
199
+
189
200
  def test_cll_column_filter(dbt_test_helper):
190
201
  dbt_test_helper.create_model(
191
202
  "model1", unique_id="model.model1", curr_sql="select 1 as c", curr_columns={"c": "int"}
@@ -215,25 +226,159 @@ def test_cll_column_filter(dbt_test_helper):
215
226
  adapter: DbtAdapter = dbt_test_helper.context.adapter
216
227
 
217
228
  result = adapter.get_cll("model.model2", "c")
218
- assert_model(result, "model.model2", [])
219
- assert_column(result, "model.model2", "c", "passthrough", [("model.model1", "c")])
220
- assert_model(result, "model.model4", [])
221
- assert result.nodes.get("model.model4").columns == {}
222
-
223
- result = adapter.get_cll("model.model3", "y")
224
- assert_model(result, "model.model3", [("model.model2", "y")])
225
- assert result.nodes.get("model.model1").columns == {}
226
- assert len(result.nodes.get("model.model2").columns) == 1
229
+ assert_lineage_model(result, [])
230
+ assert_lineage_column(result, [("model.model1", "c"), ("model.model2", "c"), ("model.model3", "c")])
227
231
 
228
232
  result = adapter.get_cll("model.model2", "y")
229
- assert_model(result, "model.model3", [("model.model2", "y")])
230
- assert result.nodes.get("model.model3").columns == {}
231
- assert result.nodes.get("model.model1").columns == {}
232
- assert len(result.nodes.get("model.model2").columns) == 1
233
+ assert_lineage_model(result, ["model.model3"])
234
+ assert_lineage_column(result, [("model.model2", "y"), ("model.model4", "y")])
233
235
 
234
236
  result = adapter.get_cll("model.model3", "c")
235
- assert_model(result, "model.model3", [("model.model2", "y")])
236
- assert_column(result, "model.model3", "c", "passthrough", [("model.model2", "c")])
237
- assert_model(result, "model.model2", [])
238
- assert_column(result, "model.model2", "c", "passthrough", [("model.model1", "c")])
239
- assert_column(result, "model.model1", "c", "source", [])
237
+ assert_lineage_model(result, [])
238
+ assert_lineage_column(result, [("model.model1", "c"), ("model.model2", "c"), ("model.model3", "c")])
239
+
240
+
241
+ def test_impact_radius_nodes(dbt_test_helper):
242
+ # non-breaking
243
+ dbt_test_helper.create_model(
244
+ "model1",
245
+ unique_id="model.model1",
246
+ curr_sql="select 1 as c",
247
+ base_sql="select 1 as c --- non-breaking",
248
+ curr_columns={"c": "int"},
249
+ base_columns={"c": "int"},
250
+ )
251
+ # breaking
252
+ dbt_test_helper.create_model(
253
+ "model2",
254
+ unique_id="model.model2",
255
+ curr_sql='select c, 2025 as y from {{ ref("model1") }}',
256
+ base_sql='select c, 2025 as y from {{ ref("model1") }} where c > 0 --- breaking',
257
+ curr_columns={"c": "int", "y": "int"},
258
+ base_columns={"c": "int", "y": "int"},
259
+ depends_on=["model.model1"],
260
+ )
261
+ dbt_test_helper.create_model(
262
+ "model3",
263
+ unique_id="model.model3",
264
+ curr_sql='select c from {{ ref("model2") }} where y < 2025',
265
+ base_sql='select c from {{ ref("model2") }} where y < 2025',
266
+ curr_columns={"c": "int"},
267
+ base_columns={"c": "int"},
268
+ depends_on=["model.model2"],
269
+ )
270
+ dbt_test_helper.create_model(
271
+ "model4",
272
+ unique_id="model.model4",
273
+ curr_sql='select y from {{ ref("model2") }}',
274
+ base_sql='select y from {{ ref("model2") }}',
275
+ curr_columns={"y": "int"},
276
+ base_columns={"y": "int"},
277
+ depends_on=["model.model2"],
278
+ )
279
+
280
+ adapter: DbtAdapter = dbt_test_helper.context.adapter
281
+
282
+ # breaking
283
+ result = adapter.get_impacted_nodes("model.model2")
284
+ assert_lineage_model(result, ["model.model2", "model.model3", "model.model4"])
285
+
286
+ # non-breaking
287
+ result = adapter.get_impacted_nodes("model.model1")
288
+ assert_lineage_model(result, [])
289
+
290
+
291
+ def test_impact_radius_columns(dbt_test_helper):
292
+ # added column
293
+ dbt_test_helper.create_model(
294
+ "model1",
295
+ unique_id="model.model1",
296
+ curr_sql="select 1 as c, 2 as d --- add d",
297
+ base_sql="select 1 as c",
298
+ curr_columns={"c": "int", "d": "int"},
299
+ base_columns={"c": "int"},
300
+ )
301
+ # modified column
302
+ dbt_test_helper.create_model(
303
+ "model2",
304
+ unique_id="model.model2",
305
+ curr_sql='select c, 2024 as y from {{ ref("model1") }} --- modify y',
306
+ base_sql='select c, 2025 as y from {{ ref("model1") }}',
307
+ curr_columns={"c": "int", "y": "int"},
308
+ base_columns={"c": "int", "y": "int"},
309
+ depends_on=["model.model1"],
310
+ )
311
+ dbt_test_helper.create_model(
312
+ "model3",
313
+ unique_id="model.model3",
314
+ curr_sql='select c from {{ ref("model2") }} where y < 2025',
315
+ base_sql='select c from {{ ref("model2") }} where y < 2025',
316
+ curr_columns={"c": "int"},
317
+ base_columns={"c": "int"},
318
+ depends_on=["model.model2"],
319
+ )
320
+ dbt_test_helper.create_model(
321
+ "model4",
322
+ unique_id="model.model4",
323
+ curr_sql='select y from {{ ref("model2") }}',
324
+ base_sql='select y from {{ ref("model2") }}',
325
+ curr_columns={"y": "int"},
326
+ base_columns={"y": "int"},
327
+ depends_on=["model.model2"],
328
+ )
329
+
330
+ adapter: DbtAdapter = dbt_test_helper.context.adapter
331
+
332
+ result = adapter.get_impacted_cll("model.model2")
333
+ assert_lineage_model(result, ["model.model3"])
334
+ assert_lineage_column(result, [("model.model2", "y"), ("model.model4", "y")])
335
+
336
+ result = adapter.get_impacted_cll("model.model1")
337
+ assert_lineage_model(result, [])
338
+ assert_lineage_column(result, [("model.model1", "d")])
339
+
340
+
341
+ def test_impact_radius(dbt_test_helper):
342
+ # added column
343
+ dbt_test_helper.create_model(
344
+ "model1",
345
+ unique_id="model.model1",
346
+ curr_sql="select 1 as c, 2 as d --- add d",
347
+ base_sql="select 1 as c",
348
+ curr_columns={"c": "int", "d": "int"},
349
+ base_columns={"c": "int"},
350
+ )
351
+ # breaking, added column, modified column
352
+ dbt_test_helper.create_model(
353
+ "model2",
354
+ unique_id="model.model2",
355
+ curr_sql='select c, 2024 as y, d from {{ ref("model1") }} --- modify y, add d',
356
+ base_sql='select c, 2025 as y from {{ ref("model1") }} where c > 0 --- breaking',
357
+ curr_columns={"c": "int", "y": "int", "d": "int"},
358
+ base_columns={"c": "int", "y": "int"},
359
+ depends_on=["model.model1"],
360
+ )
361
+ dbt_test_helper.create_model(
362
+ "model3",
363
+ unique_id="model.model3",
364
+ curr_sql='select c from {{ ref("model2") }} where y < 2025',
365
+ base_sql='select c from {{ ref("model2") }} where y < 2025',
366
+ curr_columns={"c": "int"},
367
+ base_columns={"c": "int"},
368
+ depends_on=["model.model2"],
369
+ )
370
+ dbt_test_helper.create_model(
371
+ "model4",
372
+ unique_id="model.model4",
373
+ curr_sql='select y from {{ ref("model2") }}',
374
+ base_sql='select y from {{ ref("model2") }}',
375
+ curr_columns={"y": "int"},
376
+ base_columns={"y": "int"},
377
+ depends_on=["model.model2"],
378
+ )
379
+
380
+ adapter: DbtAdapter = dbt_test_helper.context.adapter
381
+
382
+ result = adapter.get_impact_radius("model.model2")
383
+ assert_lineage_model(result, ["model.model2", "model.model3", "model.model4"])
384
+ assert_lineage_column(result, [("model.model2", "d"), ("model.model2", "y"), ("model.model4", "y")])