You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ho...@apache.org on 2011/08/01 00:08:44 UTC

svn commit: r1152653 - in /lucene/dev/trunk: lucene/src/test-framework/org/apache/lucene/util/ solr/ solr/core/src/java/org/apache/solr/search/ solr/core/src/test/org/apache/solr/search/ solr/core/src/test/org/apache/solr/search/function/

Author: hossman
Date: Sun Jul 31 22:08:43 2011
New Revision: 1152653

URL: http://svn.apache.org/viewvc?rev=1152653&view=rev
Log:
SOLR-2606: Fixed sort parsing of fields containing punctuation

Modified:
    lucene/dev/trunk/lucene/src/test-framework/org/apache/lucene/util/_TestUtil.java
    lucene/dev/trunk/solr/CHANGES.txt
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/QueryParsing.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/TestSort.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java

Modified: lucene/dev/trunk/lucene/src/test-framework/org/apache/lucene/util/_TestUtil.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/src/test-framework/org/apache/lucene/util/_TestUtil.java?rev=1152653&r1=1152652&r2=1152653&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/src/test-framework/org/apache/lucene/util/_TestUtil.java (original)
+++ lucene/dev/trunk/lucene/src/test-framework/org/apache/lucene/util/_TestUtil.java Sun Jul 31 22:08:43 2011
@@ -281,14 +281,19 @@ public class _TestUtil {
     0x2A6DF, 0x2B73F, 0x2FA1F, 0xE007F, 0xE01EF, 0xFFFFF, 0x10FFFF
   };
   
-  /** Returns random string, all codepoints within the same unicode block. */
+  /** Returns random string of length between 0-20 codepoints, all codepoints within the same unicode block. */
   public static String randomRealisticUnicodeString(Random r) {
     return randomRealisticUnicodeString(r, 20);
   }
   
