Skip to content

Commit

Permalink
Merge branch '8.x' into backport/8.x/pr-196291
Browse files Browse the repository at this point in the history
  • Loading branch information
angorayc authored Oct 23, 2024
2 parents 24fb45c + b3fef2a commit e9574be
Show file tree
Hide file tree
Showing 53 changed files with 1,795 additions and 507 deletions.
27 changes: 25 additions & 2 deletions packages/kbn-esql-ast/src/ast/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,22 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { ESQLAstNode, ESQLBinaryExpression, ESQLFunction } from '../types';
import type {
ESQLAstNode,
ESQLBinaryExpression,
ESQLColumn,
ESQLFunction,
ESQLIntegerLiteral,
ESQLLiteral,
ESQLProperNode,
} from '../types';
import { BinaryExpressionGroup } from './constants';

export const isProperNode = (node: unknown): node is ESQLProperNode =>
!!node && typeof node === 'object' && !Array.isArray(node);

export const isFunctionExpression = (node: unknown): node is ESQLFunction =>
!!node && typeof node === 'object' && !Array.isArray(node) && (node as any).type === 'function';
isProperNode(node) && node.type === 'function';

/**
* Returns true if the given node is a binary expression, i.e. an operator
Expand All @@ -28,6 +39,18 @@ export const isFunctionExpression = (node: unknown): node is ESQLFunction =>
export const isBinaryExpression = (node: unknown): node is ESQLBinaryExpression =>
isFunctionExpression(node) && node.subtype === 'binary-expression';

export const isLiteral = (node: unknown): node is ESQLLiteral =>
isProperNode(node) && node.type === 'literal';

export const isIntegerLiteral = (node: unknown): node is ESQLIntegerLiteral =>
isLiteral(node) && node.literalType === 'integer';

export const isDoubleLiteral = (node: unknown): node is ESQLIntegerLiteral =>
isLiteral(node) && node.literalType === 'double';

export const isColumn = (node: unknown): node is ESQLColumn =>
isProperNode(node) && node.type === 'column';

/**
* Returns the group of a binary expression:
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const reprint = (src: string) => {
const { root } = parse(src);
const text = BasicPrettyPrinter.print(root);

// console.log(JSON.stringify(ast, null, 2));
// console.log(JSON.stringify(root, null, 2));

return { text };
};
Expand Down Expand Up @@ -194,6 +194,66 @@ describe('single line query', () => {

expect(text).toBe('ROW NOT a');
});

test('negative numbers', () => {
const { text } = reprint('ROW -1');

expect(text).toBe('ROW -1');
});

test('negative numbers in brackets', () => {
const { text } = reprint('ROW -(1)');

expect(text).toBe('ROW -1');
});

test('negative column names', () => {
const { text } = reprint('ROW -col');

expect(text).toBe('ROW -col');
});

test('plus unary expression', () => {
const { text } = reprint('ROW +(23)');

expect(text).toBe('ROW 23');
});

test('chained multiple unary expressions', () => {
const { text } = reprint('ROW ----+-+(23)');

expect(text).toBe('ROW -23');
});

test('before another expression', () => {
const { text } = reprint('ROW ----+-+(1 + 1)');

expect(text).toBe('ROW -(1 + 1)');
});

test('negative one from the right side', () => {
const { text } = reprint('ROW 2 * -1');

expect(text).toBe('ROW -2');
});

test('two minuses is plus', () => {
const { text } = reprint('ROW --123');

expect(text).toBe('ROW 123');
});

test('two minuses is plus (float)', () => {
const { text } = reprint('ROW --1.23');

expect(text).toBe('ROW 1.23');
});

test('two minuses is plus (with brackets)', () => {
const { text } = reprint('ROW --(123)');

expect(text).toBe('ROW 123');
});
});

describe('postfix unary expression', () => {
Expand Down
79 changes: 78 additions & 1 deletion packages/kbn-esql-ast/src/pretty_print/basic_pretty_printer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,18 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { binaryExpressionGroup } from '../ast/helpers';
import {
binaryExpressionGroup,
isBinaryExpression,
isColumn,
isDoubleLiteral,
isIntegerLiteral,
isLiteral,
isProperNode,
} from '../ast/helpers';
import { ESQLAstBaseItem, ESQLAstCommand, ESQLAstQueryExpression } from '../types';
import { ESQLAstExpressionNode, Visitor } from '../visitor';
import { resolveItem } from '../visitor/utils';
import { LeafPrinter } from './leaf_printer';

export interface BasicPrettyPrinterOptions {
Expand Down Expand Up @@ -152,6 +161,62 @@ export class BasicPrettyPrinter {
return formatted;
}

protected simplifyMultiplicationByOne(
node: ESQLAstExpressionNode,
minusCount: number = 0
): string | undefined {
if (isBinaryExpression(node) && node.name === '*') {
let [left, right] = node.args;
left = resolveItem(left);
right = resolveItem(right);

if (isProperNode(left) && isProperNode(right)) {
if (!!left.formatting || !!right.formatting) {
return undefined;
}
if (isIntegerLiteral(left)) {
if (left.value === 1) {
return this.simplifyMultiplicationByOne(right, minusCount);
} else if (left.value === -1) {
return this.simplifyMultiplicationByOne(right, minusCount + 1);
}
}
if (isIntegerLiteral(right)) {
if (right.value === 1) {
return this.simplifyMultiplicationByOne(left, minusCount);
} else if (right.value === -1) {
return this.simplifyMultiplicationByOne(left, minusCount + 1);
}
}
return undefined;
} else {
return undefined;
}
}

const isNegative = minusCount % 2 === 1;

if (isNegative && (isIntegerLiteral(node) || isDoubleLiteral(node)) && node.value < 0) {
return BasicPrettyPrinter.expression(
{
...node,
value: Math.abs(node.value),
},
this.opts
);
}

let expression = BasicPrettyPrinter.expression(node, this.opts);
const sign = isNegative ? '-' : '';
const needsBrackets = !!sign && !isColumn(node) && !isLiteral(node);

if (needsBrackets) {
expression = `(${expression})`;
}

return sign ? `${sign}${expression}` : expression;
}

protected readonly visitor: Visitor<any> = new Visitor()
.on('visitExpression', (ctx) => {
return '<EXPRESSION>';
Expand Down Expand Up @@ -237,6 +302,18 @@ export class BasicPrettyPrinter {
const groupLeft = binaryExpressionGroup(left);
const groupRight = binaryExpressionGroup(right);

if (
node.name === '*' &&
((isIntegerLiteral(left) && Math.abs(left.value) === 1) ||
(isIntegerLiteral(right) && Math.abs(right.value) === 1))
) {
const formatted = this.simplifyMultiplicationByOne(node);

if (formatted) {
return formatted;
}
}

let leftFormatted = ctx.visitArgument(0);
let rightFormatted = ctx.visitArgument(1);

Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-esql-ast/src/pretty_print/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { ESQLAstBaseItem, ESQLProperNode } from '../types';
import type { ESQLAstBaseItem, ESQLProperNode } from '../types';
import { Walker } from '../walker';

export interface QueryPrettyPrintStats {
Expand Down
4 changes: 4 additions & 0 deletions packages/kbn-esql-ast/src/visitor/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export const firstItem = (items: ESQLAstItem[]): ESQLSingleAstItem | undefined =
}
};

export const resolveItem = (items: ESQLAstItem | ESQLAstItem[]): ESQLAstItem => {
return Array.isArray(items) ? resolveItem(items[0]) : items;
};

/**
* Returns the last normalized "single item" from the "item" list.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ describe('autocomplete', () => {
{ filterText: '_source', text: '_source, ', command: TRIGGER_SUGGESTION_COMMAND },
]);
// no comma if there are no more fields
testSuggestions('FROM a METADATA _id, _ignored, _index, _source, _version/', [
testSuggestions('FROM a METADATA _id, _ignored, _index, _source, _index_mode, _version/', [
{ filterText: '_version', text: '_version | ', command: TRIGGER_SUGGESTION_COMMAND },
]);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ export const SINGLE_TICK_REGEX = /`/g;
export const DOUBLE_BACKTICK = '``';
export const SINGLE_BACKTICK = '`';

export const METADATA_FIELDS = ['_version', '_id', '_index', '_source', '_ignored'];
export const METADATA_FIELDS = ['_version', '_id', '_index', '_source', '_ignored', '_index_mode'];
26 changes: 19 additions & 7 deletions src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@
import React, { ReactElement } from 'react';
import classNames from 'classnames';

import { MountPoint } from '@kbn/core/public';
import type { MountPoint } from '@kbn/core/public';
import { MountPointPortal } from '@kbn/react-kibana-mount';
import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
import { StatefulSearchBarProps } from '@kbn/unified-search-plugin/public';
import { AggregateQuery, Query } from '@kbn/es-query';
import { TopNavMenuData } from './top_nav_menu_data';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
import type { StatefulSearchBarProps } from '@kbn/unified-search-plugin/public';
import type { AggregateQuery, Query } from '@kbn/es-query';
import type { EuiBreakpointSize } from '@elastic/eui';
import type { TopNavMenuData } from './top_nav_menu_data';
import { TopNavMenuItems } from './top_nav_menu_items';
import { TopNavMenuBadgeProps, TopNavMenuBadges } from './top_nav_menu_badges';
import { type TopNavMenuBadgeProps, TopNavMenuBadges } from './top_nav_menu_badges';

export type TopNavMenuProps<QT extends Query | AggregateQuery = Query> = Omit<
StatefulSearchBarProps<QT>,
Expand Down Expand Up @@ -51,6 +52,11 @@ export type TopNavMenuProps<QT extends Query | AggregateQuery = Query> = Omit<
* ```
*/
setMenuMountPoint?: (menuMount: MountPoint | undefined) => void;

