Skip to content

Commit fd45c56

Browse files
add test for quoted tables
1 parent 4be6b4f commit fd45c56

1 file changed

Lines changed: 133 additions & 0 deletions

File tree

tests/lsp/test_reference_model_column_prefix.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
from pathlib import Path
2+
13
from lsprotocol.types import Position
4+
from sqlmesh.cli.example_project import init_example_project
25
from sqlmesh.core.context import Context
36
from sqlmesh.lsp.context import LSPContext, ModelTarget
47
from sqlmesh.lsp.reference import get_all_references
@@ -77,3 +80,133 @@ def test_column_prefix_references_are_found():
7780
assert any("WHERE sushi.orders.customer_id" in content for content in line_contents), (
7881
"Should find WHERE clause with sushi.orders.customer_id"
7982
)
83+
84+
85+
def test_quoted_uppercase_table_and_column_references(tmp_path: Path):
86+
# Initialize example project in temporary directory with case sensitive normalization
87+
init_example_project(tmp_path, dialect="duckdb,normalization_strategy=case_sensitive")
88+
89+
# Create a model with quoted uppercase schema and table names
90+
models_dir = tmp_path / "models"
91+
92+
# First, create the uppercase SUSHI.orders model that will be referenced
93+
uppercase_orders_path = models_dir / "uppercase_orders.sql"
94+
uppercase_orders_path.write_text("""MODEL (
95+
name "SUSHI".orders,
96+
kind FULL
97+
);
98+
99+
SELECT
100+
1 as id,
101+
1 as customer_id,
102+
1 as item_id""")
103+
104+
# Second, create the lowercase sushi.orders model that will be referenced
105+
lowercase_orders_path = models_dir / "lowercase_orders.sql"
106+
lowercase_orders_path.write_text("""MODEL (
107+
name sushi.orders,
108+
kind FULL
109+
);
110+
111+
SELECT
112+
1 as id,
113+
1 as customer_id""")
114+
115+
quoted_test_path = models_dir / "quoted_test.sql"
116+
quoted_test_path.write_text("""MODEL (
117+
name "SUSHI".quoted_test,
118+
kind FULL
119+
);
120+
121+
SELECT
122+
o.id,
123+
o.customer_id,
124+
o.item_id,
125+
c.item_id as c_item_id
126+
FROM "SUSHI".orders AS o, sushi.orders as c
127+
WHERE "SUSHI".orders.id > 0
128+
AND "SUSHI".orders.customer_id IS NOT NULL
129+
AND sushi.orders.id > 0""")
130+
131+
context = Context(paths=tmp_path)
132+
lsp_context = LSPContext(context)
133+
134+
# Find the quoted test model
135+
quoted_test_model_path = next(
136+
path
137+
for path, info in lsp_context.map.items()
138+
if isinstance(info, ModelTarget) and '"SUSHI".quoted_test' in info.names
139+
)
140+
141+
with open(quoted_test_model_path, "r", encoding="utf-8") as file:
142+
read_file = file.readlines()
143+
144+
# Test finding references for quoted "SUSHI".orders
145+
ranges = find_ranges_from_regex(read_file, r'"SUSHI"\.orders')
146+
147+
# Should find 3 occurrences: FROM clause and 2 in WHERE clause with column prefix
148+
assert len(ranges) == 3, f"Expected 3 occurrences of '\"SUSHI\".orders', found {len(ranges)}"
149+
150+
# Click on the table reference in FROM clause
151+
from_clause_range = None
152+
for r in ranges:
153+
line_content = read_file[r.start.line].strip()
154+
if "FROM" in line_content:
155+
from_clause_range = r
156+
break
157+
158+
assert from_clause_range is not None, 'Should find FROM clause with "SUSHI".orders'
159+
160+
position = Position(
161+
line=from_clause_range.start.line, character=from_clause_range.start.character + 5
162+
)
163+
164+
model_refs = get_all_references(lsp_context, URI.from_path(quoted_test_model_path), position)
165+
166+
# Should find only references to "SUSHI".orders (3 total: FROM clause and 2 column prefixes in WHERE)
167+
# The lowercase sushi.orders should NOT be included if case sensitivity is working
168+
assert len(model_refs) == 4, (
169+
f'Expected exactly 3 references for "SUSHI".orders, found {len(model_refs)}'
170+
)
171+
172+
# Verify that we have all 3 references
173+
ref_lines = [ref.range.start.line for ref in model_refs]
174+
175+
# Count how many references are on each line
176+
from_line = from_clause_range.start.line
177+
where_lines = [r.start.line for r in ranges if r.start.line != from_line]
178+
179+
assert from_line in ref_lines, "Should find FROM clause reference"
180+
for where_line in where_lines:
181+
assert where_line in ref_lines, f"Should find WHERE clause reference on line {where_line}"
182+
183+
# Now test that lowercase sushi.orders references are separate
184+
lowercase_ranges = find_ranges_from_regex(read_file, r"sushi\.orders")
185+
186+
# Should find 2 occurrences: FROM clause and 1 in WHERE clause
187+
assert len(lowercase_ranges) == 2, (
188+
f"Expected 2 occurrences of 'sushi.orders', found {len(lowercase_ranges)}"
189+
)
190+
191+
# Click on the lowercase table reference
192+
lowercase_from_range = None
193+
for r in lowercase_ranges:
194+
line_content = read_file[r.start.line].strip()
195+
if "FROM" in line_content:
196+
lowercase_from_range = r
197+
break
198+
199+
assert lowercase_from_range is not None, "Should find FROM clause with sushi.orders"
200+
201+
lowercase_position = Position(
202+
line=lowercase_from_range.start.line, character=lowercase_from_range.start.character + 5
203+
)
204+
205+
lowercase_refs = get_all_references(
206+
lsp_context, URI.from_path(quoted_test_model_path), lowercase_position
207+
)
208+
209+
# Should find only references to lowercase sushi.orders, NOT the uppercase ones
210+
assert len(lowercase_refs) == 3, (
211+
f"Expected exactly 2 references for sushi.orders, found {len(lowercase_refs)}"
212+
)

0 commit comments

Comments
 (0)