mirror of
https://github.com/apache/superset.git
synced 2026-04-19 16:14:52 +00:00
fix(chart-data-api): assert referenced columns are present in datasource (#10451)
* fix(chart-data-api): assert requested columns are present in datasource * add filter tests * add column_names to AnnotationDatasource * add assertion for simple metrics * lint
This commit is contained in:
@@ -42,6 +42,7 @@ from types import TracebackType
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
cast,
|
||||
Dict,
|
||||
Iterable,
|
||||
Iterator,
|
||||
@@ -102,7 +103,6 @@ logging.getLogger("MARKDOWN").setLevel(logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
DTTM_ALIAS = "__timestamp"
|
||||
ADHOC_METRIC_EXPRESSION_TYPES = {"SIMPLE": "SIMPLE", "SQL": "SQL"}
|
||||
|
||||
JS_MAX_INTEGER = 9007199254740991 # Largest int Java Script can handle 2^53-1
|
||||
|
||||
@@ -1038,20 +1038,23 @@ def backend() -> str:
|
||||
|
||||
|
||||
def is_adhoc_metric(metric: Metric) -> bool:
|
||||
if not isinstance(metric, dict):
|
||||
return False
|
||||
metric = cast(Dict[str, Any], metric)
|
||||
return bool(
|
||||
isinstance(metric, dict)
|
||||
and (
|
||||
(
|
||||
(
|
||||
metric["expressionType"] == ADHOC_METRIC_EXPRESSION_TYPES["SIMPLE"]
|
||||
and metric["column"]
|
||||
and metric["aggregate"]
|
||||
metric.get("expressionType") == AdhocMetricExpressionType.SIMPLE
|
||||
and metric.get("column")
|
||||
and cast(Dict[str, Any], metric["column"]).get("column_name")
|
||||
and metric.get("aggregate")
|
||||
)
|
||||
or (
|
||||
metric["expressionType"] == ADHOC_METRIC_EXPRESSION_TYPES["SQL"]
|
||||
and metric["sqlExpression"]
|
||||
metric.get("expressionType") == AdhocMetricExpressionType.SQL
|
||||
and metric.get("sqlExpression")
|
||||
)
|
||||
)
|
||||
and metric["label"]
|
||||
and metric.get("label")
|
||||
)
|
||||
|
||||
|
||||
@@ -1398,6 +1401,37 @@ def get_form_data_token(form_data: Dict[str, Any]) -> str:
|
||||
return form_data.get("token") or "token_" + uuid.uuid4().hex[:8]
|
||||
|
||||
|
||||
def get_column_name_from_metric(metric: Metric) -> Optional[str]:
|
||||
"""
|
||||
Extract the column that a metric is referencing. If the metric isn't
|
||||
a simple metric, always returns `None`.
|
||||
|
||||
:param metric: Ad-hoc metric
|
||||
:return: column name if simple metric, otherwise None
|
||||
"""
|
||||
if is_adhoc_metric(metric):
|
||||
metric = cast(Dict[str, Any], metric)
|
||||
if metric["expressionType"] == AdhocMetricExpressionType.SIMPLE:
|
||||
return cast(Dict[str, Any], metric["column"])["column_name"]
|
||||
return None
|
||||
|
||||
|
||||
def get_column_names_from_metrics(metrics: List[Metric]) -> List[str]:
|
||||
"""
|
||||
Extract the columns that a list of metrics are referencing. Expcludes all
|
||||
SQL metrics.
|
||||
|
||||
:param metrics: Ad-hoc metric
|
||||
:return: column name if simple metric, otherwise None
|
||||
"""
|
||||
columns: List[str] = []
|
||||
for metric in metrics:
|
||||
column_name = get_column_name_from_metric(metric)
|
||||
if column_name:
|
||||
columns.append(column_name)
|
||||
return columns
|
||||
|
||||
|
||||
class LenientEnum(Enum):
|
||||
"""Enums that do not raise ValueError when value is invalid"""
|
||||
|
||||
@@ -1523,3 +1557,8 @@ class PostProcessingContributionOrientation(str, Enum):
|
||||
|
||||
ROW = "row"
|
||||
COLUMN = "column"
|
||||
|
||||
|
||||
class AdhocMetricExpressionType(str, Enum):
|
||||
SIMPLE = "SIMPLE"
|
||||
SQL = "SQL"
|
||||
|
||||
Reference in New Issue
Block a user