You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2012/03/12 13:47:17 UTC

svn commit: r1299653 - in /jackrabbit/sandbox/jackrabbit-microkernel/src: main/java/org/apache/jackrabbit/query/ main/java/org/apache/jackrabbit/query/qom/ main/java/org/apache/jackrabbit/query/qom/tree/ main/java/org/apache/jackrabbit/query/reader/ te...

Author: thomasm
Date: Mon Mar 12 12:47:16 2012
New Revision: 1299653

URL: http://svn.apache.org/viewvc?rev=1299653&view=rev
Log:
Query implementation (WIP)

Modified:
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/QueryEngine.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/RowImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ColumnImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DynamicOperandImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchScoreImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LengthImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LowerCaseImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeLocalNameImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeNameImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/OrderingImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyExistenceImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyValueImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/UpperCaseImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingCursor.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/test/java/org/apache/jackrabbit/query/QueryTest.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/QueryEngine.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/QueryEngine.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/QueryEngine.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/QueryEngine.java Mon Mar 12 12:47:16 2012
@@ -22,6 +22,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import javax.jcr.RepositoryException;
 import javax.jcr.ValueFactory;
+import javax.jcr.query.Row;
 import org.apache.jackrabbit.commons.SimpleValueFactory;
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.query.qom.QueryObjectModelFactoryImpl;
@@ -46,7 +47,7 @@ public class QueryEngine {
         return new QueryEngine(mk);
     }
 
