jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From thom...@apache.org
Subject svn commit: r1412128 - 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-core/src/test/resources/org/apache/jackrabbit/oak/query/ oak-jcr/src/main/java/org/...
Date Wed, 21 Nov 2012 14:34:38 GMT
Author: thomasm
Date: Wed Nov 21 14:34:36 2012
New Revision: 1412128

URL: http://svn.apache.org/viewvc?rev=1412128&view=rev
Log:
OAK-295 Jackrabbit query with spaces in node names

Modified:
    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/SQL2Parser.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/ChildNodeImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
    jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2.txt
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/qom/QOMNode.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/qom/QomTest.java

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=1412128&r1=1412127&r2=1412128&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
Wed Nov 21 14:34:36 2012
@@ -23,6 +23,7 @@ import java.util.List;
 import org.apache.jackrabbit.oak.api.PropertyValue;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.namepath.JcrPathParser;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.query.ast.AstVisitorBase;
 import org.apache.jackrabbit.oak.query.ast.BindVariableValueImpl;
@@ -605,6 +606,17 @@ public class Query {
     public Tree getTree(String path) {
         return root.getTree(path);
     }
+    
+    /**
+     * Validate a path is syntactically correct.
+     * 
+     * @param path the path to validate
+     */
+    public void validatePath(String path) {
+        if (!JcrPathParser.validate(path)) {
+            throw new IllegalArgumentException("Invalid path: " + path);
+        }
+    }
 
     @Override
     public String toString() {

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=1412128&r1=1412127&r2=1412128&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
Wed Nov 21 14:34:36 2012
@@ -43,15 +43,15 @@ import java.util.ArrayList;
 import java.util.HashMap;
 
 /**
- * The SQL2 parser can convert a JCR-SQL2 query to a query.
- * The 'old' SQL query language is also supported if
+ * The SQL2 parser can convert a JCR-SQL2 query to a query. The 'old' SQL query
+ * language (here named SQL-1) is also supported.
  */
 public class SQL2Parser {
 
     // Character types, used during the tokenizer phase
     private static final int CHAR_END = -1, CHAR_VALUE = 2, CHAR_QUOTED = 3;
     private static final int CHAR_NAME = 4, CHAR_SPECIAL_1 = 5, CHAR_SPECIAL_2 = 6;
-    private static final int CHAR_STRING = 7, CHAR_DECIMAL = 8;
+    private static final int CHAR_STRING = 7, CHAR_DECIMAL = 8, CHAR_BRACKETED = 9;
 
     // Token types
     private static final int KEYWORD = 1, IDENTIFIER = 2, PARAMETER = 3, END = 4, VALUE =
5;
@@ -182,30 +182,17 @@ public class SQL2Parser {
     }
 
     private String readName() throws ParseException {
-        if (readIf("[")) {
-            if (currentTokenType == VALUE) {
-                PropertyValue value = readString();
-                read("]");
-                return value.getValue(Type.STRING);
-            } else {
-                int level = 1;
-                StringBuilder buff = new StringBuilder();
-                while (true) {
-                    if (isToken("]")) {
-                        if (--level <= 0) {
-                            read();
-                            break;
-                        }
-                    } else if (isToken("[")) {
-                        level++;
-                    }
-                    buff.append(readAny());
-                }
-                return buff.toString();
-            }
+        if (currentTokenType == END) {
+            throw getSyntaxError("a token");
+        }
+        String s;
+        if (currentTokenType == VALUE) {
+            s = currentValue.getValue(Type.STRING);
         } else {
-            return readAny();
+            s = currentToken;
         }
+        read();
+        return s;
     }
 
     private SourceImpl parseSource() throws ParseException {
@@ -778,20 +765,6 @@ public class SQL2Parser {
         read();
     }
 
-    private String readAny() throws ParseException {
-        if (currentTokenType == END) {
-            throw getSyntaxError("a token");
-        }
-        String s;
-        if (currentTokenType == VALUE) {
-            s = currentValue.getValue(Type.STRING);
-        } else {
-            s = currentToken;
-        }
-        read();
-        return s;
-    }
-
     private PropertyValue readString() throws ParseException {
         if (currentTokenType != VALUE) {
             throw getSyntaxError("string value");
@@ -836,8 +809,6 @@ public class SQL2Parser {
             case '%':
             case '?':
             case '$':
-            case '[':
-            case ']':
                 type = CHAR_SPECIAL_1;
                 break;
             case '!':
@@ -851,17 +822,28 @@ public class SQL2Parser {
             case '.':
                 type = CHAR_DECIMAL;
                 break;
+            case '[':
+                types[i] = type = CHAR_BRACKETED;
+                startLoop = i;
+                while (true) {
+                    while (command[++i] != ']') {
+                        checkRunOver(i, len, startLoop);
+                    }
+                    if (i >= len - 1 || command[i + 1] != ']') {
+                        break;
+                    }
+                    i++;
+                }
+                break;
             case '\'':
-                type = CHAR_STRING;
-                types[i] = CHAR_STRING;
+                types[i] = type = CHAR_STRING;
                 startLoop = i;
                 while (command[++i] != '\'') {
                     checkRunOver(i, len, startLoop);
                 }
                 break;
             case '\"':
-                type = CHAR_QUOTED;
-                types[i] = CHAR_QUOTED;
+                types[i] = type = CHAR_QUOTED;
                 startLoop = i;
                 while (command[++i] != '\"') {
                     checkRunOver(i, len, startLoop);
@@ -999,6 +981,11 @@ public class SQL2Parser {
             }
             readDecimal(i - 1, i);
             return;
+        case CHAR_BRACKETED:
+            readString(i, ']');
+            currentTokenType = IDENTIFIER;
+            currentToken = currentValue.getValue(Type.STRING);
+            return;
         case CHAR_STRING:
             readString(i, '\'');
             return;

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=1412128&r1=1412127&r2=1412128&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
Wed Nov 21 14:34:36 2012
@@ -40,6 +40,7 @@ abstract class AstElement {
     }
 
     protected String quote(String pathOrName) {
+        pathOrName = pathOrName.replaceAll("]", "]]");
         return '[' + pathOrName + ']';
     }
 
@@ -48,12 +49,14 @@ abstract class AstElement {
     }
 
     /**
-     * Calculate the absolute path (the path including the workspace name).
+     * Validate and normalize the path.
      *
-     * @param path the session local path
-     * @return the absolute path
+     * @param path the path to validate
+     * @return the validated and normalized path
      */
-    protected String getAbsolutePath(String path) {
+    protected String validateAndNormalizePath(String path) {
+        // TODO normalize the path (remove superfluous ".." and "." where possible)
+        query.validatePath(path);
         return path;
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeImpl.java?rev=1412128&r1=1412127&r2=1412128&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ChildNodeImpl.java
Wed Nov 21 14:34:36 2012
@@ -66,7 +66,7 @@ public class ChildNodeImpl extends Const
     @Override
     public void restrict(FilterImpl f) {
         if (selector == f.getSelector()) {
-            String path = getAbsolutePath(parentPath);
+            String path = validateAndNormalizePath(parentPath);
             f.restrictPath(path, Filter.PathRestriction.DIRECT_CHILDREN);
         }
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeImpl.java?rev=1412128&r1=1412127&r2=1412128&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/DescendantNodeImpl.java
Wed Nov 21 14:34:36 2012
@@ -42,7 +42,7 @@ public class DescendantNodeImpl extends 
         if (p == null) {
             return false;
         }
-        String path = getAbsolutePath(ancestorPath);
+        String path = validateAndNormalizePath(ancestorPath);
         if (path == null) {
             return false;
         }
@@ -67,7 +67,7 @@ public class DescendantNodeImpl extends 
     @Override
     public void restrict(FilterImpl f) {
         if (f.getSelector() == selector) {
-            String path = getAbsolutePath(ancestorPath);
+            String path = validateAndNormalizePath(ancestorPath);
             f.restrictPath(path, Filter.PathRestriction.ALL_CHILDREN);
         }
     }

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=1412128&r1=1412127&r2=1412128&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
Wed Nov 21 14:34:36 2012
@@ -37,7 +37,7 @@ public class SameNodeImpl extends Constr
 
     @Override
     public boolean evaluate() {
-        String p = getAbsolutePath(path);
+        String p = validateAndNormalizePath(path);
         // TODO normalize paths
         return selector.currentPath().equals(p);
     }
@@ -60,7 +60,7 @@ public class SameNodeImpl extends Constr
     @Override
     public void restrict(FilterImpl f) {
         if (f.getSelector() == selector) {
-            String p = getAbsolutePath(path);
+            String p = validateAndNormalizePath(path);
             f.restrictPath(p, Filter.PathRestriction.EXACT);
         }
         // TODO validate absolute path

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java?rev=1412128&r1=1412127&r2=1412128&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
Wed Nov 21 14:34:36 2012
@@ -123,6 +123,7 @@ public class SelectorImpl extends Source
 
     private Filter createFilter() {
         FilterImpl f = new FilterImpl(this, query.getStatement());
+        validateNodeType(nodeTypeName);
         f.setNodeType(nodeTypeName);
         if (joinCondition != null) {
             joinCondition.restrict(f);
@@ -143,6 +144,13 @@ public class SelectorImpl extends Source
 
         return f;
     }
+    
+    private void validateNodeType(String nodeType) {
+        // this looks a bit weird, but it should be correct - the code
+        // assumes that paths and node type names have the same format
+        // restrictions (characters such as "[" are not allowed and so on)
+        query.validatePath(nodeType);
+    }
 
     @Override
     public boolean next() {

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=1412128&r1=1412127&r2=1412128&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
Wed Nov 21 14:34:36 2012
@@ -23,6 +23,15 @@
 # * new tests are typically be added on top, after the syntax docs
 # * use ascii character only
 
+# test spaces in identifiers
+
+commit / + "test": { "space space": { }}
+
+select * from [nt:base] where issamenode([/test/space space])
+/test/space space
+
+commit / - "test"
+
 # test multi-valued properties
 
 commit / + "test": { "a": { "name": ["Hello", "World" ] }, "b": { "name" : "Hello" }}

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/qom/QOMNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/qom/QOMNode.java?rev=1412128&r1=1412127&r2=1412128&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/qom/QOMNode.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/qom/QOMNode.java
Wed Nov 21 14:34:36 2012
@@ -52,6 +52,7 @@ abstract class QOMNode {
     }
 
     private static String quoteName(String name) {
+        name = name.replaceAll("]", "]]");
         return '[' + name + ']';
     }
 

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/qom/QomTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/qom/QomTest.java?rev=1412128&r1=1412127&r2=1412128&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/qom/QomTest.java
(original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/qom/QomTest.java
Wed Nov 21 14:34:36 2012
@@ -387,7 +387,7 @@ public class QomTest extends AbstractRep
         assertEquals("selectorName", s.getSelectorName());
         assertEquals("[nodeTypeName] AS [selectorName]", s.toString());
         assertEquals("[n]", f.selector("n",  null).toString());
-           }
+    }
 
     @Test
     public void upperCase() throws RepositoryException {
@@ -419,5 +419,14 @@ public class QomTest extends AbstractRep
         assertEquals(o, q.getOrderings()[0]);
         assertEquals(col, q.getColumns()[0]);
     }
-
+    
+    @Test
+    public void escapedName() throws RepositoryException {
+        assertEquals("[[n]]]", f.selector("[n]",  null).toString());
+        assertEquals("[[s]]].[[p]]]", f.propertyValue("[s]", "[p]").toString());
+        assertEquals("ISSAMENODE([[s1]]], [[s2]]], [[p]]])", 
+                f.sameNodeJoinCondition("[s1]", "[s2]", "[p]").toString());        
+        assertEquals("ISSAMENODE([[s]]], [[p]]])", 
+                f.sameNode("[s]", "[p]").toString());        
+    }
 }



Mime
View raw message