Dates accessed from scripts should use UTC timezone

this was broken in the field data refactoring we did in 0.90, fixes #3091
This commit is contained in:
Shay Banon 2013-05-25 22:43:48 +02:00
parent 24fccc91d8
commit b4d75a50bf
3 changed files with 88 additions and 76 deletions

View File

@ -24,7 +24,7 @@ import org.apache.lucene.util.BytesRef;
/**
*/
public abstract class AtomicNumericFieldData implements AtomicFieldData<ScriptDocValues> {
private boolean isFloat;
public AtomicNumericFieldData(boolean isFloat) {
@ -39,59 +39,59 @@ public abstract class AtomicNumericFieldData implements AtomicFieldData<ScriptDo
@Override
public ScriptDocValues getScriptValues() {
if (isFloat) {
return new ScriptDocValues.NumericDouble(getDoubleValues());
return new ScriptDocValues.Doubles(getDoubleValues());
} else {
return new ScriptDocValues.NumericLong(getLongValues());
return new ScriptDocValues.Longs(getLongValues());
}
}
@Override
public BytesValues getBytesValues() {
if (isFloat) {
final DoubleValues values = getDoubleValues();
return new BytesValues(values.isMultiValued()) {
if (isFloat) {
final DoubleValues values = getDoubleValues();
return new BytesValues(values.isMultiValued()) {
@Override
public boolean hasValue(int docId) {
return values.hasValue(docId);
}
@Override
public boolean hasValue(int docId) {
return values.hasValue(docId);
}
@Override
public BytesRef getValueScratch(int docId, BytesRef ret) {
if (values.hasValue(docId)) {
ret.copyChars(Double.toString(values.getValue(docId)));
} else {
ret.length = 0;
}
return ret;
}
@Override
public BytesRef getValueScratch(int docId, BytesRef ret) {
if (values.hasValue(docId)) {
ret.copyChars(Double.toString(values.getValue(docId)));
} else {
ret.length = 0;
}
return ret;
}
@Override
public Iter getIter(int docId) {
final DoubleValues.Iter iter = values.getIter(docId);
return new BytesValues.Iter() {
private final BytesRef spare = new BytesRef();
@Override
public Iter getIter(int docId) {
final DoubleValues.Iter iter = values.getIter(docId);
return new BytesValues.Iter() {
private final BytesRef spare = new BytesRef();
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public BytesRef next() {
spare.copyChars(Double.toString(iter.next()));
return spare;
}
@Override
public BytesRef next() {
spare.copyChars(Double.toString(iter.next()));
return spare;
}
@Override
public int hash() {
return spare.hashCode();
}
@Override
public int hash() {
return spare.hashCode();
}
};
}
};
} else {
};
}
};
} else {
final LongValues values = getLongValues();
return new BytesValues(values.isMultiValued()) {
@ -135,7 +135,7 @@ public abstract class AtomicNumericFieldData implements AtomicFieldData<ScriptDo
};
}
};
}
}
}
@Override

View File

