|
10 | 10 | from sqlmesh.core.linter.helpers import TokenPositionDetails, get_range_of_model_block |
11 | 11 | from sqlmesh.core.linter.rule import Rule, RuleViolation, Range, Fix, TextEdit |
12 | 12 | from sqlmesh.core.linter.definition import RuleSet |
13 | | -from sqlmesh.core.model import Model, SqlModel |
| 13 | +from sqlmesh.core.model import Model, SqlModel, ExternalModel |
14 | 14 |
|
15 | 15 |
|
16 | 16 | class NoSelectStar(Rule): |
17 | | - """Query should not contain SELECT * on its outer most projections, even if it can be expanded.""" |
| 17 | + """Query should not contain SELECT * on its outermost projections, even if it can be expanded.""" |
18 | 18 |
|
19 | 19 | def check_model(self, model: Model) -> t.Optional[RuleViolation]: |
20 | 20 | # Only applies to SQL models, as other model types do not have a query. |
@@ -110,4 +110,31 @@ def check_model(self, model: Model) -> t.Optional[RuleViolation]: |
110 | 110 | return self.violation() |
111 | 111 |
|
112 | 112 |
|
| 113 | +class NoMissingExternalModels(Rule): |
| 114 | + """All external models must be registered in the external_models.yaml file""" |
| 115 | + |
| 116 | + def check_model(self, model: Model) -> t.Optional[RuleViolation]: |
| 117 | + # Ignore external models themselves, because either they are registered, |
| 118 | + # and if they are not, they will be caught as referenced in another model. |
| 119 | + if isinstance(model, ExternalModel): |
| 120 | + return None |
| 121 | + |
| 122 | + # Handle other models that may refer to the external models. |
| 123 | + not_registered_external_models: t.Set[str] = set() |
| 124 | + for depends_on_model in model.depends_on: |
| 125 | + existing_model = self.context.get_model(depends_on_model) |
| 126 | + if existing_model is None: |
| 127 | + not_registered_external_models.add(depends_on_model) |
| 128 | + |
| 129 | + if not not_registered_external_models: |
| 130 | + return None |
| 131 | + |
| 132 | + return RuleViolation( |
| 133 | + rule=self, |
| 134 | + violation_msg=f"Model '{model.name}' depends on unregistered external models: " |
| 135 | + f"{', '.join(m for m in not_registered_external_models)}. " |
| 136 | + "Please register them in the external_models.yaml file.", |
| 137 | + ) |
| 138 | + |
| 139 | + |
113 | 140 | BUILTIN_RULES = RuleSet(subclasses(__name__, Rule, (Rule,))) |
0 commit comments