jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From thom...@apache.org
Subject svn commit: r1383429 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/plugins/index/ main/java/org/apache/jackrabbit/oak/query/ test/java/org/apache/jackrabbit/oak/query/ test/resources/org/apache/jackrabbit/oak/query/
Date Tue, 11 Sep 2012 14:33:40 GMT
Author: thomasm
Date: Tue Sep 11 14:33:40 2012
New Revision: 1383429

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

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeLeaf.java
  (props changed)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeNode.java
  (props changed)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreePage.java
  (contents, props changed)
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/Indexer.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndex.java
  (props changed)
    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/XPathToSQL2Converter.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/sql2.txt
    jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/xpath.txt

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeLeaf.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreeNode.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreePage.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreePage.java?rev=1383429&r1=1383428&r2=1383429&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreePage.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreePage.java
Tue Sep 11 14:33:40 2012
@@ -21,7 +21,7 @@ import org.apache.jackrabbit.oak.commons
 /**
  * An index page.
  */
-abstract public class BTreePage implements PropertyIndexConstants {
+public abstract class BTreePage implements PropertyIndexConstants {
 
     protected final BTree tree;
     protected BTreeNode parent;

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/BTreePage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/Indexer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/Indexer.java?rev=1383429&r1=1383428&r2=1383429&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/Indexer.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/Indexer.java
Tue Sep 11 14:33:40 2012
@@ -310,7 +310,7 @@ public class Indexer implements Property
         }
     }
 
