Remove case_sensitive request option (#63218) (#63244)

Make EQL case sensitive by default and adapt some of the string functions
Remove the case sensitive option from Between string function
Add case_insensitive option to term and wildcard queries usage

(cherry picked from commit 7550e0664c8c2f1f13519036c759b1e76345551f)
This commit is contained in:
Andrei Stefan 2020-10-05 22:04:42 +03:00 committed by GitHub
parent 1a6837883a
commit 76bba601ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 298 additions and 434 deletions

View File

@ -39,7 +39,6 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
private QueryBuilder filter = null; private QueryBuilder filter = null;
private String timestampField = "@timestamp"; private String timestampField = "@timestamp";
private String eventCategoryField = "event.category"; private String eventCategoryField = "event.category";
private boolean isCaseSensitive = true;
private int size = 10; private int size = 10;
private int fetchSize = 1000; private int fetchSize = 1000;
@ -55,7 +54,6 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
static final String KEY_TIMESTAMP_FIELD = "timestamp_field"; static final String KEY_TIMESTAMP_FIELD = "timestamp_field";
static final String KEY_TIEBREAKER_FIELD = "tiebreaker_field"; static final String KEY_TIEBREAKER_FIELD = "tiebreaker_field";
static final String KEY_EVENT_CATEGORY_FIELD = "event_category_field"; static final String KEY_EVENT_CATEGORY_FIELD = "event_category_field";
static final String KEY_CASE_SENSITIVE = "case_sensitive";
static final String KEY_SIZE = "size"; static final String KEY_SIZE = "size";
static final String KEY_FETCH_SIZE = "fetch_size"; static final String KEY_FETCH_SIZE = "fetch_size";
static final String KEY_QUERY = "query"; static final String KEY_QUERY = "query";
@ -81,7 +79,6 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
builder.field(KEY_EVENT_CATEGORY_FIELD, eventCategoryField()); builder.field(KEY_EVENT_CATEGORY_FIELD, eventCategoryField());
builder.field(KEY_SIZE, size()); builder.field(KEY_SIZE, size());
builder.field(KEY_FETCH_SIZE, fetchSize()); builder.field(KEY_FETCH_SIZE, fetchSize());
builder.field(KEY_CASE_SENSITIVE, isCaseSensitive());
builder.field(KEY_QUERY, query); builder.field(KEY_QUERY, query);
if (waitForCompletionTimeout != null) { if (waitForCompletionTimeout != null) {
@ -143,15 +140,6 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
return this; return this;
} }
public boolean isCaseSensitive() {
return this.isCaseSensitive;
}
public EqlSearchRequest isCaseSensitive(boolean isCaseSensitive) {
this.isCaseSensitive = isCaseSensitive;
return this;
}
public int size() { public int size() {
return this.size; return this.size;
} }
@ -232,7 +220,6 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
Objects.equals(tiebreakerField, that.tiebreakerField) && Objects.equals(tiebreakerField, that.tiebreakerField) &&
Objects.equals(eventCategoryField, that.eventCategoryField) && Objects.equals(eventCategoryField, that.eventCategoryField) &&
Objects.equals(query, that.query) && Objects.equals(query, that.query) &&
Objects.equals(isCaseSensitive, that.isCaseSensitive) &&
Objects.equals(waitForCompletionTimeout, that.waitForCompletionTimeout) && Objects.equals(waitForCompletionTimeout, that.waitForCompletionTimeout) &&
Objects.equals(keepAlive, that.keepAlive) && Objects.equals(keepAlive, that.keepAlive) &&
Objects.equals(keepOnCompletion, that.keepOnCompletion); Objects.equals(keepOnCompletion, that.keepOnCompletion);
@ -250,7 +237,6 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
tiebreakerField, tiebreakerField,
eventCategoryField, eventCategoryField,
query, query,
isCaseSensitive,
waitForCompletionTimeout, waitForCompletionTimeout,
keepAlive, keepAlive,
keepOnCompletion); keepOnCompletion);

View File

@ -486,34 +486,6 @@ GET /my-index-000001/_eql/search
---- ----
// TEST[setup:sec_logs] // TEST[setup:sec_logs]
[discrete]
[[eql-search-case-sensitive]]
=== Run a case-sensitive EQL search
By default, matching for EQL queries is case-insensitive. You can use the
`case_sensitive` parameter to toggle case sensitivity on or off.
The following search request contains a query that matches `process` events
with a `process.executable` containing `System32`.
Because `case_sensitive` is `true`, this query only matches `process.executable`
values containing `System32` with the exact same capitalization. A
`process.executable` value containing `system32` or `SYSTEM32` would not match
this query.
[source,console]
----
GET /my-index-000001/_eql/search
{
"keep_on_completion": true,
"case_sensitive": true,
"query": """
process where stringContains(process.executable, "System32")
"""
}
----
// TEST[setup:sec_logs]
[discrete] [discrete]
[[eql-search-async]] [[eql-search-async]]
=== Run an async EQL search === Run an async EQL search

View File

