DATACOUCH-251 - Wrap base where criteria with parenthesis for OR expressions.

Base criteria for the query should be wrapped before adding the entity filter criteria so the priority of filtering is clear.
This commit is contained in:
Subhashni Balakrishnan
2016-11-23 07:51:23 -08:00
committed by Oliver Gierke
parent ce8dd97d66
commit b52dee3a3c
4 changed files with 48 additions and 3 deletions

View File

@@ -18,11 +18,13 @@ package org.springframework.data.couchbase.repository;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.data.couchbase.IntegrationTestApplicationConfig;
import org.springframework.data.couchbase.repository.config.RepositoryOperationsMapping;
import org.springframework.data.couchbase.repository.support.CouchbaseRepositoryFactory;
@@ -56,10 +58,28 @@ public class N1qlCouchbaseRepositoryTests {
private PartyPagingRepository repository;
private PartyRepository partyRepository;
private ItemRepository itemRepository;
private final String KEY_PARTY = "Party1";
private final String KEY_ITEM = "Item1";
@Before
public void setup() throws Exception {
RepositoryFactorySupport factory = new CouchbaseRepositoryFactory(operationsMapping, indexManager);
repository = factory.getRepository(PartyPagingRepository.class);
partyRepository = factory.getRepository(PartyRepository.class);
itemRepository = factory.getRepository(ItemRepository.class);
partyRepository.save(new Party(KEY_PARTY, "partyName", "MatchingDescription", null, 0, null));
itemRepository.save(new Item(KEY_ITEM, "MatchingDescription"));
}
@After
public void cleanUp() {
try { itemRepository.delete(KEY_ITEM); } catch (DataRetrievalFailureException e) {}
try { partyRepository.delete(KEY_PARTY); } catch (DataRetrievalFailureException e) {}
}
@Test
@@ -104,7 +124,7 @@ public class N1qlCouchbaseRepositoryTests {
Pageable pageable = new PageRequest(0, 8);
Page<Party> page1 = repository.findAll(pageable);
assertEquals(15, page1.getTotalElements()); //12 generated parties + 3 specifically crafted party
assertEquals(16, page1.getTotalElements()); //12 generated parties + 4 specifically crafted party
assertEquals(8, page1.getNumberOfElements());
}
@@ -113,7 +133,7 @@ public class N1qlCouchbaseRepositoryTests {
Pageable pageable = new PageRequest(0, 8, Sort.Direction.DESC, "attendees");
Page<Party> page1 = repository.findAll(pageable);
assertEquals(15, page1.getTotalElements()); //12 generated parties + 3 specifically crafted party
assertEquals(16, page1.getTotalElements()); //12 generated parties + 4 specifically crafted party
assertEquals(8, page1.getNumberOfElements());
List<Party> parties = page1.getContent();
@@ -125,4 +145,10 @@ public class N1qlCouchbaseRepositoryTests {
previousAttendees = party.getAttendees();
}
}
@Test
public void testWrapWhereCriteria() {
List<Party> partyList = partyRepository.findByDescriptionOrName("MatchingDescription", "partyName");
assertTrue(partyList.size() == 1);
}
}

View File

@@ -54,4 +54,6 @@ public interface PartyRepository extends CouchbaseRepository<Party, String> {
" AND `desc` NOT LIKE '%' || $1 || '%' AND `desc` != \"this is \\\"$excluded\\\"\"")
List<Party> findAllWithPositionalParamsAndQuotedNamedParams(@Param("excluded") String ex, @Param("included") String inc, @Param("min") long min);
List<Party> findByDescriptionOrName(String description, String name);
}

View File

@@ -20,6 +20,7 @@ import static com.couchbase.client.java.query.Select.select;
import static com.couchbase.client.java.query.dsl.Expression.i;
import static com.couchbase.client.java.query.dsl.Expression.path;
import static com.couchbase.client.java.query.dsl.Expression.s;
import static com.couchbase.client.java.query.dsl.Expression.x;
import static com.couchbase.client.java.query.dsl.functions.AggregateFunctions.count;
import static com.couchbase.client.java.query.dsl.functions.MetaFunctions.meta;
import static com.couchbase.client.java.query.dsl.functions.StringFunctions.lower;
@@ -149,7 +150,7 @@ public class N1qlUtils {
if (baseWhereCriteria == null) {
baseWhereCriteria = typeSelector;
} else {
baseWhereCriteria = baseWhereCriteria.and(typeSelector);
baseWhereCriteria = x("(" + baseWhereCriteria.toString() + ")").and(typeSelector);
}
return baseWhereCriteria;
}

View File

@@ -1,5 +1,6 @@
package org.springframework.data.couchbase.repository.query.support;
import static com.couchbase.client.java.query.dsl.Expression.*;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
@@ -132,4 +133,19 @@ public class N1qlUtilsTest {
assertEquals(expectedDefault, real);
assertEquals(expectedTypeKey, realWithTypeKey);
}
@Test
public void testCreateWhereFilterForEntityWithBaseCriteria() throws Exception {
String expected = "(field1 >= 30 OR field2 = \"foo\") AND `_class` = \"java.lang.String\"";
CouchbaseConverter converter = mock(CouchbaseConverter.class);
when(converter.getTypeKey()).thenReturn("_class");
EntityMetadata metadata = mock(EntityMetadata.class);
when(metadata.getJavaType()).thenReturn(String.class);
String real = N1qlUtils.createWhereFilterForEntity(
x("field1").gte(30).or(x("field2").eq(s("foo"))),
converter, metadata).toString();
assertEquals(expected, real);
}
}