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/02/29 15:41:57 UTC

svn commit: r1295136 - in /jackrabbit/sandbox/jackrabbit-microkernel/src: main/java/org/apache/jackrabbit/query/qom/ main/java/org/apache/jackrabbit/query/qom/tree/ test/resources/

Author: thomasm
Date: Wed Feb 29 14:41:56 2012
New Revision: 1295136

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

Modified:
    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/ComparisonImpl.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/UpperCaseImpl.java
    jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt

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=1295136&r1=1295135&r2=1295136&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 Wed Feb 29 14:41:56 2012
@@ -32,7 +32,9 @@ import org.apache.jackrabbit.query.qom.t
 import org.apache.jackrabbit.query.qom.tree.DescendantNodeJoinConditionImpl;
 import org.apache.jackrabbit.query.qom.tree.EquiJoinConditionImpl;
 import org.apache.jackrabbit.query.qom.tree.FullTextSearchScoreImpl;
+import org.apache.jackrabbit.query.qom.tree.LengthImpl;
 import org.apache.jackrabbit.query.qom.tree.LiteralImpl;
+import org.apache.jackrabbit.query.qom.tree.LowerCaseImpl;
 import org.apache.jackrabbit.query.qom.tree.NodeLocalNameImpl;
 import org.apache.jackrabbit.query.qom.tree.NodeNameImpl;
 import org.apache.jackrabbit.query.qom.tree.OrderingImpl;
@@ -43,6 +45,7 @@ import org.apache.jackrabbit.query.qom.t
 import org.apache.jackrabbit.query.qom.tree.SameNodeJoinConditionImpl;
 import org.apache.jackrabbit.query.qom.tree.SelectorImpl;
 import org.apache.jackrabbit.query.qom.tree.SourceImpl;
