Skip to content

Commit

Permalink
Merge pull request #242 from elastic/main
Browse files Browse the repository at this point in the history
🤖 ESQL: Merge upstream
  • Loading branch information
elasticsearchmachine committed Sep 15, 2022
2 parents 2dfac44 + f5d61fb commit 04eaa49
Show file tree
Hide file tree
Showing 58 changed files with 1,651 additions and 173 deletions.
5 changes: 5 additions & 0 deletions docs/changelog/89895.yaml
@@ -0,0 +1,5 @@
pr: 89895
summary: Initial code to support binary expression scripts
area: "Infra/Scripting"
type: enhancement
issues: []
5 changes: 5 additions & 0 deletions docs/changelog/90017.yaml
@@ -0,0 +1,5 @@
pr: 90017
summary: Fix Fields API Caching Regression
area: Infra/Scripting
type: regression
issues: []
5 changes: 5 additions & 0 deletions docs/changelog/90035.yaml
@@ -0,0 +1,5 @@
pr: 90035
summary: Add a TSID global ordinal to `TimeSeriesIndexSearcher`
area: TSDB
type: feature
issues: []
3 changes: 3 additions & 0 deletions docs/reference/health/health.asciidoc
Expand Up @@ -273,6 +273,9 @@ details have contents and a structure that is unique to each indicator.
`node_id`::
(string) The node id of a master-eligible node
`name`::
(Optional, string) The node name of a master-eligible node
`cluster_formation_message`::
(string) A detailed description explaining what went wrong with cluster formation, or why this node was
unable to join the cluster if it has formed.
Expand Down
Expand Up @@ -53,6 +53,11 @@ Name of the repository to delete a snapshot from.
(Required, string)
Comma-separated list of snapshot names to delete. Also accepts wildcards (`*`).

[[delete-snapshot-api-query-params]]
==== {api-query-parms-title}

include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=master-timeout]

[[delete-snapshot-api-example]]
==== {api-example-title}

Expand Down
@@ -0,0 +1,88 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.script.expression;

import org.apache.lucene.expressions.Bindings;
import org.apache.lucene.expressions.Expression;
import org.apache.lucene.search.DoubleValues;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.Rescorer;
import org.apache.lucene.search.SortField;
import org.elasticsearch.script.DoubleValuesScript;

import java.util.function.Function;

/**
* A factory for a custom compiled {@link Expression} scripts
* <p>
* Instead of an execution result, we return a wrapper to an {@link Expression} object, which
* can be used for all supported double values operations.
*/
public class ExpressionDoubleValuesScript implements DoubleValuesScript.Factory {
private final Expression exprScript;

ExpressionDoubleValuesScript(Expression e) {
this.exprScript = e;
}

@Override
public DoubleValuesScript newInstance() {
return new DoubleValuesScript() {
@Override
public double execute() {
return exprScript.evaluate(new DoubleValues[0]);
}

@Override
public double evaluate(DoubleValues[] functionValues) {
return exprScript.evaluate(functionValues);
}

@Override
public DoubleValuesSource getDoubleValuesSource(Function<String, DoubleValuesSource> sourceProvider) {
return exprScript.getDoubleValuesSource(new Bindings() {
@Override
public DoubleValuesSource getDoubleValuesSource(String name) {
return sourceProvider.apply(name);
}
});
}

@Override
public SortField getSortField(Function<String, DoubleValuesSource> sourceProvider, boolean reverse) {
return exprScript.getSortField(new Bindings() {
@Override
public DoubleValuesSource getDoubleValuesSource(String name) {
return sourceProvider.apply(name);
}
}, reverse);
}

@Override
public Rescorer getRescorer(Function<String, DoubleValuesSource> sourceProvider) {
return exprScript.getRescorer(new Bindings() {
@Override
public DoubleValuesSource getDoubleValuesSource(String name) {
return sourceProvider.apply(name);
}
});
}

@Override
public String sourceText() {
return exprScript.sourceText;
}

@Override
public String[] variables() {
return exprScript.variables;
}
};
}
}
Expand Up @@ -24,6 +24,7 @@
import org.elasticsearch.script.BucketAggregationScript;
import org.elasticsearch.script.BucketAggregationSelectorScript;
import org.elasticsearch.script.ClassPermission;
import org.elasticsearch.script.DoubleValuesScript;
import org.elasticsearch.script.FieldScript;
import org.elasticsearch.script.FilterScript;
import org.elasticsearch.script.NumberSortScript;
Expand Down Expand Up @@ -132,6 +133,14 @@ public FieldScript.LeafFactory newFactory(Map<String, Object> params, SearchLook
return newFieldScript(expr, lookup, params);
}