@ -40,7 +40,6 @@ public abstract class BaseEqlSpecTestCase extends ESRestTestCase {
private final String query; private final String query;
private final String name; private final String name;
private final long[] eventIds; private final long[] eventIds;
private final boolean caseSensitive;
@Before @Before
private void setup() throws Exception { private void setup() throws Exception {
@ -74,28 +73,22 @@ public abstract class BaseEqlSpecTestCase extends ESRestTestCase {
name = "" + (counter); name = "" + (counter);
} }
boolean[] values = spec.caseSensitive() == null ? new boolean[] { true, false } : new boolean[] { spec.caseSensitive() }; results.add(new Object[] { spec.query(), name, spec.expectedEventIds() });
for (boolean sensitive : values) {
String prefixed = name + (sensitive ? "-sensitive" : "-insensitive");
results.add(new Object[] { spec.query(), prefixed, spec.expectedEventIds(), sensitive });
}
} }
return results; return results;
} }
BaseEqlSpecTestCase(String index, String query, String name, long[] eventIds, boolean caseSensitive) { BaseEqlSpecTestCase(String index, String query, String name, long[] eventIds) {
this.index = index; this.index = index;
this.query = query; this.query = query;
this.name = name; this.name = name;
this.eventIds = eventIds; this.eventIds = eventIds;
this.caseSensitive = caseSensitive;
} }
public void test() throws Exception { public void test() throws Exception {
assertResponse(runQuery(index, query, caseSensitive)); assertResponse(runQuery(index, query));
} }
protected void assertResponse(EqlSearchResponse response) { protected void assertResponse(EqlSearchResponse response) {
@ -111,9 +104,8 @@ public abstract class BaseEqlSpecTestCase extends ESRestTestCase {
} }
} }
protected EqlSearchResponse runQuery(String index, String query, boolean isCaseSensitive) throws Exception { protected EqlSearchResponse runQuery(String index, String query) throws Exception {
EqlSearchRequest request = new EqlSearchRequest(index, query); EqlSearchRequest request = new EqlSearchRequest(index, query);
request.isCaseSensitive(isCaseSensitive);
request.tiebreakerField("event.sequence"); request.tiebreakerField("event.sequence");
// some queries return more than 10 results // some queries return more than 10 results
request.size(50); request.size(50);

View File

@ -20,8 +20,8 @@ public abstract class EqlExtraSpecTestCase extends BaseEqlSpecTestCase {
return asArray(EqlSpecLoader.load("/test_extra.toml", true, new HashSet<>())); return asArray(EqlSpecLoader.load("/test_extra.toml", true, new HashSet<>()));
} }
public EqlExtraSpecTestCase(String query, String name, long[] eventIds, boolean caseSensitive) { public EqlExtraSpecTestCase(String query, String name, long[] eventIds) {
super(TEST_EXTRA_INDEX, query, name, eventIds, caseSensitive); super(TEST_EXTRA_INDEX, query, name, eventIds);
} }
@Override @Override

View File

@ -19,12 +19,6 @@ public class EqlSpec {
private String query; private String query;
private long[] expectedEventIds; private long[] expectedEventIds;
// flag to dictate which modes are supported for the test
// null -> apply the test to both modes (case sensitive and case insensitive)
// TRUE -> case sensitive
// FALSE -> case insensitive
private Boolean caseSensitive = null;
public String name() { public String name() {
return name; return name;
} }
@ -73,14 +67,6 @@ public class EqlSpec {
this.expectedEventIds = expectedEventIds; this.expectedEventIds = expectedEventIds;
} }
public void caseSensitive(Boolean caseSensitive) {
this.caseSensitive = caseSensitive;
}
public Boolean caseSensitive() {
return this.caseSensitive;
}
public EqlSpec withSensitivity(boolean caseSensitive) { public EqlSpec withSensitivity(boolean caseSensitive) {
EqlSpec spec = new EqlSpec(); EqlSpec spec = new EqlSpec();
spec.name = name; spec.name = name;
@ -90,7 +76,6 @@ public class EqlSpec {
spec.query = query; spec.query = query;
spec.expectedEventIds = expectedEventIds; spec.expectedEventIds = expectedEventIds;
spec.caseSensitive = caseSensitive;
return spec; return spec;
} }
@ -102,10 +87,6 @@ public class EqlSpec {
str = appendWithComma(str, "description", description); str = appendWithComma(str, "description", description);
str = appendWithComma(str, "note", note); str = appendWithComma(str, "note", note);
if (caseSensitive != null) {
str = appendWithComma(str, "case_sensitive", Boolean.toString(caseSensitive));
}
if (tags != null) { if (tags != null) {
str = appendWithComma(str, "tags", Arrays.toString(tags)); str = appendWithComma(str, "tags", Arrays.toString(tags));
} }
@ -128,13 +109,12 @@ public class EqlSpec {
EqlSpec that = (EqlSpec) other; EqlSpec that = (EqlSpec) other;
return Objects.equals(this.query(), that.query()) return Objects.equals(this.query(), that.query());
&& Objects.equals(this.caseSensitive, that.caseSensitive);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(this.query, this.caseSensitive); return Objects.hash(this.query);
} }
private static String appendWithComma(String str, String name, String append) { private static String appendWithComma(String str, String name, String append) {

View File

@ -73,20 +73,6 @@ public class EqlSpecLoader {
spec.note(getTrimmedString(table, "note")); spec.note(getTrimmedString(table, "note"));
spec.description(getTrimmedString(table, "description")); spec.description(getTrimmedString(table, "description"));
Boolean caseSensitive = table.getBoolean("case_sensitive");
Boolean caseInsensitive = table.getBoolean("case_insensitive");
// if case_sensitive is TRUE and case_insensitive is not TRUE (FALSE or NULL), then the test is case sensitive only
if (Boolean.TRUE.equals(caseSensitive)) {
if (Boolean.FALSE.equals(caseInsensitive) || caseInsensitive == null) {
spec.caseSensitive(true);
}
}
// if case_sensitive is not TRUE (FALSE or NULL) and case_insensitive is TRUE, then the test is case insensitive only
else if (Boolean.TRUE.equals(caseInsensitive)) {
spec.caseSensitive(false);
}
// in all other cases, the test should run no matter the case sensitivity (should test both scenarios)
List<?> arr = table.getList("tags"); List<?> arr = table.getList("tags");
if (arr != null) { if (arr != null) {
String tags[] = new String[arr.size()]; String tags[] = new String[arr.size()];

View File

@ -51,7 +51,7 @@ public abstract class EqlSpecTestCase extends BaseEqlSpecTestCase {
return "serial_event_id"; return "serial_event_id";
} }
public EqlSpecTestCase(String query, String name, long[] eventIds, boolean caseSensitive) { public EqlSpecTestCase(String query, String name, long[] eventIds) {
super(TEST_INDEX, query, name, eventIds, caseSensitive); super(TEST_INDEX, query, name, eventIds);
} }
} }

View File

@ -177,13 +177,11 @@ expected_event_ids = [1, 2]
[[queries]] [[queries]]
name = "compareTwoFields1" name = "compareTwoFields1"
# test that it works for comparing field <--> field # test that it works for comparing field <--> field
case_insensitive = true
query = 'process where serial_event_id < 5 and process_name <= parent_process_name' query = 'process where serial_event_id < 5 and process_name <= parent_process_name'
expected_event_ids = [2, 3] expected_event_ids = [2, 3]
[[queries]] [[queries]]
name = "compareTwoFields2" name = "compareTwoFields2"
case_sensitive = true
query = 'process where serial_event_id < 5 and process_name <= parent_process_name' query = 'process where serial_event_id < 5 and process_name <= parent_process_name'
expected_event_ids = [2] expected_event_ids = [2]
@ -219,39 +217,33 @@ expected_event_ids = [1]
[[queries]] [[queries]]
name = "processWithStringComparisonCaseSensitive1" name = "processWithStringComparisonCaseSensitive1"
case_sensitive = true
notes = "s == 0x73; S == 0x53" notes = "s == 0x73; S == 0x53"
query = 'process where process_name >= "system idle process" and process_name <= "System Idle Process"' query = 'process where process_name >= "system idle process" and process_name <= "System Idle Process"'
expected_event_ids = [] expected_event_ids = []
[[queries]] [[queries]]
name = "processWithStringComparisonCaseInsensitive1" name = "processWithStringComparisonCaseInsensitive1"
case_insensitive = true
query = 'process where process_name >= "system idle process" and process_name <= "System Idle Process"' query = 'process where process_name >= "system idle process" and process_name <= "System Idle Process"'
expected_event_ids = [1] expected_event_ids = [1]
[[queries]] [[queries]]
name = "processWithStringComparisonCaseInsensitive2" name = "processWithStringComparisonCaseInsensitive2"
case_insensitive = true
query = 'process where process_name >= "SYSTE" and process_name < "systex"' query = 'process where process_name >= "SYSTE" and process_name < "systex"'
expected_event_ids = [1, 2] expected_event_ids = [1, 2]
[[queries]] [[queries]]
name = "processWithStringComparisonCaseInsensitive3" name = "processWithStringComparisonCaseInsensitive3"
case_insensitive = true
query = 'process where process_name >= "sysT" and process_name < "SYsTeZZZ"' query = 'process where process_name >= "sysT" and process_name < "SYsTeZZZ"'
expected_event_ids = [1, 2] expected_event_ids = [1, 2]
[[queries]] [[queries]]
name = "processWithStringComparisonCaseInsensitive4" name = "processWithStringComparisonCaseInsensitive4"
case_insensitive = true
query = 'process where process_name >= "SYSTE" and process_name <= "systex"' query = 'process where process_name >= "SYSTE" and process_name <= "systex"'
expected_event_ids = [1, 2] expected_event_ids = [1, 2]
[[queries]] [[queries]]
name = "processWithStringEqualityCaseInsensitive1" name = "processWithStringEqualityCaseInsensitive1"
case_insensitive = true
query = ''' query = '''
process where process_name : "VMACTHLP.exe" and unique_pid == 12 process where process_name : "VMACTHLP.exe" and unique_pid == 12
| filter true | filter true
@ -268,7 +260,6 @@ expected_event_ids = [3, 34, 48]
[[queries]] [[queries]]
name = "processNameINCaseInsensitive1" name = "processNameINCaseInsensitive1"
case_insensitive = true
query = ''' query = '''
process where process_name in ("python.exe", "SMSS.exe", "explorer.exe") process where process_name in ("python.exe", "SMSS.exe", "explorer.exe")
| unique process_name | unique process_name
@ -277,7 +268,6 @@ expected_event_ids = [3, 34, 48]
[[queries]] [[queries]]
name = "processNameINCaseInsensitive2" name = "processNameINCaseInsensitive2"
case_insensitive = true
query = ''' query = '''
process where process_name in ("python.exe", "smss.exe", "Explorer.exe") process where process_name in ("python.exe", "smss.exe", "Explorer.exe")
| unique length(process_name) | unique length(process_name)
@ -294,7 +284,6 @@ expected_event_ids = [3, 48]
[[queries]] [[queries]]
name = "processNameINWithUnique2" name = "processNameINWithUnique2"
case_insensitive = true
query = ''' query = '''
process where process_name in ("Python.exe", "smss.exe", "explorer.exe") process where process_name in ("Python.exe", "smss.exe", "explorer.exe")
| unique process_name != "python.exe" | unique process_name != "python.exe"
@ -348,7 +337,6 @@ expected_event_ids = [3, 48, 50, 54]
[[queries]] [[queries]]
name = "lengthCaseInsensitive1" name = "lengthCaseInsensitive1"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where length(bytes_written_string_list) == 2 and bytes_written_string_list[1] : "EN" registry where length(bytes_written_string_list) == 2 and bytes_written_string_list[1] : "EN"
@ -446,7 +434,6 @@ expected_event_ids = [2, 50, 51]
[[queries]] [[queries]]
name = "twoINsCaseInsensitive" name = "twoINsCaseInsensitive"
case_insensitive = true
query = ''' query = '''
process where opcode in (1,3) and process_name in (parent_process_name, "SYSTEM") process where opcode in (1,3) and process_name in (parent_process_name, "SYSTEM")
''' '''
@ -454,7 +441,6 @@ expected_event_ids = [2, 50, 51]
[[queries]] [[queries]]
name = "simpleTailWithSort" name = "simpleTailWithSort"
case_insensitive = true
expected_event_ids = [92, 95, 96, 91] expected_event_ids = [92, 95, 96, 91]
query = ''' query = '''
file where true file where true
@ -1319,7 +1305,6 @@ any where process_name : "svchost.exe"
[[queries]] [[queries]]
name = "arrayContainsCaseInsensitive1" name = "arrayContainsCaseInsensitive1"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, "En-uS") registry where arrayContains(bytes_written_string_list, "En-uS")
@ -1327,7 +1312,6 @@ registry where arrayContains(bytes_written_string_list, "En-uS")
[[queries]] [[queries]]
name = "arrayContainsCaseInsensitive2" name = "arrayContainsCaseInsensitive2"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, "En") registry where arrayContains(bytes_written_string_list, "En")
@ -1335,7 +1319,6 @@ registry where arrayContains(bytes_written_string_list, "En")
[[queries]] [[queries]]
name = "lengthCaseInsensitive2" name = "lengthCaseInsensitive2"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] : "EN-us" registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] : "EN-us"
@ -1343,7 +1326,6 @@ registry where length(bytes_written_string_list) > 0 and bytes_written_string_li
[[queries]] [[queries]]
name = "arrayCaseInsensitive1" name = "arrayCaseInsensitive1"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where bytes_written_string_list[0] : "EN-us" registry where bytes_written_string_list[0] : "EN-us"
@ -1351,7 +1333,6 @@ registry where bytes_written_string_list[0] : "EN-us"
[[queries]] [[queries]]
name = "arrayCaseInsensitive2" name = "arrayCaseInsensitive2"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where bytes_written_string_list[1] : "EN" registry where bytes_written_string_list[1] : "EN"
@ -1360,7 +1341,6 @@ registry where bytes_written_string_list[1] : "EN"
[[queries]] [[queries]]
name = "arrayContainsCaseInsensitive3" name = "arrayContainsCaseInsensitive3"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, "en-US") registry where arrayContains(bytes_written_string_list, "en-US")
@ -1368,7 +1348,6 @@ registry where arrayContains(bytes_written_string_list, "en-US")
[[queries]] [[queries]]
name = "arrayContainsCaseInsensitive4" name = "arrayContainsCaseInsensitive4"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, "en") registry where arrayContains(bytes_written_string_list, "en")
@ -1376,7 +1355,6 @@ registry where arrayContains(bytes_written_string_list, "en")
[[queries]] [[queries]]
name = "arrayCaseInsensitive3" name = "arrayCaseInsensitive3"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] : "en-US" registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] : "en-US"
@ -1433,7 +1411,6 @@ expected_event_ids = [98]
[[queries]] [[queries]]
name = "stringEqualsCaseInsensitive1" name = "stringEqualsCaseInsensitive1"
case_insensitive = true
query = ''' query = '''
process where "net.EXE" == original_file_name process where "net.EXE" == original_file_name
| filter process_name:"net*.exe" | filter process_name:"net*.exe"
@ -1443,7 +1420,6 @@ note = "check that case insensitive comparisons are performed even for lhs strin
[[queries]] [[queries]]
name = "stringEqualsCaseInsensitive2" name = "stringEqualsCaseInsensitive2"
case_insensitive = true
query = ''' query = '''
process where process_name == original_file_name and process_name:"net*.exe" process where process_name == original_file_name and process_name:"net*.exe"
''' '''
@ -1452,7 +1428,6 @@ note = "check that case insensitive comparisons are performed for fields."
[[queries]] [[queries]]
name = "fieldsComparisonCaseInsensitive" name = "fieldsComparisonCaseInsensitive"
case_insensitive = true
query = ''' query = '''
process where original_file_name == process_name and length(original_file_name) > 0 process where original_file_name == process_name and length(original_file_name) > 0
''' '''
@ -1461,17 +1436,14 @@ description = "check that case insensitive comparisons are performed for fields.
[[queries]] [[queries]]
name = "startsWithCaseSensitive" name = "startsWithCaseSensitive"
case_sensitive = true
query = ''' query = '''
file where opcode==0 and startsWith(file_name, "explorer.") file where opcode==0 and startsWith(file_name, "explorer.")
''' '''
expected_event_ids = [88] expected_event_ids = [88]
description = "check built-in string functions" description = "check built-in string functions"
[[queries]] [[queries]]
name = "startsWithCaseInsensitive1" name = "startsWithCaseInsensitive1"
case_insensitive = true
query = ''' query = '''
file where opcode==0 and startsWith(file_name, "explorer.") file where opcode==0 and startsWith(file_name, "explorer.")
''' '''
@ -1481,7 +1453,6 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "startsWithCaseInsensitive2" name = "startsWithCaseInsensitive2"
case_insensitive = true
query = ''' query = '''
file where opcode==0 and startsWith(file_name, "exploRER.") file where opcode==0 and startsWith(file_name, "exploRER.")
''' '''
@ -1490,7 +1461,6 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "startsWithCaseInsensitive3" name = "startsWithCaseInsensitive3"
case_insensitive = true
query = ''' query = '''
file where opcode==0 and startsWith(file_name, "expLORER.exe") file where opcode==0 and startsWith(file_name, "expLORER.exe")
''' '''
@ -1508,7 +1478,6 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "endsWithCaseInsensitive" name = "endsWithCaseInsensitive"
case_insensitive = true
query = ''' query = '''
file where opcode==0 and endsWith(file_name, "loREr.exe") file where opcode==0 and endsWith(file_name, "loREr.exe")
''' '''
@ -1525,7 +1494,6 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "endsWithAndCondition" name = "endsWithAndCondition"
case_insensitive = true
query = ''' query = '''
file where opcode==0 and serial_event_id == 88 and startsWith("explorer.exeaAAAA", "EXPLORER.exe") file where opcode==0 and serial_event_id == 88 and startsWith("explorer.exeaAAAA", "EXPLORER.exe")
''' '''
@ -1542,7 +1510,6 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "indexOfCaseInsensitive" name = "indexOfCaseInsensitive"
case_insensitive = true
query = ''' query = '''
file where opcode==0 and indexOf(file_name, "plore") == 2 and indexOf(file_name, ".pf") == null file where opcode==0 and indexOf(file_name, "plore") == 2 and indexOf(file_name, ".pf") == null
''' '''
@ -1559,7 +1526,6 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "indexOf2" name = "indexOf2"
case_sensitive = true
query = ''' query = '''
file where opcode==0 and indexOf(file_name, "plorer.", 0) == 2 file where opcode==0 and indexOf(file_name, "plorer.", 0) == 2
''' '''
@ -1568,7 +1534,6 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "indexOf3" name = "indexOf3"
case_insensitive = true
query = ''' query = '''
file where opcode==0 and indexOf(file_name, "plorer.", 0) == 2 file where opcode==0 and indexOf(file_name, "plorer.", 0) == 2
''' '''
@ -1577,7 +1542,6 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "indexOf4" name = "indexOf4"
case_sensitive = true
query = ''' query = '''
file where opcode==0 and indexOf(file_name, "plorer.", 2) != null file where opcode==0 and indexOf(file_name, "plorer.", 2) != null
''' '''
@ -1586,7 +1550,6 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "indexOf5" name = "indexOf5"
case_insensitive = true
query = ''' query = '''
file where opcode==0 and indexOf(file_name, "plorer.", 2) != null file where opcode==0 and indexOf(file_name, "plorer.", 2) != null
''' '''
@ -1611,7 +1574,6 @@ description = "check built-in string functions"
[[queries]] [[queries]]
name = "indexOf8" name = "indexOf8"
case_insensitive = true
query = ''' query = '''
file where opcode==0 and indexOf(file_name, "plorer.", 2) == 2 file where opcode==0 and indexOf(file_name, "plorer.", 2) == 2
''' '''
@ -1620,7 +1582,6 @@ description = "check substring ranges"
[[queries]] [[queries]]
name = "indexOf9" name = "indexOf9"
case_sensitive = true
query = ''' query = '''
file where opcode==0 and indexOf(file_name, "plorer.", 2) == 2 file where opcode==0 and indexOf(file_name, "plorer.", 2) == 2
''' '''
@ -1629,7 +1590,6 @@ description = "check substring ranges"
[[queries]] [[queries]]
name = "indexOf10" name = "indexOf10"
case_sensitive = true
query = ''' query = '''
file where opcode==0 and indexOf(file_name, "explorer.", 0) == 0 file where opcode==0 and indexOf(file_name, "explorer.", 0) == 0
''' '''
@ -1638,7 +1598,6 @@ description = "check substring ranges"
[[queries]] [[queries]]
name = "indexOf11" name = "indexOf11"
case_insensitive = true
query = ''' query = '''
file where opcode==0 and indexOf(file_name, "explorer.", 0) == 0 file where opcode==0 and indexOf(file_name, "explorer.", 0) == 0
''' '''
@ -1647,7 +1606,6 @@ description = "check substring ranges"
[[queries]] [[queries]]
name = "substring1" name = "substring1"
case_insensitive = true
query = ''' query = '''
file where serial_event_id==88 and substring(file_name, 0, 4) : "expl" file where serial_event_id==88 and substring(file_name, 0, 4) : "expl"
''' '''
@ -1656,7 +1614,6 @@ description = "check substring ranges"
[[queries]] [[queries]]
name = "substring2" name = "substring2"
case_sensitive = true
query = ''' query = '''
file where substring(file_name, 1, 3) == "xp" file where substring(file_name, 1, 3) == "xp"
''' '''
@ -1665,7 +1622,6 @@ description = "check substring ranges"
[[queries]] [[queries]]
name = "substring3" name = "substring3"
case_insensitive = true
query = ''' query = '''
file where substring(file_name, 1, 3) : "xp" file where substring(file_name, 1, 3) : "xp"
''' '''
@ -1754,7 +1710,6 @@ description = "test string concatenation"
[[queries]] [[queries]]
name = "concatCaseInsensitive" name = "concatCaseInsensitive"
case_insensitive = true
query = ''' query = '''
process where concat(serial_event_id, ":", process_name, opcode) : "5:winINIT.exe3" process where concat(serial_event_id, ":", process_name, opcode) : "5:winINIT.exe3"
''' '''
@ -1763,7 +1718,6 @@ description = "test string concatenation"
[[queries]] [[queries]]
name = "fieldComparisonCaseInsensitive" name = "fieldComparisonCaseInsensitive"
case_insensitive = true
query = ''' query = '''
process where process_name != original_file_name and length(original_file_name) > 0 process where process_name != original_file_name and length(original_file_name) > 0
''' '''
@ -1781,7 +1735,6 @@ registry where arraySearch(bytes_written_string_list, a, a : "en-US")
[[queries]] [[queries]]
name = "arraySearchCaseSensitive" name = "arraySearchCaseSensitive"
case_sensitive = true
expected_event_ids = [] expected_event_ids = []
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
@ -1790,7 +1743,6 @@ registry where arraySearch(bytes_written_string_list, a, a : "EN-US")
[[queries]] [[queries]]
name = "arraySearchCaseInsensitive1" name = "arraySearchCaseInsensitive1"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
@ -1799,7 +1751,6 @@ registry where arraySearch(bytes_written_string_list, a, a : "en-us")
[[queries]] [[queries]]
name = "arraySearchCaseInsensitive2" name = "arraySearchCaseInsensitive2"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
@ -1889,7 +1840,6 @@ network where safe(divide(process_name, process_name))
[[queries]] [[queries]]
name = "nestedSetComparisons" name = "nestedSetComparisons"
case_insensitive = true
query = ''' query = '''
file where serial_event_id == 82 and (true == (process_name in ("svchost.EXE", "bad.exe", "bad2.exe"))) file where serial_event_id == 82 and (true == (process_name in ("svchost.EXE", "bad.exe", "bad2.exe")))
''' '''
@ -1898,7 +1848,6 @@ description = "nested set comparisons"
[[queries]] [[queries]]
name = "arrayCount1" name = "arrayCount1"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayCount(bytes_written_string_list, s, s : "*-us") == 1 registry where arrayCount(bytes_written_string_list, s, s : "*-us") == 1
@ -1906,7 +1855,6 @@ registry where arrayCount(bytes_written_string_list, s, s : "*-us") == 1
[[queries]] [[queries]]
name = "arrayCount2" name = "arrayCount2"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayCount(bytes_written_string_list, s, s : "*en*") == 2 registry where arrayCount(bytes_written_string_list, s, s : "*en*") == 2
@ -1914,7 +1862,6 @@ registry where arrayCount(bytes_written_string_list, s, s : "*en*") == 2
[[queries]] [[queries]]
name = "arrayContainsCaseInsensitive5" name = "arrayContainsCaseInsensitive5"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, "missing", "en-US") registry where arrayContains(bytes_written_string_list, "missing", "en-US")
@ -1952,7 +1899,6 @@ query = "file where serial_event_id % 40 == 2"
[[queries]] [[queries]]
name = "betweenCaseInsensitive1" name = "betweenCaseInsensitive1"
case_insensitive = true
expected_event_ids = [1, 2] expected_event_ids = [1, 2]
query = ''' query = '''
process where between(process_name, "s", "e") : "yst" process where between(process_name, "s", "e") : "yst"
@ -1960,7 +1906,6 @@ process where between(process_name, "s", "e") : "yst"
[[queries]] [[queries]]
name = "betweenCaseInsensitive2" name = "betweenCaseInsensitive2"
case_insensitive = true
expected_event_ids = [1, 2] expected_event_ids = [1, 2]
query = ''' query = '''
process where between(process_name, "s", "e", false) : "yst" process where between(process_name, "s", "e", false) : "yst"
@ -1968,7 +1913,6 @@ process where between(process_name, "s", "e", false) : "yst"
[[queries]] [[queries]]
name = "betweenCaseSensitive" name = "betweenCaseSensitive"
case_sensitive = true
expected_event_ids = [1, 2, 42] expected_event_ids = [1, 2, 42]
query = ''' query = '''
process where between(process_name, "s", "e", false) : "t" process where between(process_name, "s", "e", false) : "t"
@ -1983,7 +1927,6 @@ process where between(process_name, "S", "e", true) : "ystem Idle Proc"
[[queries]] [[queries]]
name = "betweenCaseInsensitive3" name = "betweenCaseInsensitive3"
case_insensitive = true
expected_event_ids = [1] expected_event_ids = [1]
query = ''' query = '''
process where between(process_name, "s", "e", true) : "ystem Idle Proc" process where between(process_name, "s", "e", true) : "ystem Idle Proc"
@ -2034,7 +1977,6 @@ network where cidrMatch(source_address, "0.0.0.0/0")
[[queries]] [[queries]]
name = "lengthCaseSensitive" name = "lengthCaseSensitive"
case_sensitive = true
expected_event_ids = [7, 14, 29, 44] expected_event_ids = [7, 14, 29, 44]
query = ''' query = '''
process where length(between(process_name, "g", "e")) > 0 process where length(between(process_name, "g", "e")) > 0
@ -2042,7 +1984,6 @@ process where length(between(process_name, "g", "e")) > 0
[[queries]] [[queries]]
name = "lengthCaseInsensitiveAndBetween" name = "lengthCaseInsensitiveAndBetween"
case_insensitive = true
expected_event_ids = [7, 14, 22, 29, 44] expected_event_ids = [7, 14, 22, 29, 44]
query = ''' query = '''
process where length(between(process_name, "g", "e")) > 0 process where length(between(process_name, "g", "e")) > 0

