From 4d82e4295f89ac905c9703e2d558d3ca8f6d8c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Bedi?= Date: Wed, 10 Dec 2025 12:14:54 +0100 Subject: [PATCH] Enhance SelectRow component with improved alias option handling - Updated alias options for time series and variable queries to prevent duplicates and ensure correct options are displayed. --- .../visual-query-builder/SelectRow.tsx | 58 ++++++++++++++----- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/packages/grafana-sql/src/components/visual-query-builder/SelectRow.tsx b/packages/grafana-sql/src/components/visual-query-builder/SelectRow.tsx index 2bd4ce58c65..78b7eccb8d0 100644 --- a/packages/grafana-sql/src/components/visual-query-builder/SelectRow.tsx +++ b/packages/grafana-sql/src/components/visual-query-builder/SelectRow.tsx @@ -1,6 +1,6 @@ import { css } from '@emotion/css'; import { uniqueId } from 'lodash'; -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import { SelectableValue, toOption } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; @@ -26,20 +26,50 @@ interface SelectRowProps { export function SelectRow({ query, onQueryChange, db, columns, isVariableQuery }: SelectRowProps) { const styles = useStyles2(getStyles); const { onSqlChange } = useSqlChange({ query, onQueryChange, db }); - const aliasOpts: Array> = []; - // Add necessary alias options for time series format - // when that format has been selected - if (query.format === QueryFormat.Timeseries) { - aliasOpts.push({ label: t('grafana-sql.components.select-row.label.time', 'time'), value: 'time' }); - aliasOpts.push({ label: t('grafana-sql.components.select-row.label.value', 'value'), value: 'value' }); - } + // Get currently used aliases from all columns + const usedAliases = useMemo(() => { + const aliases = new Set(); + query.sql?.columns?.forEach((col) => { + if (col.alias) { + // Remove quotes from alias + const cleanAlias = col.alias.replace(/"/g, ''); + aliases.add(cleanAlias); + } + }); + return aliases; + }, [query.sql?.columns]); - // Add variable query alias options for text and value - if (isVariableQuery) { - aliasOpts.push({ label: t('grafana-sql.components.select-row.label.__text', '__text'), value: '__text' }); - aliasOpts.push({ label: t('grafana-sql.components.select-row.label.__value', '__value'), value: '__value' }); - } + // Function to get available alias options for a specific column + const getAliasOptions = useCallback( + (currentAlias?: string): Array> => { + const aliasOpts: Array> = []; + const cleanCurrentAlias = currentAlias?.replace(/"/g, ''); + + // Add necessary alias options for time series format + if (query.format === QueryFormat.Timeseries) { + if (!usedAliases.has('time') || cleanCurrentAlias === 'time') { + aliasOpts.push({ label: t('grafana-sql.components.select-row.label.time', 'time'), value: 'time' }); + } + if (!usedAliases.has('value') || cleanCurrentAlias === 'value') { + aliasOpts.push({ label: t('grafana-sql.components.select-row.label.value', 'value'), value: 'value' }); + } + } + + // Add variable query alias options for __text and __value + if (isVariableQuery) { + if (!usedAliases.has('__text') || cleanCurrentAlias === '__text') { + aliasOpts.push({ label: t('grafana-sql.components.select-row.label.__text', '__text'), value: '__text' }); + } + if (!usedAliases.has('__value') || cleanCurrentAlias === '__value') { + aliasOpts.push({ label: t('grafana-sql.components.select-row.label.__value', '__value'), value: '__value' }); + } + } + + return aliasOpts; + }, + [query.format, isVariableQuery, usedAliases] + ); const onAggregationChange = useCallback( (item: QueryEditorFunctionExpression, index: number) => (aggregation: SelectableValue) => { @@ -152,7 +182,7 @@ export function SelectRow({ query, onQueryChange, db, columns, isVariableQuery } value={item.alias ? toOption(item.alias) : null} inputId={`select-alias-${index}-${uniqueId()}`} data-testid={selectors.components.SQLQueryEditor.selectAlias} - options={aliasOpts} + options={getAliasOptions(item.alias)} onChange={onAliasChange(item, index)} isClearable menuShouldPortal