You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2008/02/22 13:46:26 UTC

svn commit: r630183 - in /jackrabbit/branches/1.4/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/query/lucene/WildcardTermEnum.java test/java/org/apache/jackrabbit/core/query/UpperLowerCaseQueryTest.java

Author: mreutegg
Date: Fri Feb 22 04:46:23 2008
New Revision: 630183

URL: http://svn.apache.org/viewvc?rev=630183&view=rev
Log:
JCR-1408: Invalid query results when using jcr:like with a case transform function and a pattern not starting with a wildcard

Modified:
    jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardTermEnum.java
    jackrabbit/branches/1.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/UpperLowerCaseQueryTest.java

Modified: jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardTermEnum.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardTermEnum.java?rev=630183&r1=630182&r2=630183&view=diff
==============================================================================
--- jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardTermEnum.java (original)
+++ jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/WildcardTermEnum.java Fri Feb 22 04:46:23 2008
@@ -93,15 +93,22 @@
         this.transform = transform;
 
         int idx = 0;
-        while (idx < pattern.length()
-                && Character.isLetterOrDigit(pattern.charAt(idx))) {
-            idx++;
-        }
 
-        if (propName == null) {
-            prefix = pattern.substring(0, idx);
+        if (transform == TRANSFORM_NONE) {
+            // optimize the term comparison by removing the prefix from the pattern
+            // and therefore use a more precise range scan
+            while (idx < pattern.length()
+                    && Character.isLetterOrDigit(pattern.charAt(idx))) {
+                idx++;
+            }
+
+            if (propName == null) {
+                prefix = pattern.substring(0, idx);
+            } else {
+                prefix = FieldNames.createNamedValue(propName, pattern.substring(0, idx));
+            }
         } else {
-            prefix = FieldNames.createNamedValue(propName, pattern.substring(0, idx));
+            prefix = FieldNames.createNamedValue(propName, "");
         }
 
         // initialize with prefix as dummy value
@@ -271,19 +278,14 @@
                                 new Term(field, prefix), new Term(field, limit)));
                     }
 
-                    String prefix = FieldNames.createNamedValue(propName, patternPrefix);
-                    // initialize with prefix as dummy value
-                    OffsetCharSequence input = new OffsetCharSequence(prefix.length(), prefix, transform);
-                    Matcher matcher = createRegexp(pattern.substring(idx)).matcher(input);
-
-                    // do range scans with patter matcher
+                    // do range scans with pattern matcher
                     for (Iterator it = rangeScans.iterator(); it.hasNext(); ) {
                         RangeScan scan = (RangeScan) it.next();
                         do {
                             Term t = scan.term();
                             if (t != null) {
                                 input.setBase(t.text());
-                                if (matcher.reset().matches()) {
+                                if (WildcardTermEnum.this.pattern.reset().matches()) {
                                     orderedTerms.put(t, new Integer(scan.docFreq()));
                                 }
                             }

Modified: jackrabbit/branches/1.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/UpperLowerCaseQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/UpperLowerCaseQueryTest.java?rev=630183&r1=630182&r2=630183&view=diff
==============================================================================
--- jackrabbit/branches/1.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/UpperLowerCaseQueryTest.java (original)
+++ jackrabbit/branches/1.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/UpperLowerCaseQueryTest.java Fri Feb 22 04:46:23 2008
@@ -22,6 +22,7 @@
 import javax.jcr.query.InvalidQueryException;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.Random;
 
 /**
  * <code>UpperLowerCaseQueryTest</code> tests the functions fn:lower-case() and
@@ -136,10 +137,39 @@
                 "like",
                 "_oo",
                 new boolean[]{true, true, true, true});
-        check(new String[]{"foo", "Foa", "fOO", "FO", "foRm"},
+        check(new String[]{"foo", "Foa", "fOO", "FO", "foRm", "fPo", "fno", "FPo", "Fno"},
                 "like",
                 "fo%",
-                new boolean[]{true, true, true, true, true});
+                new boolean[]{true, true, true, true, true, false, false, false, false});
+    }
+
+    public void testLikeComparisonRandom() throws RepositoryException {
+        String abcd = "abcd";
+        Random random = new Random();
+        for (int i = 0; i < 50; i++) {
+            String pattern = "";
+            pattern += getRandomChar(abcd, random);
+            pattern += getRandomChar(abcd, random);
+
+            // create 10 random values with 4 characters
+            String[] values = new String[10];
+            boolean[] matches = new boolean[10];
+            for (int n = 0; n < 10; n++) {
+                // at least the first character always matches
+                String value = String.valueOf(pattern.charAt(0));
+                for (int r = 1; r < 4; r++) {
+                    char c = getRandomChar(abcd, random);
+                    if (random.nextBoolean()) {
+                        c = Character.toUpperCase(c);
+                    }
+                    value += c;
+                }
+                matches[n] = value.toLowerCase().startsWith(pattern);
+                values[n] = value;
+            }
+            pattern += "%";
+            check(values, "like", pattern, matches);
+        }
     }
 
     public void testRangeWithEmptyString() throws RepositoryException {
@@ -191,6 +221,23 @@
         if (values.length != matches.length) {
             throw new IllegalArgumentException("values and matches must have same length");
         }
+        // create log message
+        StringBuffer logMsg = new StringBuffer();
+        logMsg.append("queryTerm: ").append(queryTerm);
+        logMsg.append(" values: ");
+        String separator = "";
+        for (int i = 0; i < values.length; i++) {
+            logMsg.append(separator);
+            separator = ", ";
+            if (matches[i]) {
+                logMsg.append("+");
+            } else {
+                logMsg.append("-");
+            }
+            logMsg.append(values[i]);
+        }
+        log.write(logMsg.toString());
+        log.flush();
         for (NodeIterator it = testRootNode.getNodes(); it.hasNext();) {
             it.nextNode().remove();
         }
@@ -241,5 +288,9 @@
                 testRoot + "/%' and UPPER(" + propertyName1 + ") " +
                 sqlOperation + " '" + queryTerm.toUpperCase() + "'";
         executeSQLQuery(sql, nodes);
+    }
+
+    private char getRandomChar(String pool, Random random) {
+        return pool.charAt(random.nextInt(pool.length()));
     }
 }