diff --git a/src/main/java/org/elasticsearch/search/aggregations/support/numeric/ScriptDoubleValues.java b/src/main/java/org/elasticsearch/search/aggregations/support/numeric/ScriptDoubleValues.java index bee2942c28c..907daf8fc94 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/support/numeric/ScriptDoubleValues.java +++ b/src/main/java/org/elasticsearch/search/aggregations/support/numeric/ScriptDoubleValues.java @@ -36,7 +36,7 @@ public class ScriptDoubleValues extends DoubleValues implements ScriptValues { final SearchScript script; private Object value; - private double[] values = new double[4]; + private double[] values = new double[1]; private int valueCount; private int valueOffset; @@ -76,6 +76,7 @@ public class ScriptDoubleValues extends DoubleValues implements ScriptValues { else if (value instanceof Collection) { valueCount = ((Collection) value).size(); + values = ArrayUtil.grow(values, valueCount); int i = 0; for (Iterator it = ((Collection) value).iterator(); it.hasNext(); ++i) { values[i] = ((Number) it.next()).doubleValue(); diff --git a/src/main/java/org/elasticsearch/search/aggregations/support/numeric/ScriptLongValues.java b/src/main/java/org/elasticsearch/search/aggregations/support/numeric/ScriptLongValues.java index 078d1712b17..373c2864556 100644 --- a/src/main/java/org/elasticsearch/search/aggregations/support/numeric/ScriptLongValues.java +++ b/src/main/java/org/elasticsearch/search/aggregations/support/numeric/ScriptLongValues.java @@ -36,7 +36,7 @@ public class ScriptLongValues extends LongValues implements ScriptValues { final SearchScript script; private Object value; - private long[] values = new long[4]; + private long[] values = new long[1]; private int valueCount; private int valueOffset; @@ -69,12 +69,13 @@ public class ScriptLongValues extends LongValues implements ScriptValues { valueCount = Array.getLength(value); values = ArrayUtil.grow(values, valueCount); for (int i = 0; i < valueCount; ++i) { - values[i] = ((Number) Array.get(value, i++)).longValue(); + values[i] = ((Number) Array.get(value, i)).longValue(); } } else if (value instanceof Collection) { valueCount = ((Collection) value).size(); + values = ArrayUtil.grow(values, valueCount); int i = 0; for (Iterator it = ((Collection) value).iterator(); it.hasNext(); ++i) { values[i] = ((Number) it.next()).longValue(); diff --git a/src/test/java/org/elasticsearch/search/aggregations/support/ScriptValuesTests.java b/src/test/java/org/elasticsearch/search/aggregations/support/ScriptValuesTests.java new file mode 100644 index 00000000000..b14dd6fa73b --- /dev/null +++ b/src/test/java/org/elasticsearch/search/aggregations/support/ScriptValuesTests.java @@ -0,0 +1,162 @@ +/* + * 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.search.aggregations.support; + +import com.carrotsearch.randomizedtesting.generators.RandomStrings; +import org.apache.lucene.index.AtomicReaderContext; +import org.apache.lucene.search.Scorer; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.script.SearchScript; +import org.elasticsearch.search.aggregations.support.bytes.ScriptBytesValues; +import org.elasticsearch.search.aggregations.support.numeric.ScriptDoubleValues; +import org.elasticsearch.search.aggregations.support.numeric.ScriptLongValues; +import org.elasticsearch.test.ElasticsearchTestCase; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Map; + +public class ScriptValuesTests extends ElasticsearchTestCase { + + private static class FakeSearchScript implements SearchScript { + + private final Object[][] values; + int index; + + FakeSearchScript(Object[][] values) { + this.values = values; + index = -1; + } + + @Override + public void setNextVar(String name, Object value) { + } + + @Override + public Object run() { + // Script values are supposed to support null, single values, arrays and collections + final Object[] values = this.values[index]; + if (values.length <= 1 && randomBoolean()) { + return values.length == 0 ? null : values[0]; + } + return randomBoolean() ? values : Arrays.asList(values); + } + + @Override + public Object unwrap(Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public void setNextReader(AtomicReaderContext reader) { + } + + @Override + public void setScorer(Scorer scorer) { + } + + @Override + public void setNextDocId(int doc) { + index = doc; + } + + @Override + public void setNextSource(Map source) { + } + + @Override + public void setNextScore(float score) { + } + + @Override + public float runAsFloat() { + throw new UnsupportedOperationException(); + } + + @Override + public long runAsLong() { + throw new UnsupportedOperationException(); + } + + @Override + public double runAsDouble() { + throw new UnsupportedOperationException(); + } + + } + + @Test + public void longs() { + final Object[][] values = new Long[randomInt(10)][]; + for (int i = 0; i < values.length; ++i) { + values[i] = new Long[randomInt(8)]; + for (int j = 0; j < values[i].length; ++j) { + values[i][j] = randomLong(); + } + } + FakeSearchScript script = new FakeSearchScript(values); + ScriptLongValues scriptValues = new ScriptLongValues(script); + for (int i = 0; i < values.length; ++i) { + assertEquals(values[i].length, scriptValues.setDocument(i)); + for (int j = 0; j < values[i].length; ++j) { + assertEquals(values[i][j], scriptValues.nextValue()); + } + } + } + + @Test + public void doubles() { + final Object[][] values = new Double[randomInt(10)][]; + for (int i = 0; i < values.length; ++i) { + values[i] = new Double[randomInt(8)]; + for (int j = 0; j < values[i].length; ++j) { + values[i][j] = randomDouble(); + } + } + FakeSearchScript script = new FakeSearchScript(values); + ScriptDoubleValues scriptValues = new ScriptDoubleValues(script); + for (int i = 0; i < values.length; ++i) { + assertEquals(values[i].length, scriptValues.setDocument(i)); + for (int j = 0; j < values[i].length; ++j) { + assertEquals(values[i][j], scriptValues.nextValue()); + } + } + } + + @Test + public void bytes() { + final String[][] values = new String[randomInt(10)][]; + for (int i = 0; i < values.length; ++i) { + values[i] = new String[randomInt(8)]; + for (int j = 0; j < values[i].length; ++j) { + values[i][j] = RandomStrings.randomAsciiOfLength(getRandom(), 5); + } + } + FakeSearchScript script = new FakeSearchScript(values); + ScriptBytesValues scriptValues = new ScriptBytesValues(script); + for (int i = 0; i < values.length; ++i) { + assertEquals(values[i].length, scriptValues.setDocument(i)); + for (int j = 0; j < values[i].length; ++j) { + assertEquals(new BytesRef(values[i][j]), scriptValues.nextValue()); + } + } + } + +}