diff --git a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlParser.java b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlParser.java index 4896f3f15f737..21bcfdbd2a195 100644 --- a/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlParser.java +++ b/x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/parser/EqlParser.java @@ -164,14 +164,14 @@ public void exitFunctionExpression(EqlBaseParser.FunctionExpressionContext conte case "arrayCount": case "arraySearch": throw new ParsingException( - "unsupported function " + functionName, + "Unsupported function [" + functionName + "]", null, token.getLine(), token.getCharPositionInLine()); default: throw new ParsingException( - "unknown function " + functionName, + "Unknown function [" + functionName + "]", null, token.getLine(), token.getCharPositionInLine()); @@ -182,7 +182,7 @@ public void exitFunctionExpression(EqlBaseParser.FunctionExpressionContext conte public void exitJoin(EqlBaseParser.JoinContext context) { Token token = context.JOIN().getSymbol(); throw new ParsingException( - "join is not supported", + "Join is not supported", null, token.getLine(), token.getCharPositionInLine()); @@ -192,7 +192,7 @@ public void exitJoin(EqlBaseParser.JoinContext context) { public void exitPipe(EqlBaseParser.PipeContext context) { Token token = context.PIPE().getSymbol(); throw new ParsingException( - "pipes are not supported", + "Pipes are not supported", null, token.getLine(), token.getCharPositionInLine()); @@ -202,7 +202,7 @@ public void exitPipe(EqlBaseParser.PipeContext context) { public void exitProcessCheck(EqlBaseParser.ProcessCheckContext context) { Token token = context.relationship; throw new ParsingException( - "process relationships are not supported", + "Process relationships are not supported", null, token.getLine(), token.getCharPositionInLine()); @@ -212,7 +212,7 @@ public void exitProcessCheck(EqlBaseParser.ProcessCheckContext context) { public void exitSequence(EqlBaseParser.SequenceContext context) { Token token = context.SEQUENCE().getSymbol(); throw new ParsingException( - "sequence is not supported", + "Sequence is not supported", null, token.getLine(), token.getCharPositionInLine()); @@ -223,7 +223,7 @@ public void exitQualifiedName(EqlBaseParser.QualifiedNameContext context) { if (context.INTEGER_VALUE().size() > 0) { Token firstIndex = context.INTEGER_VALUE(0).getSymbol(); throw new ParsingException( - "array indexes are not supported", + "Array indexes are not supported", null, firstIndex.getLine(), firstIndex.getCharPositionInLine()); diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/action/AbstractEqlIntegTestCase.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/action/AbstractEqlIntegTestCase.java index a7f1cf5099766..2c8ba1acc648b 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/action/AbstractEqlIntegTestCase.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/action/AbstractEqlIntegTestCase.java @@ -17,7 +17,7 @@ import static org.elasticsearch.test.ESIntegTestCase.Scope.SUITE; -@ESIntegTestCase.ClusterScope(scope = SUITE, numDataNodes = 0, numClientNodes = 0, maxNumDataNodes = 0) +@ESIntegTestCase.ClusterScope(scope = SUITE, numDataNodes = 0, numClientNodes = 0, maxNumDataNodes = 0, transportClientRatio = 0) public abstract class AbstractEqlIntegTestCase extends ESIntegTestCase { @Override @@ -37,5 +37,10 @@ protected Settings nodeSettings(int nodeOrdinal) { protected Collection> nodePlugins() { return Collections.singletonList(LocalStateEqlXPackPlugin.class); } + + @Override + protected Collection> transportClientPlugins() { + return nodePlugins(); + } } diff --git a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/VerifierTests.java b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/VerifierTests.java index ac339db8f1e69..951c3803165a5 100644 --- a/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/VerifierTests.java +++ b/x-pack/plugin/eql/src/test/java/org/elasticsearch/xpack/eql/analysis/VerifierTests.java @@ -8,6 +8,7 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.eql.expression.function.EqlFunctionRegistry; import org.elasticsearch.xpack.eql.parser.EqlParser; +import org.elasticsearch.xpack.eql.parser.ParsingException; import org.elasticsearch.xpack.ql.index.EsIndex; import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; @@ -18,8 +19,19 @@ public class VerifierTests extends ESTestCase { + private static final String INDEX_NAME = "test"; + private EqlParser parser = new EqlParser(); - private IndexResolution index = IndexResolution.valid(new EsIndex("test", loadEqlMapping("mapping-default.json"))); + + private IndexResolution index = loadIndexResolution("mapping-default.json"); + + private static Map loadEqlMapping(String name) { + return TypesTests.loadMapping(name); + } + + private IndexResolution loadIndexResolution(String name) { + return IndexResolution.valid(new EsIndex(INDEX_NAME, loadEqlMapping(name))); + } private LogicalPlan accept(IndexResolution resolution, String eql) { PreAnalyzer preAnalyzer = new PreAnalyzer(); @@ -38,7 +50,18 @@ private String error(String sql) { private String error(IndexResolution resolution, String eql) { VerificationException e = expectThrows(VerificationException.class, () -> accept(resolution, eql)); assertTrue(e.getMessage().startsWith("Found ")); - String header = "Found 1 problem\nline "; + final String header = "Found 1 problem\nline "; + return e.getMessage().substring(header.length()); + } + + private String errorParsing(String sql) { + return errorParsing(index, sql); + } + + private String errorParsing(IndexResolution resolution, String eql) { + ParsingException e = expectThrows(ParsingException.class, () -> accept(resolution, eql)); + final String header = "line "; + assertTrue(e.getMessage().startsWith(header)); return e.getMessage().substring(header.length()); } @@ -46,10 +69,15 @@ public void testBasicQuery() { accept("foo where true"); } + public void testQueryStartsWithNumber() { + assertEquals("1:1: no viable alternative at input '42'", errorParsing("42 where true")); + assertEquals("1:1: no viable alternative at input ''42''", errorParsing("'42' where true")); + } + public void testMissingColumn() { assertEquals("1:11: Unknown column [xxx]", error("foo where xxx == 100")); } - + public void testMisspelledColumn() { assertEquals("1:11: Unknown column [md4], did you mean [md5]?", error("foo where md4 == 1")); } @@ -58,8 +86,277 @@ public void testMisspelledColumnWithMultipleOptions() { assertEquals("1:11: Unknown column [pib], did you mean any of [pid, ppid]?", error("foo where pib == 1")); } + public void testPipesUnsupported() { + assertEquals("1:20: Pipes are not supported", errorParsing("process where true | head 6")); + } - private static Map loadEqlMapping(String name) { - return TypesTests.loadMapping(name); + public void testProcessRelationshipsUnsupported() { + assertEquals("2:7: Process relationships are not supported", + errorParsing("process where opcode=1 and process_name == \"csrss.exe\"\n" + + " and descendant of [file where file_name == \"csrss.exe\" and opcode=0]")); + assertEquals("2:7: Process relationships are not supported", + errorParsing("process where process_name=\"svchost.exe\"\n" + + " and child of [file where file_name=\"svchost.exe\" and opcode=0]")); + } + + public void testSequencesUnsupported() { + assertEquals("1:1: Sequence is not supported", errorParsing("sequence\n" + + " [process where serial_event_id = 1]\n" + + " [process where serial_event_id = 2]")); + } + + public void testJoinUnsupported() { + assertEquals("1:1: Join is not supported", errorParsing("join by user_name\n" + + " [process where opcode in (1,3) and process_name=\"smss.exe\"]\n" + + " [process where opcode in (1,3) and process_name == \"python.exe\"]")); + } + + // Some functions fail with "Unsupported" message at the parse stage + public void testArrayFunctionsUnsupported() { + assertEquals("1:16: Unsupported function [arrayContains]", + errorParsing("registry where arrayContains(bytes_written_string_list, 'En')")); + assertEquals("1:16: Unsupported function [arraySearch]", + errorParsing("registry where arraySearch(bytes_written_string_list, a, a == 'en-us')")); + assertEquals("1:16: Unsupported function [arrayCount]", + errorParsing("registry where arrayCount(bytes_written_string_list, s, s == '*-us') == 1")); + } + + // Some functions fail with "Unknown" message at the parse stage + public void testFunctionParsingUnknown() { + assertEquals("1:15: Unknown function [matchLite]", + errorParsing("process where matchLite(?'.*?net1\\s+localgroup\\s+.*?', command_line)")); + assertEquals("1:15: Unknown function [safe]", + errorParsing("network where safe(divide(process_name, process_name))")); + } + + // Test the known EQL functions that are not supported + public void testFunctionVerificationUnknown() { + assertEquals("1:26: Unknown function [substring]", + error("foo where user_domain == substring('abcdfeg', 0, 5)")); + assertEquals("1:25: Unknown function [endsWith]", + error("file where opcode=0 and endsWith(file_name, 'loREr.exe')")); + assertEquals("1:25: Unknown function [startsWith]", + error("file where opcode=0 and startsWith(file_name, 'explORER.EXE')")); + assertEquals("1:25: Unknown function [stringContains]", + error("file where opcode=0 and stringContains('ABCDEFGHIexplorer.exeJKLMNOP', file_name)")); + assertEquals("1:25: Unknown function [indexOf]", + error("file where opcode=0 and indexOf(file_name, 'plore') == 2")); + assertEquals("1:15: Unknown function [add]", + error("process where add(serial_event_id, 0) == 1")); + assertEquals("1:15: Unknown function [subtract]", + error("process where subtract(serial_event_id, -5) == 6")); + assertEquals("1:15: Unknown function [multiply]", + error("process where multiply(6, serial_event_id) == 30")); + assertEquals("1:15: Unknown function [divide]", + error("process where divide(30, 4.0) == 7.5")); + assertEquals("1:34: Unknown function [number]", + error("process where serial_event_id == number('5')")); + assertEquals("1:15: Unknown function [concat]", + error("process where concat(serial_event_id, ':', process_name, opcode) == '5:winINIT.exe3'")); + assertEquals("1:15: Unknown function [between]", + error("process where between(process_name, \"s\", \"e\") == \"yst\"")); + assertEquals("1:15: Unknown function [cidrMatch]", + error("network where cidrMatch(source_address, \"192.168.0.0/16\", \"10.6.48.157/8\")")); + assertEquals("1:22: Unknown function [between]", + error("process where length(between(process_name, 'g', 'e')) > 0")); + } + + // Test unsupported array indexes + public void testArrayIndexesUnsupported() { + assertEquals("1:84: Array indexes are not supported", + errorParsing("registry where length(bytes_written_string_list) > 0 and bytes_written_string_list[0] == 'EN-us")); + } + + // Test valid/supported queries + public void testQueryOk() { + // Mismatched type, still ok + accept("process where serial_event_id = 'abcdef'"); + + // Equals condition + accept("process where serial_event_id = 1"); + + // Less then condition + accept("process where serial_event_id < 4"); + + // Greater than + accept("process where exit_code > -1"); + accept("process where -1 < exit_code"); + + // Or and And/And Not + accept("process where process_name == \"impossible name\" or (serial_event_id < 4.5 and serial_event_id >= 3.1)"); + accept("process where (serial_event_id<=8 and not serial_event_id > 7) and (opcode=3 and opcode>2)"); + + // In statement + accept("process where not (exit_code > -1)\n" + + " and serial_event_id in (58, 64, 69, 74, 80, 85, 90, 93, 94)"); + + // Combination + accept("file where serial_event_id == 82 and (true == (process_name in ('svchost.EXE', 'bad.exe', 'bad2.exe')))"); + + // String handling + accept("process where process_path == \"*\\\\MACHINE\\\\SAM\\\\SAM\\\\*\\\\Account\\\\Us*ers\\\\00*03E9\\\\F\""); + + // Arithmetic operators + accept("file where serial_event_id - 1 == 81"); + accept("file where serial_event_id + 1 == 83"); + accept("file where serial_event_id * 2 == 164"); + accept("file where serial_event_id / 2 == 41"); + accept("file where serial_event_id % 40 == 2"); + } + + // Test mapping that doesn't have property event_type defined + public void testMissingEventType() { + final IndexResolution idxr = loadIndexResolution("mapping-missing-event-type.json"); + assertEquals("1:1: Unknown column [event_type]", error(idxr, "foo where true")); + } + + public void testAliasErrors() { + final IndexResolution idxr = loadIndexResolution("mapping-alias.json"); + + // Check unsupported + assertEquals("1:11: Cannot use field [user_name_alias] with unsupported type [alias]", + error(idxr, "foo where user_name_alias == 'bob'")); + + // Check alias name typo + assertEquals("1:11: Unknown column [user_name_alia], did you mean any of [user_name, user_domain]?", + error(idxr, "foo where user_name_alia == 'bob'")); + } + + // Test all elasticsearch numeric field types + public void testNumeric() { + final IndexResolution idxr = loadIndexResolution("mapping-numeric.json"); + accept(idxr, "foo where long_field == 0"); + accept(idxr, "foo where integer_field == 0"); + accept(idxr, "foo where short_field == 0"); + accept(idxr, "foo where byte_field == 0"); + accept(idxr, "foo where double_field == 0"); + accept(idxr, "foo where float_field == 0"); + accept(idxr, "foo where half_float_field == 0"); + accept(idxr, "foo where scaled_float_field == 0"); + + // Test query against unsupported field type int + assertEquals("1:11: Cannot use field [wrong_int_type_field] with unsupported type [int]", + error(idxr, "foo where wrong_int_type_field == 0")); + } + + public void testNoDoc() { + final IndexResolution idxr = loadIndexResolution("mapping-nodoc.json"); + accept(idxr, "foo where description_nodoc == ''"); + // TODO: add sort test on nodoc field once we have pipes support + } + + public void testDate() { + final IndexResolution idxr = loadIndexResolution("mapping-date.json"); + accept(idxr, "foo where date == ''"); + accept(idxr, "foo where date == '2020-02-02'"); + accept(idxr, "foo where date == '2020-02-41'"); + accept(idxr, "foo where date == '20200241'"); + + accept(idxr, "foo where date_with_format == ''"); + accept(idxr, "foo where date_with_format == '2020-02-02'"); + accept(idxr, "foo where date_with_format == '2020-02-41'"); + accept(idxr, "foo where date_with_format == '20200241'"); + + accept(idxr, "foo where date_with_multi_format == ''"); + accept(idxr, "foo where date_with_multi_format == '2020-02-02'"); + accept(idxr, "foo where date_with_multi_format == '2020-02-41'"); + accept(idxr, "foo where date_with_multi_format == '20200241'"); + accept(idxr, "foo where date_with_multi_format == '11:12:13'"); + + // Test query against unsupported field type date_nanos + assertEquals("1:11: Cannot use field [date_nanos_field] with unsupported type [date_nanos]", + error(idxr, "foo where date_nanos_field == ''")); + } + + public void testBoolean() { + final IndexResolution idxr = loadIndexResolution("mapping-boolean.json"); + accept(idxr, "foo where boolean_field == true"); + accept(idxr, "foo where boolean_field == 'bar'"); + accept(idxr, "foo where boolean_field == 0"); + accept(idxr, "foo where boolean_field == 123456"); + } + + public void testBinary() { + final IndexResolution idxr = loadIndexResolution("mapping-binary.json"); + accept(idxr, "foo where blob == ''"); + accept(idxr, "foo where blob == 'bar'"); + accept(idxr, "foo where blob == 0"); + accept(idxr, "foo where blob == 123456"); + } + + public void testRange() { + final IndexResolution idxr = loadIndexResolution("mapping-range.json"); + assertEquals("1:11: Cannot use field [integer_range_field] with unsupported type [integer_range]", + error(idxr, "foo where integer_range_field == ''")); + assertEquals("1:11: Cannot use field [float_range_field] with unsupported type [float_range]", + error(idxr, "foo where float_range_field == ''")); + assertEquals("1:11: Cannot use field [long_range_field] with unsupported type [long_range]", + error(idxr, "foo where long_range_field == ''")); + assertEquals("1:11: Cannot use field [double_range_field] with unsupported type [double_range]", + error(idxr, "foo where double_range_field == ''")); + assertEquals("1:11: Cannot use field [date_range_field] with unsupported type [date_range]", + error(idxr, "foo where date_range_field == ''")); + assertEquals("1:11: Cannot use field [ip_range_field] with unsupported type [ip_range]", + error(idxr, "foo where ip_range_field == ''")); + } + + public void testObject() { + final IndexResolution idxr = loadIndexResolution("mapping-object.json"); + accept(idxr, "foo where endgame.pid == 0"); + + assertEquals("1:11: Unknown column [endgame.pi], did you mean [endgame.pid]?", + error(idxr, "foo where endgame.pi == 0")); + } + + public void testNested() { + final IndexResolution idxr = loadIndexResolution("mapping-nested.json"); + accept(idxr, "foo where processes.pid == 0"); + + assertEquals("1:11: Unknown column [processe.pid], did you mean any of [processes.pid, processes.path, processes.path.keyword]?", + error(idxr, "foo where processe.pid == 0")); + } + + public void testGeo() { + final IndexResolution idxr = loadIndexResolution("mapping-geo.json"); + assertEquals("1:11: Cannot use field [location] with unsupported type [geo_point]", + error(idxr, "foo where location == 0")); + assertEquals("1:11: Cannot use field [site] with unsupported type [geo_shape]", + error(idxr, "foo where site == 0")); + } + + public void testIP() { + final IndexResolution idxr = loadIndexResolution("mapping-ip.json"); + accept(idxr, "foo where ip_addr == 0"); + } + + public void testJoin() { + final IndexResolution idxr = loadIndexResolution("mapping-join.json"); + accept(idxr, "foo where serial_event_id == 0"); + } + + public void testMultiField() { + final IndexResolution idxr = loadIndexResolution("mapping-multi-field.json"); + accept(idxr, "foo where multi_field.raw == 'bar'"); + + assertEquals("1:11: [multi_field.english == 'bar'] cannot operate on first argument field of data type [text]: " + + "No keyword/multi-field defined exact matches for [english]; define one or use MATCH/QUERY instead", + error(idxr, "foo where multi_field.english == 'bar'")); + + accept(idxr, "foo where multi_field_options.raw == 'bar'"); + accept(idxr, "foo where multi_field_options.key == 'bar'"); + + accept(idxr, "foo where multi_field_ambiguous.one == 'bar'"); + accept(idxr, "foo where multi_field_ambiguous.two == 'bar'"); + assertEquals("1:11: [multi_field_ambiguous.normalized == 'bar'] cannot operate on first argument field of data type [keyword]: " + + "Normalized keyword field cannot be used for exact match operations", + error(idxr, "foo where multi_field_ambiguous.normalized == 'bar'")); + + assertEquals("1:11: [multi_field_nested.dep_name == 'bar'] cannot operate on first argument field of data type [text]: " + + "No keyword/multi-field defined exact matches for [dep_name]; define one or use MATCH/QUERY instead", + error(idxr, "foo where multi_field_nested.dep_name == 'bar'")); + + accept(idxr, "foo where multi_field_nested.dep_id.keyword == 'bar'"); + accept(idxr, "foo where multi_field_nested.end_date == ''"); + accept(idxr, "foo where multi_field_nested.start_date == 'bar'"); } -} +} \ No newline at end of file diff --git a/x-pack/plugin/eql/src/test/resources/mapping-alias.json b/x-pack/plugin/eql/src/test/resources/mapping-alias.json new file mode 100644 index 0000000000000..e9dc557cb1777 --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-alias.json @@ -0,0 +1,17 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "user_name" : { + "type" : "keyword" + }, + "user_domain" : { + "type" : "keyword" + }, + "user_name_alias": { + "type": "alias", + "path": "user_name" + } + } +} \ No newline at end of file diff --git a/x-pack/plugin/eql/src/test/resources/mapping-binary.json b/x-pack/plugin/eql/src/test/resources/mapping-binary.json new file mode 100644 index 0000000000000..eae2014d56efb --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-binary.json @@ -0,0 +1,10 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "blob" : { + "type" : "binary" + } + } +} diff --git a/x-pack/plugin/eql/src/test/resources/mapping-boolean.json b/x-pack/plugin/eql/src/test/resources/mapping-boolean.json new file mode 100644 index 0000000000000..aa337964887ec --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-boolean.json @@ -0,0 +1,10 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "boolean_field" : { + "type" : "boolean" + } + } +} diff --git a/x-pack/plugin/eql/src/test/resources/mapping-date.json b/x-pack/plugin/eql/src/test/resources/mapping-date.json new file mode 100644 index 0000000000000..a1c1e0fb31627 --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-date.json @@ -0,0 +1,21 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "date" : { + "type" : "date" + }, + "date_with_format" : { + "type" : "date", + "format" : "yyyy-MM-dd" + }, + "date_with_multi_format" : { + "type" : "date", + "format" : "yyyy-MM-dd || basic_time || year" + }, + "date_nanos_field" : { + "type" : "date_nanos" + } + } +} diff --git a/x-pack/plugin/eql/src/test/resources/mapping-default.json b/x-pack/plugin/eql/src/test/resources/mapping-default.json index 2c87024f7f09a..54a55af5a2c0f 100644 --- a/x-pack/plugin/eql/src/test/resources/mapping-default.json +++ b/x-pack/plugin/eql/src/test/resources/mapping-default.json @@ -50,6 +50,27 @@ "ignore_above" : 256 } } + }, + "opcode" : { + "type" : "long" + }, + "file_name" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "serial_event_id" : { + "type" : "long" + }, + "source_address" : { + "type" : "ip" + }, + "exit_code" : { + "type" : "long" } } } \ No newline at end of file diff --git a/x-pack/plugin/eql/src/test/resources/mapping-geo.json b/x-pack/plugin/eql/src/test/resources/mapping-geo.json new file mode 100644 index 0000000000000..7103640986aaa --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-geo.json @@ -0,0 +1,13 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "location" : { + "type" : "geo_point" + }, + "site": { + "type" : "geo_shape" + } + } +} diff --git a/x-pack/plugin/eql/src/test/resources/mapping-ip.json b/x-pack/plugin/eql/src/test/resources/mapping-ip.json new file mode 100644 index 0000000000000..3af26c4a30663 --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-ip.json @@ -0,0 +1,10 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "ip_addr" : { + "type" : "ip" + } + } +} diff --git a/x-pack/plugin/eql/src/test/resources/mapping-join.json b/x-pack/plugin/eql/src/test/resources/mapping-join.json new file mode 100644 index 0000000000000..700024490d333 --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-join.json @@ -0,0 +1,16 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "serial_event_id" : { + "type" : "long" + }, + "parent_child" : { + "type" : "join", + "relations" : { + "question" : "answer" + } + } + } +} diff --git a/x-pack/plugin/eql/src/test/resources/mapping-missing-event-type.json b/x-pack/plugin/eql/src/test/resources/mapping-missing-event-type.json new file mode 100644 index 0000000000000..f2bbf168c9cfd --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-missing-event-type.json @@ -0,0 +1,7 @@ +{ + "properties" : { + "long_field" : { + "type" : "long" + } + } +} \ No newline at end of file diff --git a/x-pack/plugin/eql/src/test/resources/mapping-multi-field.json b/x-pack/plugin/eql/src/test/resources/mapping-multi-field.json new file mode 100644 index 0000000000000..5222d8d12b112 --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-multi-field.json @@ -0,0 +1,68 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "multi_field" : { + "type" : "text", + "fields" : { + "raw" : { + "type" : "keyword" + }, + "english" : { + "type" : "text", + "analyzer" : "english" + } + } + }, + "multi_field_options" : { + "type" : "text", + "fields" : { + "raw" : { + "type" : "keyword" + }, + "key" : { + "type" : "keyword" + } + } + }, + "multi_field_ambiguous" : { + "type" : "text", + "fields" : { + "one" : { + "type" : "keyword" + }, + "two" : { + "type" : "keyword" + }, + "normalized" : { + "type" : "keyword", + "normalizer" : "some_normalizer" + } + } + }, + "multi_field_nested" : { + "type" : "nested", + "properties" : { + "dep_name" : { + "type" : "text" + }, + "dep_id" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "end_date" : { + "type" : "date" + }, + "start_date" : { + "type" : "date" + } + } + } + } +} diff --git a/x-pack/plugin/eql/src/test/resources/mapping-nested.json b/x-pack/plugin/eql/src/test/resources/mapping-nested.json new file mode 100644 index 0000000000000..8279a9331586e --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-nested.json @@ -0,0 +1,23 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "processes" : { + "type" : "nested", + "properties" : { + "pid" : { + "type" : "long" + }, + "path" : { + "type" : "text", + "fields" : { + "keyword" : { + "type" : "keyword" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/x-pack/plugin/eql/src/test/resources/mapping-nodoc.json b/x-pack/plugin/eql/src/test/resources/mapping-nodoc.json new file mode 100644 index 0000000000000..2f4f53443ac30 --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-nodoc.json @@ -0,0 +1,11 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "description_nodoc" : { + "type" : "integer", + "doc_values" : false + } + } +} diff --git a/x-pack/plugin/eql/src/test/resources/mapping-numeric.json b/x-pack/plugin/eql/src/test/resources/mapping-numeric.json new file mode 100644 index 0000000000000..4995378681d26 --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-numeric.json @@ -0,0 +1,34 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "long_field" : { + "type" : "long" + }, + "integer_field" : { + "type" : "integer" + }, + "short_field" : { + "type" : "short" + }, + "byte_field": { + "type" : "byte" + }, + "double_field": { + "type" : "double" + }, + "float_field" : { + "type" : "float" + }, + "half_float_field" : { + "type" : "half_float" + }, + "scaled_float_field": { + "type" : "scaled_float" + }, + "wrong_int_type_field": { + "type" : "int" + } + } +} \ No newline at end of file diff --git a/x-pack/plugin/eql/src/test/resources/mapping-object.json b/x-pack/plugin/eql/src/test/resources/mapping-object.json new file mode 100644 index 0000000000000..93f001dd137bc --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-object.json @@ -0,0 +1,17 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "endgame" : { + "properties" : { + "pid" : { + "type" : "long" + }, + "user_name" : { + "type" : "keyword" + } + } + } + } +} diff --git a/x-pack/plugin/eql/src/test/resources/mapping-range.json b/x-pack/plugin/eql/src/test/resources/mapping-range.json new file mode 100644 index 0000000000000..db61ebbd89938 --- /dev/null +++ b/x-pack/plugin/eql/src/test/resources/mapping-range.json @@ -0,0 +1,25 @@ +{ + "properties" : { + "event_type" : { + "type" : "keyword" + }, + "integer_range_field" : { + "type" : "integer_range" + }, + "float_range_field" : { + "type" : "float_range" + }, + "long_range_field" : { + "type" : "long_range" + }, + "double_range_field" : { + "type" : "double_range" + }, + "date_range_field" : { + "type" : "date_range" + }, + "ip_range_field" : { + "type" : "ip_range" + } + } +} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolution.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolution.java index 9822c9633b7e8..2339124249a72 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolution.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolution.java @@ -38,7 +38,7 @@ public boolean matches(String index) { /** * Get the {@linkplain EsIndex} - * @throws MappingException if the index is invalid for use with sql + * @throws MappingException if the index is invalid for use with ql */ public EsIndex get() { if (invalid != null) { @@ -48,7 +48,7 @@ public EsIndex get() { } /** - * Is the index valid for use with sql? Returns {@code false} if the + * Is the index valid for use with ql? Returns {@code false} if the * index wasn't found. */ public boolean isValid() {