@ -19,14 +19,7 @@
package org.elasticsearch.index.fielddata;
import java.util.Collections;
import java.util.List;
import org.apache.lucene.util.ArrayUtil;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.CharsRef;
import org.apache.lucene.util.RamUsageEstimator;
import org.apache.lucene.util.UnicodeUtil;
import org.apache.lucene.util.*;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
@ -34,8 +27,12 @@ import org.elasticsearch.common.util.SlicedDoubleList;
import org.elasticsearch.common.util.SlicedLongList;
import org.elasticsearch.common.util.SlicedObjectList;
import org.elasticsearch.index.fielddata.BytesValues.Iter;
import org.joda.time.DateTimeZone;
import org.joda.time.MutableDateTime;
import java.util.Collections;
import java.util.List;
/**
* Script level doc values, the assumption is that any implementation will implement a <code>getValue</code>
* and a <code>getValues</code> that return the relevant type that then can be used in scripts.
@ -53,7 +50,7 @@ public abstract class ScriptDocValues {
}
public abstract boolean isEmpty();
public abstract List<?> getValues();
public static class Empty extends ScriptDocValues {
@ -68,7 +65,7 @@ public abstract class ScriptDocValues {
@Override
public List<?> getValues() {
return Collections.emptyList();
return Collections.emptyList();
}
}
@ -109,15 +106,15 @@ public abstract class ScriptDocValues {
}
return null;
}
public List<String> getValues() {
if (!listLoaded) {
list.offset = 0;
list.length = 0;
Iter iter = values.getIter(docId);
while(iter.hasNext()) {
while (iter.hasNext()) {
BytesRef next = iter.next();
list.grow(list.length+1);
list.grow(list.length + 1);
UnicodeUtil.UTF8toUTF16(next, spare);
list.values[list.length++] = spare.toString();
}
@ -129,14 +126,13 @@ public abstract class ScriptDocValues {
}
public static class NumericLong extends ScriptDocValues {
public static class Longs extends ScriptDocValues {
private final LongValues values;
private final MutableDateTime date = new MutableDateTime(0);
private final MutableDateTime date = new MutableDateTime(0, DateTimeZone.UTC);
private final SlicedLongList list;
public NumericLong(LongValues values) {
public Longs(LongValues values) {
this.values = values;
this.list = new SlicedLongList(values.isMultiValued() ? 10 : 1);
}
@ -149,14 +145,14 @@ public abstract class ScriptDocValues {
public long getValue() {
return values.getValue(docId);
}
public List<Long> getValues() {
if (!listLoaded) {
final LongValues.Iter iter = values.getIter(docId);
list.offset = 0;
list.length = 0;
while(iter.hasNext()) {
list.grow(list.length+1);
while (iter.hasNext()) {
list.grow(list.length + 1);
list.values[list.length++] = iter.next();
}
listLoaded = true;
@ -170,12 +166,13 @@ public abstract class ScriptDocValues {
}
}
public static class NumericDouble extends ScriptDocValues {
public static class Doubles extends ScriptDocValues {
private final DoubleValues values;
private final SlicedDoubleList list;
public NumericDouble(DoubleValues values) {
public Doubles(DoubleValues values) {
this.values = values;
this.list = new SlicedDoubleList(values.isMultiValued() ? 10 : 1);
@ -189,14 +186,14 @@ public abstract class ScriptDocValues {
public double getValue() {
return values.getValue(docId);
}
public List<Double> getValues() {
if (!listLoaded) {
final DoubleValues.Iter iter = values.getIter(docId);
list.offset = 0;
list.length = 0;
while(iter.hasNext()) {
list.grow(list.length+1);
while (iter.hasNext()) {
list.grow(list.length + 1);
list.values[list.length++] = iter.next();
}
listLoaded = true;
@ -209,7 +206,7 @@ public abstract class ScriptDocValues {
private final GeoPointValues values;
private final SlicedObjectList<GeoPoint> list;
public GeoPoints(GeoPointValues values) {
this.values = values;
list = new SlicedObjectList<GeoPoint>(values.isMultiValued() ? new GeoPoint[10] : new GeoPoint[1]) {
@ -250,7 +247,7 @@ public abstract class ScriptDocValues {
return lats;
}
public double [] getLons() {
public double[] getLons() {
List<GeoPoint> points = getValues();
double[] lons = new double[points.size()];
for (int i = 0; i < points.size(); i++) {
@ -263,19 +260,19 @@ public abstract class ScriptDocValues {
return getValue().lon();
}
public List<GeoPoint> getValues() {
if (!listLoaded) {
GeoPointValues.Iter iter = values.getIter(docId);
list.offset = 0;
list.length = 0;
while(iter.hasNext()) {
while (iter.hasNext()) {
int index = list.length;
list.grow(index+1);
GeoPoint next = iter.next();
list.grow(index + 1);
GeoPoint next = iter.next();
GeoPoint point = list.values[index];
if (point == null) {
point = list.values[index] = new GeoPoint();
point = list.values[index] = new GeoPoint();
}
point.reset(next.lat(), next.lon());
list.values[list.length++] = point;
@ -283,7 +280,7 @@ public abstract class ScriptDocValues {
listLoaded = true;
}
return list;
}
public double factorDistance(double lat, double lon) {

View File

@ -27,11 +27,13 @@ import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.index.fielddata.AtomicNumericFieldData;
import org.elasticsearch.index.fielddata.FieldDataType;
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.index.fielddata.plain.ByteArrayAtomicFieldData;
import org.elasticsearch.index.fielddata.plain.IntArrayAtomicFieldData;
import org.elasticsearch.index.fielddata.plain.LongArrayAtomicFieldData;
import org.elasticsearch.index.fielddata.plain.ShortArrayAtomicFieldData;
import org.elasticsearch.index.mapper.FieldMapper;
import org.joda.time.DateTimeZone;
import org.testng.annotations.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@ -124,6 +126,19 @@ public class LongFieldDataTests extends NumericFieldDataTests {
assertThat(fieldData.getLongValues().getValue(1), equalTo((long) Integer.MIN_VALUE - 1l));
}
@Test
public void testDateScripts() throws Exception {
fillSingleValueAllSet();
IndexNumericFieldData indexFieldData = getForField("value");
AtomicNumericFieldData fieldData = indexFieldData.load(refreshReader());
ScriptDocValues.Longs scriptValues = (ScriptDocValues.Longs) fieldData.getScriptValues();
scriptValues.setNextDocId(0);
assertThat(scriptValues.getValue(), equalTo(2l));
assertThat(scriptValues.getDate().getMillis(), equalTo(2l));
assertThat(scriptValues.getDate().getZone(), equalTo(DateTimeZone.UTC));
}
@Override
protected void fillSingleValueAllSet() throws Exception {
Document d = new Document();