diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index cc65e7d5cd3..d7eaf6ff289 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -163,6 +163,10 @@ New Features eg: stats.field={!min=true max=true}field_name (Tomas Fernandez-Lobbe, Xu Zhang, hossman) +* SOLR-7218: lucene/solr query syntax to give any query clause a constant score. + General Form: ^= + Example: (color:blue color:green)^=2.0 text:shoes + Bug Fixes ---------------------- diff --git a/solr/core/src/java/org/apache/solr/parser/CharStream.java b/solr/core/src/java/org/apache/solr/parser/CharStream.java index 7536df001f8..0400af47e05 100644 --- a/solr/core/src/java/org/apache/solr/parser/CharStream.java +++ b/solr/core/src/java/org/apache/solr/parser/CharStream.java @@ -27,6 +27,22 @@ interface CharStream { */ char readChar() throws java.io.IOException; + @Deprecated + /** + * Returns the column position of the character last read. + * @deprecated + * @see #getEndColumn + */ + int getColumn(); + + @Deprecated + /** + * Returns the line number of the character last read. + * @deprecated + * @see #getEndLine + */ + int getLine(); + /** * Returns the column number of the last character for current token (being * matched after the last call to BeginTOken). @@ -96,4 +112,4 @@ interface CharStream { void Done(); } -/* JavaCC - OriginalChecksum=a81c9280a3ec4578458c607a9d95acb4 (do not edit this line) */ +/* JavaCC - OriginalChecksum=48b70e7c01825c8f301c7362bf1028d8 (do not edit this line) */ diff --git a/solr/core/src/java/org/apache/solr/parser/FastCharStream.java b/solr/core/src/java/org/apache/solr/parser/FastCharStream.java index 2e3b4662099..91dbf9145d7 100644 --- a/solr/core/src/java/org/apache/solr/parser/FastCharStream.java +++ b/solr/core/src/java/org/apache/solr/parser/FastCharStream.java @@ -108,6 +108,15 @@ public final class FastCharStream implements CharStream { } } + @Override + public final int getColumn() { + return bufferStart + bufferPosition; + } + @Override + public final int getLine() { + return 1; + } + @Override public final int getEndColumn() { return bufferStart + bufferPosition; } diff --git a/solr/core/src/java/org/apache/solr/parser/ParseException.java b/solr/core/src/java/org/apache/solr/parser/ParseException.java index 9dc5cc49864..7732a7d5295 100644 --- a/solr/core/src/java/org/apache/solr/parser/ParseException.java +++ b/solr/core/src/java/org/apache/solr/parser/ParseException.java @@ -184,4 +184,4 @@ public class ParseException extends Exception { } } -/* JavaCC - OriginalChecksum=d7aa203ee92ebbb23011a23311e60537 (do not edit this line) */ +/* JavaCC - OriginalChecksum=25e1ae9ad9614c4ce31c4b83f8a7397b (do not edit this line) */ diff --git a/solr/core/src/java/org/apache/solr/parser/QueryParser.java b/solr/core/src/java/org/apache/solr/parser/QueryParser.java index 7624462ef83..709ad00dd38 100644 --- a/solr/core/src/java/org/apache/solr/parser/QueryParser.java +++ b/solr/core/src/java/org/apache/solr/parser/QueryParser.java @@ -100,7 +100,7 @@ public class QueryParser extends SolrQueryParserBase implements QueryParserConst } final public Query Query(String field) throws ParseException, SyntaxError { - List clauses = new ArrayList<>(); + List clauses = new ArrayList(); Query q, firstQuery=null; int conj, mods; mods = Modifiers(); @@ -581,7 +581,7 @@ public class QueryParser extends SolrQueryParserBase implements QueryParserConst return (jj_ntk = jj_nt.kind); } - private java.util.List jj_expentries = new java.util.ArrayList<>(); + private java.util.List jj_expentries = new java.util.ArrayList(); private int[] jj_expentry; private int jj_kind = -1; private int[] jj_lasttokens = new int[100]; diff --git a/solr/core/src/java/org/apache/solr/parser/QueryParser.jj b/solr/core/src/java/org/apache/solr/parser/QueryParser.jj index dafc329146f..aaa865ae27b 100644 --- a/solr/core/src/java/org/apache/solr/parser/QueryParser.jj +++ b/solr/core/src/java/org/apache/solr/parser/QueryParser.jj @@ -103,7 +103,7 @@ PARSER_END(QueryParser) } TOKEN : { - )+ ( "." (<_NUM_CHAR>)+ )? > : DEFAULT + )+ ( "." (<_NUM_CHAR>)+ )? > : DEFAULT } TOKEN : { diff --git a/solr/core/src/java/org/apache/solr/parser/QueryParserTokenManager.java b/solr/core/src/java/org/apache/solr/parser/QueryParserTokenManager.java index a9253fa75d6..00103452fea 100644 --- a/solr/core/src/java/org/apache/solr/parser/QueryParserTokenManager.java +++ b/solr/core/src/java/org/apache/solr/parser/QueryParserTokenManager.java @@ -692,7 +692,7 @@ private int jjMoveStringLiteralDfa0_0() private int jjMoveNfa_0(int startState, int curPos) { int startsAt = 0; - jjnewStateCnt = 4; + jjnewStateCnt = 5; int i = 1; jjstateSet[0] = startState; int kind = 0x7fffffff; @@ -712,28 +712,34 @@ private int jjMoveNfa_0(int startState, int curPos) { if (kind > 29) kind = 29; - jjCheckNAddTwoStates(1, 2); + jjCheckNAddTwoStates(2, 3); } else if (curChar == 45) - jjCheckNAdd(1); + jjCheckNAdd(2); + else if (curChar == 61) + jjCheckNAddTwoStates(1, 2); break; case 1: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 29) - kind = 29; - jjCheckNAddTwoStates(1, 2); + if (curChar == 45) + jjCheckNAdd(2); break; case 2: - if (curChar == 46) - jjCheckNAdd(3); - break; - case 3: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 29) kind = 29; - jjCheckNAdd(3); + jjCheckNAddTwoStates(2, 3); + break; + case 3: + if (curChar == 46) + jjCheckNAdd(4); + break; + case 4: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 29) + kind = 29; + jjCheckNAdd(4); break; default : break; } @@ -772,7 +778,7 @@ private int jjMoveNfa_0(int startState, int curPos) kind = 0x7fffffff; } ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 4 - (jjnewStateCnt = startsAt))) + if ((i = jjnewStateCnt) == (startsAt = 5 - (jjnewStateCnt = startsAt))) return curPos; try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { return curPos; } diff --git a/solr/core/src/java/org/apache/solr/parser/SolrQueryParserBase.java b/solr/core/src/java/org/apache/solr/parser/SolrQueryParserBase.java index c36f714df7c..266d4a55610 100644 --- a/solr/core/src/java/org/apache/solr/parser/SolrQueryParserBase.java +++ b/solr/core/src/java/org/apache/solr/parser/SolrQueryParserBase.java @@ -29,6 +29,7 @@ import org.apache.lucene.index.Term; import org.apache.lucene.search.AutomatonQuery; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.ConstantScoreQuery; import org.apache.lucene.search.FuzzyQuery; import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.MultiPhraseQuery; @@ -552,13 +553,28 @@ public abstract class SolrQueryParserBase extends QueryBuilder { // called from parser Query handleBoost(Query q, Token boost) { - if (boost != null) { - float boostVal = Float.parseFloat(boost.image); - // avoid boosting null queries, such as those caused by stop words - if (q != null) { - q.setBoost(q.getBoost() * boostVal); - } + // q==null check is to avoid boosting null queries, such as those caused by stop words + if (boost == null || boost.image.length()==0 || q == null) { + return q; } + + if (boost.image.charAt(0) == '=') { + // syntax looks like foo:x^=3 + float val = Float.parseFloat(boost.image.substring(1)); + Query newQ = q; + if (// q instanceof FilterQuery || // TODO: fix this when FilterQuery is introduced to avoid needless wrapping: SOLR-7219 + q instanceof ConstantScoreQuery) { + newQ.setBoost(val); + } else { + newQ = new ConstantScoreQuery(q); + newQ.setBoost(val); + } + return newQ; + } + + float boostVal = Float.parseFloat(boost.image); + q.setBoost(q.getBoost() * boostVal); + return q; } diff --git a/solr/core/src/java/org/apache/solr/parser/Token.java b/solr/core/src/java/org/apache/solr/parser/Token.java index b62daef8018..0d596035928 100644 --- a/solr/core/src/java/org/apache/solr/parser/Token.java +++ b/solr/core/src/java/org/apache/solr/parser/Token.java @@ -128,4 +128,4 @@ public class Token implements java.io.Serializable { } } -/* JavaCC - OriginalChecksum=9036cc9068ac33d9c79403fe5349f705 (do not edit this line) */ +/* JavaCC - OriginalChecksum=f463ad6fd3205ca07166de02ee86b907 (do not edit this line) */ diff --git a/solr/core/src/java/org/apache/solr/parser/TokenMgrError.java b/solr/core/src/java/org/apache/solr/parser/TokenMgrError.java index ca885ad6b61..ecdcc539d66 100644 --- a/solr/core/src/java/org/apache/solr/parser/TokenMgrError.java +++ b/solr/core/src/java/org/apache/solr/parser/TokenMgrError.java @@ -144,4 +144,4 @@ public class TokenMgrError extends Error this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); } } -/* JavaCC - OriginalChecksum=59744072870f5c27fc8796947fc3b06f (do not edit this line) */ +/* JavaCC - OriginalChecksum=200a46f65c1a0f71a7f037b35f4e934e (do not edit this line) */ diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java b/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java index 44e09bf8447..5edf4419e5d 100644 --- a/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java +++ b/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java @@ -16,7 +16,10 @@ */ package org.apache.solr.search; +import org.apache.lucene.search.ConstantScoreQuery; +import org.apache.lucene.search.Query; import org.apache.solr.SolrTestCaseJ4; +import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.transform.ScoreAugmenter; import org.junit.BeforeClass; import org.junit.Test; @@ -162,4 +165,23 @@ public class TestSolrQueryParser extends SolrTestCaseJ4 { } + + + @Test + public void testCSQ() throws Exception { + SolrQueryRequest req = req(); + + QParser qParser = QParser.getParser("text:x^=3", "lucene", req); + Query q = qParser.getQuery(); + assertTrue( q instanceof ConstantScoreQuery); + assertEquals(3.0, q.getBoost(), 0.0f); + + qParser = QParser.getParser("(text:x text:y)^=-3", "lucene", req); + q = qParser.getQuery(); + assertTrue( q instanceof ConstantScoreQuery ); + assertEquals(-3.0, q.getBoost(), 0.0f); + + req.close(); + } + }