Skip to content

Commit

Permalink
Address comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
plypaul committed Sep 15, 2023
1 parent 57df3a2 commit d45a108
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 18 deletions.
10 changes: 1 addition & 9 deletions dbt_semantic_interfaces/implementations/saved_query.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import List, Optional, Sequence
from typing import List, Optional

from typing_extensions import override

Expand Down Expand Up @@ -30,11 +30,3 @@ def _implements_protocol(self) -> SavedQuery:

description: Optional[str] = None
metadata: Optional[PydanticMetadata] = None

@property
def metric_names(self) -> Sequence[str]: # noqa: D
return self.metrics

@property
def group_by_item_names(self) -> Sequence[str]: # noqa: D
return self.group_bys
4 changes: 2 additions & 2 deletions dbt_semantic_interfaces/protocols/saved_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ def description(self) -> Optional[str]: # noqa: D

@property
@abstractmethod
def metric_names(self) -> Sequence[str]: # noqa: D
def metrics(self) -> Sequence[str]: # noqa: D
pass

@property
@abstractmethod
def group_by_item_names(self) -> Sequence[str]: # noqa: D
def group_bys(self) -> Sequence[str]: # noqa: D
pass

@property
Expand Down
49 changes: 42 additions & 7 deletions dbt_semantic_interfaces/validations/saved_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
import traceback
from typing import Generic, List, Sequence, Set

from dbt_semantic_interfaces.protocols import SemanticManifestT, SemanticModel
from dbt_semantic_interfaces.naming.dundered import DunderedNameFormatter
from dbt_semantic_interfaces.naming.keywords import METRIC_TIME_ELEMENT_NAME
from dbt_semantic_interfaces.protocols import SemanticManifestT
from dbt_semantic_interfaces.protocols.saved_query import SavedQuery
from dbt_semantic_interfaces.validations.validator_helpers import (
FileContext,
Expand All @@ -29,14 +31,30 @@ class SavedQueryRule(SemanticManifestValidationRule[SemanticManifestT], Generic[
"""

@staticmethod
def _model_requires_primary_entity(semantic_model: SemanticModel) -> bool:
return len(semantic_model.dimensions) > 0
@validate_safely("Validate the group-by field in a saved query.")
def _check_group_bys(valid_group_by_element_names: Set[str], saved_query: SavedQuery) -> Sequence[ValidationIssue]:
issues: List[ValidationIssue] = []

for group_by_item_name in saved_query.group_bys:
structured_name = DunderedNameFormatter.parse_name(group_by_item_name)
if structured_name.element_name not in valid_group_by_element_names:
issues.append(
ValidationError(
message=f"`{group_by_item_name}` is not a valid group-by name.",
context=SavedQueryContext(
file_context=FileContext.from_metadata(metadata=saved_query.metadata),
element_type=SavedQueryElementType.GROUP_BY,
element_value=group_by_item_name,
),
)
)
return issues

@staticmethod
@validate_safely("Validate a saved query.")
def _check_saved_query(valid_metric_names: Set[str], saved_query: SavedQuery) -> Sequence[ValidationIssue]:
@validate_safely("Validate the metrics field in a saved query.")
def _check_metrics(valid_metric_names: Set[str], saved_query: SavedQuery) -> Sequence[ValidationIssue]:
issues: List[ValidationIssue] = []
for metric_name in saved_query.metric_names:
for metric_name in saved_query.metrics:
if metric_name not in valid_metric_names:
issues.append(
ValidationError(
Expand All @@ -48,7 +66,12 @@ def _check_saved_query(valid_metric_names: Set[str], saved_query: SavedQuery) ->
),
)
)
return issues

@staticmethod
@validate_safely("Validate the where field in a saved query.")
def _check_where(saved_query: SavedQuery) -> Sequence[ValidationIssue]:
issues: List[ValidationIssue] = []
for where_filter in saved_query.where:
try:
where_filter.call_parameter_sets
Expand All @@ -75,10 +98,22 @@ def _check_saved_query(valid_metric_names: Set[str], saved_query: SavedQuery) ->
def validate_manifest(semantic_manifest: SemanticManifestT) -> Sequence[ValidationIssue]: # noqa: D
issues: List[ValidationIssue] = []
valid_metric_names = {metric.name for metric in semantic_manifest.metrics}
valid_group_by_element_names = {METRIC_TIME_ELEMENT_NAME}
for semantic_model in semantic_manifest.semantic_models:
for dimension in semantic_model.dimensions:
valid_group_by_element_names.add(dimension.name)
for entity in semantic_model.entities:
valid_group_by_element_names.add(entity.name)

for saved_query in semantic_manifest.saved_queries:
issues += SavedQueryRule._check_saved_query(
issues += SavedQueryRule._check_metrics(
valid_metric_names=valid_metric_names,
saved_query=saved_query,
)
issues += SavedQueryRule._check_group_bys(
valid_group_by_element_names=valid_group_by_element_names,
saved_query=saved_query,
)
issues += SavedQueryRule._check_where(saved_query=saved_query)

return issues
22 changes: 22 additions & 0 deletions tests/validations/test_saved_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def test_invalid_metric_in_saved_query( # noqa: D
description="Example description.",
metrics=["invalid_metric"],
group_bys=["booking__is_instant"],
where=[PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}")],
),
]

Expand Down Expand Up @@ -72,3 +73,24 @@ def test_invalid_where_in_saved_query( # noqa: D
manifest_validator.validate_semantic_manifest(manifest),
"trying to parse a filter in saved query",
)


def test_invalid_group_by_in_saved_query( # noqa: D
simple_semantic_manifest__with_primary_transforms: PydanticSemanticManifest,
) -> None:
manifest = copy.deepcopy(simple_semantic_manifest__with_primary_transforms)
manifest.saved_queries = [
PydanticSavedQuery(
name="Example Saved Query",
description="Example description.",
metrics=["bookings"],
group_bys=["invalid_dimension"],
where=[PydanticWhereFilter(where_sql_template="{{ Dimension('booking__is_instant') }}")],
),
]

manifest_validator = SemanticManifestValidator[PydanticSemanticManifest]([SavedQueryRule()])
check_only_one_error_with_message(
manifest_validator.validate_semantic_manifest(manifest),
"is not a valid group-by name.",
)

0 comments on commit d45a108

Please sign in to comment.