mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[ES|QL] Fixes the suggestion problem in where for multiline queries (#213240)
## Summary Closes https://github.com/elastic/kibana/issues/213323 This is the attempt to fix this bug: ``` FROM kibana_sample_data_logs | WHERE event.dataset == # cursor on this line | LIMIT 10 ``` In main the suggestions do not trigger. The problem is that the range is completely wrong. The lineNumber is 3 while it should be 2 and the start and end columns are also wrong. This PR attempts to fix it (hopefully).  ### 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
This commit is contained in:
parent
da0480bde9
commit
6f831770fd
4 changed files with 78 additions and 13 deletions
|
@ -411,7 +411,7 @@ describe('WHERE <expression>', () => {
|
||||||
detail: 'Click to create',
|
detail: 'Click to create',
|
||||||
command: { id: 'esql.control.values.create', title: 'Click to create' },
|
command: { id: 'esql.control.values.create', title: 'Click to create' },
|
||||||
sortText: '11',
|
sortText: '11',
|
||||||
rangeToReplace: { start: 31, end: 31 },
|
rangeToReplace: { start: 30, end: 30 },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -439,7 +439,7 @@ describe('WHERE <expression>', () => {
|
||||||
detail: 'Named parameter',
|
detail: 'Named parameter',
|
||||||
command: undefined,
|
command: undefined,
|
||||||
sortText: '11A',
|
sortText: '11A',
|
||||||
rangeToReplace: { start: 31, end: 31 },
|
rangeToReplace: { start: 30, end: 30 },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -608,7 +608,7 @@ export async function getSuggestionsToRightOfOperatorExpression({
|
||||||
) {
|
) {
|
||||||
suggestions.push(listCompleteItem);
|
suggestions.push(listCompleteItem);
|
||||||
} else {
|
} else {
|
||||||
const finalType = leftArgType || leftArgType || 'any';
|
const finalType = leftArgType || 'any';
|
||||||
const supportedTypes = getSupportedTypesForBinaryOperators(fnDef, finalType as string);
|
const supportedTypes = getSupportedTypesForBinaryOperators(fnDef, finalType as string);
|
||||||
|
|
||||||
// this is a special case with AND/OR
|
// this is a special case with AND/OR
|
||||||
|
@ -671,12 +671,11 @@ export async function getSuggestionsToRightOfOperatorExpression({
|
||||||
}
|
}
|
||||||
return suggestions.map<SuggestionRawDefinition>((s) => {
|
return suggestions.map<SuggestionRawDefinition>((s) => {
|
||||||
const overlap = getOverlapRange(queryText, s.text);
|
const overlap = getOverlapRange(queryText, s.text);
|
||||||
const offset = overlap.start === overlap.end ? 1 : 0;
|
|
||||||
return {
|
return {
|
||||||
...s,
|
...s,
|
||||||
rangeToReplace: {
|
rangeToReplace: {
|
||||||
start: overlap.start + offset,
|
start: overlap.start,
|
||||||
end: overlap.end + offset,
|
end: overlap.end,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the "Elastic License
|
||||||
|
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||||
|
* Public License v 1"; you may not use this file except in compliance with, at
|
||||||
|
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||||
|
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||||
|
*/
|
||||||
|
import { offsetRangeToMonacoRange } from './utils';
|
||||||
|
|
||||||
|
describe('offsetRangeToMonacoRange', () => {
|
||||||
|
test('should convert offset range to monaco range when the cursor is not at the end', () => {
|
||||||
|
const expression = 'FROM test | WHERE test == | LIMIT 1';
|
||||||
|
const range = { start: 26, end: 26 };
|
||||||
|
const monacoRange = offsetRangeToMonacoRange(expression, range);
|
||||||
|
|
||||||
|
expect(monacoRange).toEqual({
|
||||||
|
startColumn: 26,
|
||||||
|
endColumn: 26,
|
||||||
|
startLineNumber: 1,
|
||||||
|
endLineNumber: 1,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should convert offset range to monaco range when the cursor is at the end', () => {
|
||||||
|
const expression = 'FROM test | WHERE test == 1 | LIMIT 1';
|
||||||
|
const range = { start: 37, end: 37 };
|
||||||
|
const monacoRange = offsetRangeToMonacoRange(expression, range);
|
||||||
|
|
||||||
|
expect(monacoRange).toEqual({
|
||||||
|
startColumn: 37,
|
||||||
|
endColumn: 37,
|
||||||
|
startLineNumber: 1,
|
||||||
|
endLineNumber: 1,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should convert offset range to monaco range for multiple lines query when the cursor is not at the end', () => {
|
||||||
|
const expression = 'FROM test \n| WHERE test == \n| LIMIT 1';
|
||||||
|
const range = { start: 27, end: 27 };
|
||||||
|
const monacoRange = offsetRangeToMonacoRange(expression, range);
|
||||||
|
|
||||||
|
expect(monacoRange).toEqual({
|
||||||
|
startColumn: 16,
|
||||||
|
endColumn: 16,
|
||||||
|
startLineNumber: 2,
|
||||||
|
endLineNumber: 2,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should convert offset range to monaco range for multiple lines query when the cursor is at the end', () => {
|
||||||
|
const expression = 'FROM test \n| WHERE test == \n| LIMIT 1';
|
||||||
|
const range = { start: 35, end: 35 };
|
||||||
|
const monacoRange = offsetRangeToMonacoRange(expression, range);
|
||||||
|
|
||||||
|
expect(monacoRange).toEqual({
|
||||||
|
startColumn: 7,
|
||||||
|
endColumn: 7,
|
||||||
|
startLineNumber: 3,
|
||||||
|
endLineNumber: 3,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -47,22 +47,25 @@ export const offsetRangeToMonacoRange = (
|
||||||
let endLineNumber = 1;
|
let endLineNumber = 1;
|
||||||
let currentLine = 1;
|
let currentLine = 1;
|
||||||
|
|
||||||
for (let i = 0; i < expression.length; i++) {
|
const hasMultipleLines = expression.includes('\n');
|
||||||
if (expression[i] === '\n') {
|
const offset = hasMultipleLines ? 1 : 0;
|
||||||
currentLine++;
|
|
||||||
currentOffset = i + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i === range.start) {
|
for (let i = 0; i < expression.length; i++) {
|
||||||
|
if (i === range.start - offset) {
|
||||||
startLineNumber = currentLine;
|
startLineNumber = currentLine;
|
||||||
startColumn = i - currentOffset;
|
startColumn = i - currentOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i === range.end) {
|
if (i === range.end - offset) {
|
||||||
endLineNumber = currentLine;
|
endLineNumber = currentLine;
|
||||||
endColumn = i - currentOffset;
|
endColumn = i - currentOffset;
|
||||||
break; // No need to continue once we find the end position
|
break; // No need to continue once we find the end position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (expression[i] === '\n') {
|
||||||
|
currentLine++;
|
||||||
|
currentOffset = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the case where the start offset is past the end of the string
|
// Handle the case where the start offset is past the end of the string
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue