Skip to content

Commit

Permalink
Merge branch 'main' into 190311-infra-replace-metricsuiaggregation-in…
Browse files Browse the repository at this point in the history
…-favor-of-estypesaggregationsaggregate
  • Loading branch information
jennypavlova authored Aug 20, 2024
2 parents 5d70525 + 929d407 commit 30cf479
Show file tree
Hide file tree
Showing 77 changed files with 3,300 additions and 791 deletions.
2 changes: 1 addition & 1 deletion docs/api/role-management/put-bulk.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ Grant full access to all features in the Default space for `my_kibana_role_1` an

[source,sh]
--------------------------------------------------
$ curl -X PUT api/security/role
$ curl -X POST api/security/roles
{
"roles": {
"my_kibana_role_1": {
Expand Down
92 changes: 92 additions & 0 deletions packages/kbn-esql-ast/src/__tests__/ast_parser.columns.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

import { getAstAndSyntaxErrors as parse } from '../ast_parser';

describe('Column Identifier Expressions', () => {
it('can parse un-quoted identifiers', () => {
const text = 'ROW a, b.c';
const { ast } = parse(text);

expect(ast).toMatchObject([
{
type: 'command',
args: [
{
type: 'column',
parts: ['a'],
},
{
type: 'column',
parts: ['b', 'c'],
},
],
},
]);
});

it('can parse quoted identifiers', () => {
const text = 'ROW `a`, `b`.c, `d`.`👍`.`123``123`';
const { ast } = parse(text);

expect(ast).toMatchObject([
{
type: 'command',
args: [
{
type: 'column',
parts: ['a'],
},
{
type: 'column',
parts: ['b', 'c'],
},
{
type: 'column',
parts: ['d', '👍', '123`123'],
},
],
},
]);
});

it('can mix quoted and un-quoted identifiers', () => {
const text = 'ROW part1.part2.`part``3️⃣`';
const { ast } = parse(text);

expect(ast).toMatchObject([
{
type: 'command',
args: [
{
type: 'column',
parts: ['part1', 'part2', 'part`3️⃣'],
},
],
},
]);
});

it('in KEEP command', () => {
const text = 'FROM a | KEEP a.b';
const { ast } = parse(text);

expect(ast).toMatchObject([
{},
{
type: 'command',
args: [
{
type: 'column',
parts: ['a', 'b'],
},
],
},
]);
});
});
33 changes: 25 additions & 8 deletions packages/kbn-esql-ast/src/ast_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
*/

import { type Token, type ParserRuleContext, type TerminalNode } from 'antlr4';
import type {
ArithmeticUnaryContext,
DecimalValueContext,
InlineCastContext,
IntegerValueContext,
QualifiedIntegerLiteralContext,
import {
QualifiedNameContext,
type ArithmeticUnaryContext,
type DecimalValueContext,
type InlineCastContext,
type IntegerValueContext,
type QualifiedIntegerLiteralContext,
QualifiedNamePatternContext,
} from './antlr/esql_parser';
import { getPosition } from './ast_position_utils';
import { DOUBLE_TICKS_REGEX, SINGLE_BACKTICK, TICKS_REGEX } from './constants';
Expand All @@ -39,6 +41,7 @@ import type {
FunctionSubtype,
ESQLNumericLiteral,
} from './types';
import { parseIdentifier } from './parser/helpers';

export function nonNullable<T>(v: T): v is NonNullable<T> {
return v != null;
Expand Down Expand Up @@ -360,22 +363,36 @@ export function createSource(
}

export function createColumnStar(ctx: TerminalNode): ESQLColumn {
const text = ctx.getText();

return {
type: 'column',
name: ctx.getText(),
text: ctx.getText(),
name: text,
parts: [text],
text,
location: getPosition(ctx.symbol),
incomplete: ctx.getText() === '',
quoted: false,
};
}

export function createColumn(ctx: ParserRuleContext): ESQLColumn {
const parts: string[] = [];
if (ctx instanceof QualifiedNamePatternContext) {
parts.push(
...ctx.identifierPattern_list().map((identifier) => parseIdentifier(identifier.getText()))
);
} else if (ctx instanceof QualifiedNameContext) {
parts.push(...ctx.identifier_list().map((identifier) => parseIdentifier(identifier.getText())));
} else {
parts.push(sanitizeIdentifierString(ctx));
}
const text = sanitizeIdentifierString(ctx);
const hasQuotes = Boolean(getQuotedText(ctx) || isQuoted(ctx.getText()));
return {
type: 'column' as const,
name: text,
parts,
text: ctx.getText(),
location: getPosition(ctx.start, ctx.stop),
incomplete: Boolean(ctx.exception || text === ''),
Expand Down
37 changes: 37 additions & 0 deletions packages/kbn-esql-ast/src/parser/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

export const isQuotedIdentifier = (text: string): boolean => {
const firstChar = text[0];
const lastChar = text[text.length - 1];

return firstChar === '`' && lastChar === '`';
};

export const parseIdentifier = (text: string): string => {
const isQuoted = isQuotedIdentifier(text);

if (!isQuoted) {
return text;
}

return text.slice(1, -1).replace(/``/g, '`');
};

export const regexUnquotedIdentifierPattern = /^([a-z\*_\@]{1})[a-z0-9_\*]*$/i;

export const formatIdentifier = (text: string): string => {
if (regexUnquotedIdentifierPattern.test(text)) {
return text;
}

return `\`${text.replace(/`/g, '``')}\``;
};

export const formatIdentifierParts = (parts: string[]): string =>
parts.map(formatIdentifier).join('.');
16 changes: 16 additions & 0 deletions packages/kbn-esql-ast/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,22 @@ export interface ESQLSource extends ESQLAstBaseItem {

export interface ESQLColumn extends ESQLAstBaseItem {
type: 'column';

/**
* An identifier can be composed of multiple parts, e.g: part1.part2.`part``3️⃣`.
* This property contains the parsed unquoted parts of the identifier.
* For example: `['part1', 'part2', 'part`3️⃣']`.
*/
parts: string[];

/**
* @deprecated
*
* An identifier can be composed of multiple parts, e.g: part1.part2.`part3️⃣`
*
* Each part can be quoted or not quoted independently. A single `quoted`
* property is not enough to represent the identifier. Use `parts` instead.
*/
quoted: boolean;
}

Expand Down
35 changes: 9 additions & 26 deletions packages/kbn-monaco/src/console/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,7 @@ export const createParser = () => {
requestStartOffset = at - 1;
requests.push({ startOffset: requestStartOffset });
},
addRequestMethod = function(method) {
const lastRequest = getLastRequest();
lastRequest.method = method;
requests.push(lastRequest);
requestEndOffset = at - 1;
},
addRequestUrl = function(url) {
const lastRequest = getLastRequest();
lastRequest.url = url;
requests.push(lastRequest);
requestEndOffset = at - 1;
},
addRequestData = function(data) {
const lastRequest = getLastRequest();
const dataArray = lastRequest.data || [];
dataArray.push(data);
lastRequest.data = dataArray;
requests.push(lastRequest);
updateRequestEnd = function () {
requestEndOffset = at - 1;
},
addRequestEnd = function() {
Expand Down Expand Up @@ -409,26 +392,26 @@ export const createParser = () => {
request = function () {
white();
addRequestStart();
const parsedMethod = method();
addRequestMethod(parsedMethod);
method();
updateRequestEnd();
strictWhite();
const parsedUrl = url();
addRequestUrl(parsedUrl);
url();
updateRequestEnd();
strictWhite(); // advance to one new line
newLine();
strictWhite();
if (ch == '{') {
const parsedObject = object();
addRequestData(parsedObject);
object();
updateRequestEnd();
}
// multi doc request
strictWhite(); // advance to one new line
newLine();
strictWhite();
while (ch == '{') {
// another object
const parsedObject = object();
addRequestData(parsedObject);
object();
updateRequestEnd();
strictWhite();
newLine();
strictWhite();
Expand Down
21 changes: 8 additions & 13 deletions packages/kbn-monaco/src/console/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ describe('console parser', () => {
const { requests, errors } = parser(input) as ConsoleParserResult;
expect(requests.length).toBe(1);
expect(errors.length).toBe(0);
const { method, url, startOffset, endOffset } = requests[0];
expect(method).toBe('GET');
expect(url).toBe('_search');
const { startOffset, endOffset } = requests[0];
// the start offset of the request is the beginning of the string
expect(startOffset).toBe(0);
// the end offset of the request is the end of the string
Expand All @@ -38,22 +36,19 @@ describe('console parser', () => {
const input = 'GET _search\nPOST _test_index';
const { requests } = parser(input) as ConsoleParserResult;
expect(requests.length).toBe(2);
expect(requests[0].startOffset).toBe(0);
expect(requests[0].endOffset).toBe(11);
expect(requests[1].startOffset).toBe(12);
expect(requests[1].endOffset).toBe(28);
});

it('parses a request with a request body', () => {
const input =
'GET _search\n' + '{\n' + ' "query": {\n' + ' "match_all": {}\n' + ' }\n' + '}';
const { requests } = parser(input) as ConsoleParserResult;
expect(requests.length).toBe(1);
const { method, url, data } = requests[0];
expect(method).toBe('GET');
expect(url).toBe('_search');
expect(data).toEqual([
{
query: {
match_all: {},
},
},
]);
const { startOffset, endOffset } = requests[0];
expect(startOffset).toBe(0);
expect(endOffset).toBe(52);
});
});
3 changes: 0 additions & 3 deletions packages/kbn-monaco/src/console/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ export interface ErrorAnnotation {
export interface ParsedRequest {
startOffset: number;
endOffset?: number;
method: string;
url?: string;
data?: Array<Record<string, unknown>>;
}
export interface ConsoleParserResult {
errors: ErrorAnnotation[];
Expand Down
Loading

0 comments on commit 30cf479

Please sign in to comment.