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 al...@apache.org on 2014/04/02 21:04:22 UTC

svn commit: r1584132 - in /jackrabbit/oak/trunk/oak-lucene/src: main/java/org/apache/jackrabbit/oak/plugins/index/lucene/ test/java/org/apache/jackrabbit/oak/plugins/index/lucene/

Author: alexparvulescu
Date: Wed Apr  2 19:04:22 2014
New Revision: 1584132

URL: http://svn.apache.org/r1584132
Log:
OAK-1668 Lucene should not serve queries for what it doesn't index

Added:
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexExclusionQueryTest.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java?rev=1584132&r1=1584131&r2=1584132&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndex.java Wed Apr  2 19:04:22 2014
@@ -28,6 +28,8 @@ import static org.apache.jackrabbit.oak.
 import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_PROPERTY_NAME;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldNames.PATH;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.FieldNames.PATH_SELECTOR;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.EXCLUDE_PROPERTY_NAMES;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.INCLUDE_PROPERTY_TYPES;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.INDEX_DATA_CHILD_NAME;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PERSISTENCE_FILE;
 import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PERSISTENCE_NAME;
@@ -56,6 +58,8 @@ import java.util.List;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 
+import javax.jcr.PropertyType;
+
 import org.apache.jackrabbit.oak.api.PropertyValue;
 import org.apache.jackrabbit.oak.plugins.index.aggregate.NodeAggregator;
 import org.apache.jackrabbit.oak.plugins.index.lucene.util.MoreLikeThisHelper;
@@ -67,11 +71,11 @@ import org.apache.jackrabbit.oak.query.f
 import org.apache.jackrabbit.oak.query.fulltext.FullTextTerm;
 import org.apache.jackrabbit.oak.query.fulltext.FullTextVisitor;
 import org.apache.jackrabbit.oak.spi.query.Cursor;
-import org.apache.jackrabbit.oak.spi.query.Filter;
-import org.apache.jackrabbit.oak.spi.query.PropertyValues;
 import org.apache.jackrabbit.oak.spi.query.Cursors.PathCursor;
+import org.apache.jackrabbit.oak.spi.query.Filter;
 import org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction;
 import org.apache.jackrabbit.oak.spi.query.IndexRow;
+import org.apache.jackrabbit.oak.spi.query.PropertyValues;
 import org.apache.jackrabbit.oak.spi.query.QueryIndex;
 import org.apache.jackrabbit.oak.spi.query.QueryIndex.FulltextQueryIndex;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
@@ -329,7 +333,7 @@ public class LuceneIndex implements Full
         // we only restrict non-full-text conditions if there is
         // no relative property in the full-text constraint
         boolean nonFullTextConstraints = parent.isEmpty();
-        String plan = getQuery(filter, null, nonFullTextConstraints, analyzer) + " ft:(" + ft + ")";
+        String plan = getQuery(filter, null, nonFullTextConstraints, analyzer, getIndexDef(root)) + " ft:(" + ft + ")";
         if (!parent.isEmpty()) {
             plan += " parent:" + parent;
         }
@@ -363,7 +367,7 @@ public class LuceneIndex implements Full
                     IndexSearcher searcher = new IndexSearcher(reader);
                     List<LuceneResultRow> rows = new ArrayList<LuceneResultRow>();
                     Query query = getQuery(filter, reader,
-                            nonFullTextConstraints, analyzer);
+                            nonFullTextConstraints, analyzer, getIndexDef(root));
 
                     // TODO OAK-828
                     HashSet<String> seenPaths = new HashSet<String>();
@@ -428,10 +432,11 @@ public class LuceneIndex implements Full
      *            path, node type, and so on) should be added to the Lucene
      *            query
      * @param analyzer the Lucene analyzer used for building the fulltext query
+     * @param indexDefinition nodestate that contains the index definition
      * @return the Lucene query
      */
     private static Query getQuery(Filter filter, IndexReader reader,
-            boolean nonFullTextConstraints, Analyzer analyzer) {
+            boolean nonFullTextConstraints, Analyzer analyzer, NodeState indexDefinition) {
         List<Query> qs = new ArrayList<Query>();
         FullTextExpression ft = filter.getFullTextConstraint();
         if (ft == null) {
@@ -461,9 +466,9 @@ public class LuceneIndex implements Full
                     throw new RuntimeException(e);
                 }
             }
