Merge remote-tracking branch 'origin/master'

This commit is contained in:
Noble Paul 2016-08-22 23:18:13 +05:30
commit 488e41d1fc
36 changed files with 222 additions and 1910 deletions

View File

@ -14,7 +14,6 @@
<orderEntry type="library" scope="TEST" name="JUnit" level="project" />
<orderEntry type="module" scope="TEST" module-name="lucene-test-framework" />
<orderEntry type="module" module-name="grouping" />
<orderEntry type="module" module-name="backward-codecs" />
<orderEntry type="module" module-name="lucene-core" />
</component>
</module>

View File

@ -17,6 +17,5 @@
<orderEntry type="module" module-name="lucene-core" />
<orderEntry type="module" module-name="queries" />
<orderEntry type="module" module-name="sandbox" />
<orderEntry type="module" module-name="backward-codecs" />
</component>
</module>

View File

@ -26,7 +26,6 @@
<path id="classpath">
<pathelement path="${grouping.jar}"/>
<pathelement path="${backward-codecs.jar}"/>
<path refid="base.classpath"/>
</path>
@ -35,14 +34,13 @@
<pathelement location="${build.dir}/classes/java"/>
</path>
<target name="init" depends="module-build.init,jar-grouping,jar-backward-codecs"/>
<target name="init" depends="module-build.init,jar-grouping"/>
<target name="javadocs" depends="javadocs-grouping,javadocs-backward-codecs,compile-core,check-javadocs-uptodate"
<target name="javadocs" depends="javadocs-grouping,compile-core,check-javadocs-uptodate"
unless="javadocs-uptodate-${name}">
<invoke-module-javadoc>
<links>
<link href="../grouping"/>
<link href="../backward-codecs"/>
</links>
</invoke-module-javadoc>
</target>

View File

