diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java index a5774e974..08cd1092b 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java @@ -237,7 +237,8 @@ public Mono exists() { } private String assembleEntityQuery(final boolean count, String[] distinctFields, String scope, String collection) { - return query.toN1qlSelectString(template, scope, collection, this.domainType, this.returnType, count, + return query.toN1qlSelectString(template.getConverter(), template.getBucketName(), scope, collection, + this.domainType, this.returnType, count, query.getDistinctFields() != null ? query.getDistinctFields() : distinctFields, fields); } } diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java index a9f1db8e9..18476e813 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByQueryOperationSupport.java @@ -120,7 +120,8 @@ public RemoveByQueryConsistentWith withConsistency(final QueryScanConsistency } private String assembleDeleteQuery(String scope, String collection) { - return query.toN1qlRemoveString(template, scope, collection, this.domainType); + return query.toN1qlRemoveString(template.getConverter(), template.getBucketName(), scope, collection, + this.domainType); } @Override diff --git a/src/main/java/org/springframework/data/couchbase/core/convert/join/N1qlJoinResolver.java b/src/main/java/org/springframework/data/couchbase/core/convert/join/N1qlJoinResolver.java index 80df2eb57..316d76639 100644 --- a/src/main/java/org/springframework/data/couchbase/core/convert/join/N1qlJoinResolver.java +++ b/src/main/java/org/springframework/data/couchbase/core/convert/join/N1qlJoinResolver.java @@ -73,12 +73,12 @@ public static String buildQuery(ReactiveCouchbaseTemplate template, Strin String from = "FROM " + keySpacePair.lhs.keyspace + " lks " + useLKS + joinType + " " + keySpacePair.rhs.keyspace + " rks"; - StringBasedN1qlQueryParser.N1qlSpelValues n1qlL = Query.getN1qlSpelValues(template, null, + StringBasedN1qlQueryParser.N1qlSpelValues n1qlL = Query.getN1qlSpelValues(template.getConverter(), null, scope, keySpacePair.lhs.collection, parameters.getEntityTypeInfo().getType(), parameters.getEntityTypeInfo().getType(), false, null, null); String onLks = "lks." + n1qlL.filter; - StringBasedN1qlQueryParser.N1qlSpelValues n1qlR = Query.getN1qlSpelValues(template, null, + StringBasedN1qlQueryParser.N1qlSpelValues n1qlR = Query.getN1qlSpelValues(template.getConverter(), null, scope, keySpacePair.rhs.collection, parameters.getAssociatedEntityTypeInfo().getType(), parameters.getAssociatedEntityTypeInfo().getType(), false, null, null); String onRks = "rks." + n1qlR.filter; diff --git a/src/main/java/org/springframework/data/couchbase/core/query/N1QLQuery.java b/src/main/java/org/springframework/data/couchbase/core/query/N1QLQuery.java index c5fefd6ec..7b0a69abd 100644 --- a/src/main/java/org/springframework/data/couchbase/core/query/N1QLQuery.java +++ b/src/main/java/org/springframework/data/couchbase/core/query/N1QLQuery.java @@ -15,7 +15,7 @@ */ package org.springframework.data.couchbase.core.query; -import org.springframework.data.couchbase.core.ReactiveCouchbaseTemplate; +import org.springframework.data.couchbase.core.convert.CouchbaseConverter; import com.couchbase.client.java.json.JsonObject; import com.couchbase.client.java.query.QueryOptions; @@ -48,8 +48,9 @@ public JsonObject n1ql() { } @Override - public String toN1qlSelectString(ReactiveCouchbaseTemplate template, String scopeName, String collectionName, - Class domainClass, Class returnClass, boolean isCount, String[] distinctFields, String[] fields) { + public String toN1qlSelectString(CouchbaseConverter template, String bucketName, String scopeName, + String collectionName, Class domainClass, Class returnClass, boolean isCount, String[] distinctFields, + String[] fields) { return expression.toString(); } } diff --git a/src/main/java/org/springframework/data/couchbase/core/query/Query.java b/src/main/java/org/springframework/data/couchbase/core/query/Query.java index 808bf5392..a7e6d4fa7 100644 --- a/src/main/java/org/springframework/data/couchbase/core/query/Query.java +++ b/src/main/java/org/springframework/data/couchbase/core/query/Query.java @@ -343,17 +343,19 @@ public String export(int[]... paramIndexPtrHolder) { // used only by tests */ @Deprecated public String toN1qlSelectString(ReactiveCouchbaseTemplate template, Class domainClass, boolean isCount) { - return toN1qlSelectString(template, null, null, domainClass, null, isCount, null, null); + return toN1qlSelectString(template.getConverter(), template.getBucketName(), null, null, domainClass, null, isCount, + null, null); } - public String toN1qlSelectString(ReactiveCouchbaseTemplate template, String scopeName, String collectionName, - Class domainClass, Class returnClass, boolean isCount, String[] distinctFields, String[] fields) { - StringBasedN1qlQueryParser.N1qlSpelValues n1ql = getN1qlSpelValues(template, scopeName, collectionName, domainClass, - returnClass, isCount, distinctFields, fields); + public String toN1qlSelectString(CouchbaseConverter converter, String bucketName, String scopeName, + String collectionName, Class domainClass, Class returnClass, boolean isCount, String[] distinctFields, + String[] fields) { + StringBasedN1qlQueryParser.N1qlSpelValues n1ql = getN1qlSpelValues(converter, bucketName, scopeName, collectionName, + domainClass, returnClass, isCount, distinctFields, fields); final StringBuilder statement = new StringBuilder(); appendString(statement, n1ql.selectEntity); // select ... appendWhereString(statement, n1ql.filter); // typeKey = typeValue - appendWhere(statement, new int[] { 0 }, template.getConverter()); // criteria on this Query + appendWhere(statement, new int[] { 0 }, converter); // criteria on this Query if (!isCount) { appendSort(statement); appendSkipAndLimit(statement); @@ -361,35 +363,34 @@ public String toN1qlSelectString(ReactiveCouchbaseTemplate template, String scop return statement.toString(); } - public String toN1qlRemoveString(ReactiveCouchbaseTemplate template, String scopeName, String collectionName, - Class domainClass) { - StringBasedN1qlQueryParser.N1qlSpelValues n1ql = getN1qlSpelValues(template, scopeName, collectionName, domainClass, - null, false, null, null); + public String toN1qlRemoveString(CouchbaseConverter converter, String bucketName, String scopeName, + String collectionName, Class domainClass) { + StringBasedN1qlQueryParser.N1qlSpelValues n1ql = getN1qlSpelValues(converter, bucketName, scopeName, collectionName, + domainClass, null, false, null, null); final StringBuilder statement = new StringBuilder(); appendString(statement, n1ql.delete); // delete ... appendWhereString(statement, n1ql.filter); // typeKey = typeValue - appendWhere(statement, null, template.getConverter()); // criteria on this Query + appendWhere(statement, null, converter); // criteria on this Query appendString(statement, n1ql.returning); return statement.toString(); } - public static StringBasedN1qlQueryParser.N1qlSpelValues getN1qlSpelValues(ReactiveCouchbaseTemplate template, - String scopeName, String collectionName, Class domainClass, Class returnClass, boolean isCount, + public static StringBasedN1qlQueryParser.N1qlSpelValues getN1qlSpelValues(CouchbaseConverter converter, + String bucketName, String scopeName, String collectionName, Class domainClass, Class returnClass, boolean isCount, String[] distinctFields, String[] fields) { - String typeKey = template.getConverter().getTypeKey(); - final CouchbasePersistentEntity persistentEntity = template.getConverter().getMappingContext() + String typeKey = converter.getTypeKey(); + final CouchbasePersistentEntity persistentEntity = converter.getMappingContext() .getRequiredPersistentEntity(domainClass); MappingCouchbaseEntityInformation info = new MappingCouchbaseEntityInformation<>(persistentEntity); String typeValue = info.getJavaType().getName(); TypeInformation typeInfo = ClassTypeInformation.from(info.getJavaType()); - Alias alias = template.getConverter().getTypeAlias(typeInfo); + Alias alias = converter.getTypeAlias(typeInfo); if (alias != null && alias.isPresent()) { typeValue = alias.toString(); } - StringBasedN1qlQueryParser sbnqp = new StringBasedN1qlQueryParser(template.getBucketName(), scopeName, - collectionName, template.getConverter(), domainClass, returnClass, typeKey, typeValue, isCount, distinctFields, - fields); + StringBasedN1qlQueryParser sbnqp = new StringBasedN1qlQueryParser(bucketName, scopeName, collectionName, converter, + domainClass, returnClass, typeKey, typeValue, isCount, distinctFields, fields); return sbnqp.getStatementContext(); } diff --git a/src/main/java/org/springframework/data/couchbase/core/query/StringQuery.java b/src/main/java/org/springframework/data/couchbase/core/query/StringQuery.java index 372f6192d..4bed9947b 100644 --- a/src/main/java/org/springframework/data/couchbase/core/query/StringQuery.java +++ b/src/main/java/org/springframework/data/couchbase/core/query/StringQuery.java @@ -17,7 +17,7 @@ import java.util.Locale; -import org.springframework.data.couchbase.core.ReactiveCouchbaseTemplate; +import org.springframework.data.couchbase.core.convert.CouchbaseConverter; import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity; import org.springframework.data.couchbase.core.support.TemplateUtils; import org.springframework.data.couchbase.repository.query.CouchbaseQueryMethod; @@ -66,10 +66,10 @@ public StringQuery(CouchbaseQueryMethod queryMethod, String n1qlString, } @Override - public String toN1qlSelectString(ReactiveCouchbaseTemplate template, String scope, String collection, + public String toN1qlSelectString(CouchbaseConverter converter, String bucketName, String scope, String collection, Class domainClass, Class resultClass, boolean isCount, String[] distinctFields, String[] fields) { - StringBasedN1qlQueryParser parser = getStringN1qlQueryParser(template, scope, collection, domainClass, + StringBasedN1qlQueryParser parser = getStringN1qlQueryParser(converter, bucketName, scope, collection, domainClass, distinctFields, fields); N1QLExpression parsedExpression = parser.getExpression(inlineN1qlQuery, queryMethod, parameterAccessor, @@ -100,7 +100,7 @@ public String toN1qlSelectString(ReactiveCouchbaseTemplate template, String scop } else { // named parameters or no parameters, no index required paramIndexPtr = new int[] { -1 }; } - appendWhere(statement, paramIndexPtr, template.getConverter()); // criteria on this Query - should be empty for + appendWhere(statement, paramIndexPtr, converter); // criteria on this Query - should be empty for if (!isCount) { appendSort(statement); appendSkipAndLimit(statement); @@ -111,22 +111,22 @@ public String toN1qlSelectString(ReactiveCouchbaseTemplate template, String scop return statement.toString(); } - private StringBasedN1qlQueryParser getStringN1qlQueryParser(ReactiveCouchbaseTemplate template, String scopeName, - String collectionName, Class domainClass, String[] distinctFields, String[] fields) { - String typeKey = template.getConverter().getTypeKey(); - final CouchbasePersistentEntity persistentEntity = template.getConverter().getMappingContext() + private StringBasedN1qlQueryParser getStringN1qlQueryParser(CouchbaseConverter converter, String bucketName, + String scopeName, String collectionName, Class domainClass, String[] distinctFields, String[] fields) { + String typeKey = converter.getTypeKey(); + final CouchbasePersistentEntity persistentEntity = converter.getMappingContext() .getRequiredPersistentEntity(domainClass); MappingCouchbaseEntityInformation info = new MappingCouchbaseEntityInformation<>(persistentEntity); String typeValue = info.getJavaType().getName(); TypeInformation typeInfo = ClassTypeInformation.from(info.getJavaType()); - Alias alias = template.getConverter().getTypeAlias(typeInfo); + Alias alias = converter.getTypeAlias(typeInfo); if (alias != null && alias.isPresent()) { typeValue = alias.toString(); } // there are no options for distinct and fields for @Query - StringBasedN1qlQueryParser sbnqp = new StringBasedN1qlQueryParser(inlineN1qlQuery, queryMethod, - template.getBucketName(), scopeName, collectionName, template.getConverter(), typeKey, typeValue, - parameterAccessor, new SpelExpressionParser(), evaluationContextProvider); + StringBasedN1qlQueryParser sbnqp = new StringBasedN1qlQueryParser(inlineN1qlQuery, queryMethod, bucketName, + scopeName, collectionName, converter, typeKey, typeValue, parameterAccessor, new SpelExpressionParser(), + evaluationContextProvider); return sbnqp; } @@ -139,8 +139,9 @@ private StringBasedN1qlQueryParser getStringN1qlQueryParser(ReactiveCouchbaseTem * @param domainClass */ @Override - public String toN1qlRemoveString(ReactiveCouchbaseTemplate template, String scopeName, String collectionName, - Class domainClass) { - return toN1qlSelectString(template, scopeName, collectionName, domainClass, domainClass, false, null, null); + public String toN1qlRemoveString(CouchbaseConverter converter, String bucketName, String scopeName, + String collectionName, Class domainClass) { + return toN1qlSelectString(converter, bucketName, scopeName, collectionName, domainClass, domainClass, false, null, + null); } } diff --git a/src/test/java/org/springframework/data/couchbase/repository/query/StringN1qlQueryCreatorMockedTests.java b/src/test/java/org/springframework/data/couchbase/repository/query/StringN1qlQueryCreatorTests.java similarity index 76% rename from src/test/java/org/springframework/data/couchbase/repository/query/StringN1qlQueryCreatorMockedTests.java rename to src/test/java/org/springframework/data/couchbase/repository/query/StringN1qlQueryCreatorTests.java index 298779024..cebcdc1d4 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/query/StringN1qlQueryCreatorMockedTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/query/StringN1qlQueryCreatorTests.java @@ -17,18 +17,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; -import static org.springframework.data.couchbase.config.BeanNames.COUCHBASE_TEMPLATE; import java.lang.reflect.Method; import java.util.Properties; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; -import org.springframework.data.couchbase.core.CouchbaseTemplate; import org.springframework.data.couchbase.core.convert.CouchbaseConverter; import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter; import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext; @@ -37,8 +31,6 @@ import org.springframework.data.couchbase.core.query.Query; import org.springframework.data.couchbase.domain.User; import org.springframework.data.couchbase.domain.UserRepository; -import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories; -import org.springframework.data.couchbase.util.ClusterAwareIntegrationTests; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.projection.SpelAwareProxyProjectionFactory; import org.springframework.data.repository.core.NamedQueries; @@ -51,27 +43,57 @@ import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider; import org.springframework.expression.spel.standard.SpelExpressionParser; -import com.couchbase.client.core.deps.io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import com.couchbase.client.core.env.SecurityConfig; -import com.couchbase.client.java.env.ClusterEnvironment; - /** * @author Michael Nitschinger * @author Michael Reiche */ -class StringN1qlQueryCreatorMockedTests extends ClusterAwareIntegrationTests { +class StringN1qlQueryCreatorTests { MappingContext, CouchbasePersistentProperty> context; CouchbaseConverter converter; - CouchbaseTemplate couchbaseTemplate; static NamedQueries namedQueries = new PropertiesBasedNamedQueries(new Properties()); @BeforeEach public void beforeEach() { context = new CouchbaseMappingContext(); converter = new MappingCouchbaseConverter(context); - ApplicationContext ac = new AnnotationConfigApplicationContext(Config.class); - couchbaseTemplate = (CouchbaseTemplate) ac.getBean(COUCHBASE_TEMPLATE); + } + + @Test + void wrongNumberArgs() throws Exception { + String input = "getByFirstnameOrLastname"; + Method method = UserRepository.class.getMethod(input, String.class, String.class); + + CouchbaseQueryMethod queryMethod = new CouchbaseQueryMethod(method, + new DefaultRepositoryMetadata(UserRepository.class), new SpelAwareProxyProjectionFactory(), + converter.getMappingContext()); + + try { + StringN1qlQueryCreator creator = new StringN1qlQueryCreator(getAccessor(getParameters(method), "Oliver"), + queryMethod, converter, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT, + namedQueries); + } catch (IllegalArgumentException e) { + return; + } + fail("should have failed with IllegalArgumentException: Invalid number of parameters given!"); + } + + @Test + void doesNotHaveAnnotation() throws Exception { + String input = "findByFirstname"; + Method method = UserRepository.class.getMethod(input, String.class); + CouchbaseQueryMethod queryMethod = new CouchbaseQueryMethod(method, + new DefaultRepositoryMetadata(UserRepository.class), new SpelAwareProxyProjectionFactory(), + converter.getMappingContext()); + + try { + StringN1qlQueryCreator creator = new StringN1qlQueryCreator(getAccessor(getParameters(method), "Oliver"), + queryMethod, converter, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT, + namedQueries); + } catch (IllegalArgumentException e) { + return; + } + fail("should have failed with IllegalArgumentException: query has no inline Query or named Query not found"); } @Test @@ -92,7 +114,7 @@ void createsQueryCorrectly() throws Exception { + "`).`cas` AS __cas, `createdBy`, `createdDate`, `lastModifiedBy`, `lastModifiedDate`, META(`" + bucketName() + "`).`id` AS __id, `firstname`, `lastname`, `subtype` FROM `" + bucketName() + "` where `_class` = \"abstractuser\" and firstname = $1 and lastname = $2", - query.toN1qlSelectString(couchbaseTemplate.reactive(), null, null, User.class, User.class, false, null, null)); + query.toN1qlSelectString(converter, bucketName(), null, null, User.class, User.class, false, null, null)); } @Test @@ -113,44 +135,7 @@ void createsQueryCorrectly2() throws Exception { + "`).`cas` AS __cas, `createdBy`, `createdDate`, `lastModifiedBy`, `lastModifiedDate`, META(`" + bucketName() + "`).`id` AS __id, `firstname`, `lastname`, `subtype` FROM `" + bucketName() + "` where `_class` = \"abstractuser\" and (firstname = $first or lastname = $last)", - query.toN1qlSelectString(couchbaseTemplate.reactive(), null, null, User.class, User.class, false, null, null)); - } - - @Test - void wrongNumberArgs() throws Exception { - String input = "getByFirstnameOrLastname"; - Method method = UserRepository.class.getMethod(input, String.class, String.class); - - CouchbaseQueryMethod queryMethod = new CouchbaseQueryMethod(method, - new DefaultRepositoryMetadata(UserRepository.class), new SpelAwareProxyProjectionFactory(), - converter.getMappingContext()); - - try { - StringN1qlQueryCreator creator = new StringN1qlQueryCreator(getAccessor(getParameters(method), "Oliver"), - queryMethod, converter, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT, - namedQueries); - } catch (IllegalArgumentException e) { - return; - } - fail("should have failed with IllegalArgumentException: Invalid number of parameters given!"); - } - - @Test - void doesNotHaveAnnotation() throws Exception { - String input = "findByFirstname"; - Method method = UserRepository.class.getMethod(input, String.class); - CouchbaseQueryMethod queryMethod = new CouchbaseQueryMethod(method, - new DefaultRepositoryMetadata(UserRepository.class), new SpelAwareProxyProjectionFactory(), - converter.getMappingContext()); - - try { - StringN1qlQueryCreator creator = new StringN1qlQueryCreator(getAccessor(getParameters(method), "Oliver"), - queryMethod, converter, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT, - namedQueries); - } catch (IllegalArgumentException e) { - return; - } - fail("should have failed with IllegalArgumentException: query has no inline Query or named Query not found"); + query.toN1qlSelectString(converter, bucketName(), null, null, User.class, User.class, false, null, null)); } @Test @@ -166,10 +151,17 @@ void spelTests() throws Exception { Query query = creator.createQuery(); - String s = query.toN1qlSelectString(couchbaseTemplate.reactive(), "myScope", "myCollection", User.class, null, - false, null, null); - System.out.println("query: " + s); + assertEquals( + "SELECT `_class`, META(`myCollection`).`cas` AS __cas, `createdBy`, `createdDate`, " + + "`lastModifiedBy`, `lastModifiedDate`, META(`myCollection`).`id` AS __id, `firstname`, " + + "`lastname`, `subtype` FROM `myCollection`|`_class` = \"abstractuser\"" + + "|`myCollection`|`myScope`|`myCollection`", + query.toN1qlSelectString(converter, bucketName(), "myScope", "myCollection", User.class, null, false, null, + null)); + } + private String bucketName() { + return "some_bucket"; } private ParameterAccessor getAccessor(Parameters params, Object... values) { @@ -180,37 +172,4 @@ private ParameterAccessor getAccessor(Parameters params, Object... values) return new DefaultParameters(method); } - @Configuration - @EnableCouchbaseRepositories("org.springframework.data.couchbase") - static class Config extends AbstractCouchbaseConfiguration { - - @Override - public String getConnectionString() { - return connectionString(); - } - - @Override - public String getUserName() { - return config().adminUsername(); - } - - @Override - public String getPassword() { - return config().adminPassword(); - } - - @Override - public String getBucketName() { - return bucketName(); - } - - @Override - protected void configureEnvironment(ClusterEnvironment.Builder builder) { - if (config().isUsingCloud()) { - builder.securityConfig( - SecurityConfig.builder().trustManagerFactory(InsecureTrustManagerFactory.INSTANCE).enableTls(true)); - } - } - - } } diff --git a/src/test/java/org/springframework/data/couchbase/util/JavaIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/util/JavaIntegrationTests.java index d40dc6a85..b63a7493c 100644 --- a/src/test/java/org/springframework/data/couchbase/util/JavaIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/util/JavaIntegrationTests.java @@ -27,8 +27,6 @@ import static org.springframework.data.couchbase.config.BeanNames.REACTIVE_COUCHBASE_TEMPLATE; import static org.springframework.data.couchbase.util.Util.waitUntilCondition; -import com.couchbase.client.core.retry.BestEffortRetryStrategy; -import com.couchbase.client.core.retry.RetryStrategy; import okhttp3.Credentials; import okhttp3.FormBody; import okhttp3.OkHttpClient;