-        }
-        else if (nonFullTextConstraints) {
-            addNonFullTextConstraints(qs, filter, reader, analyzer);
+        } else if (nonFullTextConstraints) {
+            addNonFullTextConstraints(qs, filter, reader, analyzer,
+                    indexDefinition);
         }
         if (qs.size() == 0) {
             return new MatchAllDocsQuery();
@@ -479,7 +484,7 @@ public class LuceneIndex implements Full
     }
 
     private static void addNonFullTextConstraints(List<Query> qs,
-            Filter filter, IndexReader reader, Analyzer analyzer) {
+            Filter filter, IndexReader reader, Analyzer analyzer, NodeState indexDefinition) {
         if (!filter.matchesAllTypes()) {
             addNodeTypeConstraints(qs, filter);
         }
@@ -526,11 +531,12 @@ public class LuceneIndex implements Full
                 continue;
             }
 
-            String name = pr.propertyName;
-            if (name.contains("/")) {
-                // lucene cannot handle child-level property restrictions
+            // check excluded properties and types
+            if (isExcludedProperty(pr, indexDefinition)) {
                 continue;
             }
+
+            String name = pr.propertyName;
             if ("rep:excerpt".equals(name)) {
                 continue;
             }
@@ -617,6 +623,44 @@ public class LuceneIndex implements Full
         return token;
     }
 
