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/05/28 18:37:52 UTC

svn commit: r1486997 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/query/ test/resources/org/apache/jackrabbit/oak/query/

Author: thomasm
Date: Tue May 28 16:37:51 2013
New Revision: 1486997

URL: http://svn.apache.org/r1486997
Log:
OAK-318 Excerpt support

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java
    jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql1.txt
    jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt
    jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java?rev=1486997&r1=1486996&r2=1486997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java Tue May 28 16:37:51 2013
@@ -728,7 +728,16 @@ public class SQL2Parser {
                 ColumnOrWildcard column = new ColumnOrWildcard();
                 if (readIf("*")) {
                     column.propertyName = null;
-                } else {
+                } else if (readIf("EXCERPT")) {
+                    column.propertyName = "rep:excerpt";
+                    read("(");
+                    if (!readIf(")")) {
+                        if (!readIf(".")) {
+                            column.selectorName = readName();
+                        }
+                        read(")");
+                    }
+                } else {                    
                     column.propertyName = readName();
                     if (readIf(".")) {
                         column.selectorName = column.propertyName;

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=1486997&r1=1486996&r2=1486997&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 Tue May 28 16:37:51 2013
@@ -187,32 +187,25 @@ public class XPathToSQL2Converter {
                     read(")");
                 }
             } else if (readIf("@")) {
+                rewindSelector();
                 Property p = readProperty();
                 columnList.add(p);
             } else if (readIf("rep:excerpt")) {
-                read("(");
-                if (!readIf(")")) {
-                    // only rep:excerpt(.) and rep:excerpt() are currently supported
-                    read(".");
-                    read(")");
-                }
+                rewindSelector();
+                readExcerpt();
                 Property p = new Property(currentSelector, "rep:excerpt");
                 columnList.add(p);
             } else if (readIf("(")) {
-                // special case: ".../(@prop)" is actually not a child node, 
-                // but the same node (selector) as before 
-                if (selectors.size() > 0) {
-                    currentSelector = selectors.remove(selectors.size() - 1);
-                    // prevent (join) conditions are added again
-                    currentSelector.isChild = false;
-                    currentSelector.isDescendant = false;
-                    currentSelector.path = "";
-                    currentSelector.nodeName = null;
-                }
+                rewindSelector();
                 do {
-                    read("@");
-                    Property p = readProperty();
-                    columnList.add(p);
+                    if (readIf("@")) {
+                        Property p = readProperty();
+                        columnList.add(p);
+                    } else if (readIf("rep:excerpt")) {
+                        readExcerpt();
+                        Property p = new Property(currentSelector, "rep:excerpt");
+                        columnList.add(p);
+                    }
                 } while (readIf("|"));
                 read(")");
             } else if (currentTokenType == IDENTIFIER) {
@@ -372,6 +365,23 @@ public class XPathToSQL2Converter {
         buff.append(" */");
         return buff.toString();
     }
+    
+    /**
+     * Switch back to the old selector when reading a property. This occurs
+     * after reading a "/", but then reading a property or a list of properties.
+     * For example ".../(@prop)" is actually not a child node, but the same node
+     * (selector) as before.
+     */
+    private void rewindSelector() {
+        if (selectors.size() > 0) {
+            currentSelector = selectors.remove(selectors.size() - 1);
+            // prevent (join) conditions are added again
+            currentSelector.isChild = false;
+            currentSelector.isDescendant = false;
+            currentSelector.path = "";
+            currentSelector.nodeName = null;
+        }
+    }
 
     private void nextSelector(boolean force) throws ParseException {
         boolean isFirstSelector = selectors.size() == 0;
@@ -705,6 +715,15 @@ public class XPathToSQL2Converter {
         }
         return new Property(currentSelector, readIdentifier());
     }
+    
+    private void readExcerpt() throws ParseException {
+        read("(");
+        if (!readIf(")")) {
+            // only rep:excerpt(.) and rep:excerpt() are currently supported
+            read(".");
+            read(")");
+        }
+    }
 
     private String readIdentifier() throws ParseException {
         if (currentTokenType != IDENTIFIER) {

Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql1.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql1.txt?rev=1486997&r1=1486996&r2=1486997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql1.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql1.txt Tue May 28 16:37:51 2013
@@ -27,6 +27,8 @@
 
 sql1 select prop1 from nt:unstructured where prop1 is not null order by prop1 asc
 
+sql1 select excerpt(.) from nt:resource where contains(., 'jackrabbit')
+
 sql1 select * from nt:base where jcr:path like '/testroot/%' and birth > timestamp '1976-01-01T00:00:00.000+01:00'
 
 sql1 select * from nt:base where jcr:path like '/testroot/%' and value like 'foo\_bar' escape '\'

Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt?rev=1486997&r1=1486996&r2=1486997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_index.txt Tue May 28 16:37:51 2013
@@ -25,6 +25,9 @@
 
 # property type (value prefix) index
 
+explain select excerpt(.) from [nt:resource] where contains(*, 'jackrabbit')
+[nt:resource] as [nt:resource] /* traverse "*" where contains([nt:resource].[*], cast('jackrabbit' as string)) */
+
 explain select * from [nt:base] where [jcr:uuid]=1 or [b]=2
 [nt:base] as [nt:base] /* traverse "*" */
 

Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt?rev=1486997&r1=1486996&r2=1486997&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt Tue May 28 16:37:51 2013
@@ -155,8 +155,14 @@ select [jcr:path], [jcr:score], * from [
 
 # TODO support rep:similar()? how?
 
+xpath2sql /jcr:root/testroot/*[jcr:contains(., 'jackrabbit')]/(@my:title|@my:x)
+select [jcr:path], [jcr:score], [my:title], [my:x] from [nt:base] as a where contains(*, 'jackrabbit') and ischildnode(a, '/testroot') /* xpath: /jcr:root/testroot/*[jcr:contains(., 'jackrabbit')]/(@my:title|@my:x) */
+
+xpath2sql /jcr:root/testroot/*[jcr:contains(., 'jackrabbit')]/@my:title
+select [jcr:path], [jcr:score], [my:title] from [nt:base] as a where contains(*, 'jackrabbit') and ischildnode(a, '/testroot') /* xpath: /jcr:root/testroot/*[jcr:contains(., 'jackrabbit')]/@my:title */
+
 xpath2sql /jcr:root/testroot/*[jcr:contains(., 'jackrabbit')]/rep:excerpt(.)
-select b.[jcr:path] as [jcr:path], b.[jcr:score] as [jcr:score], b.[rep:excerpt] as [rep:excerpt] from [nt:base] as a inner join [nt:base] as b on ischildnode(b, a) where contains(a.*, 'jackrabbit') and ischildnode(a, '/testroot') /* xpath: /jcr:root/testroot/*[jcr:contains(., 'jackrabbit')]/rep:excerpt(.) */
+select [jcr:path], [jcr:score], [rep:excerpt] from [nt:base] as a where contains(*, 'jackrabbit') and ischildnode(a, '/testroot') /* xpath: /jcr:root/testroot/*[jcr:contains(., 'jackrabbit')]/rep:excerpt(.) */
 
 xpath2sql //testroot/*[@jcr:primaryType='nt:unstructured' and fn:not(@mytext)]
 select b.[jcr:path] as [jcr:path], b.[jcr:score] as [jcr:score], b.* from [nt:base] as a inner join [nt:base] as b on ischildnode(b, a) where name(a) = 'testroot' and b.[jcr:primaryType] = 'nt:unstructured' and b.[mytext] is null /* xpath: //testroot/*[@jcr:primaryType='nt:unstructured' and fn:not(@mytext)] */
@@ -204,6 +210,9 @@ select b.[jcr:path] as [jcr:path], b.[jc
 xpath2sql //element(*,my:type)
 select [jcr:path], [jcr:score], * from [my:type] as a /* xpath: //element(*,my:type) */
 
+xpath2sql //element(*,my:type)/rep:excerpt(.)
+select [jcr:path], [jcr:score], [rep:excerpt] from [my:type] as a /* xpath: //element(*,my:type)/rep:excerpt(.) */
+
 xpath2sql //element(*,my:type)/@my:title
 select [jcr:path], [jcr:score], [my:title] from [my:type] as a /* xpath: //element(*,my:type)/@my:title */