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);
+ }
+
+}