Skip to content

Commit 507c89a

Browse files
authored
Fix: Allow create_external_models to run for projects with star projections and support dbt formatted projects. (#880)
1 parent f5fe9b6 commit 507c89a

4 files changed

Lines changed: 34 additions & 23 deletions

File tree

sqlmesh/cli/main.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,15 @@ def cli(
3636
if ctx.invoked_subcommand == "version":
3737
return
3838

39+
load = True
40+
3941
if len(paths) == 1:
4042
path = os.path.abspath(paths[0])
4143
if ctx.invoked_subcommand == "init":
4244
ctx.obj = path
4345
return
46+
elif ctx.invoked_subcommand == "create_external_models":
47+
load = False
4448

4549
# Delegates the execution of the --help option to the corresponding subcommand
4650
if "--help" in sys.argv:
@@ -53,9 +57,10 @@ def cli(
5357
paths=paths,
5458
config=config,
5559
gateway=gateway,
60+
load=load,
5661
)
5762

58-
if not context.models:
63+
if load and not context.models:
5964
raise click.ClickException(
6065
f"`{paths}` doesn't seem to have any models... cd into the proper directory or specify the path(s) with -p."
6166
)

sqlmesh/core/context.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -847,12 +847,13 @@ def create_external_models(self) -> None:
847847
The schema file contains all columns and types of external models, allowing for more robust
848848
lineage, validation, and optimizations.
849849
"""
850+
models = self._models or self._loader.load(self, update_schemas=False).models
850851
for path, config in self.configs.items():
851852
create_schema_file(
852853
path=path / c.SCHEMA_YAML,
853854
models={
854855
name: model
855-
for name, model in self._models.items()
856+
for name, model in models.items()
856857
if self.config_for_model(model) is config
857858
},
858859
adapter=self._engine_adapter,

sqlmesh/core/loader.py

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ def update_model_schemas(dag: DAG[str], models: UniqueKeyDict[str, Model]) -> No
6969
if external:
7070
if "*" in model.columns_to_types:
7171
raise ConfigError(
72-
f"Can't expand SELECT * expression for model '{name}'. Projections for models that use external sources must be specified explicitly at '{model._path}'"
72+
f"Can't expand SELECT * expression for model '{name}'."
73+
" Projections for models that use external sources must be specified explicitly"
74+
" or use external models (https://sqlmesh.readthedocs.io/en/stable/concepts/models/external_models)."
7375
)
7476
elif model.mapping_schema:
7577
try:
@@ -97,7 +99,7 @@ def __init__(self) -> None:
9799
self._path_mtimes: t.Dict[Path, float] = {}
98100
self._dag: DAG[str] = DAG()
99101

100-
def load(self, context: Context) -> LoadedProject:
102+
def load(self, context: Context, update_schemas: bool = True) -> LoadedProject:
101103
"""
102104
Loads all hooks, macros, and models in the context's path
103105
@@ -128,7 +130,8 @@ def load(self, context: Context) -> LoadedProject:
128130
models = self._load_models(macros, hooks, jinja_macros)
129131
for model in models.values():
130132
self._add_model_to_dag(model)
131-
update_model_schemas(self._dag, models)
133+
if update_schemas:
134+
update_model_schemas(self._dag, models)
132135

133136
audits = self._load_audits()
134137

@@ -169,6 +172,24 @@ def _load_models(
169172
def _load_audits(self) -> UniqueKeyDict[str, Audit]:
170173
"""Loads all audits."""
171174

175+
def _load_external_models(self) -> UniqueKeyDict[str, Model]:
176+
models: UniqueKeyDict = UniqueKeyDict("models")
177+
for context_path, config in self._context.configs.items():
178+
path = Path(context_path / c.SCHEMA_YAML)
179+
180+
if path.exists():
181+
self._track_file(path)
182+
183+
with open(path, "r", encoding="utf-8") as file:
184+
for row in YAML().load(file.read()):
185+
model = create_external_model(
186+
**row,
187+
dialect=config.model_defaults.dialect,
188+
path=path,
189+
)
190+
models[model.name] = model
191+
return models
192+
172193
def _add_model_to_dag(self, model: Model) -> None:
173194
self._dag.graph[model.name] = set()
174195
self._dag.add(model.name, model.depends_on)
@@ -240,24 +261,6 @@ def _load_models(
240261

241262
return models
242263

243-
def _load_external_models(self) -> UniqueKeyDict[str, Model]:
244-
models: UniqueKeyDict = UniqueKeyDict("models")
245-
for context_path, config in self._context.configs.items():
246-
path = Path(context_path / c.SCHEMA_YAML)
247-
248-
if path.exists():
249-
self._track_file(path)
250-
251-
with open(path, "r", encoding="utf-8") as file:
252-
for row in YAML().load(file.read()):
253-
model = create_external_model(
254-
**row,
255-
dialect=config.model_defaults.dialect,
256-
path=path,
257-
)
258-
models[model.name] = model
259-
return models
260-
261264
def _load_sql_models(
262265
self, macros: MacroRegistry, hooks: HookRegistry, jinja_macros: JinjaMacroRegistry
263266
) -> UniqueKeyDict[str, Model]:

sqlmesh/dbt/loader.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ def _load_models(
108108
}
109109
)
110110

111+
models.update(self._load_external_models())
112+
111113
return models
112114

113115
def _load_audits(self) -> UniqueKeyDict[str, Audit]:

0 commit comments

Comments
 (0)