+    private static boolean isExcludedProperty(PropertyRestriction pr,
+            NodeState definition) {
+        String name = pr.propertyName;
+        if (name.contains("/")) {
+            // lucene cannot handle child-level property restrictions
+            return true;
+        }
+
+        // check name
+        for (String e : definition.getStrings(EXCLUDE_PROPERTY_NAMES)) {
+            if (e.equalsIgnoreCase(name)) {
+                return true;
+            }
+        }
+
+        // check type
+        Integer type = null;
+        if (pr.first != null) {
+            type = pr.first.getType().tag();
+        } else if (pr.last != null) {
+            type = pr.last.getType().tag();
+        } else if (pr.list != null && !pr.list.isEmpty()) {
+            type = pr.list.get(0).getType().tag();
+        }
+        if (type != null) {
+            boolean isIn = false;
+            for (String e : definition.getStrings(INCLUDE_PROPERTY_TYPES)) {
+                if (PropertyType.valueFromName(e) == type) {
+                    isIn = true;
+                }
+            }
+            if (!isIn) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private static void addReferenceConstraint(String uuid, List<Query> qs,
             IndexReader reader) {
         if (reader == null) {

Added: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexExclusionQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexExclusionQueryTest.java?rev=1584132&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexExclusionQueryTest.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexExclusionQueryTest.java Wed Apr  2 19:04:22 2014
@@ -0,0 +1,109 @@
+/*
+ * 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.plugins.index.lucene;
+
+import static com.google.common.collect.ImmutableList.of;
+import static javax.jcr.PropertyType.TYPENAME_BINARY;
+import static javax.jcr.PropertyType.TYPENAME_STRING;
+import static org.apache.jackrabbit.JcrConstants.JCR_LASTMODIFIED;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
+import static org.apache.jackrabbit.oak.api.Type.DATE;
+import static org.apache.jackrabbit.oak.api.Type.STRINGS;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.EXCLUDE_PROPERTY_NAMES;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.INCLUDE_PROPERTY_TYPES;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.TYPE_LUCENE;
+
+import java.util.List;
+
+import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.api.ContentRepository;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
+import org.apache.jackrabbit.oak.query.AbstractQueryTest;
+import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
+import org.junit.Test;
+
+/**
+ * Tests the {@link LuceneIndexProvider} exclusion settings
+ */
+public class LuceneIndexExclusionQueryTest extends AbstractQueryTest {
+
+    private static final String NOT_IN = "notincluded";
+
+    @Override
+    protected void createTestIndexNode() throws Exception {
+        Tree lucene = createTestIndexNode(root.getTree("/"), TYPE_LUCENE);
+        lucene.setProperty(INCLUDE_PROPERTY_TYPES,
+                of(TYPENAME_BINARY, TYPENAME_STRING), STRINGS);
+        lucene.setProperty(EXCLUDE_PROPERTY_NAMES, of(NOT_IN), STRINGS);
+        root.commit();
+    }
+
+    @Override
+    protected ContentRepository createRepository() {
+        return new Oak().with(new InitialContent())
+                .with(new OpenSecurityProvider())
+                .with(new LowCostLuceneIndexProvider())
+                .with(new LuceneIndexEditorProvider())
+                .createContentRepository();
+    }
+
+    @Test
+    public void ignoreByType() throws Exception {
+        Tree content = root.getTree("/").addChild("content");
+        Tree one = content.addChild("one");
+        one.setProperty(JCR_PRIMARYTYPE, NT_UNSTRUCTURED);
+        one.setProperty(JCR_LASTMODIFIED, "2013-04-01T09:58:03.231Z", DATE);
+        one.setProperty("jcr:title", "abc");
+
+        Tree two = content.addChild("two");
+        two.setProperty(JCR_PRIMARYTYPE, NT_UNSTRUCTURED);
+        two.setProperty(JCR_LASTMODIFIED, "2014-04-01T09:58:03.231Z", DATE);
+        two.setProperty("jcr:title", "abc");
+
+        root.commit();
+
+        String query = "/jcr:root/content//*[jcr:contains(., 'abc' )"
+                + " and (@" + JCR_LASTMODIFIED
+                + " > xs:dateTime('2014-04-01T08:58:03.231Z')) ]";
+        assertQuery(query, "xpath", of("/content/two"));
+    }
+
+    @Test
+    public void ignoreByName() throws Exception {
+        final List<String> expected = of("/content/two");
+
+        Tree content = root.getTree("/").addChild("content");
+        Tree one = content.addChild("one");
+        one.setProperty(JCR_PRIMARYTYPE, NT_UNSTRUCTURED);
+        one.setProperty("jcr:title", "abc");
+        one.setProperty(NOT_IN, "azerty");
+
+        Tree two = content.addChild("two");
+        two.setProperty(JCR_PRIMARYTYPE, NT_UNSTRUCTURED);
+        two.setProperty("jcr:title", "abc");
+        two.setProperty(NOT_IN, "querty");
+
+        root.commit();
+
+        String query = "/jcr:root/content//*[jcr:contains(., 'abc' )"
+                + " and (@" + NOT_IN + " = 'querty') ]";
+        assertQuery(query, "xpath", expected);
+    }
+
+}

Propchange: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexExclusionQueryTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java?rev=1584132&r1=1584131&r2=1584132&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexTest.java Wed Apr  2 19:04:22 2014
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.oak.plugins.index.lucene;
 
+import static javax.jcr.PropertyType.TYPENAME_STRING;
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
@@ -26,8 +27,6 @@ import static org.apache.jackrabbit.oak.
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_NODE_TYPES;
 import static org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent.INITIAL_CONTENT;
 
-import javax.jcr.PropertyType;
-
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider;
 import org.apache.jackrabbit.oak.query.QueryEngineSettings;
@@ -63,7 +62,8 @@ public class LuceneIndexTest {
     @Test
     public void testLucene() throws Exception {
         NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
-        newLuceneIndexDefinition(index, "lucene", null);
+        newLuceneIndexDefinition(index, "lucene",
+                ImmutableSet.of(TYPENAME_STRING));
 
         NodeState before = builder.getNodeState();
         builder.setProperty("foo", "bar");
@@ -85,7 +85,8 @@ public class LuceneIndexTest {
     @Test
     public void testLucene2() throws Exception {
         NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
-        newLuceneIndexDefinition(index, "lucene", null);
+        newLuceneIndexDefinition(index, "lucene",
+                ImmutableSet.of(TYPENAME_STRING));
 
         NodeState before = builder.getNodeState();
         builder.setProperty("foo", "bar");
@@ -116,7 +117,7 @@ public class LuceneIndexTest {
     public void testLucene3() throws Exception {
         NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
         newLuceneIndexDefinition(index, "lucene",
-                ImmutableSet.of(PropertyType.TYPENAME_STRING));
+                ImmutableSet.of(TYPENAME_STRING));
 
         NodeState before = builder.getNodeState();
         builder.setProperty("foo", "bar");