/*
* (C) Copyright 2011-2012 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed 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.
*
* Contributors:
* Thierry Martins
* Florent Guillaume
* Marwane Kalam-Alami
*/
package org.nuxeo.ecm.platform.query.api;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.SortInfo;
import org.nuxeo.ecm.core.api.impl.DocumentModelImpl;
import org.nuxeo.ecm.core.test.CoreFeature;
import org.nuxeo.ecm.core.test.annotations.Granularity;
import org.nuxeo.ecm.core.test.annotations.RepositoryConfig;
import org.nuxeo.ecm.platform.query.nxql.NXQLQueryBuilder;
import org.nuxeo.runtime.api.Framework;
import org.nuxeo.runtime.test.runner.Deploy;
import org.nuxeo.runtime.test.runner.Features;
import org.nuxeo.runtime.test.runner.FeaturesRunner;
import org.nuxeo.runtime.test.runner.LocalDeploy;
@RunWith(FeaturesRunner.class)
@Features(CoreFeature.class)
@RepositoryConfig(cleanup = Granularity.METHOD)
@Deploy("org.nuxeo.ecm.platform.query.api")
@LocalDeploy({ "org.nuxeo.ecm.platform.query.api.test:test-schemas-contrib.xml",
"org.nuxeo.ecm.platform.query.api.test:test-pageprovider-contrib.xml" })
public class TestNXQLQueryBuilder {
@Test
public void testBuildIsNullQuery() throws Exception {
PageProviderService pps = Framework.getService(PageProviderService.class);
assertNotNull(pps);
WhereClauseDefinition whereClause = pps.getPageProviderDefinition("ADVANCED_SEARCH").getWhereClause();
SortInfo sortInfos = new SortInfo("dc:title", true);
String[] params = { "foo" };
DocumentModel model = new DocumentModelImpl("/", "doc", "AdvancedSearch");
model.setPropertyValue("search:title", "bar");
String query = NXQLQueryBuilder.getQuery(model, whereClause, params, sortInfos);
assertEquals("SELECT * FROM Document WHERE dc:title LIKE 'bar' AND (ecm:parentId = 'foo') ORDER BY dc:title",
query);
model.setPropertyValue("search:isPresent", Boolean.TRUE);
query = NXQLQueryBuilder.getQuery(model, whereClause, params, sortInfos);
assertEquals(
"SELECT * FROM Document WHERE dc:title LIKE 'bar' AND dc:modified IS NULL AND (ecm:parentId = 'foo') ORDER BY dc:title",
query);
// only boolean available in schema without default value
model.setPropertyValue("search:isPresent", Boolean.FALSE);
query = NXQLQueryBuilder.getQuery(model, whereClause, params, sortInfos);
assertEquals(
"SELECT * FROM Document WHERE dc:title LIKE 'bar' AND dc:modified IS NOT NULL AND (ecm:parentId = 'foo') ORDER BY dc:title",
query);
query = NXQLQueryBuilder.getQuery("SELECT * FROM ? WHERE ? = '?'",
new Object[] { "Document", "dc:title", null }, false, true, null);
assertEquals("SELECT * FROM Document WHERE dc:title = ''", query);
}
@Test
public void testBuildInQuery() throws Exception {
PageProviderService pps = Framework.getService(PageProviderService.class);
WhereClauseDefinition whereClause = pps.getPageProviderDefinition("TEST_IN").getWhereClause();
DocumentModel model = new DocumentModelImpl("/", "doc", "File");
model.setPropertyValue("dc:subjects", new String[] { "foo", "bar" });
String query = NXQLQueryBuilder.getQuery(model, whereClause, null);
assertEquals("SELECT * FROM Document WHERE dc:title IN ('foo', 'bar')", query);
model.setPropertyValue("dc:subjects", new String[]{"foo"});
query = NXQLQueryBuilder.getQuery(model, whereClause, null);
assertEquals("SELECT * FROM Document WHERE dc:title = 'foo'", query);
// criteria with no values are removed
model.setPropertyValue("dc:subjects", new String[]{});
query = NXQLQueryBuilder.getQuery(model, whereClause, null);
assertEquals("SELECT * FROM Document", query);
}
@Test
public void testBuildInIntegersQuery() throws Exception {
PageProviderService pps = Framework.getService(PageProviderService.class);
WhereClauseDefinition whereClause = pps.getPageProviderDefinition("TEST_IN_INTEGERS").getWhereClause();
DocumentModel model = new DocumentModelImpl("/", "doc", "AdvancedSearch");
@SuppressWarnings("boxing")
Integer[] array1 = new Integer[] { 1, 2, 3 };
model.setPropertyValue("search:integerlist", array1);
String query = NXQLQueryBuilder.getQuery(model, whereClause, null);
assertEquals("SELECT * FROM Document WHERE size IN (1, 2, 3)", query);
@SuppressWarnings("boxing")
Integer[] array2 = new Integer[] { 1 };
model.setPropertyValue("search:integerlist", array2);
query = NXQLQueryBuilder.getQuery(model, whereClause, null);
assertEquals("SELECT * FROM Document WHERE size = 1", query);
// criteria with no values are removed
Integer[] array3 = new Integer[0];
model.setPropertyValue("search:integerlist", array3);
query = NXQLQueryBuilder.getQuery(model, whereClause, null);
assertEquals("SELECT * FROM Document", query);
// arrays of long work too
@SuppressWarnings("boxing")
Long[] array4 = new Long[] { 1L, 2L, 3L };
model.setPropertyValue("search:integerlist", array4);
query = NXQLQueryBuilder.getQuery(model, whereClause, null);
assertEquals("SELECT * FROM Document WHERE size IN (1, 2, 3)", query);
// lists work too
@SuppressWarnings("boxing")
List<Long> list = Arrays.asList(1L, 2L, 3L);
model.setPropertyValue("search:integerlist", (Serializable) list);
query = NXQLQueryBuilder.getQuery(model, whereClause, null);
assertEquals("SELECT * FROM Document WHERE size IN (1, 2, 3)", query);
}
@Test
public void testBuildInIntegersEmptyQuery() throws Exception {
String pattern = "SELECT * FROM Document WHERE ecm:parentId = ? and ecm:currentLifeCycleState IN (?)";
Object[] params = new Object[] { "docId", "" };
String query = NXQLQueryBuilder.getQuery(pattern, params, true, true, null);
assertEquals("SELECT * FROM Document WHERE ecm:parentId = 'docId' and ecm:currentLifeCycleState IN ('')", query);
params = new Object[] { "docId", new String[] { "foo", "bar" } };
query = NXQLQueryBuilder.getQuery(pattern, params, true, true, null);
assertEquals(
"SELECT * FROM Document WHERE ecm:parentId = 'docId' and ecm:currentLifeCycleState IN ('foo', 'bar')",
query);
}
// @Since 5.9
@Test
public void testSortedColumnQuery() throws Exception {
String pattern = "SELECT * FROM Document WHERE SORTED_COLUMN IS NOT NULL";
String query = NXQLQueryBuilder.getQuery(pattern, null, true, true, null);
assertEquals("SELECT * FROM Document WHERE ecm:uuid IS NOT NULL", query);
SortInfo sortInfo = new SortInfo("dc:title", true);
query = NXQLQueryBuilder.getQuery(pattern, null, true, true, null, sortInfo);
assertEquals("SELECT * FROM Document WHERE dc:title IS NOT NULL ORDER BY dc:title", query);
sortInfo = new SortInfo("dc:created", true);
SortInfo sortInfo2 = new SortInfo("dc:title", true);
query = NXQLQueryBuilder.getQuery(pattern, null, true, true, null, sortInfo, sortInfo2);
assertEquals("SELECT * FROM Document WHERE dc:created IS NOT NULL ORDER BY dc:created , dc:title", query);
}
// @Since 5.9.2
@Test
public void testCustomSelectStatement() throws Exception {
PageProviderService pps = Framework.getService(PageProviderService.class);
assertNotNull(pps);
WhereClauseDefinition whereClause = pps.getPageProviderDefinition("CUSTOM_SELECT_STATEMENT").getWhereClause();
String[] params = { "foo" };
DocumentModel model = new DocumentModelImpl("/", "doc", "AdvancedSearch");
model.setPropertyValue("search:title", "bar");
String query = NXQLQueryBuilder.getQuery(model, whereClause, params);
assertEquals("SELECT * FROM Note WHERE dc:title LIKE 'bar' AND (ecm:parentId = 'foo')", query);
}
// @Since 7.3
@Test
public void testPredicatesWithHint() throws Exception {
PageProviderService pps = Framework.getService(PageProviderService.class);
assertNotNull(pps);
WhereClauseDefinition whereClause = pps.getPageProviderDefinition("PREDICATE_WITH_HINT").getWhereClause();
DocumentModel model = new DocumentModelImpl("/", "doc", "AdvancedSearch");
model.setPropertyValue("search:title", "foo");
String query = NXQLQueryBuilder.getQuery(model, whereClause, null);
assertEquals("SELECT * FROM Note WHERE " + //
"/*+ES: INDEX(dc:title.custom) */ dc:title LIKE 'foo' AND " + //
"/*+ES: ANALYZER(fr_analyzer) */ ecm:fulltext.dc:title = 'foo' AND " + //
"/*+ES: INDEX(dc:title.fulltext) OPERATOR(fuzzy) */ ecm:fulltext = 'foo' AND " + //
"ecm:fulltext.dc:title = 'foo' AND " + //
"ecm:fulltext.dc:description = 'foo'" , query);
}
@Test
public void iCanFindNamedParameters() {
// Given a regexp when I put named parameters
String pattern = "SELECT * FROM Document WHERE ecm:parentId = "
+ ":parentIdVal AND ecm:currentLifeCycleState IN (:param1, "
+ ":param2) AND dc:title = \":pouet\" AND dc:description = "
+ "':desc' AND dc:description = 'ihfifehi:desc'";
String query = pattern.replaceAll(NXQLQueryBuilder.REGEXP_EXCLUDE_DOUBLE_QUOTE, StringUtils.EMPTY);
query = query.replaceAll(NXQLQueryBuilder.REGEXP_EXCLUDE_QUOTE, StringUtils.EMPTY);
Pattern p1 = Pattern.compile(NXQLQueryBuilder.REGEXP_NAMED_PARAMETER);
Matcher m1 = p1.matcher(query);
List<String> matches = new ArrayList<String>();
// I have to find them
while (m1.find()) {
matches.add(m1.group().substring(m1.group().indexOf(":") + 1));
}
assertEquals(3, matches.size());
assertEquals("parentIdVal", matches.get(0));
assertEquals("param1", matches.get(1));
assertEquals("param2", matches.get(2));
}
@Test
public void iCanReplacePattern() {
// Given a regexp when I put named parameters
String pattern1 = "SELECT * FROM Document WHERE dc:title = :myTitle";
String pattern2 = "SELECT * FROM Document WHERE dc:title = :title";
String pattern3 = "SELECT * FROM Document WHERE dc:title = :title OR dc:title = :titleLonger";
String pattern4 = "SELECT * FROM Document WHERE dc:title = :titleLongest OR dc:title = :title OR dc:title = :titleLonger";
String pattern5 = "SELECT * FROM Document WHERE dc:title = :titleLonger OR dc:title = :title";
String replacedPattern1 = NXQLQueryBuilder.buildPattern(pattern1, ":title", "'test'");
String replacedPattern2 = NXQLQueryBuilder.buildPattern(pattern2, ":title", "'test'");
String replacedPattern3 = NXQLQueryBuilder.buildPattern(pattern3, ":title", "'test'");
String replacedPattern4 = NXQLQueryBuilder.buildPattern(pattern4, ":title", "'test'");
String replacedPattern5 = NXQLQueryBuilder.buildPattern(pattern5, ":title", "'test'");
assertEquals("SELECT * FROM Document WHERE dc:title = :myTitle", replacedPattern1);
assertEquals("SELECT * FROM Document WHERE dc:title = 'test'", replacedPattern2);
assertEquals("SELECT * FROM Document WHERE dc:title = 'test' OR dc:title = :titleLonger", replacedPattern3);
assertEquals("SELECT * FROM Document WHERE dc:title = :titleLongest OR dc:title = 'test' OR dc:title = :titleLonger", replacedPattern4);
assertEquals("SELECT * FROM Document WHERE dc:title = :titleLonger OR dc:title = 'test'", replacedPattern5);
}
}