Allow scripts to return more than 4 values in aggregations.
A missing call to ArrayUtil.grow prevented the array that stores the values from growing in case the number of values returned by the script was higher than the original size of the array. Close #5414
This commit is contained in:
parent
2aaf81f8ef
commit
b7de1becf4
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<String, Object> 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue