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 2012/05/31 16:43:30 UTC

svn commit: r1344752 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/api/ main/java/org/apache/jackrabbit/oak/query/ main/java/org/apache/jackrabbit/oak/query/ast/ test/java/org/apache/jackrabbit/oak/query/ test/resources/o...

Author: thomasm
Date: Thu May 31 14:43:30 2012
New Revision: 1344752

URL: http://svn.apache.org/viewvc?rev=1344752&view=rev
Log:
OAK-28 Query implementation

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryTest.java
    jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryXpathTest.txt

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java Thu May 31 14:43:30 2012
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.api;
 import java.text.ParseException;
 import java.util.List;
 import java.util.Map;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 
 /**
  * The query engine allows to parse and execute queries.
@@ -53,12 +54,14 @@ public interface QueryEngine {
      * @param limit the maximum result set size
      * @param offset the number of rows to skip
      * @param bindings the bind variable value bindings
+     * @param namePathMapper the name and path mapper to use
      * @return the result
      * @throws ParseException if the statement could not be parsed
      * @throws IllegalArgumentException if there was an error executing the query
      */
     Result executeQuery(String statement, String language, ContentSession session,
-            long limit, long offset, Map<String, CoreValue> bindings) throws ParseException;
+            long limit, long offset, Map<String, CoreValue> bindings,
+            NamePathMapper namePathMapper) throws ParseException;
 
     // TODO pass namespace mapping
     // TODO pass node type information (select * from [xyz] is supposed to return at least the mandatory columns for xyz)

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java Thu May 31 14:43:30 2012
@@ -23,6 +23,7 @@ import org.apache.jackrabbit.mk.api.Micr
 import org.apache.jackrabbit.oak.api.ContentSession;
 import org.apache.jackrabbit.oak.api.CoreValue;
 import org.apache.jackrabbit.oak.api.CoreValueFactory;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.query.ast.AstVisitorBase;
 import org.apache.jackrabbit.oak.query.ast.BindVariableValueImpl;
 import org.apache.jackrabbit.oak.query.ast.ChildNodeImpl;
@@ -73,6 +74,7 @@ public class Query {
     private boolean prepared;
     private final CoreValueFactory valueFactory;
     private ContentSession session;
+    private NamePathMapper namePathMapper;
 
     Query(SourceImpl source, ConstraintImpl constraint, OrderingImpl[] orderings,
           ColumnImpl[] columns, CoreValueFactory valueFactory) {
@@ -496,4 +498,12 @@ public class Query {
         this.session = session;
     }
 
+    public void setNamePathMapper(NamePathMapper namePathMapper) {
+        this.namePathMapper = namePathMapper;
+    }
+
+    public NamePathMapper getNamePathMapper() {
+        return namePathMapper;
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java Thu May 31 14:43:30 2012
@@ -26,6 +26,7 @@ import org.apache.jackrabbit.oak.api.Con
 import org.apache.jackrabbit.oak.api.CoreValue;
 import org.apache.jackrabbit.oak.api.CoreValueFactory;
 import org.apache.jackrabbit.oak.api.QueryEngine;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.query.index.FilterImpl;
 import org.apache.jackrabbit.oak.query.index.TraversingIndex;
 import org.apache.jackrabbit.oak.spi.QueryIndex;
@@ -36,6 +37,7 @@ public class QueryEngineImpl implements 
 
     static final String SQL2 = "JCR-SQL2";
     private static final String XPATH = "xpath";
+    private static final String JQOM = "JCR-JQOM";
 
     private final MicroKernel mk;
     private final CoreValueFactory vf;
@@ -51,7 +53,7 @@ public class QueryEngineImpl implements 
 
     @Override
     public List<String> getSupportedQueryLanguages() {
-        return Arrays.asList(SQL2, XPATH);
+        return Arrays.asList(SQL2, XPATH, JQOM);
     }
 
     /**
@@ -70,7 +72,7 @@ public class QueryEngineImpl implements 
 
     private Query parseQuery(String statement, String language) throws ParseException {
         Query q;
-        if (SQL2.equals(language)) {
+        if (SQL2.equals(language) || JQOM.equals(language)) {
             q = parserSQL2.parse(statement);
         } else if (XPATH.equals(language)) {
             XPathToSQL2Converter converter = new XPathToSQL2Converter();
@@ -84,9 +86,11 @@ public class QueryEngineImpl implements 
 
     @Override
     public ResultImpl executeQuery(String statement, String language, ContentSession session,
-            long limit, long offset, Map<String, CoreValue> bindings) throws ParseException {
+            long limit, long offset, Map<String, CoreValue> bindings,
+            NamePathMapper namePathMapper) throws ParseException {
         Query q = parseQuery(statement, language);
         q.setSession(session);
+        q.setNamePathMapper(namePathMapper);
         q.setLimit(limit);
         q.setOffset(offset);
         q.setMicroKernel(mk);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java Thu May 31 14:43:30 2012
@@ -169,8 +169,8 @@ public class XPathToSQL2Converter {
                 f.params.add(Literal.newString(path));
                 condition = add(condition, f);
             } else {
-                // TODO jcr:path is only a pseudo-property
-                Condition c = new Condition(new Property("jcr:path"), "=", Literal.newString(path));
+                Function c = new Function("issamenode");
+                c.params.add(Literal.newString(path));
                 condition = add(condition, c);
             }
             if (nodeName != null) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java Thu May 31 14:43:30 2012
@@ -24,6 +24,7 @@ import org.apache.jackrabbit.oak.api.Cor
 import org.apache.jackrabbit.oak.api.CoreValueFactory;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.kernel.CoreValueMapper;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.query.Query;
 
 import javax.jcr.PropertyType;
@@ -125,5 +126,18 @@ abstract class AstElement {
         return true;
     }
 
+    protected String getOakPath(String jcrPath) {
+        NamePathMapper m = query.getNamePathMapper();
+        if (m == null) {
+            // to simplify testing, a getNamePathMapper isn't required
+            return jcrPath;
+        }
+        String p = m.getOakPath(jcrPath);
+        if (p == null) {
+            throw new IllegalArgumentException("Not a valid JCR path: " + jcrPath);
+        }
+        return p;
+    }
+
 }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java Thu May 31 14:43:30 2012
@@ -64,7 +64,7 @@ public class ComparisonImpl extends Cons
         if (v1.getType() != v2.getType()) {
             // "the value of operand2 is converted to the
             // property type of the value of operand1"
-            v2 = convert(query.getValueFactory(), v2, v1.getType());
+            v2 = convert(v2, v1.getType());
         }
         switch (operator) {
         case EQUAL:
@@ -85,7 +85,7 @@ public class ComparisonImpl extends Cons
         throw new IllegalArgumentException("Unknown operator: " + operator);
     }
 
-    private static CoreValue convert(CoreValueFactory vf, CoreValue v, int targetType) {
+    private CoreValue convert(CoreValue v, int targetType) {
         // TODO support full set of conversion features defined in the JCR spec
         // at 3.6.4 Property Type Conversion
         // re-use existing code if possible
@@ -93,6 +93,7 @@ public class ComparisonImpl extends Cons
         if (sourceType == targetType) {
             return v;
         }
+        CoreValueFactory vf = query.getValueFactory();
         switch (sourceType) {
         case PropertyType.STRING:
             switch(targetType) {
@@ -122,7 +123,7 @@ public class ComparisonImpl extends Cons
         case PropertyType.DECIMAL:
             return vf.createValue(v.getString(), PropertyType.DECIMAL);
         case PropertyType.NAME:
-            return vf.createValue(v.getString(), PropertyType.NAME);
+            return vf.createValue(getOakPath(v.getString()), PropertyType.NAME);
         case PropertyType.PATH:
             return vf.createValue(v.getString(), PropertyType.PATH);
         case PropertyType.REFERENCE:

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java Thu May 31 14:43:30 2012
@@ -18,6 +18,7 @@
  */
 package org.apache.jackrabbit.oak.query.ast;
 
+import javax.jcr.PropertyType;
 import org.apache.jackrabbit.oak.api.CoreValue;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.query.index.FilterImpl;
@@ -55,7 +56,11 @@ public class NodeNameImpl extends Dynami
     @Override
     public CoreValue currentValue() {
         String name = PathUtils.getName(selector.currentPath());
-        return query.getValueFactory().createValue(name);
+        CoreValue v = query.getValueFactory().createValue(name);
+        String path = v.getString();
+        // normalize paths (./name > name)
+        path = getOakPath(path);
+        return query.getValueFactory().createValue(path, PropertyType.NAME);
     }
 
     @Override
@@ -64,10 +69,11 @@ public class NodeNameImpl extends Dynami
             throw new IllegalArgumentException("Invalid name value: " + v.toString());
         }
         String path = v.getString();
+        // normalize paths (./name > name)
+        path = getOakPath(path);
         if (PathUtils.isAbsolute(path)) {
             throw new IllegalArgumentException("NAME() comparison with absolute path are not allowed: " + path);
         }
-        // TODO normalize paths (./name > name)
         if (PathUtils.getDepth(path) > 1) {
             throw new IllegalArgumentException("NAME() comparison with relative path are not allowed: " + path);
         }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java Thu May 31 14:43:30 2012
@@ -43,6 +43,7 @@ public class SameNodeImpl extends Constr
     @Override
     public boolean evaluate() {
         String p = getAbsolutePath(path);
+        // TODO normalize paths
         return selector.currentPath().equals(p);
     }
 
@@ -69,6 +70,7 @@ public class SameNodeImpl extends Constr
             String p = getAbsolutePath(path);
             f.restrictPath(p, Filter.PathRestriction.EXACT);
         }
+        // TODO validate absolute path
     }
 
 }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryTest.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryTest.java Thu May 31 14:43:30 2012
@@ -191,7 +191,7 @@ public class QueryTest extends AbstractQ
     }
 
     private Result executeQuery(String statement, HashMap<String, CoreValue> sv) throws ParseException {
-        return qe.executeQuery(statement, QueryEngineImpl.SQL2, session, Long.MAX_VALUE, 0, sv);
+        return qe.executeQuery(statement, QueryEngineImpl.SQL2, session, Long.MAX_VALUE, 0, sv, null);
     }
 
 }

Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryXpathTest.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryXpathTest.txt?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryXpathTest.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryXpathTest.txt Thu May 31 14:43:30 2012
@@ -19,7 +19,7 @@
 # * use ascii character only
 
 xpath /jcr:root/testdata/node[@jcr:primaryType]
-select [jcr:path], [jcr:score], * from [nt:base] where ([jcr:primaryType] is not null) and ([jcr:path] = '/testdata/node')
+select [jcr:path], [jcr:score], * from [nt:base] where ([jcr:primaryType] is not null) and issamenode('/testdata/node')
 
 xpath //testroot/*[@jcr:primaryType='nt:unstructured'] order by @prop2, @prop1
 invalid: Query: //testroot/*(*)[@jcr:primaryType='nt:unstructured'] order by @prop2, @prop1; expected: non-path condition
@@ -31,10 +31,10 @@ xpath /jcr:root/test//text()
 select [jcr:path], [jcr:score], * from [nt:base] where isdescendantnode('/test') and (name() = 'jcr:xmltext')
 
 xpath /jcr:root/test/jcr:xmltext
-select [jcr:path], [jcr:score], * from [nt:base] where [jcr:path] = '/test/jcr:xmltext'
+select [jcr:path], [jcr:score], * from [nt:base] where issamenode('/test/jcr:xmltext')
 
 xpath /jcr:root/test/text()
-select [jcr:path], [jcr:score], * from [nt:base] where [jcr:path] = '/test/jcr:xmltext'
+select [jcr:path], [jcr:score], * from [nt:base] where issamenode('/test/jcr:xmltext')
 
 xpath //*[@*='x']
 select [jcr:path], [jcr:score], * from [nt:base] where [*] = 'x'
@@ -87,6 +87,9 @@ select [jcr:path], [jcr:score], * from [
 xpath /jcr:root/content/campaigns//element(*, PageContent)[(@sling:resourceType = 'teaser' or @sling:resourceType = 'newsletter' or @teaserPageType = 'newsletter' or @teaserPageType = 'tweet') and ((@onTime < xs:dateTime('2012-04-01T00:00:00.000+02:00')) or not(@onTime)) and ((@offTime >= xs:dateTime('2012-02-26T00:00:00.000+01:00')) or not(@offTime))] order by @onTime
 select [jcr:path], [jcr:score], * from [PageContent] where (((((([sling:resourceType] = 'teaser') or ([sling:resourceType] = 'newsletter')) or ([teaserPageType] = 'newsletter')) or ([teaserPageType] = 'tweet')) and (([onTime] < cast('2012-04-01T00:00:00.000+02:00' as date)) or ([onTime] is null))) and (([offTime] >= cast('2012-02-26T00:00:00.000+01:00' as date)) or ([offTime] is null))) and isdescendantnode('/content/campaigns') order by [onTime]
 
+xpath /jcr:root/content/dam//element(*, asset)
+select [jcr:path], [jcr:score], * from [asset] where isdescendantnode('/content/dam')
+
 xpath /jcr:root/content/dam//element(*, asset)[jcr:content/metadata/@dam:scene]
 select [jcr:path], [jcr:score], * from [asset] where ([jcr:content/metadata/dam:scene] is not null) and isdescendantnode('/content/dam')
 
@@ -129,7 +132,7 @@ xpath /jcr:root/nodes//element(*, my:typ
 select [jcr:path], [jcr:score], * from [my:type] where isdescendantnode('/nodes')
 
 xpath /jcr:root/some/element(nodes, my:type)
-select [jcr:path], [jcr:score], * from [my:type] where [jcr:path] = '/some/nodes'
+select [jcr:path], [jcr:score], * from [my:type] where issamenode('/some/nodes')
 
 xpath /jcr:root/some/nodes/element(*, my:type)
 select [jcr:path], [jcr:score], * from [my:type] where ischildnode('/some/nodes')