-    synchronized public void updateUntil(String toRevision) {
+    public synchronized void updateUntil(String toRevision) {
         if (DISABLED) {
             return;
         }
@@ -505,20 +505,20 @@ public class Indexer implements Property
             // actually not required, just to make sure
             if (PathUtils.getParentPath(path).equals(indexRootNode)) {
                 String name = PathUtils.getName(path);
-                if (name.startsWith(Indexer.TYPE_PREFIX)) {
-                    String prefix = name.substring(Indexer.TYPE_PREFIX.length());
+                if (name.startsWith(PropertyIndexConstants.TYPE_PREFIX)) {
+                    String prefix = name.substring(PropertyIndexConstants.TYPE_PREFIX.length());
                     if (remove) {
                         removePrefixIndex(prefix);
                     }
                     if (add) {
                         createPrefixIndex(prefix);
                     }
-                } else if (name.startsWith(Indexer.TYPE_PROPERTY)) {
-                    String property = name.substring(Indexer.TYPE_PROPERTY.length());
+                } else if (name.startsWith(PropertyIndexConstants.TYPE_PROPERTY)) {
+                    String property = name.substring(PropertyIndexConstants.TYPE_PROPERTY.length());
                     boolean unique = false;
-                    if (property.endsWith("," + Indexer.UNIQUE)) {
+                    if (property.endsWith("," + PropertyIndexConstants.UNIQUE)) {
                         unique = true;
-                        property = property.substring(0, property.length() - Indexer.UNIQUE.length()
- 1);
+                        property = property.substring(0, property.length() - PropertyIndexConstants.UNIQUE.length()
- 1);
                     }
                     if (remove) {
                         removePropertyIndex(property, unique);

Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/PropertyIndex.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=1383429&r1=1383428&r2=1383429&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
Tue Sep 11 14:33:40 2012
@@ -629,7 +629,8 @@ public class Query {
     public int getColumnIndex(String columnName) {
         for (int i = 0, size = columns.length; i < size; i++) {
             ColumnImpl c = columns[i];
-            if (c.getColumnName().equals(columnName)) {
+            String cn = c.getColumnName();
+            if (cn != null && cn.equals(columnName)) {
                 return i;
             }
         }

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=1383429&r1=1383428&r2=1383429&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 Sep 11 14:33:40 2012
@@ -58,40 +58,55 @@ public class XPathToSQL2Converter {
      * @throws ParseException if parsing fails
      */
     public String convert(String query) throws ParseException {
+        query = query.trim();
         boolean explain = query.startsWith("explain ");
         if (explain) {
-            query = query.substring("explain ".length());
+            query = query.substring("explain".length()).trim();
         }
         boolean measure = query.startsWith("measure");
         if (measure) {
-            query = query.substring("measure ".length());
+            query = query.substring("measure".length()).trim();
         }
-        // TODO verify this is correct
-        if (!query.startsWith("/")) {
-            query = "/jcr:root/" + query;
+        
+        if (query.isEmpty()) {
+            // special case, will always result in an empty result
+            query = "//jcr:root";
         }
+        
         initialize(query);
+        
         expected = new ArrayList<String>();
         read();
+        
+        if (currentTokenType == END) {
+            throw getSyntaxError("the query may not be empty");
+        }
 
         currentSelector.name = "a";
-        currentSelector.nodeType = "nt:base";
 
         ArrayList<Expression> columnList = new ArrayList<Expression>();
 
-        // TODO support one node matcher ('*' wildcard), example:
-        // /jcr:root/content/acme/*/jcr:content[@template='/apps/acme']
-
-        // TODO verify '//' is behaving correctly, as specified, example:
-        // /jcr:root/content/acme//jcr:content[@template='/apps/acme']
+        // TODO support "..", example:
+        // /jcr:root/etc/..
         
         String pathPattern = "";
+        boolean startOfQuery = true;
 
         while (true) {
+            
+            // if true, path or nodeType conditions are not allowed
             boolean shortcut = false;
             boolean slash = readIf("/");
+            
             if (!slash) {
-                break;
+                if (startOfQuery) {
+                    // the query doesn't start with "/"
+                    currentSelector.path = "/";
+                    pathPattern = "/";
+                    currentSelector.isChild = true;
+                } else {
+                    break;
+                }
             } else if (readIf("jcr:root")) {
                 // "/jcr:root" may only appear at the beginning
                 if (!pathPattern.isEmpty()) {
@@ -105,12 +120,13 @@ public class XPathToSQL2Converter {
                         // "/jcr:root//"
                         pathPattern = "//";
                         currentSelector.isDescendant = true;
+                    } else {
+                        currentSelector.isChild = true;
                     }
                 } else {
                     // for example "/jcr:root[condition]"
                     pathPattern = "/%";
                     currentSelector.path = "/";
-                    currentSelector.isDescendant = true;
                     shortcut = true;
                 }
             } else if (readIf("/")) {
@@ -120,16 +136,26 @@ public class XPathToSQL2Converter {
             } else {
                 // the token "/" was read
                 pathPattern += "/";
+                if (startOfQuery) {
+                    currentSelector.path = "/";
+                } else {
+                    currentSelector.isChild = true;
+                }
             }
             if (shortcut) {
-                // query of the style: "/jcr:root[condition]"
+                // "*" and so on are not allowed now
             } else if (readIf("*")) {
                 // "...*"
                 pathPattern += "%";
-                currentSelector.nodeType = "nt:base";
-                currentSelector.isChild = true;
+                if (!currentSelector.isDescendant) {
+                    if (selectors.size() == 0 && currentSelector.path.equals(""))
{
+                        // the query /* is special
+                        currentSelector.path = "/";
+                    }
+                }
             } else if (readIf("text")) {
                 // "...text()"
+                currentSelector.isChild = false;
                 pathPattern += "jcr:xmltext";
                 read("(");
                 read(")");
@@ -143,11 +169,10 @@ public class XPathToSQL2Converter {
                 read("(");
                 if (readIf(")")) {
                     // any
-                    currentSelector.isChild = true;
+                    pathPattern += "%";
                 } else {
                     if (readIf("*")) {
                         // any
-                        currentSelector.isChild = true;
                         pathPattern += "%";
                     } else {
                         currentSelector.isChild = false;
@@ -157,8 +182,6 @@ public class XPathToSQL2Converter {
                     }
                     if (readIf(",")) {
                         currentSelector.nodeType = readIdentifier();
-                    } else {
-                        currentSelector.nodeType = "nt:base";
                     }
                     read(")");
                 }
@@ -176,31 +199,41 @@ public class XPathToSQL2Converter {
                     currentSelector.path = "";
                     currentSelector.nodeName = null;
                 }
-                if (currentSelector.nodeType == null) {
-                    currentSelector.nodeType = "nt:base";
-                }
                 do {
                     read("@");
                     Property p = readProperty();
                     columnList.add(p);
                 } while (readIf("|"));
                 read(")");
-            } else {
+            } else if (currentTokenType == IDENTIFIER) {
                 // path restriction
                 String name = readIdentifier();
-                if (currentSelector.isDescendant) {
-                    pathPattern += name;
+                pathPattern += name;
+                if (!currentSelector.isChild) {
                     currentSelector.nodeName = name;
                 } else {
-                    pathPattern += name;
-                    currentSelector.path = PathUtils.concat(currentSelector.path, name);
+                    if (selectors.size() > 0) {
+                        // no explicit path restriction - so it's a node name restriction
+                        currentSelector.isChild = true;
+                        currentSelector.nodeName = name;
+                    } else {
+                        if (currentSelector.isChild) {
+                            currentSelector.isChild = false;
+                            String oldPath = currentSelector.path;
+                            // further extending the path
+                            currentSelector.path = PathUtils.concat(oldPath, name);
+                        }
+                    }
                 }
+            } else {
+                throw getSyntaxError();
             }
             if (readIf("[")) {
                 Expression c = parseConstraint();
                 currentSelector.condition = add(currentSelector.condition, c);
                 read("]");
             }
+            startOfQuery = false;
             nextSelector(false);
         }
         if (selectors.size() == 0) {
@@ -241,15 +274,26 @@ public class XPathToSQL2Converter {
         // select ...
         buff.append("select ");
         buff.append(new Property(currentSelector, "jcr:path").toString());
+        if (selectors.size() > 1) {
+            buff.append(" as [jcr:path]");
+        }
         buff.append(", ");
         buff.append(new Property(currentSelector, "jcr:score").toString());
+        if (selectors.size() > 1) {
+            buff.append(" as [jcr:score]");
+        }
         if (columnList.isEmpty()) {
             buff.append(", ");
             buff.append(new Property(currentSelector, "*").toString());
         } else {
             for (int i = 0; i < columnList.size(); i++) {
                 buff.append(", ");
-                buff.append(columnList.get(i).toString());
+                Expression e = columnList.get(i);
+                String columnName = e.toString();
+                buff.append(columnName);
+                if (selectors.size() > 1) {
+                    buff.append(" as [").append(e.getColumnAliasName()).append("]");
+                }
             }
         }
         
@@ -260,7 +304,11 @@ public class XPathToSQL2Converter {
             if (i > 0) {
                 buff.append(" inner join ");
             }
-            buff.append('[' + s.nodeType + ']').append(" as ").append(s.name);
+            String nodeType = s.nodeType;
+            if (nodeType == null) {
+                nodeType = "nt:base";
+            }
+            buff.append('[' + nodeType + ']').append(" as ").append(s.name);
             if (s.joinCondition != null) {
                 buff.append(" on ").append(s.joinCondition);
             }
@@ -434,6 +482,9 @@ public class XPathToSQL2Converter {
             c = new Condition(left, "<=", parseExpression(), Expression.PRECEDENCE_CONDITION);
         } else if (readIf(">=")) {
             c = new Condition(left, ">=", parseExpression(), Expression.PRECEDENCE_CONDITION);
+        // TODO support "x eq y"? it seems this only matches for single value properties?
 
+        // } else if (readIf("eq")) {
+        //    c = new Condition(left, "==", parseExpression(), Expression.PRECEDENCE_CONDITION);
         } else {
             c = new Condition(left, "is not null", null, Expression.PRECEDENCE_CONDITION);
         }
@@ -898,7 +949,7 @@ public class XPathToSQL2Converter {
     }
 
     private ParseException getSyntaxError(String expected) {
-        int index = Math.min(parseIndex, statement.length() - 1);
+        int index = Math.max(0, Math.min(parseIndex, statement.length() - 1));
         String query = statement.substring(0, index) + "(*)" + statement.substring(index).trim();
         if (expected != null) {
             query += "; expected: " + expected;
@@ -995,6 +1046,17 @@ public class XPathToSQL2Converter {
         int getPrecedence() {
             return PRECEDENCE_OPERAND;
         }
+        
+        /**
+         * Get the column alias name of an expression. For a property, this is the
+         * property name (no matter how many selectors the query contains); for
+         * other expressions it matches the toString() method.
+         * 
+         * @return the simple column name
+         */
+        String getColumnAliasName() {
+            return toString();
+        }
 
     }
 
@@ -1072,6 +1134,11 @@ public class XPathToSQL2Converter {
             }
             return buff.toString();
         }
+        
+        @Override
+        public String getColumnAliasName() {
+            return name;
+        }
 
     }
 

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=1383429&r1=1383428&r2=1383429&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
Tue Sep 11 14:33:40 2012
@@ -27,6 +27,7 @@ import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 
@@ -100,6 +101,7 @@ public class QueryTest extends AbstractQ
         LineNumberReader r = new LineNumberReader(new InputStreamReader(in));
         PrintWriter w = new PrintWriter(new OutputStreamWriter(
                 new FileOutputStream("target/" + file)));
+        HashSet<String> knownQueries = new HashSet<String>();
         boolean errors = false;
         try {
             while (true) {
@@ -124,6 +126,9 @@ public class QueryTest extends AbstractQ
                         // e.printStackTrace();
                         got = "error: " + e.toString().replace('\n', ' ');
                     }
+                    if (!knownQueries.add(line)) {
+                        got = "duplicate xpath2sql query";
+                    }
                     line = r.readLine().trim();
                     w.println(got);
                     if (!line.equals(got)) {

Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt?rev=1383429&r1=1383428&r2=1383429&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt
(original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt
Tue Sep 11 14:33:40 2012
@@ -48,6 +48,9 @@ commit / + "test": { "a": { "id": "10" }
 select * from [nt:base] where id is not null and not id = '100' and id <> '20'
 /test/a
 
+select * from [nt:base] where id < '1000'
+/test/a
+
 select * from [nt:base] where id is not null and not (id = '100' and id <> '20')
 /test/a
 /test/b
@@ -77,6 +80,9 @@ commit / - "test"
 
 # other tests
 
+select [jcr:path] from [nt:base] as a where issamenode(a, '/')
+/
+
 commit / + "test": { "My Documents": { "x" : {}}}
 
 select [jcr:path] from [nt:base] where name() = 'My_x0020_Documents'

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=1383429&r1=1383428&r2=1383429&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 Sep 11 14:33:40 2012
@@ -25,11 +25,76 @@
 
 # jackrabbit test queries
 
+xpath2sql /test
+select [jcr:path], [jcr:score], * from [nt:base] as a where name(a) = 'test' and issamenode(a,
'/')
+
+xpath2sql /
+invalid: Query: (*)/; expected: jcr:root, /, *, text, element, @, (
+
+xpath2sql /[@name='data']
+invalid: Query: /[(*)@name='data']; expected: jcr:root, /, *, text, element, @, (
+
+xpath2sql //[@name='data']
+invalid: Query: //[(*)@name='data']; expected: *, text, element, @, (
+
+xpath2sql //child/[@id='2.1']
+invalid: Query: //child/[(*)@id='2.1']; expected: jcr:root, /, *, text, element, @, (
+
+xpath2sql //
+invalid: Query: /(*)/; expected: *, text, element, @, (
+
+xpath2sql [@name='data']
+invalid: Query: [(*)@name='data']; expected: /, *, text, element, @, (
+
+xpath2sql test
+select [jcr:path], [jcr:score], * from [nt:base] as a where issamenode(a, '/test')
+
+xpath2sql jcr:root
+select [jcr:path], [jcr:score], * from [nt:base] as a where issamenode(a, '/jcr:root')
+
+xpath2sql /jcr:root
+select [jcr:path], [jcr:score], * from [nt:base] as a where issamenode(a, '/')
+
+xpath2sql //jcr:root
+select [jcr:path], [jcr:score], * from [nt:base] as a where name(a) = 'jcr:root'
+
+xpath2sql *
+select [jcr:path], [jcr:score], * from [nt:base] as a where ischildnode(a, '/')
+
+xpath2sql /*
+select [jcr:path], [jcr:score], * from [nt:base] as a where issamenode(a, '/')
+
+xpath2sql //*
+select [jcr:path], [jcr:score], * from [nt:base] as a
+
+xpath2sql test/*
+select [jcr:path], [jcr:score], * from [nt:base] as a where ischildnode(a, '/test')
+
+xpath2sql element(*, nt:folder)
+select [jcr:path], [jcr:score], * from [nt:folder] as a where ischildnode(a, '/')
+
+xpath2sql //test
+select [jcr:path], [jcr:score], * from [nt:base] as a where name(a) = 'test'
+
+xpath2sql /jcr:root[@foo = 'does-not-exist']
+select [jcr:path], [jcr:score], * from [nt:base] as a where [foo] = 'does-not-exist' and
issamenode(a, '/')
+
+xpath2sql 
+select [jcr:path], [jcr:score], * from [nt:base] as a where name(a) = 'jcr:root'
+
+xpath2sql /jcr:root/testroot/*/node11
+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 ischildnode(a, '/testroot') and name(b)
= 'node11'
+
+# eq can't currently be supported as there is no equivalent in SQL-2
+# (the behavior is different from = if one of the operands is a multi-valued property)
+xpath2sql //testRoot/*[@jcr:primaryType='nt:unstructured' and @text eq 'foo']
+invalid: Query: //testRoot/*[@jcr:primaryType='nt:unstructured' and @text eq(*)'foo']; expected:
]
+
 xpath2sql //testRoot/*[@text = 'foo']
-select b.[jcr:path], b.[jcr:score], b.* from [nt:base] as a inner join [nt:base] as b on
ischildnode(b, a) where name(a) = 'testRoot' and b.[text] = 'foo'
+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.[text] = 'foo'
 
 xpath2sql /testRoot/*[@jcr:primaryType='nt:unstructured' and fn:not(@mytext)]
-select [jcr:path], [jcr:score], * from [nt:base] as a where [jcr:primaryType] = 'nt:unstructured'
and [mytext] is null and ischildnode(a, '/testRoot')
+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 issamenode(a,
'/') and b.[jcr:primaryType] = 'nt:unstructured' and b.[mytext] is null
 
 xpath2sql /jcr:root/testroot/*[jcr:contains(., '"quick brown" -cat')]
 select [jcr:path], [jcr:score], * from [nt:base] as a where contains(*, '"quick brown" -cat')
and ischildnode(a, '/testroot')
@@ -63,17 +128,14 @@ xpath2sql /jcr:root/testroot/*[jcr:conta
 invalid: Query: /jcr:root/testroot/*[jcr:contains(., 'jackrabbit')]/rep:excerpt((*).); expected:
<end>
 
 xpath2sql /jcr:root/testroot//child/..[@foo1]
-invalid: Query: /jcr:root/testroot//child/.(*).[@foo1]; expected: identifier
+invalid: Query: /jcr:root/testroot//child/.(*).[@foo1]; expected: jcr:root, /, *, text, element,
@, (
 
 xpath2sql //testroot/*[@jcr:primaryType='nt:unstructured' and fn:not(@mytext)]
-select b.[jcr:path], b.[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
+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
 
 xpath2sql /jcr:root/testroot/people/jcr:deref(@worksfor, '*')
 invalid: Query: /jcr:root/testroot/people/jcr:deref((*)@worksfor, '*'); expected: <end>
 
-xpath2sql /jcr:root[@foo = 'does-not-exist']
-select [jcr:path], [jcr:score], * from [nt:base] as a where [foo] = 'does-not-exist' and
isdescendantnode(a, '/')
-
 xpath2sql //*[@jcr:primaryType='nt:unstructured' and jcr:like(@foo,"%ar'ba%")]
 select [jcr:path], [jcr:score], * from [nt:base] as a where [jcr:primaryType] = 'nt:unstructured'
and [foo] like '%ar''ba%'
 
@@ -104,16 +166,13 @@ select [jcr:path], [jcr:score], * from [
 # sling queries
 
 xpath2sql //element(*,mix:language)[fn:lower-case(@jcr:language)='en']//element(*,sling:Message)[@sling:message]/(@sling:key|@sling:message)
-select b.[jcr:path], b.[jcr:score], b.[sling:key], b.[sling:message] from [mix:language]
as a inner join [sling:Message] as b on isdescendantnode(b, a) where lower(a.[jcr:language])
= 'en' and b.[sling:message] is not null
+select b.[jcr:path] as [jcr:path], b.[jcr:score] as [jcr:score], b.[sling:key] as [sling:key],
b.[sling:message] as [sling:message] from [mix:language] as a inner join [sling:Message] as
b on isdescendantnode(b, a) where lower(a.[jcr:language]) = 'en' and b.[sling:message] is
not null
 
 xpath2sql //element(*,mix:language)[fn:upper-case(@jcr:language)='en']//element(*,sling:Message)[@sling:message]/(@sling:key|@sling:message)
-select b.[jcr:path], b.[jcr:score], b.[sling:key], b.[sling:message] from [mix:language]
as a inner join [sling:Message] as b on isdescendantnode(b, a) where upper(a.[jcr:language])
= 'en' and b.[sling:message] is not null
+select b.[jcr:path] as [jcr:path], b.[jcr:score] as [jcr:score], b.[sling:key] as [sling:key],
b.[sling:message] as [sling:message] from [mix:language] as a inner join [sling:Message] as
b on isdescendantnode(b, a) where upper(a.[jcr:language]) = 'en' and b.[sling:message] is
not null
 
 # jboss example queries
 
-xpath2sql //*
-select [jcr:path], [jcr:score], * from [nt:base] as a
-
 xpath2sql //element(*,my:type)
 select [jcr:path], [jcr:score], * from [my:type] as a
 
@@ -129,7 +188,7 @@ xpath2sql /jcr:root/testdata/node[@jcr:p
 select [jcr:path], [jcr:score], * from [nt:base] as a where [jcr:primaryType] is not null
and issamenode(a, '/testdata/node')
 
 xpath2sql //testroot/*[@jcr:primaryType='nt:unstructured'] order by @prop2, @prop1
-select b.[jcr:path], b.[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' order
by b.[prop2], b.[prop1]
+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' order by b.[prop2], b.[prop1]
 
 xpath2sql /jcr:root/test//jcr:xmltext
 select [jcr:path], [jcr:score], * from [nt:base] as a where name(a) = 'jcr:xmltext' and isdescendantnode(a,
'/test')
@@ -143,9 +202,6 @@ select [jcr:path], [jcr:score], * from [
 xpath2sql /jcr:root/test/text()
 select [jcr:path], [jcr:score], * from [nt:base] as a where issamenode(a, '/test/jcr:xmltext')
 
-xpath2sql /jcr:root
-select [jcr:path], [jcr:score], * from [nt:base] as a where isdescendantnode(a, '/')
-
 xpath2sql //*[@name='Hello']
 select [jcr:path], [jcr:score], * from [nt:base] as a where [name] = 'Hello'
 
@@ -220,9 +276,6 @@ select [jcr:path], [jcr:score], * from [
 
 # other queries
 
-xpath2sql //*
-select [jcr:path], [jcr:score], * from [nt:base] as a
-
 xpath2sql //element(*, my:type)
 select [jcr:path], [jcr:score], * from [my:type] as a
 
@@ -296,7 +349,7 @@ xpath2sql //element(*, my:type)[jcr:cont
 select [jcr:path], [jcr:score], * from [my:type] as a where contains([my:title], 'jcr') order
by score(a) desc
 
 xpath2sql [invalid/query
-invalid: Query: /jcr:root/[(*)invalid/query; expected: identifier
+invalid: Query: [(*)invalid/query; expected: /, *, text, element, @, (
 
 xpath2sql //element(*, my:type)[@my:value = -'x']
 invalid: Query: //element(*, my:type)[@my:value = -'x'(*)]



Mime
View raw message