From b52dee3a3cc4356526f5c279222a475e7f42e4c0 Mon Sep 17 00:00:00 2001 From: Subhashni Balakrishnan Date: Wed, 23 Nov 2016 07:51:23 -0800 Subject: [PATCH] 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. --- .../N1qlCouchbaseRepositoryTests.java | 30 +++++++++++++++++-- .../couchbase/repository/PartyRepository.java | 2 ++ .../repository/query/support/N1qlUtils.java | 3 +- .../query/support/N1qlUtilsTest.java | 16 ++++++++++ 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/integration/java/org/springframework/data/couchbase/repository/N1qlCouchbaseRepositoryTests.java b/src/integration/java/org/springframework/data/couchbase/repository/N1qlCouchbaseRepositoryTests.java index 30d7c26a..26a44d26 100644 --- a/src/integration/java/org/springframework/data/couchbase/repository/N1qlCouchbaseRepositoryTests.java +++ b/src/integration/java/org/springframework/data/couchbase/repository/N1qlCouchbaseRepositoryTests.java @@ -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 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 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 parties = page1.getContent(); @@ -125,4 +145,10 @@ public class N1qlCouchbaseRepositoryTests { previousAttendees = party.getAttendees(); } } + + @Test + public void testWrapWhereCriteria() { + List partyList = partyRepository.findByDescriptionOrName("MatchingDescription", "partyName"); + assertTrue(partyList.size() == 1); + } } diff --git a/src/integration/java/org/springframework/data/couchbase/repository/PartyRepository.java b/src/integration/java/org/springframework/data/couchbase/repository/PartyRepository.java index 082b1ef2..b79dfec2 100644 --- a/src/integration/java/org/springframework/data/couchbase/repository/PartyRepository.java +++ b/src/integration/java/org/springframework/data/couchbase/repository/PartyRepository.java @@ -54,4 +54,6 @@ public interface PartyRepository extends CouchbaseRepository { " AND `desc` NOT LIKE '%' || $1 || '%' AND `desc` != \"this is \\\"$excluded\\\"\"") List findAllWithPositionalParamsAndQuotedNamedParams(@Param("excluded") String ex, @Param("included") String inc, @Param("min") long min); + List findByDescriptionOrName(String description, String name); + } diff --git a/src/main/java/org/springframework/data/couchbase/repository/query/support/N1qlUtils.java b/src/main/java/org/springframework/data/couchbase/repository/query/support/N1qlUtils.java index ea18ceda..8ee7c768 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/query/support/N1qlUtils.java +++ b/src/main/java/org/springframework/data/couchbase/repository/query/support/N1qlUtils.java @@ -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; } diff --git a/src/test/java/org/springframework/data/couchbase/repository/query/support/N1qlUtilsTest.java b/src/test/java/org/springframework/data/couchbase/repository/query/support/N1qlUtilsTest.java index 6272f64f..f9e6b52a 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/query/support/N1qlUtilsTest.java +++ b/src/test/java/org/springframework/data/couchbase/repository/query/support/N1qlUtilsTest.java @@ -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); + } } \ No newline at end of file