/*
* Copyright (C) 2012-2015 DataStax Inc.
*
* 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 com.datastax.driver.mapping;
import com.datastax.driver.core.CCMTestsSupport;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.exceptions.CodecNotFoundException;
import com.datastax.driver.core.utils.CassandraVersion;
import com.datastax.driver.mapping.annotations.*;
import com.google.common.collect.Lists;
import org.testng.annotations.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@SuppressWarnings("unused")
public class MapperAccessorParamsTest extends CCMTestsSupport {
@Override
public void onTestContextInitialized() {
execute(
"CREATE TABLE user ( key int primary key, gender int, home_phone text, work_phone text)",
"CREATE INDEX on user(gender)",
"CREATE TABLE user_str ( key int primary key, gender text)",
"CREATE INDEX on user_str(gender)"
);
}
@Test(groups = "short")
@CassandraVersion(value = "2.0", description = "Uses named parameters")
public void should_allow_less_parameters_than_bind_markers_if_there_are_repeated_names() {
UserPhoneAccessor accessor = new MappingManager(session())
.createAccessor(UserPhoneAccessor.class);
session().execute("delete from user where key = 0");
accessor.updatePhones_positional("1111", "2222", 0);
assertPhonesEqual(0, "1111", "2222");
session().execute("delete from user where key = 0");
accessor.updatePhones_named(0, "1111", "2222");
assertPhonesEqual(0, "1111", "2222");
session().execute("delete from user where key = 0");
accessor.updatePhones_fallback("1111", "2222", 0);
assertPhonesEqual(0, "1111", "2222");
session().execute("delete from user where key = 0");
accessor.updateBothPhones(0, "1111");
assertPhonesEqual(0, "1111", "1111");
session().execute("delete from user where key = 0");
accessor.updatePhones_fallback2("1111", "2222", 0);
assertPhonesEqual(0, "1111", "2222");
}
@Test(groups = "short", expectedExceptions = RuntimeException.class)
public void should_fail_if_not_enough_parameters() {
new MappingManager(session())
.createAccessor(UserPhoneAccessor_NotEnoughParams.class);
}
@Test(groups = "short", expectedExceptions = RuntimeException.class)
public void should_fail_if_too_many_parameters() {
new MappingManager(session())
.createAccessor(UserPhoneAccessor_TooManyParams.class);
}
/**
* Ensures that a wrong parameter type is detected when
* the accessor is called with a wrong data type.
*
* @jira_ticket JAVA-974
*/
@Test(groups = "short", expectedExceptions = CodecNotFoundException.class)
public void should_fail_if_wrong_parameter_type() {
UserPhoneAccessor_WrongParameterTypes accessor = new MappingManager(session())
.createAccessor(UserPhoneAccessor_WrongParameterTypes.class);
accessor.findUsersBykeys(Lists.newArrayList(1, 2, 3));
}
private void assertPhonesEqual(int key, String home, String work) {
Row row = session().execute("select * from user where key = " + key).one();
assertThat(row.getString("home_phone")).isEqualTo(home);
assertThat(row.getString("work_phone")).isEqualTo(work);
}
enum Enum {
MALE, FEMALE
}
/**
* Tests various ways to match method parameters to query bind markers.
*/
@Accessor
public interface UserPhoneAccessor {
/**
* Standard positional markers
*/
@Query("update user set home_phone = ?, work_phone = ? where key = ?")
void updatePhones_positional(String homePhone, String workPhone, int key);
/**
* Standard named markers
*/
@Query("update user set home_phone = :home, work_phone = :work where key = :key")
void updatePhones_named(@Param("key") int key, @Param("home") String homePhone, @Param("work") String workPhone);
/**
* Named markers with no @Param. Should fallback to positional matching
*/
@Query("update user set home_phone = :home, work_phone = :work where key = :key")
void updatePhones_fallback(String homePhone, String workPhone, int key);
/**
* Named markers with repeated names
*/
@Query("update user set home_phone = :phone, work_phone = :phone where key = :key")
void updateBothPhones(@Param("key") int key, @Param("phone") String uniquePhone);
/**
* Named markers with repeated names, but no @Param. Should fallback to positional matching
*/
@Query("update user set home_phone = :phone, work_phone = :phone where key = :key")
void updatePhones_fallback2(String homePhone, String workPhone, int key);
}
@Accessor
public interface UserPhoneAccessor_NotEnoughParams {
@SuppressWarnings("unused")
@Query("update user set home_phone = :phone, work_phone = :phone where key = :key")
void updateBothPhones(@Param("key") int key);
}
@Accessor
public interface UserPhoneAccessor_TooManyParams {
@SuppressWarnings("unused")
@Query("update user set home_phone = ?, work_phone = ? where key = ?")
void updatePhones(String homePhone, String workPhone, int key, int extra);
}
@Table(name = "user")
public static class User {
@PartitionKey
private int key;
public User() {
}
public User(int k) {
this.key = k;
}
public int getKey() {
return this.key;
}
public void setKey(int pk) {
this.key = pk;
}
}
@Table(name = "user")
public static class UserStr {
@PartitionKey
private int key;
private Enum gender;
public UserStr() {
}
public UserStr(int k, Enum val) {
this.key = k;
this.gender = val;
}
public int getKey() {
return this.key;
}
public void setKey(int pk) {
this.key = pk;
}
public Enum getGender() {
return this.gender;
}
public void setGender(Enum val) {
this.gender = val;
}
}
@Accessor
public interface UserPhoneAccessor_WrongParameterTypes {
@Query("select * from user where key IN (?)")
// WRONG, should be "where key IN ?"
void findUsersBykeys(List<Integer> keys);
}
}