-    public Iterator<String> executeQuery(String query, Map<String, String> bindings) throws RepositoryException {
+    public Iterator<? extends Row> executeQuery(String query, Map<String, String> bindings) throws RepositoryException {
         QueryObjectModelImpl q = parserSQL2.createQueryObjectModel(query);
         q.setMicroKernel(mk);
         if (bindings != null) {

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/RowImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/RowImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/RowImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/RowImpl.java Mon Mar 12 12:47:16 2012
@@ -16,16 +16,28 @@
  */
 package org.apache.jackrabbit.query;
 
-import javax.jcr.ItemNotFoundException;
 import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.query.Row;
+import org.apache.jackrabbit.query.qom.QueryObjectModelImpl;
 
 /**
- * The implementation of the corresponding JCR interface.
+ * A query result row that keeps all data in memory.
  */
-public class RowImpl implements Row {
+public class RowImpl implements Row, Comparable<RowImpl> {
+
+    private final QueryObjectModelImpl qom;
+    private final String[] paths;
+    private final Value[] values;
+    private final Value[] orderValues;
+
+    public RowImpl(QueryObjectModelImpl qom, String[] paths, Value[] values, Value[] orderValues) {
+        this.qom = qom;
+        this.paths = paths;
+        this.values = values;
+        this.orderValues = orderValues;
+    }
 
     public Node getNode() throws RepositoryException {
         // TODO
@@ -38,13 +50,14 @@ public class RowImpl implements Row {
     }
 
     public String getPath() throws RepositoryException {
-        // TODO
-        return null;
+        if (paths.length > 0) {
+            throw new RepositoryException("More than one selector");
+        }
+        return paths[0];
     }
 
     public String getPath(String selectorName) throws RepositoryException {
-        // TODO
-        return null;
+        return paths[qom.getSelectorIndex(selectorName)];
     }
 
     public double getScore() throws RepositoryException {
@@ -57,14 +70,19 @@ public class RowImpl implements Row {
         return 0;
     }
 
-    public Value getValue(String columnName) throws ItemNotFoundException, RepositoryException {
-        // TODO
-        return null;
+    public Value getValue(String columnName) throws RepositoryException {
+        return values[qom.getColumnIndex(columnName)];
     }
 
     public Value[] getValues() throws RepositoryException {
-        // TODO
-        return null;
+        Value[] v2 = new Value[values.length];
+        System.arraycopy(values, 0, v2, 0, v2.length);
+        return v2;
+    }
+
+    @Override
+    public int compareTo(RowImpl o) {
+        return qom.compareRows(orderValues, o.orderValues);
     }
 
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/QueryObjectModelImpl.java Mon Mar 12 12:47:16 2012
@@ -13,7 +13,9 @@
  */
 package org.apache.jackrabbit.query.qom;
 
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import javax.jcr.Node;
@@ -21,9 +23,11 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
 import javax.jcr.query.QueryResult;
+import javax.jcr.query.Row;
 import javax.jcr.query.qom.QueryObjectModel;
 import org.apache.jackrabbit.commons.SimpleValueFactory;
 import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.query.RowImpl;
 import org.apache.jackrabbit.query.qom.tree.BindVariableValueImpl;
 import org.apache.jackrabbit.query.qom.tree.ChildNodeImpl;
 import org.apache.jackrabbit.query.qom.tree.ChildNodeJoinConditionImpl;
@@ -61,11 +65,11 @@ public class QueryObjectModelImpl implem
     private final OrderingImpl[] orderings;
     private final ColumnImpl[] columns;
     final HashMap<String, Value> bindVariableMap = new HashMap<String, Value>();
+    final ArrayList<SelectorImpl> selectors = new ArrayList<SelectorImpl>();
     private boolean explain;
     private long limit;
     private long offset;
     private boolean prepared;
-
     private ValueFactory valueFactory = new SimpleValueFactory();
 
     public QueryObjectModelImpl(SourceImpl source, ConstraintImpl constraint, OrderingImpl[] orderings,
@@ -207,6 +211,9 @@ public class QueryObjectModelImpl implem
 
         }.visit(this);
         source.init(this);
+        for (int i = 0; i < columns.length; i++) {
+            columns[i].bindSelector(source);
+        }
     }
 
     public ColumnImpl[] getColumns() {
@@ -279,13 +286,57 @@ public class QueryObjectModelImpl implem
         this.explain = explain;
     };
 
-    public Iterator<String> executeQuery(String revisionId) {
+    public Iterator<? extends Row> executeQuery(String revisionId) {
         prepare();
         if (explain) {
-            return Arrays.asList(source.getPlan()).iterator();
-        } else {
-            return new ResultIterator(revisionId);
+            String plan = source.getPlan();
+            RowImpl r = new RowImpl(this, null, new Value[] { valueFactory.createValue(plan) }, null);
+            return Arrays.asList(r).iterator();
+        }
+        RowIterator it = new RowIterator(revisionId);
+        if (orderings == null) {
+            return it;
+        }
+        // TODO "order by" is not necessary if the used index returns rows in the same order
+        ArrayList<RowImpl> list = new ArrayList<RowImpl>();
+        while (it.hasNext()) {
+            RowImpl r = it.next();
+            list.add(r);
+        }
+        Collections.sort(list);
+        return list.iterator();
+    }
+
+    public int compareRows(Value[] orderValues, Value[] orderValues2) {
+        int comp = 0;
+        for (int i=0, size = orderings.length; i < size; i++) {
+            Value a = orderValues[i];
+            Value b = orderValues2[i];
+            // TODO order by: currently use string compare
+            try {
+                String as = a == null ? null : a.getString();
+                String bs = b == null ? null : b.getString();
+                if (as == null || bs == null) {
+                    if (as == bs) {
+                        comp = 0;
+                    } else if (as == null) {
+                        // TODO order by: nulls first, last, low or high?
+                        comp = 1;
+                    }
+                } else {
+                    comp = as.compareTo(bs);
+                }
+            } catch (RepositoryException e) {
+                throw new RuntimeException(e);
+            }
+            if (comp != 0) {
+                if (orderings[i].isDescending()) {
+                    comp = -comp;
+                }
+                break;
+            }
         }
+        return comp;
     }
 
     private void prepare() {
@@ -295,13 +346,13 @@ public class QueryObjectModelImpl implem
         source.prepare(mk);
     }
 
-    class ResultIterator implements Iterator<String> {
+    class RowIterator implements Iterator<RowImpl> {
 
         private final String revisionId;
-        private String current;
+        private RowImpl current;
         private boolean started, end;
 
-        ResultIterator(String revisionId) {
+        RowIterator(String revisionId) {
             this.revisionId = revisionId;
         }
 
@@ -316,7 +367,7 @@ public class QueryObjectModelImpl implem
             while (true) {
                 if (source.next()) {
                     if (constraint == null || constraint.evaluate()) {
-                        current = source.currentPath();
+                        current = currentRow();
                         break;
                     }
                 } else {
@@ -339,14 +390,14 @@ public class QueryObjectModelImpl implem
         }
 
         @Override
-        public String next() {
+        public RowImpl next() {
             if (end) {
                 return null;
             }
             if (current == null) {
                 fetchNext();
             }
-            String r = current;
+            RowImpl r = current;
             current = null;
             return r;
         }
@@ -358,4 +409,53 @@ public class QueryObjectModelImpl implem
 
     }
 
+    RowImpl currentRow() {
+        try {
+            int selectorCount = selectors.size();
+            String[] paths = new String[selectorCount];
+            for (int i = 0; i < selectorCount; i++) {
+                SelectorImpl s = selectors.get(i);
+                paths[i] = s.currentPath();
+            }
+            int columnCount = columns.length;
+            Value[] values = new Value[columnCount];
+            for (int i = 0; i < columnCount; i++) {
+                ColumnImpl c = columns[i];
+                values[i] = c.currentValue();
+            }
+            Value[] orderValues;
+            if (orderings == null) {
+                orderValues = null;
+            } else {
+                int size = orderings.length;
+                orderValues = new Value[size];
+                for (int i=0; i<size; i++) {
+                    orderValues[i] = orderings[i].getOperand().currentValue();
+                }
+            }
+            return new RowImpl(this, paths, values, orderValues);
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public int getSelectorIndex(String selectorName) throws RepositoryException {
+        for (int i=0, size = selectors.size(); i<size; i++) {
+            if (selectors.get(i).getSelectorName().equals(selectorName)) {
+                return i;
+            }
+        }
+        throw new RepositoryException("Unknown selector: " + selectorName);
+    }
+
+    public int getColumnIndex(String columnName) throws RepositoryException {
+        for (int i=0, size = columns.length; i<size; i++) {
+            ColumnImpl c = columns[i];
+            if (c.getColumnName().equals(columnName)) {
+                return i;
+            }
+        }
+        throw new RepositoryException("Column not found: " + columnName);
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ColumnImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ColumnImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ColumnImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ColumnImpl.java Mon Mar 12 12:47:16 2012
@@ -18,6 +18,7 @@
  */
 package org.apache.jackrabbit.query.qom.tree;
 
+import javax.jcr.Value;
 import javax.jcr.query.qom.Column;
 
 /**
@@ -26,6 +27,7 @@ import javax.jcr.query.qom.Column;
 public class ColumnImpl extends QOMNode implements Column {
 
     private final String selectorName, propertyName, columnName;
+    private SelectorImpl selector;
 
     public ColumnImpl(String selectorName, String propertyName, String columnName) {
         this.selectorName = selectorName;
@@ -59,4 +61,18 @@ public class ColumnImpl extends QOMNode 
         }
     }
 
+    public Value currentValue() {
+        if (propertyName == null) {
+            // TODO for SELECT * FROM queries, currently return the path (for testing only)
+            String p = selector.currentPath();
+            return p == null ? null : query.getValueFactory().createValue(p);
+        }
+        String v = selector.currentNode().getProperty(propertyName);
+        return v == null ? null : query.getValueFactory().createValue(v);
+    }
+
+    public void bindSelector(SourceImpl source) {
+        selector = source.getSelector(selectorName);
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DynamicOperandImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DynamicOperandImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DynamicOperandImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/DynamicOperandImpl.java Mon Mar 12 12:47:16 2012
@@ -22,6 +22,6 @@ import javax.jcr.query.qom.DynamicOperan
 
 public abstract class DynamicOperandImpl extends QOMNode implements DynamicOperand {
 
-    abstract Value currentValue() throws RepositoryException;
+    public abstract Value currentValue() throws RepositoryException;
 
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchScoreImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchScoreImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchScoreImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/FullTextSearchScoreImpl.java Mon Mar 12 12:47:16 2012
@@ -18,7 +18,6 @@
  */
 package org.apache.jackrabbit.query.qom.tree;
 
-import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.query.qom.FullTextSearchScore;
 
@@ -47,7 +46,7 @@ public class FullTextSearchScoreImpl ext
     }
 
     @Override
-    Value currentValue() throws RepositoryException {
+    public Value currentValue() {
         // TODO Auto-generated method stub
         return null;
     }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LengthImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LengthImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LengthImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LengthImpl.java Mon Mar 12 12:47:16 2012
@@ -47,7 +47,7 @@ public class LengthImpl extends DynamicO
     }
 
     @Override
-    Value currentValue() throws RepositoryException {
+    public Value currentValue() throws RepositoryException {
         Value v = propertyValue.currentValue();
         if (v == null) {
             return null;

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LowerCaseImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LowerCaseImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LowerCaseImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/LowerCaseImpl.java Mon Mar 12 12:47:16 2012
@@ -47,7 +47,7 @@ public class LowerCaseImpl extends Dynam
     }
 
     @Override
-    Value currentValue() throws RepositoryException {
+    public Value currentValue() throws RepositoryException {
         Value v = operand.currentValue();
         if (v == null) {
             return null;

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeLocalNameImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeLocalNameImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeLocalNameImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeLocalNameImpl.java Mon Mar 12 12:47:16 2012
@@ -18,7 +18,6 @@
  */
 package org.apache.jackrabbit.query.qom.tree;
 
-import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.query.qom.NodeLocalName;
 
@@ -47,7 +46,7 @@ public class NodeLocalNameImpl extends D
     }
 
     @Override
-    Value currentValue() throws RepositoryException {
+    public Value currentValue() {
         // TODO Auto-generated method stub
         return null;
     }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeNameImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeNameImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeNameImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/NodeNameImpl.java Mon Mar 12 12:47:16 2012
@@ -18,7 +18,6 @@
  */
 package org.apache.jackrabbit.query.qom.tree;
 
-import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.query.qom.NodeName;
 
@@ -47,7 +46,7 @@ public class NodeNameImpl extends Dynami
     }
 
     @Override
-    Value currentValue() throws RepositoryException {
+    public  Value currentValue() {
         // TODO Auto-generated method stub
         return null;
     }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/OrderingImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/OrderingImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/OrderingImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/OrderingImpl.java Mon Mar 12 12:47:16 2012
@@ -54,4 +54,8 @@ public class OrderingImpl extends QOMNod
         }
     }
 
+    public boolean isDescending() {
+        return order == Order.DESCENDING;
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyExistenceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyExistenceImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyExistenceImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyExistenceImpl.java Mon Mar 12 12:47:16 2012
@@ -19,6 +19,7 @@
 package org.apache.jackrabbit.query.qom.tree;
 
 import javax.jcr.query.qom.PropertyExistence;
+import org.apache.jackrabbit.mk.simple.NodeImpl;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -44,7 +45,8 @@ public class PropertyExistenceImpl exten
 
     @Override
     public boolean evaluate() {
-        return selector.currentNode().hasProperty(propertyName);
+        NodeImpl n = selector.currentNode();
+        return n == null ? false : n.hasProperty(propertyName);
     }
 
     @Override

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyValueImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyValueImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyValueImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/PropertyValueImpl.java Mon Mar 12 12:47:16 2012
@@ -56,7 +56,7 @@ public class PropertyValueImpl extends D
     }
 
     @Override
-    Value currentValue() {
+    public Value currentValue() {
         NodeImpl n = selector.currentNode();
         String value = n.getProperty(propertyName);
         if (value == null) {

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/UpperCaseImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/UpperCaseImpl.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/UpperCaseImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/UpperCaseImpl.java Mon Mar 12 12:47:16 2012
@@ -47,7 +47,7 @@ public class UpperCaseImpl extends Dynam
     }
 
     @Override
-    Value currentValue() throws RepositoryException {
+    public Value currentValue() throws RepositoryException {
         Value v = operand.currentValue();
         if (v == null) {
             return null;

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingCursor.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingCursor.java?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingCursor.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/reader/TraversingCursor.java Mon Mar 12 12:47:16 2012
@@ -53,6 +53,9 @@ public class TraversingCursor implements
     @Override
     public NodeImpl currentNode() {
         if (currentNode == null) {
+            if (currentPath == null) {
+                return null;
+            }
             currentNode = NodeImpl.parse(mk.getNodes(currentPath, revisionId));
         }
         return currentNode;
@@ -67,11 +70,13 @@ public class TraversingCursor implements
     public boolean next() {
         currentNode = null;
         if (nodes == null) {
+            currentPath = null;
             return false;
         }
         if (nodes.size() == 0) {
             if (!mk.nodeExists(currentPath, revisionId)) {
                 nodes = null;
+                currentPath = null;
                 return false;
             }
             loadChildren(currentPath, 0);
@@ -101,6 +106,7 @@ public class TraversingCursor implements
            }
         }
         nodes = null;
+        currentPath = null;
         return false;
     }
 

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=1299653&r1=1299652&r2=1299653&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 Mon Mar 12 12:47:16 2012
@@ -20,7 +20,10 @@ import java.io.LineNumberReader;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.util.Iterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
 import javax.jcr.query.InvalidQueryException;
+import javax.jcr.query.Row;
 import org.apache.jackrabbit.mk.MicroKernelFactory;
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.junit.After;
@@ -86,10 +89,11 @@ public class QueryTest {
                     }
                 } else if (line.startsWith("select") || line.startsWith("explain")) {
                     w.println(line);
-                    Iterator<String> result = qe.executeQuery(line, null);
+                    Iterator<? extends Row> result = qe.executeQuery(line, null);
                     boolean readEnd = true;
                     while (result.hasNext()) {
-                        String resultLine = result.next();
+                        Row row = result.next();
+                        String resultLine = readRow(line, row);
                         w.println(resultLine);
                         if (readEnd) {
                             line = r.readLine();
@@ -134,4 +138,17 @@ public class QueryTest {
         }
     }
 
+    private String readRow(String query, Row row) throws RepositoryException {
+        StringBuilder buff = new StringBuilder();
+        Value[] values = row.getValues();
+        for (int i = 0; i < values.length; i++) {
+            if (i > 0) {
+                buff.append(", ");
+            }
+            Value v = values[i];
+            buff.append(v == null ? "null" : v.getString());
+        }
+        return buff.toString();
+    }
+
 }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt?rev=1299653&r1=1299652&r2=1299653&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt Mon Mar 12 12:47:16 2012
@@ -9,30 +9,40 @@
 + "parents": { "p0": {"id": "0"}, "p1": {"id": "1"}, "p2": {"id": "2"}}
 + "children": { "c1": {"p": "1"}, "c2": {"p": "1"}, "c3": {"p": "2"}, "c4": {"p": "3"}}
 
+select id from [nt:base] where id is not null
+"0"
+"1"
+"2"
+
+select id from [nt:base] where id is not null order by id desc
+"2"
+"1"
+"0"
+
 select * from [nt:base] as c right outer join [nt:base] as p on p.id = c.p where p.id is not null
-/parents/p0
-/parents/p1
-/parents/p1
-/parents/p2
+null, /parents/p0
+/children/c1, /parents/p1
+/children/c2, /parents/p1
+/children/c3, /parents/p2
 
 select * from [nt:base] as p left outer join [nt:base] as c on p.id = c.p where p.id is not null
-/parents/p0
-/parents/p1
-/parents/p1
-/parents/p2
+/parents/p0, null
+/parents/p1, /children/c1
+/parents/p1, /children/c2
+/parents/p2, /children/c3
 
 select * from [nt:base] as p left outer join [nt:base] as c on p.id = c.p where p.id is not null and c.p is null
-/parents/p0
+/parents/p0, null
 
 select * from [nt:base] as p left outer join [nt:base] as c on p.id = c.p where p.id is not null and c.p is not null
-/parents/p1
-/parents/p1
-/parents/p2
+/parents/p1, /children/c1
+/parents/p1, /children/c2
+/parents/p2, /children/c3
 
 select * from [nt:base] as p inner join [nt:base] as c on p.id = c.p
-/parents/p1
-/parents/p1
-/parents/p2
+/parents/p1, /children/c1
+/parents/p1, /children/c2
+/parents/p2, /children/c3
 
 explain select * from [nt:base] as p inner join [nt:base] as c on p.id = c.p
 nt:base AS p /* traverse "/" */ INNER JOIN nt:base AS c /* traverse "/" */
@@ -72,12 +82,20 @@ select * from [nt:base] where x is null
 - "test"
 - "test2"
 
-+ "test": { "name": "Hello" }
++ "test": { "name": "hello" }
 + "test2": { "name": "World!" }
 + "test3": { "name": "Hallo" }
 + "test4": { "name": "10%" }
 + "test5": { "name": "10 percent" }
 
+select name from [nt:base] order by upper(name)
+"10 percent"
+"10%"
+"Hallo"
+"hello"
+"World!"
+null
+
 select * from [nt:base] where length(name) = 5
 /test
 /test3
@@ -94,7 +112,7 @@ select * from [nt:base] where name like 
 select * from [nt:base] where name like '%o_%'
 /test2
 
-select * from [nt:base] where name like 'H_llo'
+select * from [nt:base] where name like '__llo'
 /test
 /test3