forked from elastic/elasticsearch
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[KQL Query] Create the ANTLR parser (elastic#114927)
- Loading branch information
Showing
19 changed files
with
3,033 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import org.elasticsearch.gradle.internal.info.BuildParams | ||
|
||
apply plugin: 'elasticsearch.internal-es-plugin' | ||
apply plugin: 'elasticsearch.internal-cluster-test' | ||
apply plugin: 'elasticsearch.publish' | ||
|
||
esplugin { | ||
name 'x-pack-kql' | ||
description 'Elasticsearch Expanded Pack Plugin - KQL query' | ||
classname 'org.elasticsearch.xpack.kql.KqlPlugin' | ||
extendedPlugins = ['x-pack-core'] | ||
} | ||
base { | ||
archivesName = 'x-pack-kql' | ||
} | ||
|
||
dependencies { | ||
compileOnly project(path: xpackModule('core')) | ||
compileOnly "org.antlr:antlr4-runtime:${versions.antlr4}" | ||
|
||
testImplementation "org.antlr:antlr4-runtime:${versions.antlr4}" | ||
testImplementation project(':test:framework') | ||
testImplementation(testArtifact(project(xpackModule('core')))) | ||
} | ||
|
||
/**************************************************************** | ||
* Enable QA/rest integration tests for snapshot builds only * | ||
* TODO: Enable for all builds upon this feature release * | ||
****************************************************************/ | ||
if (BuildParams.isSnapshotBuild()) { | ||
addQaCheckDependencies(project) | ||
} | ||
|
||
/********************************** | ||
* KQL parser configuration * | ||
**********************************/ | ||
configurations { | ||
regenerate | ||
} | ||
|
||
dependencies { | ||
regenerate "org.antlr:antlr4:${versions.antlr4}" | ||
} | ||
|
||
String grammarPath = 'src/main/antlr' | ||
String outputPath = 'src/main/java/org/elasticsearch/xpack/kql/parser' | ||
|
||
pluginManager.withPlugin('com.diffplug.spotless') { | ||
spotless { | ||
java { | ||
// for some reason "${outputPath}/KqlBaser*.java" does not match the same files... | ||
targetExclude "src/main/java/org/elasticsearch/xpack/kql/parser/KqlBase*.java" | ||
} | ||
} | ||
} | ||
tasks.named('checkstyleMain').configure { | ||
exclude { it.file.toString().contains("src/main/java/org/elasticsearch/xpack/kql/parser/KqlBase") } | ||
} | ||
|
||
tasks.register("cleanGenerated", Delete) { | ||
delete fileTree(grammarPath) { | ||
include '*.tokens' | ||
} | ||
delete fileTree(outputPath) { | ||
include 'KqlBase*.java' | ||
include 'KqlBase*.interp' | ||
} | ||
} | ||
|
||
tasks.register("regenParser", JavaExec) { | ||
dependsOn "cleanGenerated" | ||
mainClass = 'org.antlr.v4.Tool' | ||
classpath = configurations.regenerate | ||
systemProperty 'file.encoding', 'UTF-8' | ||
systemProperty 'user.language', 'en' | ||
systemProperty 'user.country', 'US' | ||
systemProperty 'user.variant', '' | ||
args '-Werror', | ||
'-package', 'org.elasticsearch.xpack.kql.parser', | ||
'-listener', | ||
'-visitor', | ||
'-o', outputPath, | ||
"${file(grammarPath)}/KqlBase.g4" | ||
} | ||
|
||
tasks.register("regen") { | ||
dependsOn "regenParser" | ||
doLast { | ||
// moves token files to grammar directory for use with IDE's | ||
ant.move(file: "${outputPath}/KqlBase.tokens", toDir: grammarPath) | ||
ant.move(file: "${outputPath}/KqlBaseLexer.tokens", toDir: grammarPath) | ||
// make the generated classes package private | ||
ant.replaceregexp(match: 'public ((interface|class) \\QKqlBase\\E\\w+)', | ||
replace: '\\1', | ||
encoding: 'UTF-8') { | ||
fileset(dir: outputPath, includes: 'KqlBase*.java') | ||
} | ||
// nuke timestamps/filenames in generated files | ||
ant.replaceregexp(match: '\\Q// Generated from \\E.*', | ||
replace: '\\/\\/ ANTLR GENERATED CODE: DO NOT EDIT', | ||
encoding: 'UTF-8') { | ||
fileset(dir: outputPath, includes: 'KqlBase*.java') | ||
} | ||
// remove tabs in antlr generated files | ||
ant.replaceregexp(match: '\t', flags: 'g', replace: ' ', encoding: 'UTF-8') { | ||
fileset(dir: outputPath, includes: 'KqlBase*.java') | ||
} | ||
// fix line endings | ||
ant.fixcrlf(srcdir: outputPath, eol: 'lf') { | ||
patternset(includes: 'KqlBase*.java') | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
/* | ||
* 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; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
grammar KqlBase; | ||
|
||
|
||
@header { | ||
/* | ||
* 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; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
} | ||
|
||
options { | ||
caseInsensitive=true; | ||
} | ||
|
||
topLevelQuery | ||
: query? EOF | ||
; | ||
|
||
query | ||
: query (AND | OR) query #booleanQuery | ||
| NOT subQuery=simpleQuery #notQuery | ||
| simpleQuery #defaultQuery | ||
; | ||
|
||
simpleQuery | ||
: nestedQuery | ||
| expression | ||
| parenthesizedQuery | ||
; | ||
|
||
expression | ||
: fieldTermQuery | ||
| fieldRangeQuery | ||
; | ||
|
||
nestedQuery | ||
: fieldName COLON LEFT_CURLY_BRACKET query RIGHT_CURLY_BRACKET | ||
; | ||
|
||
parenthesizedQuery: | ||
LEFT_PARENTHESIS query RIGHT_PARENTHESIS; | ||
|
||
fieldRangeQuery | ||
: fieldName operator=OP_COMPARE rangeQueryValue | ||
; | ||
|
||
fieldTermQuery | ||
: (fieldName COLON)? termQueryValue | ||
; | ||
|
||
fieldName | ||
: wildcardExpression | ||
| unquotedLiteralExpression | ||
| quotedStringExpression | ||
; | ||
|
||
rangeQueryValue | ||
: unquotedLiteralExpression | ||
| quotedStringExpression | ||
; | ||
|
||
termQueryValue | ||
: wildcardExpression | ||
| quotedStringExpression | ||
| termValue=unquotedLiteralExpression | ||
| groupingTermExpression; | ||
|
||
groupingTermExpression | ||
: LEFT_PARENTHESIS unquotedLiteralExpression RIGHT_PARENTHESIS | ||
; | ||
|
||
unquotedLiteralExpression | ||
: UNQUOTED_LITERAL+ | ||
; | ||
|
||
quotedStringExpression | ||
: QUOTED_STRING | ||
; | ||
|
||
wildcardExpression | ||
: WILDCARD | ||
; | ||
|
||
|
||
DEFAULT_SKIP: WHITESPACE -> skip; | ||
|
||
AND: 'and'; | ||
OR: 'or'; | ||
NOT: 'not'; | ||
|
||
COLON: ':'; | ||
OP_COMPARE: OP_LESS | OP_MORE | OP_LESS_EQ | OP_MORE_EQ; | ||
|
||
LEFT_PARENTHESIS: '('; | ||
RIGHT_PARENTHESIS: ')'; | ||
LEFT_CURLY_BRACKET: '{'; | ||
RIGHT_CURLY_BRACKET: '}'; | ||
|
||
UNQUOTED_LITERAL: WILDCARD* UNQUOTED_LITERAL_CHAR+ WILDCARD*; | ||
|
||
QUOTED_STRING: '"'QUOTED_CHAR*'"'; | ||
|
||
WILDCARD: WILDCARD_CHAR+; | ||
|
||
fragment WILDCARD_CHAR: '*'; | ||
fragment OP_LESS: '<'; | ||
fragment OP_LESS_EQ: '<='; | ||
fragment OP_MORE: '>'; | ||
fragment OP_MORE_EQ: '>='; | ||
|
||
fragment UNQUOTED_LITERAL_CHAR | ||
: ESCAPED_WHITESPACE | ||
| ESCAPED_SPECIAL_CHAR | ||
| ESCAPE_UNICODE_SEQUENCE | ||
| '\\' (AND | OR | NOT) | ||
| WILDCARD_CHAR UNQUOTED_LITERAL_CHAR | ||
| NON_SPECIAL_CHAR | ||
; | ||
|
||
fragment QUOTED_CHAR | ||
: ESCAPED_WHITESPACE | ||
| ESCAPE_UNICODE_SEQUENCE | ||
| ESCAPED_QUOTE | ||
| ~["] | ||
; | ||
fragment WHITESPACE: [ \t\n\r\u3000]; | ||
fragment ESCAPED_WHITESPACE: '\\r' | '\\t' | '\\n'; | ||
fragment NON_SPECIAL_CHAR: ~[ \\():<>"*{}]; | ||
fragment ESCAPED_SPECIAL_CHAR: '\\'[ \\():<>"*{}]; | ||
fragment ESCAPED_QUOTE: '\\"'; | ||
fragment ESCAPE_UNICODE_SEQUENCE: '\\' UNICODE_SEQUENCE; | ||
fragment UNICODE_SEQUENCE: 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT; | ||
fragment HEX_DIGIT: [0-9a-f]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
DEFAULT_SKIP=1 | ||
AND=2 | ||
OR=3 | ||
NOT=4 | ||
COLON=5 | ||
OP_COMPARE=6 | ||
LEFT_PARENTHESIS=7 | ||
RIGHT_PARENTHESIS=8 | ||
LEFT_CURLY_BRACKET=9 | ||
RIGHT_CURLY_BRACKET=10 | ||
UNQUOTED_LITERAL=11 | ||
QUOTED_STRING=12 | ||
WILDCARD=13 | ||
'and'=2 | ||
'or'=3 | ||
'not'=4 | ||
':'=5 | ||
'('=7 | ||
')'=8 | ||
'{'=9 | ||
'}'=10 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
DEFAULT_SKIP=1 | ||
AND=2 | ||
OR=3 | ||
NOT=4 | ||
COLON=5 | ||
OP_COMPARE=6 | ||
LEFT_PARENTHESIS=7 | ||
RIGHT_PARENTHESIS=8 | ||
LEFT_CURLY_BRACKET=9 | ||
RIGHT_CURLY_BRACKET=10 | ||
UNQUOTED_LITERAL=11 | ||
QUOTED_STRING=12 | ||
WILDCARD=13 | ||
'and'=2 | ||
'or'=3 | ||
'not'=4 | ||
':'=5 | ||
'('=7 | ||
')'=8 | ||
'{'=9 | ||
'}'=10 |
16 changes: 16 additions & 0 deletions
16
x-pack/plugin/kql/src/main/java/org/elasticsearch/xpack/kql/KqlPlugin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* 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; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.kql; | ||
|
||
import org.elasticsearch.plugins.ExtensiblePlugin; | ||
import org.elasticsearch.plugins.Plugin; | ||
import org.elasticsearch.plugins.SearchPlugin; | ||
|
||
public class KqlPlugin extends Plugin implements SearchPlugin, ExtensiblePlugin { | ||
|
||
} |
29 changes: 29 additions & 0 deletions
29
x-pack/plugin/kql/src/main/java/org/elasticsearch/xpack/kql/parser/KqlAstBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* 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; you may not use this file except in compliance with the Elastic License | ||
* 2.0. | ||
*/ | ||
|
||
package org.elasticsearch.xpack.kql.parser; | ||
|
||
import org.antlr.v4.runtime.ParserRuleContext; | ||
import org.elasticsearch.index.query.MatchAllQueryBuilder; | ||
import org.elasticsearch.index.query.QueryBuilder; | ||
import org.elasticsearch.index.query.SearchExecutionContext; | ||
|
||
class KqlAstBuilder extends KqlBaseBaseVisitor<QueryBuilder> { | ||
private final SearchExecutionContext searchExecutionContext; | ||
|
||
KqlAstBuilder(SearchExecutionContext searchExecutionContext) { | ||
this.searchExecutionContext = searchExecutionContext; | ||
} | ||
|
||
public QueryBuilder toQueryBuilder(ParserRuleContext ctx) { | ||
if (ctx instanceof KqlBaseParser.TopLevelQueryContext topLeveQueryContext) { | ||
return new MatchAllQueryBuilder(); | ||
} | ||
|
||
throw new IllegalArgumentException("context should be of type TopLevelQueryContext"); | ||
} | ||
} |
Oops, something went wrong.