/* * 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); } }