/**
* A list of named breakpoints at which to show the popover version. If not provided, it will use the default set of ['xs', 's'] that is internally provided by EUI.
*/
popoverBreakpoints?: EuiBreakpointSize[];
};

/*
Expand All @@ -76,7 +82,13 @@ export function TopNavMenu<QT extends AggregateQuery | Query = Query>(
}

function renderMenu(className: string): ReactElement | null {
return <TopNavMenuItems config={config} className={className} />;
return (
<TopNavMenuItems
config={config}
className={className}
popoverBreakpoints={props.popoverBreakpoints}
/>
);
}

function renderSearchBar(): ReactElement | null {
Expand Down
21 changes: 15 additions & 6 deletions src/plugins/navigation/public/top_nav_menu/top_nav_menu_items.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,30 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { EuiHeaderLinks } from '@elastic/eui';
import { EuiBreakpointSize, EuiHeaderLinks } from '@elastic/eui';
import React from 'react';
import type { TopNavMenuData } from './top_nav_menu_data';
import { TopNavMenuItem } from './top_nav_menu_item';

interface TopNavMenuItemsProps {
config: TopNavMenuData[] | undefined;
className?: string;
popoverBreakpoints?: EuiBreakpointSize[];
}

export const TopNavMenuItems = ({
config,
className,
}: {
config: TopNavMenuData[] | undefined;
className?: string;
}) => {
popoverBreakpoints,
}: TopNavMenuItemsProps) => {
if (!config || config.length === 0) return null;
return (
<EuiHeaderLinks data-test-subj="top-nav" gutterSize="xs" className={className}>
<EuiHeaderLinks
data-test-subj="top-nav"
gutterSize="xs"
className={className}
popoverBreakpoints={popoverBreakpoints}
>
{config.map((menuItem: TopNavMenuData, i: number) => {
return <TopNavMenuItem key={`nav-menu-${i}`} {...menuItem} />;
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,16 @@ export type InferenceServiceSettings =
};
};
}
| {
service: 'watsonxai';
service_settings: {
api_key: string;
url: string;
model_id: string;
project_id: string;
api_version: string;
};
}
| {
service: 'amazonbedrock';
service_settings: {
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/alerting/server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import { deleteRuleRoute } from './rule/apis/delete/delete_rule_route';
import { aggregateRulesRoute } from './rule/apis/aggregate/aggregate_rules_route';
import { disableRuleRoute } from './rule/apis/disable/disable_rule_route';
import { enableRuleRoute } from './rule/apis/enable/enable_rule_route';
import { findRulesRoute, findInternalRulesRoute } from './rule/apis/find/find_rules_route';
import { findRulesRoute } from './rule/apis/find/find_rules_route';
import { findInternalRulesRoute } from './rule/apis/find/find_internal_rules_route';
import { getRuleAlertSummaryRoute } from './get_rule_alert_summary';
import { getRuleExecutionLogRoute } from './get_rule_execution_log';
import { getGlobalExecutionLogRoute } from './get_global_execution_logs';
Expand Down
Loading

0 comments on commit e9574be

Please sign in to comment.