Skip to content

Commit 1b0d59f

Browse files
committed
selecting models by name when the name contains quotes now works
1 parent 4fcc8a3 commit 1b0d59f

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

sqlmesh/core/selector.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,32 @@ def expand_model_selections(
191191
models_by_tags.setdefault(tag, set())
192192
models_by_tags[tag].add(model.fqn)
193193

194+
def _normalize_for_match(name: str) -> str:
195+
"""Strip surrounding identifier quotes on each component for glob-style matching."""
196+
parts = name.split(".")
197+
198+
def _unquote(part: str) -> str:
199+
if len(part) >= 2 and part[0] == part[-1] and part[0] in {"'", '"', "`", "["}:
200+
# For [] quoting, ensure trailing ]
201+
if part[0] == "[" and part[-1] != "]":
202+
return part
203+
return part[1:-1]
204+
return part
205+
206+
return ".".join(_unquote(p) for p in parts)
207+
194208
def evaluate(node: exp.Expression) -> t.Set[str]:
195209
if isinstance(node, exp.Var):
196210
pattern = node.this
197211
if "*" in pattern:
212+
normalized_pattern = _normalize_for_match(pattern)
198213
return {
199214
fqn
200215
for fqn, model in all_models.items()
201-
if fnmatch.fnmatchcase(self._model_name(model), node.this)
216+
if fnmatch.fnmatchcase(
217+
_normalize_for_match(self._model_name(model)),
218+
normalized_pattern,
219+
)
202220
}
203221
return self._pattern_to_model_fqns(pattern, all_models)
204222
if isinstance(node, exp.And):
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from __future__ import annotations
2+
3+
import fnmatch
4+
5+
import pytest
6+
7+
from sqlmesh.core.selector import parse
8+
9+
10+
@pytest.mark.parametrize(
11+
("selector", "expected"),
12+
[
13+
("foo.bar", "foo.bar"),
14+
("foo*", "foo*"),
15+
("*bar", "*bar"),
16+
("'biquery-project'.schema.table", "'biquery-project'.schema.table"),
17+
("'biquery-project'.schema*", "'biquery-project'.schema*"),
18+
('"biquery-project".schema*', '"biquery-project".schema*'),
19+
("`biquery-project`.schema*", "`biquery-project`.schema*"),
20+
],
21+
)
22+
def test_parse_preserves_quotes_in_var(selector: str, expected: str) -> None:
23+
node = parse(selector)
24+
assert node.this == expected
25+
26+
27+
def test_fnmatch_works_with_quotes_in_pattern() -> None:
28+
model_name = "'biquery-project'.schema.table"
29+
assert fnmatch.fnmatchcase(model_name, "'biquery-project'.schema*")

0 commit comments

Comments
 (0)