View File

@ -8,6 +8,99 @@
# in order to allow at least one round-trip test with the test harness. # in order to allow at least one round-trip test with the test harness.
# This will be removed once the EQL implementation is wired and actually supports this query. # This will be removed once the EQL implementation is wired and actually supports this query.
[[queries]]
name = "startsWithCaseInsensitive1"
query = '''
file where opcode==0 and startsWith(file_name, "explorer.")
'''
expected_event_ids = [88, 92]
description = "check built-in string functions"
[[queries]]
name = "startsWithCaseInsensitive2"
query = '''
file where opcode==0 and startsWith(file_name, "exploRER.")
'''
expected_event_ids = [88, 92]
description = "check built-in string functions"
[[queries]]
name = "startsWithCaseInsensitive3"
query = '''
file where opcode==0 and startsWith(file_name, "expLORER.exe")
'''
expected_event_ids = [88, 92]
description = "check built-in string functions"
[[queries]]
name = "endsWithCaseInsensitive"
query = '''
file where opcode==0 and endsWith(file_name, "loREr.exe")
'''
expected_event_ids = [88]
description = "check built-in string functions"
[[queries]]
name = "endsWithAndCondition"
query = '''
file where opcode==0 and serial_event_id == 88 and startsWith("explorer.exeaAAAA", "EXPLORER.exe")
'''
expected_event_ids = [88]
description = "check built-in string functions"
[[queries]]
name = "indexOf3"
query = '''
file where opcode==0 and indexOf(file_name, "plorer.", 0) == 2
'''
expected_event_ids = [88, 92]
description = "check built-in string functions"
[[queries]]
name = "indexOf5"
query = '''
file where opcode==0 and indexOf(file_name, "plorer.", 2) != null
'''
expected_event_ids = [88, 92]
description = "check built-in string functions"
[[queries]]
name = "indexOf8"
query = '''
file where opcode==0 and indexOf(file_name, "plorer.", 2) == 2
'''
expected_event_ids = [88, 92]
description = "check substring ranges"
[[queries]]
name = "indexOf11"
query = '''
file where opcode==0 and indexOf(file_name, "explorer.", 0) == 0
'''
expected_event_ids = [88, 92]
description = "check substring ranges"
[[queries]]
name = "betweenCaseInsensitive1"
expected_event_ids = [1, 2]
query = '''
process where between(process_name, "s", "e") : "yst"
'''
[[queries]]
name = "betweenCaseInsensitive2"
expected_event_ids = [1, 2]
query = '''
process where between(process_name, "s", "e", false) : "yst"
'''
[[queries]]
name = "betweenCaseInsensitive3"
expected_event_ids = [1]
query = '''
process where between(process_name, "s", "e", true) : "ystem Idle Proc"
'''
[[queries]] [[queries]]
name = "twoSequencesWithKeys" name = "twoSequencesWithKeys"
query = ''' query = '''
@ -93,13 +186,11 @@ expected_event_ids = [7, 8]
[[queries]] [[queries]]
name = "compareTwoFields1" name = "compareTwoFields1"
case_insensitive = true
query = 'process where serial_event_id < 5 and process_name <= parent_process_name' query = 'process where serial_event_id < 5 and process_name <= parent_process_name'
expected_event_ids = [2, 3] expected_event_ids = [2, 3]
[[queries]] [[queries]]
name = "compareTwoFields2" name = "compareTwoFields2"
case_sensitive = true
query = 'process where serial_event_id < 5 and process_name <= parent_process_name' query = 'process where serial_event_id < 5 and process_name <= parent_process_name'
expected_event_ids = [2] expected_event_ids = [2]
@ -107,32 +198,27 @@ expected_event_ids = [2]
[[queries]] [[queries]]
name = "processWithStringComparisonCaseInsensitive1" name = "processWithStringComparisonCaseInsensitive1"
case_insensitive = true
query = 'process where process_name >= "system idle process" and process_name <= "System Idle Process"' query = 'process where process_name >= "system idle process" and process_name <= "System Idle Process"'
expected_event_ids = [1] expected_event_ids = [1]
[[queries]] [[queries]]
name = "processWithStringComparisonCaseInsensitive2" name = "processWithStringComparisonCaseInsensitive2"
case_insensitive = true
query = 'process where process_name >= "SYSTE" and process_name < "systex"' query = 'process where process_name >= "SYSTE" and process_name < "systex"'
expected_event_ids = [1, 2] expected_event_ids = [1, 2]
[[queries]] [[queries]]
name = "processWithStringComparisonCaseInsensitive3" name = "processWithStringComparisonCaseInsensitive3"
case_insensitive = true
query = 'process where process_name >= "sysT" and process_name < "SYsTeZZZ"' query = 'process where process_name >= "sysT" and process_name < "SYsTeZZZ"'
expected_event_ids = [1, 2] expected_event_ids = [1, 2]
[[queries]] [[queries]]
name = "processWithStringComparisonCaseInsensitive4" name = "processWithStringComparisonCaseInsensitive4"
case_insensitive = true
query = 'process where process_name >= "SYSTE" and process_name <= "systex"' query = 'process where process_name >= "SYSTE" and process_name <= "systex"'
expected_event_ids = [1, 2] expected_event_ids = [1, 2]
[[queries]] [[queries]]
name = "processWithStringEqualityCaseInsensitive1" name = "processWithStringEqualityCaseInsensitive1"
case_insensitive = true
query = ''' query = '''
process where process_name : "VMACTHLP.exe" and unique_pid == 12 process where process_name : "VMACTHLP.exe" and unique_pid == 12
| filter true | filter true
@ -149,7 +235,6 @@ expected_event_ids = [3, 34, 48]
[[queries]] [[queries]]
name = "processNameINCaseInsensitive1" name = "processNameINCaseInsensitive1"
case_insensitive = true
query = ''' query = '''
process where process_name in ("python.exe", "SMSS.exe", "explorer.exe") process where process_name in ("python.exe", "SMSS.exe", "explorer.exe")
| unique process_name | unique process_name
@ -158,7 +243,6 @@ expected_event_ids = [3, 34, 48]
[[queries]] [[queries]]
name = "processNameINCaseInsensitive2" name = "processNameINCaseInsensitive2"
case_insensitive = true
query = ''' query = '''
process where process_name in ("python.exe", "smss.exe", "Explorer.exe") process where process_name in ("python.exe", "smss.exe", "Explorer.exe")
| unique length(process_name) | unique length(process_name)
@ -175,7 +259,6 @@ expected_event_ids = [3, 48]
[[queries]] [[queries]]
name = "processNameINWithUnique2" name = "processNameINWithUnique2"
case_insensitive = true
query = ''' query = '''
process where process_name in ("Python.exe", "smss.exe", "explorer.exe") process where process_name in ("Python.exe", "smss.exe", "explorer.exe")
| unique process_name != "python.exe" | unique process_name != "python.exe"
@ -229,7 +312,6 @@ expected_event_ids = [3, 48, 50, 54]
[[queries]] [[queries]]
name = "lengthCaseInsensitive" name = "lengthCaseInsensitive"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where length(bytes_written_string_list) == 2 and bytes_written_string_list[1] : "EN" registry where length(bytes_written_string_list) == 2 and bytes_written_string_list[1] : "EN"
@ -282,7 +364,6 @@ expected_event_ids = [2, 50, 51]
[[queries]] [[queries]]
name = "twoINsCaseInsensitive" name = "twoINsCaseInsensitive"
case_insensitive = true
query = ''' query = '''
process where opcode in (1,3) and process_name in (parent_process_name, "SYSTEM") process where opcode in (1,3) and process_name in (parent_process_name, "SYSTEM")
''' '''
@ -290,7 +371,6 @@ expected_event_ids = [2, 50, 51]
[[queries]] [[queries]]
name = "simpleTailWithSort" name = "simpleTailWithSort"
case_insensitive = true
expected_event_ids = [92, 95, 96, 91] expected_event_ids = [92, 95, 96, 91]
query = ''' query = '''
file where true file where true
@ -716,7 +796,6 @@ any where process_name : "svchost.exe"
[[queries]] [[queries]]
name = "arrayContainsCaseInsensitive1" name = "arrayContainsCaseInsensitive1"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, "En-uS") registry where arrayContains(bytes_written_string_list, "En-uS")
@ -724,7 +803,6 @@ registry where arrayContains(bytes_written_string_list, "En-uS")
[[queries]] [[queries]]
name = "arrayContainsCaseInsensitive2" name = "arrayContainsCaseInsensitive2"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, "En") registry where arrayContains(bytes_written_string_list, "En")
@ -732,7 +810,6 @@ registry where arrayContains(bytes_written_string_list, "En")
[[queries]] [[queries]]
name = "lengthCaseInsensitive" name = "lengthCaseInsensitive"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] : "EN-us" registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] : "EN-us"
@ -740,7 +817,6 @@ registry where length(bytes_written_string_list) > 0 and bytes_written_string_li
[[queries]] [[queries]]
name = "arrayCaseInsensitive1" name = "arrayCaseInsensitive1"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where bytes_written_string_list[0] : "EN-us" registry where bytes_written_string_list[0] : "EN-us"
@ -748,7 +824,6 @@ registry where bytes_written_string_list[0] : "EN-us"
[[queries]] [[queries]]
name = "arrayCaseInsensitive2" name = "arrayCaseInsensitive2"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where bytes_written_string_list[1] : "EN" registry where bytes_written_string_list[1] : "EN"
@ -757,7 +832,6 @@ registry where bytes_written_string_list[1] : "EN"
[[queries]] [[queries]]
name = "arrayContainsCaseInsensitive3" name = "arrayContainsCaseInsensitive3"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, "en-US") registry where arrayContains(bytes_written_string_list, "en-US")
@ -765,7 +839,6 @@ registry where arrayContains(bytes_written_string_list, "en-US")
[[queries]] [[queries]]
name = "arrayContainsCaseInsensitive4" name = "arrayContainsCaseInsensitive4"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, "en") registry where arrayContains(bytes_written_string_list, "en")
@ -773,7 +846,6 @@ registry where arrayContains(bytes_written_string_list, "en")
[[queries]] [[queries]]
name = "arrayCaseInsensitive3" name = "arrayCaseInsensitive3"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] : "en-US" registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] : "en-US"
@ -831,7 +903,6 @@ expected_event_ids = [98]
[[queries]] [[queries]]
name = "stringEqualsCaseInsensitive1" name = "stringEqualsCaseInsensitive1"
case_insensitive = true
query = ''' query = '''
process where "net.EXE" == original_file_name process where "net.EXE" == original_file_name
| filter process_name:"net*.exe" | filter process_name:"net*.exe"
@ -841,7 +912,6 @@ note = "check that case insensitive comparisons are performed even for lhs strin
[[queries]] [[queries]]
name = "stringEqualsCaseInsensitive2" name = "stringEqualsCaseInsensitive2"
case_insensitive = true
query = ''' query = '''
process where process_name == original_file_name and process_name:"net*.exe" process where process_name == original_file_name and process_name:"net*.exe"
''' '''
@ -850,7 +920,6 @@ note = "check that case insensitive comparisons are performed for fields."
[[queries]] [[queries]]
name = "fieldsComparisonCaseInsensitive" name = "fieldsComparisonCaseInsensitive"
case_insensitive = true
query = ''' query = '''
process where original_file_name == process_name and length(original_file_name) > 0 process where original_file_name == process_name and length(original_file_name) > 0
''' '''
@ -859,7 +928,6 @@ description = "check that case insensitive comparisons are performed for fields.
[[queries]] [[queries]]
name = "substring3" name = "substring3"
case_insensitive = true
query = ''' query = '''
file where substring(file_name, 1, 3) : "xp" file where substring(file_name, 1, 3) : "xp"
''' '''
@ -876,7 +944,6 @@ description = "test built-in math functions"
[[queries]] [[queries]]
name = "concatCaseInsensitive" name = "concatCaseInsensitive"
case_insensitive = true
query = ''' query = '''
process where concat(serial_event_id, ":", process_name, opcode) : "5:winINIT.exe3" process where concat(serial_event_id, ":", process_name, opcode) : "5:winINIT.exe3"
''' '''
@ -885,7 +952,6 @@ description = "test string concatenation"
[[queries]] [[queries]]
name = "fieldComparisonCaseInsensitive" name = "fieldComparisonCaseInsensitive"
case_insensitive = true
query = ''' query = '''
process where process_name != original_file_name and length(original_file_name) > 0 process where process_name != original_file_name and length(original_file_name) > 0
''' '''
@ -903,7 +969,6 @@ registry where arraySearch(bytes_written_string_list, a, a : "en-US")
[[queries]] [[queries]]
name = "arraySearchCaseSensitive" name = "arraySearchCaseSensitive"
case_sensitive = true
expected_event_ids = [] expected_event_ids = []
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
@ -912,7 +977,6 @@ registry where arraySearch(bytes_written_string_list, a, a : "EN-US")
[[queries]] [[queries]]
name = "arraySearchCaseInsensitive1" name = "arraySearchCaseInsensitive1"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
@ -921,7 +985,6 @@ registry where arraySearch(bytes_written_string_list, a, a : "en-us")
[[queries]] [[queries]]
name = "arraySearchCaseInsensitive2" name = "arraySearchCaseInsensitive2"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects" description = "test arraySearch functionality for lists of strings, and lists of objects"
query = ''' query = '''
@ -1011,7 +1074,6 @@ network where safe(divide(process_name, process_name))
[[queries]] [[queries]]
name = "nestedSetComparisons" name = "nestedSetComparisons"
case_insensitive = true
query = ''' query = '''
file where serial_event_id == 82 and (true == (process_name in ("svchost.EXE", "bad.exe", "bad2.exe"))) file where serial_event_id == 82 and (true == (process_name in ("svchost.EXE", "bad.exe", "bad2.exe")))
''' '''
@ -1020,7 +1082,6 @@ description = "nested set comparisons"
[[queries]] [[queries]]
name = "arrayCount1" name = "arrayCount1"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayCount(bytes_written_string_list, s, s : "*-us") == 1 registry where arrayCount(bytes_written_string_list, s, s : "*-us") == 1
@ -1028,7 +1089,6 @@ registry where arrayCount(bytes_written_string_list, s, s : "*-us") == 1
[[queries]] [[queries]]
name = "arrayCount2" name = "arrayCount2"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayCount(bytes_written_string_list, s, s : "*en*") == 2 registry where arrayCount(bytes_written_string_list, s, s : "*en*") == 2
@ -1036,7 +1096,6 @@ registry where arrayCount(bytes_written_string_list, s, s : "*en*") == 2
[[queries]] [[queries]]
name = "arrayContainsCaseInsensitive5" name = "arrayContainsCaseInsensitive5"
case_insensitive = true
expected_event_ids = [57] expected_event_ids = [57]
query = ''' query = '''
registry where arrayContains(bytes_written_string_list, "missing", "en-US") registry where arrayContains(bytes_written_string_list, "missing", "en-US")
@ -1069,7 +1128,6 @@ expected_event_ids = [1, 2,
# TODO: update toggles for this function # TODO: update toggles for this function
[[queries]] [[queries]]
name = "betweenCaseSensitive" name = "betweenCaseSensitive"
case_sensitive = true
expected_event_ids = [1, 2, 42] expected_event_ids = [1, 2, 42]
query = ''' query = '''
process where between(process_name, "s", "e", false) : "t" process where between(process_name, "s", "e", false) : "t"
@ -1078,7 +1136,6 @@ process where between(process_name, "s", "e", false) : "t"
# TODO: add toggles to this function so it's not always insensitive # TODO: add toggles to this function so it's not always insensitive
[[queries]] [[queries]]
name = "lengthCaseSensitive" name = "lengthCaseSensitive"
case_sensitive = true
expected_event_ids = [7, 14, 29, 44] expected_event_ids = [7, 14, 29, 44]
query = ''' query = '''
process where length(between(process_name, "g", "e")) > 0 process where length(between(process_name, "g", "e")) > 0

View File

@ -12,7 +12,7 @@ import org.elasticsearch.test.junit.annotations.TestLogging;
@TestLogging(value = "org.elasticsearch.xpack.eql:TRACE", reason = "results logging") @TestLogging(value = "org.elasticsearch.xpack.eql:TRACE", reason = "results logging")
public class EqlExtraIT extends EqlExtraSpecTestCase { public class EqlExtraIT extends EqlExtraSpecTestCase {
public EqlExtraIT(String query, String name, long[] eventIds, boolean caseSensitive) { public EqlExtraIT(String query, String name, long[] eventIds) {
super(query, name, eventIds, caseSensitive); super(query, name, eventIds);
} }
} }

View File

@ -10,7 +10,7 @@ import org.elasticsearch.test.eql.EqlSpecTestCase;
public class EqlSpecIT extends EqlSpecTestCase { public class EqlSpecIT extends EqlSpecTestCase {
public EqlSpecIT(String query, String name, long[] eventIds, boolean caseSensitive) { public EqlSpecIT(String query, String name, long[] eventIds) {
super(query, name, eventIds, caseSensitive); super(query, name, eventIds);
} }
} }

View File

@ -50,7 +50,6 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
private int size = RequestDefaults.SIZE; private int size = RequestDefaults.SIZE;
private int fetchSize = RequestDefaults.FETCH_SIZE; private int fetchSize = RequestDefaults.FETCH_SIZE;
private String query; private String query;
private boolean isCaseSensitive = false;
// Async settings // Async settings
private TimeValue waitForCompletionTimeout = null; private TimeValue waitForCompletionTimeout = null;
@ -67,7 +66,6 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
static final String KEY_WAIT_FOR_COMPLETION_TIMEOUT = "wait_for_completion_timeout"; static final String KEY_WAIT_FOR_COMPLETION_TIMEOUT = "wait_for_completion_timeout";
static final String KEY_KEEP_ALIVE = "keep_alive"; static final String KEY_KEEP_ALIVE = "keep_alive";
static final String KEY_KEEP_ON_COMPLETION = "keep_on_completion"; static final String KEY_KEEP_ON_COMPLETION = "keep_on_completion";
static final String KEY_CASE_SENSITIVE = "case_sensitive";
static final ParseField FILTER = new ParseField(KEY_FILTER); static final ParseField FILTER = new ParseField(KEY_FILTER);
static final ParseField TIMESTAMP_FIELD = new ParseField(KEY_TIMESTAMP_FIELD); static final ParseField TIMESTAMP_FIELD = new ParseField(KEY_TIMESTAMP_FIELD);
@ -79,7 +77,6 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
static final ParseField WAIT_FOR_COMPLETION_TIMEOUT = new ParseField(KEY_WAIT_FOR_COMPLETION_TIMEOUT); static final ParseField WAIT_FOR_COMPLETION_TIMEOUT = new ParseField(KEY_WAIT_FOR_COMPLETION_TIMEOUT);
static final ParseField KEEP_ALIVE = new ParseField(KEY_KEEP_ALIVE); static final ParseField KEEP_ALIVE = new ParseField(KEY_KEEP_ALIVE);
static final ParseField KEEP_ON_COMPLETION = new ParseField(KEY_KEEP_ON_COMPLETION); static final ParseField KEEP_ON_COMPLETION = new ParseField(KEY_KEEP_ON_COMPLETION);
static final ParseField CASE_SENSITIVE = new ParseField(KEY_CASE_SENSITIVE);
private static final ObjectParser<EqlSearchRequest, Void> PARSER = objectParser(EqlSearchRequest::new); private static final ObjectParser<EqlSearchRequest, Void> PARSER = objectParser(EqlSearchRequest::new);
@ -103,7 +100,9 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
this.keepAlive = in.readOptionalTimeValue(); this.keepAlive = in.readOptionalTimeValue();
this.keepOnCompletion = in.readBoolean(); this.keepOnCompletion = in.readBoolean();
} }
isCaseSensitive = in.readBoolean(); if (in.getVersion().before(Version.V_7_10_0)) {
in.readBoolean();
}
} }
@Override @Override
@ -178,7 +177,6 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
builder.field(KEY_KEEP_ALIVE, keepAlive); builder.field(KEY_KEEP_ALIVE, keepAlive);
} }
builder.field(KEY_KEEP_ON_COMPLETION, keepOnCompletion); builder.field(KEY_KEEP_ON_COMPLETION, keepOnCompletion);
builder.field(KEY_CASE_SENSITIVE, isCaseSensitive);
return builder; return builder;
} }
@ -203,7 +201,6 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
parser.declareField(EqlSearchRequest::keepAlive, parser.declareField(EqlSearchRequest::keepAlive,
(p, c) -> TimeValue.parseTimeValue(p.text(), KEY_KEEP_ALIVE), KEEP_ALIVE, ObjectParser.ValueType.VALUE); (p, c) -> TimeValue.parseTimeValue(p.text(), KEY_KEEP_ALIVE), KEEP_ALIVE, ObjectParser.ValueType.VALUE);
parser.declareBoolean(EqlSearchRequest::keepOnCompletion, KEEP_ON_COMPLETION); parser.declareBoolean(EqlSearchRequest::keepOnCompletion, KEEP_ON_COMPLETION);
parser.declareBoolean(EqlSearchRequest::isCaseSensitive, CASE_SENSITIVE);
return parser; return parser;
} }
@ -293,13 +290,6 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
return this; return this;
} }
public boolean isCaseSensitive() { return this.isCaseSensitive; }
public EqlSearchRequest isCaseSensitive(boolean isCaseSensitive) {
this.isCaseSensitive = isCaseSensitive;
return this;
}
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out); super.writeTo(out);
@ -317,7 +307,9 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
out.writeOptionalTimeValue(keepAlive); out.writeOptionalTimeValue(keepAlive);
out.writeBoolean(keepOnCompletion); out.writeBoolean(keepOnCompletion);
} }
out.writeBoolean(isCaseSensitive); if (out.getVersion().onOrAfter(Version.V_7_10_0)) {
out.writeBoolean(true);
}
} }
@Override @Override
@ -341,8 +333,7 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
Objects.equals(eventCategoryField, that.eventCategoryField) && Objects.equals(eventCategoryField, that.eventCategoryField) &&
Objects.equals(query, that.query) && Objects.equals(query, that.query) &&
Objects.equals(waitForCompletionTimeout, that.waitForCompletionTimeout) && Objects.equals(waitForCompletionTimeout, that.waitForCompletionTimeout) &&
Objects.equals(keepAlive, that.keepAlive) && Objects.equals(keepAlive, that.keepAlive);
Objects.equals(isCaseSensitive, that.isCaseSensitive);
} }
@ -359,8 +350,7 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
eventCategoryField, eventCategoryField,
query, query,
waitForCompletionTimeout, waitForCompletionTimeout,
keepAlive, keepAlive);
isCaseSensitive);
} }
@Override @Override

