diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/Filter.java b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/Filter.java index db5276e8d..00801fd00 100755 --- a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/Filter.java +++ b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/Filter.java @@ -27,6 +27,7 @@ import org.apache.tsfile.read.filter.factory.ValueFilterApi; import org.apache.tsfile.read.filter.operator.And; import org.apache.tsfile.read.filter.operator.ExtractTimeFilterOperators; +import org.apache.tsfile.read.filter.operator.ExtractValueFilterOperators; import org.apache.tsfile.read.filter.operator.GroupByFilter; import org.apache.tsfile.read.filter.operator.GroupByMonthFilter; import org.apache.tsfile.read.filter.operator.Not; @@ -258,6 +259,18 @@ public static Filter deserialize(ByteBuffer buffer) { return new ExtractTimeFilterOperators.ExtractTimeLt(buffer); case EXTRACT_TIME_LTEQ: return new ExtractTimeFilterOperators.ExtractTimeLtEq(buffer); + case EXTRACT_VALUE_EQ: + return new ExtractValueFilterOperators.ExtractValueEq(buffer); + case EXTRACT_VALUE_NEQ: + return new ExtractValueFilterOperators.ExtractValueNotEq(buffer); + case EXTRACT_VALUE_GT: + return new ExtractValueFilterOperators.ExtractValueGt(buffer); + case EXTRACT_VALUE_GTEQ: + return new ExtractValueFilterOperators.ExtractValueGtEq(buffer); + case EXTRACT_VALUE_LT: + return new ExtractValueFilterOperators.ExtractValueLt(buffer); + case EXTRACT_VALUE_LTEQ: + return new ExtractValueFilterOperators.ExtractValueLtEq(buffer); default: throw new UnsupportedOperationException("Unsupported operator type:" + type); } diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/OperatorType.java b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/OperatorType.java index bad1ce76e..d898e0097 100644 --- a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/OperatorType.java +++ b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/OperatorType.java @@ -73,7 +73,13 @@ public enum OperatorType { EXTRACT_TIME_GT(">"), EXTRACT_TIME_GTEQ(">="), EXTRACT_TIME_LT("<"), - EXTRACT_TIME_LTEQ("<="); + EXTRACT_TIME_LTEQ("<="), + EXTRACT_VALUE_EQ("="), + EXTRACT_VALUE_NEQ("!="), + EXTRACT_VALUE_GT(">"), + EXTRACT_VALUE_GTEQ(">="), + EXTRACT_VALUE_LT("<"), + EXTRACT_VALUE_LTEQ("<="); private final String symbol; diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/TimeFilter.java b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/TimeFilter.java index 18d444d7c..f1789b4bf 100644 --- a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/TimeFilter.java +++ b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/TimeFilter.java @@ -137,7 +137,7 @@ public boolean[] satisfyTsBlock(boolean[] selection, TsBlock tsBlock) { return satisfyInfo; } - protected abstract boolean timeSatisfy(long time); + public abstract boolean timeSatisfy(long time); @Override public boolean canSkip(IMetadata metadata) { diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/factory/ValueFilterApi.java b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/factory/ValueFilterApi.java index 53c4b74c2..6ccec7ecc 100644 --- a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/factory/ValueFilterApi.java +++ b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/factory/ValueFilterApi.java @@ -25,6 +25,8 @@ import org.apache.tsfile.read.filter.operator.BinaryFilterOperators; import org.apache.tsfile.read.filter.operator.BooleanFilterOperators; import org.apache.tsfile.read.filter.operator.DoubleFilterOperators; +import org.apache.tsfile.read.filter.operator.ExtractTimeFilterOperators; +import org.apache.tsfile.read.filter.operator.ExtractValueFilterOperators; import org.apache.tsfile.read.filter.operator.FloatFilterOperators; import org.apache.tsfile.read.filter.operator.IntegerFilterOperators; import org.apache.tsfile.read.filter.operator.LongFilterOperators; @@ -33,8 +35,10 @@ import org.apache.tsfile.read.filter.operator.ValueIsNullOperator; import org.apache.tsfile.utils.Binary; +import java.time.ZoneId; import java.util.Objects; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; public class ValueFilterApi { @@ -435,4 +439,64 @@ public static > Filter notIn( throw new UnsupportedOperationException("Unsupported data type: " + type); } } + + public static Filter extractValueGt( + int measurementIndex, + long value, + ExtractTimeFilterOperators.Field field, + ZoneId zoneId, + TimeUnit currPrecision) { + return new ExtractValueFilterOperators.ExtractValueGt( + measurementIndex, value, field, zoneId, currPrecision); + } + + public static Filter extractValueGtEq( + int measurementIndex, + long value, + ExtractTimeFilterOperators.Field field, + ZoneId zoneId, + TimeUnit currPrecision) { + return new ExtractValueFilterOperators.ExtractValueGtEq( + measurementIndex, value, field, zoneId, currPrecision); + } + + public static Filter extractValueLt( + int measurementIndex, + long value, + ExtractTimeFilterOperators.Field field, + ZoneId zoneId, + TimeUnit currPrecision) { + return new ExtractValueFilterOperators.ExtractValueLt( + measurementIndex, value, field, zoneId, currPrecision); + } + + public static Filter extractValueLtEq( + int measurementIndex, + long value, + ExtractTimeFilterOperators.Field field, + ZoneId zoneId, + TimeUnit currPrecision) { + return new ExtractValueFilterOperators.ExtractValueLtEq( + measurementIndex, value, field, zoneId, currPrecision); + } + + public static Filter extractValueEq( + int measurementIndex, + long value, + ExtractTimeFilterOperators.Field field, + ZoneId zoneId, + TimeUnit currPrecision) { + return new ExtractValueFilterOperators.ExtractValueEq( + measurementIndex, value, field, zoneId, currPrecision); + } + + public static Filter extractValueNotEq( + int measurementIndex, + long value, + ExtractTimeFilterOperators.Field field, + ZoneId zoneId, + TimeUnit currPrecision) { + return new ExtractValueFilterOperators.ExtractValueNotEq( + measurementIndex, value, field, zoneId, currPrecision); + } } diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/ExtractTimeFilterOperators.java b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/ExtractTimeFilterOperators.java index 8c43d1bfe..3c93af5a3 100644 --- a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/ExtractTimeFilterOperators.java +++ b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/ExtractTimeFilterOperators.java @@ -280,6 +280,22 @@ protected ExtractTimeCompareFilter(ByteBuffer buffer) { TimeUnit.values()[ReadWriteIOUtils.readInt(buffer)]); } + public long getConstant() { + return constant; + } + + public Field getField() { + return field; + } + + public TimeUnit getCurrPrecision() { + return currPrecision; + } + + public ZoneId getZoneId() { + return zoneId; + } + @Override public void serialize(DataOutputStream outputStream) throws IOException { super.serialize(outputStream); diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/ExtractValueFilterOperators.java b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/ExtractValueFilterOperators.java new file mode 100644 index 000000000..05a39f0a7 --- /dev/null +++ b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/ExtractValueFilterOperators.java @@ -0,0 +1,341 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tsfile.read.filter.operator; + +import org.apache.tsfile.file.metadata.statistics.Statistics; +import org.apache.tsfile.read.filter.basic.Filter; +import org.apache.tsfile.read.filter.basic.LongFilter; +import org.apache.tsfile.read.filter.basic.OperatorType; +import org.apache.tsfile.utils.ReadWriteIOUtils; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.time.ZoneId; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +public final class ExtractValueFilterOperators { + + private ExtractValueFilterOperators() { + // forbidden construction + } + + private static final String EXTRACT_OPERATOR_TO_STRING_FORMAT = + "extract %s from measurements[%s] %s %s"; + + // The input type of Extract must be INT64 + abstract static class ExtractValueCompareFilter extends LongFilter { + + protected final ExtractTimeFilterOperators.ExtractTimeCompareFilter delegate; + + protected ExtractValueCompareFilter( + int measurementIndex, ExtractTimeFilterOperators.ExtractTimeCompareFilter delegate) { + super(measurementIndex); + this.delegate = delegate; + } + + @Override + public void serialize(DataOutputStream outputStream) throws IOException { + super.serialize(outputStream); + delegate.serialize(outputStream); + } + + @Override + public boolean valueSatisfy(Object value) { + return valueSatisfy((long) value); + } + + @Override + public boolean valueSatisfy(long value) { + return delegate.timeSatisfy(value); + } + + @Override + @SuppressWarnings("unchecked") + public boolean canSkip(Statistics statistics) { + if (statistics.isEmpty()) { + return false; + } + // has no intersection + return !delegate.satisfyStartEndTime( + (Long) statistics.getMinValue(), (Long) statistics.getMaxValue()); + } + + @Override + @SuppressWarnings("unchecked") + public boolean allSatisfy(Statistics statistics) { + if (statistics.isEmpty()) { + return false; + } + // contains all start and end time + return delegate.containStartEndTime( + (Long) statistics.getMinValue(), (Long) statistics.getMaxValue()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + ExtractTimeFilterOperators.ExtractTimeCompareFilter thatDelegate = + ((ExtractValueCompareFilter) o).delegate; + return delegate.equals(thatDelegate); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), delegate); + } + + @Override + public String toString() { + return String.format( + EXTRACT_OPERATOR_TO_STRING_FORMAT, + delegate.getField(), + measurementIndex, + getOperatorType().getSymbol(), + delegate.getConstant()); + } + } + + public static final class ExtractValueEq extends ExtractValueCompareFilter { + + public ExtractValueEq( + int measurementIndex, + long constant, + ExtractTimeFilterOperators.Field field, + ZoneId zoneId, + TimeUnit currPrecision) { + super( + measurementIndex, + new ExtractTimeFilterOperators.ExtractTimeEq(constant, field, zoneId, currPrecision)); + } + + public ExtractValueEq(ByteBuffer buffer) { + super( + ReadWriteIOUtils.readInt(buffer), + (ExtractTimeFilterOperators.ExtractTimeCompareFilter) + ExtractTimeFilterOperators.ExtractTimeEq.deserialize(buffer)); + } + + @Override + public Filter reverse() { + return new ExtractValueNotEq( + measurementIndex, + delegate.getConstant(), + delegate.getField(), + delegate.getZoneId(), + delegate.getCurrPrecision()); + } + + @Override + public OperatorType getOperatorType() { + return OperatorType.EXTRACT_VALUE_EQ; + } + } + + public static final class ExtractValueNotEq extends ExtractValueCompareFilter { + + public ExtractValueNotEq( + int measurementIndex, + long constant, + ExtractTimeFilterOperators.Field field, + ZoneId zoneId, + TimeUnit currPrecision) { + super( + measurementIndex, + new ExtractTimeFilterOperators.ExtractTimeNotEq(constant, field, zoneId, currPrecision)); + } + + public ExtractValueNotEq(ByteBuffer buffer) { + super( + ReadWriteIOUtils.readInt(buffer), + (ExtractTimeFilterOperators.ExtractTimeCompareFilter) + ExtractTimeFilterOperators.ExtractTimeNotEq.deserialize(buffer)); + } + + @Override + public Filter reverse() { + return new ExtractValueEq( + measurementIndex, + delegate.getConstant(), + delegate.getField(), + delegate.getZoneId(), + delegate.getCurrPrecision()); + } + + @Override + public OperatorType getOperatorType() { + return OperatorType.EXTRACT_VALUE_NEQ; + } + } + + public static final class ExtractValueLt extends ExtractValueCompareFilter { + + public ExtractValueLt( + int measurementIndex, + long constant, + ExtractTimeFilterOperators.Field field, + ZoneId zoneId, + TimeUnit currPrecision) { + super( + measurementIndex, + new ExtractTimeFilterOperators.ExtractTimeLt(constant, field, zoneId, currPrecision)); + } + + public ExtractValueLt(ByteBuffer buffer) { + super( + ReadWriteIOUtils.readInt(buffer), + (ExtractTimeFilterOperators.ExtractTimeCompareFilter) + ExtractTimeFilterOperators.ExtractTimeLt.deserialize(buffer)); + } + + @Override + public Filter reverse() { + return new ExtractValueGtEq( + measurementIndex, + delegate.getConstant(), + delegate.getField(), + delegate.getZoneId(), + delegate.getCurrPrecision()); + } + + @Override + public OperatorType getOperatorType() { + return OperatorType.EXTRACT_VALUE_LT; + } + } + + public static final class ExtractValueLtEq extends ExtractValueCompareFilter { + + public ExtractValueLtEq( + int measurementIndex, + long constant, + ExtractTimeFilterOperators.Field field, + ZoneId zoneId, + TimeUnit currPrecision) { + super( + measurementIndex, + new ExtractTimeFilterOperators.ExtractTimeLtEq(constant, field, zoneId, currPrecision)); + } + + public ExtractValueLtEq(ByteBuffer buffer) { + super( + ReadWriteIOUtils.readInt(buffer), + (ExtractTimeFilterOperators.ExtractTimeCompareFilter) + ExtractTimeFilterOperators.ExtractTimeLtEq.deserialize(buffer)); + } + + @Override + public Filter reverse() { + return new ExtractValueGt( + measurementIndex, + delegate.getConstant(), + delegate.getField(), + delegate.getZoneId(), + delegate.getCurrPrecision()); + } + + @Override + public OperatorType getOperatorType() { + return OperatorType.EXTRACT_VALUE_LTEQ; + } + } + + public static final class ExtractValueGt extends ExtractValueCompareFilter { + + public ExtractValueGt( + int measurementIndex, + long constant, + ExtractTimeFilterOperators.Field field, + ZoneId zoneId, + TimeUnit currPrecision) { + super( + measurementIndex, + new ExtractTimeFilterOperators.ExtractTimeGt(constant, field, zoneId, currPrecision)); + } + + public ExtractValueGt(ByteBuffer buffer) { + super( + ReadWriteIOUtils.readInt(buffer), + (ExtractTimeFilterOperators.ExtractTimeCompareFilter) + ExtractTimeFilterOperators.ExtractTimeGt.deserialize(buffer)); + } + + @Override + public Filter reverse() { + return new ExtractValueLtEq( + measurementIndex, + delegate.getConstant(), + delegate.getField(), + delegate.getZoneId(), + delegate.getCurrPrecision()); + } + + @Override + public OperatorType getOperatorType() { + return OperatorType.EXTRACT_VALUE_GT; + } + } + + public static final class ExtractValueGtEq extends ExtractValueCompareFilter { + + public ExtractValueGtEq( + int measurementIndex, + long constant, + ExtractTimeFilterOperators.Field field, + ZoneId zoneId, + TimeUnit currPrecision) { + super( + measurementIndex, + new ExtractTimeFilterOperators.ExtractTimeGtEq(constant, field, zoneId, currPrecision)); + } + + public ExtractValueGtEq(ByteBuffer buffer) { + super( + ReadWriteIOUtils.readInt(buffer), + (ExtractTimeFilterOperators.ExtractTimeCompareFilter) + ExtractTimeFilterOperators.ExtractTimeGtEq.deserialize(buffer)); + } + + @Override + public Filter reverse() { + return new ExtractValueLt( + measurementIndex, + delegate.getConstant(), + delegate.getField(), + delegate.getZoneId(), + delegate.getCurrPrecision()); + } + + @Override + public OperatorType getOperatorType() { + return OperatorType.EXTRACT_VALUE_GTEQ; + } + } +} diff --git a/java/tsfile/src/test/java/org/apache/tsfile/read/filter/ExtractValueFilterTest.java b/java/tsfile/src/test/java/org/apache/tsfile/read/filter/ExtractValueFilterTest.java new file mode 100644 index 000000000..63cb0b043 --- /dev/null +++ b/java/tsfile/src/test/java/org/apache/tsfile/read/filter/ExtractValueFilterTest.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tsfile.read.filter; + +import org.apache.tsfile.file.metadata.IMetadata; +import org.apache.tsfile.file.metadata.statistics.LongStatistics; +import org.apache.tsfile.read.filter.basic.ValueFilter; +import org.apache.tsfile.read.filter.factory.ValueFilterApi; +import org.apache.tsfile.read.filter.operator.ExtractTimeFilterOperators; +import org.apache.tsfile.read.filter.operator.ExtractValueFilterOperators; + +import org.junit.Assert; +import org.junit.Test; + +import java.time.ZoneId; +import java.util.concurrent.TimeUnit; + +import static org.apache.tsfile.read.filter.FilterTestUtil.newMetadata; + +public class ExtractValueFilterTest { + private final ZoneId zoneId1 = ZoneId.of("+0000"); + private final ZoneId zoneId2 = ZoneId.of("+0800"); + + private final LongStatistics statistics = new LongStatistics(); + private final IMetadata metadata = newMetadata(statistics); + + // Test delegate logic is right + @Test + public void test() { + statistics.setEmpty(false); + // 2025/07/08 09:18:51 00:00:00+8:00 + long testTime1 = 1751937531000L; + // 2025/07/08 10:18:51 00:00:00+8:00 + long testTime2 = 1751941131000L; + + // 1751936400000L -> 2025/07/08 09:00:00+8:00 + // 1751940000000L -> 2025/07/08 10:00:00+8:00 + ValueFilter extractValueEq1 = + new ExtractValueFilterOperators.ExtractValueEq( + ValueFilterApi.DEFAULT_MEASUREMENT_INDEX, + 1, + ExtractTimeFilterOperators.Field.HOUR, + zoneId1, + TimeUnit.MILLISECONDS); + Assert.assertTrue(extractValueEq1.satisfy(testTime1, testTime1)); + Assert.assertFalse(extractValueEq1.satisfy(testTime2, testTime2)); + statistics.initializeStats(testTime1 - 1, testTime1 + 1, 0, 0, 0); + Assert.assertFalse(extractValueEq1.canSkip(metadata)); + statistics.initializeStats(1751936400000L, 2751936400000L, 0, 0, 0); + Assert.assertFalse(extractValueEq1.canSkip(metadata)); + statistics.initializeStats(1751936400000L - 1, testTime1 + 1, 0, 0, 0); + Assert.assertFalse(extractValueEq1.canSkip(metadata)); + statistics.initializeStats(1751936400000L - 2, 1751936400000L - 1, 0, 0, 0); + Assert.assertTrue(extractValueEq1.canSkip(metadata)); + + statistics.initializeStats(1751936400000L, 1751940000000L - 1, 0, 0, 0); + Assert.assertTrue(extractValueEq1.allSatisfy(metadata)); + statistics.initializeStats(testTime1 - 1, testTime1 + 1, 0, 0, 0); + Assert.assertTrue(extractValueEq1.allSatisfy(metadata)); + statistics.initializeStats(1751936400000L - 1, 1751940000000L, 0, 0, 0); + Assert.assertFalse(extractValueEq1.allSatisfy(metadata)); + statistics.initializeStats(1751936400000L - 1, testTime1 + 1, 0, 0, 0); + Assert.assertFalse(extractValueEq1.allSatisfy(metadata)); + statistics.initializeStats(1751936400000L - 2, 1751936400000L - 1, 0, 0, 0); + Assert.assertFalse(extractValueEq1.allSatisfy(metadata)); + statistics.initializeStats(1751936400000L, 2751936400000L, 0, 0, 0); + Assert.assertFalse(extractValueEq1.allSatisfy(metadata)); + + ValueFilter extractValueEq2 = + new ExtractValueFilterOperators.ExtractValueEq( + ValueFilterApi.DEFAULT_MEASUREMENT_INDEX, + 9, + ExtractTimeFilterOperators.Field.HOUR, + zoneId2, + TimeUnit.MILLISECONDS); + Assert.assertTrue(extractValueEq2.satisfy(testTime1, testTime1)); + Assert.assertFalse(extractValueEq2.satisfy(testTime2, testTime2)); + statistics.initializeStats(testTime1 - 1, testTime1 + 1, 0, 0, 0); + Assert.assertFalse(extractValueEq2.canSkip(metadata)); + statistics.initializeStats(1751936400000L, 2751936400000L, 0, 0, 0); + Assert.assertFalse(extractValueEq2.canSkip(metadata)); + statistics.initializeStats(1751936400000L - 1, testTime1 + 1, 0, 0, 0); + Assert.assertFalse(extractValueEq2.canSkip(metadata)); + statistics.initializeStats(1751936400000L - 2, 1751936400000L - 1, 0, 0, 0); + Assert.assertTrue(extractValueEq2.canSkip(metadata)); + + statistics.initializeStats(1751936400000L, 1751940000000L - 1, 0, 0, 0); + Assert.assertTrue(extractValueEq2.allSatisfy(metadata)); + statistics.initializeStats(testTime1 - 1, testTime1 + 1, 0, 0, 0); + Assert.assertTrue(extractValueEq2.allSatisfy(metadata)); + statistics.initializeStats(1751936400000L - 1, 1751940000000L, 0, 0, 0); + Assert.assertFalse(extractValueEq2.allSatisfy(metadata)); + statistics.initializeStats(1751936400000L - 1, testTime1 + 1, 0, 0, 0); + Assert.assertFalse(extractValueEq2.allSatisfy(metadata)); + statistics.initializeStats(1751936400000L - 2, 1751936400000L - 1, 0, 0, 0); + Assert.assertFalse(extractValueEq2.allSatisfy(metadata)); + statistics.initializeStats(1751936400000L, 2751936400000L, 0, 0, 0); + Assert.assertFalse(extractValueEq2.allSatisfy(metadata)); + } +}