sqlmesh 0.186.2.dev17__py3-none-any.whl → 0.186.2.dev19__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.
sqlmesh/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.186.2.dev17'
21
- __version_tuple__ = version_tuple = (0, 186, 2, 'dev17')
20
+ __version__ = version = '0.186.2.dev19'
21
+ __version_tuple__ = version_tuple = (0, 186, 2, 'dev19')
sqlmesh/lsp/main.py CHANGED
@@ -279,21 +279,31 @@ class SQLMeshLanguageServer:
279
279
  raise RuntimeError(f"No context found for document: {document.path}")
280
280
 
281
281
  references = get_references(self.lsp_context, uri, params.position)
282
- return [
283
- types.LocationLink(
284
- target_uri=reference.uri,
285
- target_selection_range=types.Range(
282
+ location_links = []
283
+ for reference in references:
284
+ # Use target_range if available (for CTEs), otherwise default to start of file
285
+ if reference.target_range:
286
+ target_range = reference.target_range
287
+ target_selection_range = reference.target_range
288
+ else:
289
+ target_range = types.Range(
286
290
  start=types.Position(line=0, character=0),
287
291
  end=types.Position(line=0, character=0),
288
- ),
289
- target_range=types.Range(
292
+ )
293
+ target_selection_range = types.Range(
290
294
  start=types.Position(line=0, character=0),
291
295
  end=types.Position(line=0, character=0),
292
- ),
293
- origin_selection_range=reference.range,
296
+ )
297
+
298
+ location_links.append(
299
+ types.LocationLink(
300
+ target_uri=reference.uri,
301
+ target_selection_range=target_selection_range,
302
+ target_range=target_range,
303
+ origin_selection_range=reference.range,
304
+ )
294
305
  )
295
- for reference in references
296
- ]
306
+ return location_links
297
307
  except Exception as e:
298
308
  ls.show_message(f"Error getting references: {e}", types.MessageType.Error)
299
309
  return []
sqlmesh/lsp/reference.py CHANGED
@@ -6,23 +6,27 @@ from sqlmesh.core.model.definition import SqlModel
6
6
  from sqlmesh.lsp.context import LSPContext, ModelTarget, AuditTarget
7
7
  from sqlglot import exp
8
8
  from sqlmesh.lsp.description import generate_markdown_description
9
+ from sqlglot.optimizer.scope import build_scope
9
10
  from sqlmesh.lsp.uri import URI
10
11
  from sqlmesh.utils.pydantic import PydanticModel
12
+ from sqlglot.optimizer.normalize_identifiers import normalize_identifiers
11
13
 
12
14
 
13
15
  class Reference(PydanticModel):
14
16
  """
15
- A reference to a model.
17
+ A reference to a model or CTE.
16
18
 
17
19
  Attributes:
18
20
  range: The range of the reference in the source file
19
21
  uri: The uri of the referenced model
20
22
  markdown_description: The markdown description of the referenced model
23
+ target_range: The range of the definition for go-to-definition (optional, used for CTEs)
21
24
  """
22
25
 
23
26
  range: Range
24
27
  uri: str
25
28
  markdown_description: t.Optional[str] = None
29
+ target_range: t.Optional[Range] = None
26
30
 
27
31
 
28
32
  def by_position(position: Position) -> t.Callable[[Reference], bool]:
@@ -88,6 +92,7 @@ def get_model_definitions_for_a_path(
88
92
  - Need to normalize it before matching
89
93
  - Try get_model before normalization
90
94
  - Match to models that the model refers to
95
+ - Also find CTE references within the query
91
96
  """
92
97
  path = document_uri.to_path()
93
98
  if path.suffix != ".sql":
@@ -126,66 +131,95 @@ def get_model_definitions_for_a_path(
126
131
  # Find all possible references
127
132
  references = []
128
133
 
129
- # Get SQL query and find all table references
130
- tables = list(query.find_all(exp.Table))
131
- if len(tables) == 0:
132
- return []
133
-
134
134
  with open(file_path, "r", encoding="utf-8") as file:
135
135
  read_file = file.readlines()
136
136
 
137
- for table in tables:
138
- # Normalize the table reference
139
- unaliased = table.copy()
140
- if unaliased.args.get("alias") is not None:
141
- unaliased.set("alias", None)
142
- reference_name = unaliased.sql(dialect=dialect)
143
- try:
144
- normalized_reference_name = normalize_model_name(
145
- reference_name,
146
- default_catalog=lint_context.context.default_catalog,
147
- dialect=dialect,
148
- )
149
- if normalized_reference_name not in depends_on:
150
- continue
151
- except Exception:
152
- # Skip references that cannot be normalized
153
- continue
154
-
155
- # Get the referenced model uri
156
- referenced_model = lint_context.context.get_model(
157
- model_or_snapshot=normalized_reference_name, raise_if_missing=False
158
- )
159
- if referenced_model is None:
160
- continue
161
- referenced_model_path = referenced_model._path
162
- # Check whether the path exists
163
- if not referenced_model_path.is_file():
164
- continue
165
- referenced_model_uri = URI.from_path(referenced_model_path)
166
-
167
- # Extract metadata for positioning
168
- table_meta = TokenPositionDetails.from_meta(table.this.meta)
169
- table_range = _range_from_token_position_details(table_meta, read_file)
170
- start_pos = table_range.start
171
- end_pos = table_range.end
172
-
173
- # If there's a catalog or database qualifier, adjust the start position
174
- catalog_or_db = table.args.get("catalog") or table.args.get("db")
175
- if catalog_or_db is not None:
176
- catalog_or_db_meta = TokenPositionDetails.from_meta(catalog_or_db.meta)
177
- catalog_or_db_range = _range_from_token_position_details(catalog_or_db_meta, read_file)
178
- start_pos = catalog_or_db_range.start
179
-
180
- description = generate_markdown_description(referenced_model)
181
-
182
- references.append(
183
- Reference(
184
- uri=referenced_model_uri.value,
185
- range=Range(start=start_pos, end=end_pos),
186
- markdown_description=description,
187
- )
188
- )
137
+ # Build scope tree to properly handle nested CTEs
138
+ query = normalize_identifiers(query.copy(), dialect=dialect)
139
+ root_scope = build_scope(query)
140
+
141
+ if root_scope:
142
+ # Traverse all scopes to find CTE definitions and table references
143
+ for scope in root_scope.traverse():
144
+ for table in scope.tables:
145
+ table_name = table.name
146
+
147
+ # Check if this table reference is a CTE in the current scope
148
+ if cte_scope := scope.cte_sources.get(table_name):
149
+ cte = cte_scope.expression.parent
150
+ alias = cte.args["alias"]
151
+ if isinstance(alias, exp.TableAlias):
152
+ identifier = alias.this
153
+ if isinstance(identifier, exp.Identifier):
154
+ target_range = _range_from_token_position_details(
155
+ TokenPositionDetails.from_meta(identifier.meta), read_file
156
+ )
157
+ table_range = _range_from_token_position_details(
158
+ TokenPositionDetails.from_meta(table.this.meta), read_file
159
+ )
160
+ references.append(
161
+ Reference(
162
+ uri=document_uri.value, # Same file
163
+ range=table_range,
164
+ target_range=target_range,
165
+ )
166
+ )
167
+ continue
168
+
169
+ # For non-CTE tables, process as before (external model references)
170
+ # Normalize the table reference
171
+ unaliased = table.copy()
172
+ if unaliased.args.get("alias") is not None:
173
+ unaliased.set("alias", None)
174
+ reference_name = unaliased.sql(dialect=dialect)
175
+ try:
176
+ normalized_reference_name = normalize_model_name(
177
+ reference_name,
178
+ default_catalog=lint_context.context.default_catalog,
179
+ dialect=dialect,
180
+ )
181
+ if normalized_reference_name not in depends_on:
182
+ continue
183
+ except Exception:
184
+ # Skip references that cannot be normalized
185
+ continue
186
+
187
+ # Get the referenced model uri
188
+ referenced_model = lint_context.context.get_model(
189
+ model_or_snapshot=normalized_reference_name, raise_if_missing=False
190
+ )
191
+ if referenced_model is None:
192
+ continue
193
+ referenced_model_path = referenced_model._path
194
+ # Check whether the path exists
195
+ if not referenced_model_path.is_file():
196
+ continue
197
+ referenced_model_uri = URI.from_path(referenced_model_path)
198
+
199
+ # Extract metadata for positioning
200
+ table_meta = TokenPositionDetails.from_meta(table.this.meta)
201
+ table_range = _range_from_token_position_details(table_meta, read_file)
202
+ start_pos = table_range.start
203
+ end_pos = table_range.end
204
+
205
+ # If there's a catalog or database qualifier, adjust the start position
206
+ catalog_or_db = table.args.get("catalog") or table.args.get("db")
207
+ if catalog_or_db is not None:
208
+ catalog_or_db_meta = TokenPositionDetails.from_meta(catalog_or_db.meta)
209
+ catalog_or_db_range = _range_from_token_position_details(
210
+ catalog_or_db_meta, read_file
211
+ )
212
+ start_pos = catalog_or_db_range.start
213
+
214
+ description = generate_markdown_description(referenced_model)
215
+
216
+ references.append(
217
+ Reference(
218
+ uri=referenced_model_uri.value,
219
+ range=Range(start=start_pos, end=end_pos),
220
+ markdown_description=description,
221
+ )
222
+ )
189
223
 
190
224
  return references
191
225
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlmesh
3
- Version: 0.186.2.dev17
3
+ Version: 0.186.2.dev19
4
4
  Summary: Next-generation data transformation framework
5
5
  Author-email: "TobikoData Inc." <engineering@tobikodata.com>
6
6
  License: Apache License
@@ -1,5 +1,5 @@
1
1
  sqlmesh/__init__.py,sha256=69xw6bTmi4cW90M-sl3g6wLDgxVcLHcKg1q8GS3lqyA,7466
2
- sqlmesh/_version.py,sha256=uVts1wYEXwhfLjxOxzfc3ynvmNDBEXjxwxw9qMXF_Dg,530
2
+ sqlmesh/_version.py,sha256=jLiYtCYI57WrZTPDzSrzKIXY5C2UdjMbD3bzBJdIXz0,530
3
3
  sqlmesh/magics.py,sha256=JHorAZNtezf123jmTyNSoUC9yHmv-08hMP205PJmmIo,39750
4
4
  sqlmesh/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  sqlmesh/cicd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -160,8 +160,8 @@ sqlmesh/lsp/completions.py,sha256=Uo8lUzPBeoB58Eu2642YoAtNI0pgIFWFSvwmuJALTv4,35
160
160
  sqlmesh/lsp/context.py,sha256=nCWg2uVH28-IJC2uDYuCbiXTh1lUFElSpNu4Q-fDWi4,2918
161
161
  sqlmesh/lsp/custom.py,sha256=1YVcQz0y-4cdsvTdOQvlhUQXwOqPBWi3v_u1X2EqQxE,901
162
162
  sqlmesh/lsp/description.py,sha256=4QIGC9ix8IzmWF6DVUNhY4m1Crk3sNQA6hZ1RbyqU78,827
163
- sqlmesh/lsp/main.py,sha256=5EF1xA1rESYq4sTKDJPPG9Zl6mx3xfy6dbzWBbDee0M,18553
164
- sqlmesh/lsp/reference.py,sha256=bO2edkI2avmEYayQI11_OsDX1gjp36kq9ANwHczWSC0,8285
163
+ sqlmesh/lsp/main.py,sha256=S4zWFhZc0WXZ0JbIhvlm1hEFNWxJS85LR4d7woBzh9o,19101
164
+ sqlmesh/lsp/reference.py,sha256=v4VXMYQY9rPC8b5w-jzob3i77VdZ1FZ8sA_-sWuPx7M,10502
165
165
  sqlmesh/lsp/uri.py,sha256=mvSLbZGmMTHPpliThOtVWiFcHnfJzp1w39q9l-xD2SI,802
166
166
  sqlmesh/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
167
167
  sqlmesh/migrations/v0001_init.py,sha256=h8FwMYJj9_O8yGpk12guaSaGwX5A3we2GiKeHrXi15o,2048
@@ -270,7 +270,7 @@ sqlmesh/utils/pydantic.py,sha256=I898jAFqa3qU6lG2uPpRebVFncOUo8ZrLWM_R3K3DHU,116
270
270
  sqlmesh/utils/rich.py,sha256=xNZyPCqEc4TAlJlsEthg-5eYUWpaizz0QjBzO7a1Yv4,1509
271
271
  sqlmesh/utils/windows.py,sha256=r7Yin4WEwbvH7sKA3hOJtRsclmscNuBeCklCfVPvtQs,611
272
272
  sqlmesh/utils/yaml.py,sha256=np-WVcwmwsKghCgAj1OBBMsK1SXSRn4wR-H37cGiFr8,2282
273
- sqlmesh-0.186.2.dev17.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
273
+ sqlmesh-0.186.2.dev19.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
274
274
  web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
275
275
  web/client/dist/index.html,sha256=M50OuwjW63dRCS0Dz40Yecgvw9ecLFqizbTa6gv5Nd4,5472
276
276
  web/client/dist/assets/Audits-BPlxzqeG.js,sha256=TCx1qCjCGgmUSvH6HoPr5t8ztbRXMlOxrcW4o7hRjlA,1041
@@ -388,8 +388,8 @@ web/server/api/endpoints/models.py,sha256=ud-lRwriyI_OYg9tZchrBgeiXELiRTLNEodraf
388
388
  web/server/api/endpoints/modules.py,sha256=8hqqgonGay_mJmpCw0IdbjsPhWlQH2VLdKAqha-myac,468
389
389
  web/server/api/endpoints/plan.py,sha256=OYuQ_4dgbhG9ibTcX1a8mvYgH3ANxw9Fhbb4wg6QWqc,9222
390
390
  web/server/api/endpoints/table_diff.py,sha256=Wd5YxeKbZB7AkrDvqFgvV9ZQlnKYOF1n5W_w2EHE_Zw,2085
391
- sqlmesh-0.186.2.dev17.dist-info/METADATA,sha256=PZvvbApn2rdxUldi_hf_uTtZEIRdm3R6LYqdDWbT42E,25524
392
- sqlmesh-0.186.2.dev17.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
393
- sqlmesh-0.186.2.dev17.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
394
- sqlmesh-0.186.2.dev17.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
395
- sqlmesh-0.186.2.dev17.dist-info/RECORD,,
391
+ sqlmesh-0.186.2.dev19.dist-info/METADATA,sha256=Iu3T2sHxxhBJo6atE2xIfZNfCw7xR9-DGYeeR-aucX8,25524
392
+ sqlmesh-0.186.2.dev19.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
393
+ sqlmesh-0.186.2.dev19.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
394
+ sqlmesh-0.186.2.dev19.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
395
+ sqlmesh-0.186.2.dev19.dist-info/RECORD,,