@ -17,20 +17,13 @@
package org.apache.lucene.search.join;
import java.io.IOException;
import java.util.function.LongConsumer;
import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.NumericDocValues;
import org.apache.lucene.index.SortedNumericDocValues;
import org.apache.lucene.index.SortedSetDocValues;
import org.apache.lucene.legacy.LegacyNumericType;
import org.apache.lucene.legacy.LegacyNumericUtils;
import org.apache.lucene.search.SimpleCollector;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefBuilder;
abstract class DocValuesTermsCollector<DV> extends SimpleCollector {
@ -57,79 +50,4 @@ abstract class DocValuesTermsCollector<DV> extends SimpleCollector {
static Function<SortedSetDocValues> sortedSetDocValues(String field) {
return (ctx) -> DocValues.getSortedSet(ctx, field);
}
static Function<BinaryDocValues> numericAsBinaryDocValues(String field, LegacyNumericType numTyp) {
return (ctx) -> {
final NumericDocValues numeric = DocValues.getNumeric(ctx, field);
final BytesRefBuilder bytes = new BytesRefBuilder();
final LongConsumer coder = coder(bytes, numTyp, field);
return new BinaryDocValues() {
@Override
public BytesRef get(int docID) {
final long lVal = numeric.get(docID);
coder.accept(lVal);
return bytes.get();
}
};
};
}
static LongConsumer coder(BytesRefBuilder bytes, LegacyNumericType type, String fieldName){
switch(type){
case INT:
return (l) -> LegacyNumericUtils.intToPrefixCoded((int) l, 0, bytes);
case LONG:
return (l) -> LegacyNumericUtils.longToPrefixCoded(l, 0, bytes);
default:
throw new IllegalArgumentException("Unsupported "+type+
". Only "+ LegacyNumericType.INT+" and "+ LegacyNumericType.LONG+" are supported."
+ "Field "+fieldName );
}
}
/** this adapter is quite weird. ords are per doc index, don't use ords across different docs*/
static Function<SortedSetDocValues> sortedNumericAsSortedSetDocValues(String field, LegacyNumericType numTyp) {
return (ctx) -> {
final SortedNumericDocValues numerics = DocValues.getSortedNumeric(ctx, field);
final BytesRefBuilder bytes = new BytesRefBuilder();
final LongConsumer coder = coder(bytes, numTyp, field);
return new SortedSetDocValues() {
private int index = Integer.MIN_VALUE;
@Override
public long nextOrd() {
return index < numerics.count()-1 ? ++index : NO_MORE_ORDS;
}
@Override
public void setDocument(int docID) {
numerics.setDocument(docID);
index=-1;
}
@Override
public BytesRef lookupOrd(long ord) {
assert ord>=0 && ord<numerics.count();
final long value = numerics.valueAt((int)ord);
coder.accept(value);
return bytes.get();
}
@Override
public long getValueCount() {
throw new UnsupportedOperationException("it's just number encoding wrapper");
}
@Override
public long lookupTerm(BytesRef key) {
throw new UnsupportedOperationException("it's just number encoding wrapper");
}
};
};
}
}

View File

@ -26,7 +26,6 @@ import java.util.function.BiConsumer;
import java.util.function.LongFunction;
import org.apache.lucene.document.DoublePoint;
import org.apache.lucene.legacy.LegacyNumericType;
import org.apache.lucene.document.FloatPoint;
import org.apache.lucene.document.IntPoint;
import org.apache.lucene.document.LongPoint;
@ -111,50 +110,6 @@ public final class JoinUtil {
}
/**
* @deprecated Because {@link LegacyNumericType} is deprecated, instead use {@link #createJoinQuery(String, boolean, String, Class, Query, IndexSearcher, ScoreMode)}
*
* Method for query time joining for numeric fields. It supports multi- and single- values longs and ints.
* All considerations from {@link JoinUtil#createJoinQuery(String, boolean, String, Query, IndexSearcher, ScoreMode)} are applicable here too,
* though memory consumption might be higher.
* <p>
*
* @param fromField The from field to join from
* @param multipleValuesPerDocument Whether the from field has multiple terms per document
* when true fromField might be {@link DocValuesType#SORTED_NUMERIC},
* otherwise fromField should be {@link DocValuesType#NUMERIC}
* @param toField The to field to join to, should be {@link org.apache.lucene.legacy.LegacyIntField} or {@link org.apache.lucene.legacy.LegacyLongField}
* @param numericType either {@link LegacyNumericType#INT} or {@link LegacyNumericType#LONG}, it should correspond to fromField and toField types
* @param fromQuery The query to match documents on the from side
* @param fromSearcher The searcher that executed the specified fromQuery
* @param scoreMode Instructs how scores from the fromQuery are mapped to the returned query
* @return a {@link Query} instance that can be used to join documents based on the
* terms in the from and to field
* @throws IOException If I/O related errors occur
*/
@Deprecated
public static Query createJoinQuery(String fromField,
boolean multipleValuesPerDocument,
String toField, LegacyNumericType numericType,
Query fromQuery,
IndexSearcher fromSearcher,
ScoreMode scoreMode) throws IOException {
final GenericTermsCollector termsCollector;
if (multipleValuesPerDocument) {
Function<SortedSetDocValues> mvFunction = DocValuesTermsCollector.sortedNumericAsSortedSetDocValues(fromField,numericType);
termsCollector = GenericTermsCollector.createCollectorMV(mvFunction, scoreMode);
} else {
Function<BinaryDocValues> svFunction = DocValuesTermsCollector.numericAsBinaryDocValues(fromField,numericType);
termsCollector = GenericTermsCollector.createCollectorSV(svFunction, scoreMode);
}
return createJoinQuery(multipleValuesPerDocument, toField, fromQuery, fromSearcher, scoreMode,
termsCollector);
}
/**
* Method for query time joining for numeric fields. It supports multi- and single- values longs, ints, floats and longs.
* All considerations from {@link JoinUtil#createJoinQuery(String, boolean, String, Query, IndexSearcher, ScoreMode)} are applicable here too,

View File

@ -27,7 +27,6 @@ import org.apache.lucene.index.PostingsEnum;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.legacy.LegacyNumericUtils;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
@ -245,14 +244,6 @@ class TermsIncludingScoreQuery extends Query {
for (int i = 0; i < terms.size(); i++) {
terms.get(ords[i], ref);
out.print(ref+" "+ref.utf8ToString()+" ");
try {
out.print(Long.toHexString(LegacyNumericUtils.prefixCodedToLong(ref))+"L");
} catch (Exception e) {
try {
out.print(Integer.toHexString(LegacyNumericUtils.prefixCodedToInt(ref))+"i");
} catch (Exception ee) {
}
}
out.println(" score="+scores[ords[i]]);
out.println("");
}

View File

@ -56,9 +56,6 @@ import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.MultiDocValues;
import org.apache.lucene.index.MultiDocValues.OrdinalMap;
import org.apache.lucene.legacy.LegacyIntField;
import org.apache.lucene.legacy.LegacyLongField;
import org.apache.lucene.legacy.LegacyNumericType;
import org.apache.lucene.index.MultiFields;
import org.apache.lucene.index.NoMergePolicy;
import org.apache.lucene.index.NumericDocValues;
@ -971,7 +968,7 @@ public class TestJoinUtil extends LuceneTestCase {
final String fromField = from ? "from":"to";
final String toField = from ? "to":"from";
int surpriseMe = random().nextInt(3);
int surpriseMe = random().nextInt(2);
switch (surpriseMe) {
case 0:
Class<? extends Number> numType;
@ -992,10 +989,6 @@ public class TestJoinUtil extends LuceneTestCase {
joinQuery = JoinUtil.createJoinQuery(fromField + suffix, muliValsQuery, toField + suffix, numType, actualQuery, indexSearcher, scoreMode);
break;
case 1:
final LegacyNumericType legacyNumType = random().nextBoolean() ? LegacyNumericType.INT: LegacyNumericType.LONG ;
joinQuery = JoinUtil.createJoinQuery(fromField+legacyNumType, muliValsQuery, toField+legacyNumType, legacyNumType, actualQuery, indexSearcher, scoreMode);
break;
case 2:
joinQuery = JoinUtil.createJoinQuery(fromField, muliValsQuery, toField, actualQuery, indexSearcher, scoreMode);
break;
default:
@ -1336,26 +1329,24 @@ public class TestJoinUtil extends LuceneTestCase {
document.add(newTextField(random, fieldName, linkValue, Field.Store.NO));
final int linkInt = Integer.parseUnsignedInt(linkValue,16);
document.add(new LegacyIntField(fieldName + LegacyNumericType.INT, linkInt, Field.Store.NO));
document.add(new IntPoint(fieldName + LegacyNumericType.INT, linkInt));
document.add(new IntPoint(fieldName + "INT", linkInt));
document.add(new FloatPoint(fieldName + "FLOAT", linkInt));
final long linkLong = linkInt<<32 | linkInt;
document.add(new LegacyLongField(fieldName + LegacyNumericType.LONG, linkLong, Field.Store.NO));
document.add(new LongPoint(fieldName + LegacyNumericType.LONG, linkLong));
document.add(new LongPoint(fieldName + "LONG", linkLong));
document.add(new DoublePoint(fieldName + "DOUBLE", linkLong));
if (multipleValuesPerDocument) {
document.add(new SortedSetDocValuesField(fieldName, new BytesRef(linkValue)));
document.add(new SortedNumericDocValuesField(fieldName+ LegacyNumericType.INT, linkInt));
document.add(new SortedNumericDocValuesField(fieldName+ "INT", linkInt));
document.add(new SortedNumericDocValuesField(fieldName+ "FLOAT", Float.floatToRawIntBits(linkInt)));
document.add(new SortedNumericDocValuesField(fieldName+ LegacyNumericType.LONG, linkLong));
document.add(new SortedNumericDocValuesField(fieldName+ "LONG", linkLong));
document.add(new SortedNumericDocValuesField(fieldName+ "DOUBLE", Double.doubleToRawLongBits(linkLong)));
} else {
document.add(new SortedDocValuesField(fieldName, new BytesRef(linkValue)));
document.add(new NumericDocValuesField(fieldName+ LegacyNumericType.INT, linkInt));
document.add(new NumericDocValuesField(fieldName+ "INT", linkInt));
document.add(new FloatDocValuesField(fieldName+ "FLOAT", linkInt));
document.add(new NumericDocValuesField(fieldName+ LegacyNumericType.LONG, linkLong));
document.add(new NumericDocValuesField(fieldName+ "LONG", linkLong));
document.add(new DoubleDocValuesField(fieldName+ "DOUBLE", linkLong));
}
if (globalOrdinalJoin) {

View File

@ -25,17 +25,15 @@
<path id="classpath">
<pathelement path="${queries.jar}"/>
<pathelement path="${sandbox.jar}"/>
<pathelement path="${backward-codecs.jar}"/>
<path refid="base.classpath"/>
</path>
<target name="compile-core" depends="jar-backward-codecs,jar-queries,jar-sandbox,common.compile-core"/>
<target name="compile-core" depends="jar-queries,jar-sandbox,common.compile-core"/>
<target name="javadocs" depends="javadocs-backward-codecs,javadocs-queries,javadocs-sandbox,compile-core,check-javadocs-uptodate"
<target name="javadocs" depends="javadocs-queries,javadocs-sandbox,compile-core,check-javadocs-uptodate"
unless="javadocs-uptodate-${name}">
<invoke-module-javadoc>
<links>
<link href="../backward-codecs"/>
<link href="../queries"/>
<link href="../sandbox"/>
</links>

View File

@ -29,7 +29,6 @@ import org.apache.lucene.queryparser.flexible.core.QueryParserHelper;
import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
import org.apache.lucene.queryparser.flexible.standard.builders.StandardQueryTreeBuilder;
import org.apache.lucene.queryparser.flexible.standard.config.FuzzyConfig;
import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
import org.apache.lucene.queryparser.flexible.standard.config.PointsConfig;
import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler;
import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
@ -293,24 +292,6 @@ public class StandardQueryParser extends QueryParserHelper implements CommonQuer
}
/**
* Sets field configuration for legacy numeric fields
* @deprecated Index with points instead and use {@link #setPointsConfigMap(Map)}
*/
@Deprecated
public void setLegacyNumericConfigMap(Map<String,LegacyNumericConfig> legacyNumericConfigMap) {
getQueryConfigHandler().set(ConfigurationKeys.LEGACY_NUMERIC_CONFIG_MAP, legacyNumericConfigMap);
}
/**
* Gets field configuration for legacy numeric fields
* @deprecated Index with points instead and use {@link #getPointsConfigMap()}
*/
@Deprecated
public Map<String,LegacyNumericConfig> getLegacyNumericConfigMap() {
return getQueryConfigHandler().get(ConfigurationKeys.LEGACY_NUMERIC_CONFIG_MAP);
}
public void setPointsConfigMap(Map<String,PointsConfig> pointsConfigMap) {
getQueryConfigHandler().set(ConfigurationKeys.POINTS_CONFIG_MAP, pointsConfigMap);
}

View File

@ -1,93 +0,0 @@
/*
* 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.lucene.queryparser.flexible.standard.builders;
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
import org.apache.lucene.legacy.LegacyNumericType;
import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericQueryNode;
import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericRangeQueryNode;
/**
* Builds {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}s out of {@link LegacyNumericRangeQueryNode}s.
*
* @see org.apache.lucene.legacy.LegacyNumericRangeQuery
* @see LegacyNumericRangeQueryNode
* @deprecated Index with points and use {@link PointRangeQueryNodeBuilder} instead.
*/
@Deprecated
public class LegacyNumericRangeQueryNodeBuilder implements StandardQueryBuilder {
/**
* Constructs a {@link LegacyNumericRangeQueryNodeBuilder} object.
*/
public LegacyNumericRangeQueryNodeBuilder() {
// empty constructor
}
@Override
public LegacyNumericRangeQuery<? extends Number> build(QueryNode queryNode)
throws QueryNodeException {
LegacyNumericRangeQueryNode numericRangeNode = (LegacyNumericRangeQueryNode) queryNode;
LegacyNumericQueryNode lowerNumericNode = numericRangeNode.getLowerBound();
LegacyNumericQueryNode upperNumericNode = numericRangeNode.getUpperBound();
Number lowerNumber = lowerNumericNode.getValue();
Number upperNumber = upperNumericNode.getValue();
LegacyNumericConfig numericConfig = numericRangeNode.getNumericConfig();
LegacyNumericType numberType = numericConfig.getType();
String field = StringUtils.toString(numericRangeNode.getField());
boolean minInclusive = numericRangeNode.isLowerInclusive();
boolean maxInclusive = numericRangeNode.isUpperInclusive();
int precisionStep = numericConfig.getPrecisionStep();
switch (numberType) {
case LONG:
return LegacyNumericRangeQuery.newLongRange(field, precisionStep,
(Long) lowerNumber, (Long) upperNumber, minInclusive, maxInclusive);
case INT:
return LegacyNumericRangeQuery.newIntRange(field, precisionStep,
(Integer) lowerNumber, (Integer) upperNumber, minInclusive,
maxInclusive);
case FLOAT:
return LegacyNumericRangeQuery.newFloatRange(field, precisionStep,
(Float) lowerNumber, (Float) upperNumber, minInclusive,
maxInclusive);
case DOUBLE:
return LegacyNumericRangeQuery.newDoubleRange(field, precisionStep,
(Double) lowerNumber, (Double) upperNumber, minInclusive,
maxInclusive);
default :
throw new QueryNodeException(new MessageImpl(
QueryParserMessages.UNSUPPORTED_NUMERIC_DATA_TYPE, numberType));
}
}
}

View File

@ -32,8 +32,6 @@ import org.apache.lucene.queryparser.flexible.core.nodes.TokenizedPhraseQueryNod
import org.apache.lucene.queryparser.flexible.standard.nodes.MultiPhraseQueryNode;
import org.apache.lucene.queryparser.flexible.standard.nodes.PointQueryNode;
import org.apache.lucene.queryparser.flexible.standard.nodes.PointRangeQueryNode;
import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericQueryNode;
import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericRangeQueryNode;
import org.apache.lucene.queryparser.flexible.standard.nodes.PrefixWildcardQueryNode;
import org.apache.lucene.queryparser.flexible.standard.nodes.TermRangeQueryNode;
import org.apache.lucene.queryparser.flexible.standard.nodes.RegexpQueryNode;
@ -59,8 +57,6 @@ public class StandardQueryTreeBuilder extends QueryTreeBuilder implements
setBuilder(FieldQueryNode.class, new FieldQueryNodeBuilder());
setBuilder(BooleanQueryNode.class, new BooleanQueryNodeBuilder());
setBuilder(FuzzyQueryNode.class, new FuzzyQueryNodeBuilder());
setBuilder(LegacyNumericQueryNode.class, new DummyQueryNodeBuilder());
setBuilder(LegacyNumericRangeQueryNode.class, new LegacyNumericRangeQueryNodeBuilder());
setBuilder(PointQueryNode.class, new DummyQueryNodeBuilder());
setBuilder(PointRangeQueryNode.class, new PointRangeQueryNodeBuilder());
setBuilder(BoostQueryNode.class, new BoostQueryNodeBuilder());

View File

@ -1,165 +0,0 @@
/*
* 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.lucene.queryparser.flexible.standard.config;
import java.text.NumberFormat;
import java.util.Objects;
import org.apache.lucene.legacy.LegacyNumericType;
/**
* This class holds the configuration used to parse numeric queries and create
* {@link org.apache.lucene.legacy.LegacyNumericRangeQuery}s.
*
* @see org.apache.lucene.legacy.LegacyNumericRangeQuery
* @see NumberFormat
* @deprecated Index with Points instead and use {@link PointsConfig}
*/
@Deprecated
public class LegacyNumericConfig {
private int precisionStep;
private NumberFormat format;
private LegacyNumericType type;
/**
* Constructs a {@link LegacyNumericConfig} object.
*
* @param precisionStep
* the precision used to index the numeric values
* @param format
* the {@link NumberFormat} used to parse a {@link String} to
* {@link Number}
* @param type
* the numeric type used to index the numeric values
*
* @see LegacyNumericConfig#setPrecisionStep(int)
* @see LegacyNumericConfig#setNumberFormat(NumberFormat)
* @see #setType(LegacyNumericType)
*/
public LegacyNumericConfig(int precisionStep, NumberFormat format,
LegacyNumericType type) {
setPrecisionStep(precisionStep);
setNumberFormat(format);
setType(type);
}
/**
* Returns the precision used to index the numeric values
*
* @return the precision used to index the numeric values
*
* @see org.apache.lucene.legacy.LegacyNumericRangeQuery#getPrecisionStep()
*/
public int getPrecisionStep() {
return precisionStep;
}
/**
* Sets the precision used to index the numeric values
*
* @param precisionStep
* the precision used to index the numeric values
*
* @see org.apache.lucene.legacy.LegacyNumericRangeQuery#getPrecisionStep()
*/
public void setPrecisionStep(int precisionStep) {
this.precisionStep = precisionStep;
}
/**
* Returns the {@link NumberFormat} used to parse a {@link String} to
* {@link Number}
*
* @return the {@link NumberFormat} used to parse a {@link String} to
* {@link Number}
*/
public NumberFormat getNumberFormat() {
return format;
}
/**
* Returns the numeric type used to index the numeric values
*
* @return the numeric type used to index the numeric values
*/
public LegacyNumericType getType() {
return type;
}
/**
* Sets the numeric type used to index the numeric values
*
* @param type the numeric type used to index the numeric values
*/
public void setType(LegacyNumericType type) {
if (type == null) {
throw new IllegalArgumentException("type must not be null!");
}
this.type = type;
}
/**
* Sets the {@link NumberFormat} used to parse a {@link String} to
* {@link Number}
*
* @param format
* the {@link NumberFormat} used to parse a {@link String} to
* {@link Number}, must not be <code>null</code>
*/
public void setNumberFormat(NumberFormat format) {
if (format == null) {
throw new IllegalArgumentException("format must not be null!");
}
this.format = format;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj instanceof LegacyNumericConfig) {
LegacyNumericConfig other = (LegacyNumericConfig) obj;
if (this.precisionStep == other.precisionStep
&& this.type == other.type
&& (this.format == other.format || (this.format.equals(other.format)))) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(precisionStep, type, format);
}
}

View File

@ -1,75 +0,0 @@
/*
* 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.lucene.queryparser.flexible.standard.config;
import java.util.Map;
import org.apache.lucene.queryparser.flexible.core.config.FieldConfig;
import org.apache.lucene.queryparser.flexible.core.config.FieldConfigListener;
import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
/**
* This listener is used to listen to {@link FieldConfig} requests in
* {@link QueryConfigHandler} and add {@link ConfigurationKeys#LEGACY_NUMERIC_CONFIG}
* based on the {@link ConfigurationKeys#LEGACY_NUMERIC_CONFIG_MAP} set in the
* {@link QueryConfigHandler}.
*
* @see LegacyNumericConfig
* @see QueryConfigHandler
* @see ConfigurationKeys#LEGACY_NUMERIC_CONFIG
* @see ConfigurationKeys#LEGACY_NUMERIC_CONFIG_MAP
* @deprecated Index with Points instead and use {@link PointsConfigListener}
*/
@Deprecated
public class LegacyNumericFieldConfigListener implements FieldConfigListener {
final private QueryConfigHandler config;
/**
* Constructs a {@link LegacyNumericFieldConfigListener} object using the given {@link QueryConfigHandler}.
*
* @param config the {@link QueryConfigHandler} it will listen too
*/
public LegacyNumericFieldConfigListener(QueryConfigHandler config) {
if (config == null) {
throw new IllegalArgumentException("config must not be null!");
}
this.config = config;
}
@Override
public void buildFieldConfig(FieldConfig fieldConfig) {
Map<String,LegacyNumericConfig> numericConfigMap = config
.get(ConfigurationKeys.LEGACY_NUMERIC_CONFIG_MAP);
if (numericConfigMap != null) {
LegacyNumericConfig numericConfig = numericConfigMap
.get(fieldConfig.getField());
if (numericConfig != null) {
fieldConfig.set(ConfigurationKeys.LEGACY_NUMERIC_CONFIG, numericConfig);
}
}
}
}

View File

@ -158,39 +158,19 @@ public class StandardQueryConfigHandler extends QueryConfigHandler {
*/
final public static ConfigurationKey<Float> BOOST = ConfigurationKey.newInstance();
/**
* Key used to set a field to its {@link LegacyNumericConfig}.
*
* @see StandardQueryParser#setLegacyNumericConfigMap(Map)
* @see StandardQueryParser#getLegacyNumericConfigMap()
* @deprecated Index with Points instead and use {@link #POINTS_CONFIG}
*/
@Deprecated
final public static ConfigurationKey<LegacyNumericConfig> LEGACY_NUMERIC_CONFIG = ConfigurationKey.newInstance();
/**
* Key used to set the {@link LegacyNumericConfig} in {@link FieldConfig} for numeric fields.
*
* @see StandardQueryParser#setLegacyNumericConfigMap(Map)
* @see StandardQueryParser#getLegacyNumericConfigMap()
* @deprecated Index with Points instead and use {@link #POINTS_CONFIG_MAP}
*/
@Deprecated
final public static ConfigurationKey<Map<String,LegacyNumericConfig>> LEGACY_NUMERIC_CONFIG_MAP = ConfigurationKey.newInstance();
/**
* Key used to set a field to its {@link PointsConfig}.
*
* @see StandardQueryParser#setLegacyNumericConfigMap(Map)
* @see StandardQueryParser#getLegacyNumericConfigMap()
* @see StandardQueryParser#setPointsConfigMap(Map)
* @see StandardQueryParser#getPointsConfigMap()
*/
final public static ConfigurationKey<PointsConfig> POINTS_CONFIG = ConfigurationKey.newInstance();
/**
* Key used to set the {@link PointsConfig} in {@link FieldConfig} for point fields.
*
* @see StandardQueryParser#setLegacyNumericConfigMap(Map)
* @see StandardQueryParser#getLegacyNumericConfigMap()
* @see StandardQueryParser#setPointsConfigMap(Map)
* @see StandardQueryParser#getPointsConfigMap()
*/
final public static ConfigurationKey<Map<String,PointsConfig>> POINTS_CONFIG_MAP = ConfigurationKey.newInstance();
@ -207,7 +187,6 @@ public class StandardQueryConfigHandler extends QueryConfigHandler {
// Add listener that will build the FieldConfig.
addFieldConfigListener(new FieldBoostMapFCListener(this));
addFieldConfigListener(new FieldDateResolutionFCListener(this));
addFieldConfigListener(new LegacyNumericFieldConfigListener(this));
addFieldConfigListener(new PointsConfigListener(this));
// Default Values

View File

@ -1,153 +0,0 @@
/*
* 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.lucene.queryparser.flexible.standard.nodes;
import java.text.NumberFormat;
import java.util.Locale;
import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
import org.apache.lucene.queryparser.flexible.core.nodes.FieldValuePairQueryNode;
import org.apache.lucene.queryparser.flexible.core.nodes.QueryNodeImpl;
import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax.Type;
import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
/**
* This query node represents a field query that holds a numeric value. It is
* similar to {@link FieldQueryNode}, however the {@link #getValue()} returns a
* {@link Number}.
*
* @see LegacyNumericConfig
* @deprecated Index with Points instead and use {@link PointQueryNode} instead.
*/
@Deprecated
public class LegacyNumericQueryNode extends QueryNodeImpl implements
FieldValuePairQueryNode<Number> {
private NumberFormat numberFormat;
private CharSequence field;
private Number value;
/**
* Creates a {@link LegacyNumericQueryNode} object using the given field,
* {@link Number} value and {@link NumberFormat} used to convert the value to
* {@link String}.
*
* @param field the field associated with this query node
* @param value the value hold by this node
* @param numberFormat the {@link NumberFormat} used to convert the value to {@link String}
*/
public LegacyNumericQueryNode(CharSequence field, Number value,
NumberFormat numberFormat) {
super();
setNumberFormat(numberFormat);
setField(field);
setValue(value);
}
/**
* Returns the field associated with this node.
*
* @return the field associated with this node
*/
@Override
public CharSequence getField() {
return this.field;
}
/**
* Sets the field associated with this node.
*
* @param fieldName the field associated with this node
*/
@Override
public void setField(CharSequence fieldName) {
this.field = fieldName;
}
/**
* This method is used to get the value converted to {@link String} and
* escaped using the given {@link EscapeQuerySyntax}.
*
* @param escaper the {@link EscapeQuerySyntax} used to escape the value {@link String}
*
* @return the value converte to {@link String} and escaped
*/
protected CharSequence getTermEscaped(EscapeQuerySyntax escaper) {
return escaper.escape(numberFormat.format(this.value),
Locale.ROOT, Type.NORMAL);
}
@Override
public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
if (isDefaultField(this.field)) {
return getTermEscaped(escapeSyntaxParser);
} else {
return this.field + ":" + getTermEscaped(escapeSyntaxParser);
}
}
/**
* Sets the {@link NumberFormat} used to convert the value to {@link String}.
*
* @param format the {@link NumberFormat} used to convert the value to {@link String}
*/
public void setNumberFormat(NumberFormat format) {
this.numberFormat = format;
}
/**
* Returns the {@link NumberFormat} used to convert the value to {@link String}.
*
* @return the {@link NumberFormat} used to convert the value to {@link String}
*/
public NumberFormat getNumberFormat() {
return this.numberFormat;
}
/**
* Returns the numeric value as {@link Number}.
*
* @return the numeric value
*/
@Override
public Number getValue() {
return value;
}
/**
* Sets the numeric value.
*
* @param value the numeric value
*/
@Override
public void setValue(Number value) {
this.value = value;
}
@Override
public String toString() {
return "<numeric field='" + this.field + "' number='"
+ numberFormat.format(value) + "'/>";
}
}

View File

@ -1,152 +0,0 @@
/*
* 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.lucene.queryparser.flexible.standard.nodes;
import org.apache.lucene.legacy.LegacyNumericType;
import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
/**
* This query node represents a range query composed by {@link LegacyNumericQueryNode}
* bounds, which means the bound values are {@link Number}s.
*
* @see LegacyNumericQueryNode
* @see AbstractRangeQueryNode
* @deprecated Index with Points instead and use {@link PointRangeQueryNode} instead.
*/
@Deprecated
public class LegacyNumericRangeQueryNode extends
AbstractRangeQueryNode<LegacyNumericQueryNode> {
public LegacyNumericConfig numericConfig;
/**
* Constructs a {@link LegacyNumericRangeQueryNode} object using the given
* {@link LegacyNumericQueryNode} as its bounds and {@link LegacyNumericConfig}.
*
* @param lower the lower bound
* @param upper the upper bound
* @param lowerInclusive <code>true</code> if the lower bound is inclusive, otherwise, <code>false</code>
* @param upperInclusive <code>true</code> if the upper bound is inclusive, otherwise, <code>false</code>
* @param numericConfig the {@link LegacyNumericConfig} that represents associated with the upper and lower bounds
*
* @see #setBounds(LegacyNumericQueryNode, LegacyNumericQueryNode, boolean, boolean, LegacyNumericConfig)
*/
public LegacyNumericRangeQueryNode(LegacyNumericQueryNode lower, LegacyNumericQueryNode upper,
boolean lowerInclusive, boolean upperInclusive, LegacyNumericConfig numericConfig) throws QueryNodeException {
setBounds(lower, upper, lowerInclusive, upperInclusive, numericConfig);
}
private static LegacyNumericType getNumericDataType(Number number) throws QueryNodeException {
if (number instanceof Long) {
return LegacyNumericType.LONG;
} else if (number instanceof Integer) {
return LegacyNumericType.INT;
} else if (number instanceof Double) {
return LegacyNumericType.DOUBLE;
} else if (number instanceof Float) {
return LegacyNumericType.FLOAT;
} else {
throw new QueryNodeException(
new MessageImpl(
QueryParserMessages.NUMBER_CLASS_NOT_SUPPORTED_BY_NUMERIC_RANGE_QUERY,
number.getClass()));
}
}
/**
* Sets the upper and lower bounds of this range query node and the
* {@link LegacyNumericConfig} associated with these bounds.
*
* @param lower the lower bound
* @param upper the upper bound
* @param lowerInclusive <code>true</code> if the lower bound is inclusive, otherwise, <code>false</code>
* @param upperInclusive <code>true</code> if the upper bound is inclusive, otherwise, <code>false</code>
* @param numericConfig the {@link LegacyNumericConfig} that represents associated with the upper and lower bounds
*
*/
public void setBounds(LegacyNumericQueryNode lower, LegacyNumericQueryNode upper,
boolean lowerInclusive, boolean upperInclusive, LegacyNumericConfig numericConfig) throws QueryNodeException {
if (numericConfig == null) {
throw new IllegalArgumentException("numericConfig must not be null!");
}
LegacyNumericType lowerNumberType, upperNumberType;
if (lower != null && lower.getValue() != null) {
lowerNumberType = getNumericDataType(lower.getValue());
} else {
lowerNumberType = null;
}
if (upper != null && upper.getValue() != null) {
upperNumberType = getNumericDataType(upper.getValue());
} else {
upperNumberType = null;
}
if (lowerNumberType != null
&& !lowerNumberType.equals(numericConfig.getType())) {
throw new IllegalArgumentException(
"lower value's type should be the same as numericConfig type: "
+ lowerNumberType + " != " + numericConfig.getType());
}
if (upperNumberType != null
&& !upperNumberType.equals(numericConfig.getType())) {
throw new IllegalArgumentException(
"upper value's type should be the same as numericConfig type: "
+ upperNumberType + " != " + numericConfig.getType());
}
super.setBounds(lower, upper, lowerInclusive, upperInclusive);
this.numericConfig = numericConfig;
}
/**
* Returns the {@link LegacyNumericConfig} associated with the lower and upper bounds.
*
* @return the {@link LegacyNumericConfig} associated with the lower and upper bounds
*/
public LegacyNumericConfig getNumericConfig() {
return this.numericConfig;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("<numericRange lowerInclusive='");
sb.append(isLowerInclusive()).append("' upperInclusive='").append(
isUpperInclusive()).append(
"' precisionStep='" + numericConfig.getPrecisionStep()).append(
"' type='" + numericConfig.getType()).append("'>\n");
sb.append(getLowerBound()).append('\n');
sb.append(getUpperBound()).append('\n');
sb.append("</numericRange>");
return sb.toString();
}
}

View File

@ -1,154 +0,0 @@
/*
* 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.lucene.queryparser.flexible.standard.processors;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.List;
import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
import org.apache.lucene.queryparser.flexible.core.config.FieldConfig;
import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
import org.apache.lucene.queryparser.flexible.core.nodes.RangeQueryNode;
import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessorImpl;
import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericQueryNode;
import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericRangeQueryNode;
/**
* This processor is used to convert {@link FieldQueryNode}s to
* {@link LegacyNumericRangeQueryNode}s. It looks for
* {@link ConfigurationKeys#LEGACY_NUMERIC_CONFIG} set in the {@link FieldConfig} of
* every {@link FieldQueryNode} found. If
* {@link ConfigurationKeys#LEGACY_NUMERIC_CONFIG} is found, it considers that
* {@link FieldQueryNode} to be a numeric query and convert it to
* {@link LegacyNumericRangeQueryNode} with upper and lower inclusive and lower and
* upper equals to the value represented by the {@link FieldQueryNode} converted
* to {@link Number}. It means that <b>field:1</b> is converted to <b>field:[1
* TO 1]</b>. <br>
* <br>
* Note that {@link FieldQueryNode}s children of a
* {@link RangeQueryNode} are ignored.
*
* @see ConfigurationKeys#LEGACY_NUMERIC_CONFIG
* @see FieldQueryNode
* @see LegacyNumericConfig
* @see LegacyNumericQueryNode
* @deprecated Index with points and use {@link PointQueryNodeProcessor} instead.
*/
@Deprecated
public class LegacyNumericQueryNodeProcessor extends QueryNodeProcessorImpl {
/**
* Constructs a {@link LegacyNumericQueryNodeProcessor} object.
*/
public LegacyNumericQueryNodeProcessor() {
// empty constructor
}
@Override
protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
if (node instanceof FieldQueryNode
&& !(node.getParent() instanceof RangeQueryNode)) {
QueryConfigHandler config = getQueryConfigHandler();
if (config != null) {
FieldQueryNode fieldNode = (FieldQueryNode) node;
FieldConfig fieldConfig = config.getFieldConfig(fieldNode
.getFieldAsString());
if (fieldConfig != null) {
LegacyNumericConfig numericConfig = fieldConfig
.get(ConfigurationKeys.LEGACY_NUMERIC_CONFIG);
if (numericConfig != null) {
NumberFormat numberFormat = numericConfig.getNumberFormat();
String text = fieldNode.getTextAsString();
Number number = null;
if (text.length() > 0) {
try {
number = numberFormat.parse(text);
} catch (ParseException e) {
throw new QueryNodeParseException(new MessageImpl(
QueryParserMessages.COULD_NOT_PARSE_NUMBER, fieldNode
.getTextAsString(), numberFormat.getClass()
.getCanonicalName()), e);
}
switch (numericConfig.getType()) {
case LONG:
number = number.longValue();
break;
case INT:
number = number.intValue();
break;
case DOUBLE:
number = number.doubleValue();
break;
case FLOAT:
number = number.floatValue();
}
} else {
throw new QueryNodeParseException(new MessageImpl(
QueryParserMessages.NUMERIC_CANNOT_BE_EMPTY, fieldNode.getFieldAsString()));
}
LegacyNumericQueryNode lowerNode = new LegacyNumericQueryNode(fieldNode
.getField(), number, numberFormat);
LegacyNumericQueryNode upperNode = new LegacyNumericQueryNode(fieldNode
.getField(), number, numberFormat);
return new LegacyNumericRangeQueryNode(lowerNode, upperNode, true, true,
numericConfig);
}
}
}
}
return node;
}
@Override
protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
return node;
}
@Override
protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
throws QueryNodeException {
return children;
}
}

