blob: 15abc9bd86a9db8c4da63c1bac868940638534cb [file] [log] [blame]
/*
* 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 org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
import static org.apache.jackrabbit.oak.api.Type.NAME;
import static org.apache.jackrabbit.oak.plugins.index.lucene.TestUtil.useV2;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.Calendar;
import java.util.List;
import org.apache.jackrabbit.oak.InitialContentHelper;
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.search.FulltextIndexConstants;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
import org.apache.jackrabbit.oak.query.AbstractQueryTest;
import org.apache.jackrabbit.oak.query.QueryEngineSettings;
import org.apache.jackrabbit.oak.spi.commit.Observer;
import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
import org.junit.Test;
import com.google.common.collect.Lists;
public class LuceneIndexQueryTestSQL2OptimisationTest extends AbstractQueryTest {
Oak getOakRepo() {
LowCostLuceneIndexProvider provider = new LowCostLuceneIndexProvider();
return new Oak(new MemoryNodeStore(InitialContentHelper.INITIAL_CONTENT))
.with(new OpenSecurityProvider())
.with((QueryIndexProvider) provider)
.with((Observer) provider)
.with(new LuceneIndexEditorProvider())
.with(new QueryEngineSettings() {
@Override
public boolean isSql2Optimisation() {
return true;
}
});
}
@Override
protected ContentRepository createRepository() {
return getOakRepo().createContentRepository();
}
@Override
protected void createTestIndexNode() throws Exception {
Tree index = root.getTree("/");
Tree indexDefn = createTestIndexNode(index, LuceneIndexConstants.TYPE_LUCENE);
useV2(indexDefn);
indexDefn.setProperty(LuceneIndexConstants.TEST_MODE, true);
indexDefn.setProperty(FulltextIndexConstants.EVALUATE_PATH_RESTRICTION, true);
Tree props = TestUtil.newRulePropTree(indexDefn, "nt:base");
props.getParent().setProperty(FulltextIndexConstants.INDEX_NODE_NAME, true);
TestUtil.enablePropertyIndex(props, "c1/p", false);
TestUtil.enableForFullText(props, FulltextIndexConstants.REGEX_ALL_PROPS, true);
TestUtil.enablePropertyIndex(props, "a/name", false);
TestUtil.enablePropertyIndex(props, "b/name", false);
TestUtil.enableFunctionIndex(props, "length([name])");
TestUtil.enableFunctionIndex(props, "lower([name])");
TestUtil.enableFunctionIndex(props, "upper([name])");
root.commit();
}
@Test
public void oak2660() throws Exception {
final String name = "name";
final String surname = "surname";
final String description = "description";
final String added = "added";
final String yes = "yes";
Tree t;
// re-define the lucene index
t = root.getTree("/oak:index/" + TEST_INDEX_NAME);
assertTrue(t.exists());
t.remove();
root.commit();
assertFalse(root.getTree("/oak:index/" + TEST_INDEX_NAME).exists());
t = root.getTree("/");
Tree indexDefn = createTestIndexNode(t, LuceneIndexConstants.TYPE_LUCENE);
useV2(indexDefn);
indexDefn.setProperty(LuceneIndexConstants.TEST_MODE, true);
Tree props = TestUtil.newRulePropTree(indexDefn, NT_UNSTRUCTURED);
TestUtil.enablePropertyIndex(props, name, false);
TestUtil.enableForFullText(props, surname, false);
TestUtil.enableForFullText(props, description, false);
TestUtil.enableForOrdered(props, added);
root.commit();
// creating the dataset
List<String> expected = Lists.newArrayList();
Tree content = root.getTree("/").addChild("content");
t = content.addChild("test1");
t.setProperty(JCR_PRIMARYTYPE, NT_UNSTRUCTURED, NAME);
t.setProperty(name, yes);
t.setProperty(surname, yes);
t.setProperty(description, yes);
t.setProperty(added, Calendar.getInstance());
expected.add(t.getPath());
t = content.addChild("test2");
t.setProperty(JCR_PRIMARYTYPE, NT_UNSTRUCTURED, NAME);
t.setProperty(name, yes);
t.setProperty(surname, yes);
t.setProperty(description, "no");
t.setProperty(added, Calendar.getInstance());
expected.add(t.getPath());
t = content.addChild("test3");
t.setProperty(JCR_PRIMARYTYPE, NT_UNSTRUCTURED, NAME);
t.setProperty(name, yes);
t.setProperty(surname, "no");
t.setProperty(description, "no");
t.setProperty(added, Calendar.getInstance());
expected.add(t.getPath());
t = content.addChild("test4");
t.setProperty(JCR_PRIMARYTYPE, NT_UNSTRUCTURED, NAME);
t.setProperty(name, "no");
t.setProperty(surname, yes);
t.setProperty(description, "no");
t.setProperty(added, Calendar.getInstance());
expected.add(t.getPath());
t = content.addChild("test5");
t.setProperty(JCR_PRIMARYTYPE, NT_UNSTRUCTURED, NAME);
t.setProperty(name, "no");
t.setProperty(surname, "no");
t.setProperty(description, yes);
t.setProperty(added, Calendar.getInstance());
expected.add(t.getPath());
t = content.addChild("test6");
t.setProperty(JCR_PRIMARYTYPE, NT_UNSTRUCTURED, NAME);
t.setProperty(name, "no");
t.setProperty(surname, "no");
t.setProperty(description, "no");
t.setProperty(added, Calendar.getInstance());
root.commit();
// asserting the initial state
for (String s : expected) {
assertTrue("wrong initial state", root.getTree(s).exists());
}
final String statement =
"SELECT * " +
"FROM [" + NT_UNSTRUCTURED + "] AS c " +
"WHERE " +
"( " +
"c.[" + name + "] = '" + yes + "' " +
"OR CONTAINS(c.[" + surname + "], '" + yes + "') " +
"OR CONTAINS(c.[" + description + "], '" + yes + "') " +
") " +
"AND ISDESCENDANTNODE(c, '" + content.getPath() + "') " +
"ORDER BY " + added + " DESC ";
assertQuery(statement, SQL2, expected);
}
}