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 2013/09/05 11:14:10 UTC

svn commit: r1520258 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/api/ oak-core/src/main/java/org/apache/jackrabbit/oak/query/ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/ oak-jcr/src/test/java/org/apache/j...

Author: thomasm
Date: Thu Sep  5 09:14:09 2013
New Revision: 1520258

URL: http://svn.apache.org/r1520258
Log:
OAK-995 XPath: allow using RowIterator Row.getPath() for all queries

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Result.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ResultRow.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultRowImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/RowImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Result.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Result.java?rev=1520258&r1=1520257&r2=1520258&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Result.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Result.java Thu Sep  5 09:14:09 2013
@@ -27,6 +27,15 @@ public interface Result {
      * @return the column names
      */
     String[] getColumnNames();
+    
+    /**
+     * Get the distinct selector names of all columns. The list is ordered as
+     * selectors appear in the result. For columns without selector, an empty
+     * entry (null) is used.
+     * 
+     * @return the distinct selector names
+     */
+    String[] getColumnSelectorNames();
 
     /**
      * Get the list of selector names.

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ResultRow.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ResultRow.java?rev=1520258&r1=1520257&r2=1520258&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ResultRow.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/ResultRow.java Thu Sep  5 09:14:09 2013
@@ -21,13 +21,39 @@ package org.apache.jackrabbit.oak.api;
  * A query result row.
  */
 public interface ResultRow {
-
+    
+    /**
+     * The path, assuming there is only one selector.
+     * 
+     * @return the path
+     * @throws IllegalArgumentException if there are multiple selectors
+     */
     String getPath();
 
+    /**
+     * The path for the given selector name.
+     * 
+     * @param selectorName the selector name (null if there is only one selector)
+     * @return the path
+     * @throws IllegalArgumentException if the selector was not found,
+     *      or if there are multiple selectors but the passed selectorName is null
+     */
     String getPath(String selectorName);
 
+    /**
+     * The property value.
+     * 
+     * @param columnName the column name
+     * @return the value
+     * @throws IllegalArgumentException if the column was not found
+     */
     PropertyValue getValue(String columnName);
 
+    /**
+     * Get the list of values.
+     * 
+     * @return the values
+     */
     PropertyValue[] getValues();
 
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java?rev=1520258&r1=1520257&r2=1520258&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java Thu Sep  5 09:14:09 2013
@@ -16,11 +16,13 @@
  */
 package org.apache.jackrabbit.oak.query;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 
 import org.apache.jackrabbit.oak.api.Result;
 import org.apache.jackrabbit.oak.api.ResultRow;
 import org.apache.jackrabbit.oak.query.ast.ColumnImpl;
+import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
 
 /**
  * A query result.
@@ -42,6 +44,19 @@ public class ResultImpl implements Resul
         }
         return names;
     }
+    
+    @Override
+    public String[] getColumnSelectorNames() {
+        ArrayList<String> list = new ArrayList<String>();
+        for (ColumnImpl c : query.getColumns()) {
+            SelectorImpl selector = c.getSelector();
+            String name = selector == null ? null : selector.getSelectorName();
+            if (!list.contains(name)) {
+                list.add(name);
+            }
+        }
+        return list.toArray(new String[list.size()]);
+    }
 
     @Override
     public String[] getSelectorNames() {

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=1520258&r1=1520257&r2=1520258&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 Sep  5 09:14:09 2013
@@ -51,16 +51,19 @@ public class ResultRowImpl implements Re
 
     @Override
     public String getPath() {
-        if (paths.length > 1) {
-            throw new IllegalArgumentException("More than one selector");
-        } else if (paths.length == 0) {
-            throw new IllegalArgumentException("This query does not have a selector");
-        }
-        return paths[0];
+        return getPath(null);
     }
 
     @Override
     public String getPath(String selectorName) {
+        if (selectorName == null) {
+            if (paths.length > 1) {
+                throw new IllegalArgumentException("More than one selector");
+            } else if (paths.length == 0) {
+                throw new IllegalArgumentException("This query does not have a selector");
+            }
+            return paths[0];
+        }
         int index = query.getSelectorIndex(selectorName);
         if (paths == null || index >= paths.length) {
             return null;

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java?rev=1520258&r1=1520257&r2=1520258&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java Thu Sep  5 09:14:09 2013
@@ -18,6 +18,7 @@
  */
 package org.apache.jackrabbit.oak.jcr.query;
 
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 
@@ -47,7 +48,7 @@ import org.slf4j.LoggerFactory;
  */
 public class QueryResultImpl implements QueryResult {
 
-    private static final Logger log = LoggerFactory.getLogger(QueryResultImpl.class);
+    static final Logger LOG = LoggerFactory.getLogger(QueryResultImpl.class);
 
     /**
      * The minimum number of rows / nodes to pre-fetch.
@@ -107,9 +108,16 @@ public class QueryResultImpl implements 
         Iterator<RowImpl> rowIterator = new Iterator<RowImpl>() {
 
             private final Iterator<? extends ResultRow> it = result.getRows().iterator();
+            private final String pathSelector;
             private RowImpl current;
 
             {
+                String[] columnSelectorNames = result.getColumnSelectorNames();
+                if (columnSelectorNames.length == 1) {
+                    pathSelector = columnSelectorNames[0];
+                } else {
+                    pathSelector = null;
+                }
                 fetch();
             }
 
@@ -117,13 +125,18 @@ public class QueryResultImpl implements 
                 current = null;
                 while (it.hasNext()) {
                     ResultRow r = it.next();
+                    boolean include = true;
                     for (String s : getSelectorNames()) {
                         String path = r.getPath(s);
-                        if (includeRow(path)) {
-                            current = new RowImpl(QueryResultImpl.this, r);
-                            return;
+                        if (!includeRow(path)) {
+                            include = false;
+                            break;
                         }
                     }
+                    if (include) {
+                        current = new RowImpl(QueryResultImpl.this, r, pathSelector);
+                        return;
+                    }
                 }
             }
 
@@ -178,16 +191,16 @@ public class QueryResultImpl implements 
 
     @Override
     public NodeIterator getNodes() throws RepositoryException {
-        String[] selectorNames = getSelectorNames();
-        if (getSelectorNames().length > 1) {
-            // TODO verify using the last selector is allowed according to the specification,
-            // otherwise just allow it when using XPath queries, or make XPath queries
-            // look like they only contain one selector
-            // throw new RepositoryException("Query contains more than one selector: " +
-            //        Arrays.toString(getSelectorNames()));
+        String[] columnSelectorNames = result.getColumnSelectorNames();
+        if (columnSelectorNames.length != 1) {
+            throw new RepositoryException("Query contains more than one selector: " +
+                    Arrays.toString(columnSelectorNames));
+        }
+        final String selectorName = columnSelectorNames[0];
+        if (selectorName == null) {
+            throw new RepositoryException("Query does not contain a selector: " +
+                    Arrays.toString(columnSelectorNames));
         }
-        // use the last selector
-        final String selectorName = selectorNames[selectorNames.length - 1];
         Iterator<NodeImpl<? extends NodeDelegate>> nodeIterator = new Iterator<NodeImpl<? extends NodeDelegate>>() {
 
             private final Iterator<? extends ResultRow> it = result.getRows().iterator();
@@ -207,7 +220,7 @@ public class QueryResultImpl implements 
                             current = getNode(getLocalPath(path));
                             break;
                         } catch (RepositoryException e) {
-                            log.warn("Unable to fetch result node for path " + path, e);
+                            LOG.warn("Unable to fetch result node for path " + path, e);
                         }
                     }
                 }

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/RowImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/RowImpl.java?rev=1520258&r1=1520257&r2=1520258&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/RowImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/RowImpl.java Thu Sep  5 09:14:09 2013
@@ -33,10 +33,12 @@ public class RowImpl implements Row {
 
     private final QueryResultImpl result;
     private final ResultRow row;
+    private final String pathSelector;
 
-    public RowImpl(QueryResultImpl result, ResultRow row) {
+    public RowImpl(QueryResultImpl result, ResultRow row, String pathSelector) {
         this.result = result;
         this.row = row;
+        this.pathSelector = pathSelector;
     }
 
     @Override
@@ -52,7 +54,7 @@ public class RowImpl implements Row {
     @Override
     public String getPath() throws RepositoryException {
         try {
-            return result.getLocalPath(row.getPath());
+            return result.getLocalPath(row.getPath(pathSelector));
         } catch (IllegalArgumentException e) {
             throw new RepositoryException(e);
         }

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java?rev=1520258&r1=1520257&r2=1520258&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java Thu Sep  5 09:14:09 2013
@@ -56,7 +56,30 @@ public class QueryTest extends AbstractR
     public QueryTest(NodeStoreFixture fixture) {
         super(fixture);
     }
-    
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void or() throws RepositoryException {
+        Session session = getAdminSession();
+        Node hello = session.getRootNode().addNode("hello");
+        hello.setProperty("x", 1);
+        Node world = hello.addNode("world");
+        world.setProperty("x", 2);
+        session.save();
+        QueryManager qm = session.getWorkspace().getQueryManager();
+        Query q;
+        
+        q = qm.createQuery("select a.[jcr:path] from [nt:base] as a " + 
+                    "inner join [nt:base] as b " +
+                    "on ischildnode(a, b) " + 
+                    "where a.x = 1 or a.x = 2 or b.x = 3 or b.x = 4", Query.JCR_SQL2);
+        assertEquals("/hello", getPaths(q));
+
+        q = qm.createQuery("//hello[@x=1]/*[@x=2]", Query.XPATH);
+        assertEquals("/hello/world", getPaths(q));
+
+    }
+
     @SuppressWarnings("deprecation")
     @Test
     public void encodedPath() throws RepositoryException {
@@ -74,7 +97,7 @@ public class QueryTest extends AbstractR
         
         q = qm.createQuery("//element(hel_x006c_o, nt:base)", Query.XPATH);
         assertEquals("/hello", getPaths(q));
-        
+
     }
     
     private static String getPaths(Query q) throws RepositoryException {