View File

@ -1,170 +0,0 @@
/*
* 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.lucene.queryparser.flexible.standard.processors;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.List;
import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
import org.apache.lucene.queryparser.flexible.core.config.FieldConfig;
import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessorImpl;
import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.ConfigurationKeys;
import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericQueryNode;
import org.apache.lucene.queryparser.flexible.standard.nodes.LegacyNumericRangeQueryNode;
import org.apache.lucene.queryparser.flexible.standard.nodes.TermRangeQueryNode;
/**
* This processor is used to convert {@link TermRangeQueryNode}s to
* {@link LegacyNumericRangeQueryNode}s. It looks for
* {@link ConfigurationKeys#LEGACY_NUMERIC_CONFIG} set in the {@link FieldConfig} of
* every {@link TermRangeQueryNode} found. If
* {@link ConfigurationKeys#LEGACY_NUMERIC_CONFIG} is found, it considers that
* {@link TermRangeQueryNode} to be a numeric range query and convert it to
* {@link LegacyNumericRangeQueryNode}.
*
* @see ConfigurationKeys#LEGACY_NUMERIC_CONFIG
* @see TermRangeQueryNode
* @see LegacyNumericConfig
* @see LegacyNumericRangeQueryNode
* @deprecated Index with points and use {@link PointRangeQueryNodeProcessor} instead.
*/
@Deprecated
public class LegacyNumericRangeQueryNodeProcessor extends QueryNodeProcessorImpl {
/**
* Constructs an empty {@link LegacyNumericRangeQueryNode} object.
*/
public LegacyNumericRangeQueryNodeProcessor() {
// empty constructor
}
@Override
protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
if (node instanceof TermRangeQueryNode) {
QueryConfigHandler config = getQueryConfigHandler();
if (config != null) {
TermRangeQueryNode termRangeNode = (TermRangeQueryNode) node;
FieldConfig fieldConfig = config.getFieldConfig(StringUtils
.toString(termRangeNode.getField()));
if (fieldConfig != null) {
LegacyNumericConfig numericConfig = fieldConfig
.get(ConfigurationKeys.LEGACY_NUMERIC_CONFIG);
if (numericConfig != null) {
FieldQueryNode lower = termRangeNode.getLowerBound();
FieldQueryNode upper = termRangeNode.getUpperBound();
String lowerText = lower.getTextAsString();
String upperText = upper.getTextAsString();
NumberFormat numberFormat = numericConfig.getNumberFormat();
Number lowerNumber = null, upperNumber = null;
if (lowerText.length() > 0) {
try {
lowerNumber = numberFormat.parse(lowerText);
} catch (ParseException e) {
throw new QueryNodeParseException(new MessageImpl(
QueryParserMessages.COULD_NOT_PARSE_NUMBER, lower
.getTextAsString(), numberFormat.getClass()
.getCanonicalName()), e);
}
}
if (upperText.length() > 0) {
try {
upperNumber = numberFormat.parse(upperText);
} catch (ParseException e) {
throw new QueryNodeParseException(new MessageImpl(
QueryParserMessages.COULD_NOT_PARSE_NUMBER, upper
.getTextAsString(), numberFormat.getClass()
.getCanonicalName()), e);
}
}
switch (numericConfig.getType()) {
case LONG:
if (upperNumber != null) upperNumber = upperNumber.longValue();
if (lowerNumber != null) lowerNumber = lowerNumber.longValue();
break;
case INT:
if (upperNumber != null) upperNumber = upperNumber.intValue();
if (lowerNumber != null) lowerNumber = lowerNumber.intValue();
break;
case DOUBLE:
if (upperNumber != null) upperNumber = upperNumber.doubleValue();
if (lowerNumber != null) lowerNumber = lowerNumber.doubleValue();
break;
case FLOAT:
if (upperNumber != null) upperNumber = upperNumber.floatValue();
if (lowerNumber != null) lowerNumber = lowerNumber.floatValue();
}
LegacyNumericQueryNode lowerNode = new LegacyNumericQueryNode(
termRangeNode.getField(), lowerNumber, numberFormat);
LegacyNumericQueryNode upperNode = new LegacyNumericQueryNode(
termRangeNode.getField(), upperNumber, numberFormat);
boolean lowerInclusive = termRangeNode.isLowerInclusive();
boolean upperInclusive = termRangeNode.isUpperInclusive();
return new LegacyNumericRangeQueryNode(lowerNode, upperNode,
lowerInclusive, upperInclusive, numericConfig);
}
}
}
}
return node;
}
@Override
protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
return node;
}
@Override
protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
throws QueryNodeException {
return children;
}
}