+import org.apache.jackrabbit.query.qom.tree.UpperCaseImpl;
 
 /**
  * The implementation of the corresponding JCR interface. Lifecycle: use the
@@ -178,6 +181,24 @@ public class QueryObjectModelImpl implem
                 return true;
             }
 
+            @Override
+            public boolean visit(LengthImpl node) {
+                node.setQuery(query);
+                return super.visit(node);
+            }
+
+            @Override
+            public boolean visit(UpperCaseImpl node) {
+                node.setQuery(query);
+                return super.visit(node);
+            }
+
+            @Override
+            public boolean visit(LowerCaseImpl node) {
+                node.setQuery(query);
+                return super.visit(node);
+            }
+
         }.visit(this);
         source.init(this);
     }

Modified: jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ComparisonImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ComparisonImpl.java?rev=1295136&r1=1295135&r2=1295136&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ComparisonImpl.java (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/main/java/org/apache/jackrabbit/query/qom/tree/ComparisonImpl.java Wed Feb 29 14:41:56 2012
@@ -21,6 +21,7 @@ package org.apache.jackrabbit.query.qom.
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.query.qom.Comparison;
+import org.h2.message.DbException;
 
 /**
  * The implementation of the corresponding JCR interface.
@@ -64,11 +65,12 @@ public class ComparisonImpl extends Cons
             case GE:
             case GT:
             case LE:
-            case LIKE:
             case LT:
                 return operand1.currentValue() .equals(operand2.currentValue());
             case NE:
                 return !operand1.currentValue().equals(operand2.currentValue());
+            case LIKE:
+                return evaluateLike(v1, v2);
             }
             // TODO Auto-generated method stub
             return false;
@@ -78,6 +80,11 @@ public class ComparisonImpl extends Cons
         }
     }
 
+    private boolean evaluateLike(Value v1, Value v2) throws RepositoryException {
+        LikePattern like = new LikePattern(v2.getString());
+        return like.matches(v1.getString());
+    }
+
     @Override
     boolean accept(QOMVisitor v) {
         return v.visit(this);
@@ -87,4 +94,118 @@ public class ComparisonImpl extends Cons
         return operator.formatSql(operand1.toString(), operand2.toString());
     }
 
+    /**
+     * A pattern matcher.
+     */
+    public static class LikePattern {
+
+        // TODO LIKE: optimize condition to '=' when no patterns are used, or 'between x and x+1'
+        // TODO LIKE: what to do for invalid patterns (patterns ending with a backslash)
+
+        private static final int MATCH = 0, ONE = 1, ANY = 2;
+
+        private String patternString;
+        private boolean invalidPattern;
+        private char[] patternChars;
+        private int[] patternTypes;
+        private int patternLength;
+
+        LikePattern(String pattern) {
+            initPattern(pattern);
+        }
+
+        boolean matches(String value) {
+            if (invalidPattern) {
+                return false;
+            }
+            return compareAt(value, 0, 0, value.length(), patternChars, patternTypes);
+        }
+
+        private boolean compare(char[] pattern, String s, int pi, int si) {
+            return pattern[pi] == s.charAt(si);
+        }
+
+        private boolean compareAt(String s, int pi, int si, int sLen, char[] pattern, int[] types) {
+            for (; pi < patternLength; pi++) {
+                switch (types[pi]) {
+                case MATCH:
+                    if ((si >= sLen) || !compare(pattern, s, pi, si++)) {
+                        return false;
+                    }
+                    break;
+                case ONE:
+                    if (si++ >= sLen) {
+                        return false;
+                    }
+                    break;
+                case ANY:
+                    if (++pi >= patternLength) {
+                        return true;
+                    }
+                    while (si < sLen) {
+                        if (compare(pattern, s, pi, si) && compareAt(s, pi, si, sLen, pattern, types)) {
+                            return true;
+                        }
+                        si++;
+                    }
+                    return false;
+                default:
+                    DbException.throwInternalError();
+                }
+            }
+            return si == sLen;
+        }
+
+        private void initPattern(String p) {
+            patternLength = 0;
+            if (p == null) {
+                patternTypes = null;
+                patternChars = null;
+                return;
+            }
+            int len = p.length();
+            patternChars = new char[len];
+            patternTypes = new int[len];
+            boolean lastAny = false;
+            for (int i = 0; i < len; i++) {
+                char c = p.charAt(i);
+                int type;
+                if (c == '\\') {
+                    if (i >= len - 1) {
+                        invalidPattern = true;
+                        return;
+                    }
+                    c = p.charAt(++i);
+                    type = MATCH;
+                    lastAny = false;
+                } else if (c == '%') {
+                    if (lastAny) {
+                        continue;
+                    }
+                    type = ANY;
+                    lastAny = true;
+                } else if (c == '_') {
+                    type = ONE;
+                } else {
+                    type = MATCH;
+                    lastAny = false;
+                }
+                patternTypes[patternLength] = type;
+                patternChars[patternLength++] = c;
+            }
+            for (int i = 0; i < patternLength - 1; i++) {
+                if ((patternTypes[i] == ANY) && (patternTypes[i + 1] == ONE)) {
+                    patternTypes[i] = ONE;
+                    patternTypes[i + 1] = ANY;
+                }
+            }
+            patternString = new String(patternChars, 0, patternLength);
+        }
+
+        public String toString() {
+            return patternString;
+        }
+
+    }
+
 }

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=1295136&r1=1295135&r2=1295136&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 Wed Feb 29 14:41:56 2012
@@ -48,7 +48,11 @@ public class LengthImpl extends DynamicO
 
     @Override
     Value currentValue() throws RepositoryException {
-        String value = propertyValue.currentValue().getString();
+        Value v = propertyValue.currentValue();
+        if (v == null) {
+            return null;
+        }
+        String value = v.getString();
         return query.getValueFactory().createValue(value.length());
     }
 

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=1295136&r1=1295135&r2=1295136&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 Wed Feb 29 14:41:56 2012
@@ -48,8 +48,12 @@ public class LowerCaseImpl extends Dynam
 
     @Override
     Value currentValue() throws RepositoryException {
-        Value value = operand.currentValue();
-        return query.getValueFactory().createValue(value.getString().toUpperCase());
+        Value v = operand.currentValue();
+        if (v == null) {
+            return null;
+        }
+        String value = v.getString();
+        return query.getValueFactory().createValue(value.toLowerCase());
     }
 
 }

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=1295136&r1=1295135&r2=1295136&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 Wed Feb 29 14:41:56 2012
@@ -48,8 +48,12 @@ public class UpperCaseImpl extends Dynam
 
     @Override
     Value currentValue() throws RepositoryException {
-        Value value = operand.currentValue();
-        return query.getValueFactory().createValue(value.getString().toUpperCase());
+        Value v = operand.currentValue();
+        if (v == null) {
+            return null;
+        }
+        String value = v.getString();
+        return query.getValueFactory().createValue(value.toUpperCase());
     }
 
 }

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=1295136&r1=1295135&r2=1295136&view=diff
==============================================================================
--- jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt (original)
+++ jackrabbit/sandbox/jackrabbit-microkernel/src/test/resources/queryTest.txt Wed Feb 29 14:41:56 2012
@@ -34,3 +34,41 @@ select * from [nt:base] where x is null
 - "test"
 - "test2"
 
++ "test": { "name": "Hello" }
++ "test2": { "name": "World!" }
++ "test3": { "name": "Hallo" }
++ "test4": { "name": "10%" }
++ "test5": { "name": "10 percent" }
+
+select * from [nt:base] where length(name) = 5
+/test
+/test3
+
+select * from [nt:base] where upper(name) = 'HELLO'
+/test
+
+select * from [nt:base] where lower(name) = 'world!'
+/test2
+
+select * from [nt:base] where name like 'W%'
+/test2
+
+select * from [nt:base] where name like '%o_%'
+/test2
+
+select * from [nt:base] where name like 'H_llo'
+/test
+/test3
+
+select * from [nt:base] where upper(name) like 'H_LLO'
+/test
+/test3
+
+select * from [nt:base] where upper(name) like 'H\_LLO'
+
+select * from [nt:base] where upper(name) like '10%'
+/test4
+/test5
+
+select * from [nt:base] where upper(name) like '10\%'
+/test4