mirror of
https://github.com/apache/superset.git
synced 2026-07-14 18:55:47 +00:00
fix(mcp): fix pre_validate aliases and sql_expression normalization
Three pre_validate methods were checking only canonical field names, but
the Pydantic schemas accept validation aliases. For example
PieChartConfig.dimension accepts "groupby" as an alias, so sending
{"groupby": ...} would pass the schema but be incorrectly rejected by
pre_validate.
Four normalize_column_refs implementations did not guard against
sql_expression metrics (name=None), causing AttributeError when
_get_canonical_column_name(None, ...) was called. XYChartPlugin already
handled this correctly; the fix brings the other plugins in line.
Pre-validate alias fixes:
- TableChartPlugin: accept columns/all_columns/groupby (AliasChoices)
- PieChartPlugin: accept dimension/groupby (AliasChoices)
- PivotTableChartPlugin: accept rows/groupby/dimension (AliasChoices)
sql_expression normalization guards:
- BigNumberChartPlugin: skip metric normalization when sql_expression set
- PieChartPlugin: same for metric field
- MixedTimeseriesChartPlugin: skip in _norm_list helper
- PivotTableChartPlugin: skip in _norm_col_list helper
This commit is contained in:
@@ -208,7 +208,9 @@ class BigNumberChartPlugin(BaseChartPlugin):
|
||||
config_dict = config.model_dump()
|
||||
|
||||
if config_dict.get("metric"):
|
||||
if config_dict["metric"].get("saved_metric"):
|
||||
if config_dict["metric"].get("sql_expression"):
|
||||
pass
|
||||
elif config_dict["metric"].get("saved_metric"):
|
||||
config_dict["metric"]["name"] = (
|
||||
DatasetValidator._get_canonical_metric_name(
|
||||
config_dict["metric"]["name"], dataset_context
|
||||
|
||||
@@ -132,6 +132,8 @@ class MixedTimeseriesChartPlugin(BaseChartPlugin):
|
||||
def _norm_list(key: str) -> None:
|
||||
if config_dict.get(key):
|
||||
for col in config_dict[key]:
|
||||
if col.get("sql_expression"):
|
||||
continue
|
||||
if col.get("saved_metric"):
|
||||
col["name"] = DatasetValidator._get_canonical_metric_name(
|
||||
col["name"], dataset_context
|
||||
|
||||
@@ -47,7 +47,7 @@ class PieChartPlugin(BaseChartPlugin):
|
||||
) -> ChartGenerationError | None:
|
||||
missing_fields = []
|
||||
|
||||
if "dimension" not in config:
|
||||
if "dimension" not in config and "groupby" not in config:
|
||||
missing_fields.append("'dimension' (category column for slices)")
|
||||
if "metric" not in config:
|
||||
missing_fields.append("'metric' (value metric for slice sizes)")
|
||||
@@ -104,7 +104,9 @@ class PieChartPlugin(BaseChartPlugin):
|
||||
)
|
||||
)
|
||||
if config_dict.get("metric"):
|
||||
if config_dict["metric"].get("saved_metric"):
|
||||
if config_dict["metric"].get("sql_expression"):
|
||||
pass
|
||||
elif config_dict["metric"].get("saved_metric"):
|
||||
config_dict["metric"]["name"] = (
|
||||
DatasetValidator._get_canonical_metric_name(
|
||||
config_dict["metric"]["name"], dataset_context
|
||||
|
||||
@@ -47,7 +47,7 @@ class PivotTableChartPlugin(BaseChartPlugin):
|
||||
) -> ChartGenerationError | None:
|
||||
missing_fields = []
|
||||
|
||||
if not config.get("rows"):
|
||||
if not (config.get("rows") or config.get("groupby") or config.get("dimension")):
|
||||
missing_fields.append("'rows' (row grouping columns)")
|
||||
if not config.get("metrics"):
|
||||
missing_fields.append("'metrics' (aggregation metrics)")
|
||||
@@ -67,7 +67,10 @@ class PivotTableChartPlugin(BaseChartPlugin):
|
||||
error_code="MISSING_PIVOT_FIELDS",
|
||||
)
|
||||
|
||||
if not isinstance(config.get("rows", []), list):
|
||||
rows_val = (
|
||||
config.get("rows") or config.get("groupby") or config.get("dimension") or []
|
||||
)
|
||||
if not isinstance(rows_val, list):
|
||||
return ChartGenerationError(
|
||||
error_type="invalid_rows_format",
|
||||
message="Rows must be a list of columns",
|
||||
@@ -123,6 +126,8 @@ class PivotTableChartPlugin(BaseChartPlugin):
|
||||
def _norm_col_list(key: str) -> None:
|
||||
if config_dict.get(key):
|
||||
for col in config_dict[key]:
|
||||
if col.get("sql_expression"):
|
||||
continue
|
||||
if col.get("saved_metric"):
|
||||
col["name"] = DatasetValidator._get_canonical_metric_name(
|
||||
col["name"], dataset_context
|
||||
|
||||
@@ -46,7 +46,10 @@ class TableChartPlugin(BaseChartPlugin):
|
||||
self,
|
||||
config: dict[str, Any],
|
||||
) -> ChartGenerationError | None:
|
||||
if not config.get("columns"):
|
||||
columns = (
|
||||
config.get("columns") or config.get("all_columns") or config.get("groupby")
|
||||
)
|
||||
if not columns:
|
||||
return ChartGenerationError(
|
||||
error_type="missing_columns",
|
||||
message="Table chart missing required field: columns",
|
||||
@@ -63,7 +66,7 @@ class TableChartPlugin(BaseChartPlugin):
|
||||
error_code="MISSING_COLUMNS",
|
||||
)
|
||||
|
||||
if not isinstance(config.get("columns", []), list):
|
||||
if not isinstance(columns, list):
|
||||
return ChartGenerationError(
|
||||
error_type="invalid_columns_format",
|
||||
message="Columns must be a list",
|
||||
|
||||
Reference in New Issue
Block a user