You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2014/02/27 11:18:25 UTC

svn commit: r1572496 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/query/ main/java/org/apache/jackrabbit/oak/query/ast/ main/java/org/apache/jackrabbit/oak/query/xpath/ test/java/org/apache/jackrabbit/oak/plugins/index/p...

Author: thomasm
Date: Thu Feb 27 10:18:24 2014
New Revision: 1572496

URL: http://svn.apache.org/r1572496
Log:
OAK-1325 Support native pass-through queries (e.g. Lucene)

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NativeFunctionImpl.java
    jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_native.txt
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.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/AstElementFactory.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexQueryTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java?rev=1572496&r1=1572495&r2=1572496&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java Thu Feb 27 10:18:24 2014
@@ -46,6 +46,7 @@ import org.apache.jackrabbit.oak.query.a
 import org.apache.jackrabbit.oak.query.ast.LengthImpl;
 import org.apache.jackrabbit.oak.query.ast.LiteralImpl;
 import org.apache.jackrabbit.oak.query.ast.LowerCaseImpl;
+import org.apache.jackrabbit.oak.query.ast.NativeFunctionImpl;
 import org.apache.jackrabbit.oak.query.ast.NodeLocalNameImpl;
 import org.apache.jackrabbit.oak.query.ast.NodeNameImpl;
 import org.apache.jackrabbit.oak.query.ast.NotImpl;
@@ -194,6 +195,13 @@ public class QueryImpl implements Query 
             }
 
             @Override
+            public boolean visit(NativeFunctionImpl node) {
+                node.setQuery(query);
+                node.bindSelector(source);
+                return super.visit(node);
+            }
+
+            @Override
             public boolean visit(FullTextSearchScoreImpl node) {
                 node.setQuery(query);
                 node.bindSelector(source);

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=1572496&r1=1572495&r2=1572496&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 Thu Feb 27 10:18:24 2014
@@ -513,6 +513,17 @@ public class SQL2Parser {
             } else {
                 c = factory.descendantNode(getOnlySelectorName(), name);
             }
+        } else if ("NATIVE".equalsIgnoreCase(functionName)) {
+            String selectorName;
+            if (currentTokenType == IDENTIFIER) {
+                selectorName = readName();
+                read(",");
+            } else {
+                selectorName = getOnlySelectorName();
+            }
+            String language = readString().getValue(Type.STRING);
+            read(",");
+            c = factory.nativeFunction(selectorName, language, parseStaticOperand());
         } else {
             return null;
         }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java?rev=1572496&r1=1572495&r2=1572496&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElementFactory.java Thu Feb 27 10:18:24 2014
@@ -148,4 +148,8 @@ public class AstElementFactory {
         return new InImpl(left, list);
     }
 
+    public NativeFunctionImpl nativeFunction(String selectorName, String language, StaticOperandImpl expression) {
+        return new NativeFunctionImpl(selectorName, language, expression);
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java?rev=1572496&r1=1572495&r2=1572496&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitor.java Thu Feb 27 10:18:24 2014
@@ -79,4 +79,6 @@ public interface AstVisitor {
 
     boolean visit(UpperCaseImpl node);
 
+    boolean visit(NativeFunctionImpl nativeFunctionImpl);
+
 }
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java?rev=1572496&r1=1572495&r2=1572496&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java Thu Feb 27 10:18:24 2014
@@ -63,6 +63,14 @@ public abstract class AstVisitorBase imp
         node.getFullTextSearchExpression().accept(this);
         return true;
     }
+    
+    /**
+     * Calls accept on the static operand in the native search constraint.
+     */
+    @Override
+    public boolean visit(NativeFunctionImpl node) {
+        return true;
+    }
 
     /**
      * Calls accept on the two sources and the join condition in the join node.

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NativeFunctionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NativeFunctionImpl.java?rev=1572496&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NativeFunctionImpl.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NativeFunctionImpl.java Thu Feb 27 10:18:24 2014
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.oak.query.ast;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex.FulltextQueryIndex;
+
+/**
+ * A native function condition.
+ */
+public class NativeFunctionImpl extends ConstraintImpl {
+    
+    public static final String NATIVE_PREFIX = "native*";
+    
+    private final String selectorName;
+    private final String language;
+    private final StaticOperandImpl nativeSearchExpression;
+    private SelectorImpl selector;
+    
+    NativeFunctionImpl(String selectorName, String language, StaticOperandImpl expression) {
+        this.selectorName = selectorName;
+        this.language = language;
+        this.nativeSearchExpression = expression;
+    }
+    
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("native(");
+        builder.append(quote(selectorName));
+        builder.append(", ");
+        builder.append(quote(language));
+        builder.append(", ");
+        builder.append(getNativeSearchExpression());
+        builder.append(')');
+        return builder.toString();
+    }
+    
+    @Override
+    public boolean evaluate() {
+        // disable evaluation if a fulltext index is used,
+        // and because we don't know how to process native
+        // conditions
+        if (!(selector.getIndex() instanceof FulltextQueryIndex)) {
+            throw new IllegalArgumentException("No full-text index was found that can process the condition " + toString());
+        }
+        // we assume the index only returns the requested entries
+        return true;
+    }
+
+    @Override
+    public Set<PropertyExistenceImpl> getPropertyExistenceConditions() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Map<DynamicOperandImpl, Set<StaticOperandImpl>> getInMap() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public void restrict(FilterImpl f) {
+        if (f.getSelector().equals(selector)) {
+            PropertyValue v = nativeSearchExpression.currentValue();
+            f.restrictProperty(NATIVE_PREFIX + language, Operator.EQUAL, v);
+        }
+    }
+
+    @Override
+    public void restrictPushDown(SelectorImpl s) {
+        if (s.equals(selector)) {
+            selector.restrictSelector(this);
+        }
+    }
+
+    @Override
+    public Set<SelectorImpl> getSelectors() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    boolean accept(AstVisitor v) {
+        return v.visit(this);
+    }
+
+    public void bindSelector(SourceImpl source) {
+        selector = source.getExistingSelector(selectorName);
+    }
+    
+    public StaticOperandImpl getNativeSearchExpression() {
+        return nativeSearchExpression;
+    }
+
+}

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java?rev=1572496&r1=1572495&r2=1572496&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java Thu Feb 27 10:18:24 2014
@@ -325,6 +325,40 @@ abstract class Expression {
         }
     
     }    
