From 81ec22aa17153a1812d1d6840013d626f98db155 Mon Sep 17 00:00:00 2001 From: Stuart Tettemer Date: Fri, 6 Dec 2019 13:09:44 -0700 Subject: [PATCH] Scripting: Groundwork for caching script results (#49895) In order to cache script results in the query shard cache, we need to check if scripts are deterministic. This change adds a default method to the script factories, `isResultDeterministic() -> false` which is used by the `QueryShardContext`. Script results were never cached and that does not change here. Future changes will implement this method based on whether the results of the scripts are deterministic or not and therefore cacheable. Refs: #49466 --- .../common/AnalysisPredicateScript.java | 3 +- .../PredicateTokenScriptFilterTests.java | 3 +- .../ScriptedConditionTokenFilterTests.java | 3 +- .../expression/ExpressionScriptEngine.java | 8 ++- .../script/mustache/MustacheScriptEngine.java | 8 ++- .../painless/PainlessScriptEngine.java | 27 +++++++--- .../action/PainlessExecuteAction.java | 3 +- .../painless/BaseClassTests.java | 53 ++++++++++--------- .../painless/BasicStatementTests.java | 3 +- .../elasticsearch/painless/BindingsTests.java | 3 +- .../elasticsearch/painless/FactoryTests.java | 7 +-- .../expertscript/ExpertScriptPlugin.java | 47 ++++++++++++---- .../index/query/InnerHitContextBuilder.java | 2 +- .../index/query/IntervalFilterScript.java | 3 +- .../index/query/IntervalsSourceProvider.java | 2 +- .../index/query/QueryShardContext.java | 14 +++-- .../index/query/ScriptQueryBuilder.java | 2 +- .../index/query/TermsSetQueryBuilder.java | 4 +- .../ScriptScoreFunctionBuilder.java | 2 +- .../ScriptScoreQueryBuilder.java | 2 +- .../script/AggregationScript.java | 2 +- .../script/BucketAggregationScript.java | 2 +- .../BucketAggregationSelectorScript.java | 2 +- .../org/elasticsearch/script/FieldScript.java | 2 +- .../elasticsearch/script/FilterScript.java | 2 +- .../script/IngestConditionalScript.java | 2 +- .../elasticsearch/script/IngestScript.java | 2 +- .../script/NumberSortScript.java | 2 +- .../org/elasticsearch/script/ScoreScript.java | 2 +- .../elasticsearch/script/ScriptContext.java | 2 +- .../elasticsearch/script/ScriptEngine.java | 7 ++- .../elasticsearch/script/ScriptFactory.java | 28 ++++++++++ .../elasticsearch/script/ScriptService.java | 2 +- .../script/ScriptedMetricAggContexts.java | 8 +-- .../SignificantTermsHeuristicScoreScript.java | 2 +- .../script/SimilarityScript.java | 4 +- .../script/SimilarityWeightScript.java | 2 +- .../script/StringSortScript.java | 2 +- .../elasticsearch/script/TemplateScript.java | 2 +- .../script/TermsSetQueryScript.java | 2 +- .../elasticsearch/script/UpdateScript.java | 2 +- .../heuristics/ScriptHeuristic.java | 2 +- .../ScriptedMetricAggregationBuilder.java | 6 +-- .../metrics/TopHitsAggregationBuilder.java | 2 +- .../pipeline/MovingFunctionScript.java | 3 +- .../support/ValuesSourceConfig.java | 2 +- .../search/sort/ScriptSortBuilder.java | 4 +- .../phrase/PhraseSuggestionBuilder.java | 2 +- .../query/IntervalQueryBuilderTests.java | 3 +- .../script/ScriptContextTests.java | 12 ++--- .../script/ScriptLanguagesInfoTests.java | 2 +- .../functionscore/ExplainableScriptIT.java | 8 ++- .../search/suggest/SuggestSearchIT.java | 8 ++- .../ingest/TestTemplateService.java | 3 +- .../script/MockScriptEngine.java | 2 +- .../script/MockMustacheScriptEngine.java | 2 +- .../test/MockPainlessScriptEngine.java | 3 +- .../condition/WatcherConditionScript.java | 3 +- .../script/WatcherTransformScript.java | 3 +- 59 files changed, 236 insertions(+), 114 deletions(-) create mode 100644 server/src/main/java/org/elasticsearch/script/ScriptFactory.java diff --git a/modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/AnalysisPredicateScript.java b/modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/AnalysisPredicateScript.java index 5d8c491efc585..f14bd9ded9cc1 100644 --- a/modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/AnalysisPredicateScript.java +++ b/modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/AnalysisPredicateScript.java @@ -27,6 +27,7 @@ import org.apache.lucene.analysis.tokenattributes.TypeAttribute; import org.apache.lucene.util.AttributeSource; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; /** * A predicate based on the current token in a TokenStream @@ -107,7 +108,7 @@ public boolean isKeyword() { */ public abstract boolean execute(Token token); - public interface Factory { + public interface Factory extends ScriptFactory { AnalysisPredicateScript newInstance(); } diff --git a/modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/PredicateTokenScriptFilterTests.java b/modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/PredicateTokenScriptFilterTests.java index 84ba5e5d3373c..9e61a59237348 100644 --- a/modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/PredicateTokenScriptFilterTests.java +++ b/modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/PredicateTokenScriptFilterTests.java @@ -30,6 +30,7 @@ import org.elasticsearch.indices.analysis.AnalysisModule; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.script.ScriptService; import org.elasticsearch.test.ESTokenStreamTestCase; import org.elasticsearch.test.IndexSettingsModule; @@ -63,7 +64,7 @@ public boolean execute(Token token) { @SuppressWarnings("unchecked") ScriptService scriptService = new ScriptService(indexSettings, Collections.emptyMap(), Collections.emptyMap()){ @Override - public FactoryType compile(Script script, ScriptContext context) { + public FactoryType compile(Script script, ScriptContext context) { assertEquals(context, AnalysisPredicateScript.CONTEXT); assertEquals(new Script("my_script"), script); return (FactoryType) factory; diff --git a/modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/ScriptedConditionTokenFilterTests.java b/modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/ScriptedConditionTokenFilterTests.java index 58226ac169bc3..d2bbc780c8747 100644 --- a/modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/ScriptedConditionTokenFilterTests.java +++ b/modules/analysis-common/src/test/java/org/elasticsearch/analysis/common/ScriptedConditionTokenFilterTests.java @@ -30,6 +30,7 @@ import org.elasticsearch.indices.analysis.AnalysisModule; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.script.ScriptService; import org.elasticsearch.test.ESTokenStreamTestCase; import org.elasticsearch.test.IndexSettingsModule; @@ -63,7 +64,7 @@ public boolean execute(Token token) { @SuppressWarnings("unchecked") ScriptService scriptService = new ScriptService(indexSettings, Collections.emptyMap(), Collections.emptyMap()){ @Override - public FactoryType compile(Script script, ScriptContext context) { + public FactoryType compile(Script script, ScriptContext context) { assertEquals(context, AnalysisPredicateScript.CONTEXT); assertEquals(new Script("token.getPosition() > 1"), script); return (FactoryType) factory; diff --git a/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java b/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java index 78b14e563e19d..7c4a77a791d42 100644 --- a/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java +++ b/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java @@ -44,6 +44,7 @@ import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptEngine; import org.elasticsearch.script.ScriptException; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.script.TermsSetQueryScript; import org.elasticsearch.search.lookup.SearchLookup; @@ -113,7 +114,12 @@ public String getType() { } @Override - public T compile(String scriptName, String scriptSource, ScriptContext context, Map params) { + public T compile( + String scriptName, + String scriptSource, + ScriptContext context, + Map params + ) { // classloader created here final SecurityManager sm = System.getSecurityManager(); SpecialPermission.check(); diff --git a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustacheScriptEngine.java b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustacheScriptEngine.java index bd02f22afa678..cb02311edbf1c 100644 --- a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustacheScriptEngine.java +++ b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustacheScriptEngine.java @@ -32,6 +32,7 @@ import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptEngine; import org.elasticsearch.script.ScriptException; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.script.TemplateScript; import java.io.Reader; @@ -64,7 +65,12 @@ public final class MustacheScriptEngine implements ScriptEngine { * @return a compiled template object for later execution. * */ @Override - public T compile(String templateName, String templateSource, ScriptContext context, Map options) { + public T compile( + String templateName, + String templateSource, + ScriptContext context, + Map options + ) { if (context.instanceClazz.equals(TemplateScript.class) == false) { throw new IllegalArgumentException("mustache engine does not know how to handle context [" + context.name + "]"); } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java index 3bcc44e620afa..e8ca7be373da4 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngine.java @@ -28,6 +28,7 @@ import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptEngine; import org.elasticsearch.script.ScriptException; +import org.elasticsearch.script.ScriptFactory; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; @@ -66,7 +67,7 @@ public final class PainlessScriptEngine implements ScriptEngine { */ private static final AccessControlContext COMPILATION_CONTEXT; - /** + /* * Setup the allowed permissions. */ static { @@ -122,7 +123,12 @@ public String getType() { } @Override - public T compile(String scriptName, String scriptSource, ScriptContext context, Map params) { + public T compile( + String scriptName, + String scriptSource, + ScriptContext context, + Map params + ) { Compiler compiler = contextsToCompilers.get(context); // Check we ourselves are not being called by unprivileged code. @@ -162,12 +168,16 @@ public Set> getSupportedContexts() { * @param The factory class. * @return A factory class that will return script instances. */ - private Type generateStatefulFactory(Loader loader, ScriptContext context, Set extractedVariables) { + private Type generateStatefulFactory( + Loader loader, + ScriptContext context, + Set extractedVariables + ) { int classFrames = ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS; int classAccess = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL; String interfaceBase = Type.getType(context.statefulFactoryClazz).getInternalName(); String className = interfaceBase + "$StatefulFactory"; - String classInterfaces[] = new String[] { interfaceBase }; + String[] classInterfaces = new String[] { interfaceBase }; ClassWriter writer = new ClassWriter(classFrames); writer.visit(WriterConstants.CLASS_VERSION, classAccess, className, null, OBJECT_TYPE.getInternalName(), classInterfaces); @@ -263,12 +273,17 @@ private Type generateStatefulFactory(Loader loader, ScriptContext context * @param The factory class. * @return A factory class that will return script instances. */ - private T generateFactory(Loader loader, ScriptContext context, Set extractedVariables, Type classType) { + private T generateFactory( + Loader loader, + ScriptContext context, + Set extractedVariables, + Type classType + ) { int classFrames = ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS; int classAccess = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER| Opcodes.ACC_FINAL; String interfaceBase = Type.getType(context.factoryClazz).getInternalName(); String className = interfaceBase + "$Factory"; - String classInterfaces[] = new String[] { interfaceBase }; + String[] classInterfaces = new String[] { interfaceBase }; ClassWriter writer = new ClassWriter(classFrames); writer.visit(WriterConstants.CLASS_VERSION, classAccess, className, null, OBJECT_TYPE.getInternalName(), classInterfaces); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java index a1825d2d4093e..7f0bd27e8c708 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/action/PainlessExecuteAction.java @@ -76,6 +76,7 @@ import org.elasticsearch.script.ScoreScript; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptType; import org.elasticsearch.threadpool.ThreadPool; @@ -434,7 +435,7 @@ public Map getParams() { public abstract Object execute(); - public interface Factory { + public interface Factory extends ScriptFactory { PainlessTestScript newInstance(Map params); diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BaseClassTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BaseClassTests.java index ae96c8b3b7944..96790301139f3 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BaseClassTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BaseClassTests.java @@ -21,6 +21,7 @@ import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import java.util.Collections; import java.util.HashMap; @@ -65,7 +66,7 @@ protected Map, List> scriptContexts() { public abstract static class Gets { - public interface Factory { + public interface Factory extends ScriptFactory { Gets newInstance(String testString, int testInt, Map params); } @@ -111,7 +112,7 @@ public void testGets() throws Exception { } public abstract static class NoArgs { - public interface Factory { + public interface Factory extends ScriptFactory { NoArgs newInstance(); } @@ -137,7 +138,7 @@ public void testNoArgs() throws Exception { } public abstract static class OneArg { - public interface Factory { + public interface Factory extends ScriptFactory { OneArg newInstance(); } @@ -154,7 +155,7 @@ public void testOneArg() throws Exception { } public abstract static class ArrayArg { - public interface Factory { + public interface Factory extends ScriptFactory { ArrayArg newInstance(); } @@ -171,7 +172,7 @@ public void testArrayArg() throws Exception { } public abstract static class PrimitiveArrayArg { - public interface Factory { + public interface Factory extends ScriptFactory { PrimitiveArrayArg newInstance(); } @@ -188,7 +189,7 @@ public void testPrimitiveArrayArg() throws Exception { } public abstract static class DefArrayArg { - public interface Factory { + public interface Factory extends ScriptFactory { DefArrayArg newInstance(); } @@ -212,7 +213,7 @@ public void testDefArrayArg()throws Exception { } public abstract static class ManyArgs { - public interface Factory { + public interface Factory extends ScriptFactory { ManyArgs newInstance(); } @@ -251,7 +252,7 @@ public void testManyArgs() throws Exception { } public abstract static class VarArgs { - public interface Factory { + public interface Factory extends ScriptFactory { VarArgs newInstance(); } @@ -267,7 +268,7 @@ public void testVarArgs() throws Exception { } public abstract static class DefaultMethods { - public interface Factory { + public interface Factory extends ScriptFactory { DefaultMethods newInstance(); } @@ -301,7 +302,7 @@ public void testDefaultMethods() throws Exception { } public abstract static class ReturnsVoid { - public interface Factory { + public interface Factory extends ScriptFactory { ReturnsVoid newInstance(); } @@ -325,7 +326,7 @@ public void testReturnsVoid() throws Exception { } public abstract static class ReturnsPrimitiveBoolean { - public interface Factory { + public interface Factory extends ScriptFactory { ReturnsPrimitiveBoolean newInstance(); } @@ -391,20 +392,20 @@ public void testReturnsPrimitiveBoolean() throws Exception { } public abstract static class ReturnsPrimitiveInt { - public interface Factory { + public interface Factory extends ScriptFactory { ReturnsPrimitiveInt newInstance(); } public static final ScriptContext CONTEXT = new ScriptContext<>("returnsprimitiveint", Factory.class); - + public static final String[] PARAMETERS = new String[] {}; public abstract int execute(); } public void testReturnsPrimitiveInt() throws Exception { - assertEquals(1, + assertEquals(1, scriptEngine.compile("testReturnsPrimitiveInt0", "1", ReturnsPrimitiveInt.CONTEXT, emptyMap()) .newInstance().execute()); - assertEquals(1, + assertEquals(1, scriptEngine.compile("testReturnsPrimitiveInt1", "(int) 1L", ReturnsPrimitiveInt.CONTEXT, emptyMap()) .newInstance().execute()); assertEquals(1, scriptEngine.compile("testReturnsPrimitiveInt2", "(int) 1.1d", ReturnsPrimitiveInt.CONTEXT, emptyMap()) @@ -455,12 +456,12 @@ public void testReturnsPrimitiveInt() throws Exception { } public abstract static class ReturnsPrimitiveFloat { - public interface Factory { + public interface Factory extends ScriptFactory { ReturnsPrimitiveFloat newInstance(); } public static final ScriptContext CONTEXT = new ScriptContext<>("returnsprimitivefloat", Factory.class); - + public static final String[] PARAMETERS = new String[] {}; public abstract float execute(); } @@ -504,12 +505,12 @@ public void testReturnsPrimitiveFloat() throws Exception { } public abstract static class ReturnsPrimitiveDouble { - public interface Factory { + public interface Factory extends ScriptFactory { ReturnsPrimitiveDouble newInstance(); } public static final ScriptContext CONTEXT = new ScriptContext<>("returnsprimitivedouble", Factory.class); - + public static final String[] PARAMETERS = new String[] {}; public abstract double execute(); } @@ -567,7 +568,7 @@ public void testReturnsPrimitiveDouble() throws Exception { } public abstract static class NoArgsConstant { - public interface Factory { + public interface Factory extends ScriptFactory { NoArgsConstant newInstance(); } @@ -584,7 +585,7 @@ public void testNoArgsConstant() { } public abstract static class WrongArgsConstant { - public interface Factory { + public interface Factory extends ScriptFactory { WrongArgsConstant newInstance(); } @@ -602,7 +603,7 @@ public void testWrongArgsConstant() { } public abstract static class WrongLengthOfArgConstant { - public interface Factory { + public interface Factory extends ScriptFactory { WrongLengthOfArgConstant newInstance(); } @@ -619,7 +620,7 @@ public void testWrongLengthOfArgConstant() { } public abstract static class UnknownArgType { - public interface Factory { + public interface Factory extends ScriptFactory { UnknownArgType newInstance(); } @@ -636,7 +637,7 @@ public void testUnknownArgType() { } public abstract static class UnknownReturnType { - public interface Factory { + public interface Factory extends ScriptFactory { UnknownReturnType newInstance(); } @@ -653,7 +654,7 @@ public void testUnknownReturnType() { } public abstract static class UnknownArgTypeInArray { - public interface Factory { + public interface Factory extends ScriptFactory { UnknownArgTypeInArray newInstance(); } @@ -670,7 +671,7 @@ public void testUnknownArgTypeInArray() { } public abstract static class TwoExecuteMethods { - public interface Factory { + public interface Factory extends ScriptFactory { TwoExecuteMethods newInstance(); } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java index e4d1db2243b82..72fc01dbf2ce6 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicStatementTests.java @@ -2,6 +2,7 @@ import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import java.util.ArrayList; import java.util.Collections; @@ -260,7 +261,7 @@ public void testReturnStatement() { } public abstract static class OneArg { - public interface Factory { + public interface Factory extends ScriptFactory { OneArg newInstance(); } diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BindingsTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BindingsTests.java index 171880abd7907..d165e0ef76d81 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/BindingsTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/BindingsTests.java @@ -23,6 +23,7 @@ import org.elasticsearch.painless.spi.WhitelistInstanceBinding; import org.elasticsearch.painless.spi.WhitelistLoader; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import java.util.ArrayList; import java.util.Collections; @@ -89,7 +90,7 @@ public abstract static class BindingsTestScript { public static final String[] PARAMETERS = { "test", "bound" }; public int getTestValue() {return 7;} public abstract int execute(int test, int bound); - public interface Factory { + public interface Factory extends ScriptFactory { BindingsTestScript newInstance(); } public static final ScriptContext CONTEXT = new ScriptContext<>("bindings_test", Factory.class); diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FactoryTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FactoryTests.java index 556ef8dd3c6d3..1d3fd829d2512 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FactoryTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FactoryTests.java @@ -21,6 +21,7 @@ import org.elasticsearch.painless.spi.Whitelist; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.script.TemplateScript; import java.util.Collections; @@ -84,7 +85,7 @@ public interface StatefulFactory { boolean needsD(); } - public interface Factory { + public interface Factory extends ScriptFactory { StatefulFactory newFactory(int x, int y); boolean needsTest(); @@ -137,7 +138,7 @@ public Map getParams() { public static final String[] PARAMETERS = new String[] {"test"}; public abstract Object execute(int test); - public interface Factory { + public interface Factory extends ScriptFactory { FactoryTestScript newInstance(Map params); boolean needsTest(); @@ -165,7 +166,7 @@ public abstract static class EmptyTestScript { public static final String[] PARAMETERS = {}; public abstract Object execute(); - public interface Factory { + public interface Factory extends ScriptFactory { EmptyTestScript newInstance(); } diff --git a/plugins/examples/script-expert-scoring/src/main/java/org/elasticsearch/example/expertscript/ExpertScriptPlugin.java b/plugins/examples/script-expert-scoring/src/main/java/org/elasticsearch/example/expertscript/ExpertScriptPlugin.java index 149db3dfdd2cf..92c4846ae0bd7 100644 --- a/plugins/examples/script-expert-scoring/src/main/java/org/elasticsearch/example/expertscript/ExpertScriptPlugin.java +++ b/plugins/examples/script-expert-scoring/src/main/java/org/elasticsearch/example/expertscript/ExpertScriptPlugin.java @@ -29,6 +29,7 @@ import org.elasticsearch.script.ScoreScript.LeafFactory; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptEngine; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.search.lookup.SearchLookup; import java.io.IOException; @@ -39,16 +40,21 @@ import java.util.Set; /** - * An example script plugin that adds a {@link ScriptEngine} implementing expert scoring. + * An example script plugin that adds a {@link ScriptEngine} + * implementing expert scoring. */ public class ExpertScriptPlugin extends Plugin implements ScriptPlugin { @Override - public ScriptEngine getScriptEngine(Settings settings, Collection> contexts) { + public ScriptEngine getScriptEngine( + Settings settings, + Collection> contexts + ) { return new MyExpertScriptEngine(); } - /** An example {@link ScriptEngine} that uses Lucene segment details to implement pure document frequency scoring. */ + /** An example {@link ScriptEngine} that uses Lucene segment details to + * implement pure document frequency scoring. */ // tag::expert_engine private static class MyExpertScriptEngine implements ScriptEngine { @Override @@ -57,8 +63,12 @@ public String getType() { } @Override - public T compile(String scriptName, String scriptSource, - ScriptContext context, Map params) { + public T compile( + String scriptName, + String scriptSource, + ScriptContext context, + Map params + ) { if (context.equals(ScoreScript.CONTEXT) == false) { throw new IllegalArgumentException(getType() + " scripts cannot be used for context [" @@ -66,7 +76,7 @@ public T compile(String scriptName, String scriptSource, } // we use the script "source" as the script identifier if ("pure_df".equals(scriptSource)) { - ScoreScript.Factory factory = PureDfLeafFactory::new; + ScoreScript.Factory factory = new PureDfFactory(); return context.factoryClazz.cast(factory); } throw new IllegalArgumentException("Unknown script name " @@ -83,6 +93,23 @@ public Set> getSupportedContexts() { return Collections.singleton(ScoreScript.CONTEXT); } + private static class PureDfFactory implements ScoreScript.Factory { + @Override + public boolean isResultDeterministic() { + // PureDfLeafFactory only uses deterministic APIs, this + // implies the results are cacheable. + return true; + } + + @Override + public LeafFactory newFactory( + Map params, + SearchLookup lookup + ) { + return new PureDfLeafFactory(params, lookup); + } + } + private static class PureDfLeafFactory implements LeafFactory { private final Map params; private final SearchLookup lookup; @@ -122,7 +149,9 @@ public ScoreScript newInstance(LeafReaderContext context) */ return new ScoreScript(params, lookup, context) { @Override - public double execute(ExplanationHolder explanation) { + public double execute( + ExplanationHolder explanation + ) { return 0.0d; } }; @@ -148,8 +177,8 @@ public void setDocument(int docid) { public double execute(ExplanationHolder explanation) { if (postings.docID() != currentDocid) { /* - * advance moved past the current doc, so this doc - * has no occurrences of the term + * advance moved past the current doc, so this + * doc has no occurrences of the term */ return 0.0d; } diff --git a/server/src/main/java/org/elasticsearch/index/query/InnerHitContextBuilder.java b/server/src/main/java/org/elasticsearch/index/query/InnerHitContextBuilder.java index 87faca07d524b..7b05b0cf731cb 100644 --- a/server/src/main/java/org/elasticsearch/index/query/InnerHitContextBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/InnerHitContextBuilder.java @@ -93,7 +93,7 @@ protected void setupInnerHitsContext(QueryShardContext queryShardContext, if (innerHitBuilder.getScriptFields() != null) { for (SearchSourceBuilder.ScriptField field : innerHitBuilder.getScriptFields()) { QueryShardContext innerContext = innerHitsContext.getQueryShardContext(); - FieldScript.Factory factory = innerContext.getScriptService().compile(field.script(), FieldScript.CONTEXT); + FieldScript.Factory factory = innerContext.compile(field.script(), FieldScript.CONTEXT); FieldScript.LeafFactory fieldScript = factory.newFactory(field.script().getParams(), innerHitsContext.lookup()); innerHitsContext.scriptFields().add(new org.elasticsearch.search.fetch.subphase.ScriptFieldsContext.ScriptField( field.fieldName(), fieldScript, field.ignoreFailure())); diff --git a/server/src/main/java/org/elasticsearch/index/query/IntervalFilterScript.java b/server/src/main/java/org/elasticsearch/index/query/IntervalFilterScript.java index 1f86179dca73c..2d0fc99258c4d 100644 --- a/server/src/main/java/org/elasticsearch/index/query/IntervalFilterScript.java +++ b/server/src/main/java/org/elasticsearch/index/query/IntervalFilterScript.java @@ -21,6 +21,7 @@ import org.apache.lucene.queries.intervals.IntervalIterator; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; /** * Base class for scripts used as interval filters, see {@link IntervalsSourceProvider.IntervalFilter} @@ -50,7 +51,7 @@ public int getGaps() { public abstract boolean execute(Interval interval); - public interface Factory { + public interface Factory extends ScriptFactory { IntervalFilterScript newInstance(); } diff --git a/server/src/main/java/org/elasticsearch/index/query/IntervalsSourceProvider.java b/server/src/main/java/org/elasticsearch/index/query/IntervalsSourceProvider.java index 97093f0c92fc9..167266e0892fd 100644 --- a/server/src/main/java/org/elasticsearch/index/query/IntervalsSourceProvider.java +++ b/server/src/main/java/org/elasticsearch/index/query/IntervalsSourceProvider.java @@ -717,7 +717,7 @@ public IntervalFilter(StreamInput in) throws IOException { public IntervalsSource filter(IntervalsSource input, QueryShardContext context, MappedFieldType fieldType) throws IOException { if (script != null) { - IntervalFilterScript ifs = context.getScriptService().compile(script, IntervalFilterScript.CONTEXT).newInstance(); + IntervalFilterScript ifs = context.compile(script, IntervalFilterScript.CONTEXT).newInstance(); return new ScriptFilterSource(input, script.getIdOrCode(), ifs); } IntervalsSource filterSource = filter.getSource(context, fieldType); diff --git a/server/src/main/java/org/elasticsearch/index/query/QueryShardContext.java b/server/src/main/java/org/elasticsearch/index/query/QueryShardContext.java index 088d2b9732828..ee9e9a56abdad 100644 --- a/server/src/main/java/org/elasticsearch/index/query/QueryShardContext.java +++ b/server/src/main/java/org/elasticsearch/index/query/QueryShardContext.java @@ -54,6 +54,9 @@ import org.elasticsearch.index.mapper.TypeFieldMapper; import org.elasticsearch.index.query.support.NestedScope; import org.elasticsearch.index.similarity.SimilarityService; +import org.elasticsearch.script.Script; +import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.script.ScriptService; import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.transport.RemoteClusterAware; @@ -354,10 +357,13 @@ public Index index() { return indexSettings.getIndex(); } - /** Return the script service to allow compiling scripts. */ - public final ScriptService getScriptService() { - failIfFrozen(); - return scriptService; + /** Compile script using script service */ + public FactoryType compile(Script script, ScriptContext context) { + FactoryType factory = scriptService.compile(script, context); + if (factory.isResultDeterministic() == false) { + failIfFrozen(); + } + return factory; } /** diff --git a/server/src/main/java/org/elasticsearch/index/query/ScriptQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/ScriptQueryBuilder.java index 8a3666afb9d12..e9b18bd0aa1f1 100644 --- a/server/src/main/java/org/elasticsearch/index/query/ScriptQueryBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/ScriptQueryBuilder.java @@ -130,7 +130,7 @@ public static ScriptQueryBuilder fromXContent(XContentParser parser) throws IOEx @Override protected Query doToQuery(QueryShardContext context) throws IOException { - FilterScript.Factory factory = context.getScriptService().compile(script, FilterScript.CONTEXT); + FilterScript.Factory factory = context.compile(script, FilterScript.CONTEXT); FilterScript.LeafFactory filterScript = factory.newFactory(script.getParams(), context.lookup()); return new ScriptQuery(script, filterScript); } diff --git a/server/src/main/java/org/elasticsearch/index/query/TermsSetQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/TermsSetQueryBuilder.java index 1e151896df046..ac2526d34325a 100644 --- a/server/src/main/java/org/elasticsearch/index/query/TermsSetQueryBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/TermsSetQueryBuilder.java @@ -40,6 +40,7 @@ import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.script.Script; +import org.elasticsearch.script.TermsSetQueryScript; import java.io.IOException; import java.util.ArrayList; @@ -47,7 +48,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import org.elasticsearch.script.TermsSetQueryScript; public final class TermsSetQueryBuilder extends AbstractQueryBuilder { @@ -262,7 +262,7 @@ private LongValuesSource createValuesSource(QueryShardContext context) { IndexNumericFieldData fieldData = context.getForField(msmFieldType); longValuesSource = new FieldValuesSource(fieldData); } else if (minimumShouldMatchScript != null) { - TermsSetQueryScript.Factory factory = context.getScriptService().compile(minimumShouldMatchScript, + TermsSetQueryScript.Factory factory = context.compile(minimumShouldMatchScript, TermsSetQueryScript.CONTEXT); Map params = new HashMap<>(); params.putAll(minimumShouldMatchScript.getParams()); diff --git a/server/src/main/java/org/elasticsearch/index/query/functionscore/ScriptScoreFunctionBuilder.java b/server/src/main/java/org/elasticsearch/index/query/functionscore/ScriptScoreFunctionBuilder.java index 8fc2d4ff6b1a4..3d5326d5f3da0 100644 --- a/server/src/main/java/org/elasticsearch/index/query/functionscore/ScriptScoreFunctionBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/functionscore/ScriptScoreFunctionBuilder.java @@ -92,7 +92,7 @@ protected int doHashCode() { @Override protected ScoreFunction doToFunction(QueryShardContext context) { try { - ScoreScript.Factory factory = context.getScriptService().compile(script, ScoreScript.CONTEXT); + ScoreScript.Factory factory = context.compile(script, ScoreScript.CONTEXT); ScoreScript.LeafFactory searchScript = factory.newFactory(script.getParams(), context.lookup()); return new ScriptScoreFunction(script, searchScript, context.index().getName(), context.getShardId(), context.indexVersionCreated()); diff --git a/server/src/main/java/org/elasticsearch/index/query/functionscore/ScriptScoreQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/functionscore/ScriptScoreQueryBuilder.java index 59086f163a17f..e55c6d318777a 100644 --- a/server/src/main/java/org/elasticsearch/index/query/functionscore/ScriptScoreQueryBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/functionscore/ScriptScoreQueryBuilder.java @@ -170,7 +170,7 @@ protected int doHashCode() { @Override protected Query doToQuery(QueryShardContext context) throws IOException { - ScoreScript.Factory factory = context.getScriptService().compile(script, ScoreScript.CONTEXT); + ScoreScript.Factory factory = context.compile(script, ScoreScript.CONTEXT); ScoreScript.LeafFactory scoreScriptFactory = factory.newFactory(script.getParams(), context.lookup()); Query query = this.query.toQuery(context); return new ScriptScoreQuery(query, script, scoreScriptFactory, minScore, diff --git a/server/src/main/java/org/elasticsearch/script/AggregationScript.java b/server/src/main/java/org/elasticsearch/script/AggregationScript.java index f48d097355110..302d3cb6479bb 100644 --- a/server/src/main/java/org/elasticsearch/script/AggregationScript.java +++ b/server/src/main/java/org/elasticsearch/script/AggregationScript.java @@ -159,7 +159,7 @@ public interface LeafFactory { /** * A factory to construct stateful {@link AggregationScript} factories for a specific index. */ - public interface Factory { + public interface Factory extends ScriptFactory { LeafFactory newFactory(Map params, SearchLookup lookup); } } diff --git a/server/src/main/java/org/elasticsearch/script/BucketAggregationScript.java b/server/src/main/java/org/elasticsearch/script/BucketAggregationScript.java index 76ff776353ef2..897134173537a 100644 --- a/server/src/main/java/org/elasticsearch/script/BucketAggregationScript.java +++ b/server/src/main/java/org/elasticsearch/script/BucketAggregationScript.java @@ -48,7 +48,7 @@ public Map getParams() { public abstract Number execute(); - public interface Factory { + public interface Factory extends ScriptFactory { BucketAggregationScript newInstance(Map params); } } diff --git a/server/src/main/java/org/elasticsearch/script/BucketAggregationSelectorScript.java b/server/src/main/java/org/elasticsearch/script/BucketAggregationSelectorScript.java index a8e2fad7cdcda..3c765439223d2 100644 --- a/server/src/main/java/org/elasticsearch/script/BucketAggregationSelectorScript.java +++ b/server/src/main/java/org/elasticsearch/script/BucketAggregationSelectorScript.java @@ -48,7 +48,7 @@ public Map getParams() { public abstract boolean execute(); - public interface Factory { + public interface Factory extends ScriptFactory { BucketAggregationSelectorScript newInstance(Map params); } } diff --git a/server/src/main/java/org/elasticsearch/script/FieldScript.java b/server/src/main/java/org/elasticsearch/script/FieldScript.java index 7707301ab4c1d..b68bef276ed8c 100644 --- a/server/src/main/java/org/elasticsearch/script/FieldScript.java +++ b/server/src/main/java/org/elasticsearch/script/FieldScript.java @@ -99,7 +99,7 @@ public interface LeafFactory { FieldScript newInstance(LeafReaderContext ctx) throws IOException; } - public interface Factory { + public interface Factory extends ScriptFactory { LeafFactory newFactory(Map params, SearchLookup lookup); } diff --git a/server/src/main/java/org/elasticsearch/script/FilterScript.java b/server/src/main/java/org/elasticsearch/script/FilterScript.java index 500ab99c6a56b..166a2b59ffa3f 100644 --- a/server/src/main/java/org/elasticsearch/script/FilterScript.java +++ b/server/src/main/java/org/elasticsearch/script/FilterScript.java @@ -70,7 +70,7 @@ public interface LeafFactory { } /** A factory to construct stateful {@link FilterScript} factories for a specific index. */ - public interface Factory { + public interface Factory extends ScriptFactory { LeafFactory newFactory(Map params, SearchLookup lookup); } diff --git a/server/src/main/java/org/elasticsearch/script/IngestConditionalScript.java b/server/src/main/java/org/elasticsearch/script/IngestConditionalScript.java index 27ce29b95dc50..44d87cfe6aba2 100644 --- a/server/src/main/java/org/elasticsearch/script/IngestConditionalScript.java +++ b/server/src/main/java/org/elasticsearch/script/IngestConditionalScript.java @@ -45,7 +45,7 @@ public Map getParams() { public abstract boolean execute(Map ctx); - public interface Factory { + public interface Factory extends ScriptFactory { IngestConditionalScript newInstance(Map params); } } diff --git a/server/src/main/java/org/elasticsearch/script/IngestScript.java b/server/src/main/java/org/elasticsearch/script/IngestScript.java index f357394ed31f0..7104ed7d9b0d2 100644 --- a/server/src/main/java/org/elasticsearch/script/IngestScript.java +++ b/server/src/main/java/org/elasticsearch/script/IngestScript.java @@ -46,7 +46,7 @@ public Map getParams() { public abstract void execute(Map ctx); - public interface Factory { + public interface Factory extends ScriptFactory { IngestScript newInstance(Map params); } } diff --git a/server/src/main/java/org/elasticsearch/script/NumberSortScript.java b/server/src/main/java/org/elasticsearch/script/NumberSortScript.java index d0b3fdbed363e..f1eb118b8bdd5 100644 --- a/server/src/main/java/org/elasticsearch/script/NumberSortScript.java +++ b/server/src/main/java/org/elasticsearch/script/NumberSortScript.java @@ -54,7 +54,7 @@ public interface LeafFactory { /** * A factory to construct stateful {@link NumberSortScript} factories for a specific index. */ - public interface Factory { + public interface Factory extends ScriptFactory { LeafFactory newFactory(Map params, SearchLookup lookup); } } diff --git a/server/src/main/java/org/elasticsearch/script/ScoreScript.java b/server/src/main/java/org/elasticsearch/script/ScoreScript.java index b95f499196581..76f6de4285c5e 100644 --- a/server/src/main/java/org/elasticsearch/script/ScoreScript.java +++ b/server/src/main/java/org/elasticsearch/script/ScoreScript.java @@ -239,7 +239,7 @@ public interface LeafFactory { } /** A factory to construct stateful {@link ScoreScript} factories for a specific index. */ - public interface Factory { + public interface Factory extends ScriptFactory { ScoreScript.LeafFactory newFactory(Map params, SearchLookup lookup); diff --git a/server/src/main/java/org/elasticsearch/script/ScriptContext.java b/server/src/main/java/org/elasticsearch/script/ScriptContext.java index 081a26d1e511a..4e927da09d118 100644 --- a/server/src/main/java/org/elasticsearch/script/ScriptContext.java +++ b/server/src/main/java/org/elasticsearch/script/ScriptContext.java @@ -54,7 +54,7 @@ * If the variable name starts with an underscore, for example, {@code _score}, the needs method would * be {@code boolean needs_score()}. */ -public final class ScriptContext { +public final class ScriptContext { /** A unique identifier for this context. */ public final String name; diff --git a/server/src/main/java/org/elasticsearch/script/ScriptEngine.java b/server/src/main/java/org/elasticsearch/script/ScriptEngine.java index 9ace06d701d14..4c38ae5c6e19c 100644 --- a/server/src/main/java/org/elasticsearch/script/ScriptEngine.java +++ b/server/src/main/java/org/elasticsearch/script/ScriptEngine.java @@ -42,7 +42,12 @@ public interface ScriptEngine extends Closeable { * @param params compile-time parameters (such as flags to the compiler) * @return A compiled script of the FactoryType from {@link ScriptContext} */ - FactoryType compile(String name, String code, ScriptContext context, Map params); + FactoryType compile( + String name, + String code, + ScriptContext context, + Map params + ); @Override default void close() throws IOException {} diff --git a/server/src/main/java/org/elasticsearch/script/ScriptFactory.java b/server/src/main/java/org/elasticsearch/script/ScriptFactory.java new file mode 100644 index 0000000000000..d05e4f77c6449 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/script/ScriptFactory.java @@ -0,0 +1,28 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.script; + +/** + * Contains utility methods for compiled scripts without impacting concrete script signatures + */ +public interface ScriptFactory { + /** Returns {@code true} if the result of the script will be deterministic, {@code false} otherwise. */ + default boolean isResultDeterministic() { return false; } +} diff --git a/server/src/main/java/org/elasticsearch/script/ScriptService.java b/server/src/main/java/org/elasticsearch/script/ScriptService.java index f23a2d9cedd8d..eb335ebe94228 100644 --- a/server/src/main/java/org/elasticsearch/script/ScriptService.java +++ b/server/src/main/java/org/elasticsearch/script/ScriptService.java @@ -284,7 +284,7 @@ void setMaxCompilationRate(Tuple newRate) { * * @return a compiled script which may be used to construct instances of a script for the given context */ - public FactoryType compile(Script script, ScriptContext context) { + public FactoryType compile(Script script, ScriptContext context) { Objects.requireNonNull(script); Objects.requireNonNull(context); diff --git a/server/src/main/java/org/elasticsearch/script/ScriptedMetricAggContexts.java b/server/src/main/java/org/elasticsearch/script/ScriptedMetricAggContexts.java index f1c3e996ec8be..3fc97b60ba999 100644 --- a/server/src/main/java/org/elasticsearch/script/ScriptedMetricAggContexts.java +++ b/server/src/main/java/org/elasticsearch/script/ScriptedMetricAggContexts.java @@ -53,7 +53,7 @@ public Object getState() { public abstract void execute(); - public interface Factory { + public interface Factory extends ScriptFactory { InitScript newInstance(Map params, Map state); } @@ -143,7 +143,7 @@ public interface LeafFactory { MapScript newInstance(LeafReaderContext ctx); } - public interface Factory { + public interface Factory extends ScriptFactory { LeafFactory newFactory(Map params, Map state, SearchLookup lookup); } @@ -170,7 +170,7 @@ public Map getState() { public abstract Object execute(); - public interface Factory { + public interface Factory extends ScriptFactory { CombineScript newInstance(Map params, Map state); } @@ -197,7 +197,7 @@ public List getStates() { public abstract Object execute(); - public interface Factory { + public interface Factory extends ScriptFactory { ReduceScript newInstance(Map params, List states); } diff --git a/server/src/main/java/org/elasticsearch/script/SignificantTermsHeuristicScoreScript.java b/server/src/main/java/org/elasticsearch/script/SignificantTermsHeuristicScoreScript.java index 0296bc36ce107..b1a280783a70d 100644 --- a/server/src/main/java/org/elasticsearch/script/SignificantTermsHeuristicScoreScript.java +++ b/server/src/main/java/org/elasticsearch/script/SignificantTermsHeuristicScoreScript.java @@ -32,7 +32,7 @@ public abstract class SignificantTermsHeuristicScoreScript { public abstract double execute(Map params); - public interface Factory { + public interface Factory extends ScriptFactory { SignificantTermsHeuristicScoreScript newInstance(); } } diff --git a/server/src/main/java/org/elasticsearch/script/SimilarityScript.java b/server/src/main/java/org/elasticsearch/script/SimilarityScript.java index 4aeb4063959b3..c3efb55a6031e 100644 --- a/server/src/main/java/org/elasticsearch/script/SimilarityScript.java +++ b/server/src/main/java/org/elasticsearch/script/SimilarityScript.java @@ -22,7 +22,7 @@ import org.elasticsearch.index.similarity.ScriptedSimilarity; /** A script that is used to build {@link ScriptedSimilarity} instances. */ -public abstract class SimilarityScript { +public abstract class SimilarityScript { /** Compute the score. * @param weight weight computed by the {@link SimilarityWeightScript} if any, or 1. @@ -34,7 +34,7 @@ public abstract class SimilarityScript { public abstract double execute(double weight, ScriptedSimilarity.Query query, ScriptedSimilarity.Field field, ScriptedSimilarity.Term term, ScriptedSimilarity.Doc doc); - public interface Factory { + public interface Factory extends ScriptFactory { SimilarityScript newInstance(); } diff --git a/server/src/main/java/org/elasticsearch/script/SimilarityWeightScript.java b/server/src/main/java/org/elasticsearch/script/SimilarityWeightScript.java index 04bbc3cccf40a..2797da64a0e25 100644 --- a/server/src/main/java/org/elasticsearch/script/SimilarityWeightScript.java +++ b/server/src/main/java/org/elasticsearch/script/SimilarityWeightScript.java @@ -32,7 +32,7 @@ public abstract class SimilarityWeightScript { public abstract double execute(ScriptedSimilarity.Query query, ScriptedSimilarity.Field field, ScriptedSimilarity.Term term); - public interface Factory { + public interface Factory extends ScriptFactory { SimilarityWeightScript newInstance(); } diff --git a/server/src/main/java/org/elasticsearch/script/StringSortScript.java b/server/src/main/java/org/elasticsearch/script/StringSortScript.java index 1c6c47dd21552..8c459fceed64d 100644 --- a/server/src/main/java/org/elasticsearch/script/StringSortScript.java +++ b/server/src/main/java/org/elasticsearch/script/StringSortScript.java @@ -45,7 +45,7 @@ public interface LeafFactory { /** * A factory to construct stateful {@link StringSortScript} factories for a specific index. */ - public interface Factory { + public interface Factory extends ScriptFactory { LeafFactory newFactory(Map params, SearchLookup lookup); } } diff --git a/server/src/main/java/org/elasticsearch/script/TemplateScript.java b/server/src/main/java/org/elasticsearch/script/TemplateScript.java index c053cf2b509d0..f7cf4590387d8 100644 --- a/server/src/main/java/org/elasticsearch/script/TemplateScript.java +++ b/server/src/main/java/org/elasticsearch/script/TemplateScript.java @@ -41,7 +41,7 @@ public Map getParams() { /** Run a template and return the resulting string, encoded in utf8 bytes. */ public abstract String execute(); - public interface Factory { + public interface Factory extends ScriptFactory { TemplateScript newInstance(Map params); } diff --git a/server/src/main/java/org/elasticsearch/script/TermsSetQueryScript.java b/server/src/main/java/org/elasticsearch/script/TermsSetQueryScript.java index c651c3ce69041..c7ae36c5b01c4 100644 --- a/server/src/main/java/org/elasticsearch/script/TermsSetQueryScript.java +++ b/server/src/main/java/org/elasticsearch/script/TermsSetQueryScript.java @@ -112,7 +112,7 @@ public interface LeafFactory { /** * A factory to construct stateful {@link TermsSetQueryScript} factories for a specific index. */ - public interface Factory { + public interface Factory extends ScriptFactory { LeafFactory newFactory(Map params, SearchLookup lookup); } } diff --git a/server/src/main/java/org/elasticsearch/script/UpdateScript.java b/server/src/main/java/org/elasticsearch/script/UpdateScript.java index 765489b7e4449..354e6f53bcd1a 100644 --- a/server/src/main/java/org/elasticsearch/script/UpdateScript.java +++ b/server/src/main/java/org/elasticsearch/script/UpdateScript.java @@ -67,7 +67,7 @@ public Map getCtx() { public abstract void execute(); - public interface Factory { + public interface Factory extends ScriptFactory { UpdateScript newInstance(Map params, Map ctx); } } diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ScriptHeuristic.java b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ScriptHeuristic.java index 50ef203880d94..e90df2ed33a0b 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ScriptHeuristic.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/heuristics/ScriptHeuristic.java @@ -101,7 +101,7 @@ public SignificanceHeuristic rewrite(InternalAggregation.ReduceContext context) @Override public SignificanceHeuristic rewrite(QueryShardContext queryShardContext) { - SignificantTermsHeuristicScoreScript.Factory compiledScript = queryShardContext.getScriptService().compile(script, + SignificantTermsHeuristicScoreScript.Factory compiledScript = queryShardContext.compile(script, SignificantTermsHeuristicScoreScript.CONTEXT); return new ExecutableScriptHeuristic(script, compiledScript.newInstance()); } diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/ScriptedMetricAggregationBuilder.java b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/ScriptedMetricAggregationBuilder.java index e650a968036cc..accee6fcb5250 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/ScriptedMetricAggregationBuilder.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/ScriptedMetricAggregationBuilder.java @@ -209,14 +209,14 @@ protected ScriptedMetricAggregatorFactory doBuild(QueryShardContext queryShardCo ScriptedMetricAggContexts.InitScript.Factory compiledInitScript; Map initScriptParams; if (initScript != null) { - compiledInitScript = queryShardContext.getScriptService().compile(initScript, ScriptedMetricAggContexts.InitScript.CONTEXT); + compiledInitScript = queryShardContext.compile(initScript, ScriptedMetricAggContexts.InitScript.CONTEXT); initScriptParams = initScript.getParams(); } else { compiledInitScript = (p, a) -> null; initScriptParams = Collections.emptyMap(); } - ScriptedMetricAggContexts.MapScript.Factory compiledMapScript = queryShardContext.getScriptService().compile(mapScript, + ScriptedMetricAggContexts.MapScript.Factory compiledMapScript = queryShardContext.compile(mapScript, ScriptedMetricAggContexts.MapScript.CONTEXT); Map mapScriptParams = mapScript.getParams(); @@ -224,7 +224,7 @@ protected ScriptedMetricAggregatorFactory doBuild(QueryShardContext queryShardCo ScriptedMetricAggContexts.CombineScript.Factory compiledCombineScript; Map combineScriptParams; - compiledCombineScript = queryShardContext.getScriptService().compile(combineScript, + compiledCombineScript = queryShardContext.compile(combineScript, ScriptedMetricAggContexts.CombineScript.CONTEXT); combineScriptParams = combineScript.getParams(); diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/TopHitsAggregationBuilder.java b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/TopHitsAggregationBuilder.java index 67a95d23e916b..faaa7d733912e 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/metrics/TopHitsAggregationBuilder.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/metrics/TopHitsAggregationBuilder.java @@ -592,7 +592,7 @@ protected TopHitsAggregatorFactory doBuild(QueryShardContext queryShardContext, List fields = new ArrayList<>(); if (scriptFields != null) { for (ScriptField field : scriptFields) { - FieldScript.Factory factory = queryShardContext.getScriptService().compile(field.script(), FieldScript.CONTEXT); + FieldScript.Factory factory = queryShardContext.compile(field.script(), FieldScript.CONTEXT); FieldScript.LeafFactory searchScript = factory.newFactory(field.script().getParams(), queryShardContext.lookup()); fields.add(new org.elasticsearch.search.fetch.subphase.ScriptFieldsContext.ScriptField( field.fieldName(), searchScript, field.ignoreFailure())); diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovingFunctionScript.java b/server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovingFunctionScript.java index 79e1f740729ce..8dae73138b272 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovingFunctionScript.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/pipeline/MovingFunctionScript.java @@ -20,6 +20,7 @@ package org.elasticsearch.search.aggregations.pipeline; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import java.util.Map; @@ -35,7 +36,7 @@ public abstract class MovingFunctionScript { */ public abstract double execute(Map params, double[] values); - public interface Factory { + public interface Factory extends ScriptFactory { MovingFunctionScript newInstance(); } diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceConfig.java b/server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceConfig.java index 4919b5bc9f9ad..ba599827b88af 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceConfig.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/support/ValuesSourceConfig.java @@ -138,7 +138,7 @@ private static AggregationScript.LeafFactory createScript(Script script, QuerySh if (script == null) { return null; } else { - AggregationScript.Factory factory = context.getScriptService().compile(script, AggregationScript.CONTEXT); + AggregationScript.Factory factory = context.compile(script, AggregationScript.CONTEXT); return factory.newFactory(script.getParams(), context.lookup()); } } diff --git a/server/src/main/java/org/elasticsearch/search/sort/ScriptSortBuilder.java b/server/src/main/java/org/elasticsearch/search/sort/ScriptSortBuilder.java index 4ebb8f2689c2d..fd0408a85bc48 100644 --- a/server/src/main/java/org/elasticsearch/search/sort/ScriptSortBuilder.java +++ b/server/src/main/java/org/elasticsearch/search/sort/ScriptSortBuilder.java @@ -335,7 +335,7 @@ public SortFieldAndFormat build(QueryShardContext context) throws IOException { final IndexFieldData.XFieldComparatorSource fieldComparatorSource; switch (type) { case STRING: - final StringSortScript.Factory factory = context.getScriptService().compile(script, StringSortScript.CONTEXT); + final StringSortScript.Factory factory = context.compile(script, StringSortScript.CONTEXT); final StringSortScript.LeafFactory searchScript = factory.newFactory(script.getParams(), context.lookup()); fieldComparatorSource = new BytesRefFieldComparatorSource(null, null, valueMode, nested) { StringSortScript leafScript; @@ -364,7 +364,7 @@ protected void setScorer(Scorable scorer) { }; break; case NUMBER: - final NumberSortScript.Factory numberSortFactory = context.getScriptService().compile(script, NumberSortScript.CONTEXT); + final NumberSortScript.Factory numberSortFactory = context.compile(script, NumberSortScript.CONTEXT); final NumberSortScript.LeafFactory numberSortScript = numberSortFactory.newFactory(script.getParams(), context.lookup()); fieldComparatorSource = new DoubleValuesComparatorSource(null, Double.MAX_VALUE, valueMode, nested) { NumberSortScript leafScript; diff --git a/server/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionBuilder.java b/server/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionBuilder.java index 5b66badc733e0..7bbcc0d6c5405 100644 --- a/server/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionBuilder.java +++ b/server/src/main/java/org/elasticsearch/search/suggest/phrase/PhraseSuggestionBuilder.java @@ -634,7 +634,7 @@ public SuggestionContext build(QueryShardContext context) throws IOException { } if (this.collateQuery != null) { - TemplateScript.Factory scriptFactory = context.getScriptService().compile(this.collateQuery, TemplateScript.CONTEXT); + TemplateScript.Factory scriptFactory = context.compile(this.collateQuery, TemplateScript.CONTEXT); suggestionContext.setCollateQueryScript(scriptFactory); if (this.collateParams != null) { suggestionContext.setCollateScriptParams(this.collateParams); diff --git a/server/src/test/java/org/elasticsearch/index/query/IntervalQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/IntervalQueryBuilderTests.java index 7b004db65da50..ed28a06500d5a 100644 --- a/server/src/test/java/org/elasticsearch/index/query/IntervalQueryBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/IntervalQueryBuilderTests.java @@ -35,6 +35,7 @@ import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptType; import org.elasticsearch.test.AbstractQueryTestCase; @@ -396,7 +397,7 @@ public boolean execute(Interval interval) { ScriptService scriptService = new ScriptService(Settings.EMPTY, Collections.emptyMap(), Collections.emptyMap()){ @Override @SuppressWarnings("unchecked") - public FactoryType compile(Script script, ScriptContext context) { + public FactoryType compile(Script script, ScriptContext context) { assertEquals(IntervalFilterScript.CONTEXT, context); assertEquals(new Script("interval.start > 3"), script); return (FactoryType) factory; diff --git a/server/src/test/java/org/elasticsearch/script/ScriptContextTests.java b/server/src/test/java/org/elasticsearch/script/ScriptContextTests.java index 157b0969ae813..dc77fb0126262 100644 --- a/server/src/test/java/org/elasticsearch/script/ScriptContextTests.java +++ b/server/src/test/java/org/elasticsearch/script/ScriptContextTests.java @@ -23,28 +23,28 @@ public class ScriptContextTests extends ESTestCase { - public interface TwoNewInstance { + public interface TwoNewInstance extends ScriptFactory { String newInstance(int foo, int bar); String newInstance(int foo); - interface StatefulFactory { + interface StatefulFactory extends ScriptFactory { TwoNewInstance newFactory(); } } - public interface TwoNewFactory { + public interface TwoNewFactory extends ScriptFactory { String newFactory(int foo, int bar); String newFactory(int foo); } - public interface MissingNewInstance { + public interface MissingNewInstance extends ScriptFactory { String typoNewInstanceMethod(int foo); } public interface DummyScript { int execute(int foo); - interface Factory { + interface Factory extends ScriptFactory { DummyScript newInstance(); } } @@ -54,7 +54,7 @@ public interface DummyStatefulScript { interface StatefulFactory { DummyStatefulScript newInstance(); } - interface Factory { + interface Factory extends ScriptFactory { StatefulFactory newFactory(); } } diff --git a/server/src/test/java/org/elasticsearch/script/ScriptLanguagesInfoTests.java b/server/src/test/java/org/elasticsearch/script/ScriptLanguagesInfoTests.java index 38139103ed2ab..6e720b480934b 100644 --- a/server/src/test/java/org/elasticsearch/script/ScriptLanguagesInfoTests.java +++ b/server/src/test/java/org/elasticsearch/script/ScriptLanguagesInfoTests.java @@ -75,7 +75,7 @@ private ScriptService getMockScriptService(Settings settings) { } - public interface MiscContext { + public interface MiscContext extends ScriptFactory { void execute(); Object newInstance(); } diff --git a/server/src/test/java/org/elasticsearch/search/functionscore/ExplainableScriptIT.java b/server/src/test/java/org/elasticsearch/search/functionscore/ExplainableScriptIT.java index 79593c89cd193..480d787fab18b 100644 --- a/server/src/test/java/org/elasticsearch/search/functionscore/ExplainableScriptIT.java +++ b/server/src/test/java/org/elasticsearch/search/functionscore/ExplainableScriptIT.java @@ -34,6 +34,7 @@ import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptEngine; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.script.ScriptType; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; @@ -75,7 +76,12 @@ public String getType() { } @Override - public T compile(String scriptName, String scriptSource, ScriptContext context, Map params) { + public T compile( + String scriptName, + String scriptSource, + ScriptContext context, + Map params + ) { assert scriptSource.equals("explainable_script"); assert context == ScoreScript.CONTEXT; ScoreScript.Factory factory = (params1, lookup) -> new ScoreScript.LeafFactory() { diff --git a/server/src/test/java/org/elasticsearch/search/suggest/SuggestSearchIT.java b/server/src/test/java/org/elasticsearch/search/suggest/SuggestSearchIT.java index f544121f7d203..4191dd9c764b7 100644 --- a/server/src/test/java/org/elasticsearch/search/suggest/SuggestSearchIT.java +++ b/server/src/test/java/org/elasticsearch/search/suggest/SuggestSearchIT.java @@ -34,6 +34,7 @@ import org.elasticsearch.plugins.ScriptPlugin; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptEngine; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.script.TemplateScript; import org.elasticsearch.search.suggest.phrase.DirectCandidateGeneratorBuilder; import org.elasticsearch.search.suggest.phrase.Laplace; @@ -1137,7 +1138,12 @@ public String getType() { } @Override - public T compile(String scriptName, String scriptSource, ScriptContext context, Map params) { + public T compile( + String scriptName, + String scriptSource, + ScriptContext context, + Map params + ) { if (context.instanceClazz != TemplateScript.class) { throw new UnsupportedOperationException(); } diff --git a/test/framework/src/main/java/org/elasticsearch/ingest/TestTemplateService.java b/test/framework/src/main/java/org/elasticsearch/ingest/TestTemplateService.java index 5bbf39d8fdc17..b5fcb2a37d7e3 100644 --- a/test/framework/src/main/java/org/elasticsearch/ingest/TestTemplateService.java +++ b/test/framework/src/main/java/org/elasticsearch/ingest/TestTemplateService.java @@ -23,6 +23,7 @@ import org.elasticsearch.script.MockScriptEngine; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.TemplateScript; @@ -48,7 +49,7 @@ private TestTemplateService(boolean compilationException) { } @Override - public FactoryType compile(Script script, ScriptContext context) { + public FactoryType compile(Script script, ScriptContext context) { if (this.compilationException) { throw new RuntimeException("could not compile script"); } else { diff --git a/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java b/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java index 4188af16556a0..a213159e5efad 100644 --- a/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java +++ b/test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java @@ -84,7 +84,7 @@ public String getType() { } @Override - public T compile(String name, String source, ScriptContext context, Map params) { + public T compile(String name, String source, ScriptContext context, Map params) { // Scripts are always resolved using the script's source. For inline scripts, it's easy because they don't have names and the // source is always provided. For stored and file scripts, the source of the script must match the key of a predefined script. Function, Object> script = scripts.get(source); diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/script/MockMustacheScriptEngine.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/script/MockMustacheScriptEngine.java index 4f9b125a9fd6b..16a95f0accdac 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/script/MockMustacheScriptEngine.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/script/MockMustacheScriptEngine.java @@ -39,7 +39,7 @@ public String getType() { } @Override - public T compile(String name, String script, ScriptContext context, Map params) { + public T compile(String name, String script, ScriptContext context, Map params) { if (script.contains("{{") && script.contains("}}")) { throw new IllegalArgumentException("Fix your test to not rely on mustache"); } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/monitoring/test/MockPainlessScriptEngine.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/monitoring/test/MockPainlessScriptEngine.java index 2052cebe1d0e9..254542f355e5d 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/monitoring/test/MockPainlessScriptEngine.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/monitoring/test/MockPainlessScriptEngine.java @@ -11,6 +11,7 @@ import org.elasticsearch.script.ScoreScript; import org.elasticsearch.script.ScriptContext; import org.elasticsearch.script.ScriptEngine; +import org.elasticsearch.script.ScriptFactory; import java.util.Collection; import java.util.Collections; @@ -42,7 +43,7 @@ public String getType() { } @Override - public T compile(String name, String script, ScriptContext context, Map options) { + public T compile(String name, String script, ScriptContext context, Map options) { if (context.instanceClazz.equals(ScoreScript.class)) { return context.factoryClazz.cast(new MockScoreScript(p -> 0.0)); } diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/condition/WatcherConditionScript.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/condition/WatcherConditionScript.java index 1a5c8718bbd45..f5376aa424692 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/condition/WatcherConditionScript.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/condition/WatcherConditionScript.java @@ -6,6 +6,7 @@ package org.elasticsearch.xpack.watcher.condition; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.xpack.core.watcher.execution.WatchExecutionContext; import org.elasticsearch.xpack.watcher.support.Variables; @@ -37,7 +38,7 @@ public Map getCtx() { return ctx; } - public interface Factory { + public interface Factory extends ScriptFactory { WatcherConditionScript newInstance(Map params, WatchExecutionContext watcherContext); } diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transform/script/WatcherTransformScript.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transform/script/WatcherTransformScript.java index 57ee1e9f35c5d..3ef1f87cd608c 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transform/script/WatcherTransformScript.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/transform/script/WatcherTransformScript.java @@ -6,6 +6,7 @@ package org.elasticsearch.xpack.watcher.transform.script; import org.elasticsearch.script.ScriptContext; +import org.elasticsearch.script.ScriptFactory; import org.elasticsearch.xpack.core.watcher.execution.WatchExecutionContext; import org.elasticsearch.xpack.core.watcher.watch.Payload; import org.elasticsearch.xpack.watcher.support.Variables; @@ -38,7 +39,7 @@ public Map getCtx() { return ctx; } - public interface Factory { + public interface Factory extends ScriptFactory { WatcherTransformScript newInstance(Map params, WatchExecutionContext watcherContext, Payload payload); }