Author: thomasm
Date: Thu Jul 27 11:56:28 2017
New Revision: 1803166

URL: http://svn.apache.org/viewvc?rev=1803166&view=rev
Log:
OAK-6502 Property index: include/exclude key pattern list (escaping)

Added:
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePatternPropertyIndexTests.java
Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePattern.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java?rev=1803166&r1=1803165&r2=1803166&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
 Thu Jul 27 11:56:28 2017
@@ -109,31 +109,46 @@ class PropertyIndex implements QueryInde
     PropertyIndex(MountInfoProvider mountInfoProvider) {
         this.mountInfoProvider = mountInfoProvider;
     }
-
+    
     static Set<String> encode(PropertyValue value, ValuePattern pattern) {
+        return encode(read(value, pattern));
+    }
+    
+    static Set<String> read(PropertyValue value, ValuePattern pattern) {
         if (value == null) {
             return null;
         }
         Set<String> values = new HashSet<String>();
         for (String v : value.getValue(Type.STRINGS)) {
-            try {
+            if (!pattern.matches(v)) {
+                continue;
+            }
+            values.add(v);
+        }
+        return values;
+    }
+
+    static Set<String> encode(Set<String> set) {
+        if (set == null || set.isEmpty()) {
+            return set;
+        }
+        try {
+            Set<String> values = new HashSet<String>();
+            for(String v : set) {
                 if (v.length() > MAX_STRING_LENGTH) {
                     v = v.substring(0, MAX_STRING_LENGTH);
                 }
-                if (!pattern.matches(v)) {
-                    continue;
-                }
                 if (v.isEmpty()) {
                     v = EMPTY_TOKEN;
                 } else {
                     v = URLEncoder.encode(v, Charsets.UTF_8.name());
                 }
                 values.add(v);
-            } catch (UnsupportedEncodingException e) {
-                throw new IllegalStateException("UTF-8 is unsupported", e);
             }
+            return values;
+        } catch (UnsupportedEncodingException e) {
+            throw new IllegalStateException("UTF-8 is unsupported", e);
         }
-        return values;
     }
 
     private PropertyIndexPlan getPlan(NodeState root, Filter filter) {

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java?rev=1803166&r1=1803165&r2=1803166&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndexPlan.java
 Thu Jul 27 11:56:28 2017
@@ -24,7 +24,6 @@ import static java.util.Collections.empt
 import static 
org.apache.jackrabbit.oak.plugins.index.IndexConstants.DECLARING_NODE_TYPES;
 import static 
org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_CONTENT_NODE_NAME;
 import static 
org.apache.jackrabbit.oak.plugins.index.IndexConstants.PROPERTY_NAMES;
-import static 
org.apache.jackrabbit.oak.plugins.index.property.PropertyIndex.encode;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -33,13 +32,13 @@ import java.util.Set;
 import org.apache.jackrabbit.oak.api.PropertyValue;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.index.Cursors;
 import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
 import org.apache.jackrabbit.oak.plugins.index.PathFilter;
 import 
org.apache.jackrabbit.oak.plugins.index.property.strategy.IndexStoreStrategy;
 import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
 import org.apache.jackrabbit.oak.spi.mount.Mounts;
 import org.apache.jackrabbit.oak.spi.query.Cursor;
-import org.apache.jackrabbit.oak.plugins.index.Cursors;
 import org.apache.jackrabbit.oak.spi.query.Filter;
 import org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction;
 import org.apache.jackrabbit.oak.spi.query.QueryEngineSettings;
@@ -164,6 +163,7 @@ public class PropertyIndexPlan {
                             continue;
                         }
                     }
+                    values = PropertyIndex.encode(values);
                     double cost = strategies.isEmpty() ? MAX_COST : 0;
                     for (IndexStoreStrategy strategy : strategies) {
                         cost += strategy.count(filter, root, definition,
@@ -243,12 +243,12 @@ public class PropertyIndexPlan {
                 && restriction.first != null
                 && restriction.first.equals(restriction.last)) {
             // "[property] = $value"
-            return encode(restriction.first, pattern);
+            return PropertyIndex.read(restriction.first, pattern);
         } else if (restriction.list != null) {
             // "[property] IN (...)
             Set<String> values = newLinkedHashSet(); // keep order for testing
             for (PropertyValue value : restriction.list) {
-                values.addAll(encode(value, pattern));
+                values.addAll(PropertyIndex.read(value, pattern));
             }
             return values;
         } else {

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePattern.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePattern.java?rev=1803166&r1=1803165&r2=1803166&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePattern.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePattern.java
 Thu Jul 27 11:56:28 2017
@@ -60,7 +60,7 @@ public class ValuePattern {
     }
     
     public boolean matches(String v) {
-        if (v == null) {
+        if (matchesAll() || v == null) {
             return true;
         }
         if (includePrefixes != null) {

Added: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePatternPropertyIndexTests.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePatternPropertyIndexTests.java?rev=1803166&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePatternPropertyIndexTests.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/ValuePatternPropertyIndexTests.java
 Thu Jul 27 11:56:28 2017
@@ -0,0 +1,73 @@
+/*
+ * 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.property;
+
+import static com.google.common.collect.ImmutableList.of;
+import static org.apache.jackrabbit.oak.api.Type.NAMES;
+import static 
org.apache.jackrabbit.oak.plugins.index.IndexConstants.PROPERTY_NAMES;
+import static 
org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_PROPERTY_NAME;
+import static 
org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider.TYPE;
+import static org.junit.Assert.assertTrue;
+
+import javax.jcr.query.Query;
+
+import org.apache.jackrabbit.oak.InitialContent;
+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.index.IndexConstants;
+import org.apache.jackrabbit.oak.query.AbstractQueryTest;
+import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
+import org.junit.Test;
+
+public class ValuePatternPropertyIndexTests extends AbstractQueryTest {
+    private static final String INDEXED_PROPERTY = "indexedProperty";
+    
+    @Override
+    protected ContentRepository createRepository() {
+        return new Oak().with(new InitialContent())
+            .with(new OpenSecurityProvider())
+            .with(new PropertyIndexProvider())
+            .with(new PropertyIndexEditorProvider())
+            .createContentRepository();
+    }
+
+    @Test
+    public void valuePattern() throws Exception {
+//        valuePattern("", "* property test-index");
+//        valuePattern("x", "* property test-index");
+        valuePattern(" ", "* property test-index");
+        valuePattern("-", "* property test-index");
+        valuePattern("/", "* property test-index");
+    }
+    
+    private void valuePattern(String middle, String plan) throws Exception {
+        Tree index = super.createTestIndexNode(root.getTree("/"), TYPE);
+        index.setProperty(PROPERTY_NAMES, of(INDEXED_PROPERTY), NAMES);
+        index.setProperty(IndexConstants.VALUE_INCLUDED_PREFIXES, "hello" + 
middle + "world");
+        index.setProperty(REINDEX_PROPERTY_NAME, true);
+        root.commit();
+        Tree content = root.getTree("/").addChild("content");
+        content.addChild("node1").setProperty(INDEXED_PROPERTY, "hello" + 
middle + "world");
+        content.addChild("node2").setProperty(INDEXED_PROPERTY, "hello");
+        root.commit();
+        String statement = "explain select * from [nt:base] where [" + 
INDEXED_PROPERTY + "] = 'hello" + middle + "world'";
+        String result = executeQuery(statement, Query.JCR_SQL2, false, 
false).toString();
+        assertTrue(result, result.indexOf(plan) >= 0);
+    }
+    
+}


Reply via email to