diff --git a/superset/models/helpers.py b/superset/models/helpers.py index 754956cbc2fa..a1c92adaa146 100644 --- a/superset/models/helpers.py +++ b/superset/models/helpers.py @@ -2800,6 +2800,21 @@ def get_sqla_query( # pylint: disable=too-many-arguments,too-many-locals,too-ma col = self.convert_tbl_column_to_sqla_col( columns_by_name[col], template_processor=template_processor ) + elif isinstance(col, str) and columns: + # Check if this is a label reference to an adhoc column + adhoc_col = next( + ( + c + for c in columns + if utils.is_adhoc_column(c) and c.get("label") == col + ), + None, + ) + if adhoc_col: + col = self.adhoc_column_to_sqla( + col=adhoc_col, + template_processor=template_processor, + ) if isinstance(col, ColumnElement): orderby_exprs.append(col) diff --git a/tests/unit_tests/models/helpers_test.py b/tests/unit_tests/models/helpers_test.py index e913526975fb..e5a177285e80 100644 --- a/tests/unit_tests/models/helpers_test.py +++ b/tests/unit_tests/models/helpers_test.py @@ -1703,3 +1703,43 @@ def test_adhoc_column_with_spaces_in_full_query(database: Database) -> None: # Verify SELECT and FROM clauses are present assert "SELECT" in sql assert "FROM" in sql + + +def test_orderby_adhoc_column(database: Database) -> None: + """ + Test that orderby works with adhoc column labels. + + When orderby contains a string that matches the label of an adhoc column + in the columns list, it should correctly convert to a SQLAlchemy column + instead of raising QueryObjectValidationError. + """ + from superset.connectors.sqla.models import SqlaTable, TableColumn + + table = SqlaTable( + database=database, + schema=None, + table_name="t", + columns=[ + TableColumn(column_name="a"), + TableColumn(column_name="b"), + ], + ) + + # Should not raise QueryObjectValidationError + result = table.get_sqla_query( + columns=[ + {"expressionType": "SQL", "label": "custom_col", "sqlExpression": "a + 1"}, + "b", + ], + orderby=[("custom_col", False)], # Order by adhoc column label + metrics=[], + extras={}, + filter=[], + granularity=None, + is_timeseries=False, + ) + assert result is not None + + # Verify the SQL contains the expression from the adhoc column + sql = str(result.sqla_query) + assert "ORDER BY" in sql.upper()