/*
* Copyright 2016-2017 the original author or authors.
*
* 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.
*/
package org.springframework.data.cassandra.repository.query;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.cassandra.repository.query.StubParameterAccessor.*;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.annotation.Id;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
import org.springframework.data.cassandra.convert.UpdateMapper;
import org.springframework.data.cassandra.core.StatementFactory;
import org.springframework.data.cassandra.core.query.Query;
import org.springframework.data.cassandra.domain.Person;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.PrimaryKeyClass;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.data.cassandra.repository.support.MappingCassandraEntityInformation;
import org.springframework.data.repository.query.parser.PartTree;
import com.datastax.driver.core.RegularStatement;
/**
* Unit tests for {@link CassandraQueryCreator}.
*
* @author Mark Paluch
*/
public class CassandraQueryCreatorUnitTests {
CassandraMappingContext context;
CassandraConverter converter;
@Rule public ExpectedException exception = ExpectedException.none();
@Before
public void setUp() throws SecurityException, NoSuchMethodException {
context = new BasicCassandraMappingContext();
converter = new MappingCassandraConverter(context);
}
@Test // DATACASS-7
public void createsQueryCorrectly() {
String query = createQuery("findByFirstname", Person.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname='Walter';");
}
@Test // DATACASS-7
public void createsQueryWithSortCorrectly() {
String query = createQuery("findByFirstnameOrderByLastname", Person.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname='Walter' ORDER BY lastname ASC;");
}
@Test // DATACASS-7
public void createsAndQueryCorrectly() {
String query = createQuery("findByFirstnameAndLastname", Person.class, "Walter", "White");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname='Walter' AND lastname='White';");
}
@Test(expected = InvalidDataAccessApiUsageException.class) // DATACASS-7
public void rejectsNegatingQuery() {
createQuery("findByFirstnameNot", Person.class, "Walter");
}
@Test(expected = InvalidDataAccessApiUsageException.class) // DATACASS-7
public void rejectsOrQuery() {
createQuery("findByFirstnameOrLastname", Person.class, "Walter", "White");
}
@Test // DATACASS-7
public void createsGreaterThanQueryCorrectly() {
String query = createQuery("findByFirstnameGreaterThan", Person.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname>'Walter';");
}
@Test // DATACASS-7
public void createsGreaterThanEqualQueryCorrectly() {
String query = createQuery("findByFirstnameGreaterThanEqual", Person.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname>='Walter';");
}
@Test // DATACASS-7
public void createsLessThanQueryCorrectly() {
String query = createQuery("findByFirstnameLessThan", Person.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname<'Walter';");
}
@Test // DATACASS-7
public void createsLessThanEqualQueryCorrectly() {
String query = createQuery("findByFirstnameLessThanEqual", Person.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname<='Walter';");
}
@Test // DATACASS-7
public void createsInQueryCorrectly() {
String query = createQuery("findByFirstnameIn", Person.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname IN ('Walter');");
}
@Test // DATACASS-7
public void createsInQueryWithListCorrectly() {
String query = createQuery("findByFirstnameIn", Person.class, Arrays.asList("Walter", "Gus"));
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname IN ('Walter','Gus');");
}
@Test // DATACASS-7
public void createsInQueryWithArrayCorrectly() {
String query = createQuery("findByFirstnameInAndLastname", Person.class, new String[] { "Walter", "Gus" }, "Fring");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname IN ('Walter','Gus') AND lastname='Fring';");
}
@Test // DATACASS-7
public void createsLikeQueryCorrectly() {
assertThat(createQuery("findByFirstnameLike", Person.class, "Wal%ter"))
.isEqualTo("SELECT * FROM person WHERE firstname LIKE 'Wal%ter';");
assertThat(createQuery("findByFirstnameLike", Person.class, "Walter"))
.isEqualTo("SELECT * FROM person WHERE firstname LIKE 'Walter';");
}
@Test // DATACASS-7
public void createsStartsWithQueryCorrectly() {
String query = createQuery("findByFirstnameStartsWith", Person.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname LIKE 'Walter%';");
}
@Test // DATACASS-7
public void createsEndsWithQueryCorrectly() {
String query = createQuery("findByFirstnameEndsWith", Person.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname LIKE '%Walter';");
}
@Test // DATACASS-7
public void createsContainsQueryOnSimplePropertyCorrectly() {
String query = createQuery("findByFirstnameContains", Person.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname LIKE '%Walter%';");
}
@Test // DATACASS-7
public void createsContainsQueryOnSetPropertyCorrectly() {
String query = createQuery("findByMysetContains", TypeWithSet.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM typewithset WHERE myset CONTAINS 'Walter';");
}
@Test // DATACASS-7
public void createsContainsQueryOnListPropertyCorrectly() {
String query = createQuery("findByMylistContains", TypeWithList.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM typewithlist WHERE mylist CONTAINS 'Walter';");
}
@Test // DATACASS-7
public void createsContainsQueryOnMapPropertyCorrectly() {
String query = createQuery("findByMymapContains", TypeWithMap.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM typewithmap WHERE mymap CONTAINS 'Walter';");
}
@Test // DATACASS-7
public void createsIsTrueQueryCorrectly() {
String query = createQuery("findByFirstnameIsTrue", Person.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname=true;");
}
@Test // DATACASS-7
public void createsIsFalseQueryCorrectly() {
String query = createQuery("findByFirstnameIsFalse", Person.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM person WHERE firstname=false;");
}
@Test // DATACASS-7
public void createsQueryUsingQuotingCorrectly() {
String query = createQuery("findByIdAndSet", QuotedType.class, "Walter", "White");
assertThat(query).isEqualTo("SELECT * FROM \"myTable\" WHERE \"my_id\"='Walter' AND \"set\"='White';");
}
@Test // DATACASS-7
public void createsFindByPrimaryKeyPartCorrectly() {
String query = createQuery("findByKeyFirstname", TypeWithCompositeId.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM typewithcompositeid WHERE firstname='Walter';");
}
@Test // DATACASS-7
public void createsFindByPrimaryKeyPartWithSortCorrectly() {
String query = createQuery("findByKeyFirstnameOrderByKeyLastnameAsc", TypeWithCompositeId.class, "Walter");
assertThat(query).isEqualTo("SELECT * FROM typewithcompositeid WHERE firstname='Walter' ORDER BY lastname ASC;");
}
@Test // DATACASS-7
public void createsFindByPrimaryKeyPartOfPrimaryKeyClassCorrectly() {
String query = createQuery("findByFirstname", Key.class, "Walter");
// ⊙_ʘ rly? ヾ( •́д•̀ ;)ノ
assertThat(query).isEqualTo("SELECT * FROM key WHERE firstname='Walter';");
}
@Test(expected = IllegalStateException.class) // DATACASS-7
public void createsFindByPrimaryKey2PartCorrectly() {
createQuery("findByKey", TypeWithCompositeId.class, new Key());
}
private String createQuery(String source, Class<?> entityClass, Object... values) {
PartTree tree = new PartTree(source, entityClass);
CassandraQueryCreator creator = new CassandraQueryCreator(tree, getAccessor(converter, values), context);
StatementFactory factory = new StatementFactory(new UpdateMapper(converter));
Query query = creator.createQuery();
RegularStatement select = factory.select(query, context.getRequiredPersistentEntity(entityClass));
return select.toString();
}
@SuppressWarnings("unchecked")
private <T> CassandraEntityInformation<T, Serializable> getEntityInformation(final Class<T> entityClass) {
return new MappingCassandraEntityInformation<>(
(CassandraPersistentEntity) context.getRequiredPersistentEntity(entityClass), converter);
}
@Table
private static class TypeWithSet {
@Id String id;
Set<String> myset;
}
@Table
private static class TypeWithList {
@Id String id;
List<String> mylist;
}
@Table
private static class TypeWithMap {
@Id String id;
Map<String, String> mymap;
}
@Table(value = "myTable", forceQuote = true)
private static class QuotedType {
@PrimaryKey(value = "my_id", forceQuote = true) String id;
@Column(value = "set") Set<String> set;
}
@PrimaryKeyClass
private static class Key implements Serializable {
@PrimaryKeyColumn(type = PrimaryKeyType.PARTITIONED, ordinal = 1) String firstname;
@PrimaryKeyColumn(type = PrimaryKeyType.PARTITIONED, ordinal = 1) String lastname;
}
@Table
private static class TypeWithCompositeId {
@PrimaryKey Key key;
String city;
}
}