-  /** Returns random string, all codepoints within the same unicode block. */
+  /** Returns random string of length up to maxLength codepoints , all codepoints within the same unicode block. */
   public static String randomRealisticUnicodeString(Random r, int maxLength) {
-    final int end = r.nextInt(maxLength);
+    return randomRealisticUnicodeString(r, 0, 20);
+  }
+
+  /** Returns random string of length between min and max codepoints, all codepoints within the same unicode block. */
+  public static String randomRealisticUnicodeString(Random r, int minLength, int maxLength) {
+    final int end = minLength + r.nextInt(maxLength);
     final int block = r.nextInt(blockStarts.length);
     StringBuilder sb = new StringBuilder();
     for (int i = 0; i < end; i++)

Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1152653&r1=1152652&r2=1152653&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Sun Jul 31 22:08:43 2011
@@ -406,6 +406,10 @@ Bug Fixes
   in servlet containers such as WebSphere that do not use a default list
   (Jay R. Jaeger, hossman)
 
+* SOLR-2606: Fixed sort parsing of fields containing punctuation that 
+  failed due to sort by function changes introduced in SOLR-1297
+  (Mitsu Hadeishi, hossman)
+
  Other Changes
 ----------------------
 

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/QueryParsing.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/QueryParsing.java?rev=1152653&r1=1152652&r2=1152653&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/QueryParsing.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/search/QueryParsing.java Sun Jul 31 22:08:43 2011
@@ -247,10 +247,11 @@ public class QueryParsing {
 
         // short circuit test for a really simple field name
         String field = sp.getId(null);
-        ParseException qParserException = null;
+        Exception qParserException = null;
 
-        if (field == null || sp.ch() != ' ') {
+        if (field == null || !Character.isWhitespace(sp.peekChar())) {
           // let's try it as a function instead
+          field = null;
           String funcStr = sp.val.substring(start);
 
           QParser parser = QParser.getParser(funcStr, FunctionQParserPlugin.NAME, req);
@@ -297,7 +298,9 @@ public class QueryParsing {
               }
               continue;
             }
-          } catch (ParseException e) {
+          } catch (IOException ioe) {
+            throw ioe;
+          } catch (Exception e) {
             // hang onto this in case the string isn't a full field name either
             qParserException = e;
           }

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/TestSort.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/TestSort.java?rev=1152653&r1=1152652&r2=1152653&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/TestSort.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/TestSort.java Sun Jul 31 22:08:43 2011
@@ -24,21 +24,28 @@ import org.apache.lucene.index.IndexRead
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.search.*;
+import org.apache.lucene.search.SortField.Type;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.RAMDirectory;
 import org.apache.lucene.util.OpenBitSet;
-import org.apache.solr.util.AbstractSolrTestCase;
+import org.apache.lucene.util._TestUtil;
+
+import org.apache.solr.request.SolrQueryRequest;
+
+import org.apache.solr.SolrTestCaseJ4;
+
+import org.junit.BeforeClass;
 
 import java.io.IOException;
 import java.util.*;
 
-public class TestSort extends AbstractSolrTestCase {
-  @Override
-  public String getSchemaFile() { return null; }
-  @Override
-  public String getSolrConfigFile() { return null; }
+public class TestSort extends SolrTestCaseJ4 {
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    initCore("solrconfig.xml","schema-minimal.xml");
+  }
 
-  Random r = random;
+  final Random r = random;
 
   int ndocs = 77;
   int iter = 50;
@@ -57,6 +64,92 @@ public class TestSort extends AbstractSo
     }
   }
 
+  public void testRandomFieldNameSorts() throws Exception {
+    SolrQueryRequest req = lrf.makeRequest("q", "*:*");
+
+    final int iters = atLeast(5000);
+    int numberOfOddities = 0;
+
+    for (int i = 0; i < iters; i++) {
+      final StringBuilder input = new StringBuilder();
+      final String[] names = new String[_TestUtil.nextInt(r,1,10)];
+      final boolean[] reverse = new boolean[names.length];
+      for (int j = 0; j < names.length; j++) {
+        names[j] = _TestUtil.randomRealisticUnicodeString(r, 1, 20);
+
+        // reduce the likelyhood that the random str is a valid query or func 
+        names[j] = names[j].replaceFirst("\\{","\\{\\{");
+        names[j] = names[j].replaceFirst("\\(","\\(\\(");
+        names[j] = names[j].replaceFirst("(\\\"|\\')","$1$1");
+        names[j] = names[j].replaceFirst("(\\d)","$1x");
+
+        // eliminate pesky problem chars
+        names[j] = names[j].replaceAll("\\p{Cntrl}|\\p{javaWhitespace}","");
+
+        if (0 == names[j].length()) {
+          numberOfOddities++;
+          // screw it, i'm taking my toys and going home
+          names[j] = "last_ditch_i_give_up";
+        }
+        reverse[j] = r.nextBoolean();
+
+        input.append(r.nextBoolean() ? " " : "");
+        input.append(names[j]);
+        input.append(" ");
+        input.append(reverse[j] ? "desc," : "asc,");
+      }
+      input.deleteCharAt(input.length()-1);
+      SortField[] sorts = null;
+      try {
+        sorts = QueryParsing.parseSort(input.toString(), req).getSort();
+      } catch (RuntimeException e) {
+        throw new RuntimeException("Failed to parse sort: " + input, e);
+      }
+      assertEquals("parsed sorts had unexpected size", 
+                   names.length, sorts.length);
+      for (int j = 0; j < names.length; j++) {
+        assertEquals("sorts["+j+"] had unexpected reverse: " + input,
+                     reverse[j], sorts[j].getReverse());
+
+        final Type type = sorts[j].getType();
+
+        if (Type.SCORE.equals(type)) {
+          numberOfOddities++;
+          assertEquals("sorts["+j+"] is (unexpectedly) type score : " + input,
+                       "score", names[j]);
+        } else if (Type.DOC.equals(type)) {
+          numberOfOddities++;
+          assertEquals("sorts["+j+"] is (unexpectedly) type doc : " + input,
+                       "_docid_", names[j]);
+        } else if (Type.CUSTOM.equals(type) || Type.REWRITEABLE.equals(type)) {
+          numberOfOddities++;
+
+          // our orig string better be parsable as a func/query
+          QParser qp = 
+            QParser.getParser(names[j], FunctionQParserPlugin.NAME, req);
+          try { 
+            Query q = qp.getQuery();
+            assertNotNull("sorts["+j+"] had type " + type + 
+                          " but parsed to null func/query: " + input, q);
+          } catch (Exception e) {
+            assertNull("sorts["+j+"] had type " + type + 
+                       " but errored parsing as func/query: " + input, e);
+          }
+        } else {
+          assertEquals("sorts["+j+"] had unexpected field: " + input,
+                       names[j], sorts[j].getField());
+        }
+      }
+    }
+
+    assertTrue("Over 0.2% oddities in test: " +
+               numberOfOddities + "/" + iters +
+               " have func/query parsing semenatics gotten broader?",
+               numberOfOddities < 0.002 * iters);
+  }
+
+
+
   public void testSort() throws Exception {
     Directory dir = new RAMDirectory();
     Field f = new Field("f","0", Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS);

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java?rev=1152653&r1=1152652&r2=1152653&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/search/function/TestFunctionQuery.java Sun Jul 31 22:08:43 2011
@@ -434,9 +434,15 @@ public class TestFunctionQuery extends S
 
   @Test
   public void testSortByFunc() throws Exception {
-    assertU(adoc("id", "1", "const_s", "xx", "x_i", "100", "1_s", "a"));
-    assertU(adoc("id", "2", "const_s", "xx", "x_i", "300", "1_s", "c"));
-    assertU(adoc("id", "3", "const_s", "xx", "x_i", "200", "1_s", "b"));
+    assertU(adoc("id",    "1",   "const_s", "xx", 
+                 "x_i",   "100", "1_s", "a",
+                 "x:x_i", "100", "1-1_s", "a"));
+    assertU(adoc("id",    "2",   "const_s", "xx", 
+                 "x_i",   "300", "1_s", "c",
+                 "x:x_i", "300", "1-1_s", "c"));
+    assertU(adoc("id",    "3",   "const_s", "xx", 
+                 "x_i",   "200", "1_s", "b",
+                 "x:x_i", "200", "1-1_s", "b"));
     assertU(commit());
 
     String desc = "/response/docs==[{'x_i':300},{'x_i':200},{'x_i':100}]";
@@ -494,6 +500,12 @@ public class TestFunctionQuery extends S
     assertJQ(req("q",q,  "fl","x_i", "sort", "1_s asc")
              ,asc
     );
+    assertJQ(req("q",q,  "fl","x_i", "sort", "x:x_i desc")
+             ,desc
+    );
+    assertJQ(req("q",q,  "fl","x_i", "sort", "1-1_s asc")
+             ,asc
+    );
 
     // really ugly field name that isn't a java Id, and can't be 
     // parsed as a func, but sorted fine in Solr 1.4