Index: src/java/org/apache/lucene/search/ExactPhraseScorer.java =================================================================== --- src/java/org/apache/lucene/search/ExactPhraseScorer.java (revision 447480) +++ src/java/org/apache/lucene/search/ExactPhraseScorer.java (working copy) @@ -28,6 +28,7 @@ protected final float phraseFreq() throws IOException { // sort list with pq + pq.clear(); for (PhrasePositions pp = first; pp != null; pp = pp.next) { pp.firstPosition(); pq.put(pp); // build pq from list Index: src/java/org/apache/lucene/search/PhraseQueue.java =================================================================== --- src/java/org/apache/lucene/search/PhraseQueue.java (revision 447480) +++ src/java/org/apache/lucene/search/PhraseQueue.java (working copy) @@ -27,7 +27,10 @@ PhrasePositions pp1 = (PhrasePositions)o1; PhrasePositions pp2 = (PhrasePositions)o2; if (pp1.doc == pp2.doc) - return pp1.position < pp2.position; + if (pp1.position == pp2.position) + return pp1.position+pp1.offset < pp2.position+pp2.offset; + else + return pp1.position < pp2.position; else return pp1.doc < pp2.doc; } Index: src/java/org/apache/lucene/search/PhraseScorer.java =================================================================== --- src/java/org/apache/lucene/search/PhraseScorer.java (revision 447480) +++ src/java/org/apache/lucene/search/PhraseScorer.java (working copy) @@ -93,6 +93,7 @@ } public boolean skipTo(int target) throws IOException { + firstTime = false; for (PhrasePositions pp = first; more && pp != null; pp = pp.next) { more = pp.skipTo(target); } Index: src/test/org/apache/lucene/search/QueryUtils.java =================================================================== --- src/test/org/apache/lucene/search/QueryUtils.java (revision 467721) +++ src/test/org/apache/lucene/search/QueryUtils.java (working copy) @@ -84,41 +84,66 @@ */ public static void checkSkipTo(final Query q, final IndexSearcher s) throws IOException { //System.out.println("Checking "+q); - final Weight w = q.weight(s); - final Scorer scorer = w.scorer(s.getIndexReader()); - - // FUTURE: ensure scorer.doc()==-1 - + if (BooleanQuery.getUseScorer14()) return; // 1.4 doesn't support skipTo - final int[] which = new int[1]; - final int[] sdoc = new int[] {-1}; - final float maxDiff = 1e-5f; - s.search(q,new HitCollector() { - public void collect(int doc, float score) { - try { - boolean more = (which[0]++&0x02)==0 ? scorer.skipTo(sdoc[0]+1) : scorer.next(); - sdoc[0] = scorer.doc(); - float scorerScore = scorer.score(); - float scoreDiff = Math.abs(score-scorerScore); - scoreDiff=0; // TODO: remove this go get LUCENE-697 failures - if (more==false || doc != sdoc[0] || scoreDiff>maxDiff) { - throw new RuntimeException("ERROR matching docs:" - +"\n\tscorer.more=" + more + " doc="+sdoc[0] + " score="+scorerScore - +"\n\thitCollector.doc=" + doc + " score="+score - +"\n\t Scorer=" + scorer - +"\n\t Query=" + q - +"\n\t Searcher=" + s - ); + final int skip_op = 0; + final int next_op = 1; + final int orders [][] = { + {skip_op}, + {next_op}, + {skip_op, next_op}, + {next_op, skip_op}, + {skip_op, skip_op, next_op, next_op}, + {next_op, next_op, skip_op, skip_op}, + {skip_op, skip_op, skip_op, next_op, next_op}, + }; + for (int k = 0; k < orders.length; k++) { + final int order[] = orders[k]; + //System.out.print("Order:");for (int i = 0; i < order.length; i++) System.out.print(order[i]==skip_op ? " skip()":" next()"); System.out.println(); + final int opidx[] = {0}; + + final Weight w = q.weight(s); + final Scorer scorer = w.scorer(s.getIndexReader()); + + // FUTURE: ensure scorer.doc()==-1 + + final int[] sdoc = new int[] {-1}; + final float maxDiff = 1e-5f; + s.search(q,new HitCollector() { + public void collect(int doc, float score) { + try { + int op = order[(opidx[0]++)%order.length]; + //System.out.println(op==skip_op ? "skip("+(sdoc[0]+1)+")":"next()"); + boolean more = op==skip_op ? scorer.skipTo(sdoc[0]+1) : scorer.next(); + sdoc[0] = scorer.doc(); + float scorerScore = scorer.score(); + float scoreDiff = Math.abs(score-scorerScore); + if (more==false || doc != sdoc[0] || scoreDiff>maxDiff) { + StringBuffer sbord = new StringBuffer(); + for (int i = 0; i < order.length; i++) + sbord.append(order[i]==skip_op ? " skip()":" next()"); + throw new RuntimeException("ERROR matching docs:" + +"\n\tscorer.more=" + more + " doc="+sdoc[0] + " score="+scorerScore + +"\n\thitCollector.doc=" + doc + " score="+score + +"\n\t Scorer=" + scorer + +"\n\t Query=" + q + +"\n\t Searcher=" + s + +"\n\t Order=" + sbord + ); + } + } catch (IOException e) { + throw new RuntimeException(e); } - } catch (IOException e) { - throw new RuntimeException(e); } - } - }); - - // make sure next call to scorer is false. - TestCase.assertFalse((which[0]++&0x02)==0 ? scorer.skipTo(sdoc[0]+1) : scorer.next()); + }); + + // make sure next call to scorer is false. + int op = order[(opidx[0]++)%order.length]; + //System.out.println(op==skip_op ? "last: skip()":"last: next()"); + boolean more = op==skip_op ? scorer.skipTo(sdoc[0]+1) : scorer.next(); + TestCase.assertFalse(more); + } } }