+    
+    /**
+     * A native call.
+     */
+    static class NativeFunction extends Expression {
+        
+        final String selector;
+        final Expression language, expression;
+    
+        NativeFunction(String selector, Expression language, Expression expression) {
+            this.selector = selector;
+            this.language = language;
+            this.expression = expression;
+        }
+    
+        @Override
+        public String toString() {
+            StringBuilder buff = new StringBuilder("native(");
+            buff.append(selector);
+            buff.append(", ").append(language).append(", ").append(expression).append(')');
+            return buff.toString();
+        }
+    
+        @Override
+        boolean isCondition() {
+            return true;
+        }
+        
+        @Override
+        boolean isName() {
+            return false;
+        }
+    
+    }    
 
     /**
      * A function call.

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java?rev=1572496&r1=1572495&r2=1572496&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java Thu Feb 27 10:18:24 2014
@@ -606,6 +606,14 @@ public class XPathToSQL2Converter {
         } else if ("jcr:deref".equals(functionName)) {
              // TODO maybe support jcr:deref
              throw getSyntaxError("jcr:deref is not supported");
+        } else if ("rep:native".equals(functionName)) {
+            String selectorName = currentSelector.name;
+            Expression language = parseExpression();
+            read(",");
+            Expression expr = parseExpression();
+            read(")");
+            Expression.NativeFunction f = new Expression.NativeFunction(selectorName, language, expr);
+            return f;
         } else if ("rep:similar".equals(functionName)) {
              // TODO maybe support rep:similar
              throw getSyntaxError("rep:similar is not supported");

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexQueryTest.java?rev=1572496&r1=1572495&r2=1572496&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexQueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexQueryTest.java Thu Feb 27 10:18:24 2014
@@ -50,6 +50,11 @@ public class PropertyIndexQueryTest exte
     }
 
     @Test
+    public void nativeQuery() throws Exception {
+        test("sql2_native.txt");
+    }
+
+    @Test
     public void xpath() throws Exception {
         test("xpath.txt");
     }

Added: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_native.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_native.txt?rev=1572496&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_native.txt (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/sql2_native.txt Thu Feb 27 10:18:24 2014
@@ -0,0 +1,45 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Syntax:
+# * lines that start with spaces belong to the previous line
+# * lines starting with "#" are remarks.
+# * lines starting with "select" are queries, followed by expected results and an empty line
+# * lines starting with "explain" are followed by expected query plan and an empty line
+# * lines starting with "sql1" are run using the sql1 language
+# * lines starting with "xpath2sql" are just converted from xpath to sql2
+# * all other lines are are committed into the microkernel (line by line)
+# * new tests are typically be added on top, after the syntax docs
+# * use ascii character only
+
+commit / + "test": { "a": { "name": "Hello" }, "b": { "name" : "World" }}
+
+select [jcr:path] from [nt:base]
+  where native('solr', 'name:(Hello OR World)')
+java.lang.IllegalArgumentException: No full-text index was found that can process the condition native([nt:base], [solr], cast('name:(Hello OR World)' as string))
+
+select [jcr:path] from [nt:base] as a
+  where native(a, 'solr', 'path_child:\/test _val_:"recip(rord(name),1,2,3)"')
+java.lang.IllegalArgumentException: No full-text index was found that can process the condition native([a], [solr], cast('path_child:\/test _val_:"recip(rord(name),1,2,3)"' as string))
+
+select [jcr:path] from [nt:base]
+  where native('solr', 'path_child:\/test _val_:"recip(rord(name),1,2,3)"')
+java.lang.IllegalArgumentException: No full-text index was found that can process the condition native([nt:base], [solr], cast('path_child:\/test _val_:"recip(rord(name),1,2,3)"' as string))
+
+xpath2sql //*[rep:native('solr', 'xyz')]
+select [jcr:path], [jcr:score], *
+  from [nt:base] as a
+  where native(a, 'solr', 'xyz')
+  /* xpath ... */
\ No newline at end of file