From b314186cf17c5b0eac1baa16bc1431f77121d103 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Sun, 10 Oct 2021 15:39:59 -0700 Subject: [PATCH 1/7] start to change painless fields api from java type to mapped type --- .../index/fielddata/LeafFieldData.java | 9 + .../index/fielddata/ScriptDocValues.java | 128 +---- .../index/mapper/IpFieldMapper.java | 6 - .../elasticsearch/script/DocBasedScript.java | 2 +- .../script/DocValuesDocReader.java | 29 +- .../script/field/BigIntegerField.java | 100 ---- .../script/field/BooleanField.java | 58 -- .../script/field/BytesRefField.java | 20 - .../elasticsearch/script/field/Converter.java | 31 -- .../script/field/DateMillisField.java | 55 -- .../script/field/DateNanosField.java | 61 --- .../script/field/DelegatingFieldValues.java | 31 -- .../{IpField.java => DocValuesField.java} | 9 +- .../script/field/DoubleField.java | 81 --- .../script/field/EmptyField.java | 22 +- .../org/elasticsearch/script/field/Field.java | 113 +--- .../script/field/FieldValues.java | 36 -- .../script/field/GeoPointField.java | 20 - .../script/field/InvalidConversion.java | 31 -- .../elasticsearch/script/field/LongField.java | 105 ---- .../script/field/StringField.java | 86 --- .../script/field/VersionField.java | 18 - .../search/lookup/LeafDocLookup.java | 33 ++ .../query/SearchExecutionContextTests.java | 5 - .../script/field/ConvertersTestBase.java | 509 ------------------ .../script/field/ConvertersTests.java | 180 ------- .../UnsignedLongDocValuesField.java | 143 +++++ .../xpack/unsignedlong/UnsignedLongField.java | 138 +---- .../UnsignedLongLeafFieldData.java | 6 + .../UnsignedLongScriptDocValues.java | 32 +- .../unsignedlong/UnsignedLongFieldTests.java | 137 ----- .../versionfield/VersionScriptDocValues.java | 11 - .../AbstractAtomicGeoShapeShapeFieldData.java | 13 - .../BinaryDenseVectorScriptDocValues.java | 5 - .../query/DenseVectorScriptDocValues.java | 6 - 35 files changed, 238 insertions(+), 2031 deletions(-) delete mode 100644 server/src/main/java/org/elasticsearch/script/field/BigIntegerField.java delete mode 100644 server/src/main/java/org/elasticsearch/script/field/BooleanField.java delete mode 100644 server/src/main/java/org/elasticsearch/script/field/BytesRefField.java delete mode 100644 server/src/main/java/org/elasticsearch/script/field/Converter.java delete mode 100644 server/src/main/java/org/elasticsearch/script/field/DateMillisField.java delete mode 100644 server/src/main/java/org/elasticsearch/script/field/DateNanosField.java delete mode 100644 server/src/main/java/org/elasticsearch/script/field/DelegatingFieldValues.java rename server/src/main/java/org/elasticsearch/script/field/{IpField.java => DocValuesField.java} (69%) delete mode 100644 server/src/main/java/org/elasticsearch/script/field/DoubleField.java delete mode 100644 server/src/main/java/org/elasticsearch/script/field/FieldValues.java delete mode 100644 server/src/main/java/org/elasticsearch/script/field/GeoPointField.java delete mode 100644 server/src/main/java/org/elasticsearch/script/field/InvalidConversion.java delete mode 100644 server/src/main/java/org/elasticsearch/script/field/LongField.java delete mode 100644 server/src/main/java/org/elasticsearch/script/field/StringField.java delete mode 100644 server/src/main/java/org/elasticsearch/script/field/VersionField.java delete mode 100644 server/src/test/java/org/elasticsearch/script/field/ConvertersTestBase.java delete mode 100644 server/src/test/java/org/elasticsearch/script/field/ConvertersTests.java create mode 100644 x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongDocValuesField.java delete mode 100644 x-pack/plugin/mapper-unsigned-long/src/test/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongFieldTests.java diff --git a/server/src/main/java/org/elasticsearch/index/fielddata/LeafFieldData.java b/server/src/main/java/org/elasticsearch/index/fielddata/LeafFieldData.java index d692f24a14e4a..f537e61ed8613 100644 --- a/server/src/main/java/org/elasticsearch/index/fielddata/LeafFieldData.java +++ b/server/src/main/java/org/elasticsearch/index/fielddata/LeafFieldData.java @@ -10,6 +10,8 @@ import org.apache.lucene.util.Accountable; import org.elasticsearch.core.Releasable; +import org.elasticsearch.script.field.DocValuesField; +import org.elasticsearch.script.field.Field; import org.elasticsearch.search.DocValueFormat; import java.io.IOException; @@ -24,6 +26,13 @@ public interface LeafFieldData extends Accountable, Releasable { */ ScriptDocValues getScriptValues(); + /** + * Returns an {@code Field} for use in accessing field values in scripting. + */ + default DocValuesField getScriptField() { + throw new UnsupportedOperationException(); + } + /** * Return a String representation of the values. */ diff --git a/server/src/main/java/org/elasticsearch/index/fielddata/ScriptDocValues.java b/server/src/main/java/org/elasticsearch/index/fielddata/ScriptDocValues.java index 68d9076cdf310..7fc17a274dc7e 100644 --- a/server/src/main/java/org/elasticsearch/index/fielddata/ScriptDocValues.java +++ b/server/src/main/java/org/elasticsearch/index/fielddata/ScriptDocValues.java @@ -17,17 +17,6 @@ import org.elasticsearch.common.geo.GeoUtils; import org.elasticsearch.common.time.DateUtils; import org.elasticsearch.geometry.utils.Geohash; -import org.elasticsearch.script.field.BooleanField; -import org.elasticsearch.script.field.BytesRefField; -import org.elasticsearch.script.field.DateMillisField; -import org.elasticsearch.script.field.DateNanosField; -import org.elasticsearch.script.field.DoubleField; -import org.elasticsearch.script.field.Field; -import org.elasticsearch.script.field.FieldValues; -import org.elasticsearch.script.field.GeoPointField; -import org.elasticsearch.script.field.InvalidConversion; -import org.elasticsearch.script.field.LongField; -import org.elasticsearch.script.field.StringField; import java.io.IOException; import java.time.Instant; @@ -47,7 +36,7 @@ * return as a single {@link ScriptDocValues} instance can be reused to return * values form multiple documents. */ -public abstract class ScriptDocValues extends AbstractList implements FieldValues { +public abstract class ScriptDocValues extends AbstractList { /** * Set the current doc ID. @@ -80,24 +69,6 @@ public final void sort(Comparator c) { throw new UnsupportedOperationException("doc values are unmodifiable"); } - public abstract Field toField(String fieldName); - - public List getValues() { - return this; - } - - public T getNonPrimitiveValue() { - return get(0); - } - - public long getLongValue() { - throw new InvalidConversion(this.getClass(), long.class); - } - - public double getDoubleValue() { - throw new InvalidConversion(this.getClass(), double.class); - } - protected void throwIfEmpty() { if (size() == 0) { throw new IllegalStateException("A document doesn't have a value for a field! " + @@ -152,23 +123,6 @@ public Long get(int index) { public int size() { return count; } - - @Override - public long getLongValue() { - throwIfEmpty(); - return values[0]; - } - - @Override - public double getDoubleValue() { - throwIfEmpty(); - return values[0]; - } - - @Override - public Field toField(String fieldName) { - return new LongField(fieldName, this); - } } public static final class Dates extends ScriptDocValues { @@ -243,28 +197,6 @@ void refreshArray() throws IOException { } } } - - @Override - public long getLongValue() { - throwIfEmpty(); - if (isNanos) { - return DateNanosField.toLong(dates[0]); - } - return DateMillisField.toLong(dates[0]); - } - - @Override - public double getDoubleValue() { - return getLongValue(); - } - - @Override - public Field toField(String fieldName) { - if (isNanos) { - return new DateNanosField(fieldName, this); - } - return new DateMillisField(fieldName, this); - } } public static final class Doubles extends ScriptDocValues { @@ -319,22 +251,6 @@ public Double get(int index) { public int size() { return count; } - - @Override - public long getLongValue() { - return (long) getDoubleValue(); - } - - @Override - public double getDoubleValue() { - throwIfEmpty(); - return values[0]; - } - - @Override - public Field toField(String fieldName) { - return new DoubleField(fieldName, this); - } } public abstract static class Geometry extends ScriptDocValues { @@ -525,11 +441,6 @@ public double getMercatorHeight() { public GeoBoundingBox getBoundingBox() { return size() == 0 ? null : boundingBox; } - - @Override - public Field toField(String fieldName) { - return new GeoPointField(fieldName, this); - } } public static final class Booleans extends ScriptDocValues { @@ -589,23 +500,6 @@ private static boolean[] grow(boolean[] array, int minSize) { } else return array; } - - @Override - public long getLongValue() { - throwIfEmpty(); - return BooleanField.toLong(values[0]); - } - - @Override - public double getDoubleValue() { - throwIfEmpty(); - return BooleanField.toDouble(values[0]); - } - - @Override - public Field toField(String fieldName) { - return new BooleanField(fieldName, this); - } } abstract static class BinaryScriptDocValues extends ScriptDocValues { @@ -678,21 +572,6 @@ protected String bytesToString(BytesRef bytes) { public final String getValue() { return get(0); } - - @Override - public long getLongValue() { - return Long.parseLong(get(0)); - } - - @Override - public double getDoubleValue() { - return Double.parseDouble(get(0)); - } - - @Override - public Field toField(String fieldName) { - return new StringField(fieldName, this); - } } public static final class BytesRefs extends BinaryScriptDocValues { @@ -718,10 +597,5 @@ public BytesRef get(int index) { public BytesRef getValue() { return get(0); } - - @Override - public Field toField(String fieldName) { - return new BytesRefField(fieldName, this); - } } } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/IpFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/IpFieldMapper.java index df11c09735c48..63b048aa1be35 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/IpFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/IpFieldMapper.java @@ -32,7 +32,6 @@ import org.elasticsearch.script.IpFieldScript; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptCompiler; -import org.elasticsearch.script.field.IpField; import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.aggregations.support.CoreValuesSourceType; import org.elasticsearch.search.lookup.FieldValues; @@ -361,11 +360,6 @@ public String get(int index) { public int size() { return count; } - - @Override - public org.elasticsearch.script.field.Field toField(String fieldName) { - return new IpField(fieldName, this); - } } @Override diff --git a/server/src/main/java/org/elasticsearch/script/DocBasedScript.java b/server/src/main/java/org/elasticsearch/script/DocBasedScript.java index 8ef8104652aed..9eb2fb4fab960 100644 --- a/server/src/main/java/org/elasticsearch/script/DocBasedScript.java +++ b/server/src/main/java/org/elasticsearch/script/DocBasedScript.java @@ -25,7 +25,7 @@ public DocBasedScript(DocReader docReader) { public Field field(String fieldName) { if (docReader == null) { - return new EmptyField<>(fieldName); + return new EmptyField<>(); } return docReader.field(fieldName); } diff --git a/server/src/main/java/org/elasticsearch/script/DocValuesDocReader.java b/server/src/main/java/org/elasticsearch/script/DocValuesDocReader.java index ba6f270b181e5..e045b83596ac3 100644 --- a/server/src/main/java/org/elasticsearch/script/DocValuesDocReader.java +++ b/server/src/main/java/org/elasticsearch/script/DocValuesDocReader.java @@ -12,6 +12,7 @@ import org.elasticsearch.index.fielddata.ScriptDocValues; import org.elasticsearch.script.field.EmptyField; import org.elasticsearch.script.field.Field; +import org.elasticsearch.search.lookup.LeafDocLookup; import org.elasticsearch.search.lookup.LeafSearchLookup; import org.elasticsearch.search.lookup.SearchLookup; @@ -22,28 +23,30 @@ * Provide access to DocValues for script {@code field} api and {@code doc} API. */ public class DocValuesDocReader implements DocReader, LeafReaderContextSupplier { - /** A leaf lookup for the bound segment this proxy will operate on. */ - protected LeafSearchLookup leafLookup; + + protected final SearchLookup searchLookup; // provide access to the leaf context reader for expressions protected final LeafReaderContext leafReaderContext; - protected final SearchLookup lookup; + /** A leaf lookup for the bound segment this proxy will operate on. */ + protected LeafSearchLookup leafSearchLookup; - public DocValuesDocReader(SearchLookup lookup, LeafReaderContext leafContext) { - this.lookup = lookup; + public DocValuesDocReader(SearchLookup searchLookup, LeafReaderContext leafContext) { + this.searchLookup = searchLookup; this.leafReaderContext = leafContext; - this.leafLookup = lookup.getLeafSearchLookup(leafReaderContext); + this.leafSearchLookup = searchLookup.getLeafSearchLookup(leafReaderContext); } @Override public Field field(String fieldName) { - Map> doc = leafLookup.doc(); + LeafDocLookup leafDocLookup = leafSearchLookup.doc(); - if (doc.containsKey(fieldName) == false) { - return new EmptyField<>(fieldName); + if (leafDocLookup.containsKey(fieldName) == false) { + return new EmptyField<>(); } - return doc.get(fieldName).toField(fieldName); + + return leafDocLookup.getScriptField(fieldName); } @@ -54,17 +57,17 @@ public Stream> fields(String fieldGlob) { @Override public void setDocument(int docID) { - leafLookup.setDocument(docID); + leafSearchLookup.setDocument(docID); } @Override public Map docAsMap() { - return leafLookup.asMap(); + return leafSearchLookup.asMap(); } @Override public Map> doc() { - return leafLookup.doc(); + return leafSearchLookup.doc(); } @Override diff --git a/server/src/main/java/org/elasticsearch/script/field/BigIntegerField.java b/server/src/main/java/org/elasticsearch/script/field/BigIntegerField.java deleted file mode 100644 index 5eab119f155de..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/BigIntegerField.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -import java.util.List; -import java.util.stream.Collectors; - -public class BigIntegerField extends Field { - - /* ---- Conversion Class From Other Fields ----*/ - - /** - * Convert to a {@link BigIntegerField} from Long, Double or String Fields. - * Longs and Doubles are wrapped as BigIntegers. - * Strings are parsed as either Longs or Doubles and wrapped in a BigInteger. - */ - public static final Converter BigInteger; - - static { - BigInteger = new Converter() { - @Override - public BigIntegerField convert(Field sourceField) { - if (sourceField instanceof LongField) { - return LongField.toBigIntegerField((LongField) sourceField); - } - - if (sourceField instanceof DoubleField) { - return DoubleField.toBigIntegerField((DoubleField) sourceField); - } - - if (sourceField instanceof StringField) { - return StringField.toBigIntegerField((StringField) sourceField); - } - - if (sourceField instanceof DateMillisField) { - return LongField.toBigIntegerField(DateMillisField.toLongField((DateMillisField) sourceField)); - } - - if (sourceField instanceof DateNanosField) { - return LongField.toBigIntegerField(DateNanosField.toLongField((DateNanosField) sourceField)); - } - - if (sourceField instanceof BooleanField) { - return LongField.toBigIntegerField(BooleanField.toLongField((BooleanField) sourceField)); - } - - throw new InvalidConversion(sourceField.getClass(), getFieldClass()); - } - - @Override - public Class getFieldClass() { - return BigIntegerField.class; - } - - @Override - public Class getTargetClass() { - return java.math.BigInteger.class; - } - }; - } - - /* ---- Conversion Helpers To Other Fields ---- */ - - public static LongField toLongField(BigIntegerField sourceField) { - FieldValues fv = sourceField.getFieldValues(); - return new LongField(sourceField.getName(), new DelegatingFieldValues(fv) { - @Override - public List getValues() { - return values.getValues().stream().map(java.math.BigInteger::longValue).collect(Collectors.toList()); - } - - @Override - public Long getNonPrimitiveValue() { - return values.getNonPrimitiveValue().longValue(); - } - - @Override - public long getLongValue() { - return values.getLongValue(); - } - - @Override - public double getDoubleValue() { - return values.getDoubleValue(); - } - }); - } - - /* ---- Big Integer Field Members ---- */ - - public BigIntegerField(String name, FieldValues values) { - super(name, values); - } -} diff --git a/server/src/main/java/org/elasticsearch/script/field/BooleanField.java b/server/src/main/java/org/elasticsearch/script/field/BooleanField.java deleted file mode 100644 index eec6dc453df2a..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/BooleanField.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -import java.util.List; -import java.util.stream.Collectors; - -public class BooleanField extends Field { - - /* ---- Conversion Helpers To Other Fields ---- */ - - public static LongField toLongField(BooleanField sourceField) { - FieldValues fv = sourceField.getFieldValues(); - return new LongField(sourceField.getName(), new DelegatingFieldValues(fv) { - @Override - public List getValues() { - return values.getValues().stream().map(BooleanField::toLong).collect(Collectors.toList()); - } - - @Override - public Long getNonPrimitiveValue() { - return toLong(values.getNonPrimitiveValue()); - } - - @Override - public long getLongValue() { - return values.getLongValue(); - } - - @Override - public double getDoubleValue() { - return (long)values.getDoubleValue(); - } - }); - } - - /* ---- Conversion Helpers To Other Types ---- */ - - public static long toLong(boolean bool) { - return bool ? 1L : 0L; - } - - public static double toDouble(boolean bool) { - return bool ? 1.0 : 0.0; - } - - /* ---- Boolean Field Members ---- */ - - public BooleanField(String name, FieldValues values) { - super(name, values); - } -} diff --git a/server/src/main/java/org/elasticsearch/script/field/BytesRefField.java b/server/src/main/java/org/elasticsearch/script/field/BytesRefField.java deleted file mode 100644 index 952d78b613d70..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/BytesRefField.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -import org.apache.lucene.util.BytesRef; - -public class BytesRefField extends Field { - - /* ---- Bytes Ref Field Members ---- */ - - public BytesRefField(String name, FieldValues values) { - super(name, values); - } -} diff --git a/server/src/main/java/org/elasticsearch/script/field/Converter.java b/server/src/main/java/org/elasticsearch/script/field/Converter.java deleted file mode 100644 index 8cbd71d72bfab..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/Converter.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -/** - * Converts between one scripting {@link Field} type and another, {@code FC}, with a different underlying - * value type, {@code TC}. - */ -public interface Converter> { - /** - * Convert {@code sourceField} to a new field-type. Conversions come from user scripts so {@code covert} may - * be called on a {@link Field}'s own type. - */ - FC convert(Field sourceField); - - /** - * The destination {@link Field} class. - */ - Class getFieldClass(); - - /** - * The target value type. - */ - Class getTargetClass(); -} diff --git a/server/src/main/java/org/elasticsearch/script/field/DateMillisField.java b/server/src/main/java/org/elasticsearch/script/field/DateMillisField.java deleted file mode 100644 index a8f1ccd1dd2d7..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/DateMillisField.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -import java.time.ZonedDateTime; -import java.util.List; -import java.util.stream.Collectors; - -public class DateMillisField extends Field { - - /* ---- Conversion Helpers To Other Fields ---- */ - - public static LongField toLongField(DateMillisField sourceField) { - FieldValues fv = sourceField.getFieldValues(); - return new LongField(sourceField.getName(), new DelegatingFieldValues(fv) { - @Override - public List getValues() { - return values.getValues().stream().map(dt -> dt.toInstant().toEpochMilli()).collect(Collectors.toList()); - } - - @Override - public Long getNonPrimitiveValue() { - return toLong(values.getNonPrimitiveValue()); - } - - @Override - public long getLongValue() { - return values.getLongValue(); - } - - @Override - public double getDoubleValue() { - return (long)values.getDoubleValue(); - } - }); - } - - /* ---- Conversion Helpers To Other Types ---- */ - - public static long toLong(ZonedDateTime dt) { - return dt.toInstant().toEpochMilli(); - } - - /* ---- DateMillis Field Members ---- */ - - public DateMillisField(String name, FieldValues values) { - super(name, values); - } -} diff --git a/server/src/main/java/org/elasticsearch/script/field/DateNanosField.java b/server/src/main/java/org/elasticsearch/script/field/DateNanosField.java deleted file mode 100644 index 23bc4422f7053..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/DateNanosField.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -import java.time.Instant; -import java.time.ZonedDateTime; -import java.time.temporal.ChronoUnit; -import java.util.List; -import java.util.stream.Collectors; - -public class DateNanosField extends Field { - - /* ---- Conversion Helpers To Other Fields ---- */ - - public static LongField toLongField(DateNanosField sourceField) { - FieldValues fv = sourceField.getFieldValues(); - return new LongField(sourceField.getName(), new DelegatingFieldValues(fv) { - protected long nanoLong(ZonedDateTime dt) { - return ChronoUnit.NANOS.between(Instant.EPOCH, dt.toInstant()); - } - - @Override - public List getValues() { - return values.getValues().stream().map(this::nanoLong).collect(Collectors.toList()); - } - - @Override - public Long getNonPrimitiveValue() { - return toLong(values.getNonPrimitiveValue()); - } - - @Override - public long getLongValue() { - return values.getLongValue(); - } - - @Override - public double getDoubleValue() { - return (long)values.getDoubleValue(); - } - }); - } - - /* ---- Conversion Helpers To Other Types ---- */ - - public static long toLong(ZonedDateTime dt) { - return ChronoUnit.NANOS.between(Instant.EPOCH, dt.toInstant()); - } - - /* ---- DateNanos Field Members ---- */ - - public DateNanosField(String name, FieldValues values) { - super(name, values); - } -} diff --git a/server/src/main/java/org/elasticsearch/script/field/DelegatingFieldValues.java b/server/src/main/java/org/elasticsearch/script/field/DelegatingFieldValues.java deleted file mode 100644 index fce2bd7a486c5..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/DelegatingFieldValues.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -/** - * Helper for creating {@link Converter} classes which delegates all un-overridden methods to the underlying - * {@link FieldValues}. - */ -public abstract class DelegatingFieldValues implements FieldValues { - protected FieldValues values; - - public DelegatingFieldValues(FieldValues values) { - this.values = values; - } - - @Override - public boolean isEmpty() { - return values.isEmpty(); - } - - @Override - public int size() { - return values.size(); - } -} diff --git a/server/src/main/java/org/elasticsearch/script/field/IpField.java b/server/src/main/java/org/elasticsearch/script/field/DocValuesField.java similarity index 69% rename from server/src/main/java/org/elasticsearch/script/field/IpField.java rename to server/src/main/java/org/elasticsearch/script/field/DocValuesField.java index cfa2425ca51cf..9a48c3aa8f871 100644 --- a/server/src/main/java/org/elasticsearch/script/field/IpField.java +++ b/server/src/main/java/org/elasticsearch/script/field/DocValuesField.java @@ -8,11 +8,10 @@ package org.elasticsearch.script.field; -public class IpField extends Field { +import java.io.IOException; - /* ---- Ip Field Members ---- */ +public interface DocValuesField extends Field { - public IpField(String name, FieldValues values) { - super(name, values); - } + /** Set the current document ID. */ + void setNextDocId(int docId) throws IOException; } diff --git a/server/src/main/java/org/elasticsearch/script/field/DoubleField.java b/server/src/main/java/org/elasticsearch/script/field/DoubleField.java deleted file mode 100644 index 75411c890dc0c..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/DoubleField.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.List; -import java.util.stream.Collectors; - -public class DoubleField extends Field { - - /* ---- Conversion Helpers To Other Fields ---- */ - - public static BigIntegerField toBigIntegerField(DoubleField sourceField) { - FieldValues fv = sourceField.getFieldValues(); - return new BigIntegerField(sourceField.getName(), new DelegatingFieldValues(fv) { - @Override - public List getValues() { - return values.getValues().stream().map(DoubleField::toBigInteger).collect(Collectors.toList()); - } - - @Override - public BigInteger getNonPrimitiveValue() { - return toBigInteger(values.getNonPrimitiveValue()); - } - - @Override - public long getLongValue() { - return values.getLongValue(); - } - - @Override - public double getDoubleValue() { - return toBigInteger(values.getDoubleValue()).doubleValue(); - } - }); - } - - public static LongField toLongField(DoubleField sourceField) { - FieldValues fv = sourceField.getFieldValues(); - return new LongField(sourceField.getName(), new DelegatingFieldValues(fv) { - @Override - public List getValues() { - return values.getValues().stream().map(Double::longValue).collect(Collectors.toList()); - } - - @Override - public Long getNonPrimitiveValue() { - return values.getNonPrimitiveValue().longValue(); - } - - @Override - public long getLongValue() { - return values.getLongValue(); - } - - @Override - public double getDoubleValue() { - return (long)values.getDoubleValue(); - } - }); - } - - /* ---- Conversion Helpers To Other Types ---- */ - - public static BigInteger toBigInteger(double dbl) { - return BigDecimal.valueOf(dbl).toBigInteger(); - } - - /* ---- Double Field Members ---- */ - - public DoubleField(String name, FieldValues values) { - super(name, values); - } -} diff --git a/server/src/main/java/org/elasticsearch/script/field/EmptyField.java b/server/src/main/java/org/elasticsearch/script/field/EmptyField.java index 9d69b14ccf100..e76b4a5d26ef8 100644 --- a/server/src/main/java/org/elasticsearch/script/field/EmptyField.java +++ b/server/src/main/java/org/elasticsearch/script/field/EmptyField.java @@ -14,11 +14,7 @@ /** * Script field with no mapping, always returns {@code defaultValue}. */ -public class EmptyField extends Field { - - public EmptyField(String name) { - super(name, null); - } +public class EmptyField implements Field { @Override public boolean isEmpty() { @@ -26,14 +22,13 @@ public boolean isEmpty() { } @Override - public List getValues() { - return Collections.emptyList(); + public int size() { + return 0; } @Override - public > Field convert(Converter converter) { - // new object created to ensure EmptyField - return new EmptyField<>(name); + public List getValues() { + return Collections.emptyList(); } @Override @@ -42,12 +37,7 @@ public T getValue(T defaultValue) { } @Override - public double getDouble(double defaultValue) { - return defaultValue; - } - - @Override - public long getLong(long defaultValue) { + public T getValue(int index, T defaultValue) { return defaultValue; } } diff --git a/server/src/main/java/org/elasticsearch/script/field/Field.java b/server/src/main/java/org/elasticsearch/script/field/Field.java index be56009d36dbb..4e8398c598ad2 100644 --- a/server/src/main/java/org/elasticsearch/script/field/Field.java +++ b/server/src/main/java/org/elasticsearch/script/field/Field.java @@ -11,112 +11,21 @@ import java.util.List; -/** - * A field in a document accessible via scripting. In search contexts, the Field may be backed by doc values, source - * or both. In ingestion, the field may be in the source document or being added to the document. - * - * Field's methods must not throw exceptions nor return null. A Field object representing a empty or unmapped field will have - * * {@code isEmpty() == true} - * * {@code getValues().equals(Collections.emptyList())} - * * {@code getValue(defaultValue) == defaultValue} - */ -public abstract class Field { - - protected final String name; - protected final FieldValues values; - - public Field(String name, FieldValues values) { - this.name = name; - this.values = values; - } - - public String getName() { - return name; - } +/** A field in a document accessible via scripting. */ +public interface Field { - /** - * Does the field have any values? An unmapped field may have values from source - */ - public boolean isEmpty() { - return values.isEmpty(); - } + /** Returns {@code true} if this field has no values, otherwise {@code false}. */ + boolean isEmpty(); - /** - * Get all values of a multivalued field. If {@code isEmpty()} this returns an empty list - */ - public List getValues() { - return values.getValues(); - } + /** Returns the number of values this field has. */ + int size(); - /** - * Convert this {@code Field} into another {@code Field} type using a {@link Converter} of the target type. - * - * As this is called from user scripts, {@code as} may be called to convert a field into its same type, if - * so {@code this} is cast via converters {@link Converter#getFieldClass()}. - * - */ - public final > Field as(Converter converter) { - if (converter.getFieldClass().isInstance(this)) { - return converter.getFieldClass().cast(this); - } - - return convert(converter); - } - - /** - * Extensions outside the core package should override this method to implement their own conversions, calling - * the superclass of this method as a fallback. - */ - protected > Field convert(Converter converter) { - return converter.convert(this); - } - - /** - * Provide {@link Converter}s access to the underlying {@link FieldValues}, should not be exposed to scripts - */ - public FieldValues getFieldValues() { - return values; - } + /** Get all values of a multivalued field. If {@code isEmpty()} this returns an empty list. */ + List getValues(); /** Get the first value of a field, if {@code isEmpty()} return defaultValue instead */ - public T getValue(T defaultValue) { - if (isEmpty()) { - return defaultValue; - } - try { - return values.getNonPrimitiveValue(); - } catch (RuntimeException err) { - return defaultValue; - } - } - - /** - * Get the underlying value as a {@code long} unless {@link #isEmpty()}, in which case return {@code defaultValue}. - * May throw {@link InvalidConversion} if the underlying value is not representable as a {@code long}. - */ - public long getLong(long defaultValue) { - if (isEmpty()) { - return defaultValue; - } - try { - return values.getLongValue(); - } catch (RuntimeException err) { - return defaultValue; - } - } + T getValue(T defaultValue); - /** - * Get the underlying value as a {@code double} unless {@link #isEmpty()}, in which case return {@code defaultValue}. - * May throw {@link InvalidConversion} if the underlying value is not representable as a {@code double}. - */ - public double getDouble(double defaultValue) { - if (isEmpty()) { - return defaultValue; - } - try { - return values.getDoubleValue(); - } catch (RuntimeException err) { - return defaultValue; - } - } + /** Get the value of a field as the specified index. */ + T getValue(int index, T defaultValue); } diff --git a/server/src/main/java/org/elasticsearch/script/field/FieldValues.java b/server/src/main/java/org/elasticsearch/script/field/FieldValues.java deleted file mode 100644 index 9a69698587aba..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/FieldValues.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -import java.util.List; - -/** - * The underlying contents of a scripting Field. Implementations include - * {@link org.elasticsearch.index.fielddata.ScriptDocValues}, {@code _source}, runtime fields, or - * the converted form of the these values from a {@link Converter}. - */ -public interface FieldValues { - /** Are there any values? */ - boolean isEmpty(); - - /** How many values? */ - int size(); - - /** All underlying values. Note this boxes primitives */ - List getValues(); - - /** The first value as a subclass of {@link java.lang.Object}. Boxes primitives */ - T getNonPrimitiveValue(); - - /** The first value as a primitive long. For performance reasons, implementations should avoid intermediate boxings if possible */ - long getLongValue(); - - /** The first value as a primitive double. For performance reasons, implementations should avoid intermediate boxings if possible */ - double getDoubleValue(); -} diff --git a/server/src/main/java/org/elasticsearch/script/field/GeoPointField.java b/server/src/main/java/org/elasticsearch/script/field/GeoPointField.java deleted file mode 100644 index 650d93de2cc6f..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/GeoPointField.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -import org.elasticsearch.common.geo.GeoPoint; - -public class GeoPointField extends Field { - - /* ---- Geo Point Field Members ---- */ - - public GeoPointField(String name, FieldValues values) { - super(name, values); - } -} diff --git a/server/src/main/java/org/elasticsearch/script/field/InvalidConversion.java b/server/src/main/java/org/elasticsearch/script/field/InvalidConversion.java deleted file mode 100644 index 08f5be33254f2..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/InvalidConversion.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -/** - * A failed conversion of a script {@link Field}. Thrown by {@link Converter}s and - * {@link FieldValues#getDoubleValue()}/{@link FieldValues#getLongValue()}. - */ -public class InvalidConversion extends RuntimeException { - /** Source {@link Field} or underlying value */ - protected final Class from; - - /** Destination class or {@link Converter} */ - protected final Class converter; - - public InvalidConversion(Class from, Class converter) { - this.from = from; - this.converter = converter; - } - - @Override - public String getMessage() { - return "Cannot convert from [" + from.getSimpleName() + "] using converter [" + converter.getSimpleName() + "]"; - } -} diff --git a/server/src/main/java/org/elasticsearch/script/field/LongField.java b/server/src/main/java/org/elasticsearch/script/field/LongField.java deleted file mode 100644 index c6c3beb9f628b..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/LongField.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -import java.math.BigInteger; -import java.util.List; -import java.util.stream.Collectors; - -public class LongField extends Field { - - /* ---- Conversion Class From Other Fields ----*/ - - /** - * Convert to a {@link LongField} from Double, String, DateMillis, DateNanos, BigInteger or Boolean Fields. - * Double is cast to a Long. - * String is parsed as a Long. - * DateMillis is milliseconds since epoch. - * DateNanos is nanoseconds since epoch. - * {@link java.math.BigInteger#longValue()} is used for the BigInteger conversion. - * Boolean is {@code 1L} if {@code true}, {@code 0L} if {@code false}. - */ - public static final Converter Long; - - static { - Long = new Converter() { - @Override - public LongField convert(Field sourceField) { - if (sourceField instanceof DoubleField) { - return DoubleField.toLongField((DoubleField) sourceField); - } - - if (sourceField instanceof StringField) { - return StringField.toLongField((StringField) sourceField); - } - - if (sourceField instanceof DateMillisField) { - return DateMillisField.toLongField((DateMillisField) sourceField); - } - - if (sourceField instanceof DateNanosField) { - return DateNanosField.toLongField((DateNanosField) sourceField); - } - - if (sourceField instanceof BigIntegerField) { - return BigIntegerField.toLongField((BigIntegerField) sourceField); - } - - if (sourceField instanceof BooleanField) { - return BooleanField.toLongField((BooleanField) sourceField); - } - - throw new InvalidConversion(sourceField.getClass(), getFieldClass()); - } - - @Override - public Class getFieldClass() { - return LongField.class; - } - - @Override - public Class getTargetClass() { - return Long.class; - } - }; - } - - /* ---- Conversion Helpers To Other Fields ---- */ - - public static BigIntegerField toBigIntegerField(LongField sourceField) { - FieldValues fv = sourceField.getFieldValues(); - return new BigIntegerField(sourceField.getName(), new DelegatingFieldValues(fv) { - @Override - public List getValues() { - return values.getValues().stream().map(BigInteger::valueOf).collect(Collectors.toList()); - } - - @Override - public BigInteger getNonPrimitiveValue() { - return BigInteger.valueOf(values.getNonPrimitiveValue()); - } - - @Override - public long getLongValue() { - return values.getLongValue(); - } - - @Override - public double getDoubleValue() { - return DoubleField.toBigInteger(values.getDoubleValue()).doubleValue(); - } - }); - } - - /* ---- Long Field Members ---- */ - - public LongField(String name, FieldValues values) { - super(name, values); - } -} diff --git a/server/src/main/java/org/elasticsearch/script/field/StringField.java b/server/src/main/java/org/elasticsearch/script/field/StringField.java deleted file mode 100644 index 4a15e63aecc5f..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/StringField.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.List; -import java.util.stream.Collectors; - -public class StringField extends Field { - - /* ---- Conversion Helpers To Other Fields ---- */ - - public static BigIntegerField toBigIntegerField(StringField sourceField) { - FieldValues fv = sourceField.getFieldValues(); - return new BigIntegerField(sourceField.getName(), new DelegatingFieldValues(fv) { - @Override - public List getValues() { - // This may throw NumberFormatException, should we catch and truncate the List? (#76951) - return values.getValues().stream().map(StringField::toBigInteger).collect(Collectors.toList()); - } - - @Override - public BigInteger getNonPrimitiveValue() { - return toBigInteger(values.getNonPrimitiveValue()); - } - - @Override - public long getLongValue() { - return values.getLongValue(); - } - - @Override - public double getDoubleValue() { - return DoubleField.toBigInteger(values.getDoubleValue()).doubleValue(); - } - }); - } - - public static LongField toLongField(StringField sourceField) { - FieldValues fv = sourceField.getFieldValues(); - return new LongField(sourceField.getName(), new DelegatingFieldValues(fv) { - @Override - public List getValues() { - return values.getValues().stream().map(Long::parseLong).collect(Collectors.toList()); - } - - @Override - public Long getNonPrimitiveValue() { - return Long.parseLong(values.getNonPrimitiveValue()); - } - - @Override - public long getLongValue() { - return values.getLongValue(); - } - - @Override - public double getDoubleValue() { - return (long)values.getDoubleValue(); - } - }); - } - - /* ---- Conversion Helpers To Other Types ---- */ - - public static BigInteger toBigInteger(String str) { - try { - return new BigInteger(str); - } catch (NumberFormatException nfe) { - return new BigDecimal(str).toBigInteger(); - } - } - - /* ---- String Field Members ---- */ - - public StringField(String name, FieldValues values) { - super(name, values); - } -} diff --git a/server/src/main/java/org/elasticsearch/script/field/VersionField.java b/server/src/main/java/org/elasticsearch/script/field/VersionField.java deleted file mode 100644 index 4696fda121174..0000000000000 --- a/server/src/main/java/org/elasticsearch/script/field/VersionField.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -public class VersionField extends Field { - - /* ---- Version Field Members ---- */ - - public VersionField(String name, FieldValues values) { - super(name, values); - } -} diff --git a/server/src/main/java/org/elasticsearch/search/lookup/LeafDocLookup.java b/server/src/main/java/org/elasticsearch/search/lookup/LeafDocLookup.java index fed14ae4a4431..88ec4b7595959 100644 --- a/server/src/main/java/org/elasticsearch/search/lookup/LeafDocLookup.java +++ b/server/src/main/java/org/elasticsearch/search/lookup/LeafDocLookup.java @@ -12,6 +12,7 @@ import org.elasticsearch.index.fielddata.IndexFieldData; import org.elasticsearch.index.fielddata.ScriptDocValues; import org.elasticsearch.index.mapper.MappedFieldType; +import org.elasticsearch.script.field.DocValuesField; import java.io.IOException; import java.security.AccessController; @@ -24,6 +25,7 @@ public class LeafDocLookup implements Map> { + private final Map> localCacheScriptFieldData = new HashMap<>(4); private final Map> localCacheFieldData = new HashMap<>(4); private final Function fieldTypeLookup; private final Function> fieldDataLookup; @@ -43,6 +45,37 @@ public void setDocument(int docId) { this.docId = docId; } + public DocValuesField getScriptField(String fieldName) { + DocValuesField field = localCacheScriptFieldData.get(fieldName); + + if (field == null) { + final MappedFieldType fieldType = fieldTypeLookup.apply(fieldName); + + if (fieldType == null) { + throw new IllegalArgumentException("no field found for [" + fieldName + "] in mapping"); + } + + // Load the field data on behalf of the script. Otherwise, it would require + // additional permissions to deal with pagedbytes/ramusagestimator/etc. + field = AccessController.doPrivileged(new PrivilegedAction>() { + @Override + public DocValuesField run() { + return fieldDataLookup.apply(fieldType).load(reader).getScriptField(); + } + }); + + localCacheScriptFieldData.put(fieldName, field); + } + + try { + field.setNextDocId(docId); + } catch (IOException ioe) { + throw ExceptionsHelper.convertToElastic(ioe); + } + + return field; + } + @Override public ScriptDocValues get(Object key) { // assume its a string... diff --git a/server/src/test/java/org/elasticsearch/index/query/SearchExecutionContextTests.java b/server/src/test/java/org/elasticsearch/index/query/SearchExecutionContextTests.java index a3bfc11c74e17..3f2e6e3fbddd4 100644 --- a/server/src/test/java/org/elasticsearch/index/query/SearchExecutionContextTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/SearchExecutionContextTests.java @@ -513,11 +513,6 @@ public void setNextDocId(int docId) { leafLookup.setDocument(docId); value = runtimeDocValues.apply(leafLookup, docId); } - - @Override - public org.elasticsearch.script.field.Field toField(String fieldName) { - return new org.elasticsearch.script.field.StringField(fieldName, this); - } }; } diff --git a/server/src/test/java/org/elasticsearch/script/field/ConvertersTestBase.java b/server/src/test/java/org/elasticsearch/script/field/ConvertersTestBase.java deleted file mode 100644 index 0b1ab21b26e6b..0000000000000 --- a/server/src/test/java/org/elasticsearch/script/field/ConvertersTestBase.java +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -import org.elasticsearch.common.geo.GeoPoint; -import org.elasticsearch.test.ESTestCase; -import org.junit.Before; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.DoubleStream; -import java.util.stream.LongStream; -import java.util.stream.Stream; - -/** - * A set of the standard available field types for scripting with raw values - * contained in a test field to test conversions to other field types. - */ -public abstract class ConvertersTestBase extends ESTestCase { - - protected boolean[] rawBooleanValues; - protected FieldValues booleanFieldValues; - protected Field booleanField; - - @Before - public void setupBooleanField() { - rawBooleanValues = new boolean[] { - true, - false - }; - - booleanFieldValues = new FieldValues() { - @Override - public boolean isEmpty() { - return false; - } - - @Override - public int size() { - return rawBooleanValues.length; - } - - @Override - public List getValues() { - List values = new ArrayList<>(); - - for (boolean bool : rawBooleanValues) { - values.add(bool); - } - - return values; - } - - @Override - public Boolean getNonPrimitiveValue() { - return rawBooleanValues[0]; - } - - @Override - public long getLongValue() { - return BooleanField.toLong(rawBooleanValues[0]); - } - - @Override - public double getDoubleValue() { - return BooleanField.toDouble(rawBooleanValues[0]); - } - }; - - booleanField = new BooleanField("boolean_field", booleanFieldValues); - } - - protected long[] rawLongValues; - protected FieldValues longFieldValues; - protected Field longField; - - @Before - public void setupLongField() { - rawLongValues = new long[] { - 15, - -1, - 0, - 1, - Long.MIN_VALUE, - Long.MAX_VALUE, - Integer.MIN_VALUE, - Integer.MAX_VALUE - }; - - longFieldValues = new FieldValues() { - @Override - public boolean isEmpty() { - return false; - } - - @Override - public int size() { - return rawLongValues.length; - } - - @Override - public List getValues() { - return LongStream.of(rawLongValues).boxed().collect(Collectors.toList()); - } - - @Override - public Long getNonPrimitiveValue() { - return rawLongValues[0]; - } - - @Override - public long getLongValue() { - return rawLongValues[0]; - } - - @Override - public double getDoubleValue() { - return rawLongValues[0]; - } - }; - - longField = new LongField("long_field", longFieldValues); - } - - protected double[] rawDoubleValues; - protected FieldValues doubleFieldValues; - protected Field doubleField; - - @Before - public void setupDoubleField() { - rawDoubleValues = new double[] { - 3.456, - 0.0, - -1.0, - 1.0, - -1.5, - 1.5, - Double.MAX_VALUE, - Double.MIN_VALUE, - Float.MAX_VALUE, - Float.MIN_VALUE, - Long.MAX_VALUE, - Long.MIN_VALUE, - }; - - doubleFieldValues = new FieldValues() { - @Override - public boolean isEmpty() { - return false; - } - - @Override - public int size() { - return rawDoubleValues.length; - } - - @Override - public List getValues() { - return DoubleStream.of(rawDoubleValues).boxed().collect(Collectors.toList()); - } - - @Override - public Double getNonPrimitiveValue() { - return rawDoubleValues[0]; - } - - @Override - public long getLongValue() { - return (long)rawDoubleValues[0]; - } - - @Override - public double getDoubleValue() { - return rawDoubleValues[0]; - } - }; - - doubleField = new DoubleField("double_field", doubleFieldValues); - } - - protected BigInteger[] rawBigIntegerValues; - protected FieldValues bigIntegerFieldValues; - protected Field bigIntegerField; - - @Before - public void setupBigIntegerField() { - rawBigIntegerValues = new BigInteger[] { - BigInteger.valueOf(123), - BigDecimal.valueOf(Double.MAX_VALUE).toBigInteger(), - BigDecimal.valueOf(Double.MIN_VALUE).toBigInteger(), - BigDecimal.valueOf(Float.MAX_VALUE).toBigInteger(), - BigDecimal.valueOf(Float.MIN_VALUE).toBigInteger(), - BigInteger.valueOf(Long.MAX_VALUE), - BigInteger.valueOf(Long.MIN_VALUE), - BigInteger.ZERO, - BigInteger.ONE, - BigInteger.TWO, - BigInteger.valueOf(-1) - }; - - bigIntegerFieldValues = new FieldValues() { - @Override - public boolean isEmpty() { - return false; - } - - @Override - public int size() { - return rawBigIntegerValues.length; - } - - @Override - public List getValues() { - return Stream.of(rawBigIntegerValues).collect(Collectors.toList()); - } - - @Override - public BigInteger getNonPrimitiveValue() { - return rawBigIntegerValues[0]; - } - - @Override - public long getLongValue() { - return rawBigIntegerValues[0].longValue(); - } - - @Override - public double getDoubleValue() { - return rawBigIntegerValues[0].doubleValue(); - } - }; - - bigIntegerField = new BigIntegerField("big_integer_field", bigIntegerFieldValues); - } - - protected String[] rawStringValuesAsLongs; - protected FieldValues stringFieldValuesAsLongs; - protected Field stringFieldAsLongs; - - @Before - public void setupStringFieldAsLongs() { - rawStringValuesAsLongs = new String[] { - "72", - "0", - "-1", - "1", - ((Integer)Integer.MAX_VALUE).toString(), - ((Integer)Integer.MIN_VALUE).toString(), - ((Long)Long.MAX_VALUE).toString(), - ((Long)Long.MIN_VALUE).toString() - }; - - stringFieldValuesAsLongs = new FieldValues() { - @Override - public boolean isEmpty() { - return false; - } - - @Override - public int size() { - return rawStringValuesAsLongs.length; - } - - @Override - public List getValues() { - return Stream.of(rawStringValuesAsLongs).collect(Collectors.toList()); - } - - @Override - public String getNonPrimitiveValue() { - return rawStringValuesAsLongs[0]; - } - - @Override - public long getLongValue() { - return Long.parseLong(rawStringValuesAsLongs[0]); - } - - @Override - public double getDoubleValue() { - return Double.parseDouble(rawStringValuesAsLongs[0]); - } - }; - - stringFieldAsLongs = new StringField("string_field_as_longs", stringFieldValuesAsLongs); - } - - protected String[] rawStringValuesAsDoubles; - protected FieldValues stringFieldValuesAsDoubles; - protected Field stringFieldAsDoubles; - - @Before - public void setupStringFieldAsDoubles() { - rawStringValuesAsDoubles = new String[] { - "72", - "0", - "-1", - "1", - ((Long)Long.MAX_VALUE).toString(), - ((Long)Long.MIN_VALUE).toString(), - ((Double)Double.MAX_VALUE).toString(), - ((Double)Double.MIN_VALUE).toString() - }; - - stringFieldValuesAsDoubles = new FieldValues() { - @Override - public boolean isEmpty() { - return false; - } - - @Override - public int size() { - return rawStringValuesAsDoubles.length; - } - - @Override - public List getValues() { - return Stream.of(rawStringValuesAsDoubles).collect(Collectors.toList()); - } - - @Override - public String getNonPrimitiveValue() { - return rawStringValuesAsDoubles[0]; - } - - @Override - public long getLongValue() { - return Long.parseLong(rawStringValuesAsDoubles[0]); - } - - @Override - public double getDoubleValue() { - return Double.parseDouble(rawStringValuesAsDoubles[0]); - } - }; - - stringFieldAsDoubles = new StringField("string_field_as_doubles", stringFieldValuesAsDoubles); - } - - long[] rawLongMillisValues; - List rawDateMillisValues; - protected FieldValues dateMillisFieldValues; - protected Field dateMillisField; - - @Before - public void setupDateMillisField() { - rawLongMillisValues = new long[] { - 1629830752000L, - 0L, - 2040057952000L, - -6106212564000L - }; - - rawDateMillisValues = List.of( - ZonedDateTime.ofInstant(Instant.ofEpochMilli(rawLongMillisValues[0]), ZoneOffset.ofHours(-7)), - ZonedDateTime.ofInstant(Instant.ofEpochMilli(rawLongMillisValues[1]), ZoneOffset.ofHours(-6)), - ZonedDateTime.ofInstant(Instant.ofEpochMilli(rawLongMillisValues[2]), ZoneOffset.ofHours(0)), - ZonedDateTime.ofInstant(Instant.ofEpochMilli(rawLongMillisValues[3]), ZoneOffset.ofHours(-5)) - ); - - dateMillisFieldValues = new FieldValues() { - @Override - public boolean isEmpty() { - return false; - } - - @Override - public int size() { - return rawDateMillisValues.size(); - } - - @Override - public List getValues() { - return Collections.unmodifiableList(rawDateMillisValues); - } - - @Override - public ZonedDateTime getNonPrimitiveValue() { - return rawDateMillisValues.get(0); - } - - @Override - public long getLongValue() { - return DateMillisField.toLong(rawDateMillisValues.get(0)); - } - - @Override - public double getDoubleValue() { - return getLongValue(); - } - }; - - dateMillisField = new DateMillisField("millis_date_field", dateMillisFieldValues); - } - - long[] rawLongNanosValues; - List rawDateNanosValues; - protected FieldValues dateNanosFieldValues; - protected Field dateNanosField; - - @Before - public void setupDateNanosField() { - rawLongNanosValues = new long[] { - 1629830752000L, - 0L, - 2040057952000L, - -6106212564000L - }; - - rawDateNanosValues = List.of( - ZonedDateTime.ofInstant(Instant.EPOCH.plusNanos(rawLongNanosValues[0]), ZoneOffset.ofHours(-7)), - ZonedDateTime.ofInstant(Instant.EPOCH.plusNanos(rawLongNanosValues[1]), ZoneOffset.ofHours(-6)), - ZonedDateTime.ofInstant(Instant.EPOCH.plusNanos(rawLongNanosValues[2]), ZoneOffset.ofHours(0)), - ZonedDateTime.ofInstant(Instant.EPOCH.plusNanos(rawLongNanosValues[3]), ZoneOffset.ofHours(-5)) - ); - - dateNanosFieldValues = new FieldValues() { - @Override - public boolean isEmpty() { - return false; - } - - @Override - public int size() { - return rawDateNanosValues.size(); - } - - @Override - public List getValues() { - return Collections.unmodifiableList(rawDateNanosValues); - } - - @Override - public ZonedDateTime getNonPrimitiveValue() { - return rawDateNanosValues.get(0); - } - - @Override - public long getLongValue() { - return DateNanosField.toLong(rawDateNanosValues.get(0)); - } - - @Override - public double getDoubleValue() { - return getLongValue(); - } - }; - - dateNanosField = new DateNanosField("nanos_date_field", dateNanosFieldValues); - } - - List rawGeoPointValues; - protected FieldValues getPointFieldValues; - protected Field getPointField; - - @Before - public void setupGeoPointField() { - rawGeoPointValues = List.of( - new GeoPoint(0.0, 0.0) - ); - - getPointFieldValues = new FieldValues() { - @Override - public boolean isEmpty() { - return false; - } - - @Override - public int size() { - return rawGeoPointValues.size(); - } - - @Override - public List getValues() { - return Collections.unmodifiableList(rawGeoPointValues); - } - - @Override - public GeoPoint getNonPrimitiveValue() { - return rawGeoPointValues.get(0); - } - - @Override - public long getLongValue() { - throw new UnsupportedOperationException(); - } - - @Override - public double getDoubleValue() { - throw new UnsupportedOperationException(); - } - }; - - getPointField = new GeoPointField("geo_point_field", getPointFieldValues); - } -} diff --git a/server/src/test/java/org/elasticsearch/script/field/ConvertersTests.java b/server/src/test/java/org/elasticsearch/script/field/ConvertersTests.java deleted file mode 100644 index 116fedacaf8f8..0000000000000 --- a/server/src/test/java/org/elasticsearch/script/field/ConvertersTests.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -package org.elasticsearch.script.field; - -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.LongStream; -import java.util.stream.Stream; - -public class ConvertersTests extends ConvertersTestBase{ - - public void testInvalidFieldConversion() { - InvalidConversion ic = expectThrows(InvalidConversion.class, () -> getPointField.as(BigIntegerField.BigInteger)); - assertEquals("Cannot convert from [GeoPointField] using converter [BigIntegerField]", ic.getMessage()); - - ic = expectThrows(InvalidConversion.class, () -> getPointField.as(LongField.Long)); - assertEquals("Cannot convert from [GeoPointField] using converter [LongField]", ic.getMessage()); - } - - public void testLongFieldToBigIntegerField() { - // transform: long field to big integer field - List expectedBigIntegers = LongStream.of(rawLongValues).mapToObj(BigInteger::valueOf).collect(Collectors.toList()); - Field toBigIntegerField = longField.as(BigIntegerField.BigInteger); - assertEquals(expectedBigIntegers, toBigIntegerField.getValues()); - assertEquals(expectedBigIntegers.get(0), toBigIntegerField.getValue(null)); // default value ignored - assertEquals(rawLongValues[0], toBigIntegerField.getLong(10)); // default value ignored - assertEquals((double)rawLongValues[0], toBigIntegerField.getDouble(10.0), 0.0001); // default value ignored - - // reverse transform (symmetric): big integer field to long field - Field toLongField = toBigIntegerField.as(LongField.Long); - assertEquals(LongStream.of(rawLongValues).boxed().collect(Collectors.toList()), toLongField.getValues()); - assertEquals(Long.valueOf(rawLongValues[0]), toLongField.getValue(null)); // default value ignored - assertEquals(rawLongValues[0], toLongField.getLong(10)); // default value ignored - assertEquals((double)rawLongValues[0], toLongField.getDouble(10.0d), 0.0001d); // default value ignored - } - - public void testBigIntegerFieldToLongField() { - // transform: big integer field to long field - List expectedLongs = Stream.of(rawBigIntegerValues).mapToLong(BigInteger::longValue).boxed().collect(Collectors.toList()); - Field toLongField = bigIntegerField.as(LongField.Long); - assertEquals(expectedLongs, toLongField.getValues()); - assertEquals(expectedLongs.get(0), toLongField.getValue(null)); // default value ignored - assertEquals(rawBigIntegerValues[0].longValue(), toLongField.getLong(10)); // default value ignored - assertEquals(rawBigIntegerValues[0].doubleValue(), toLongField.getDouble(10.0), 0.0001); // default value ignored - - // reverse transform (asymmetric): long field to big integer field - Field toBigIntegerField = toLongField.as(BigIntegerField.BigInteger); - assertEquals(expectedLongs.stream().map(BigInteger::valueOf).collect(Collectors.toList()), toBigIntegerField.getValues()); - assertEquals( - BigInteger.valueOf(rawBigIntegerValues[0].longValue()), - toBigIntegerField.getValue(null)); // default value ignored - assertEquals(rawBigIntegerValues[0].longValue(), toBigIntegerField.getLong(10)); // default value ignored - assertEquals( - rawBigIntegerValues[0].doubleValue(), - toBigIntegerField.getDouble(10.0d), // default value ignored - 0.0001d); - } - - public void testDoubleFieldToBigIntegerField() { - // transform: double field to big integer field - List expectedBigIntegers = - Arrays.stream(rawDoubleValues).mapToObj(DoubleField::toBigInteger).collect(Collectors.toList()); - Field toBigIntegerField = doubleField.as(BigIntegerField.BigInteger); - assertEquals(expectedBigIntegers, toBigIntegerField.getValues()); - assertEquals(expectedBigIntegers.get(0), toBigIntegerField.getValue(null)); // default value ignored - assertEquals((long)rawDoubleValues[0], toBigIntegerField.getLong(10)); // default value ignored - assertEquals( - expectedBigIntegers.get(0).doubleValue(), - toBigIntegerField.getDouble(10.0d), // default value ignored - 0.00001d); - } - - public void testDoubleFieldToLongField() { - // transform: double field to long field - List expectedLongs = Arrays.stream(rawDoubleValues).mapToLong(d -> (long)d).boxed().collect(Collectors.toList()); - Field toLongField = doubleField.as(LongField.Long); - assertEquals(expectedLongs, toLongField.getValues()); - assertEquals((Long)(long)rawDoubleValues[0], toLongField.getValue(null)); // default value ignored - assertEquals((long)rawDoubleValues[0], toLongField.getLong(10)); // default value ignored - assertEquals((double)(long)rawDoubleValues[0], toLongField.getDouble(10.0d), 0.1d); // default value ignored - } - - public void testStringFieldToBigIntegerField() { - // transform: string field to big integer field - List expectedBigIntegers = - Arrays.stream(rawStringValuesAsDoubles).map(StringField::toBigInteger).collect(Collectors.toList()); - Field toBigIntegerField = stringFieldAsDoubles.as(BigIntegerField.BigInteger); - assertEquals(expectedBigIntegers, toBigIntegerField.getValues()); - assertEquals(expectedBigIntegers.get(0), toBigIntegerField.getValue(null)); // default value ignored - assertEquals(expectedBigIntegers.get(0).longValue(), toBigIntegerField.getLong(10)); // default value ignored - assertEquals(expectedBigIntegers.get(0).doubleValue(), toBigIntegerField.getDouble(10.0d), 0.1d); // default value ignored - } - - public void testStringFieldToLongField() { - // transform: string field to long field - List expectedLongs = Arrays.stream(rawStringValuesAsLongs).map(Long::parseLong).collect(Collectors.toList()); - Field toLongField = stringFieldAsLongs.as(LongField.Long); - assertEquals(expectedLongs, toLongField.getValues()); - assertEquals(expectedLongs.get(0), toLongField.getValue(null)); // default value ignored - assertEquals(expectedLongs.get(0).longValue(), toLongField.getLong(10)); // default value ignored - assertEquals(expectedLongs.get(0).doubleValue(), toLongField.getDouble(10.0d), 0.1d); // default value ignored - } - - public void testBooleanFieldToBigIntegerField() { - // transform: boolean field to big integer field - List expectedBigIntegers = new ArrayList<>(); - for (boolean bool : rawBooleanValues) { - expectedBigIntegers.add(BigInteger.valueOf(BooleanField.toLong(bool))); - } - Field toBigIntegerField = booleanField.as(BigIntegerField.BigInteger); - assertEquals(expectedBigIntegers, toBigIntegerField.getValues()); - assertEquals(expectedBigIntegers.get(0), toBigIntegerField.getValue(null)); // default value ignored - assertEquals(expectedBigIntegers.get(0).longValue(), toBigIntegerField.getLong(10)); // default value ignored - assertEquals(expectedBigIntegers.get(0).doubleValue(), toBigIntegerField.getDouble(10.0d), 0.1d); // default value ignored - } - - public void testBooleanFieldToLongField() { - // transform: boolean field to long field - List expectedLongs = new ArrayList<>(); - for (boolean bool : rawBooleanValues) { - expectedLongs.add(BooleanField.toLong(bool)); - } - Field toLongField = booleanField.as(LongField.Long); - assertEquals(expectedLongs, toLongField.getValues()); - assertEquals(expectedLongs.get(0), toLongField.getValue(null)); // default value ignored - assertEquals(expectedLongs.get(0).longValue(), toLongField.getLong(10)); // default value ignored - assertEquals(expectedLongs.get(0).doubleValue(), toLongField.getDouble(10.0d), 0.1d); // default value ignored - } - - public void testDateMillisFieldToBigIntegerField() { - // transform: boolean field to big integer field - List expectedBigIntegers = - rawDateMillisValues.stream().map(DateMillisField::toLong).map(BigInteger::valueOf).collect(Collectors.toList()); - Field toBigIntegerField = dateMillisField.as(BigIntegerField.BigInteger); - assertEquals(expectedBigIntegers, toBigIntegerField.getValues()); - assertEquals(expectedBigIntegers.get(0), toBigIntegerField.getValue(null)); // default value ignored - assertEquals(expectedBigIntegers.get(0).longValue(), toBigIntegerField.getLong(10)); // default value ignored - assertEquals(expectedBigIntegers.get(0).doubleValue(), toBigIntegerField.getDouble(10.0d), 0.1d); // default value ignored - } - - public void testDateMillisFieldToLongField() { - // transform: boolean field to long field - List expectedLongs = rawDateMillisValues.stream().map(DateMillisField::toLong).collect(Collectors.toList()); - Field toLongField = dateMillisField.as(LongField.Long); - assertEquals(expectedLongs, toLongField.getValues()); - assertEquals(expectedLongs.get(0), toLongField.getValue(null)); // default value ignored - assertEquals(expectedLongs.get(0).longValue(), toLongField.getLong(10)); // default value ignored - assertEquals(expectedLongs.get(0).doubleValue(), toLongField.getDouble(10.0d), 0.1d); // default value ignored - } - - public void testDateNanosFieldToBigIntegerField() { - // transform: boolean field to big integer field - List expectedBigIntegers = - rawDateNanosValues.stream().map(DateNanosField::toLong).map(BigInteger::valueOf).collect(Collectors.toList()); - Field toBigIntegerField = dateNanosField.as(BigIntegerField.BigInteger); - assertEquals(expectedBigIntegers, toBigIntegerField.getValues()); - assertEquals(expectedBigIntegers.get(0), toBigIntegerField.getValue(null)); // default value ignored - assertEquals(expectedBigIntegers.get(0).longValue(), toBigIntegerField.getLong(10)); // default value ignored - assertEquals(expectedBigIntegers.get(0).doubleValue(), toBigIntegerField.getDouble(10.0d), 0.1d); // default value ignored - } - - public void testDateNanosFieldToLongField() { - // transform: boolean field to long field - List expectedLongs = rawDateNanosValues.stream().map(DateNanosField::toLong).collect(Collectors.toList()); - Field toLongField = dateNanosField.as(LongField.Long); - assertEquals(expectedLongs, toLongField.getValues()); - assertEquals(expectedLongs.get(0), toLongField.getValue(null)); // default value ignored - assertEquals(expectedLongs.get(0).longValue(), toLongField.getLong(10)); // default value ignored - assertEquals(expectedLongs.get(0).doubleValue(), toLongField.getDouble(10.0d), 0.1d); // default value ignored - } -} diff --git a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongDocValuesField.java b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongDocValuesField.java new file mode 100644 index 0000000000000..1e62550732ddd --- /dev/null +++ b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongDocValuesField.java @@ -0,0 +1,143 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.unsignedlong; + +import org.apache.lucene.index.SortedNumericDocValues; +import org.apache.lucene.util.ArrayUtil; +import org.elasticsearch.script.field.DocValuesField; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.elasticsearch.search.DocValueFormat.MASK_2_63; +import static org.elasticsearch.xpack.unsignedlong.UnsignedLongFieldMapper.BIGINTEGER_2_64_MINUS_ONE; + +public class UnsignedLongDocValuesField implements UnsignedLongField, DocValuesField { + + private final SortedNumericDocValues input; + private long[] values = new long[0]; + private int count; + + public UnsignedLongDocValuesField(SortedNumericDocValues input) { + this.input = input; + } + + @Override + public void setNextDocId(int docId) throws IOException { + if (input.advanceExact(docId)) { + resize(input.docValueCount()); + for (int i = 0; i < count; i++) { + values[i] = input.nextValue(); + } + } else { + resize(0); + } + } + + protected void resize(int newSize) { + count = newSize; + values = ArrayUtil.grow(values, count); + } + + @Override + public boolean isEmpty() { + return count == 0; + } + + @Override + public int size() { + return count; + } + + /** + * Applies the formatting from {@link org.elasticsearch.search.DocValueFormat.UnsignedLongShiftedDocValueFormat#format(long)} so + * that the underlying value can be treated as a primitive long as that method returns either a {@code long} or a {@code BigInteger}. + */ + protected long toFormatted(int index) { + return values[index] ^ MASK_2_63; + } + + @Override + public List getValues() { + if (isEmpty()) { + return Collections.emptyList(); + } + + List values = new ArrayList<>(count); + + for (int index = 0; index < count; ++index) { + values.add(toFormatted(index)); + } + + return values; + } + + @Override + public Long getValue(Long defaultValue) { + return getValue(0, defaultValue); + } + + @Override + public Long getValue(int index, Long defaultValue) { + if (isEmpty() || index < 0 || index >= count) { + return defaultValue; + } + + return toFormatted(index); + } + + @Override + public long getLong(long defaultValue) { + return getLong(0, defaultValue); + } + + @Override + public long getLong(int index, long defaultValue) { + if (isEmpty() || index < 0 || index >= count) { + return defaultValue; + } + + return toFormatted(index); + } + + protected BigInteger toBigInteger(int index) { + return BigInteger.valueOf(toFormatted(index)).and(BIGINTEGER_2_64_MINUS_ONE); + } + + @Override + public List getBigIntegers() { + if (isEmpty()) { + return Collections.emptyList(); + } + + List values = new ArrayList<>(count); + + for (int index = 0; index < count; ++index) { + values.add(toBigInteger(index)); + } + + return values; + } + + @Override + public BigInteger getBigInteger(BigInteger defaultValue) { + return getBigInteger(0, defaultValue); + } + + @Override + public BigInteger getBigInteger(int index, BigInteger defaultValue) { + if (isEmpty() || index < 0 || index >= count) { + return defaultValue; + } + + return toBigInteger(index); + } +} diff --git a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongField.java b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongField.java index 071722a36139d..fa3e60e869e70 100644 --- a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongField.java +++ b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongField.java @@ -7,146 +7,20 @@ package org.elasticsearch.xpack.unsignedlong; -import org.elasticsearch.script.field.BigIntegerField; -import org.elasticsearch.script.field.Converter; -import org.elasticsearch.script.field.DelegatingFieldValues; import org.elasticsearch.script.field.Field; -import org.elasticsearch.script.field.FieldValues; -import org.elasticsearch.script.field.InvalidConversion; -import org.elasticsearch.script.field.LongField; import java.math.BigInteger; import java.util.List; -import java.util.stream.Collectors; -import static org.elasticsearch.xpack.unsignedlong.UnsignedLongFieldMapper.BIGINTEGER_2_64_MINUS_ONE; +public interface UnsignedLongField extends Field { -public class UnsignedLongField extends LongField { + long getLong(long defaultValue); - /* ---- Conversion Class From Other Fields ----*/ + long getLong(int index, long defaultValue); - public static final Converter UnsignedLong = new Converter() { - @Override - public UnsignedLongField convert(Field sourceField) { - if (sourceField instanceof BigIntegerField) { - return fromBigIntegerField((BigIntegerField) sourceField); - } - if (sourceField instanceof LongField) { - return fromLongField((LongField) sourceField); - } + BigInteger getBigInteger(BigInteger defaultValue); - throw new InvalidConversion(sourceField.getClass(), UnsignedLongField.class); - } + BigInteger getBigInteger(int index, BigInteger defaultValue); - @Override - public Class getFieldClass() { - return UnsignedLongField.class; - } - - @Override - public Class getTargetClass() { - return Long.class; - } - }; - - /* ---- Conversion Helpers To Other Fields ---- */ - - public static BigIntegerField toBigIntegerField(UnsignedLongField sourceField) { - FieldValues fv = sourceField.getFieldValues(); - return new BigIntegerField(sourceField.getName(), new DelegatingFieldValues(fv) { - private BigInteger toBigInteger(long formatted) { - return java.math.BigInteger.valueOf(formatted).and(BIGINTEGER_2_64_MINUS_ONE); - } - - @Override - public List getValues() { - return values.getValues().stream().map(this::toBigInteger).collect(Collectors.toList()); - } - - @Override - public BigInteger getNonPrimitiveValue() { - return toBigInteger(values.getNonPrimitiveValue()); - } - - @Override - public long getLongValue() { - return toBigInteger(values.getNonPrimitiveValue()).longValue(); - } - - @Override - public double getDoubleValue() { - return toBigInteger(values.getNonPrimitiveValue()).doubleValue(); - } - }); - } - - /* ---- Conversion Helpers From Other Fields ---- */ - - public static UnsignedLongField fromBigIntegerField(BigIntegerField sourceField) { - FieldValues fv = sourceField.getFieldValues(); - return new UnsignedLongField(sourceField.getName(), new DelegatingFieldValues<>(fv) { - @Override - public List getValues() { - return values.getValues().stream().map(BigInteger::longValue).collect(Collectors.toList()); - } - - @Override - public Long getNonPrimitiveValue() { - return values.getNonPrimitiveValue().longValue(); - } - - @Override - public long getLongValue() { - return values.getNonPrimitiveValue().longValue(); - } - - @Override - public double getDoubleValue() { - return values.getNonPrimitiveValue().doubleValue(); - } - }); - } - - public static UnsignedLongField fromLongField(LongField sourceField) { - FieldValues fv = sourceField.getFieldValues(); - return new UnsignedLongField(sourceField.getName(), new DelegatingFieldValues<>(fv) { - @Override - public List getValues() { - // Takes longs in raw format - return values.getValues().stream().map(UnsignedLongScriptDocValues::shiftedLong).collect(Collectors.toList()); - } - - @Override - public Long getNonPrimitiveValue() { - return getLongValue(); - } - - @Override - public long getLongValue() { - return UnsignedLongScriptDocValues.shiftedLong(values.getLongValue()); - } - - @Override - public double getDoubleValue() { - return getLongValue(); - } - }); - } - - /* ---- Unsigned Long Field Members ---- */ - - public UnsignedLongField(String name, FieldValues values) { - super(name, values); - } - - // UnsignedLongFields must define their own conversions as they are in x-pack - @Override - public > Field convert(Converter converter) { - if (converter.getTargetClass() == BigInteger.class) { - BigIntegerField bigIntegerField = toBigIntegerField(this); - return converter.getFieldClass().cast(bigIntegerField); - } - - return super.as(converter); - } + List getBigIntegers(); } diff --git a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongLeafFieldData.java b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongLeafFieldData.java index c898d2e147c9e..d5100d2d20f6f 100644 --- a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongLeafFieldData.java +++ b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongLeafFieldData.java @@ -17,6 +17,7 @@ import org.elasticsearch.index.fielddata.ScriptDocValues; import org.elasticsearch.index.fielddata.SortedBinaryDocValues; import org.elasticsearch.index.fielddata.SortedNumericDoubleValues; +import org.elasticsearch.script.field.DocValuesField; import org.elasticsearch.search.DocValueFormat; import java.io.IOException; @@ -77,6 +78,11 @@ public ScriptDocValues getScriptValues() { return new UnsignedLongScriptDocValues(getLongValues()); } + @Override + public DocValuesField getScriptField() { + return new UnsignedLongDocValuesField(getLongValues()); + } + @Override public SortedBinaryDocValues getBytesValues() { return FieldData.toString(getDoubleValues()); diff --git a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongScriptDocValues.java b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongScriptDocValues.java index 87548a3d8d0bc..b751790ba91cb 100644 --- a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongScriptDocValues.java +++ b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongScriptDocValues.java @@ -10,13 +10,13 @@ import org.apache.lucene.index.SortedNumericDocValues; import org.apache.lucene.util.ArrayUtil; import org.elasticsearch.index.fielddata.ScriptDocValues; -import org.elasticsearch.script.field.Field; import java.io.IOException; import static org.elasticsearch.search.DocValueFormat.MASK_2_63; public class UnsignedLongScriptDocValues extends ScriptDocValues { + private final SortedNumericDocValues in; private long[] values = new long[0]; private int count; @@ -49,11 +49,6 @@ protected void resize(int newSize) { values = ArrayUtil.grow(values, count); } - public long getValue() { - throwIfEmpty(); - return format(0); - } - @Override public Long get(int index) { throwIfEmpty(); @@ -65,34 +60,11 @@ public Long get(int index) { * that the underlying value can be treated as a primitive long as that method returns either a {@code long} or a {@code BigInteger}. */ protected long format(int index) { - return shiftedLong(values[index]); - } - - // Package private for use in UnsignedLongField - static long shiftedLong(long unshifted) { - return unshifted ^ MASK_2_63; + return values[index] ^ MASK_2_63; } @Override public int size() { return count; } - - @Override - public long getLongValue() { - throwIfEmpty(); - return format(0); - } - - @Override - public double getDoubleValue() { - throwIfEmpty(); - return format(0); - } - - @Override - public Field toField(String fieldName) { - return new UnsignedLongField(fieldName, this); - } - } diff --git a/x-pack/plugin/mapper-unsigned-long/src/test/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongFieldTests.java b/x-pack/plugin/mapper-unsigned-long/src/test/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongFieldTests.java deleted file mode 100644 index 1fef82545411f..0000000000000 --- a/x-pack/plugin/mapper-unsigned-long/src/test/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongFieldTests.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.unsignedlong; - -import org.elasticsearch.script.field.BigIntegerField; -import org.elasticsearch.script.field.Field; -import org.elasticsearch.script.field.FieldValues; -import org.elasticsearch.script.field.LongField; -import org.elasticsearch.test.ESTestCase; - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.LongStream; - -import static org.elasticsearch.search.DocValueFormat.MASK_2_63; - -public class UnsignedLongFieldTests extends ESTestCase { - static List VALUES; - - static List LONG_VALUES; - - protected static UnsignedLongField makeField(List biValues) { - return new UnsignedLongField("test", new FieldValues() { - protected long[] values = biValues.stream().mapToLong(BigInteger::longValue).toArray(); - - @Override - public boolean isEmpty() { - return values.length == 0; - } - - @Override - public int size() { - return values.length; - } - - @Override - public List getValues() { - return Arrays.stream(values).boxed().collect(Collectors.toList()); - } - - @Override - public Long getNonPrimitiveValue() { - return UnsignedLongScriptDocValues.shiftedLong(values[0]); - } - - @Override - public long getLongValue() { - return UnsignedLongScriptDocValues.shiftedLong(values[0]); - } - - @Override - public double getDoubleValue() { - return UnsignedLongScriptDocValues.shiftedLong(values[0]); - } - }); - } - - public void testLongValues() { - assertEquals(LONG_VALUES, makeField(VALUES).convert(LongField.Long).getValues()); - } - - public void testUnsignedConverter() { - Field thereAndBackAgain = makeField(VALUES).as(BigIntegerField.BigInteger).as(UnsignedLongField.UnsignedLong); - assertEquals(LONG_VALUES, thereAndBackAgain.getValues()); - } - - public void testLongToUnsignedLong() { - long[] raw = { Long.MIN_VALUE, Long.MAX_VALUE, ((long) Integer.MIN_VALUE - 1), ((long) Integer.MAX_VALUE + 1), -1L, 0L, 1L }; - Field src = new LongField("", new FieldValues() { - @Override - public boolean isEmpty() { - return false; - } - - @Override - public int size() { - return raw.length; - } - - @Override - public List getValues() { - return LongStream.of(raw).boxed().collect(Collectors.toList()); - } - - @Override - public Long getNonPrimitiveValue() { - return raw[0]; - } - - @Override - public long getLongValue() { - return raw[0]; - } - - @Override - public double getDoubleValue() { - return raw[0]; - } - }); - - Field dst = src.as(UnsignedLongField.UnsignedLong); - assertEquals(LongStream.of(raw).map(l -> l ^ MASK_2_63).boxed().collect(Collectors.toList()), dst.getValues()); - assertEquals(Long.valueOf(raw[0] ^ MASK_2_63), dst.getValue(null)); - assertEquals(raw[0] ^ MASK_2_63, dst.getLong(10)); - assertEquals((double) (raw[0] ^ MASK_2_63), dst.getDouble(10.0d), 0.1d); - } - - @Override - public void setUp() throws Exception { - super.setUp(); - long rawRandom = randomLongBetween(0, Long.MAX_VALUE); - BigInteger rawBigIntegerRandom = BigInteger.valueOf(rawRandom); - - if (randomBoolean()) { - rawRandom = rawRandom | MASK_2_63; - rawBigIntegerRandom = rawBigIntegerRandom.add(BigInteger.TWO.pow(63)); - } - - VALUES = List.of( - rawBigIntegerRandom, - new BigInteger("18446744073709551615"), // 2^64 - 1 - BigInteger.valueOf(0L), - new BigInteger("9223372036854775807"), // 2^63 - 1 - new BigInteger("9223372036854775808"), // 2^63 - new BigInteger("9223372036854775809") // 2^63 + 1 - ); - - LONG_VALUES = List.of(rawRandom, -1L, 0L, 9223372036854775807L, -9223372036854775808L, -9223372036854775807L); - } -} diff --git a/x-pack/plugin/mapper-version/src/main/java/org/elasticsearch/xpack/versionfield/VersionScriptDocValues.java b/x-pack/plugin/mapper-version/src/main/java/org/elasticsearch/xpack/versionfield/VersionScriptDocValues.java index 727378ac0d929..9841fa643050d 100644 --- a/x-pack/plugin/mapper-version/src/main/java/org/elasticsearch/xpack/versionfield/VersionScriptDocValues.java +++ b/x-pack/plugin/mapper-version/src/main/java/org/elasticsearch/xpack/versionfield/VersionScriptDocValues.java @@ -10,8 +10,6 @@ import org.apache.lucene.index.SortedSetDocValues; import org.apache.lucene.util.ArrayUtil; import org.elasticsearch.index.fielddata.ScriptDocValues; -import org.elasticsearch.script.field.Field; -import org.elasticsearch.script.field.VersionField; import java.io.IOException; @@ -36,10 +34,6 @@ public void setNextDocId(int docId) throws IOException { } } - public String getValue() { - return get(0); - } - @Override public String get(int index) { if (count == 0) { @@ -58,9 +52,4 @@ public String get(int index) { public int size() { return count; } - - @Override - public Field toField(String fieldName) { - return new VersionField(fieldName, this); - } } diff --git a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/plain/AbstractAtomicGeoShapeShapeFieldData.java b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/plain/AbstractAtomicGeoShapeShapeFieldData.java index a9e7291afb974..62b0abedd788d 100644 --- a/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/plain/AbstractAtomicGeoShapeShapeFieldData.java +++ b/x-pack/plugin/spatial/src/main/java/org/elasticsearch/xpack/spatial/index/fielddata/plain/AbstractAtomicGeoShapeShapeFieldData.java @@ -12,8 +12,6 @@ import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.index.fielddata.ScriptDocValues; import org.elasticsearch.index.fielddata.SortedBinaryDocValues; -import org.elasticsearch.script.field.Field; -import org.elasticsearch.script.field.FieldValues; import org.elasticsearch.xpack.spatial.index.fielddata.GeoShapeValues; import org.elasticsearch.xpack.spatial.index.fielddata.LeafGeoShapeFieldData; @@ -117,16 +115,5 @@ public GeoShapeValues.GeoShapeValue get(int index) { public int size() { return value == null ? 0 : 1; } - - @Override - public Field toField(String fieldName) { - return new GeoShapeField(fieldName, this); - } - } - - public static class GeoShapeField extends Field { - public GeoShapeField(String name, FieldValues values) { - super(name, values); - } } } diff --git a/x-pack/plugin/vectors/src/main/java/org/elasticsearch/xpack/vectors/query/BinaryDenseVectorScriptDocValues.java b/x-pack/plugin/vectors/src/main/java/org/elasticsearch/xpack/vectors/query/BinaryDenseVectorScriptDocValues.java index 2b24ccdfd01fc..4616af49f5c0c 100644 --- a/x-pack/plugin/vectors/src/main/java/org/elasticsearch/xpack/vectors/query/BinaryDenseVectorScriptDocValues.java +++ b/x-pack/plugin/vectors/src/main/java/org/elasticsearch/xpack/vectors/query/BinaryDenseVectorScriptDocValues.java @@ -60,11 +60,6 @@ public int size() { } } - @Override - public BytesRef getNonPrimitiveValue() { - return value; - } - @Override public double dotProduct(float[] queryVector) { ByteBuffer byteBuffer = ByteBuffer.wrap(value.bytes, value.offset, value.length); diff --git a/x-pack/plugin/vectors/src/main/java/org/elasticsearch/xpack/vectors/query/DenseVectorScriptDocValues.java b/x-pack/plugin/vectors/src/main/java/org/elasticsearch/xpack/vectors/query/DenseVectorScriptDocValues.java index 62d97cf71ae84..daf4a174c19e4 100644 --- a/x-pack/plugin/vectors/src/main/java/org/elasticsearch/xpack/vectors/query/DenseVectorScriptDocValues.java +++ b/x-pack/plugin/vectors/src/main/java/org/elasticsearch/xpack/vectors/query/DenseVectorScriptDocValues.java @@ -10,7 +10,6 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.index.fielddata.ScriptDocValues; -import org.elasticsearch.script.field.Field; public abstract class DenseVectorScriptDocValues extends ScriptDocValues { public static final String MISSING_VECTOR_FIELD_MESSAGE = "A document doesn't have a value for a vector field!"; @@ -45,11 +44,6 @@ public BytesRef get(int index) { "Use 'vectorValue' or 'magnitude' instead!'"); } - @Override - public Field toField(String fieldName) { - throw new IllegalStateException("not implemented"); - } - public static DenseVectorScriptDocValues empty(int dims) { return new DenseVectorScriptDocValues(dims) { @Override From b52beeb95a4b0cc26e14f5ac464880bdae2423d5 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 11 Oct 2021 09:43:47 -0700 Subject: [PATCH 2/7] ignore bwc tests --- modules/lang-painless/build.gradle | 41 ++ .../org.elasticsearch.script.fields.txt | 11 +- .../test/painless/100_terms_agg.yml | 54 -- .../test/painless/130_metric_agg.yml | 22 - .../test/painless/20_scriptfield.yml | 75 --- .../test/painless/40_fields_api.yml | 594 ------------------ .../painless/70_execute_painless_scripts.yml | 226 ------- 7 files changed, 43 insertions(+), 980 deletions(-) delete mode 100644 modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/40_fields_api.yml diff --git a/modules/lang-painless/build.gradle b/modules/lang-painless/build.gradle index 6cfe759377d54..ae3a9ee4ca5d7 100644 --- a/modules/lang-painless/build.gradle +++ b/modules/lang-painless/build.gradle @@ -58,6 +58,47 @@ tasks.named("test").configure { jvmArgs '-XX:-OmitStackTraceInFastThrow', '-XX:-HeapDumpOnOutOfMemoryError' } +tasks.named("yamlRestTestV7CompatTest").configure { + systemProperty 'tests.rest.blacklist', [ + 'painless/20_scriptfield/Scripted Field Doing Compare (fields api)', + 'painless/70_execute_painless_scripts/Execute with double field context (single-value, fields api)', + 'painless/70_execute_painless_scripts/Execute with double field context (single-value, fields api)', + '70_execute_painless_scripts/Execute with geo point field context (multi-value, fields api)', + '70_execute_painless_scripts/Execute with ip field context (single-value, fields api)', + '70_execute_painless_scripts/Execute with boolean field context (single-value, fields api)', + 'painless/70_execute_painless_scripts/Execute with boolean field context (multi-value, fields api)', + 'painless/40_fields_api/date to long', + 'painless/130_metric_agg/Scripted Metric Agg Total (fields api)', + 'painless/70_execute_painless_scripts/Execute with keyword field context (multi-value, fields api)', + 'painless/100_terms_agg/Double Value Script with doc notation (fields api)', + 'painless/100_terms_agg/Long Value Script with doc notation (fields api)', + 'painless/20_scriptfield/Access a date (fields api)', + 'painless/70_execute_painless_scripts/Execute with date field context (multi-value, fields api)', + 'painless/70_execute_painless_scripts/Execute with keyword field context (single-value, fields api)', + 'painless/70_execute_painless_scripts/Execute with long field context (multi-value, fields api)', + 'painless/20_scriptfield/Scripted Field (fields api)', + 'painless/70_execute_painless_scripts/Execute with long field context (single-value, fields api)', + 'painless/70_execute_painless_scripts/Execute with geo point field context (single-value, fields api)', + 'painless/70_execute_painless_scripts/Execute with date field context (single-value, fields api)', + 'painless/40_fields_api/missing field', + 'painless/40_fields_api/sort script fields api', + 'painless/20_scriptfield/Access many dates (fields api)', + 'painless/70_execute_painless_scripts/Execute with long field context (single-value, fields api)', + 'painless/70_execute_painless_scripts/Execute with geo point field context (single-value, fields api)', + 'painless/70_execute_painless_scripts/Execute with date field context (single-value, fields api)', + 'painless/40_fields_api/missing field', + 'painless/40_fields_api/sort script fields api', + 'painless/20_scriptfield/Access many dates (fields api)', + 'painless/100_terms_agg/String Value Script with doc notation (fields api)', + 'painless/40_fields_api/string to long and bigint', + 'painless/40_fields_api/boolean to long and bigint', + 'painless/40_fields_api/script fields api for dates', + 'painless/70_execute_painless_scripts/Execute with double field context (multi-value, fields api)', + 'painless/40_fields_api/filter script fields api', + 'painless/40_fields_api/script score fields api' + ].join(',') +} + /* Build Javadoc for the Java classes in Painless's public API that are in the * Painless plugin */ tasks.register("apiJavadoc", Javadoc) { diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.fields.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.fields.txt index c2603853dd150..ed7024c81fd7c 100644 --- a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.fields.txt +++ b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.fields.txt @@ -10,18 +10,11 @@ # API class org.elasticsearch.script.field.Field { - org.elasticsearch.script.field.Converter BigInteger @augmented[augmented_canonical_class_name="org.elasticsearch.script.field.BigIntegerField"] - org.elasticsearch.script.field.Converter Long @augmented[augmented_canonical_class_name="org.elasticsearch.script.field.LongField"] - String getName() boolean isEmpty() + int size() List getValues() def getValue(def) - double getDouble(double) - long getLong(long) - org.elasticsearch.script.field.Field as(org.elasticsearch.script.field.Converter) -} - -class org.elasticsearch.script.field.Converter { + def getValue(int, def) } class org.elasticsearch.script.DocBasedScript { diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/100_terms_agg.yml b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/100_terms_agg.yml index 824036e193037..000e1af694d7d 100644 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/100_terms_agg.yml +++ b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/100_terms_agg.yml @@ -66,24 +66,6 @@ setup: - is_false: aggregations.str_terms.buckets.1.key_as_string - match: { aggregations.str_terms.buckets.1.doc_count: 1 } ---- -"String Value Script with doc notation (fields api)": - - - do: - search: - rest_total_hits_as_int: true - body: { "size" : 0, "aggs" : { "str_terms" : { "terms" : { "field" : "str", "script": { "source": "return field('str').getValue('') + \"1\""} } } } } - - - match: { hits.total: 3 } - - - length: { aggregations.str_terms.buckets: 2 } - - match: { aggregations.str_terms.buckets.0.key: "abc1" } - - is_false: aggregations.str_terms.buckets.0.key_as_string - - match: { aggregations.str_terms.buckets.0.doc_count: 2 } - - match: { aggregations.str_terms.buckets.1.key: "bcd1" } - - is_false: aggregations.str_terms.buckets.1.key_as_string - - match: { aggregations.str_terms.buckets.1.doc_count: 1 } - --- "Long Value Script with doc notation": @@ -102,24 +84,6 @@ setup: - is_false: aggregations.long_terms.buckets.1.key_as_string - match: { aggregations.long_terms.buckets.1.doc_count: 1 } ---- -"Long Value Script with doc notation (fields api)": - - - do: - search: - rest_total_hits_as_int: true - body: { "size" : 0, "aggs" : { "long_terms" : { "terms" : { "field" : "number", "script": { "source": "return field('number').getValue(0L) + 1"} } } } } - - - match: { hits.total: 3 } - - - length: { aggregations.long_terms.buckets: 2 } - - match: { aggregations.long_terms.buckets.0.key: 2.0 } - - is_false: aggregations.long_terms.buckets.0.key_as_string - - match: { aggregations.long_terms.buckets.0.doc_count: 2 } - - match: { aggregations.long_terms.buckets.1.key: 3.0 } - - is_false: aggregations.long_terms.buckets.1.key_as_string - - match: { aggregations.long_terms.buckets.1.doc_count: 1 } - --- "Double Value Script with doc notation": @@ -138,24 +102,6 @@ setup: - is_false: aggregations.double_terms.buckets.1.key_as_string - match: { aggregations.double_terms.buckets.1.doc_count: 1 } ---- -"Double Value Script with doc notation (fields api)": - - - do: - search: - rest_total_hits_as_int: true - body: { "size" : 0, "aggs" : { "double_terms" : { "terms" : { "field" : "double", "script": { "source": "return field('double').getValue(0.0) + 1"} } } } } - - - match: { hits.total: 3 } - - - length: { aggregations.double_terms.buckets: 2 } - - match: { aggregations.double_terms.buckets.0.key: 2.0 } - - is_false: aggregations.double_terms.buckets.0.key_as_string - - match: { aggregations.double_terms.buckets.0.doc_count: 2 } - - match: { aggregations.double_terms.buckets.1.key: 3.0 } - - is_false: aggregations.double_terms.buckets.1.key_as_string - - match: { aggregations.double_terms.buckets.1.doc_count: 1 } - --- "Bucket script with keys": diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/130_metric_agg.yml b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/130_metric_agg.yml index 60cc31f623cfe..355da5cd27e9e 100644 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/130_metric_agg.yml +++ b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/130_metric_agg.yml @@ -61,25 +61,3 @@ setup: - match: { hits.total: 3 } - match: { aggregations.total.value: 4.0 } ---- -"Scripted Metric Agg Total (fields api)": - - - do: - search: - rest_total_hits_as_int: true - body: { - "size": 0, - "aggs": { - "total": { - "scripted_metric": { - "init_script": "state.transactions = []", - "map_script": "state.transactions.add(field('double').getValue(0.0))", - "combine_script": "double total = 0.0; for (t in state.transactions) { total += t } return total", - "reduce_script": "double total = 0; for (a in states) { total += a } return total" - } - } - } - } - - - match: { hits.total: 3 } - - match: { aggregations.total.value: 4.0 } diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/20_scriptfield.yml b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/20_scriptfield.yml index 0ff7c38b77633..3a3e5608e02bf 100644 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/20_scriptfield.yml +++ b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/20_scriptfield.yml @@ -44,21 +44,6 @@ setup: - match: { hits.hits.0.fields.bar.0: "aaabbb"} ---- -"Scripted Field (fields api)": - - do: - search: - rest_total_hits_as_int: true - body: - script_fields: - bar: - script: - source: "field('foo').getValue('') + params.x;" - params: - x: "bbb" - - - match: { hits.hits.0.fields.bar.0: "aaabbb"} - --- "Scripted Field Doing Compare": - do: @@ -88,35 +73,6 @@ setup: - match: { hits.hits.0.fields.bar.0: false} ---- -"Scripted Field Doing Compare (fields api)": - - do: - search: - rest_total_hits_as_int: true - body: - script_fields: - bar: - script: - source: "boolean compare(Supplier s, def v) {return s.get() == v;} - compare(() -> { return field('foo').getValue('') }, params.x);" - params: - x: "aaa" - - - match: { hits.hits.0.fields.bar.0: true} - - do: - search: - rest_total_hits_as_int: true - body: - script_fields: - bar: - script: - source: "boolean compare(Supplier s, def v) {return s.get() == v;} - compare(() -> { return doc['foo'].value }, params.x);" - params: - x: "bbb" - - - match: { hits.hits.0.fields.bar.0: false} - --- "Scripted Field with a null safe dereference (non-null)": - do: @@ -160,19 +116,6 @@ setup: - match: { hits.hits.0.fields.bar.0: 7} ---- -"Access a date (fields api)": - - do: - search: - rest_total_hits_as_int: true - body: - script_fields: - bar: - script: - source: "field('date').getValue(new Date()).dayOfWeekEnum.value" - - - match: { hits.hits.0.fields.bar.0: 7} - --- "Access many dates": - do: @@ -191,24 +134,6 @@ setup: - match: { hits.hits.0.fields.bar.0: "7 3 3"} ---- -"Access many dates (fields api)": - - do: - search: - rest_total_hits_as_int: true - body: - script_fields: - bar: - script: - source: > - StringBuilder b = new StringBuilder(); - for (def date : field('dates').getValues()) { - b.append(" ").append(date.getDayOfWeekEnum().value); - } - return b.toString().trim() - - - match: { hits.hits.0.fields.bar.0: "7 3 3"} - --- "Scripted Field with script error": - do: diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/40_fields_api.yml b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/40_fields_api.yml deleted file mode 100644 index eb02667536104..0000000000000 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/40_fields_api.yml +++ /dev/null @@ -1,594 +0,0 @@ -# Integration tests for sort script queries using Painless - -setup: -- skip: - version: " - 7.14.99" - reason: "sort script fields api was added in 7.15.0" - ---- -"sort script fields api": - - do: - indices.create: - index: test - body: - settings: - number_of_shards: 2 - mappings: - properties: - dval: - type: double - - do: - index: - index: test - id: d1 - body: {"dval": 10, "sval": "f"} - - do: - index: - index: test - id: d2 - body: {} - - do: - index: - index: test - id: d3 - body: {"dval": 5, "sval": "a"} - - do: - indices.refresh: {} - - do: - search: - rest_total_hits_as_int: true - index: test - body: - sort: - _script: - type: number - script: - source: "field('dval').getValue(3)" - - match: { hits.total: 3 } - - match: { hits.hits.0._id: d2 } - - match: { hits.hits.1._id: d3 } - - match: { hits.hits.2._id: d1 } - - do: - search: - rest_total_hits_as_int: true - index: test - body: - sort: - _script: - type: string - script: - source: "field('sval.keyword').getValue('g')" - - match: { hits.total: 3 } - - match: { hits.hits.0._id: d3 } - - match: { hits.hits.1._id: d1 } - - match: { hits.hits.2._id: d2 } - ---- -"script fields api for dates": - - do: - indices.create: - index: test - body: - settings: - number_of_shards: 2 - mappings: - properties: - dt: - type: date_nanos - - do: - index: - index: test - id: d1 - body: {"dt": "2021-08-24T18:45:52.123456789Z" } - - do: - indices.refresh: {} - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: { "match_all": {} } - sort: [ { dt: asc } ] - script_fields: - date_field: - script: - source: "field('dt').getLong(100L)" - - match: { hits.total: 1 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.0.fields.date_field.0: 1629830752123456789 } - ---- -"script score fields api": - - do: - indices.create: - index: test - body: - settings: - number_of_shards: 2 - mappings: - properties: - dval: - type: double - - do: - index: - index: test - id: d1 - body: {"dval": 10} - - do: - index: - index: test - id: d2 - body: {} - - do: - index: - index: test - id: d3 - body: {"dval": 5} - - do: - indices.refresh: {} - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: - script_score: - query: {match_all: {} } - script: - source: "field('dval').getValue(3)" - - match: { hits.total: 3 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.1._id: d3 } - - match: { hits.hits.2._id: d2 } - ---- -"filter script fields api": - - do: - indices.create: - index: test - body: - settings: - number_of_shards: 2 - mappings: - properties: - dval: - type: double - - do: - index: - index: test - id: d1 - body: {"dval": 10, "sval": "f"} - - do: - index: - index: test - id: d2 - body: {} - - do: - index: - index: test - id: d3 - body: {"dval": 5, "sval": "a"} - - do: - indices.refresh: {} - - do: - search: - rest_total_hits_as_int: true - body: - query: - bool: - filter: - script: - script: "field('dval').getValue(6) > 6" - - match: { hits.total: 1 } - - match: { hits.hits.0._id: d1 } - - do: - search: - rest_total_hits_as_int: true - body: - query: - bool: - filter: - script: - script: "field('sval.keyword').getValue('b') == 'a'" - - match: { hits.total: 1 } - - match: { hits.hits.0._id: d3 } - ---- -"missing field": - - do: - indices.create: - index: test - body: - settings: - number_of_shards: 2 - mappings: - properties: - dval: - type: double - - do: - index: - index: test - id: d1 - body: {"foo": 25, "dval": 1.0 } - - do: - index: - index: test - id: d2 - body: {"foo": 9223372036854775807, "dval": 2.0 } - - do: - index: - index: test - id: d3 - body: { "bar": "abc", "dval": 3.0 } - - do: - indices.refresh: {} - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: { "match_all": {} } - sort: [ { dval: asc } ] - script_fields: - missing_field: - script: - source: "field('foo').as(Field.BigInteger).getValue(BigInteger.TEN).add(BigInteger.ONE)" - - match: { hits.total: 3 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.0.fields.missing_field.0: 26 } - - match: { hits.hits.1._id: d2 } - - match: { hits.hits.1.fields.missing_field.0: 9223372036854775808 } - - match: { hits.hits.2._id: d3 } - - match: { hits.hits.2.fields.missing_field.0: 11 } - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: { "match_all": {} } - sort: [ { dval: asc } ] - script_fields: - missing_field: - script: - source: "field('foo').as(Field.BigInteger).as(Field.Long).getValue(10L) + 2L" - - match: { hits.total: 3 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.0.fields.missing_field.0: 27 } - - match: { hits.hits.1._id: d2 } - - match: { hits.hits.1.fields.missing_field.0: -9223372036854775809 } - - match: { hits.hits.2._id: d3 } - - match: { hits.hits.2.fields.missing_field.0: 12 } - ---- -"date to long": - - do: - indices.create: - index: test - body: - settings: - number_of_shards: 2 - mappings: - properties: - dval: - type: double - dtnanos: - type: date_nanos - dt: - type: date - - do: - index: - index: test - id: d1 - body: { "dval": 101, "dt": "2015-01-01T12:10:40Z" } - - do: - index: - index: test - id: d2 - body: { "dval": 202, "dt": "2015-01-01" } - - do: - index: - index: test - id: d3 - body: { "dval": 303, "dt": 1420072496000 } - - do: - index: - index: test - id: d4 - body: { "dval": 404, "dtnanos": "2015-01-01T12:10:30.123456789Z"} - - do: - index: - index: test - id: d5 - body: { "dval": 505, "dtnanos": "2261-04-11T23:47:33.54775807Z" } - - do: - index: - index: test - id: d6 - body: { "dval": 606 } - - do: - indices.refresh: {} - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: { "match_all": {} } - sort: [ { dval: asc } ] - script_fields: - dt_bigint: - script: - source: "field('dt').as(Field.BigInteger).getValue(BigInteger.TEN).add(BigInteger.ONE)" - - match: { hits.total: 6 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.0.fields.dt_bigint.0: 1420114240001 } - - match: { hits.hits.1._id: d2 } - - match: { hits.hits.1.fields.dt_bigint.0: 1420070400001 } - - match: { hits.hits.2._id: d3 } - - match: { hits.hits.2.fields.dt_bigint.0: 1420072496001 } - - match: { hits.hits.3._id: d4 } - - match: { hits.hits.3.fields.dt_bigint.0: 11 } - - match: { hits.hits.4._id: d5 } - - match: { hits.hits.4.fields.dt_bigint.0: 11 } - - match: { hits.hits.5._id: d6 } - - match: { hits.hits.5.fields.dt_bigint.0: 11 } - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: { "match_all": {} } - sort: [ { dval: asc } ] - script_fields: - dt_long: - script: - source: "field('dt').as(Field.Long).getValue(10L) + 2L" - - match: { hits.total: 6 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.0.fields.dt_long.0: 1420114240002 } - - match: { hits.hits.1._id: d2 } - - match: { hits.hits.1.fields.dt_long.0: 1420070400002 } - - match: { hits.hits.2._id: d3 } - - match: { hits.hits.2.fields.dt_long.0: 1420072496002 } - - match: { hits.hits.3._id: d4 } - - match: { hits.hits.3.fields.dt_long.0: 12 } - - match: { hits.hits.4._id: d5 } - - match: { hits.hits.4.fields.dt_long.0: 12 } - - match: { hits.hits.5._id: d6 } - - match: { hits.hits.5.fields.dt_long.0: 12 } - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: { "match_all": {} } - sort: [ { dval: asc } ] - script_fields: - dtnan_bigint: - script: - source: "field('dtnanos').as(Field.BigInteger).getValue(BigInteger.TEN).add(BigInteger.ONE)" - - match: { hits.total: 6 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.0.fields.dtnan_bigint.0: 11 } - - match: { hits.hits.1._id: d2 } - - match: { hits.hits.1.fields.dtnan_bigint.0: 11 } - - match: { hits.hits.2._id: d3 } - - match: { hits.hits.2.fields.dtnan_bigint.0: 11 } - - match: { hits.hits.3._id: d4 } - - match: { hits.hits.3.fields.dtnan_bigint.0: 1420114230123456790 } - - match: { hits.hits.4._id: d5 } - - match: { hits.hits.4.fields.dtnan_bigint.0: 9191836053547758071 } - - match: { hits.hits.5._id: d6 } - - match: { hits.hits.5.fields.dtnan_bigint.0: 11 } - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: { "match_all": {} } - sort: [ { dval: asc } ] - script_fields: - dtnan_long: - script: - source: "field('dtnanos').as(Field.Long).getValue(field('dt').as(Field.Long).getValue(0L) * 1000) + 2L" - - match: { hits.total: 6 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.0.fields.dtnan_long.0: 1420114240000002 } - - match: { hits.hits.1._id: d2 } - - match: { hits.hits.1.fields.dtnan_long.0: 1420070400000002 } - - match: { hits.hits.2._id: d3 } - - match: { hits.hits.2.fields.dtnan_long.0: 1420072496000002 } - - match: { hits.hits.3._id: d4 } - - match: { hits.hits.3.fields.dtnan_long.0: 1420114230123456791 } - - match: { hits.hits.4._id: d5 } - - match: { hits.hits.4.fields.dtnan_long.0: 9191836053547758072 } - - match: { hits.hits.5._id: d6 } - - match: { hits.hits.5.fields.dtnan_long.0: 2 } - ---- -"boolean to long and bigint": - - do: - indices.create: - index: test - body: - settings: - number_of_shards: 2 - mappings: - properties: - dval: - type: double - bool: - type: boolean - - do: - index: - index: test - id: d1 - body: { "dval": 101, "bool": true } - - do: - index: - index: test - id: d2 - body: { "dval": 202, "bool": false } - - do: - index: - index: test - id: d3 - body: { "dval": 303 } - - do: - indices.refresh: {} - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: { "match_all": {} } - sort: [ { dval: asc } ] - script_fields: - bool: - script: - source: "field('bool').as(Field.Long).getValue(-1)" - - match: { hits.total: 3 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.0.fields.bool.0: 1 } - - match: { hits.hits.1._id: d2 } - - match: { hits.hits.1.fields.bool.0: 0 } - - match: { hits.hits.2._id: d3 } - - match: { hits.hits.2.fields.bool.0: -1 } - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: { "match_all": {} } - sort: [ { dval: asc } ] - script_fields: - bool: - script: - source: "field('bool').as(Field.BigInteger).getValue(-1)" - - match: { hits.total: 3 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.0.fields.bool.0: 1 } - - match: { hits.hits.1._id: d2 } - - match: { hits.hits.1.fields.bool.0: 0 } - - match: { hits.hits.2._id: d3 } - - match: { hits.hits.2.fields.bool.0: -1 } ---- -"string to long and bigint": - - do: - indices.create: - index: test - body: - settings: - number_of_shards: 2 - mappings: - properties: - dval: - type: double - str: - type: keyword - - do: - index: - index: test - id: d1 - body: { "dval": 101, "str": "18446744073709551618" } - - do: - index: - index: test - id: d2 - body: { "dval": 202, "str": "9223372036854775809" } - - do: - index: - index: test - id: d3 - body: { "dval": 303, "str": "-1" } - - do: - index: - index: test - id: d4 - body: { "dval": 404 } - - do: - index: - index: test - id: d5 - body: { "dval": 505, "str": "unparseable number" } - - do: - index: - index: test - id: d6 - body: { "dval": 606, "str": "10E40" } - - do: - index: - index: test - id: d7 - body: { "dval": 707, "str": "18446744073709551618.555" } - - do: - indices.refresh: {} - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: { "match_all": {} } - sort: [ { dval: asc } ] - script_fields: - str: - script: - source: "field('str').as(Field.Long).getValue(-20)" - - match: { hits.total: 7 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.0.fields.str.0: -20 } - - match: { hits.hits.1._id: d2 } - - match: { hits.hits.1.fields.str.0: -20 } - - match: { hits.hits.2._id: d3 } - - match: { hits.hits.2.fields.str.0: -1 } - - match: { hits.hits.3._id: d4 } - - match: { hits.hits.3.fields.str.0: -20 } - - match: { hits.hits.4._id: d5 } - - match: { hits.hits.4.fields.str.0: -20 } - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: { "match_all": {} } - sort: [ { dval: asc } ] - script_fields: - str: - script: - source: "field('str').getLong(-40)" - - match: { hits.total: 7 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.0.fields.str.0: -40 } - - match: { hits.hits.1._id: d2 } - - match: { hits.hits.1.fields.str.0: -40 } - - match: { hits.hits.2._id: d3 } - - match: { hits.hits.2.fields.str.0: -1 } - - match: { hits.hits.3._id: d4 } - - match: { hits.hits.3.fields.str.0: -40 } - - match: { hits.hits.4._id: d5 } - - match: { hits.hits.4.fields.str.0: -40 } - - do: - search: - rest_total_hits_as_int: true - index: test - body: - query: { "match_all": {} } - sort: [ { dval: asc } ] - script_fields: - str: - script: - source: "field('str').as(Field.BigInteger).getValue(BigInteger.TEN)" - - match: { hits.total: 7 } - - match: { hits.hits.0._id: d1 } - - match: { hits.hits.0.fields.str.0: 18446744073709551618 } - - match: { hits.hits.1._id: d2 } - - match: { hits.hits.1.fields.str.0: 9223372036854775809 } - - match: { hits.hits.2._id: d3 } - - match: { hits.hits.2.fields.str.0: -1 } - - match: { hits.hits.3._id: d4 } - - match: { hits.hits.3.fields.str.0: 10 } - - match: { hits.hits.4._id: d5 } - - match: { hits.hits.4.fields.str.0: 10 } - - match: { hits.hits.5._id: d6 } - - match: { hits.hits.5.fields.str.0: 100000000000000000000000000000000000000000 } - - match: { hits.hits.6._id: d7 } - - match: { hits.hits.6.fields.str.0: 18446744073709551618 } diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/70_execute_painless_scripts.yml b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/70_execute_painless_scripts.yml index abdf09fa76819..bb01fc3eca154 100644 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/70_execute_painless_scripts.yml +++ b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/70_execute_painless_scripts.yml @@ -118,39 +118,6 @@ setup: index: "my-index" - match: { result: [ false, false, true, true ] } ---- -"Execute with boolean field context (single-value, fields api)": - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('rank').getValue(false) < params.max_rank);" - params: - max_rank: 5.0 - context: "boolean_field" - context_setup: - document: - rank: 4 - index: "my-index" - - match: { result: [ true ] } - - ---- -"Execute with boolean field context (multi-value, fields api)": - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('rank').getValue(false) < params.max_rank); emit(false); emit(false); emit(true);" - params: - max_rank: 5.0 - context: "boolean_field" - context_setup: - document: - rank: 4 - index: "my-index" - - match: { result: [ false, false, true, true ] } - --- "Execute with date field context (single-value)": - do: @@ -180,35 +147,6 @@ setup: index: "my-index" - match: { result: [ "2015-01-01T12:10:30.000Z", "2010-11-30T13:14:35.000Z" ] } ---- -"Execute with date field context (single-value, fields api)": - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('date').getValue(0).toInstant().toEpochMilli())" - context: "date_field" - context_setup: - document: - date: "2015-01-01T12:10:30Z" - index: "my-index" - - match: { result: [ "2015-01-01T12:10:30.000Z" ] } - ---- -"Execute with date field context (multi-value, fields api)": - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('date0').values[0].toInstant().toEpochMilli()); emit(field('date1').values[0].toInstant().toEpochMilli());" - context: "date_field" - context_setup: - document: - date0: "2015-01-01T12:10:30Z" - date1: "2010-11-30T13:14:35Z" - index: "my-index" - - match: { result: [ "2015-01-01T12:10:30.000Z", "2010-11-30T13:14:35.000Z" ] } - --- "Execute with double field context (single-value)": - do: @@ -241,38 +179,6 @@ setup: index: "my-index" - match: { result: [ 20.0, 400.0, 55.0 ] } ---- -"Execute with double field context (single-value, fields api)": - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('rank').getValue(0.0) * params.max_rank)" - params: - max_rank: 5.0 - context: "double_field" - context_setup: - document: - rank: 4 - index: "my-index" - - match: { result: [ 20.0 ] } - ---- -"Execute with double field context (multi-value, fields api)": - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('rank').getValue(0.0) * params.max_rank); emit(400.0); emit(55.0)" - params: - max_rank: 5.0 - context: "double_field" - context_setup: - document: - rank: 4 - index: "my-index" - - match: { result: [ 20.0, 400.0, 55.0 ] } - --- "Execute with geo point field context (single-value)": - skip: @@ -313,47 +219,6 @@ setup: - close_to: { result.1.coordinates.1: { value: 41.0, error: 0.00001 } } - match: { result.1.type: "Point" } ---- -"Execute with geo point field context (single-value, fields api)": - - skip: - features: close_to - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('point').getValue(null).lat + 1.0, field('point').getValue(null).lon - 1.0)" - context: "geo_point_field" - context_setup: - document: - point: "30.0,40.0" - index: "my-index" - - close_to: { result.0.coordinates.0: { value: 39.0, error: 0.00001 } } - - close_to: { result.0.coordinates.1: { value: 31.0, error: 0.00001 } } - - match: { result.0.type: "Point" } - ---- -"Execute with geo point field context (multi-value, fields api)": - - skip: - features: close_to - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('p0').values[0].lat + 1.0, field('p0').values[0].lon - 1.0); - emit(field('p1').values[0].lat + 1.0, field('p1').values[0].lon - 1.0)" - context: "geo_point_field" - context_setup: - document: - p0: "30.0,40.0" - p1: "40.0,30.0" - index: "my-index" - - close_to: { result.0.coordinates.0: { value: 39.0, error: 0.00001 } } - - close_to: { result.0.coordinates.1: { value: 31.0, error: 0.00001 } } - - match: { result.0.type: "Point" } - - close_to: { result.1.coordinates.0: { value: 29.0, error: 0.00001 } } - - close_to: { result.1.coordinates.1: { value: 41.0, error: 0.00001 } } - - match: { result.1.type: "Point" } - --- "Execute with ip field context (single-value)": - do: @@ -382,36 +247,6 @@ setup: index: "my-index" - match: { result: [ "2001:db8::8a2e:370:7333", "192.168.1.254", "2001:db8::8a2e:370:7334" ] } ---- -"Execute with ip field context (single-value, fields api)": - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('ip').getValue('0.0.0.0'));" - context: "ip_field" - context_setup: - document: - ip: "192.168.1.254" - index: "my-index" - - match: { result: [ "192.168.1.254" ] } - ---- -"Execute with ip field context (multi-value, fields api)": - - do: - scripts_painless_execute: - body: - script: - source: "emit('2001:0db8:0000:0000:0000:8a2e:0370:7333'); - emit(field('ip').getValue('0.0.0.0')); - emit('2001:db8::8a2e:370:7334')" - context: "ip_field" - context_setup: - document: - ip: "192.168.1.254" - index: "my-index" - - match: { result: [ "2001:db8::8a2e:370:7333", "192.168.1.254", "2001:db8::8a2e:370:7334" ] } - --- "Execute with long field context (single-value)": - do: @@ -444,38 +279,6 @@ setup: index: "my-index" - match: { result: [ 20, 35, 0, -90, 20 ] } ---- -"Execute with long field context (single-value, fields api)": - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('rank').getValue(0L) * (long)params.max_rank)" - params: - max_rank: 5.0 - context: "long_field" - context_setup: - document: - rank: 4 - index: "my-index" - - match: { result: [ 20 ] } - ---- -"Execute with long field context (multi-value, fields api)": - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('rank').getValue(0L) * (long)params.max_rank); emit(35); emit(0); emit(-90); emit(20);" - params: - max_rank: 5.0 - context: "long_field" - context_setup: - document: - rank: 4 - index: "my-index" - - match: { result: [ 20, 35, 0, -90, 20 ] } - --- "Execute with keyword field context (single-value)": - do: @@ -505,35 +308,6 @@ setup: - match: { result.0: "my_keyword" } - match: { result.1: "my_keyword_test" } ---- -"Execute with keyword field context (single-value, fields api)": - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('keyword').getValue(''));" - context: "keyword_field" - context_setup: - document: - keyword: "my_keyword" - index: "my-index" - - match: { result.0: "my_keyword" } - ---- -"Execute with keyword field context (multi-value, fields api)": - - do: - scripts_painless_execute: - body: - script: - source: "emit(field('keyword').getValue('')); emit(field('keyword').getValue('') + '_test');" - context: "keyword_field" - context_setup: - document: - keyword: "my_keyword" - index: "my-index" - - match: { result.0: "my_keyword" } - - match: { result.1: "my_keyword_test" } - --- "Execute against an empty index with no mappings": - do: From f64784296c85a40be2d6e08098d926e2b1822e1c Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 11 Oct 2021 12:43:18 -0700 Subject: [PATCH 3/7] add allowed methods for unsigned long field --- .../index/fielddata/LeafFieldData.java | 1 - .../org.elasticsearch.xpack.unsignedlong.txt | 13 ++++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/index/fielddata/LeafFieldData.java b/server/src/main/java/org/elasticsearch/index/fielddata/LeafFieldData.java index f537e61ed8613..46fdbfb510b52 100644 --- a/server/src/main/java/org/elasticsearch/index/fielddata/LeafFieldData.java +++ b/server/src/main/java/org/elasticsearch/index/fielddata/LeafFieldData.java @@ -11,7 +11,6 @@ import org.apache.lucene.util.Accountable; import org.elasticsearch.core.Releasable; import org.elasticsearch.script.field.DocValuesField; -import org.elasticsearch.script.field.Field; import org.elasticsearch.search.DocValueFormat; import java.io.IOException; diff --git a/x-pack/plugin/mapper-unsigned-long/src/main/resources/org/elasticsearch/xpack/unsignedlong/org.elasticsearch.xpack.unsignedlong.txt b/x-pack/plugin/mapper-unsigned-long/src/main/resources/org/elasticsearch/xpack/unsignedlong/org.elasticsearch.xpack.unsignedlong.txt index b3861fa9ed327..36d2939c79c94 100644 --- a/x-pack/plugin/mapper-unsigned-long/src/main/resources/org/elasticsearch/xpack/unsignedlong/org.elasticsearch.xpack.unsignedlong.txt +++ b/x-pack/plugin/mapper-unsigned-long/src/main/resources/org/elasticsearch/xpack/unsignedlong/org.elasticsearch.xpack.unsignedlong.txt @@ -11,10 +11,13 @@ class org.elasticsearch.xpack.unsignedlong.UnsignedLongScriptDocValues { long getValue() } - -class org.elasticsearch.script.field.Field { - org.elasticsearch.script.field.Converter UnsignedLong @augmented[augmented_canonical_class_name="org.elasticsearch.xpack.unsignedlong.UnsignedLongField"] +class org.elasticsearch.xpack.unsignedlong.UnsignedLongField { + long getLong(long) + long getLong(int, long) + BigInteger getBigInteger(BigInteger) + BigInteger getBigInteger(int, BigInteger) + List getBigIntegers() } -class org.elasticsearch.xpack.unsignedlong.UnsignedLongField @no_import { -} +class org.elasticsearch.xpack.unsignedlong.UnsignedLongDocValuesField { +} \ No newline at end of file From f7c110498e8bc95120e30aaa0df65171a7c73fa8 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Mon, 11 Oct 2021 15:22:53 -0700 Subject: [PATCH 4/7] move and update yaml tests for new field types --- .../org.elasticsearch.script.fields.txt | 2 +- .../index/fielddata/ScriptDocValues.java | 1 - .../plugin/mapper-unsigned-long/build.gradle | 9 +++++ .../UnsignedLongScriptDocValues.java | 4 +++ .../org.elasticsearch.xpack.unsignedlong.txt | 4 +-- .../UnsignedLongClientYamlTestSuiteIT.java | 35 +++++++++++++++++++ .../rest-api-spec/test}/10_basic.yml | 0 .../rest-api-spec/test}/20_null_value.yml | 0 .../rest-api-spec/test}/30_multi_fields.yml | 0 .../test}/40_different_numeric.yml | 0 .../rest-api-spec/test}/50_script_values.yml | 34 ++---------------- .../rest-api-spec/test}/60_collapse.yml | 0 .../versionfield/VersionScriptDocValues.java | 4 +++ 13 files changed, 58 insertions(+), 35 deletions(-) create mode 100644 x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongClientYamlTestSuiteIT.java rename x-pack/plugin/{src/yamlRestTest/resources/rest-api-spec/test/unsigned_long => mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test}/10_basic.yml (100%) rename x-pack/plugin/{src/yamlRestTest/resources/rest-api-spec/test/unsigned_long => mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test}/20_null_value.yml (100%) rename x-pack/plugin/{src/yamlRestTest/resources/rest-api-spec/test/unsigned_long => mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test}/30_multi_fields.yml (100%) rename x-pack/plugin/{src/yamlRestTest/resources/rest-api-spec/test/unsigned_long => mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test}/40_different_numeric.yml (100%) rename x-pack/plugin/{src/yamlRestTest/resources/rest-api-spec/test/unsigned_long => mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test}/50_script_values.yml (80%) rename x-pack/plugin/{src/yamlRestTest/resources/rest-api-spec/test/unsigned_long => mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test}/60_collapse.yml (100%) diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.fields.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.fields.txt index ed7024c81fd7c..83d7b6a137824 100644 --- a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.fields.txt +++ b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.fields.txt @@ -9,7 +9,7 @@ # The whitelist for the fields api # API -class org.elasticsearch.script.field.Field { +class org.elasticsearch.script.field.Field @dynamic_type { boolean isEmpty() int size() List getValues() diff --git a/server/src/main/java/org/elasticsearch/index/fielddata/ScriptDocValues.java b/server/src/main/java/org/elasticsearch/index/fielddata/ScriptDocValues.java index 7fc17a274dc7e..81346a65eb1bf 100644 --- a/server/src/main/java/org/elasticsearch/index/fielddata/ScriptDocValues.java +++ b/server/src/main/java/org/elasticsearch/index/fielddata/ScriptDocValues.java @@ -25,7 +25,6 @@ import java.util.AbstractList; import java.util.Arrays; import java.util.Comparator; -import java.util.List; import java.util.function.UnaryOperator; /** diff --git a/x-pack/plugin/mapper-unsigned-long/build.gradle b/x-pack/plugin/mapper-unsigned-long/build.gradle index 609cab576f807..4eac800de79d4 100644 --- a/x-pack/plugin/mapper-unsigned-long/build.gradle +++ b/x-pack/plugin/mapper-unsigned-long/build.gradle @@ -8,6 +8,8 @@ evaluationDependsOn(xpackModule('core')) apply plugin: 'elasticsearch.internal-es-plugin' +apply plugin: 'elasticsearch.internal-yaml-rest-test' +apply plugin: 'elasticsearch.yaml-rest-compat-test' esplugin { name 'unsigned-long' @@ -21,4 +23,11 @@ dependencies { compileOnly project(':modules:lang-painless:spi') compileOnly project(path: xpackModule('core')) testImplementation(testArtifact(project(xpackModule('core')))) + yamlRestTestImplementation(testArtifact(project(xpackModule('core')))) } + +restResources { + restApi { + include '_common', 'bulk', 'indices', 'index', 'search', 'xpack' + } +} \ No newline at end of file diff --git a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongScriptDocValues.java b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongScriptDocValues.java index b751790ba91cb..af31aafec68d5 100644 --- a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongScriptDocValues.java +++ b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongScriptDocValues.java @@ -49,6 +49,10 @@ protected void resize(int newSize) { values = ArrayUtil.grow(values, count); } + public long getValue() { + return get(0); + } + @Override public Long get(int index) { throwIfEmpty(); diff --git a/x-pack/plugin/mapper-unsigned-long/src/main/resources/org/elasticsearch/xpack/unsignedlong/org.elasticsearch.xpack.unsignedlong.txt b/x-pack/plugin/mapper-unsigned-long/src/main/resources/org/elasticsearch/xpack/unsignedlong/org.elasticsearch.xpack.unsignedlong.txt index 36d2939c79c94..bebec2e2a47da 100644 --- a/x-pack/plugin/mapper-unsigned-long/src/main/resources/org/elasticsearch/xpack/unsignedlong/org.elasticsearch.xpack.unsignedlong.txt +++ b/x-pack/plugin/mapper-unsigned-long/src/main/resources/org/elasticsearch/xpack/unsignedlong/org.elasticsearch.xpack.unsignedlong.txt @@ -11,7 +11,7 @@ class org.elasticsearch.xpack.unsignedlong.UnsignedLongScriptDocValues { long getValue() } -class org.elasticsearch.xpack.unsignedlong.UnsignedLongField { +class org.elasticsearch.xpack.unsignedlong.UnsignedLongField @dynamic_type { long getLong(long) long getLong(int, long) BigInteger getBigInteger(BigInteger) @@ -19,5 +19,5 @@ class org.elasticsearch.xpack.unsignedlong.UnsignedLongField { List getBigIntegers() } -class org.elasticsearch.xpack.unsignedlong.UnsignedLongDocValuesField { +class org.elasticsearch.xpack.unsignedlong.UnsignedLongDocValuesField @dynamic_type { } \ No newline at end of file diff --git a/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongClientYamlTestSuiteIT.java b/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongClientYamlTestSuiteIT.java new file mode 100644 index 0000000000000..9640ebc6408c7 --- /dev/null +++ b/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongClientYamlTestSuiteIT.java @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch.xpack.unsignedlong; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; +import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; + +/** Runs yaml rest tests */ +public class UnsignedLongClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase { + + public UnsignedLongClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { + super(testCandidate); + } + + @ParametersFactory + public static Iterable parameters() throws Exception { + return ESClientYamlSuiteTestCase.createParameters(); + } +} diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/10_basic.yml b/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/10_basic.yml similarity index 100% rename from x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/10_basic.yml rename to x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/10_basic.yml diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/20_null_value.yml b/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/20_null_value.yml similarity index 100% rename from x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/20_null_value.yml rename to x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/20_null_value.yml diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/30_multi_fields.yml b/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/30_multi_fields.yml similarity index 100% rename from x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/30_multi_fields.yml rename to x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/30_multi_fields.yml diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/40_different_numeric.yml b/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/40_different_numeric.yml similarity index 100% rename from x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/40_different_numeric.yml rename to x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/40_different_numeric.yml diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/50_script_values.yml b/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/50_script_values.yml similarity index 80% rename from x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/50_script_values.yml rename to x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/50_script_values.yml index a5efde6968847..c43f22a193f38 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/50_script_values.yml +++ b/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/50_script_values.yml @@ -88,7 +88,7 @@ setup: order: desc type: number script: - source: "field('ul').as(Field.BigInteger).getValue(BigInteger.valueOf(Long.parseUnsignedLong('18446744073709551614'))).doubleValue()" + source: "field('ul').getBigInteger(BigInteger.valueOf(Long.parseUnsignedLong('18446744073709551614'))).doubleValue()" - match: { hits.hits.0.sort: [1.8446744073709552E19] } - match: { hits.hits.1.sort: [1.8446744073709552E19] } @@ -142,7 +142,7 @@ setup: filter: script: script: - source: "field('ul').as(Field.BigInteger).getValue(BigInteger.valueOf(Long.parseUnsignedLong('18446744073709551614'))).doubleValue() > 10E18" + source: "field('ul').getBigInteger(BigInteger.valueOf(Long.parseUnsignedLong('18446744073709551614'))).doubleValue() > 10E18" sort: [ { ul: asc } ] - match: { hits.total.value: 2 } - match: { hits.hits.0._id: "4" } @@ -172,34 +172,6 @@ setup: source: "doc['ul'].value.doubleValue() > 9E18" - match: { hits.total.value: 1 } - match: { hits.hits.0._id: "2" } - - do: - search: - index: test1 - body: - query: - bool: - filter: - script: - script: - source: "field('ul').as(Field.BigInteger).as(Field.UnsignedLong).getDouble(-2.2d) > 9E18" - sort: [ { ul: asc } ] - - match: { hits.total.value: 4 } - - match: { hits.hits.0._id: "2" } - - match: { hits.hits.1._id: "3" } - - match: { hits.hits.2._id: "4" } - - match: { hits.hits.3._id: "5" } - - do: - search: - index: test1 - body: - query: - bool: - filter: - script: - script: - source: "field('ul').as(Field.BigInteger).as(Field.UnsignedLong).getLong(-2L) > 9E18" - - match: { hits.total.value: 1 } - - match: { hits.hits.0._id: "2" } - do: search: @@ -224,7 +196,7 @@ setup: script_score: query: {match_all: {}} script: - source: "field('ul').as(Field.BigInteger).getValue(BigInteger.valueOf(Long.parseUnsignedLong('18446744073709551614'))).doubleValue()" + source: "field('ul').getBigInteger(BigInteger.valueOf(Long.parseUnsignedLong('18446744073709551614'))).doubleValue()" - match: { hits.total.value: 5 } - do: diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/60_collapse.yml b/x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/60_collapse.yml similarity index 100% rename from x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/unsigned_long/60_collapse.yml rename to x-pack/plugin/mapper-unsigned-long/src/yamlRestTest/resources/rest-api-spec/test/60_collapse.yml diff --git a/x-pack/plugin/mapper-version/src/main/java/org/elasticsearch/xpack/versionfield/VersionScriptDocValues.java b/x-pack/plugin/mapper-version/src/main/java/org/elasticsearch/xpack/versionfield/VersionScriptDocValues.java index 9841fa643050d..25cd66a0eb212 100644 --- a/x-pack/plugin/mapper-version/src/main/java/org/elasticsearch/xpack/versionfield/VersionScriptDocValues.java +++ b/x-pack/plugin/mapper-version/src/main/java/org/elasticsearch/xpack/versionfield/VersionScriptDocValues.java @@ -34,6 +34,10 @@ public void setNextDocId(int docId) throws IOException { } } + public String getValue() { + return get(0); + } + @Override public String get(int index) { if (count == 0) { From a22956204ac5c7b7f427c37810ad9cca73afa024 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Wed, 13 Oct 2021 09:44:58 -0700 Subject: [PATCH 5/7] add removed tests to restcompat ignore --- x-pack/plugin/build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/x-pack/plugin/build.gradle b/x-pack/plugin/build.gradle index e08da7bff5895..676d4739f02c6 100644 --- a/x-pack/plugin/build.gradle +++ b/x-pack/plugin/build.gradle @@ -75,6 +75,14 @@ tasks.named("yamlRestTest").configure { dependsOn "copyExtraResources" } +tasks.named("yamlRestTestV7CompatTest").configure { + systemProperty 'tests.rest.blacklist', [ + 'unsigned_long/50_script_values/Scripted sort values', + 'unsigned_long/50_script_values/script_score query', + 'unsigned_long/50_script_values/Script query', + ].join(',') +} + tasks.named("yamlRestTestV7CompatTransform").configure{ task -> task.skipTest("vectors/10_dense_vector_basic/Deprecated function signature", "to support it, it would require to almost revert back the #48725 and complicate the code" ) task.skipTest("vectors/30_sparse_vector_basic/Cosine Similarity", "not supported for compatibility") From fbb2e328b40d40646bbf0d1faf9b84b4ca9d2be6 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Wed, 13 Oct 2021 11:35:56 -0700 Subject: [PATCH 6/7] add name back --- .../painless/org.elasticsearch.script.fields.txt | 1 + .../elasticsearch/index/fielddata/LeafFieldData.java | 2 +- .../java/org/elasticsearch/script/DocBasedScript.java | 2 +- .../org/elasticsearch/script/DocValuesDocReader.java | 2 +- .../org/elasticsearch/script/field/EmptyField.java | 11 +++++++++++ .../java/org/elasticsearch/script/field/Field.java | 3 +++ .../elasticsearch/search/lookup/LeafDocLookup.java | 2 +- .../unsignedlong/UnsignedLongDocValuesField.java | 10 +++++++++- .../xpack/unsignedlong/UnsignedLongLeafFieldData.java | 4 ++-- 9 files changed, 30 insertions(+), 7 deletions(-) diff --git a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.fields.txt b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.fields.txt index 83d7b6a137824..61986fab9423c 100644 --- a/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.fields.txt +++ b/modules/lang-painless/src/main/resources/org/elasticsearch/painless/org.elasticsearch.script.fields.txt @@ -10,6 +10,7 @@ # API class org.elasticsearch.script.field.Field @dynamic_type { + String getName() boolean isEmpty() int size() List getValues() diff --git a/server/src/main/java/org/elasticsearch/index/fielddata/LeafFieldData.java b/server/src/main/java/org/elasticsearch/index/fielddata/LeafFieldData.java index 46fdbfb510b52..69cf081da0d04 100644 --- a/server/src/main/java/org/elasticsearch/index/fielddata/LeafFieldData.java +++ b/server/src/main/java/org/elasticsearch/index/fielddata/LeafFieldData.java @@ -28,7 +28,7 @@ public interface LeafFieldData extends Accountable, Releasable { /** * Returns an {@code Field} for use in accessing field values in scripting. */ - default DocValuesField getScriptField() { + default DocValuesField getScriptField(String name) { throw new UnsupportedOperationException(); } diff --git a/server/src/main/java/org/elasticsearch/script/DocBasedScript.java b/server/src/main/java/org/elasticsearch/script/DocBasedScript.java index 9eb2fb4fab960..8ef8104652aed 100644 --- a/server/src/main/java/org/elasticsearch/script/DocBasedScript.java +++ b/server/src/main/java/org/elasticsearch/script/DocBasedScript.java @@ -25,7 +25,7 @@ public DocBasedScript(DocReader docReader) { public Field field(String fieldName) { if (docReader == null) { - return new EmptyField<>(); + return new EmptyField<>(fieldName); } return docReader.field(fieldName); } diff --git a/server/src/main/java/org/elasticsearch/script/DocValuesDocReader.java b/server/src/main/java/org/elasticsearch/script/DocValuesDocReader.java index e045b83596ac3..b295736fdb8d4 100644 --- a/server/src/main/java/org/elasticsearch/script/DocValuesDocReader.java +++ b/server/src/main/java/org/elasticsearch/script/DocValuesDocReader.java @@ -43,7 +43,7 @@ public Field field(String fieldName) { LeafDocLookup leafDocLookup = leafSearchLookup.doc(); if (leafDocLookup.containsKey(fieldName) == false) { - return new EmptyField<>(); + return new EmptyField<>(fieldName); } return leafDocLookup.getScriptField(fieldName); diff --git a/server/src/main/java/org/elasticsearch/script/field/EmptyField.java b/server/src/main/java/org/elasticsearch/script/field/EmptyField.java index e76b4a5d26ef8..968a82ebc9660 100644 --- a/server/src/main/java/org/elasticsearch/script/field/EmptyField.java +++ b/server/src/main/java/org/elasticsearch/script/field/EmptyField.java @@ -16,6 +16,17 @@ */ public class EmptyField implements Field { + private final String name; + + public EmptyField(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + @Override public boolean isEmpty() { return true; diff --git a/server/src/main/java/org/elasticsearch/script/field/Field.java b/server/src/main/java/org/elasticsearch/script/field/Field.java index 4e8398c598ad2..3d927afd3dd32 100644 --- a/server/src/main/java/org/elasticsearch/script/field/Field.java +++ b/server/src/main/java/org/elasticsearch/script/field/Field.java @@ -14,6 +14,9 @@ /** A field in a document accessible via scripting. */ public interface Field { + /** Returns the name of this field. */ + String getName(); + /** Returns {@code true} if this field has no values, otherwise {@code false}. */ boolean isEmpty(); diff --git a/server/src/main/java/org/elasticsearch/search/lookup/LeafDocLookup.java b/server/src/main/java/org/elasticsearch/search/lookup/LeafDocLookup.java index 88ec4b7595959..9352e91341c9b 100644 --- a/server/src/main/java/org/elasticsearch/search/lookup/LeafDocLookup.java +++ b/server/src/main/java/org/elasticsearch/search/lookup/LeafDocLookup.java @@ -60,7 +60,7 @@ public DocValuesField getScriptField(String fieldName) { field = AccessController.doPrivileged(new PrivilegedAction>() { @Override public DocValuesField run() { - return fieldDataLookup.apply(fieldType).load(reader).getScriptField(); + return fieldDataLookup.apply(fieldType).load(reader).getScriptField(fieldName); } }); diff --git a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongDocValuesField.java b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongDocValuesField.java index 1e62550732ddd..9739b63e9da7d 100644 --- a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongDocValuesField.java +++ b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongDocValuesField.java @@ -26,8 +26,11 @@ public class UnsignedLongDocValuesField implements UnsignedLongField, DocValuesF private long[] values = new long[0]; private int count; - public UnsignedLongDocValuesField(SortedNumericDocValues input) { + private final String name; + + public UnsignedLongDocValuesField(SortedNumericDocValues input, String name) { this.input = input; + this.name = name; } @Override @@ -47,6 +50,11 @@ protected void resize(int newSize) { values = ArrayUtil.grow(values, count); } + @Override + public String getName() { + return name; + } + @Override public boolean isEmpty() { return count == 0; diff --git a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongLeafFieldData.java b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongLeafFieldData.java index d5100d2d20f6f..30575818d169a 100644 --- a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongLeafFieldData.java +++ b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongLeafFieldData.java @@ -79,8 +79,8 @@ public ScriptDocValues getScriptValues() { } @Override - public DocValuesField getScriptField() { - return new UnsignedLongDocValuesField(getLongValues()); + public DocValuesField getScriptField(String name) { + return new UnsignedLongDocValuesField(getLongValues(), name); } @Override From 44e5c1d66a6531c0fc9d50deb8f353ff76498be1 Mon Sep 17 00:00:00 2001 From: Jack Conradson Date: Wed, 13 Oct 2021 13:36:09 -0700 Subject: [PATCH 7/7] add javadoc for unsignedlongfield --- .../elasticsearch/xpack/unsignedlong/UnsignedLongField.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongField.java b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongField.java index fa3e60e869e70..96b8c730eed69 100644 --- a/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongField.java +++ b/x-pack/plugin/mapper-unsigned-long/src/main/java/org/elasticsearch/xpack/unsignedlong/UnsignedLongField.java @@ -14,13 +14,18 @@ public interface UnsignedLongField extends Field { + /** Returns the 0th index value as an {@code long} if it exists, otherwise {@code defaultValue}. */ long getLong(long defaultValue); + /** Returns the value at {@code index} as an {@code long} if it exists, otherwise {@code defaultValue}. */ long getLong(int index, long defaultValue); + /** Returns the 0th index value as a {@code BigInteger} if it exists, otherwise {@code defaultValue}. */ BigInteger getBigInteger(BigInteger defaultValue); + /** Returns the value at {@code index} as a {@code BigInteger} if it exists, otherwise {@code defaultValue}. */ BigInteger getBigInteger(int index, BigInteger defaultValue); + /** Converts all the values to {@code BigInteger} and returns them as a {@code List}. */ List getBigIntegers(); }