Skip to content

Commit 8c7c910

Browse files
committed
EQL: Introduce ~ grammar for case-insensitive functions (#67869)
By default, operators and string comparisons are case sensitive. This PR enables support for case insensitive comparisons through the ~ (tilde) symbol which works on functions. For example: process where endsWith~(file.path, "ExE") will match all file.path that end with "exe", regardless of their case. In the process, refactored the code by introducing a common class and improving code consistency. Fix #67868 (cherry picked from commit afa4ce0)
1 parent 4f169d2 commit 8c7c910

File tree

62 files changed

+1598
-1281
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1598
-1281
lines changed

x-pack/plugin/eql/qa/common/src/main/resources/test_queries.toml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,7 +1445,7 @@ description = "check built-in string functions"
14451445
[[queries]]
14461446
name = "startsWithCaseInsensitive1"
14471447
query = '''
1448-
file where opcode==0 and startsWith(file_name, "explorer.")
1448+
file where opcode==0 and startsWith~(file_name, "explorer.")
14491449
'''
14501450
expected_event_ids = [88, 92]
14511451
description = "check built-in string functions"
@@ -1454,15 +1454,15 @@ description = "check built-in string functions"
14541454
[[queries]]
14551455
name = "startsWithCaseInsensitive2"
14561456
query = '''
1457-
file where opcode==0 and startsWith(file_name, "exploRER.")
1457+
file where opcode==0 and startsWith~(file_name, "exploRER.")
14581458
'''
14591459
expected_event_ids = [88, 92]
14601460
description = "check built-in string functions"
14611461

14621462
[[queries]]
14631463
name = "startsWithCaseInsensitive3"
14641464
query = '''
1465-
file where opcode==0 and startsWith(file_name, "expLORER.exe")
1465+
file where opcode==0 and startsWith~(file_name, "expLORER.ExE")
14661466
'''
14671467
expected_event_ids = [88, 92]
14681468
description = "check built-in string functions"
@@ -1479,7 +1479,7 @@ description = "check built-in string functions"
14791479
[[queries]]
14801480
name = "endsWithCaseInsensitive"
14811481
query = '''
1482-
file where opcode==0 and endsWith(file_name, "loREr.exe")
1482+
file where opcode==0 and endsWith~(file_name, "loREr.exe")
14831483
'''
14841484
expected_event_ids = [88]
14851485
description = "check built-in string functions"
@@ -1495,7 +1495,7 @@ description = "check built-in string functions"
14951495
[[queries]]
14961496
name = "endsWithAndCondition"
14971497
query = '''
1498-
file where opcode==0 and serial_event_id == 88 and startsWith("explorer.exeaAAAA", "EXPLORER.exe")
1498+
file where opcode==0 and serial_event_id == 88 and startsWith~("explorer.exeaAAAA", "EXPLORER.exe")
14991499
'''
15001500
expected_event_ids = [88]
15011501
description = "check built-in string functions"
@@ -1511,7 +1511,7 @@ description = "check built-in string functions"
15111511
[[queries]]
15121512
name = "indexOfCaseInsensitive"
15131513
query = '''
1514-
file where opcode==0 and indexOf(file_name, "plore") == 2 and indexOf(file_name, ".pf") == null
1514+
file where opcode==0 and indexOf~(file_name, "plore") == 2 and indexOf~(file_name, ".pf") == null
15151515
'''
15161516
expected_event_ids = [88]
15171517
description = "check built-in string functions"
@@ -1535,7 +1535,7 @@ description = "check built-in string functions"
15351535
[[queries]]
15361536
name = "indexOf3"
15371537
query = '''
1538-
file where opcode==0 and indexOf(file_name, "plorer.", 0) == 2
1538+
file where opcode==0 and indexOf~(file_name, "plorer.", 0) == 2
15391539
'''
15401540
expected_event_ids = [88, 92]
15411541
description = "check built-in string functions"
@@ -1551,7 +1551,7 @@ description = "check built-in string functions"
15511551
[[queries]]
15521552
name = "indexOf5"
15531553
query = '''
1554-
file where opcode==0 and indexOf(file_name, "plorer.", 2) != null
1554+
file where opcode==0 and indexOf~(file_name, "plorer.", 2) != null
15551555
'''
15561556
expected_event_ids = [88, 92]
15571557
description = "check built-in string functions"
@@ -1575,7 +1575,7 @@ description = "check built-in string functions"
15751575
[[queries]]
15761576
name = "indexOf8"
15771577
query = '''
1578-
file where opcode==0 and indexOf(file_name, "plorer.", 2) == 2
1578+
file where opcode==0 and indexOf~(file_name, "pLOrer.", 2) == 2
15791579
'''
15801580
expected_event_ids = [88, 92]
15811581
description = "check substring ranges"
@@ -1599,7 +1599,7 @@ description = "check substring ranges"
15991599
[[queries]]
16001600
name = "indexOf11"
16011601
query = '''
1602-
file where opcode==0 and indexOf(file_name, "explorer.", 0) == 0
1602+
file where opcode==0 and indexOf~(file_name, "explorer.", 0) == 0
16031603
'''
16041604
expected_event_ids = [88, 92]
16051605
description = "check substring ranges"
@@ -1901,14 +1901,14 @@ query = "file where serial_event_id % 40 == 2"
19011901
name = "betweenCaseInsensitive1"
19021902
expected_event_ids = [1, 2]
19031903
query = '''
1904-
process where between(process_name, "s", "e") : "yst"
1904+
process where between~(process_name, "s", "E") : "yst"
19051905
'''
19061906

19071907
[[queries]]
19081908
name = "betweenCaseInsensitive2"
19091909
expected_event_ids = [1, 2]
19101910
query = '''
1911-
process where between(process_name, "s", "e", false) : "yst"
1911+
process where between~(process_name, "s", "E", false) : "yst"
19121912
'''
19131913

19141914
[[queries]]
@@ -1929,7 +1929,7 @@ process where between(process_name, "S", "e", true) : "ystem Idle Proc"
19291929
name = "betweenCaseInsensitive3"
19301930
expected_event_ids = [1]
19311931
query = '''
1932-
process where between(process_name, "s", "e", true) : "ystem Idle Proc"
1932+
process where between~(process_name, "s", "e", true) : "ystem Idle Proc"
19331933
'''
19341934

19351935
[[queries]]

x-pack/plugin/eql/qa/common/src/main/resources/test_queries_unsupported.toml

Lines changed: 0 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -8,99 +8,6 @@
88
# in order to allow at least one round-trip test with the test harness.
99
# This will be removed once the EQL implementation is wired and actually supports this query.
1010

11-
[[queries]]
12-
name = "startsWithCaseInsensitive1"
13-
query = '''
14-
file where opcode==0 and startsWith(file_name, "explorer.")
15-
'''
16-
expected_event_ids = [88, 92]
17-
description = "check built-in string functions"
18-
19-
[[queries]]
20-
name = "startsWithCaseInsensitive2"
21-
query = '''
22-
file where opcode==0 and startsWith(file_name, "exploRER.")
23-
'''
24-
expected_event_ids = [88, 92]
25-
description = "check built-in string functions"
26-
27-
[[queries]]
28-
name = "startsWithCaseInsensitive3"
29-
query = '''
30-
file where opcode==0 and startsWith(file_name, "expLORER.exe")
31-
'''
32-
expected_event_ids = [88, 92]
33-
description = "check built-in string functions"
34-
35-
[[queries]]
36-
name = "endsWithCaseInsensitive"
37-
query = '''
38-
file where opcode==0 and endsWith(file_name, "loREr.exe")
39-
'''
40-
expected_event_ids = [88]
41-
description = "check built-in string functions"
42-
43-
[[queries]]
44-
name = "endsWithAndCondition"
45-
query = '''
46-
file where opcode==0 and serial_event_id == 88 and startsWith("explorer.exeaAAAA", "EXPLORER.exe")
47-
'''
48-
expected_event_ids = [88]
49-
description = "check built-in string functions"
50-
51-
[[queries]]
52-
name = "indexOf3"
53-
query = '''
54-
file where opcode==0 and indexOf(file_name, "plorer.", 0) == 2
55-
'''
56-
expected_event_ids = [88, 92]
57-
description = "check built-in string functions"
58-
59-
[[queries]]
60-
name = "indexOf5"
61-
query = '''
62-
file where opcode==0 and indexOf(file_name, "plorer.", 2) != null
63-
'''
64-
expected_event_ids = [88, 92]
65-
description = "check built-in string functions"
66-
67-
[[queries]]
68-
name = "indexOf8"
69-
query = '''
70-
file where opcode==0 and indexOf(file_name, "plorer.", 2) == 2
71-
'''
72-
expected_event_ids = [88, 92]
73-
description = "check substring ranges"
74-
75-
[[queries]]
76-
name = "indexOf11"
77-
query = '''
78-
file where opcode==0 and indexOf(file_name, "explorer.", 0) == 0
79-
'''
80-
expected_event_ids = [88, 92]
81-
description = "check substring ranges"
82-
83-
[[queries]]
84-
name = "betweenCaseInsensitive1"
85-
expected_event_ids = [1, 2]
86-
query = '''
87-
process where between(process_name, "s", "e") : "yst"
88-
'''
89-
90-
[[queries]]
91-
name = "betweenCaseInsensitive2"
92-
expected_event_ids = [1, 2]
93-
query = '''
94-
process where between(process_name, "s", "e", false) : "yst"
95-
'''
96-
97-
[[queries]]
98-
name = "betweenCaseInsensitive3"
99-
expected_event_ids = [1]
100-
query = '''
101-
process where between(process_name, "s", "e", true) : "ystem Idle Proc"
102-
'''
103-
10411
[[queries]]
10512
name = "twoSequencesWithKeys"
10613
query = '''

x-pack/plugin/eql/src/main/antlr/EqlBase.g4

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ functionExpression
117117

118118
functionName
119119
: IDENTIFIER
120+
| TILDE_IDENTIFIER
120121
;
121122

122123
constant
@@ -226,6 +227,10 @@ QUOTED_IDENTIFIER
226227
: '`' ( ~'`' | '``' )* '`'
227228
;
228229
230+
TILDE_IDENTIFIER
231+
: LETTER (LETTER | DIGIT | '_')* '~'
232+
;
233+
229234
eventValue
230235
: STRING
231236
| IDENTIFIER

x-pack/plugin/eql/src/main/antlr/EqlBase.tokens

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ INTEGER_VALUE=38
3939
DECIMAL_VALUE=39
4040
IDENTIFIER=40
4141
QUOTED_IDENTIFIER=41
42-
LINE_COMMENT=42
43-
BRACKETED_COMMENT=43
44-
WS=44
42+
TILDE_IDENTIFIER=42
43+
LINE_COMMENT=43
44+
BRACKETED_COMMENT=44
45+
WS=45
4546
'and'=1
4647
'any'=2
4748
'by'=3

x-pack/plugin/eql/src/main/antlr/EqlBaseLexer.tokens

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ INTEGER_VALUE=38
3939
DECIMAL_VALUE=39
4040
IDENTIFIER=40
4141
QUOTED_IDENTIFIER=41
42-
LINE_COMMENT=42
43-
BRACKETED_COMMENT=43
44-
WS=44
42+
TILDE_IDENTIFIER=42
43+
LINE_COMMENT=43
44+
BRACKETED_COMMENT=44
45+
WS=45
4546
'and'=1
4647
'any'=2
4748
'by'=3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.eql.expression.function;
8+
9+
import org.elasticsearch.xpack.ql.expression.function.Function;
10+
import org.elasticsearch.xpack.ql.expression.function.FunctionDefinition;
11+
12+
import java.util.List;
13+
14+
/**
15+
* Dedicated wrapper for EQL specific function definitions.
16+
* Used mainly for validating case sensitivity of wrapping functions.
17+
*/
18+
class EqlFunctionDefinition extends FunctionDefinition {
19+
20+
private final boolean caseAware;
21+
22+
protected EqlFunctionDefinition(String name,
23+
List<String> aliases,
24+
Class<? extends Function> clazz,
25+
boolean caseAware,
26+
Builder builder) {
27+
super(name, aliases, clazz, builder);
28+
this.caseAware = caseAware;
29+
}
30+
31+
public boolean isCaseAware() {
32+
return caseAware;
33+
}
34+
35+
@Override
36+
protected Builder builder() {
37+
return super.builder();
38+
}
39+
}

0 commit comments

Comments
 (0)