View File

@ -53,8 +53,6 @@ public class StandardQueryNodeProcessorPipeline extends
add(new RegexpQueryNodeProcessor());
add(new MatchAllDocsQueryNodeProcessor());
add(new OpenRangeQueryNodeProcessor());
add(new LegacyNumericQueryNodeProcessor());
add(new LegacyNumericRangeQueryNodeProcessor());
add(new PointQueryNodeProcessor());
add(new PointRangeQueryNodeProcessor());
add(new TermRangeQueryNodeProcessor());

View File

@ -71,7 +71,6 @@ public class CoreParser implements QueryBuilder {
queryFactory.addBuilder("TermsQuery", new TermsQueryBuilder(analyzer));
queryFactory.addBuilder("MatchAllDocsQuery", new MatchAllDocsQueryBuilder());
queryFactory.addBuilder("BooleanQuery", new BooleanQueryBuilder(queryFactory));
queryFactory.addBuilder("LegacyNumericRangeQuery", new LegacyNumericRangeQueryBuilder());
queryFactory.addBuilder("PointRangeQuery", new PointRangeQueryBuilder());
queryFactory.addBuilder("RangeQuery", new RangeQueryBuilder());
queryFactory.addBuilder("DisjunctionMaxQuery", new DisjunctionMaxQueryBuilder(queryFactory));

View File

@ -1,535 +0,0 @@
/*
* 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.lucene.queryparser.flexible.standard;
import java.io.IOException;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.TimeZone;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.legacy.LegacyDoubleField;
import org.apache.lucene.legacy.LegacyFieldType;
import org.apache.lucene.legacy.LegacyFloatField;
import org.apache.lucene.legacy.LegacyIntField;
import org.apache.lucene.legacy.LegacyLongField;
import org.apache.lucene.legacy.LegacyNumericType;
import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
import org.apache.lucene.queryparser.flexible.standard.config.NumberDateFormat;
import org.apache.lucene.queryparser.flexible.standard.config.LegacyNumericConfig;
import org.apache.lucene.queryparser.flexible.standard.parser.EscapeQuerySyntaxImpl;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util.TestUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class TestLegacyNumericQueryParser extends LuceneTestCase {
private static enum NumberType {
NEGATIVE, ZERO, POSITIVE;
}
final private static int[] DATE_STYLES = {DateFormat.FULL, DateFormat.LONG,
DateFormat.MEDIUM, DateFormat.SHORT};
final private static int PRECISION_STEP = 8;
final private static String FIELD_NAME = "field";
private static Locale LOCALE;
private static TimeZone TIMEZONE;
private static Map<String,Number> RANDOM_NUMBER_MAP;
private static EscapeQuerySyntax ESCAPER = new EscapeQuerySyntaxImpl();
final private static String DATE_FIELD_NAME = "date";
private static int DATE_STYLE;
private static int TIME_STYLE;
private static Analyzer ANALYZER;
private static NumberFormat NUMBER_FORMAT;
private static StandardQueryParser qp;
private static NumberDateFormat DATE_FORMAT;
private static Directory directory = null;
private static IndexReader reader = null;
private static IndexSearcher searcher = null;
private static boolean checkDateFormatSanity(DateFormat dateFormat, long date) {
try {
return date == dateFormat.parse(dateFormat.format(new Date(date)))
.getTime();
} catch (ParseException e) {
return false;
}
}
@BeforeClass
public static void beforeClass() throws Exception {
ANALYZER = new MockAnalyzer(random());
qp = new StandardQueryParser(ANALYZER);
final HashMap<String,Number> randomNumberMap = new HashMap<>();
SimpleDateFormat dateFormat;
long randomDate;
boolean dateFormatSanityCheckPass;
int count = 0;
do {
if (count > 100) {
fail("This test has problems to find a sane random DateFormat/NumberFormat. Stopped trying after 100 iterations.");
}
dateFormatSanityCheckPass = true;
LOCALE = randomLocale(random());
TIMEZONE = randomTimeZone(random());
DATE_STYLE = randomDateStyle(random());
TIME_STYLE = randomDateStyle(random());
// assumes localized date pattern will have at least year, month, day,
// hour, minute
dateFormat = (SimpleDateFormat) DateFormat.getDateTimeInstance(
DATE_STYLE, TIME_STYLE, LOCALE);
// not all date patterns includes era, full year, timezone and second,
// so we add them here
dateFormat.applyPattern(dateFormat.toPattern() + " G s Z yyyy");
dateFormat.setTimeZone(TIMEZONE);
DATE_FORMAT = new NumberDateFormat(dateFormat);
do {
randomDate = random().nextLong();
// prune date value so it doesn't pass in insane values to some
// calendars.
randomDate = randomDate % 3400000000000l;
// truncate to second
randomDate = (randomDate / 1000L) * 1000L;
// only positive values
randomDate = Math.abs(randomDate);
} while (randomDate == 0L);
dateFormatSanityCheckPass &= checkDateFormatSanity(dateFormat, randomDate);
dateFormatSanityCheckPass &= checkDateFormatSanity(dateFormat, 0);
dateFormatSanityCheckPass &= checkDateFormatSanity(dateFormat,
-randomDate);
count++;
} while (!dateFormatSanityCheckPass);
NUMBER_FORMAT = NumberFormat.getNumberInstance(LOCALE);
NUMBER_FORMAT.setMaximumFractionDigits((random().nextInt() & 20) + 1);
NUMBER_FORMAT.setMinimumFractionDigits((random().nextInt() & 20) + 1);
NUMBER_FORMAT.setMaximumIntegerDigits((random().nextInt() & 20) + 1);
NUMBER_FORMAT.setMinimumIntegerDigits((random().nextInt() & 20) + 1);
double randomDouble;
long randomLong;
int randomInt;
float randomFloat;
while ((randomLong = normalizeNumber(Math.abs(random().nextLong()))
.longValue()) == 0L)
;
while ((randomDouble = normalizeNumber(Math.abs(random().nextDouble()))
.doubleValue()) == 0.0)
;
while ((randomFloat = normalizeNumber(Math.abs(random().nextFloat()))
.floatValue()) == 0.0f)
;
while ((randomInt = normalizeNumber(Math.abs(random().nextInt())).intValue()) == 0)
;
randomNumberMap.put(LegacyNumericType.LONG.name(), randomLong);
randomNumberMap.put(LegacyNumericType.INT.name(), randomInt);
randomNumberMap.put(LegacyNumericType.FLOAT.name(), randomFloat);
randomNumberMap.put(LegacyNumericType.DOUBLE.name(), randomDouble);
randomNumberMap.put(DATE_FIELD_NAME, randomDate);
RANDOM_NUMBER_MAP = Collections.unmodifiableMap(randomNumberMap);
directory = newDirectory();
RandomIndexWriter writer = new RandomIndexWriter(random(), directory,
newIndexWriterConfig(new MockAnalyzer(random()))
.setMaxBufferedDocs(TestUtil.nextInt(random(), 50, 1000))
.setMergePolicy(newLogMergePolicy()));
Document doc = new Document();
HashMap<String,LegacyNumericConfig> numericConfigMap = new HashMap<>();
HashMap<String,Field> numericFieldMap = new HashMap<>();
qp.setLegacyNumericConfigMap(numericConfigMap);
for (LegacyNumericType type : LegacyNumericType.values()) {
numericConfigMap.put(type.name(), new LegacyNumericConfig(PRECISION_STEP,
NUMBER_FORMAT, type));
LegacyFieldType ft = new LegacyFieldType(LegacyIntField.TYPE_NOT_STORED);
ft.setNumericType(type);
ft.setStored(true);
ft.setNumericPrecisionStep(PRECISION_STEP);
ft.freeze();
final Field field;
switch(type) {
case INT:
field = new LegacyIntField(type.name(), 0, ft);
break;
case FLOAT:
field = new LegacyFloatField(type.name(), 0.0f, ft);
break;
case LONG:
field = new LegacyLongField(type.name(), 0l, ft);
break;
case DOUBLE:
field = new LegacyDoubleField(type.name(), 0.0, ft);
break;
default:
fail();
field = null;
}
numericFieldMap.put(type.name(), field);
doc.add(field);
}
numericConfigMap.put(DATE_FIELD_NAME, new LegacyNumericConfig(PRECISION_STEP,
DATE_FORMAT, LegacyNumericType.LONG));
LegacyFieldType ft = new LegacyFieldType(LegacyLongField.TYPE_NOT_STORED);
ft.setStored(true);
ft.setNumericPrecisionStep(PRECISION_STEP);
LegacyLongField dateField = new LegacyLongField(DATE_FIELD_NAME, 0l, ft);
numericFieldMap.put(DATE_FIELD_NAME, dateField);
doc.add(dateField);
for (NumberType numberType : NumberType.values()) {
setFieldValues(numberType, numericFieldMap);
if (VERBOSE) System.out.println("Indexing document: " + doc);
writer.addDocument(doc);
}
reader = writer.getReader();
searcher = newSearcher(reader);
writer.close();
}
private static Number getNumberType(NumberType numberType, String fieldName) {
if (numberType == null) {
return null;
}
switch (numberType) {
case POSITIVE:
return RANDOM_NUMBER_MAP.get(fieldName);
case NEGATIVE:
Number number = RANDOM_NUMBER_MAP.get(fieldName);
if (LegacyNumericType.LONG.name().equals(fieldName)
|| DATE_FIELD_NAME.equals(fieldName)) {
number = -number.longValue();
} else if (LegacyNumericType.DOUBLE.name().equals(fieldName)) {
number = -number.doubleValue();
} else if (LegacyNumericType.FLOAT.name().equals(fieldName)) {
number = -number.floatValue();
} else if (LegacyNumericType.INT.name().equals(fieldName)) {
number = -number.intValue();
} else {
throw new IllegalArgumentException("field name not found: "
+ fieldName);
}
return number;
default:
return 0;
}
}
private static void setFieldValues(NumberType numberType,
HashMap<String,Field> numericFieldMap) {
Number number = getNumberType(numberType, LegacyNumericType.DOUBLE
.name());
numericFieldMap.get(LegacyNumericType.DOUBLE.name()).setDoubleValue(
number.doubleValue());
number = getNumberType(numberType, LegacyNumericType.INT.name());
numericFieldMap.get(LegacyNumericType.INT.name()).setIntValue(
number.intValue());
number = getNumberType(numberType, LegacyNumericType.LONG.name());
numericFieldMap.get(LegacyNumericType.LONG.name()).setLongValue(
number.longValue());
number = getNumberType(numberType, LegacyNumericType.FLOAT.name());
numericFieldMap.get(LegacyNumericType.FLOAT.name()).setFloatValue(
number.floatValue());
number = getNumberType(numberType, DATE_FIELD_NAME);
numericFieldMap.get(DATE_FIELD_NAME).setLongValue(number.longValue());
}
private static int randomDateStyle(Random random) {
return DATE_STYLES[random.nextInt(DATE_STYLES.length)];
}
@Test
public void testInclusiveNumericRange() throws Exception {
assertRangeQuery(NumberType.ZERO, NumberType.ZERO, true, true, 1);
assertRangeQuery(NumberType.ZERO, NumberType.POSITIVE, true, true, 2);
assertRangeQuery(NumberType.NEGATIVE, NumberType.ZERO, true, true, 2);
assertRangeQuery(NumberType.NEGATIVE, NumberType.POSITIVE, true, true, 3);
assertRangeQuery(NumberType.NEGATIVE, NumberType.NEGATIVE, true, true, 1);
}
@Test
// test disabled since standard syntax parser does not work with inclusive and
// exclusive at the same time
public void testInclusiveLowerNumericRange() throws Exception {
assertRangeQuery(NumberType.NEGATIVE, NumberType.ZERO, false, true, 1);
assertRangeQuery(NumberType.ZERO, NumberType.POSITIVE, false, true, 1);
assertRangeQuery(NumberType.NEGATIVE, NumberType.POSITIVE, false, true, 2);
assertRangeQuery(NumberType.NEGATIVE, NumberType.NEGATIVE, false, true, 0);
}
@Test
// test disabled since standard syntax parser does not work with inclusive and
// exclusive at the same time
public void testInclusiveUpperNumericRange() throws Exception {
assertRangeQuery(NumberType.NEGATIVE, NumberType.ZERO, true, false, 1);
assertRangeQuery(NumberType.ZERO, NumberType.POSITIVE, true, false, 1);
assertRangeQuery(NumberType.NEGATIVE, NumberType.POSITIVE, true, false, 2);
assertRangeQuery(NumberType.NEGATIVE, NumberType.NEGATIVE, true, false, 0);
}
@Test
public void testExclusiveNumericRange() throws Exception {
assertRangeQuery(NumberType.ZERO, NumberType.ZERO, false, false, 0);
assertRangeQuery(NumberType.ZERO, NumberType.POSITIVE, false, false, 0);
assertRangeQuery(NumberType.NEGATIVE, NumberType.ZERO, false, false, 0);
assertRangeQuery(NumberType.NEGATIVE, NumberType.POSITIVE, false, false, 1);
assertRangeQuery(NumberType.NEGATIVE, NumberType.NEGATIVE, false, false, 0);
}
@Test
public void testOpenRangeNumericQuery() throws Exception {
assertOpenRangeQuery(NumberType.ZERO, "<", 1);
assertOpenRangeQuery(NumberType.POSITIVE, "<", 2);
assertOpenRangeQuery(NumberType.NEGATIVE, "<", 0);
assertOpenRangeQuery(NumberType.ZERO, "<=", 2);
assertOpenRangeQuery(NumberType.POSITIVE, "<=", 3);
assertOpenRangeQuery(NumberType.NEGATIVE, "<=", 1);
assertOpenRangeQuery(NumberType.ZERO, ">", 1);
assertOpenRangeQuery(NumberType.POSITIVE, ">", 0);
assertOpenRangeQuery(NumberType.NEGATIVE, ">", 2);
assertOpenRangeQuery(NumberType.ZERO, ">=", 2);
assertOpenRangeQuery(NumberType.POSITIVE, ">=", 1);
assertOpenRangeQuery(NumberType.NEGATIVE, ">=", 3);
assertOpenRangeQuery(NumberType.NEGATIVE, "=", 1);
assertOpenRangeQuery(NumberType.ZERO, "=", 1);
assertOpenRangeQuery(NumberType.POSITIVE, "=", 1);
assertRangeQuery(NumberType.NEGATIVE, null, true, true, 3);
assertRangeQuery(NumberType.NEGATIVE, null, false, true, 2);
assertRangeQuery(NumberType.POSITIVE, null, true, false, 1);
assertRangeQuery(NumberType.ZERO, null, false, false, 1);
assertRangeQuery(null, NumberType.POSITIVE, true, true, 3);
assertRangeQuery(null, NumberType.POSITIVE, true, false, 2);
assertRangeQuery(null, NumberType.NEGATIVE, false, true, 1);
assertRangeQuery(null, NumberType.ZERO, false, false, 1);
assertRangeQuery(null, null, false, false, 3);
assertRangeQuery(null, null, true, true, 3);
}
@Test
public void testSimpleNumericQuery() throws Exception {
assertSimpleQuery(NumberType.ZERO, 1);
assertSimpleQuery(NumberType.POSITIVE, 1);
assertSimpleQuery(NumberType.NEGATIVE, 1);
}
public void assertRangeQuery(NumberType lowerType, NumberType upperType,
boolean lowerInclusive, boolean upperInclusive, int expectedDocCount)
throws QueryNodeException, IOException {
StringBuilder sb = new StringBuilder();
String lowerInclusiveStr = (lowerInclusive ? "[" : "{");
String upperInclusiveStr = (upperInclusive ? "]" : "}");
for (LegacyNumericType type : LegacyNumericType.values()) {
String lowerStr = numberToString(getNumberType(lowerType, type.name()));
String upperStr = numberToString(getNumberType(upperType, type.name()));
sb.append("+").append(type.name()).append(':').append(lowerInclusiveStr)
.append('"').append(lowerStr).append("\" TO \"").append(upperStr)
.append('"').append(upperInclusiveStr).append(' ');
}
Number lowerDateNumber = getNumberType(lowerType, DATE_FIELD_NAME);
Number upperDateNumber = getNumberType(upperType, DATE_FIELD_NAME);
String lowerDateStr;
String upperDateStr;
if (lowerDateNumber != null) {
lowerDateStr = ESCAPER.escape(
DATE_FORMAT.format(new Date(lowerDateNumber.longValue())), LOCALE,
EscapeQuerySyntax.Type.STRING).toString();
} else {
lowerDateStr = "*";
}
if (upperDateNumber != null) {
upperDateStr = ESCAPER.escape(
DATE_FORMAT.format(new Date(upperDateNumber.longValue())), LOCALE,
EscapeQuerySyntax.Type.STRING).toString();
} else {
upperDateStr = "*";
}
sb.append("+").append(DATE_FIELD_NAME).append(':')
.append(lowerInclusiveStr).append('"').append(lowerDateStr).append(
"\" TO \"").append(upperDateStr).append('"').append(
upperInclusiveStr);
testQuery(sb.toString(), expectedDocCount);
}
public void assertOpenRangeQuery(NumberType boundType, String operator, int expectedDocCount)
throws QueryNodeException, IOException {
StringBuilder sb = new StringBuilder();
for (LegacyNumericType type : LegacyNumericType.values()) {
String boundStr = numberToString(getNumberType(boundType, type.name()));
sb.append("+").append(type.name()).append(operator).append('"').append(boundStr).append('"').append(' ');
}
String boundDateStr = ESCAPER.escape(
DATE_FORMAT.format(new Date(getNumberType(boundType, DATE_FIELD_NAME)
.longValue())), LOCALE, EscapeQuerySyntax.Type.STRING).toString();
sb.append("+").append(DATE_FIELD_NAME).append(operator).append('"').append(boundDateStr).append('"');
testQuery(sb.toString(), expectedDocCount);
}
public void assertSimpleQuery(NumberType numberType, int expectedDocCount)
throws QueryNodeException, IOException {
StringBuilder sb = new StringBuilder();
for (LegacyNumericType type : LegacyNumericType.values()) {
String numberStr = numberToString(getNumberType(numberType, type.name()));
sb.append('+').append(type.name()).append(":\"").append(numberStr)
.append("\" ");
}
String dateStr = ESCAPER.escape(
DATE_FORMAT.format(new Date(getNumberType(numberType, DATE_FIELD_NAME)
.longValue())), LOCALE, EscapeQuerySyntax.Type.STRING).toString();
sb.append('+').append(DATE_FIELD_NAME).append(":\"").append(dateStr)
.append('"');
testQuery(sb.toString(), expectedDocCount);
}
private void testQuery(String queryStr, int expectedDocCount)
throws QueryNodeException, IOException {
if (VERBOSE) System.out.println("Parsing: " + queryStr);
Query query = qp.parse(queryStr, FIELD_NAME);
if (VERBOSE) System.out.println("Querying: " + query);
TopDocs topDocs = searcher.search(query, 1000);
String msg = "Query <" + queryStr + "> retrieved " + topDocs.totalHits
+ " document(s), " + expectedDocCount + " document(s) expected.";
if (VERBOSE) System.out.println(msg);
assertEquals(msg, expectedDocCount, topDocs.totalHits);
}
private static String numberToString(Number number) {
return number == null ? "*" : ESCAPER.escape(NUMBER_FORMAT.format(number),
LOCALE, EscapeQuerySyntax.Type.STRING).toString();
}
private static Number normalizeNumber(Number number) throws ParseException {
return NUMBER_FORMAT.parse(NUMBER_FORMAT.format(number));
}
@AfterClass
public static void afterClass() throws Exception {
searcher = null;
reader.close();
reader = null;
directory.close();
directory = null;
qp = null;
LOCALE = null;
TIMEZONE = null;
NUMBER_FORMAT = null;
DATE_FORMAT = null;
ESCAPER = null;
}
}

View File

@ -23,7 +23,6 @@ import org.apache.lucene.document.IntPoint;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.legacy.LegacyIntField;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.LuceneTestCase;
@ -53,7 +52,6 @@ class CoreParserTestIndexData implements Closeable {
Document doc = new Document();
doc.add(LuceneTestCase.newTextField("date", date, Field.Store.YES));
doc.add(LuceneTestCase.newTextField("contents", content, Field.Store.YES));
doc.add(new LegacyIntField("date2", Integer.valueOf(date), Field.Store.NO));
doc.add(new IntPoint("date3", Integer.valueOf(date)));
writer.addDocument(doc);
line = d.readLine();

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<BooleanQuery fieldName="contents">
<Clause occurs="should">
<TermQuery>merger</TermQuery>
</Clause>
<Clause occurs="mustnot">
<TermQuery >sumitomo</TermQuery>
</Clause>
<Clause occurs="must">
<TermQuery>bank</TermQuery>
</Clause>
<Clause occurs="must">
<LegacyNumericRangeQuery fieldName="date2" lowerTerm="19870409" upperTerm="19870412"/>
</Clause>
</BooleanQuery>

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<BooleanQuery fieldName="contents">
<Clause occurs="should">
<TermQuery>merger</TermQuery>
</Clause>
<Clause occurs="mustnot">
<TermQuery >sumitomo</TermQuery>
</Clause>
<Clause occurs="must">
<TermQuery>bank</TermQuery>
</Clause>
<Clause occurs="must">
<LegacyNumericRangeQuery fieldName="date2" upperTerm="19870412"/>
</Clause>
</BooleanQuery>

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<BooleanQuery fieldName="contents">
<Clause occurs="should">
<TermQuery>merger</TermQuery>
</Clause>
<Clause occurs="mustnot">
<TermQuery >sumitomo</TermQuery>
</Clause>
<Clause occurs="must">
<TermQuery>bank</TermQuery>
</Clause>
<Clause occurs="must">
<LegacyNumericRangeQuery fieldName="date2"/>
</Clause>
</BooleanQuery>

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<BooleanQuery fieldName="contents">
<Clause occurs="should">
<TermQuery>merger</TermQuery>
</Clause>
<Clause occurs="mustnot">
<TermQuery >sumitomo</TermQuery>
</Clause>
<Clause occurs="must">
<TermQuery>bank</TermQuery>
</Clause>
<Clause occurs="must">
<LegacyNumericRangeQuery fieldName="date2" lowerTerm="19870409"/>
</Clause>
</BooleanQuery>

View File

@ -132,26 +132,6 @@ public class TestCoreParser extends LuceneTestCase {
Query q = parse("NestedBooleanQuery.xml");
dumpResults("Nested Boolean query", q, 5);
}
public void testNumericRangeQueryXML() throws ParserException, IOException {
Query q = parse("LegacyNumericRangeQuery.xml");
dumpResults("LegacyNumericRangeQuery", q, 5);
}
public void testNumericRangeQueryXMLWithoutLowerTerm() throws ParserException, IOException {
Query q = parse("LegacyNumericRangeQueryWithoutLowerTerm.xml");
dumpResults("LegacyNumericRangeQueryWithoutLowerTerm", q, 5);
}
public void testNumericRangeQueryXMLWithoutUpperTerm() throws ParserException, IOException {
Query q = parse("LegacyNumericRangeQueryWithoutUpperTerm.xml");
dumpResults("LegacyNumericRangeQueryWithoutUpperTerm", q, 5);
}
public void testNumericRangeQueryXMLWithoutRange() throws ParserException, IOException {
Query q = parse("LegacyNumericRangeQueryWithoutRange.xml");
dumpResults("LegacyNumericRangeQueryWithoutRange", q, 5);
}
public void testPointRangeQuery() throws ParserException, IOException {
Query q = parse("PointRangeQuery.xml");

View File

@ -63,12 +63,31 @@ Apache UIMA 2.3.1
Apache ZooKeeper 3.4.6
Jetty 9.3.8.v20160314
Detailed Change List
----------------------
New Features
----------------------
Bug Fixes
----------------------
* SOLR-9310: PeerSync fails on a node restart due to IndexFingerPrint mismatch (Pushkar Raste, noble)
Other Changes
----------------------
* SOLR-9412: Add failOnMissingParams option to MacroExpander, add TestMacroExpander class.
(Jon Dorando, Christine Poerschke)
Optimizations
----------------------
Other Changes
----------------------
* SOLR-7362: Fix TestReqParamsAPI test failures (noble, Varun Thacker)
================== 6.2.0 ==================
Versions of Major Components

View File

@ -29,6 +29,7 @@ import java.util.Map;
import com.google.common.collect.ImmutableMap;
import org.apache.solr.cloud.ZkSolrResourceLoader;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.util.Utils;
import org.apache.zookeeper.KeeperException;
@ -156,10 +157,8 @@ public class RequestParams implements MapSerializable {
requestParams = new RequestParams((Map) o[0], (Integer) o[1]);
log.info("request params refreshed to version {}", requestParams.getZnodeVersion());
}
} catch (KeeperException e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (KeeperException | InterruptedException e) {
SolrZkClient.checkInterrupted(e);
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
}

View File

@ -188,12 +188,12 @@ public class SolrConfigHandler extends RequestHandlerBase implements SolrCoreAwa
resp.add(ZNODEVER, Utils.makeMap(
ConfigOverlay.NAME, req.getCore().getSolrConfig().getOverlay().getZnodeVersion(),
RequestParams.NAME, req.getCore().getSolrConfig().getRequestParams().getZnodeVersion()));
boolean checkStale = false;
boolean isStale = false;
int expectedVersion = req.getParams().getInt(ConfigOverlay.NAME, -1);
int actualVersion = req.getCore().getSolrConfig().getOverlay().getZnodeVersion();
if (expectedVersion > actualVersion) {
log.info("expecting overlay version {} but my version is {}", expectedVersion, actualVersion);
checkStale = true;
isStale = true;
} else if (expectedVersion != -1) {
log.info("I already have the expected version {} of config", expectedVersion);
}
@ -201,11 +201,11 @@ public class SolrConfigHandler extends RequestHandlerBase implements SolrCoreAwa
actualVersion = req.getCore().getSolrConfig().getRequestParams().getZnodeVersion();
if (expectedVersion > actualVersion) {
log.info("expecting params version {} but my version is {}", expectedVersion, actualVersion);
checkStale = true;
isStale = true;
} else if (expectedVersion != -1) {
log.info("I already have the expected version {} of params", expectedVersion);
}
if (checkStale && req.getCore().getResourceLoader() instanceof ZkSolrResourceLoader) {
if (isStale && req.getCore().getResourceLoader() instanceof ZkSolrResourceLoader) {
new Thread(() -> {
if (!reloadLock.tryLock()) {
log.info("Another reload is in progress . Not doing anything");
@ -221,7 +221,7 @@ public class SolrConfigHandler extends RequestHandlerBase implements SolrCoreAwa
}
}, SolrConfigHandler.class.getSimpleName() + "-refreshconf").start();
} else {
log.info("checkStale {} , resourceloader {}", checkStale, req.getCore().getResourceLoader().getClass().getName());
log.info("isStale {} , resourceloader {}", isStale, req.getCore().getResourceLoader().getClass().getName());
}
} else {
@ -287,7 +287,7 @@ public class SolrConfigHandler extends RequestHandlerBase implements SolrCoreAwa
for (Map.Entry<String, Object> entry : map.entrySet()) {
Map val = null;
Map val;
String key = entry.getKey();
if (isNullOrEmpty(key)) {
op.addError("null key ");
@ -354,16 +354,13 @@ public class SolrConfigHandler extends RequestHandlerBase implements SolrCoreAwa
if (ops.isEmpty()) {
ZkController.touchConfDir(zkLoader);
} else {
log.info("persisting params data : {}", Utils.toJSONString(params.toMap()));
log.debug("persisting params data : {}", Utils.toJSONString(params.toMap()));
int latestVersion = ZkController.persistConfigResourceToZooKeeper(zkLoader,
params.getZnodeVersion(),
RequestParams.RESOURCE,
params.toByteArray(), true);
log.info("persisted to version : {} ", latestVersion);
params.getZnodeVersion(), RequestParams.RESOURCE, params.toByteArray(), true);
log.debug("persisted to version : {} ", latestVersion);
waitForAllReplicasState(req.getCore().getCoreDescriptor().getCloudDescriptor().getCollectionName(),
req.getCore().getCoreDescriptor().getCoreContainer().getZkController(),
RequestParams.NAME,
latestVersion, 30);
req.getCore().getCoreDescriptor().getCoreContainer().getZkController(), RequestParams.NAME, latestVersion, 30);
}
} else {

View File

@ -34,10 +34,16 @@ public class MacroExpander {
private String macroStart = MACRO_START;
private char escape = '\\';
private int level;
private final boolean failOnMissingParams;
public MacroExpander(Map<String,String[]> orig) {
this(orig, false);
}
public MacroExpander(Map<String,String[]> orig, boolean failOnMissingParams) {
this.orig = orig;
this.failOnMissingParams = failOnMissingParams;
}
public static Map<String,String[]> expand(Map<String,String[]> params) {
@ -163,8 +169,14 @@ public class MacroExpander {
String replacement = replacementList!=null ? replacementList[0] : defVal;
if (replacement != null) {
String expandedReplacement = expand(replacement);
if (failOnMissingParams && expandedReplacement == null) {
return null;
}
sb.append(expandedReplacement);
}
else if (failOnMissingParams) {
return null;
}
} catch (SyntaxError syntaxError) {
// append the part we would have skipped

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.queryparser.xml.builders;
package org.apache.solr.search;
import org.apache.lucene.search.Query;
import org.apache.lucene.legacy.LegacyNumericRangeQuery;
@ -22,6 +22,7 @@ import org.apache.lucene.legacy.LegacyNumericUtils;
import org.apache.lucene.queryparser.xml.DOMUtils;
import org.apache.lucene.queryparser.xml.ParserException;
import org.apache.lucene.queryparser.xml.QueryBuilder;
import org.apache.lucene.queryparser.xml.builders.PointRangeQueryBuilder;
import org.w3c.dom.Element;
/**

View File

@ -21,7 +21,6 @@ import java.util.Map;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.queryparser.xml.CoreParser;
import org.apache.lucene.queryparser.xml.QueryBuilder;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.SolrResourceLoader;
import org.apache.solr.request.SolrQueryRequest;
@ -38,6 +37,7 @@ public class SolrCoreParser extends CoreParser implements NamedListInitializedPl
public SolrCoreParser(String defaultField, Analyzer analyzer,
SolrQueryRequest req) {
super(defaultField, analyzer);
queryFactory.addBuilder("LegacyNumericRangeQuery", new LegacyNumericRangeQueryBuilder());
this.req = req;
}

View File

@ -22,9 +22,10 @@ import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.cloud.AbstractFullDistribZkTestBase;
import org.apache.solr.cloud.SolrCloudTestCase;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.Slice;
@ -32,37 +33,48 @@ import org.apache.solr.common.cloud.ZkStateReader;
import org.apache.solr.core.RequestParams;
import org.apache.solr.core.TestSolrConfigHandler;
import org.apache.solr.util.RestTestHarness;
import org.junit.BeforeClass;
import org.junit.Test;
import static java.util.Arrays.asList;
import static org.apache.solr.handler.TestSolrConfigHandlerCloud.compareValues;
public class TestReqParamsAPI extends AbstractFullDistribZkTestBase {
public class TestReqParamsAPI extends SolrCloudTestCase {
private List<RestTestHarness> restTestHarnesses = new ArrayList<>();
private static String COLL_NAME = "collection1";
private void setupHarnesses() {
for (final SolrClient client : clients) {
RestTestHarness harness = new RestTestHarness(() -> ((HttpSolrClient) client).getBaseURL());
for (final JettySolrRunner jettySolrRunner : cluster.getJettySolrRunners()) {
RestTestHarness harness = new RestTestHarness(() -> jettySolrRunner.getBaseUrl().toString() + "/" + COLL_NAME);
restTestHarnesses.add(harness);
}
}
@Override
public void distribTearDown() throws Exception {
super.distribTearDown();
for (RestTestHarness r : restTestHarnesses) {
r.close();
}
@BeforeClass
public static void createCluster() throws Exception {
System.setProperty("managed.schema.mutable", "true");
configureCluster(2)
.addConfig("conf1", TEST_PATH().resolve("configsets").resolve("cloud-managed").resolve("conf"))
.configure();
cluster.createCollection(COLL_NAME, 1, 2, "conf1", null);
}
@Test
public void test() throws Exception {
setupHarnesses();
testReqParams();
try {
setupHarnesses();
testReqParams();
} finally {
for (RestTestHarness r : restTestHarnesses) {
r.close();
}
}
}
private void testReqParams() throws Exception {
DocCollection coll = cloudClient.getZkStateReader().getClusterState().getCollection("collection1");
CloudSolrClient cloudClient = cluster.getSolrClient();
DocCollection coll = cloudClient.getZkStateReader().getClusterState().getCollection(COLL_NAME);
List<String> urls = new ArrayList<>();
for (Slice slice : coll.getSlices()) {
for (Replica replica : slice.getReplicas())
@ -70,14 +82,27 @@ public class TestReqParamsAPI extends AbstractFullDistribZkTestBase {
}
RestTestHarness writeHarness = restTestHarnesses.get(random().nextInt(restTestHarnesses.size()));
String payload = " {\n" +
String payload = "{\n" +
"'create-requesthandler' : { 'name' : '/dump0', 'class': 'org.apache.solr.handler.DumpRequestHandler' }\n" +
"}";
TestSolrConfigHandler.runConfigCommand(writeHarness, "/config?wt=json", payload);
payload = "{\n" +
"'create-requesthandler' : { 'name' : '/dump1', 'class': 'org.apache.solr.handler.DumpRequestHandler', 'useParams':'x' }\n" +
"}";
TestSolrConfigHandler.runConfigCommand(writeHarness, "/config?wt=json", payload);
AbstractFullDistribZkTestBase.waitForRecoveriesToFinish(COLL_NAME, cloudClient.getZkStateReader(), false, true, 90);
payload = " {\n" +
" 'set' : {'x': {" +
" 'a':'A val',\n" +
" 'b': 'B val'}\n" +
" }\n" +
" }";
TestSolrConfigHandler.runConfigCommand(writeHarness, "/config/params?wt=json", payload);
Map result = TestSolrConfigHandler.testForResponseElement(null,
@ -89,12 +114,6 @@ public class TestReqParamsAPI extends AbstractFullDistribZkTestBase {
10);
compareValues(result, "B val", asList("response", "params", "x", "b"));
payload = "{\n" +
"'create-requesthandler' : { 'name' : '/dump0', 'class': 'org.apache.solr.handler.DumpRequestHandler' }\n" +
"}";
TestSolrConfigHandler.runConfigCommand(writeHarness, "/config?wt=json", payload);
TestSolrConfigHandler.testForResponseElement(null,
urls.get(random().nextInt(urls.size())),
"/config/overlay?wt=json",
@ -120,12 +139,6 @@ public class TestReqParamsAPI extends AbstractFullDistribZkTestBase {
"fomrequest",
5);
payload = "{\n" +
"'create-requesthandler' : { 'name' : '/dump1', 'class': 'org.apache.solr.handler.DumpRequestHandler', 'useParams':'x' }\n" +
"}";
TestSolrConfigHandler.runConfigCommand(writeHarness, "/config?wt=json", payload);
result = TestSolrConfigHandler.testForResponseElement(null,
urls.get(random().nextInt(urls.size())),
"/config/overlay?wt=json",
@ -263,9 +276,5 @@ public class TestReqParamsAPI extends AbstractFullDistribZkTestBase {
asList("response", "params", "y", "p"),
null,
10);
}
}

View File

@ -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.solr.request.macro;
import java.util.Map;
import java.util.HashMap;
import org.apache.lucene.util.LuceneTestCase;
import org.junit.Test;
/*
* Tests for the MacroExpander
*/
public class TestMacroExpander extends LuceneTestCase {
@Test
public void testExamples() {
final Map<String,String[]> testParams = new HashMap<String,String[]>();
final MacroExpander me;
// example behavior unaffected by absence or value of failOnMissingParams
if (random().nextBoolean()) {
me = new MacroExpander(testParams);
} else {
final boolean failOnMissingParams = random().nextBoolean();
me = new MacroExpander(testParams, failOnMissingParams);
}
//default examples: https://cwiki.apache.org/confluence/display/solr/Parameter+Substitution
// and http://yonik.com/solr-query-parameter-substitution/
//using params
String[] lowParams = {"50"};
testParams.put("low",lowParams);
String[] highParams = {"100"};
testParams.put("high",highParams);
String testQuery = "q=popularity:[ ${low} TO ${high} ]";
assertEquals("q=popularity:[ 50 TO 100 ]", me.expand(testQuery));
//using default values
testQuery = "q=popularity:[ ${low:10} TO ${high:20} ]";
assertEquals("q=popularity:[ 50 TO 100 ]", me.expand(testQuery));
testParams.clear();
assertEquals("q=popularity:[ 10 TO 20 ]", me.expand(testQuery));
//multiple levels of substitutions
testQuery = "q=${pop_query}";
String[] popQueryParams = {"${pop_field}:[ ${low} TO ${high} ] AND inStock:true"};
String[] popFieldParams = {"popularity"};
testParams.put("low",lowParams);
testParams.put("high",highParams);
testParams.put("pop_query",popQueryParams);
testParams.put("pop_field",popFieldParams);
assertEquals("q=popularity:[ 50 TO 100 ] AND inStock:true", me.expand(testQuery));
//end default examples
}
@Test
public void testOnMissingParams() {
final Map<String,String[]> testParams = new HashMap<String,String[]>();
final MacroExpander meSkipOnMissingParams = new MacroExpander(testParams);
final MacroExpander meFailOnMissingParams = new MacroExpander(testParams, true);
final String low = "50";
final String high = "100";
testParams.put("low", new String[]{ low });
testParams.put("high", new String[]{ high });
final String testQuery = "q=popularity:[ ${low} TO ${high} ]";
//when params all present the expansion results match
final String expandedQuery = "q=popularity:[ "+low+" TO "+high+" ]";
assertEquals(expandedQuery, meSkipOnMissingParams.expand(testQuery));
assertEquals(expandedQuery, meFailOnMissingParams.expand(testQuery));
//when param(s) missing and have no default the expansion results differ
final String expandedLow;
final String expandedHigh;
if (random().nextBoolean()) { // keep low
expandedLow = low;
} else {
expandedLow = "";
testParams.remove("low");
}
if (random().nextBoolean()) { // keep high
expandedHigh = high;
} else {
expandedHigh = "";
testParams.remove("high");
}
assertEquals("q=popularity:[ "+expandedLow+" TO "+expandedHigh+" ]",
meSkipOnMissingParams.expand(testQuery));
if (testParams.size() < 2) { // at least one of the two parameters missing
assertEquals(null, meFailOnMissingParams.expand(testQuery));
}
}
}

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.queryparser.xml.builders;
package org.apache.solr.search;
import org.apache.lucene.search.Query;
import org.apache.lucene.util.LuceneTestCase;
@ -32,7 +32,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
public class TestNumericRangeQueryBuilder extends LuceneTestCase {
public class TestLegacyNumericRangeQueryBuilder extends LuceneTestCase {
public void testGetFilterHandleNumericParseErrorStrict() throws Exception {
LegacyNumericRangeQueryBuilder filterBuilder = new LegacyNumericRangeQueryBuilder();