DATACOUCH-384 - Apply converters to string based query parameters
Apply the converters registered to serialize the positional and named parameters to match the database representation Original Pull Request: #172.
This commit is contained in:
@@ -40,6 +40,8 @@ import org.springframework.data.repository.core.support.RepositoryFactorySupport
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -127,7 +129,7 @@ public class N1qlCouchbaseRepositoryTests {
|
||||
Pageable pageable = new PageRequest(0, 8);
|
||||
|
||||
Page<Party> page1 = repository.findAll(pageable);
|
||||
assertEquals(16, page1.getTotalElements()); //12 generated parties + 4 specifically crafted party
|
||||
assertEquals(17, page1.getTotalElements()); //12 generated parties + 5 specifically crafted party
|
||||
assertEquals(8, page1.getNumberOfElements());
|
||||
}
|
||||
|
||||
@@ -136,7 +138,7 @@ public class N1qlCouchbaseRepositoryTests {
|
||||
Pageable pageable = new PageRequest(0, 8, Sort.Direction.DESC, "attendees");
|
||||
|
||||
Page<Party> page1 = repository.findAll(pageable);
|
||||
assertEquals(16, page1.getTotalElements()); //12 generated parties + 4 specifically crafted party
|
||||
assertEquals(17, page1.getTotalElements()); //12 generated parties + 5 specifically crafted party
|
||||
assertEquals(8, page1.getNumberOfElements());
|
||||
|
||||
List<Party> parties = page1.getContent();
|
||||
@@ -195,4 +197,16 @@ public class N1qlCouchbaseRepositoryTests {
|
||||
assertTrue(partyList.size() == 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpelDateConvertion() {
|
||||
final String key = "testSpelDateConvertion";
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.clear();
|
||||
cal.set(2018, Calendar.SEPTEMBER, 10);
|
||||
Date date = cal.getTime();
|
||||
partyRepository.save(new Party(key, "", "", date, 0, null));
|
||||
List<Party> partyList = partyRepository.getByEventDate(date);
|
||||
assertTrue(partyList.size() == 1);
|
||||
assertEquals("Key mismatch", partyList.get(0).getKey(), key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,4 +89,7 @@ public interface PartyRepository extends CouchbaseRepository<Party, String> {
|
||||
List<Party> findByDescriptionOrName(String description, String name);
|
||||
|
||||
List<Party> removeByDescriptionOrName(String description, String name);
|
||||
|
||||
@Query("#{#n1ql.selectEntity} where #{#n1ql.filter} and eventDate = $1")
|
||||
List<Party> getByEventDate(Date eventDate);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ package org.springframework.data.couchbase.repository;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -115,12 +119,25 @@ public class ReactiveN1qlCouchbaseRepositoryTests {
|
||||
@Test
|
||||
public void testCustomSpelCountQuery() {
|
||||
long count = partyRepository.countCustom().block();
|
||||
assertEquals("Test N1QL Spel based query", 15, count);
|
||||
assertEquals("Test N1QL Spel based query", 17, count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPartTreeQuery() {
|
||||
long count = partyRepository.countAllByDescriptionNotNull().block();
|
||||
assertEquals("Test N1QL part tree based query", 15, count);
|
||||
assertEquals("Test N1QL part tree based query", 17, count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpelDateConvertion() {
|
||||
final String key = "testReactiveSpelDateConvertion";
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.clear();
|
||||
cal.set(2018, Calendar.SEPTEMBER, 15);
|
||||
Date date = cal.getTime();
|
||||
partyRepository.save(new Party(key, "", "", date, 0, null)).block();
|
||||
List<Party> partyList = partyRepository.getByEventDate(date).collectList().block();
|
||||
assertTrue(partyList.size() == 1);
|
||||
assertEquals("Key mismatch", partyList.get(0).getKey(), key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,4 +57,6 @@ public interface ReactivePartyRepository extends ReactiveCouchbaseRepository<Par
|
||||
|
||||
Flux<Party> findByDescriptionOrName(String description, String name);
|
||||
|
||||
@Query("#{#n1ql.selectEntity} where #{#n1ql.filter} and eventDate = $1")
|
||||
Flux<Party> getByEventDate(Date eventDate);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class ReactiveStringN1qlBasedQuery extends ReactiveAbstractN1qlBasedQuery
|
||||
super(queryMethod, couchbaseOperations);
|
||||
|
||||
this.queryParser = new StringBasedN1qlQueryParser(statement, queryMethod,
|
||||
getCouchbaseOperations().getCouchbaseBucket().name(), getTypeField(), getTypeValue());
|
||||
getCouchbaseOperations().getCouchbaseBucket().name(), getCouchbaseOperations().getConverter(), getTypeField(), getTypeValue());
|
||||
this.parser = spelParser;
|
||||
this.evaluationContextProvider = evaluationContextProvider;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.couchbase.client.java.document.json.JsonArray;
|
||||
import com.couchbase.client.java.document.json.JsonObject;
|
||||
import com.couchbase.client.java.document.json.JsonValue;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
import org.springframework.data.couchbase.repository.query.support.N1qlUtils;
|
||||
import org.springframework.data.repository.query.Parameter;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
@@ -110,10 +111,12 @@ public class StringBasedN1qlQueryParser {
|
||||
private final PlaceholderType placeHolderType;
|
||||
private final N1qlSpelValues statementContext;
|
||||
private final N1qlSpelValues countContext;
|
||||
private final CouchbaseConverter couchbaseConverter;
|
||||
|
||||
public StringBasedN1qlQueryParser(String statement,
|
||||
QueryMethod queryMethod,
|
||||
String bucketName,
|
||||
CouchbaseConverter couchbaseConverter,
|
||||
String typeField,
|
||||
Class<?> typeValue) {
|
||||
this.statement = statement;
|
||||
@@ -121,7 +124,7 @@ public class StringBasedN1qlQueryParser {
|
||||
this.placeHolderType = checkPlaceholders(statement);
|
||||
this.statementContext = createN1qlSpelValues(bucketName, typeField, typeValue, false);
|
||||
this.countContext = createN1qlSpelValues(bucketName, typeField, typeValue, true);
|
||||
|
||||
this.couchbaseConverter = couchbaseConverter;
|
||||
}
|
||||
|
||||
public static N1qlSpelValues createN1qlSpelValues(String bucketName, String typeField, Class<?> typeValue, boolean isCount) {
|
||||
@@ -211,7 +214,7 @@ public class StringBasedN1qlQueryParser {
|
||||
private JsonValue getPositionalPlaceholderValues(ParameterAccessor accessor) {
|
||||
JsonArray posValues = JsonArray.create();
|
||||
for (Parameter parameter : this.queryMethod.getParameters().getBindableParameters()) {
|
||||
posValues.add(accessor.getBindableValue(parameter.getIndex()));
|
||||
posValues.add(this.couchbaseConverter.convertForWriteIfNeeded(accessor.getBindableValue(parameter.getIndex())));
|
||||
}
|
||||
return posValues;
|
||||
}
|
||||
@@ -221,7 +224,7 @@ public class StringBasedN1qlQueryParser {
|
||||
|
||||
for (Parameter parameter : this.queryMethod.getParameters().getBindableParameters()) {
|
||||
String placeholder = parameter.getPlaceholder();
|
||||
Object value = accessor.getBindableValue(parameter.getIndex());
|
||||
Object value = this.couchbaseConverter.convertForWriteIfNeeded(accessor.getBindableValue(parameter.getIndex()));
|
||||
|
||||
if (placeholder != null && placeholder.charAt(0) == ':') {
|
||||
placeholder = placeholder.replaceFirst(":", "");
|
||||
|
||||
@@ -68,7 +68,7 @@ public class StringN1qlBasedQuery extends AbstractN1qlBasedQuery {
|
||||
SpelExpressionParser spelParser, QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
super(queryMethod, couchbaseOperations);
|
||||
this.queryParser = new StringBasedN1qlQueryParser(statement, queryMethod,
|
||||
getCouchbaseOperations().getCouchbaseBucket().name(), getTypeField(), getTypeValue());
|
||||
getCouchbaseOperations().getCouchbaseBucket().name(), getCouchbaseOperations().getConverter(), getTypeField(), getTypeValue());
|
||||
this.parser = spelParser;
|
||||
this.evaluationContextProvider = evaluationContextProvider;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package org.springframework.data.couchbase.repository.query;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.springframework.data.couchbase.repository.query.StringBasedN1qlQueryParser.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
@@ -15,11 +19,18 @@ public class StringN1QlBasedQueryTest {
|
||||
private static String spel(String expression) {
|
||||
return "#{" + expression + "}";
|
||||
}
|
||||
CouchbaseConverter couchbaseConverter;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.couchbaseConverter = mock(CouchbaseConverter.class);
|
||||
when(couchbaseConverter.convertForWriteIfNeeded(eq("value"))).thenReturn("value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllFullSelectPlaceholder() throws Exception {
|
||||
String statement = spel(SPEL_SELECT_FROM_CLAUSE) + " where " + spel(SPEL_SELECT_FROM_CLAUSE);
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", "_class", String.class)
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", this.couchbaseConverter, "_class", String.class)
|
||||
.doParse(SPEL_PARSER, SPEL_EVALUATION_CONTEXT, false);
|
||||
|
||||
assertEquals("SELECT META(`B`).id AS _ID, META(`B`).cas AS _CAS, `B`.* FROM `B` where "
|
||||
@@ -29,7 +40,7 @@ public class StringN1QlBasedQueryTest {
|
||||
@Test
|
||||
public void testReplaceAllBucketPlaceholder() throws Exception {
|
||||
String statement = "SELECT * FROM " + spel(SPEL_BUCKET) + " WHERE " + spel(SPEL_BUCKET) + ".test = 1";
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", "_class", String.class)
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", this.couchbaseConverter, "_class", String.class)
|
||||
.doParse(SPEL_PARSER, SPEL_EVALUATION_CONTEXT, false);
|
||||
|
||||
assertEquals("SELECT * FROM `B` WHERE `B`.test = 1", parsed);
|
||||
@@ -38,7 +49,7 @@ public class StringN1QlBasedQueryTest {
|
||||
@Test
|
||||
public void testReplaceAllEntityPlaceholder() throws Exception {
|
||||
String statement = "SELECT " + spel(SPEL_ENTITY) + " FROM a where a.test = 1 and " + spel(SPEL_ENTITY);
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", "_class", String.class)
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", this.couchbaseConverter, "_class", String.class)
|
||||
.doParse(SPEL_PARSER, SPEL_EVALUATION_CONTEXT, false);
|
||||
|
||||
assertEquals("SELECT META(`B`).id AS _ID, META(`B`).cas AS _CAS FROM a where a.test = 1 and "
|
||||
@@ -48,7 +59,7 @@ public class StringN1QlBasedQueryTest {
|
||||
@Test
|
||||
public void testReplaceTypePlaceholder() throws Exception {
|
||||
String statement = "SELECT " + spel(SPEL_ENTITY) + " FROM a WHERE a.test = 1 AND " + spel(SPEL_FILTER);
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", "@class", String.class)
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", this.couchbaseConverter, "@class", String.class)
|
||||
.doParse(SPEL_PARSER, SPEL_EVALUATION_CONTEXT, false);
|
||||
|
||||
assertEquals("SELECT META(`B`).id AS _ID, META(`B`).cas AS _CAS FROM a WHERE a.test = 1 AND `@class` = "
|
||||
@@ -58,7 +69,7 @@ public class StringN1QlBasedQueryTest {
|
||||
@Test
|
||||
public void testReplaceSelectFromPlaceholderWithCountIfCountTrue() {
|
||||
String statement = spel(SPEL_SELECT_FROM_CLAUSE) + " WHERE true";
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", "_class", String.class)
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", this.couchbaseConverter, "_class", String.class)
|
||||
.doParse(SPEL_PARSER, SPEL_EVALUATION_CONTEXT, true);
|
||||
|
||||
assertEquals("SELECT COUNT(*) AS " + CountFragment.COUNT_ALIAS + " FROM `B` WHERE true", parsed);
|
||||
@@ -67,7 +78,7 @@ public class StringN1QlBasedQueryTest {
|
||||
@Test
|
||||
public void testDeletePlaceholder() throws Exception {
|
||||
String statement = spel(SPEL_DELETE) + " WHERE test = 1 AND " + spel(SPEL_FILTER);
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", "_class", String.class)
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", this.couchbaseConverter, "_class", String.class)
|
||||
.doParse(SPEL_PARSER, SPEL_EVALUATION_CONTEXT, true);
|
||||
|
||||
assertEquals("DELETE FROM `B` WHERE test = 1 AND `_class` = "
|
||||
@@ -77,7 +88,7 @@ public class StringN1QlBasedQueryTest {
|
||||
@Test
|
||||
public void testReturningPlaceholder() throws Exception {
|
||||
String statement = spel(SPEL_DELETE) + " WHERE test = 1 AND " + spel(SPEL_FILTER) + spel(SPEL_RETURNING) ;
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", "_class", String.class)
|
||||
String parsed = new StringBasedN1qlQueryParser(statement, null, "B", this.couchbaseConverter, "_class", String.class)
|
||||
.doParse(SPEL_PARSER, SPEL_EVALUATION_CONTEXT, true);
|
||||
|
||||
assertEquals("DELETE FROM `B` WHERE test = 1 AND `_class` = "
|
||||
|
||||
Reference in New Issue
Block a user