[ES|QL] Calculate the query for retrieving the values correctly (#214905)

## Summary

My function to calculate the query for retrieving the values wasn't
complete. This fixes it by taking under consideration the cursor
position


![meow](https://github.com/user-attachments/assets/eac8bd8e-4e09-406e-969f-eb8dd95a0e61)


### Checklist
- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Stratoula Kalafateli 2025-03-21 07:44:39 +01:00 committed by GitHub
parent 73a41b7480
commit 96ba76de2b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 49 additions and 4 deletions

View file

@ -21,6 +21,7 @@ import {
mapVariableToColumn,
getValuesFromQueryField,
} from './query_parsing_helpers';
import { monaco } from '@kbn/monaco';
describe('esql query helpers', () => {
describe('getIndexPatternFromESQLQuery', () => {
@ -548,10 +549,28 @@ describe('esql query helpers', () => {
expect(values).toEqual('my_field');
});
it('should return the values from the query field when cursor is not at the end', () => {
const queryString = 'FROM my_index | WHERE my_field >= | STATS COUNT(*)';
const values = getValuesFromQueryField(queryString, {
lineNumber: 1,
column: 33,
} as monaco.Position);
expect(values).toEqual('my_field');
});
it('should return the values from the query field with new lines', () => {
const queryString = 'FROM my_index \n| WHERE my_field >=';
const values = getValuesFromQueryField(queryString);
expect(values).toEqual('my_field');
});
it('should return the values from the query field with new lines when cursor is not at the end', () => {
const queryString = 'FROM my_index \n| WHERE my_field >= \n| STATS COUNT(*)';
const values = getValuesFromQueryField(queryString, {
lineNumber: 2,
column: 36,
} as monaco.Position);
expect(values).toEqual('my_field');
});
});
});

View file

@ -17,6 +17,7 @@ import type {
} from '@kbn/esql-ast';
import type { ESQLControlVariable } from '@kbn/esql-types';
import type { DatatableColumn } from '@kbn/expressions-plugin/common';
import { monaco } from '@kbn/monaco';
const DEFAULT_ESQL_LIMIT = 1000;
@ -184,8 +185,28 @@ export const mapVariableToColumn = (
return columns;
};
export const getValuesFromQueryField = (queryString: string) => {
const validQuery = `${queryString} ""`;
const getQueryUpToCursor = (queryString: string, cursorPosition?: monaco.Position) => {
const lines = queryString.split('\n');
const lineNumber = cursorPosition?.lineNumber ?? lines.length;
const column = cursorPosition?.column ?? lines[lineNumber - 1].length;
// Handle the case where the cursor is within the first line
if (lineNumber === 1) {
return lines[0].slice(0, column);
}
// Get all lines up to the specified line number (exclusive of the current line)
const previousLines = lines.slice(0, lineNumber - 1).join('\n');
const currentLine = lines[lineNumber - 1].slice(0, column);
// Join the previous lines and the partial current line
return previousLines + '\n' + currentLine;
};
export const getValuesFromQueryField = (queryString: string, cursorPosition?: monaco.Position) => {
const queryInCursorPosition = getQueryUpToCursor(queryString, cursorPosition);
const validQuery = `${queryInCursorPosition} ""`;
const { root } = parse(validQuery);
const lastCommand = root.commands[root.commands.length - 1];
const columns: ESQLColumn[] = [];

View file

@ -28,5 +28,6 @@
"@kbn/i18n",
"@kbn/datemath",
"@kbn/es-query",
"@kbn/monaco",
]
}

View file

@ -69,6 +69,7 @@ export function ESQLControlsFlyout({
onCreateControl={onCreateControl}
onEditControl={onEditControl}
search={search}
cursorPosition={cursorPosition}
/>
);
} else if (

View file

@ -24,6 +24,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import type { ISearchGeneric } from '@kbn/search-types';
import { ESQLVariableType } from '@kbn/esql-types';
import { ESQLControlVariable } from '@kbn/esql-types';
import { monaco } from '@kbn/monaco';
import {
getIndexPatternFromESQLQuery,
getESQLResults,
@ -60,6 +61,7 @@ interface ValueControlFormProps {
onEditControl: (state: ESQLControlState) => void;
onCancelControl?: () => void;
initialState?: ESQLControlState;
cursorPosition?: monaco.Position;
}
const SUGGESTED_INTERVAL_VALUES = ['5 minutes', '1 hour', '1 day', '1 week', '1 month'];
@ -74,14 +76,15 @@ export function ValueControlForm({
closeFlyout,
onCreateControl,
onEditControl,
cursorPosition,
}: ValueControlFormProps) {
const isMounted = useMountedState();
const valuesField = useMemo(() => {
if (variableType === ESQLVariableType.VALUES) {
return getValuesFromQueryField(queryString);
return getValuesFromQueryField(queryString, cursorPosition);
}
return null;
}, [variableType, queryString]);
}, [variableType, queryString, cursorPosition]);
const suggestedVariableName = useMemo(() => {
const existingVariables = new Set(
esqlVariables