@Override
public boolean isResultDeterministic() {
return true;
}
},

DoubleValuesScript.CONTEXT,
(Expression expr) -> new ExpressionDoubleValuesScript(expr) {
@Override
public boolean isResultDeterministic() {
return true;
Expand Down
@@ -0,0 +1,87 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.script.expression;

import org.apache.lucene.expressions.SimpleBindings;
import org.apache.lucene.search.DoubleValues;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.SortField;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.script.DoubleValuesScript;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptException;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.test.ESTestCase;

import java.io.IOException;
import java.text.ParseException;
import java.util.Collections;
import java.util.Map;

/**
* Tests {@link ExpressionDoubleValuesScript} through the {@link ScriptService}
*/
public class ExpressionDoubleValuesScriptTests extends ESTestCase {
private ExpressionScriptEngine engine;
private ScriptService scriptService;

@Override
public void setUp() throws Exception {
super.setUp();

engine = new ExpressionScriptEngine();
scriptService = new ScriptService(Settings.EMPTY, Map.of("expression", engine), ScriptModule.CORE_CONTEXTS, () -> 1L);
}

@SuppressWarnings("unchecked")
private DoubleValuesScript compile(String expression) {
var script = new Script(ScriptType.INLINE, "expression", expression, Collections.emptyMap());
return scriptService.compile(script, DoubleValuesScript.CONTEXT).newInstance();
}

public void testCompileError() {
ScriptException e = expectThrows(ScriptException.class, () -> compile("10 * log(10)"));
assertTrue(e.getCause() instanceof ParseException);
assertEquals("Invalid expression '10 * log(10)': Unrecognized function call (log).", e.getCause().getMessage());
}

public void testEvaluate() {
var expression = compile("10 * log10(10)");
assertEquals("10 * log10(10)", expression.sourceText());
assertEquals(10.0, expression.evaluate(new DoubleValues[0]), 0.00001);
assertEquals(10.0, expression.execute(), 0.00001);

expression = compile("20 * log10(a)");
assertEquals("20 * log10(a)", expression.sourceText());
assertEquals(20.0, expression.evaluate(new DoubleValues[] { DoubleValues.withDefault(DoubleValues.EMPTY, 10.0) }), 0.00001);
}

public void testDoubleValuesSource() throws IOException {
SimpleBindings bindings = new SimpleBindings();
bindings.add("popularity", DoubleValuesSource.constant(5));

var expression = compile("10 * log10(popularity)");
var doubleValues = expression.getDoubleValuesSource((name) -> bindings.getDoubleValuesSource(name));
assertEquals("expr(10 * log10(popularity))", doubleValues.toString());
var values = doubleValues.getValues(null, null);
assertTrue(values.advanceExact(0));
assertEquals(6, (int) values.doubleValue());

var sortField = expression.getSortField((name) -> bindings.getDoubleValuesSource(name), false);
assertEquals("expr(10 * log10(popularity))", sortField.getField());
assertEquals(SortField.Type.CUSTOM, sortField.getType());
assertFalse(sortField.getReverse());

var rescorer = expression.getRescorer((name) -> bindings.getDoubleValuesSource(name));
assertNotNull(rescorer);
}

}

0 comments on commit 04eaa49

Please sign in to comment.