View File

@ -54,9 +54,4 @@ public class EqlSearchRequestBuilder extends ActionRequestBuilder<EqlSearchReque
request.query(query); request.query(query);
return this; return this;
} }
public EqlSearchRequestBuilder isCaseSensitive(boolean isCaseSensitive) {
request.isCaseSensitive(isCaseSensitive);
return this;
}
} }

View File

@ -40,7 +40,7 @@ public class EqlFunctionRegistry extends FunctionRegistry {
// Scalar functions // Scalar functions
// String // String
new FunctionDefinition[] { new FunctionDefinition[] {
def(Between.class, Between::new, 2, "between"), def(Between.class, Between::new, "between"),
def(CIDRMatch.class, CIDRMatch::new, "cidrmatch"), def(CIDRMatch.class, CIDRMatch::new, "cidrmatch"),
def(Concat.class, Concat::new, "concat"), def(Concat.class, Concat::new, "concat"),
def(EndsWith.class, EndsWith::new, "endswith"), def(EndsWith.class, EndsWith::new, "endswith"),

View File

@ -32,20 +32,20 @@ import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.par
/** /**
* EQL specific between function. * EQL specific between function.
* between(source, left, right[, greedy=false, case_sensitive=false]) * between(source, left, right[, greedy=false])
* Extracts a substring from source thats between left and right substrings * Extracts a substring from source thats between left and right substrings
*/ */
public class Between extends ScalarFunction implements OptionalArgument { public class Between extends ScalarFunction implements OptionalArgument {
private final Expression input, left, right, greedy, caseSensitive; private final Expression input, left, right, greedy, caseSensitive;
public Between(Source source, Expression input, Expression left, Expression right, Expression greedy, Expression caseSensitive) { public Between(Source source, Expression input, Expression left, Expression right, Expression greedy) {
super(source, Arrays.asList(input, left, right, toDefault(greedy), toDefault(caseSensitive))); super(source, Arrays.asList(input, left, right, toDefault(greedy)));
this.input = input; this.input = input;
this.left = left; this.left = left;
this.right = right; this.right = right;
this.greedy = arguments().get(3); this.greedy = arguments().get(3);
this.caseSensitive = arguments().get(4); this.caseSensitive = Literal.TRUE;
} }
private static Expression toDefault(Expression exp) { private static Expression toDefault(Expression exp) {
@ -73,12 +73,12 @@ public class Between extends ScalarFunction implements OptionalArgument {
return resolution; return resolution;
} }
resolution = isBoolean(greedy, sourceText(), Expressions.ParamOrdinal.FOURTH); return isBoolean(greedy, sourceText(), Expressions.ParamOrdinal.FOURTH);
if (resolution.unresolved()) { // if (resolution.unresolved()) {
return resolution; // return resolution;
} // }
//
return isBoolean(caseSensitive, sourceText(), Expressions.ParamOrdinal.FIFTH); // return isBoolean(caseSensitive, sourceText(), Expressions.ParamOrdinal.FIFTH);
} }
@Override @Override
@ -100,7 +100,7 @@ public class Between extends ScalarFunction implements OptionalArgument {
@Override @Override
protected NodeInfo<? extends Expression> info() { protected NodeInfo<? extends Expression> info() {
return NodeInfo.create(this, Between::new, input, left, right, greedy, caseSensitive); return NodeInfo.create(this, Between::new, input, left, right, greedy);
} }
@Override @Override
@ -146,10 +146,10 @@ public class Between extends ScalarFunction implements OptionalArgument {
@Override @Override
public Expression replaceChildren(List<Expression> newChildren) { public Expression replaceChildren(List<Expression> newChildren) {
if (newChildren.size() != 5) { if (newChildren.size() != 4) {
throw new IllegalArgumentException("expected [5] children but received [" + newChildren.size() + "]"); throw new IllegalArgumentException("expected [4] children but received [" + newChildren.size() + "]");
} }
return new Between(source(), newChildren.get(0), newChildren.get(1), newChildren.get(2), newChildren.get(3), newChildren.get(4)); return new Between(source(), newChildren.get(0), newChildren.get(1), newChildren.get(2), newChildren.get(3));
} }
} }

View File

@ -6,7 +6,6 @@
package org.elasticsearch.xpack.eql.expression.function.scalar.string; package org.elasticsearch.xpack.eql.expression.function.scalar.string;
import org.elasticsearch.xpack.eql.session.EqlConfiguration;
import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expression;
import org.elasticsearch.xpack.ql.expression.Expressions; import org.elasticsearch.xpack.ql.expression.Expressions;
import org.elasticsearch.xpack.ql.expression.Expressions.ParamOrdinal; import org.elasticsearch.xpack.ql.expression.Expressions.ParamOrdinal;
@ -47,7 +46,7 @@ public class EndsWith extends CaseSensitiveScalarFunction {
@Override @Override
public boolean isCaseSensitive() { public boolean isCaseSensitive() {
return ((EqlConfiguration) configuration()).isCaseSensitive(); return true;
} }
@Override @Override

View File

@ -6,7 +6,6 @@
package org.elasticsearch.xpack.eql.expression.function.scalar.string; package org.elasticsearch.xpack.eql.expression.function.scalar.string;
import org.elasticsearch.xpack.eql.session.EqlConfiguration;
import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expression;
import org.elasticsearch.xpack.ql.expression.Expressions; import org.elasticsearch.xpack.ql.expression.Expressions;
import org.elasticsearch.xpack.ql.expression.Expressions.ParamOrdinal; import org.elasticsearch.xpack.ql.expression.Expressions.ParamOrdinal;
@ -50,7 +49,7 @@ public class IndexOf extends CaseSensitiveScalarFunction implements OptionalArgu
@Override @Override
public boolean isCaseSensitive() { public boolean isCaseSensitive() {
return ((EqlConfiguration) configuration()).isCaseSensitive(); return true;
} }
@Override @Override

View File

@ -6,7 +6,6 @@
package org.elasticsearch.xpack.eql.expression.function.scalar.string; package org.elasticsearch.xpack.eql.expression.function.scalar.string;
import org.elasticsearch.xpack.eql.session.EqlConfiguration;
import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expression;
import org.elasticsearch.xpack.ql.session.Configuration; import org.elasticsearch.xpack.ql.session.Configuration;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
@ -19,7 +18,7 @@ public class StartsWith extends org.elasticsearch.xpack.ql.expression.function.s
@Override @Override
public boolean isCaseSensitive() { public boolean isCaseSensitive() {
return ((EqlConfiguration) configuration()).isCaseSensitive(); return true;
} }
} }

View File

@ -132,6 +132,6 @@ public class StringContains extends CaseSensitiveScalarFunction {
@Override @Override
public boolean isCaseSensitive() { public boolean isCaseSensitive() {
return eqlConfiguration().isCaseSensitive(); return true;
} }
} }

View File

@ -131,7 +131,7 @@ public class Optimizer extends RuleExecutor<LogicalPlan> {
} }
if (target != null) { if (target != null) {
Expression like = new Like(e.source(), target, StringUtils.toLikePattern(wildString)); Expression like = new Like(e.source(), target, StringUtils.toLikePattern(wildString), true);
if (e instanceof InsensitiveNotEquals) { if (e instanceof InsensitiveNotEquals) {
like = new Not(e.source(), like); like = new Not(e.source(), like);
} }

View File

@ -103,7 +103,7 @@ final class QueryTranslator {
// (which is important for strings) // (which is important for strings)
name = ((FieldAttribute) bc.left()).exactAttribute().name(); name = ((FieldAttribute) bc.left()).exactAttribute().name();
} }
Query query = new TermQuery(source, name, value); Query query = new TermQuery(source, name, value, true);
if (bc instanceof InsensitiveNotEquals) { if (bc instanceof InsensitiveNotEquals) {
query = new NotQuery(source, query); query = new NotQuery(source, query);

View File

@ -119,7 +119,7 @@ public class TransportEqlSearchAction extends HandledTransportAction<EqlSearchRe
.fetchSize(request.fetchSize()); .fetchSize(request.fetchSize());
EqlConfiguration cfg = new EqlConfiguration(request.indices(), zoneId, username, clusterName, filter, timeout, includeFrozen, EqlConfiguration cfg = new EqlConfiguration(request.indices(), zoneId, username, clusterName, filter, timeout, includeFrozen,
request.isCaseSensitive(), request.fetchSize(), clientId, new TaskId(nodeId, task.getId()), task); request.fetchSize(), clientId, new TaskId(nodeId, task.getId()), task);
planExecutor.eql(cfg, request.query(), params, wrap(r -> listener.onResponse(createResponse(r, task.getExecutionId())), planExecutor.eql(cfg, request.query(), params, wrap(r -> listener.onResponse(createResponse(r, task.getExecutionId())),
listener::onFailure)); listener::onFailure));
} }

View File

@ -23,14 +23,13 @@ public class EqlConfiguration extends org.elasticsearch.xpack.ql.session.Configu
private final boolean includeFrozenIndices; private final boolean includeFrozenIndices;
private final TaskId taskId; private final TaskId taskId;
private final EqlSearchTask task; private final EqlSearchTask task;
private final boolean isCaseSensitive;
private final int fetchSize; private final int fetchSize;
@Nullable @Nullable
private final QueryBuilder filter; private final QueryBuilder filter;
public EqlConfiguration(String[] indices, ZoneId zi, String username, String clusterName, QueryBuilder filter, TimeValue requestTimeout, public EqlConfiguration(String[] indices, ZoneId zi, String username, String clusterName, QueryBuilder filter, TimeValue requestTimeout,
boolean includeFrozen, boolean isCaseSensitive, int fetchSize, String clientId, TaskId taskId, boolean includeFrozen, int fetchSize, String clientId, TaskId taskId,
EqlSearchTask task) { EqlSearchTask task) {
super(zi, username, clusterName); super(zi, username, clusterName);
@ -39,7 +38,6 @@ public class EqlConfiguration extends org.elasticsearch.xpack.ql.session.Configu
this.requestTimeout = requestTimeout; this.requestTimeout = requestTimeout;
this.clientId = clientId; this.clientId = clientId;
this.includeFrozenIndices = includeFrozen; this.includeFrozenIndices = includeFrozen;
this.isCaseSensitive = isCaseSensitive;
this.taskId = taskId; this.taskId = taskId;
this.task = task; this.task = task;
this.fetchSize = fetchSize; this.fetchSize = fetchSize;
@ -73,10 +71,6 @@ public class EqlConfiguration extends org.elasticsearch.xpack.ql.session.Configu
return includeFrozenIndices; return includeFrozenIndices;
} }
public boolean isCaseSensitive() {
return isCaseSensitive;
}
public boolean isCancelled() { public boolean isCancelled() {
return task.isCancelled(); return task.isCancelled();
} }

View File

@ -31,23 +31,11 @@ public final class EqlTestUtils {
private EqlTestUtils() { private EqlTestUtils() {
} }
public static final EqlConfiguration TEST_CFG_CASE_INSENSITIVE = new EqlConfiguration(new String[] {"none"}, public static final EqlConfiguration TEST_CFG = new EqlConfiguration(new String[] {"none"},
org.elasticsearch.xpack.ql.util.DateUtils.UTC, "nobody", "cluster", null, TimeValue.timeValueSeconds(30), false, false, org.elasticsearch.xpack.ql.util.DateUtils.UTC, "nobody", "cluster", null, TimeValue.timeValueSeconds(30), false,
123, "", new TaskId("test", 123), null);
public static final EqlConfiguration TEST_CFG_CASE_SENSITIVE = new EqlConfiguration(new String[] {"none"},
org.elasticsearch.xpack.ql.util.DateUtils.UTC, "nobody", "cluster", null, TimeValue.timeValueSeconds(30), false, true,
123, "", new TaskId("test", 123), null); 123, "", new TaskId("test", 123), null);
public static EqlConfiguration randomConfiguration() { public static EqlConfiguration randomConfiguration() {
return internalRandomConfiguration(randomBoolean());
}
public static EqlConfiguration randomConfigurationWithCaseSensitive(boolean isCaseSensitive) {
return internalRandomConfiguration(isCaseSensitive);
}
private static EqlConfiguration internalRandomConfiguration(boolean isCaseSensitive) {
return new EqlConfiguration(new String[]{randomAlphaOfLength(16)}, return new EqlConfiguration(new String[]{randomAlphaOfLength(16)},
randomZone(), randomZone(),
randomAlphaOfLength(16), randomAlphaOfLength(16),
@ -55,7 +43,6 @@ public final class EqlTestUtils {
null, null,
new TimeValue(randomNonNegativeLong()), new TimeValue(randomNonNegativeLong()),
randomBoolean(), randomBoolean(),
isCaseSensitive,
randomIntBetween(1, 1000), randomIntBetween(1, 1000),
randomAlphaOfLength(16), randomAlphaOfLength(16),
new TaskId(randomAlphaOfLength(10), randomNonNegativeLong()), new TaskId(randomAlphaOfLength(10), randomNonNegativeLong()),

View File

@ -42,18 +42,13 @@ public class EqlRequestParserTests extends ESTestCase {
EqlSearchRequest::fromXContent); EqlSearchRequest::fromXContent);
assertParsingErrorMessage("{\"query\" : \"whatever\", \"size\":\"abc\"}", "failed to parse field [size]", assertParsingErrorMessage("{\"query\" : \"whatever\", \"size\":\"abc\"}", "failed to parse field [size]",
EqlSearchRequest::fromXContent); EqlSearchRequest::fromXContent);
assertParsingErrorMessage("{\"case_sensitive\" : \"whatever\"}", "failed to parse field [case_sensitive]",
EqlSearchRequest::fromXContent);
boolean setIsCaseSensitive = randomBoolean();
boolean isCaseSensitive = randomBoolean();
EqlSearchRequest request = generateRequest("endgame-*", "{\"filter\" : {\"match\" : {\"foo\":\"bar\"}}, " EqlSearchRequest request = generateRequest("endgame-*", "{\"filter\" : {\"match\" : {\"foo\":\"bar\"}}, "
+ "\"timestamp_field\" : \"tsf\", " + "\"timestamp_field\" : \"tsf\", "
+ "\"event_category_field\" : \"etf\"," + "\"event_category_field\" : \"etf\","
+ "\"size\" : \"101\"," + "\"size\" : \"101\","
+ "\"query\" : \"file where user != 'SYSTEM' by file_path\"" + "\"query\" : \"file where user != 'SYSTEM' by file_path\"}"
+ (setIsCaseSensitive ? (",\"case_sensitive\" : " + isCaseSensitive) : "") , EqlSearchRequest::fromXContent);
+ "}", EqlSearchRequest::fromXContent);
assertArrayEquals(new String[]{"endgame-*"}, request.indices()); assertArrayEquals(new String[]{"endgame-*"}, request.indices());
assertNotNull(request.query()); assertNotNull(request.query());
assertTrue(request.filter() instanceof MatchQueryBuilder); assertTrue(request.filter() instanceof MatchQueryBuilder);
@ -65,7 +60,6 @@ public class EqlRequestParserTests extends ESTestCase {
assertEquals(101, request.size()); assertEquals(101, request.size());
assertEquals(1000, request.fetchSize()); assertEquals(1000, request.fetchSize());
assertEquals("file where user != 'SYSTEM' by file_path", request.query()); assertEquals("file where user != 'SYSTEM' by file_path", request.query());
assertEquals(setIsCaseSensitive && isCaseSensitive, request.isCaseSensitive());
} }
private EqlSearchRequest generateRequest(String index, String json, Function<XContentParser, EqlSearchRequest> fromXContent) private EqlSearchRequest generateRequest(String index, String json, Function<XContentParser, EqlSearchRequest> fromXContent)

View File

@ -37,7 +37,7 @@ public class VerifierTests extends ESTestCase {
private LogicalPlan accept(IndexResolution resolution, String eql) { private LogicalPlan accept(IndexResolution resolution, String eql) {
PreAnalyzer preAnalyzer = new PreAnalyzer(); PreAnalyzer preAnalyzer = new PreAnalyzer();
Analyzer analyzer = new Analyzer(EqlTestUtils.TEST_CFG_CASE_INSENSITIVE, new EqlFunctionRegistry(), new Verifier(new Metrics())); Analyzer analyzer = new Analyzer(EqlTestUtils.TEST_CFG, new EqlFunctionRegistry(), new Verifier(new Metrics()));
return analyzer.analyze(preAnalyzer.preAnalyze(parser.createStatement(eql), resolution)); return analyzer.analyze(preAnalyzer.preAnalyze(parser.createStatement(eql), resolution));
} }

View File

@ -39,8 +39,7 @@ public class BetweenFunctionPipeTests extends AbstractNodeTestCase<BetweenFuncti
randomStringLiteral(), randomStringLiteral(),
randomStringLiteral(), randomStringLiteral(),
randomStringLiteral(), randomStringLiteral(),
randomFrom(true, false) ? randomBooleanLiteral() : null, randomFrom(true, false) ? randomBooleanLiteral() : null)
randomBooleanLiteral())
.makePipe()); .makePipe());
} }

View File

@ -11,8 +11,9 @@ import org.elasticsearch.xpack.ql.QlIllegalArgumentException;
import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.Literal;
import org.elasticsearch.xpack.ql.expression.LiteralTests; import org.elasticsearch.xpack.ql.expression.LiteralTests;
import org.elasticsearch.xpack.ql.session.Configuration; import org.elasticsearch.xpack.ql.session.Configuration;
import org.junit.Assume;
import static org.elasticsearch.xpack.eql.EqlTestUtils.randomConfigurationWithCaseSensitive; import static org.elasticsearch.xpack.eql.EqlTestUtils.randomConfiguration;
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.l; import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.l;
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD;
@ -20,10 +21,8 @@ import static org.hamcrest.Matchers.startsWith;
public class EndsWithFunctionProcessorTests extends ESTestCase { public class EndsWithFunctionProcessorTests extends ESTestCase {
final Configuration caseInsensitive = randomConfigurationWithCaseSensitive(false);
public void testEndsWithFunctionWithValidInputCaseSensitive() { public void testEndsWithFunctionWithValidInputCaseSensitive() {
final Configuration caseSensitive = randomConfigurationWithCaseSensitive(true); final Configuration caseSensitive = randomConfiguration();
assertEquals(true, new EndsWith(EMPTY, l("foobarbar"), l("r"), caseSensitive).makePipe().asProcessor().process(null)); assertEquals(true, new EndsWith(EMPTY, l("foobarbar"), l("r"), caseSensitive).makePipe().asProcessor().process(null));
assertEquals(false, new EndsWith(EMPTY, l("foobarbar"), l("R"), caseSensitive).makePipe().asProcessor().process(null)); assertEquals(false, new EndsWith(EMPTY, l("foobarbar"), l("R"), caseSensitive).makePipe().asProcessor().process(null));
assertEquals(true, new EndsWith(EMPTY, l("foobarbar"), l("bar"), caseSensitive).makePipe().asProcessor().process(null)); assertEquals(true, new EndsWith(EMPTY, l("foobarbar"), l("bar"), caseSensitive).makePipe().asProcessor().process(null));
@ -42,6 +41,9 @@ public class EndsWithFunctionProcessorTests extends ESTestCase {
} }
public void testEndsWithFunctionWithValidInputCaseInsensitive() { public void testEndsWithFunctionWithValidInputCaseInsensitive() {
Assume.assumeTrue(false); //TODO: revisit after we decide on functions case sensitivity handling
final Configuration caseInsensitive = randomConfiguration();
assertEquals(true, new EndsWith(EMPTY, l("foobarbar"), l("r"), caseInsensitive).makePipe().asProcessor().process(null)); assertEquals(true, new EndsWith(EMPTY, l("foobarbar"), l("r"), caseInsensitive).makePipe().asProcessor().process(null));
assertEquals(true, new EndsWith(EMPTY, l("foobarbar"), l("R"), caseInsensitive).makePipe().asProcessor().process(null)); assertEquals(true, new EndsWith(EMPTY, l("foobarbar"), l("R"), caseInsensitive).makePipe().asProcessor().process(null));
assertEquals(false, new EndsWith(EMPTY, l("foobar"), l("foo"), caseInsensitive).makePipe().asProcessor().process(null)); assertEquals(false, new EndsWith(EMPTY, l("foobar"), l("foo"), caseInsensitive).makePipe().asProcessor().process(null));
@ -58,21 +60,23 @@ public class EndsWithFunctionProcessorTests extends ESTestCase {
} }
public void testEndsWithFunctionInputsValidation() { public void testEndsWithFunctionInputsValidation() {
Configuration config = randomConfiguration();
QlIllegalArgumentException siae = expectThrows(QlIllegalArgumentException.class, QlIllegalArgumentException siae = expectThrows(QlIllegalArgumentException.class,
() -> new EndsWith(EMPTY, l(5), l("foo"), caseInsensitive).makePipe().asProcessor().process(null)); () -> new EndsWith(EMPTY, l(5), l("foo"), config).makePipe().asProcessor().process(null));
assertEquals("A string/char is required; received [5]", siae.getMessage()); assertEquals("A string/char is required; received [5]", siae.getMessage());
siae = expectThrows(QlIllegalArgumentException.class, siae = expectThrows(QlIllegalArgumentException.class,
() -> new EndsWith(EMPTY, l("bar"), l(false), caseInsensitive).makePipe().asProcessor().process(null)); () -> new EndsWith(EMPTY, l("bar"), l(false), config).makePipe().asProcessor().process(null));
assertEquals("A string/char is required; received [false]", siae.getMessage()); assertEquals("A string/char is required; received [false]", siae.getMessage());
} }
public void testEndsWithFunctionWithRandomInvalidDataType() { public void testEndsWithFunctionWithRandomInvalidDataType() {
Configuration config = randomConfiguration();
Literal literal = randomValueOtherThanMany(v -> v.dataType() == KEYWORD, () -> LiteralTests.randomLiteral()); Literal literal = randomValueOtherThanMany(v -> v.dataType() == KEYWORD, () -> LiteralTests.randomLiteral());
QlIllegalArgumentException siae = expectThrows(QlIllegalArgumentException.class, QlIllegalArgumentException siae = expectThrows(QlIllegalArgumentException.class,
() -> new EndsWith(EMPTY, literal, l("foo"), caseInsensitive).makePipe().asProcessor().process(null)); () -> new EndsWith(EMPTY, literal, l("foo"), config).makePipe().asProcessor().process(null));
assertThat(siae.getMessage(), startsWith("A string/char is required; received")); assertThat(siae.getMessage(), startsWith("A string/char is required; received"));
siae = expectThrows(QlIllegalArgumentException.class, siae = expectThrows(QlIllegalArgumentException.class,
() -> new EndsWith(EMPTY, l("foo"), literal, caseInsensitive).makePipe().asProcessor().process(null)); () -> new EndsWith(EMPTY, l("foo"), literal, config).makePipe().asProcessor().process(null));
assertThat(siae.getMessage(), startsWith("A string/char is required; received")); assertThat(siae.getMessage(), startsWith("A string/char is required; received"));
} }
} }

View File

@ -11,8 +11,9 @@ import org.elasticsearch.xpack.ql.QlIllegalArgumentException;
import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.Literal;
import org.elasticsearch.xpack.ql.expression.LiteralTests; import org.elasticsearch.xpack.ql.expression.LiteralTests;
import org.elasticsearch.xpack.ql.session.Configuration; import org.elasticsearch.xpack.ql.session.Configuration;
import org.junit.Assume;
import static org.elasticsearch.xpack.eql.EqlTestUtils.randomConfigurationWithCaseSensitive; import static org.elasticsearch.xpack.eql.EqlTestUtils.randomConfiguration;
import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.l; import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.l;
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD;
@ -20,9 +21,10 @@ import static org.hamcrest.Matchers.startsWith;
public class IndexOfFunctionProcessorTests extends ESTestCase { public class IndexOfFunctionProcessorTests extends ESTestCase {
final Configuration caseInsensitive = randomConfigurationWithCaseSensitive(false);
public void testIndexOfFunctionWithValidInputInsensitive() { public void testIndexOfFunctionWithValidInputInsensitive() {
Assume.assumeTrue(false); //TODO: revisit after we decide on functions case sensitivity handling
final Configuration caseInsensitive = randomConfiguration();
assertEquals(5, new IndexOf(EMPTY, l("foobarbar"), l("r"), l(null), caseInsensitive).makePipe().asProcessor().process(null)); assertEquals(5, new IndexOf(EMPTY, l("foobarbar"), l("r"), l(null), caseInsensitive).makePipe().asProcessor().process(null));
assertEquals(5, new IndexOf(EMPTY, l("foobaRbar"), l("r"), l(null), caseInsensitive).makePipe().asProcessor().process(null)); assertEquals(5, new IndexOf(EMPTY, l("foobaRbar"), l("r"), l(null), caseInsensitive).makePipe().asProcessor().process(null));
assertEquals(0, new IndexOf(EMPTY, l("foobar"), l("Foo"), l(null), caseInsensitive).makePipe().asProcessor().process(null)); assertEquals(0, new IndexOf(EMPTY, l("foobar"), l("Foo"), l(null), caseInsensitive).makePipe().asProcessor().process(null));
@ -44,7 +46,7 @@ public class IndexOfFunctionProcessorTests extends ESTestCase {
} }
public void testIndexOfFunctionWithValidInputSensitive() { public void testIndexOfFunctionWithValidInputSensitive() {
final Configuration caseSensitive = randomConfigurationWithCaseSensitive(true); final Configuration caseSensitive = randomConfiguration();
assertEquals(5, new IndexOf(EMPTY, l("foobarbar"), l("r"), l(null), caseSensitive).makePipe().asProcessor().process(null)); assertEquals(5, new IndexOf(EMPTY, l("foobarbar"), l("r"), l(null), caseSensitive).makePipe().asProcessor().process(null));
assertEquals(8, new IndexOf(EMPTY, l("foobaRbar"), l("r"), l(null), caseSensitive).makePipe().asProcessor().process(null)); assertEquals(8, new IndexOf(EMPTY, l("foobaRbar"), l("r"), l(null), caseSensitive).makePipe().asProcessor().process(null));
assertEquals(4, new IndexOf(EMPTY, l("foobARbar"), l("AR"), l(null), caseSensitive).makePipe().asProcessor().process(null)); assertEquals(4, new IndexOf(EMPTY, l("foobARbar"), l("AR"), l(null), caseSensitive).makePipe().asProcessor().process(null));
@ -67,30 +69,32 @@ public class IndexOfFunctionProcessorTests extends ESTestCase {
} }
public void testIndexOfFunctionInputsValidation() { public void testIndexOfFunctionInputsValidation() {
Configuration config = randomConfiguration();
QlIllegalArgumentException siae = expectThrows(QlIllegalArgumentException.class, QlIllegalArgumentException siae = expectThrows(QlIllegalArgumentException.class,
() -> new IndexOf(EMPTY, l(5), l("foo"), l(null), caseInsensitive).makePipe().asProcessor().process(null)); () -> new IndexOf(EMPTY, l(5), l("foo"), l(null), config).makePipe().asProcessor().process(null));
assertEquals("A string/char is required; received [5]", siae.getMessage()); assertEquals("A string/char is required; received [5]", siae.getMessage());
siae = expectThrows(QlIllegalArgumentException.class, siae = expectThrows(QlIllegalArgumentException.class,
() -> new IndexOf(EMPTY, l("bar"), l(false), l(2), caseInsensitive).makePipe().asProcessor().process(null)); () -> new IndexOf(EMPTY, l("bar"), l(false), l(2), config).makePipe().asProcessor().process(null));
assertEquals("A string/char is required; received [false]", siae.getMessage()); assertEquals("A string/char is required; received [false]", siae.getMessage());
siae = expectThrows(QlIllegalArgumentException.class, siae = expectThrows(QlIllegalArgumentException.class,
() -> new IndexOf(EMPTY, l("bar"), l("a"), l("1"), caseInsensitive).makePipe().asProcessor().process(null)); () -> new IndexOf(EMPTY, l("bar"), l("a"), l("1"), config).makePipe().asProcessor().process(null));
assertEquals("A number is required; received [1]", siae.getMessage()); assertEquals("A number is required; received [1]", siae.getMessage());
} }
public void testIndexOfFunctionWithRandomInvalidDataType() { public void testIndexOfFunctionWithRandomInvalidDataType() {
Configuration config = randomConfiguration();
Literal stringLiteral = randomValueOtherThanMany(v -> v.dataType() == KEYWORD, () -> LiteralTests.randomLiteral()); Literal stringLiteral = randomValueOtherThanMany(v -> v.dataType() == KEYWORD, () -> LiteralTests.randomLiteral());
QlIllegalArgumentException siae = expectThrows(QlIllegalArgumentException.class, QlIllegalArgumentException siae = expectThrows(QlIllegalArgumentException.class,
() -> new IndexOf(EMPTY, stringLiteral, l("foo"), l(1), caseInsensitive).makePipe().asProcessor().process(null)); () -> new IndexOf(EMPTY, stringLiteral, l("foo"), l(1), config).makePipe().asProcessor().process(null));
assertThat(siae.getMessage(), startsWith("A string/char is required; received")); assertThat(siae.getMessage(), startsWith("A string/char is required; received"));
siae = expectThrows(QlIllegalArgumentException.class, siae = expectThrows(QlIllegalArgumentException.class,
() -> new IndexOf(EMPTY, l("foo"), stringLiteral, l(2), caseInsensitive).makePipe().asProcessor().process(null)); () -> new IndexOf(EMPTY, l("foo"), stringLiteral, l(2), config).makePipe().asProcessor().process(null));
assertThat(siae.getMessage(), startsWith("A string/char is required; received")); assertThat(siae.getMessage(), startsWith("A string/char is required; received"));
Literal numericLiteral = randomValueOtherThanMany(v -> v.dataType().isNumeric(), () -> LiteralTests.randomLiteral()); Literal numericLiteral = randomValueOtherThanMany(v -> v.dataType().isNumeric(), () -> LiteralTests.randomLiteral());
siae = expectThrows(QlIllegalArgumentException.class, siae = expectThrows(QlIllegalArgumentException.class,
() -> new IndexOf(EMPTY, l("foo"), l("o"), numericLiteral, caseInsensitive).makePipe().asProcessor().process(null)); () -> new IndexOf(EMPTY, l("foo"), l("o"), numericLiteral, config).makePipe().asProcessor().process(null));
assertThat(siae.getMessage(), startsWith("A number is required; received")); assertThat(siae.getMessage(), startsWith("A number is required; received"));
} }
} }

View File

@ -13,18 +13,18 @@ import org.elasticsearch.xpack.ql.tree.Source;
import java.util.function.Supplier; import java.util.function.Supplier;
import static org.elasticsearch.xpack.eql.EqlTestUtils.randomConfigurationWithCaseSensitive; import static org.elasticsearch.xpack.eql.EqlTestUtils.randomConfiguration;
public class StartsWithFunctionProcessorTests extends org.elasticsearch.xpack.ql.expression.function.scalar.string.StartsWithProcessorTests{ public class StartsWithFunctionProcessorTests extends org.elasticsearch.xpack.ql.expression.function.scalar.string.StartsWithProcessorTests{
@Override @Override
protected Supplier<Boolean> isCaseSensitiveGenerator() { protected Supplier<Boolean> isCaseSensitiveGenerator() {
return () -> randomBoolean(); return () -> Boolean.TRUE;
} }
@Override @Override
protected Supplier<Configuration> configurationGenerator() { protected Supplier<Configuration> configurationGenerator() {
return () -> randomConfigurationWithCaseSensitive(isCaseSensitive); return () -> randomConfiguration();
} }
@Override @Override

View File

@ -16,16 +16,10 @@ public class EqlFoldSpec {
private final String description; private final String description;
private final String expression; private final String expression;
private final Object expected; private final Object expected;
// flag to dictate which modes are supported for the test
// null -> apply the test to both modes (case sensitive and case insensitive)
// TRUE -> case sensitive
// FALSE -> case insensitive
private Boolean caseSensitive = null;
EqlFoldSpec(String name, String description, Boolean caseSensitive, String expression, Object expected) { EqlFoldSpec(String name, String description, String expression, Object expected) {
this.name = name; this.name = name;
this.description = description; this.description = description;
this.caseSensitive = caseSensitive;
this.expression = expression; this.expression = expression;
this.expected = expected; this.expected = expected;
} }
@ -38,15 +32,10 @@ public class EqlFoldSpec {
return expected; return expected;
} }
public Boolean caseSensitive() {
return caseSensitive;
}
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
appendWithComma(sb, "name", name); appendWithComma(sb, "name", name);
appendWithComma(sb, "expression", expression); appendWithComma(sb, "expression", expression);
appendWithComma(sb, "case_sensitive", caseSensitive == null ? "null" : caseSensitive);
appendWithComma(sb, "expected", expected == null ? "null" : expected); appendWithComma(sb, "expected", expected == null ? "null" : expected);
return sb.toString(); return sb.toString();
} }
@ -78,12 +67,11 @@ public class EqlFoldSpec {
EqlFoldSpec that = (EqlFoldSpec) other; EqlFoldSpec that = (EqlFoldSpec) other;
return Objects.equals(this.expression, that.expression) return Objects.equals(this.expression, that.expression);
&& Objects.equals(this.caseSensitive, that.caseSensitive);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(this.expression, this.caseSensitive); return Objects.hash(this.expression);
} }
} }

View File

@ -40,20 +40,6 @@ public class EqlFoldSpecLoader {
TomlTable fold = table.getTomlTable("fold"); TomlTable fold = table.getTomlTable("fold");
String description = getTrimmedString(table, "description"); String description = getTrimmedString(table, "description");
Boolean cs = null;
Boolean caseSensitive = table.getBoolean("case_sensitive");
Boolean caseInsensitive = table.getBoolean("case_insensitive");
// if case_sensitive is TRUE and case_insensitive is not TRUE (FALSE or NULL), then the test is case sensitive only
if (Boolean.TRUE.equals(caseSensitive)) {
if (Boolean.FALSE.equals(caseInsensitive) || caseInsensitive == null) {
cs = true;
}
}
// if case_sensitive is not TRUE (FALSE or NULL) and case_insensitive is TRUE, then the test is case insensitive only
else if (Boolean.TRUE.equals(caseInsensitive)) {
cs = false;
}
// in all other cases, the test should run no matter the case sensitivity (should test both scenarios)
if (fold != null) { if (fold != null) {
List<TomlTable> tests = fold.getArrayTable("tests"); List<TomlTable> tests = fold.getArrayTable("tests");
@ -61,7 +47,7 @@ public class EqlFoldSpecLoader {
for (TomlTable test : tests) { for (TomlTable test : tests) {
String expression = getTrimmedString(test, "expression"); String expression = getTrimmedString(test, "expression");
Object expected = test.get("expected"); Object expected = test.get("expected");
EqlFoldSpec spec = new EqlFoldSpec(name, description, cs, expression, expected); EqlFoldSpec spec = new EqlFoldSpec(name, description, expression, expected);
testSpecs.add(spec); testSpecs.add(spec);
} }
} }

View File

@ -60,7 +60,7 @@ import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap; import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.elasticsearch.xpack.eql.EqlTestUtils.TEST_CFG_CASE_INSENSITIVE; import static org.elasticsearch.xpack.eql.EqlTestUtils.TEST_CFG;
import static org.elasticsearch.xpack.ql.TestUtils.UTC; import static org.elasticsearch.xpack.ql.TestUtils.UTC;
import static org.elasticsearch.xpack.ql.expression.Literal.TRUE; import static org.elasticsearch.xpack.ql.expression.Literal.TRUE;
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
@ -84,9 +84,9 @@ public class OptimizerTests extends ESTestCase {
private LogicalPlan accept(IndexResolution resolution, String eql) { private LogicalPlan accept(IndexResolution resolution, String eql) {
PreAnalyzer preAnalyzer = new PreAnalyzer(); PreAnalyzer preAnalyzer = new PreAnalyzer();
PostAnalyzer postAnalyzer = new PostAnalyzer(); PostAnalyzer postAnalyzer = new PostAnalyzer();
Analyzer analyzer = new Analyzer(TEST_CFG_CASE_INSENSITIVE, new EqlFunctionRegistry(), new Verifier(new Metrics())); Analyzer analyzer = new Analyzer(TEST_CFG, new EqlFunctionRegistry(), new Verifier(new Metrics()));
return optimizer.optimize(postAnalyzer.postAnalyze(analyzer.analyze(preAnalyzer.preAnalyze(parser.createStatement(eql), return optimizer.optimize(postAnalyzer.postAnalyze(analyzer.analyze(preAnalyzer.preAnalyze(parser.createStatement(eql),
resolution)), TEST_CFG_CASE_INSENSITIVE)); resolution)), TEST_CFG));
} }
private LogicalPlan accept(String eql) { private LogicalPlan accept(String eql) {

View File

@ -29,8 +29,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.elasticsearch.xpack.eql.EqlTestUtils.TEST_CFG_CASE_INSENSITIVE; import static org.elasticsearch.xpack.eql.EqlTestUtils.TEST_CFG;
import static org.elasticsearch.xpack.eql.EqlTestUtils.TEST_CFG_CASE_SENSITIVE;
import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY;
public class TomlFoldTests extends ESTestCase { public class TomlFoldTests extends ESTestCase {
@ -40,8 +39,7 @@ public class TomlFoldTests extends ESTestCase {
private static EqlParser parser = new EqlParser(); private static EqlParser parser = new EqlParser();
private static final EqlFunctionRegistry functionRegistry = new EqlFunctionRegistry(); private static final EqlFunctionRegistry functionRegistry = new EqlFunctionRegistry();
private static Verifier verifier = new Verifier(new Metrics()); private static Verifier verifier = new Verifier(new Metrics());
private static Analyzer caseSensitiveAnalyzer = new Analyzer(TEST_CFG_CASE_SENSITIVE, functionRegistry, verifier); private static Analyzer analyzer = new Analyzer(TEST_CFG, functionRegistry, verifier);
private static Analyzer caseInsensitiveAnalyzer = new Analyzer(TEST_CFG_CASE_INSENSITIVE, functionRegistry, verifier);
private final int num; private final int num;
private final EqlFoldSpec spec; private final EqlFoldSpec spec;
@ -70,30 +68,6 @@ public class TomlFoldTests extends ESTestCase {
} }
public void test() { public void test() {
// run both tests if case sensitivity doesn't matter
if (spec.caseSensitive() == null) {
testCaseSensitive(spec);
testCaseInsensitive(spec);
}
// run only the case sensitive test
else if (spec.caseSensitive()) {
testCaseSensitive(spec);
}
// run only the case insensitive test
else {
testCaseInsensitive(spec);
}
}
private void testCaseSensitive(EqlFoldSpec spec) {
testWithAnalyzer(caseSensitiveAnalyzer, spec);
}
private void testCaseInsensitive(EqlFoldSpec spec) {
testWithAnalyzer(caseInsensitiveAnalyzer, spec);
}
private void testWithAnalyzer(Analyzer analyzer, EqlFoldSpec spec) {
Expression expr = parser.createExpression(spec.expression()); Expression expr = parser.createExpression(spec.expression());
LogicalPlan logicalPlan = new Project(EMPTY, new LocalRelation(EMPTY, emptyList()), LogicalPlan logicalPlan = new Project(EMPTY, new LocalRelation(EMPTY, emptyList()),
singletonList(new Alias(Source.EMPTY, "test", expr))); singletonList(new Alias(Source.EMPTY, "test", expr)));

View File

@ -33,13 +33,13 @@ public class QueryFolderFailTests extends AbstractQueryFolderTestCase {
"process where between(process_name, \"s\") == \"yst\"", "process where between(process_name, \"s\") == \"yst\"",
"process where between(null) == \"yst\"", "process where between(null) == \"yst\"",
"process where between(process_name, null) == \"yst\"", "process where between(process_name, null) == \"yst\"",
"process where between(process_name, \"s\", \"e\", false, false, true) == \"yst\"", "process where between(process_name, \"s\", \"e\", false, false) == \"yst\"",
}; };
for (String query : queries) { for (String query : queries) {
ParsingException e = expectThrows(ParsingException.class, ParsingException e = expectThrows(ParsingException.class,
() -> plan(query)); () -> plan(query));
assertEquals("line 1:16: error building [between]: expects between three and five arguments", e.getMessage()); assertEquals("line 1:16: error building [between]: expects three or four arguments", e.getMessage());
} }
} }
@ -56,10 +56,6 @@ public class QueryFolderFailTests extends AbstractQueryFolderTestCase {
assertEquals("1:15: fourth argument of [between(process_name, \"s\", \"e\", \"true\")] must be [boolean], " + assertEquals("1:15: fourth argument of [between(process_name, \"s\", \"e\", \"true\")] must be [boolean], " +
"found value [\"true\"] type [keyword]", "found value [\"true\"] type [keyword]",
error("process where between(process_name, \"s\", \"e\", \"true\")")); error("process where between(process_name, \"s\", \"e\", \"true\")"));
assertEquals("1:15: fifth argument of [between(process_name, \"s\", \"e\", false, 2)] must be [boolean], " +
"found value [2] type [integer]",
error("process where between(process_name, \"s\", \"e\", false, 2)"));
} }
public void testCIDRMatchAgainstField() { public void testCIDRMatchAgainstField() {

View File

@ -10,14 +10,12 @@ import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.xpack.eql.plan.physical.EsQueryExec; import org.elasticsearch.xpack.eql.plan.physical.EsQueryExec;
import org.elasticsearch.xpack.eql.plan.physical.PhysicalPlan; import org.elasticsearch.xpack.eql.plan.physical.PhysicalPlan;
import org.junit.Assume;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
@ -110,13 +108,6 @@ public class QueryFolderOkTests extends AbstractQueryFolderTestCase {
} }
public void test() { public void test() {
String testName = name.toLowerCase(Locale.ROOT);
// skip tests that do not make sense from case sensitivity point of view
boolean isCaseSensitiveValidTest = testName.endsWith("sensitive") == false
|| testName.endsWith("-casesensitive") && configuration.isCaseSensitive()
|| testName.endsWith("-caseinsensitive") && configuration.isCaseSensitive() == false;
Assume.assumeTrue(isCaseSensitiveValidTest);
PhysicalPlan p = plan(query); PhysicalPlan p = plan(query);
assertEquals(EsQueryExec.class, p.getClass()); assertEquals(EsQueryExec.class, p.getClass());
EsQueryExec eqe = (EsQueryExec) p; EsQueryExec eqe = (EsQueryExec) p;

View File

@ -23,6 +23,8 @@ registry where not pid;
process where process_name : "net.exe" and command_line : "* user*.exe"; process where process_name : "net.exe" and command_line : "* user*.exe";
process where process_name : "net.EXE" and command_line : "* user*.EXE";
process where command_line : "~!@#$%^&*();'[]{}\\|<>?,./:\"-= ' "; process where command_line : "~!@#$%^&*();'[]{}\\|<>?,./:\"-= ' ";
process where process where
@ -33,6 +35,8 @@ process where process_name in ("net.exe", "cmd.exe", "at.exe");
process where command_line : "*.exe *admin*" or command_line : "* a b*"; process where command_line : "*.exe *admin*" or command_line : "* a b*";
process where command_line : "*.eXe *aDMin*" or command_line : "* a b*";
process where pid in (1,2,3,4,5,6,7,8) and abc : 100 and def : 200 and ghi : 300 and jkl : x; process where pid in (1,2,3,4,5,6,7,8) and abc : 100 and def : 200 and ghi : 300 and jkl : x;
process where ppid != pid; process where ppid != pid;

View File

@ -10,6 +10,8 @@
// ... // ...
// <expectation n> // <expectation n>
// ; // ;
// NOTE: do not use whitespaces in the relevant parts of the query itself, as they will be removed. For example 'process where process_name : "System Idle Process"'
// The whitespaces between System Idle Process will be removed and the assertion will fail.
basic basic
@ -21,7 +23,7 @@ null
singleNumericFilterEquals singleNumericFilterEquals
process where serial_event_id == 1 process where serial_event_id == 1
; ;
"term":{"serial_event_id":{"value":1 "term":{"serial_event_id":{"value":1,"boost":1.0}
; ;
singleNumericFilterLess singleNumericFilterLess
@ -48,10 +50,16 @@ process where serial_event_id >= 4
"range":{"serial_event_id":{"from":4,"to":null,"include_lower":true,"include_upper":false "range":{"serial_event_id":{"from":4,"to":null,"include_lower":true,"include_upper":false
; ;
caseInsensitiveEquals
process where process_name : "test"
;
"term":{"process_name":{"value":"test","case_insensitive":true,"boost":1.0}
;
mixedTypeFilter mixedTypeFilter
process where process_name : "notepad.exe" or (serial_event_id < 4.5 and serial_event_id >= 3.1) process where process_name : "notepad.exe" or (serial_event_id < 4.5 and serial_event_id >= 3.1)
; ;
"term":{"process_name":{"value":"notepad.exe" "term":{"process_name":{"value":"notepad.exe","case_insensitive":true,"boost":1.0}
"range":{"serial_event_id":{"from":3.1,"to":4.5,"include_lower":true,"include_upper":false "range":{"serial_event_id":{"from":3.1,"to":4.5,"include_lower":true,"include_upper":false
; ;
@ -70,35 +78,35 @@ process where process_name in ("python.exe", "SMSS.exe", "explorer.exe")
equalsAndInFilter equalsAndInFilter
process where process_path : "*\\red_ttp\\wininit.*" and opcode in (0,1,2,3) process where process_path : "*\\red_ttp\\wininit.*" and opcode in (0,1,2,3)
; ;
"wildcard":{"process_path":{"wildcard":"*\\\\red_ttp\\\\wininit.*" "wildcard":{"process_path":{"wildcard":"*\\\\red_ttp\\\\wininit.*","case_insensitive":true,"boost":1.0}}},
{"terms":{"opcode":[0,1,2,3] {"terms":{"opcode":[0,1,2,3],"boost":1.0}}
; ;
functionEqualsTrue functionEqualsTrue
process where cidrMatch(source_address, "10.0.0.0/8") == true process where cidrMatch(source_address, "10.0.0.0/8") == true
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process" {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}
{"terms":{"source_address":["10.0.0.0/8"] {"terms":{"source_address":["10.0.0.0/8"]
; ;
functionEqualsFalse functionEqualsFalse
process where cidrMatch(source_address, "10.0.0.0/8") == false process where cidrMatch(source_address, "10.0.0.0/8") == false
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process" {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}
{"bool":{"must_not":[{"terms":{"source_address":["10.0.0.0/8"] {"bool":{"must_not":[{"terms":{"source_address":["10.0.0.0/8"]
; ;
functionNotEqualsTrue functionNotEqualsTrue
process where cidrMatch(source_address, "10.0.0.0/8") != true process where cidrMatch(source_address, "10.0.0.0/8") != true
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process" {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}
{"bool":{"must_not":[{"terms":{"source_address":["10.0.0.0/8"] {"bool":{"must_not":[{"terms":{"source_address":["10.0.0.0/8"]
; ;
functionNotEqualsFalse functionNotEqualsFalse
process where cidrMatch(source_address, "10.0.0.0/8") != false process where cidrMatch(source_address, "10.0.0.0/8") != false
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process" {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}
{"terms":{"source_address":["10.0.0.0/8"] {"terms":{"source_address":["10.0.0.0/8"]
; ;
@ -112,13 +120,8 @@ process where endsWith(process_path, "x") == true and endsWith(process_path, "yx
twoFunctionsEqualsBooleanLiterals-caseInsensitive twoFunctionsEqualsBooleanLiterals-caseInsensitive
process where endsWith(process_path, "x") == true and endsWith(process_path, "yx") != true process where endsWith(process_path, "x") == true and endsWith(process_path, "yx") != true
; ;
"bool":{"must":[{"term":{"event.category":{"value":"process" {"bool":{"must":[{"wildcard":{"process_path":{"wildcard":"*x","boost":1.0}}},
"must":[{"script":{"script":{"source":"InternalQlScriptUtils.nullSafeFilter( {"bool":{"must_not":[{"wildcard":{"process_path":{"wildcard":"*yx","boost":1.0}}}],"adjust_pure_negative":true,"boost":1.0}}],"adjust_pure_negative":true,"boost":1.0}}
InternalEqlScriptUtils.endsWith(InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2))","lang":"painless",
"params":{"v0":"process_path","v1":"x","v2":false}}
"script":{"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.not(
InternalEqlScriptUtils.endsWith(InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2)))","lang":"painless",
"params":{"v0":"process_path","v1":"yx","v2":false}}
; ;
endsWithKeywordFieldFunction-caseSensitive endsWithKeywordFieldFunction-caseSensitive
@ -138,9 +141,8 @@ process where endsWith(hostname, "c")
endsWithFunction-caseInsensitive endsWithFunction-caseInsensitive
process where endsWith(user_name, "c") process where endsWith(user_name, "c")
; ;
"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalEqlScriptUtils.endsWith( {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}},
InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2))", {"wildcard":{"user_name":{"wildcard":"*c","boost":1.0}}}],"adjust_pure_negative":true,"boost":1.0}}
"params":{"v0":"user_name","v1":"c","v2":false}}
; ;
lengthFunctionWithExactSubField lengthFunctionWithExactSubField
@ -170,9 +172,8 @@ InternalEqlScriptUtils.length(InternalQlScriptUtils.docValue(doc,params.v0)),par
startsWithFunction-caseInsensitive startsWithFunction-caseInsensitive
process where startsWith(user_name, "A") process where startsWith(user_name, "A")
; ;
"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.startsWith( {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}},
InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2))", {"prefix":{"user_name":{"value":"A","boost":1.0}}}],"adjust_pure_negative":true,"boost":1.0}}
"params":{"v0":"user_name","v1":"A","v2":false}}
; ;
startsWithFunctionSimple-caseSensitive startsWithFunctionSimple-caseSensitive
@ -207,9 +208,8 @@ process where stringContains(hostname, "foo")
stringContains-caseInsensitive stringContains-caseInsensitive
process where stringContains(process_name, "foo") process where stringContains(process_name, "foo")
; ;
"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalEqlScriptUtils.stringContains( {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}}},
InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2))" {"wildcard":{"process_name":{"wildcard":"*foo*","boost":1.0}}}],"adjust_pure_negative":true,"boost":1.0}}
"params":{"v0":"process_name","v1":"foo","v2":false}
; ;
@ -234,7 +234,7 @@ process where indexOf(user_name, "A", 2) > 0
; ;
"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gt( "script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gt(
InternalEqlScriptUtils.indexOf(InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2,params.v3),params.v4))", InternalEqlScriptUtils.indexOf(InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2,params.v3),params.v4))",
"params":{"v0":"user_name","v1":"A","v2":2,"v3":false,"v4":0} "params":{"v0":"user_name","v1":"A","v2":2,"v3":true,"v4":0}
; ;
substringFunction substringFunction
@ -250,7 +250,7 @@ process where between(process_name, "s", "e") : "yst"
; ;
"script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalEqlScriptUtils.seq( "script":{"source":"InternalQlScriptUtils.nullSafeFilter(InternalEqlScriptUtils.seq(
InternalEqlScriptUtils.between(InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2,params.v3,params.v4),params.v5))", InternalEqlScriptUtils.between(InternalQlScriptUtils.docValue(doc,params.v0),params.v1,params.v2,params.v3,params.v4),params.v5))",
"params":{"v0":"process_name","v1":"s","v2":"e","v3":false,"v4":false,"v5":"yst"} "params":{"v0":"process_name","v1":"s","v2":"e","v3":false,"v4":true,"v5":"yst"}
; ;
concatFunction concatFunction
@ -264,35 +264,35 @@ InternalEqlScriptUtils.concat([InternalQlScriptUtils.docValue(doc,params.v0),par
cidrMatchFunctionOne cidrMatchFunctionOne
process where cidrMatch(source_address, "10.0.0.0/8") process where cidrMatch(source_address, "10.0.0.0/8")
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process" {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}
{"terms":{"source_address":["10.0.0.0/8"] {"terms":{"source_address":["10.0.0.0/8"]
; ;
cidrMatchFunctionOneBool cidrMatchFunctionOneBool
process where cidrMatch(source_address, "10.0.0.0/8") == true process where cidrMatch(source_address, "10.0.0.0/8") == true
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process" {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}
{"terms":{"source_address":["10.0.0.0/8"] {"terms":{"source_address":["10.0.0.0/8"]
; ;
cidrMatchFunctionTwo cidrMatchFunctionTwo
process where cidrMatch(source_address, "10.0.0.0/8", "192.168.0.0/16") process where cidrMatch(source_address, "10.0.0.0/8", "192.168.0.0/16")
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process" {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}
{"terms":{"source_address":["10.0.0.0/8","192.168.0.0/16"] {"terms":{"source_address":["10.0.0.0/8","192.168.0.0/16"]
; ;
cidrMatchFunctionTwoWithOr cidrMatchFunctionTwoWithOr
process where cidrMatch(source_address, "10.0.0.0/8") or cidrMatch(source_address, "192.168.0.0/16") process where cidrMatch(source_address, "10.0.0.0/8") or cidrMatch(source_address, "192.168.0.0/16")
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process" {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}
{"bool":{"should":[{"terms":{"source_address":["10.0.0.0/8"],"boost":1.0}},{"terms":{"source_address":["192.168.0.0/16"],"boost":1.0}} {"bool":{"should":[{"terms":{"source_address":["10.0.0.0/8"],"boost":1.0}},{"terms":{"source_address":["192.168.0.0/16"],"boost":1.0}}
; ;
cidrMatchFunctionThree cidrMatchFunctionThree
process where cidrMatch(source_address, "10.0.0.0/8", "192.168.0.0/16", "2001:db8::/32") process where cidrMatch(source_address, "10.0.0.0/8", "192.168.0.0/16", "2001:db8::/32")
; ;
{"bool":{"must":[{"term":{"event.category":{"value":"process" {"bool":{"must":[{"term":{"event.category":{"value":"process","boost":1.0}
{"terms":{"source_address":["10.0.0.0/8","192.168.0.0/16","2001:db8::/32"] {"terms":{"source_address":["10.0.0.0/8","192.168.0.0/16","2001:db8::/32"]
; ;
@ -351,34 +351,34 @@ InternalEqlScriptUtils.number(InternalQlScriptUtils.docValue(doc,params.v0),para
numberFunctionFoldedComparison numberFunctionFoldedComparison
process where serial_event_id == number("-32.5"); process where serial_event_id == number("-32.5");
{"term":{"serial_event_id":{"value":-32.5, {"term":{"serial_event_id":{"value":-32.5,"boost":1.0}
; ;
numberFunctionFoldedHexComparison numberFunctionFoldedHexComparison
process where serial_event_id == number("0x32", 16); process where serial_event_id == number("0x32", 16);
{"term":{"serial_event_id":{"value":50, {"term":{"serial_event_id":{"value":50,"boost":1.0}
; ;
wildcardFunctionSingleArgument wildcardFunctionSingleArgument
process where wildcard(process_path, "*\\red_ttp\\wininit.*") process where wildcard(process_path, "*\\red_ttp\\wininit.*")
; ;
"wildcard":{"process_path":{"wildcard":"*\\\\red_ttp\\\\wininit.*" "wildcard":{"process_path":{"wildcard":"*\\\\red_ttp\\\\wininit.*","boost":1.0}}
; ;
wildcardFunctionTwoArguments wildcardFunctionTwoArguments
process where wildcard(process_path, "*\\red_ttp\\wininit.*", "*\\abc\\*") process where wildcard(process_path, "*\\red_ttp\\wininit.*", "*\\abc\\*")
; ;
"wildcard":{"process_path":{"wildcard":"*\\\\red_ttp\\\\wininit.*" "wildcard":{"process_path":{"wildcard":"*\\\\red_ttp\\\\wininit.*","boost":1.0}}
"wildcard":{"process_path":{"wildcard":"*\\\\abc\\\\*" "wildcard":{"process_path":{"wildcard":"*\\\\abc\\\\*","boost":1.0}}
; ;
wildcardFunctionThreeArguments wildcardFunctionThreeArguments
process where wildcard(process_path, "*\\red_ttp\\wininit.*", "*\\abc\\*", "*def*") process where wildcard(process_path, "*\\red_ttp\\wininit.*", "*\\abc\\*", "*def*")
; ;
"wildcard":{"process_path":{"wildcard":"*\\\\red_ttp\\\\wininit.*" "wildcard":{"process_path":{"wildcard":"*\\\\red_ttp\\\\wininit.*","boost":1.0}}
"wildcard":{"process_path":{"wildcard":"*\\\\abc\\\\*" "wildcard":{"process_path":{"wildcard":"*\\\\abc\\\\*","boost":1.0}}
"wildcard":{"process_path":{"wildcard":"*def*" "wildcard":{"process_path":{"wildcard":"*def*","boost":1.0}}
; ;

View File

@ -210,7 +210,6 @@ description = "Fold string comparisons"
[string_case_sensitive_match_comparison] [string_case_sensitive_match_comparison]
description = "Fold string comparisons" description = "Fold string comparisons"
case_sensitive = true
[[string_case_sensitive_match_comparison.fold.tests]] [[string_case_sensitive_match_comparison.fold.tests]]
expression = '"Foo" == "foo"' expression = '"Foo" == "foo"'

View File

@ -104,16 +104,14 @@ description = "Test the `endsWith` function with case matching"
[endswith_insensitive] [endswith_insensitive]
description = "Test the `endsWith` function with case insensitivity" description = "Test the `endsWith` function with case insensitivity"
case_insensitive = true
[[endswith_insensitive.fold.tests]] [[endswith_insensitive.fold.tests]]
expression = 'endsWith("FooBarBaz", "baz")' expression = 'endsWith("FooBarBaz", "baz")'
expected = true expected = false
[endswith_sensitive] [endswith_sensitive]
description = "Test the `endsWith` function with case sensitivity" description = "Test the `endsWith` function with case sensitivity"
case_sensitive = true
[[endswith_sensitive.fold.tests]] [[endswith_sensitive.fold.tests]]
expression = 'endsWith("FooBarBaz", "baz")' expression = 'endsWith("FooBarBaz", "baz")'
@ -331,7 +329,6 @@ description = "Test the `startsWith` function"
[startswith_case_sensitive] [startswith_case_sensitive]
description = "Test the `startsWith` function with case-sensitive matching" description = "Test the `startsWith` function with case-sensitive matching"
case_sensitive = true
[[startswith_case_sensitive.tests]] [[startswith_case_sensitive.tests]]
expression = '''startsWith("FooBar", "Foo")''' expression = '''startsWith("FooBar", "Foo")'''
@ -344,7 +341,6 @@ case_sensitive = true
[startswith_case_insensitive] [startswith_case_insensitive]
description = "Test the `startsWith` function with case-insensitive matching" description = "Test the `startsWith` function with case-insensitive matching"
case_insensitive = true
[[startswith_case_insensitive.fold.tests]] [[startswith_case_insensitive.fold.tests]]
expression = '''startsWith("FooBar", "Foo")''' expression = '''startsWith("FooBar", "Foo")'''
@ -352,11 +348,11 @@ case_insensitive = true
[[startswith_case_insensitive.fold.tests]] [[startswith_case_insensitive.fold.tests]]
expression = '''startsWith("FooBar", "FOO")''' expression = '''startsWith("FooBar", "FOO")'''
expected = true expected = false
[[startswith_case_insensitive.fold.tests]] [[startswith_case_insensitive.fold.tests]]
expression = '''startsWith("FooBar", "foo")''' expression = '''startsWith("FooBar", "foo")'''
expected = true expected = false
[[startswith_case_insensitive.fold.tests]] [[startswith_case_insensitive.fold.tests]]
expression = '''startsWith("FooBar", "Bar")''' expression = '''startsWith("FooBar", "Bar")'''
@ -498,11 +494,10 @@ description = "Test that `wildcard` folds with correct case matches."
[wildcard_case_insensitive] [wildcard_case_insensitive]
description = "Test that `wildcard` function folds case insensitive as expected." description = "Test that `wildcard` function folds case insensitive as expected."
case_insensitive = true
[[wildcard_case_insensitive.fold.tests]] [[wildcard_case_insensitive.fold.tests]]
expression = 'wildcard("FOO", "f*o*o*")' expression = 'wildcard("FOO", "f*o*o*")'
expected = true expected = false
[[wildcard_case_insensitive.fold.tests]] [[wildcard_case_insensitive.fold.tests]]
expression = 'wildcard("bar", "f*o*o*")' expression = 'wildcard("bar", "f*o*o*")'
@ -511,7 +506,6 @@ case_insensitive = true
[wildcard_case_sensitive] [wildcard_case_sensitive]
description = "Test that `wildcard` folds case-sensitive matches." description = "Test that `wildcard` folds case-sensitive matches."
case_sensitive = true
[[wildcard_case_sensitive.fold.tests]] [[wildcard_case_sensitive.fold.tests]]
expression = 'wildcard("Foo", "F*o*o*")' expression = 'wildcard("Foo", "F*o*o*")'

View File

@ -420,13 +420,16 @@ public class FunctionRegistry {
public static <T extends Function> FunctionDefinition def(Class<T> function, public static <T extends Function> FunctionDefinition def(Class<T> function,
FourParametersFunctionBuilder<T> ctorRef, String... names) { FourParametersFunctionBuilder<T> ctorRef, String... names) {
FunctionBuilder builder = (source, children, distinct, cfg) -> { FunctionBuilder builder = (source, children, distinct, cfg) -> {
if (children.size() != 4) { boolean hasMinimumThree = OptionalArgument.class.isAssignableFrom(function);
if (hasMinimumThree && (children.size() > 4 || children.size() < 3)) {
throw new QlIllegalArgumentException("expects three or four arguments");
} else if (!hasMinimumThree && children.size() != 4) {
throw new QlIllegalArgumentException("expects exactly four arguments"); throw new QlIllegalArgumentException("expects exactly four arguments");
} }
if (distinct) { if (distinct) {
throw new QlIllegalArgumentException("does not support DISTINCT yet it was specified"); throw new QlIllegalArgumentException("does not support DISTINCT yet it was specified");
} }
return ctorRef.build(source, children.get(0), children.get(1), children.get(2), children.get(3)); return ctorRef.build(source, children.get(0), children.get(1), children.get(2), children.size() == 4 ? children.get(3) : null);
}; };
return def(function, builder, false, names); return def(function, builder, false, names);
} }

View File

@ -9,19 +9,43 @@ import org.elasticsearch.xpack.ql.expression.Expression;
import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.NodeInfo;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
import java.util.Objects;
public class Like extends RegexMatch<LikePattern> { public class Like extends RegexMatch<LikePattern> {
private final boolean caseInsensitive;
public Like(Source source, Expression left, LikePattern pattern) { public Like(Source source, Expression left, LikePattern pattern) {
this(source, left, pattern, false);
}
public Like(Source source, Expression left, LikePattern pattern, boolean caseInsensitive) {
super(source, left, pattern); super(source, left, pattern);
this.caseInsensitive = caseInsensitive;
} }
@Override @Override
protected NodeInfo<Like> info() { protected NodeInfo<Like> info() {
return NodeInfo.create(this, Like::new, field(), pattern()); return NodeInfo.create(this, Like::new, field(), pattern(), caseInsensitive());
} }
@Override @Override
protected Like replaceChild(Expression newLeft) { protected Like replaceChild(Expression newLeft) {
return new Like(source(), newLeft, pattern()); return new Like(source(), newLeft, pattern(), caseInsensitive());
} }
public boolean caseInsensitive() {
return caseInsensitive;
}
@Override
public boolean equals(Object obj) {
return super.equals(obj) && Objects.equals(((Like) obj).caseInsensitive(), caseInsensitive());
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), caseInsensitive());
}
} }

View File

@ -32,7 +32,6 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessT
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals;
import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NullEquals; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NullEquals;
import org.elasticsearch.xpack.ql.expression.predicate.regex.Like; import org.elasticsearch.xpack.ql.expression.predicate.regex.Like;
import org.elasticsearch.xpack.ql.expression.predicate.regex.LikePattern;
import org.elasticsearch.xpack.ql.expression.predicate.regex.RLike; import org.elasticsearch.xpack.ql.expression.predicate.regex.RLike;
import org.elasticsearch.xpack.ql.expression.predicate.regex.RegexMatch; import org.elasticsearch.xpack.ql.expression.predicate.regex.RegexMatch;
import org.elasticsearch.xpack.ql.querydsl.query.BoolQuery; import org.elasticsearch.xpack.ql.querydsl.query.BoolQuery;
@ -127,8 +126,8 @@ public final class ExpressionTranslators {
if (e.field() instanceof FieldAttribute) { if (e.field() instanceof FieldAttribute) {
targetFieldName = handler.nameOf(((FieldAttribute) e.field()).exactAttribute()); targetFieldName = handler.nameOf(((FieldAttribute) e.field()).exactAttribute());
if (e instanceof Like) { if (e instanceof Like) {
LikePattern p = ((Like) e).pattern(); Like l = (Like) e;
q = new WildcardQuery(e.source(), targetFieldName, p.asLuceneWildcard()); q = new WildcardQuery(e.source(), targetFieldName, l.pattern().asLuceneWildcard(), l.caseInsensitive());
} }
if (e instanceof RLike) { if (e instanceof RLike) {

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.ql.querydsl.query; package org.elasticsearch.xpack.ql.querydsl.query;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
import java.util.Objects; import java.util.Objects;
@ -16,11 +17,17 @@ public class TermQuery extends LeafQuery {
private final String term; private final String term;
private final Object value; private final Object value;
private final boolean caseInsensitive;
public TermQuery(Source source, String term, Object value) { public TermQuery(Source source, String term, Object value) {
this(source, term, value, false);
}
public TermQuery(Source source, String term, Object value, boolean caseInsensitive) {
super(source); super(source);
this.term = term; this.term = term;
this.value = value; this.value = value;
this.caseInsensitive = caseInsensitive;
} }
public String term() { public String term() {
@ -31,14 +38,20 @@ public class TermQuery extends LeafQuery {
return value; return value;
} }
public Boolean caseInsensitive() {
return caseInsensitive;
}
@Override @Override
public QueryBuilder asBuilder() { public QueryBuilder asBuilder() {
return termQuery(term, value); TermQueryBuilder qb = termQuery(term, value);
// ES does not allow case_insensitive to be set to "false", it should be either "true" or not specified
return caseInsensitive == false ? qb : qb.caseInsensitive(caseInsensitive);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(term, value); return Objects.hash(term, value, caseInsensitive);
} }
@Override @Override
@ -53,7 +66,8 @@ public class TermQuery extends LeafQuery {
TermQuery other = (TermQuery) obj; TermQuery other = (TermQuery) obj;
return Objects.equals(term, other.term) return Objects.equals(term, other.term)
&& Objects.equals(value, other.value); && Objects.equals(value, other.value)
&& Objects.equals(caseInsensitive, other.caseInsensitive);
} }
@Override @Override

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.ql.querydsl.query; package org.elasticsearch.xpack.ql.querydsl.query;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.WildcardQueryBuilder;
import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.Source;
import java.util.Objects; import java.util.Objects;
@ -15,11 +16,17 @@ import static org.elasticsearch.index.query.QueryBuilders.wildcardQuery;
public class WildcardQuery extends LeafQuery { public class WildcardQuery extends LeafQuery {
private final String field, query; private final String field, query;
private final boolean caseInsensitive;
public WildcardQuery(Source source, String field, String query) { public WildcardQuery(Source source, String field, String query) {
this(source, field, query, false);
}
public WildcardQuery(Source source, String field, String query, boolean caseInsensitive) {
super(source); super(source);
this.field = field; this.field = field;
this.query = query; this.query = query;
this.caseInsensitive = caseInsensitive;
} }
public String field() { public String field() {
@ -30,14 +37,20 @@ public class WildcardQuery extends LeafQuery {
return query; return query;
} }
public Boolean caseInsensitive() {
return caseInsensitive;
}
@Override @Override
public QueryBuilder asBuilder() { public QueryBuilder asBuilder() {
return wildcardQuery(field, query); WildcardQueryBuilder wb = wildcardQuery(field, query);
// ES does not allow case_insensitive to be set to "false", it should be either "true" or not specified
return caseInsensitive == false ? wb : wb.caseInsensitive(caseInsensitive);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(field, query); return Objects.hash(field, query, caseInsensitive);
} }
@Override @Override
@ -52,7 +65,8 @@ public class WildcardQuery extends LeafQuery {
WildcardQuery other = (WildcardQuery) obj; WildcardQuery other = (WildcardQuery) obj;
return Objects.equals(field, other.field) return Objects.equals(field, other.field)
&& Objects.equals(query, other.query); && Objects.equals(query, other.query)
&& Objects.equals(caseInsensitive, other.caseInsensitive);
} }
@Override @Override