You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2014/04/10 11:11:19 UTC

svn commit: r1586247 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/query/ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/

Author: thomasm
Date: Thu Apr 10 09:11:18 2014
New Revision: 1586247

URL: http://svn.apache.org/r1586247
Log:
OAK-1689 XPath and union queries with "or" can return the same node multiple times

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultRowImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ColumnImpl.java
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryFulltextTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java?rev=1586247&r1=1586246&r2=1586247&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java Thu Apr 10 09:11:18 2014
@@ -118,6 +118,13 @@ public class QueryImpl implements Query 
 
     private OrderingImpl[] orderings;
     private ColumnImpl[] columns;
+    
+    /**
+     * The columns that make a row distinct. This is all columns
+     * except for "jcr:score".
+     */
+    private boolean[] distinctColumns;
+    
     private boolean explain, measure;
     private boolean distinct;
     private long limit = Long.MAX_VALUE;
@@ -347,6 +354,15 @@ public class QueryImpl implements Query 
         for (ColumnImpl column : columns) {
             column.bindSelector(source);
         }
+        distinctColumns = new boolean[columns.length];
+        for (int i = 0; i < columns.length; i++) {
+            ColumnImpl c = columns[i];
+            boolean distinct = true;
+            if (JCR_SCORE.equals(c.getPropertyName())) {
+                distinct = false;
+            }
+            distinctColumns[i] = distinct;
+        }
     }
 
     @Override
@@ -409,7 +425,7 @@ public class QueryImpl implements Query 
             ResultRowImpl r = new ResultRowImpl(this,
                     Tree.EMPTY_ARRAY,
                     new PropertyValue[] { PropertyValues.newString(plan)},
-                    null);
+                    null, null);
             return Arrays.asList(r).iterator();
         }
         if (LOG.isDebugEnabled()) {
@@ -474,7 +490,7 @@ public class QueryImpl implements Query 
                             PropertyValues.newString("query"),
                             PropertyValues.newLong(rowIt.getReadCount())
                         },
-                    null);
+                    null, null);
             list.add(r);
             for (SelectorImpl selector : selectors) {
                 r = new ResultRowImpl(this,
@@ -483,7 +499,7 @@ public class QueryImpl implements Query 
                                 PropertyValues.newString(selector.getSelectorName()),
                                 PropertyValues.newLong(selector.getScanCount()),
                             },
-                        null);
+                        null, null);
                 list.add(r);
             }
             it = list.iterator();
@@ -676,7 +692,7 @@ public class QueryImpl implements Query 
                 orderValues[i] = orderings[i].getOperand().currentProperty();
             }
         }
-        return new ResultRowImpl(this, trees, values, orderValues);
+        return new ResultRowImpl(this, trees, values, distinctColumns, orderValues);
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultRowImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultRowImpl.java?rev=1586247&r1=1586246&r2=1586247&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultRowImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultRowImpl.java Thu Apr 10 09:11:18 2014
@@ -35,13 +35,28 @@ public class ResultRowImpl implements Re
 
     private final Query query;
     private final Tree[] trees;
+    
+    /**
+     * The column values.
+     */
     private final PropertyValue[] values;
+    
+    /**
+     * Whether the value at the given index is used for comparing rows (used
+     * within hashCode and equals). If null, all columns are distinct.
+     */
+    private final boolean[] distinctValues;
+    
+    /**
+     * The values used for ordering.
+     */
     private final PropertyValue[] orderValues;
 
-    ResultRowImpl(Query query, Tree[] trees, PropertyValue[] values, PropertyValue[] orderValues) {
+    ResultRowImpl(Query query, Tree[] trees, PropertyValue[] values, boolean[] distinctValues, PropertyValue[] orderValues) {
         this.query = query;
         this.trees = trees;
         this.values = values;
+        this.distinctValues = distinctValues;
         this.orderValues = orderValues;
     }
     
@@ -137,7 +152,18 @@ public class ResultRowImpl implements Re
     public int hashCode() {
         int result = 1;
         result = 31 * result + Arrays.hashCode(getPaths());
-        result = 31 * result + Arrays.hashCode(values);
+        result = 31 * result + hashCodeOfValues();
+        return result;
+    }
+    
+    private int hashCodeOfValues() {
+        int result = 1;
+        for (int i = 0; i < values.length; i++) {
+            if (distinctValues == null || distinctValues[i]) {
+                PropertyValue v = values[i];
+                result = 31 * result + (v == null ? 0 : v.hashCode());
+            }
+        }
         return result;
     }
 
@@ -153,9 +179,20 @@ public class ResultRowImpl implements Re
         ResultRowImpl other = (ResultRowImpl) obj;
         if (!Arrays.equals(getPaths(), other.getPaths())) {
             return false;
-        } else if (!Arrays.equals(values, other.values)) {
+        } else if (!Arrays.equals(distinctValues, other.distinctValues)) {
             return false;
         }
+        // if distinctValues are equals, then the number of values
+        // is also equal
+        for (int i = 0; i < values.length; i++) {
+            if (distinctValues == null || distinctValues[i]) {
+                Object o1 = values[i];
+                Object o2 = other.values[i];
+                if (!(o1 == null ? o2 == null : o1.equals(o2))) {
+                    return false;
+                }
+            }
+        }
         return true;
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java?rev=1586247&r1=1586246&r2=1586247&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java Thu Apr 10 09:11:18 2014
@@ -223,7 +223,7 @@ public class UnionQueryImpl implements Q
             ResultRowImpl r = new ResultRowImpl(this,
                     Tree.EMPTY_ARRAY,
                     new PropertyValue[] { PropertyValues.newString(plan)},
-                    null);
+                    null, null);
             return Arrays.asList(r).iterator();
         }
         if (LOG.isDebugEnabled()) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ColumnImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ColumnImpl.java?rev=1586247&r1=1586246&r2=1586247&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ColumnImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ColumnImpl.java Thu Apr 10 09:11:18 2014
@@ -39,6 +39,10 @@ public class ColumnImpl extends AstEleme
     public String getColumnName() {
         return columnName;
     }
+    
+    public String getPropertyName() {
+        return propertyName;
+    }
 
     @Override
     boolean accept(AstVisitor v) {

Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryFulltextTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryFulltextTest.java?rev=1586247&r1=1586246&r2=1586247&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryFulltextTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryFulltextTest.java Thu Apr 10 09:11:18 2014
@@ -50,6 +50,20 @@ public class QueryFulltextTest extends A
         assertEquals("n, n", result);
     }
 
+    public void testScoreWithOr() throws Exception {
+        Session session = superuser;
+        QueryManager qm = session.getWorkspace().getQueryManager();
+        Node n1 = testRootNode.addNode("node1");
+        n1.setProperty("text", "hello");
+        n1.setProperty("id", "1");
+        session.save();
+
+        String xpath = "/jcr:root//*[jcr:contains(@text, 'hello') or @id = '1']";
+        Query q = qm.createQuery(xpath, "xpath");
+        String result = getResult(q.execute(), "jcr:path");
+        assertEquals("/testroot/node1", result);
+    }
+
     public void testFulltext() throws Exception {
         Session session = superuser;
         QueryManager qm = session.getWorkspace().getQueryManager();