Skip to content

Commit 8295038

Browse files
committed
Creating the KQL fulltext function.
1 parent 843cefd commit 8295038

File tree

9 files changed

+226
-0
lines changed

9 files changed

+226
-0
lines changed

docs/reference/esql/functions/description/kql.asciidoc

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/esql/functions/kibana/definition/kql.json

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/esql/functions/kibana/docs/kql.md

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/esql/functions/layout/kql.asciidoc

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/esql/functions/parameters/kql.asciidoc

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/esql/functions/signature/kql.svg

Lines changed: 1 addition & 0 deletions
Loading

docs/reference/esql/functions/types/kql.asciidoc

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.xpack.esql.expression.function.fulltext;
9+
10+
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
11+
import org.elasticsearch.common.io.stream.StreamInput;
12+
import org.elasticsearch.common.io.stream.StreamOutput;
13+
import org.elasticsearch.xpack.esql.core.expression.Expression;
14+
import org.elasticsearch.xpack.esql.core.querydsl.query.KqlQuery;
15+
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
16+
import org.elasticsearch.xpack.esql.core.tree.Source;
17+
import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
18+
import org.elasticsearch.xpack.esql.expression.function.Param;
19+
import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput;
20+
21+
import java.io.IOException;
22+
import java.util.List;
23+
24+
/**
25+
* Full text function that performs a {@link KqlQuery} .
26+
*/
27+
public class Kql extends FullTextFunction {
28+
public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Kql", Kql::new);
29+
30+
@FunctionInfo(
31+
returnType = "boolean",
32+
preview = true,
33+
description = "Performs a KQL query. Returns true if the provided KQL query string matches the row.",
34+
examples = {}
35+
)
36+
public Kql(
37+
Source source,
38+
@Param(name = "query", type = { "keyword", "text" }, description = "Query string in KQL string format.") Expression queryString
39+
) {
40+
super(source, queryString, List.of(queryString));
41+
}
42+
43+
private Kql(StreamInput in) throws IOException {
44+
this(Source.readFrom((PlanStreamInput) in), in.readNamedWriteable(Expression.class));
45+
}
46+
47+
@Override
48+
public void writeTo(StreamOutput out) throws IOException {
49+
source().writeTo(out);
50+
out.writeNamedWriteable(query());
51+
}
52+
53+
@Override
54+
public String getWriteableName() {
55+
return ENTRY.name;
56+
}
57+
58+
@Override
59+
public String functionName() {
60+
return "KQL";
61+
}
62+
63+
@Override
64+
public Expression replaceChildren(List<Expression> newChildren) {
65+
return new Kql(source(), newChildren.get(0));
66+
}
67+
68+
@Override
69+
protected NodeInfo<? extends Expression> info() {
70+
return NodeInfo.create(this, Kql::new, query());
71+
}
72+
73+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.xpack.esql.expression.function.fulltext;
9+
10+
import com.carrotsearch.randomizedtesting.annotations.Name;
11+
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
12+
13+
import org.apache.lucene.util.BytesRef;
14+
import org.elasticsearch.xpack.esql.core.expression.Expression;
15+
import org.elasticsearch.xpack.esql.core.tree.Source;
16+
import org.elasticsearch.xpack.esql.core.type.DataType;
17+
import org.elasticsearch.xpack.esql.expression.function.AbstractFunctionTestCase;
18+
import org.elasticsearch.xpack.esql.expression.function.FunctionName;
19+
import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier;
20+
import org.hamcrest.Matcher;
21+
22+
import java.util.LinkedList;
23+
import java.util.List;
24+
import java.util.function.Supplier;
25+
26+
import static org.hamcrest.Matchers.equalTo;
27+
28+
@FunctionName("kql")
29+
public class KqlTests extends AbstractFunctionTestCase {
30+
31+
public KqlTests(@Name("TestCase") Supplier<TestCaseSupplier.TestCase> testCaseSupplier) {
32+
this.testCase = testCaseSupplier.get();
33+
}
34+
35+
@ParametersFactory
36+
public static Iterable<Object[]> parameters() {
37+
List<TestCaseSupplier> suppliers = new LinkedList<>();
38+
for (DataType strType : DataType.stringTypes()) {
39+
suppliers.add(
40+
new TestCaseSupplier(
41+
"<" + strType + ">",
42+
List.of(strType),
43+
() -> testCase(strType, randomAlphaOfLengthBetween(1, 10), equalTo(true))
44+
)
45+
);
46+
}
47+
List<TestCaseSupplier> errorsSuppliers = errorsForCasesWithoutExamples(suppliers, (v, p) -> "string");
48+
// Don't test null, as it is not allowed but the expected message is not a type error - so we check it separately in VerifierTests
49+
return parameterSuppliersFromTypedData(errorsSuppliers.stream().filter(s -> s.types().contains(DataType.NULL) == false).toList());
50+
}
51+
52+
public final void testFold() {
53+
Expression expression = buildLiteralExpression(testCase);
54+
if (testCase.getExpectedTypeError() != null) {
55+
assertTypeResolutionFailure(expression);
56+
return;
57+
}
58+
assertFalse("expected resolved", expression.typeResolved().unresolved());
59+
}
60+
61+
private static TestCaseSupplier.TestCase testCase(DataType strType, String str, Matcher<Boolean> matcher) {
62+
return new TestCaseSupplier.TestCase(
63+
List.of(new TestCaseSupplier.TypedData(new BytesRef(str), strType, "query")),
64+
"EndsWithEvaluator[str=Attribute[channel=0], suffix=Attribute[channel=1]]",
65+
DataType.BOOLEAN,
66+
matcher
67+
);
68+
}
69+
70+
@Override
71+
protected Expression build(Source source, List<Expression> args) {
72+
return new Kql(source, args.get(0));
73+
}
74+
}

0 commit comments

Comments
 (0)