Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/management/advanced-options.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ compatible with other configuration settings. Deleting a custom setting removes
.Kibana Settings Reference
[horizontal]
`query:queryString:options`:: Options for the Lucene query string parser.
`query:allowLeadingWildcards`:: When set, * is allowed as the first character in a query clause. Currently only applies when experimental query features are enabled in the query bar. To disallow leading wildcards in basic lucene queries, use query:queryString:options.
Copy link

@w33ble w33ble Mar 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the convention here that query:queryString will be for lucene settings, while query:<anything else> will be for Kuery?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I suppose so, hopefully we won't be adding any more settings specifically for lucene and eventually we'll remove query:queryString:options

`search:queryLanguage`:: Default is `lucene`. Query language used by the query bar. Choose between the lucene query syntax and kuery, an experimental new language built specifically for Kibana.
`search:queryLanguage:switcher:enable`:: Show or hide the query language switcher in the query bar.
`sort:options`:: Options for the Elasticsearch {ref}/search-request-sort.html[sort] parameter.
Expand Down
4 changes: 4 additions & 0 deletions src/core_plugins/kibana/ui_setting_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export function getUiSettingDefaults() {
description: '<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html" target="_blank" rel="noopener noreferrer">Options</a> for the lucene query string parser',
type: 'json'
},
'query:allowLeadingWildcards': {
value: true,
description: 'When set, * is allowed as the first character in a query clause. Currently only applies when experimental query features are enabled in the query bar. To disallow leading wildcards in basic lucene queries, use query:queryString:options',
},
'search:queryLanguage': {
value: 'lucene',
description: 'Query language used by the query bar. Kuery is an experimental new language built specifically for Kibana.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { buildQueryFromKuery } from './from_kuery';
import { buildQueryFromFilters } from './from_filters';
import { buildQueryFromLucene } from './from_lucene';

export function BuildESQueryProvider(Private) {
export function BuildESQueryProvider(Private, config) {
const decorateQuery = Private(DecorateQueryProvider);

/**
Expand All @@ -16,7 +16,7 @@ export function BuildESQueryProvider(Private) {
const validQueries = queries.filter((query) => has(query, 'query'));
const queriesByLanguage = groupBy(validQueries, 'language');

const kueryQuery = buildQueryFromKuery(indexPattern, queriesByLanguage.kuery);
const kueryQuery = buildQueryFromKuery(indexPattern, queriesByLanguage.kuery, config);
const luceneQuery = buildQueryFromLucene(queriesByLanguage.lucene, decorateQuery);
const filterQuery = buildQueryFromFilters(filters, decorateQuery, indexPattern);

Expand Down
13 changes: 11 additions & 2 deletions src/ui/public/courier/data_source/build_query/from_kuery.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import { fromLegacyKueryExpression, fromKueryExpression, toElasticsearchQuery, nodeTypes } from '../../../kuery';
import { documentationLinks } from '../../../documentation_links';
import { NoLeadingWildcardsError } from '../../../kuery/errors';

const queryDocs = documentationLinks.query;

export function buildQueryFromKuery(indexPattern, queries = []) {
export function buildQueryFromKuery(indexPattern, queries = [], config) {
const allowLeadingWildcards = config.get('query:allowLeadingWildcards');



const queryASTs = queries.map((query) => {
try {
return fromKueryExpression(query.query);
return fromKueryExpression(query.query, { allowLeadingWildcards });
}
catch (parseError) {
if (parseError instanceof NoLeadingWildcardsError) {
throw parseError;
}

try {
fromLegacyKueryExpression(query.query);
}
Expand Down
3 changes: 2 additions & 1 deletion src/ui/public/kuery/ast/ast.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import _ from 'lodash';
import { nodeTypes } from '../node_types/index';
import * as errors from '../errors';
import { parse as parseKuery } from './kuery';
import { parse as parseLegacyKuery } from './legacy_kuery';

Expand Down Expand Up @@ -27,7 +28,7 @@ function fromExpression(expression, parseOptions = {}, parse = parseKuery) {

parseOptions = {
...parseOptions,
helpers: { nodeTypes }
helpers: { nodeTypes, errors }
};

return parse(expression, parseOptions);
Expand Down
7 changes: 6 additions & 1 deletion src/ui/public/kuery/ast/kuery.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion src/ui/public/kuery/ast/kuery.peg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Initialization block
{
const { parseCursor, cursorSymbol, helpers: { nodeTypes } } = options;
const { parseCursor, cursorSymbol, allowLeadingWildcards = true, helpers: { nodeTypes, errors } } = options;
const buildFunctionNode = nodeTypes.function.buildNodeWithArgumentNodes;
const buildLiteralNode = nodeTypes.literal.buildNode;
const buildWildcardNode = nodeTypes.wildcard.buildNode;
Expand Down Expand Up @@ -156,6 +156,11 @@ Value
}
/ value:UnquotedLiteral {
if (value.type === 'cursor') return value;

if (!allowLeadingWildcards && value.type === 'wildcard' && nodeTypes.wildcard.hasLeadingWildcard(value)) {
throw new errors.NoLeadingWildcardsError();
}

const isPhrase = buildLiteralNode(false);
return (field) => buildFunctionNode('is', [field, value, isPhrase]);
}
Expand Down
10 changes: 10 additions & 0 deletions src/ui/public/kuery/errors/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { KbnError } from '../../errors';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This is the first KbnError that's not just in /src/ui/public/errors.js, so the argument can be made to just put this in there as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the difference here is that these errors are only meant to be thrown by the parser, so it makes sense to co-locate them with the grammar. Eventually I imagine us having a bunch of these parser errors. I wouldn't have even extended KbnError if extending Error was easier in javascript.

In general I've been trying to keep all kuery code inside the kuery directory so it doesn't become an incomprehensible mess spread across the entire codebase (see: visualize).


export class NoLeadingWildcardsError extends KbnError {
constructor() {
super(
'Leading wildcards are disabled. See query:allowLeadingWildcards in Advanced Settings.',
NoLeadingWildcardsError
);
}
}
5 changes: 5 additions & 0 deletions src/ui/public/kuery/node_types/wildcard.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ export function toQueryStringQuery(node) {
const { value } = node;
return value.split(wildcardSymbol).map(escapeQueryString).join('*');
}

export function hasLeadingWildcard(node) {
Copy link

@w33ble w33ble Mar 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This seems to be the first function not aimed at building or converting a node, but testing a value. Maybe it makes sense to do this in buildNode instead and check for value.hasLeadingWildcard in the peg definition?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test function is also not aimed at building or converting, so I think there's precedence here.

Also, these objects aren't strictly immutable, so the node could change and then value.hasLeadingWildcard would be out of date.

const { value } = node;
return value.startsWith(wildcardSymbol);
}