jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From thom...@apache.org
Subject svn commit: r1298361 - in /jackrabbit/sandbox/jackrabbit-microkernel/src: main/java/org/apache/jackrabbit/query/ main/java/org/apache/jackrabbit/query/qom/tree/ test/java/org/apache/jackrabbit/query/ test/resources/
Date Thu, 08 Mar 2012 11:17:01 GMT
Author: thomasm
Date: Thu Mar  8 11:17:01 2012
New Revision: 1298361

URL: http://svn.apache.org/viewvc?rev=1298361&view=rev
Log:
XPath to SQL2 converter (WIP)

Added:
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/XPathToSQL2Converter.java
      - copied, changed from r1297552, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/ParserXPath.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryXpathTest.txt
Removed:
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/ParserXPath.java
Modified:
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/ParserSQL2.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/QueryManagerImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LiteralImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/QueryTest.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/XPathTest.java

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/ParserSQL2.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/ParserSQL2.java?rev=1298361&r1=1298360&r2=1298361&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/ParserSQL2.java
(original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/ParserSQL2.java
Thu Mar  8 11:17:01 2012
@@ -998,4 +998,8 @@ public class ParserSQL2 {
         return selectors.get(0).getSelectorName();
     }
 
+    public static String escapeStringLiteral(String value) {
+        return '\'' + value.replace("'", "''") + '\'';
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/QueryManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/QueryManagerImpl.java?rev=1298361&r1=1298360&r2=1298361&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/QueryManagerImpl.java
(original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/QueryManagerImpl.java
Thu Mar  8 11:17:01 2012
@@ -31,32 +31,33 @@ public class QueryManagerImpl implements
 
     private final QueryObjectModelFactoryImpl qomFactory;
     private final ParserSQL2 parserSQL2;
-    private final ParserXPath parserXPath;
 
     @SuppressWarnings("deprecation")
+    private static final String XPATH = Query.XPATH;
+
     private static final String[] SUPPOERTED_QUERY_LANGUAGES = {
         Query.JCR_JQOM,
         Query.JCR_SQL2,
-        Query.SQL,
-        Query.XPATH
+        XPATH
     };
 
     public QueryManagerImpl(QueryObjectModelFactoryImpl qomFactory, ValueFactory valueFactory)
{
         this.qomFactory = qomFactory;
         parserSQL2 = new ParserSQL2(qomFactory, valueFactory);
-        parserXPath = new ParserXPath(qomFactory, valueFactory);
     }
 
-    public Query createQuery(String statement, String language) throws InvalidQueryException,
RepositoryException {
+    public Query createQuery(String statement, String language) throws RepositoryException
{
         if (Query.JCR_SQL2.equals(language)) {
             QueryObjectModel qom = parserSQL2.createQueryObjectModel(statement);
             return new QueryImpl(qom);
-        } else if (Query.XPATH.equals(language)) {
-            QueryObjectModel qom = parserXPath.createQueryObjectModel(statement);
+        } else if (XPATH.equals(language)) {
+            XPathToSQL2Converter converter = new XPathToSQL2Converter();
+            String sql2 = converter.convert(statement);
+            QueryObjectModel qom = parserSQL2.createQueryObjectModel(sql2);
             return new QueryImpl(qom);
+        } else {
+            throw new InvalidQueryException("Unsupported language: " + language);
         }
-        // TODO Auto-generated method stub
-        return null;
     }
 
     public QueryObjectModelFactoryImpl getQOMFactory() {

Copied: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/XPathToSQL2Converter.java
(from r1297552, jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/ParserXPath.java)
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/XPathToSQL2Converter.java?p2=jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/XPathToSQL2Converter.java&p1=jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/ParserXPath.java&r1=1297552&r2=1298361&rev=1298361&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/ParserXPath.java
(original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/XPathToSQL2Converter.java
Thu Mar  8 11:17:01 2012
@@ -19,17 +19,12 @@ package org.apache.jackrabbit.query;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import javax.jcr.ValueFactory;
 import javax.jcr.query.InvalidQueryException;
-import javax.jcr.query.qom.QueryObjectModel;
-import javax.jcr.query.qom.QueryObjectModelFactory;
-
 
 /**
- * The XPath parser can convert a XPATH query to a QueryObjectModel.
+ * This class can can convert a XPATH query to a SQL2 query.
  */
-public class ParserXPath {
+public class XPathToSQL2Converter {
 
     // Character types, used during the tokenizer phase
     private static final int CHAR_END = -1, CHAR_VALUE = 2, CHAR_QUOTED = 3;
@@ -37,7 +32,7 @@ public class ParserXPath {
     private static final int CHAR_STRING = 7, CHAR_DECIMAL = 8;
 
     // Token types
-    private static final int KEYWORD = 1, IDENTIFIER = 2, PARAMETER = 3, END = 4, VALUE =
5;
+    private static final int KEYWORD = 1, IDENTIFIER = 2, PARAMETER = 3, END = 4, VALUE_STRING
= 5, VALUE_NUMBER = 6;
     private static final int MINUS = 12, PLUS = 13, OPEN = 14, CLOSE = 15;
 
     // The query as an array of characters and character types
@@ -50,47 +45,163 @@ public class ParserXPath {
     private int currentTokenType;
     private String currentToken;
     private boolean currentTokenQuoted;
-    private Value currentValue;
     private ArrayList<String> expected;
 
-    // Code injection protection: if disabled, literals are not allowed
-    private boolean allowTextLiterals = true, allowNumberLiterals = true;
-
-    private QueryObjectModelFactory factory;
-    private ValueFactory valueFactory;
-
-    /**
-     * Create a new parser. A parser can be re-used, but it is not thread safe.
-     *
-     * @param factory the query object model factory
-     * @param valueFactory the value factory
-     */
-    public ParserXPath(QueryObjectModelFactory factory, ValueFactory valueFactory) {
-        this.factory = factory;
-        this.valueFactory = valueFactory;
-    }
-
     /**
-     * Parse a JCR-SQL2 query and return the query object model
+     * Convert the query to SQL2.
      *
      * @param query the query string
-     * @return the query object model
+     * @return the SQL2 query
      * @throws RepositoryException if parsing failed
      */
-    public QueryObjectModel createQueryObjectModel(String query) throws RepositoryException
{
+    public String convert(String query) throws RepositoryException {
         initialize(query);
         expected = new ArrayList<String>();
         read();
-        if (readIf("//")) {
-            System.out.println("any child node");
-        } else if (readIf("/")) {
-            System.out.println("any node: " + readString());
+        String path = "";
+        Condition condition = null;
+        String from = "nt:base";
+        ArrayList<Expression> columnList = new ArrayList<Expression>();
+        while (true) {
+            String nodeType;
+            if (readIf("/")) {
+                if (readIf("/")) {
+                    path += "%";
+                } else if (readIf("jcr:root")) {
+                    if (path.length() > 0) {
+                        throw new InvalidQueryException("jcr:root with a path: " + path);
+                    }
+                    path = "/";
+                    read("/");
+                }
+                if (readIf("*")) {
+                    nodeType = "nt:base";
+                    from = nodeType;
+                } else if (readIf("element")) {
+                    read("(");
+                    if (readIf("*")) {
+                        if (!path.endsWith("%")) {
+                            path += "%";
+                        }
+                    }
+                    read(",");
+                    nodeType = readIdentifier();
+                    from = nodeType;
+                    read(")");
+                } else if (readIf("@")) {
+                    Property p = new Property(readIdentifier());
+                    columnList.add(p);
+                } else if (readIf("(")) {
+                    do {
+                        read("@");
+                        Property p = new Property(readIdentifier());
+                        columnList.add(p);
+                    } while (readIf("|"));
+                    read(")");
+                } else {
+                    String name = readIdentifier();
+                    path += name + "/";
+                    continue;
+                }
+                if (!path.equals("%")) {
+                    Condition c = new Condition(new Property("jcr:path"), "like", Literal.newString(path));
+                    condition = add(condition, c);
+                }
+            } else {
+                break;
+            }
+        }
+        if (readIf("order")) {
+            read("by");
+            ArrayList<Order> orderList = new ArrayList<Order>();
+            do {
+                Order order = new Order();
+                order.expr = parseExpression();
+                if (readIf("descending")) {
+                    order.descending = true;
+                } else {
+                    readIf("ascending");
+                }
+                orderList.add(order);
+            } while (readIf(","));
         }
         if (currentToken.length() > 0) {
             throw getSyntaxError("<end>");
         }
-        return null;
-        // return factory.createQuery(source, constraint, orderings, columnArray);
+        StringBuilder buff = new StringBuilder("select ");
+        if (columnList.size() == 0) {
+            buff.append("*");
+        } else {
+            for (int i = 0; i < columnList.size(); i++) {
+                if (i > 0) {
+                    buff.append(", ");
+                }
+                buff.append(columnList.get(i).toString());
+            }
+        }
+        buff.append(" from ");
+        buff.append(from);
+        if (condition != null) {
+            buff.append(" where ").append(condition);
+        }
+        return buff.toString();
+    }
+
+    private static Condition add(Condition old, Condition add) {
+        if (old == null) {
+            return add;
+        }
+        return new Condition(old, "AND", add);
+    }
+
+    private Expression parseExpression() throws RepositoryException {
+        if (currentTokenType == IDENTIFIER) {
+            String name = currentToken;
+            read();
+            if (readIf("(")) {
+                return parseFunction(name);
+            } else {
+                return new Property(name);
+            }
+        } else if (currentTokenType == VALUE_NUMBER) {
+            Literal l = Literal.newNumber(currentToken);
+            read();
+            return l;
+        } else if (currentTokenType == VALUE_STRING) {
+            Literal l = Literal.newString(currentToken);
+            read();
+            return l;
+        } else {
+            throw getSyntaxError("identifier");
+        }
+    }
+
+    private Expression parseFunction(String functionName) throws RepositoryException {
+        if ("jcr:like".equals(functionName)) {
+            Condition c = new Condition(parseExpression(), "like", null);
+            read(",");
+            c.right = parseExpression();
+            read(")");
+            return c;
+        } else if ("jcr:contains".equals(functionName)) {
+            Function f = new Function();
+            f.name = "contains";
+            f.params.add(parseExpression());
+            read(",");
+            f.params.add(parseExpression());
+            read(")");
+            return f;
+        } else if ("jcr:score".equals(functionName)) {
+            Function f = new Function();
+            f.name = "score";
+            // TODO score: support parameters?
+            read(")");
+            return f;
+        // } else if ("jcr:deref".equals(functionName)) {
+            // TODO support jcr:deref?
+        } else {
+            throw getSyntaxError("jcr:like | jcr:contains | jcr:score | jcr:deref");
+        }
     }
 
     private boolean readIf(String token) throws RepositoryException {
@@ -117,27 +228,22 @@ public class ParserXPath {
         read();
     }
 
-    private String readAny() throws RepositoryException {
-        if (currentTokenType == END) {
-            throw getSyntaxError("a token");
-        }
-        String s;
-        if (currentTokenType == VALUE) {
-            s = currentValue.getString();
-        } else {
-            s = currentToken;
+    private String readIdentifier() throws RepositoryException {
+        if (currentTokenType != IDENTIFIER) {
+            throw getSyntaxError("identifier");
         }
+        String s = currentToken;
         read();
         return s;
     }
 
-    private Value readString() throws RepositoryException {
-        if (currentTokenType != VALUE) {
+    private String readString() throws RepositoryException {
+        if (currentTokenType != VALUE_STRING) {
             throw getSyntaxError("string value");
         }
-        Value value = currentValue;
+        String s = currentToken;
         read();
-        return value;
+        return s;
     }
 
     private void addExpected(String token) {
@@ -162,6 +268,8 @@ public class ParserXPath {
             char c = command[i];
             int type = 0;
             switch (c) {
+            case '@':
+            case '|':
             case '/':
             case '-':
             case '(':
@@ -182,9 +290,7 @@ public class ParserXPath {
             case '!':
             case '<':
             case '>':
-            case '|':
             case '=':
-            case ':':
                 type = CHAR_SPECIAL_2;
                 break;
             case '.':
@@ -206,6 +312,7 @@ public class ParserXPath {
                     checkRunOver(i, len, startLoop);
                 }
                 break;
+            case ':':
             case '_':
                 type = CHAR_NAME;
                 break;
@@ -310,10 +417,8 @@ public class ParserXPath {
                         readDecimal(start, i);
                         break;
                     }
-                    checkLiterals(false);
-                    currentValue = valueFactory.createValue(number);
-                    currentTokenType = VALUE;
-                    currentToken = "0";
+                    currentTokenType = VALUE_NUMBER;
+                    currentToken = String.valueOf(number);
                     parseIndex = i;
                     break;
                 }
@@ -369,17 +474,9 @@ public class ParserXPath {
             }
             i++;
         }
-        currentToken = "'";
-        checkLiterals(false);
-        currentValue = valueFactory.createValue(result);
+        currentToken = result;
         parseIndex = i;
-        currentTokenType = VALUE;
-    }
-
-    private void checkLiterals(boolean text) throws InvalidQueryException {
-        if (text && !allowTextLiterals || (!text && !allowNumberLiterals))
{
-            throw getSyntaxError("bind variable (literals of this type not allowed)");
-        }
+        currentTokenType = VALUE_STRING;
     }
 
     private void readDecimal(int start, int i) throws RepositoryException {
@@ -406,16 +503,13 @@ public class ParserXPath {
         }
         parseIndex = i;
         String sub = statement.substring(start, i);
-        BigDecimal bd;
         try {
-            bd = new BigDecimal(sub);
+            new BigDecimal(sub);
         } catch (NumberFormatException e) {
             throw new InvalidQueryException("Data conversion error converting " + sub + "
to BigDecimal: " + e);
         }
-        checkLiterals(false);
-
-        currentValue = valueFactory.createValue(bd);
-        currentTokenType = VALUE;
+        currentToken = sub;
+        currentTokenType = VALUE_NUMBER;
     }
 
     private InvalidQueryException getSyntaxError() {
@@ -442,6 +536,77 @@ public class ParserXPath {
         return new InvalidQueryException("Query:\n" + query);
     }
 
+    static class Expression {
+        // base class
+    }
+
+    static class Literal extends Expression {
+        String value;
+        private Literal(String value) {
+            this.value = value;
+        }
+        static Literal newNumber(String s) {
+            return new Literal(s);
+        }
+        static Literal newString(String s) {
+            return new Literal(ParserSQL2.escapeStringLiteral(s));
+        }
+        public String toString() {
+            return value;
+        }
+    }
+
+    static class Property extends Expression {
+        String name;
+        Property(String name) {
+            this.name = name;
+        }
+        public String toString() {
+            return name;
+        }
+    }
+
+    static class Condition extends Expression {
+        Expression left;
+        String operator;
+        Expression right;
+        Condition(Expression left, String operator, Expression right) {
+            this.left = left;
+            this.operator = operator;
+            this.right = right;
+        }
+        public String toString() {
+            return (left == null ? "" : (left + " ")) +
+                operator + " " + right;
+        }
+    }
+
+    static class Function extends Expression {
+        String name;
+        ArrayList<Expression> params = new ArrayList<Expression>();
+
+        public String toString() {
+            StringBuilder buff = new StringBuilder(name);
+            buff.append('(');
+            for (int i = 0; i < params.size(); i++) {
+                if (i > 0) {
+                    buff.append(", ");
+                }
+                buff.append(params.get(i));
+            }
+            buff.append(')');
+            return buff.toString();
+        }
+    }
+
+    static class Order {
+        boolean descending;
+        Expression expr;
+        public String toString() {
+            return expr + (descending ? " desc" : "");
+        }
+    }
+
 
 }
 

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LiteralImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LiteralImpl.java?rev=1298361&r1=1298360&r2=1298361&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LiteralImpl.java
(original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LiteralImpl.java
Thu Mar  8 11:17:01 2012
@@ -22,6 +22,7 @@ import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.query.qom.Literal;
+import org.apache.jackrabbit.query.ParserSQL2;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -82,7 +83,7 @@ public class LiteralImpl extends StaticO
     }
 
     private String escape() throws RepositoryException {
-        return '\'' + value.getString().replace("'", "''") + '\'';
+        return ParserSQL2.escapeStringLiteral(value.getString());
     }
 
     @Override

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/QueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/QueryTest.java?rev=1298361&r1=1298360&r2=1298361&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/QueryTest.java
(original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/QueryTest.java
Thu Mar  8 11:17:01 2012
@@ -46,9 +46,18 @@ public class QueryTest {
 
     @Test
     public void script() throws Exception {
-        InputStream in = getClass().getClassLoader().getResourceAsStream("queryTest.txt");
+        test("queryTest.txt");
+    }
+
+    @Test
+    public void xpath() throws Exception {
+        test("queryXpathTest.txt");
+    }
+
+    private void test(String file) throws Exception {
+        InputStream in = getClass().getClassLoader().getResourceAsStream(file);
         LineNumberReader r = new LineNumberReader(new InputStreamReader(in));
-        PrintWriter w = new PrintWriter(new OutputStreamWriter(new FileOutputStream("target/queryTest.txt")));
+        PrintWriter w = new PrintWriter(new OutputStreamWriter(new FileOutputStream("target/"
+ file)));
         boolean errors = false;
         try {
             while (true) {
@@ -59,6 +68,16 @@ public class QueryTest {
                 line = line.trim();
                 if (line.startsWith("#") || line.length() == 0) {
                     w.println(line);
+                } else if (line.startsWith("xpath")) {
+                    line = line.substring("xpath".length()).trim();
+                    w.println("xpath " + line);
+                    XPathToSQL2Converter c = new XPathToSQL2Converter();
+                    String got = c.convert(line);
+                    line = r.readLine().trim();
+                    w.println(got);
+                    if (!line.equals(got)) {
+                        errors = true;
+                    }
                 } else if (line.startsWith("select")) {
                     w.println(line);
                     Iterator<String> result = qe.executeQuery(line, null);

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/XPathTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/XPathTest.java?rev=1298361&r1=1298360&r2=1298361&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/XPathTest.java
(original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/XPathTest.java
Thu Mar  8 11:17:01 2012
@@ -16,9 +16,16 @@
  */
 package org.apache.jackrabbit.query;
 
+import org.junit.Test;
+
 public class XPathTest {
 
+    @Test
     public void test() throws Exception {
+        XPathToSQL2Converter c = new XPathToSQL2Converter();
+        String s = c.convert("/jcr:root/nodes//element(*, my:type)");
+        System.out.println(s);
+
 //        Node n = session.getRootNode().addNode("testQuery");
 //        session.save();
 //        QueryManager qm = session.getWorkspace().getQueryManager();
@@ -26,6 +33,38 @@ public class XPathTest {
 //        String stat = q.getStatement();
     }
 
+/*
+
+TODO: support text()?
+
+query:
+axes ["order by" (orderElement [{"ascending"|"descending"}]),...]
+
+axes:
+axis [,...]
+
+axis:
+{ // | / } { pathElement | * | element( { * | pathElement }, nodeType ) | attribute |
"(" attributeList ")" } [ "[“ condition "]“ ]
+
+attributeList:
+attribute [ | attribute ,... ]
+
+condition:
+attribute | jcr:like(attribute, )
+
+attribute:
+@nameElement
+
+
+
+*/
+
+    // Type constraint
+    // Property constraint
+    // Path constraint
+    // Column specifier
+    // Ordering specifier
+
     // Axes
     // child (in abbreviated syntax this is the default axis, represented simply by /, the
location path separator).
     // descendant-or-self (abbreviated syntax: //).
@@ -34,6 +73,8 @@ public class XPathTest {
     // Predicates
     // //element(*, employee)[@secretary and @assistant]
 
+    // Column Specifier
+
     // SELECT * FROM nt:base
     // //*
 
@@ -46,11 +87,50 @@ public class XPathTest {
     // SELECT my:title, my:text FROM my:type
     // //element(*, my:type)/(@my:title | @my:text)
 
+
+
+
+    // Type Constraint
+
     // SELECT * FROM my:type WHERE jcr:path LIKE '/nodes[%]/%'
     // /jcr:root/nodes//element(*, my:type)
 
+    // SELECT * FROM my:type WHERE jcr:path LIKE '/some[%]/nodes[%]'
+    // /jcr:root/some/element(nodes, my:type)
+
+    // SELECT * FROM my:type WHERE jcr:path = '/some/nodes'
+    // /jcr:root/some[1]/element(nodes, my:type)[1]
+
+    // SELECT * FROM my:type WHERE jcr:path LIKE '/some[%]/nodes[%]/%' AND NOT jcr:path LIKE
'/some[%]/nodes[%]/%/%'
+    // /jcr:root/some/nodes/element(*, my:type)
+
+    // SELECT * FROM my:type WHERE jcr:path LIKE '/some[%]/nodes[%]' OR jcr:path LIKE '/some[%]/nodes[%]/%'
+    // /jcr:root/some/nodes//element(*, my:type)
+
+    // SELECT * FROM my:type WHERE jcr:path = '/some/nodes' OR jcr:path LIKE '/some/nodes/%'
+    // /jcr:root/some[1]/nodes[1]//element(*, my:type)
+
+    // Property Constraint
+
     // SELECT * FROM my:type WHERE my:title='JSR 170'
     // //element(*, my:type)[@my:title = 'JSR 170']
+    // /jcr:root/document/para[jcr:like(@title,'%Java%')]
+
+    // my:title IS NOT NULL
+    // @my:title
+
+    // my:title IS NULL
+    // not(@my:title)
+
+    // my:title LIKE 'JSR 170%'
+    // jcr:like(@my:title, 'JSR 170%')
+
+    // CONTAINS(*, 'JSR 170')
+    // jcr:contains(., 'JSR 170')
+
+    // STRING: =, != (<>), <, <=, >, >=, jcr:like()(LIKE)
+    // LONG, DOUBLE, DATE: =, != (<>), <, <=, >, >=
+    // NAME, PATH, REFERENCE, BOOLEAN: =, != (<>)
 
     // SELECT * FROM my:type WHERE jcr:path LIKE '/some[%]/nodes[%]'
     // /jcr:root/some/element(nodes, my:type)
@@ -85,9 +165,43 @@ public class XPathTest {
     // SELECT * FROM my:type ORDER BY my:date DESC, my:title ASC
     // //element(*, my:type) order by @my:date descending, @my:title ascending
 
-    // SELECT * FROM my:type WHERE
-    // CONTAINS(*, 'jcr') ORDER BY jcr:score DESC
+    // SELECT * FROM my:type WHERE CONTAINS(*, 'jcr') ORDER BY jcr:score DESC
     // //element(*, my:type)[jcr:contains(., 'jcr')] order by jcr:score() descending
 
-    //
+    // root
+    // relation
+
+    // order (order list, ascending/descending, function(property) or property)
+
+    // textsearch
+    // exact (property=value)
+    // nodetype (nodetype match)
+    // and, or, not
+
+    // location
+    // /foo  -> descendants = false, nameTest = foo<br>
+    // //foo -> descendants = true, nameTest = foo<br>
+    // //*   -> descendants = true, nameTest = null<br>
+    // /*    -> descendants = false, nameTest = null<br>
+    // /     -> descendants = false, nameTest = ""
+
+    // path
+    // deref
+
+    // prop_function (upper-case, lower-case)
+
+    // XXX Selects all immediate child elements with tag XXX
+    // *       Selects all immediate child elements (but not character data within the element)
+    // ../TITLE        Selects the TITLE children of the parent element
+    // XXX[@AAA]       Selects all XXX child elements having an attribute named AAA
+    // *[last()]       Selects the last child of the current element
+    // */ZZZ   Selects all grandchild ZZZ elements
+    // XXX[ZZZ]        Selects all child XXX elements that have a child ZZZ
+    // XXX[@WIDTH and not(@WIDTH="20")]        Selects all child XXX elements that have a
WIDTH attribute whose value is not "20"
+    // /*      Selects the outermost element of the document
+    // //TITLE Selects all TITLE elements anywhere in the document
+    // ancestor::SECTION       Selects the innermost containing SECTION element
+    // ancestor::SECTION/@TITLE        Selects the TITLE attribute of the innermost containing
SECTION element
+    // ./@*    Selects all attributes of the current element
+
 }

Added: jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryXpathTest.txt
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryXpathTest.txt?rev=1298361&view=auto
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryXpathTest.txt (added)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryXpathTest.txt Thu Mar
 8 11:17:01 2012
@@ -0,0 +1,20 @@
+# Syntax:
+# * lines starting with "#" are remarks.
+# * lines starting with "xpath" are xpath queries, followed by expected sql2 query
+# * use ascii character only
+
+xpath //*
+select * from nt:base
+
+xpath //element(*, my:type)
+select * from my:type
+
+xpath //element(*, my:type)/@my:title
+select my:title from my:type
+
+xpath //element(*, my:type)/(@my:title | @my:text)
+select my:title, my:text from my:type
+
+xpath /jcr:root/nodes//element(*, my:type)
+select * from my:type where jcr:path like '/nodes/%'
+



Mime
View raw message