1 /*
2 Copyright (c) DataStax, Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 #include "integration.hpp"
18
19 #define TABLE_FORMAT \
20 "CREATE TABLE %s (" \
21 "key timeuuid PRIMARY KEY, " \
22 "a int, " \
23 "b boolean, " \
24 "c text, " \
25 "abc float, " \
26 "\"ABC\" float, " \
27 "\"aBc\" float" \
28 ")"
29 #define TABLE_BYTES_FORMAT \
30 "CREATE TABLE %s (" \
31 "key timeuuid PRIMARY KEY, " \
32 "blobs blob, " \
33 "varints varint" \
34 ")"
35 #define INSERT_FORMAT "INSERT INTO %s (key, a, b, c) VALUES (?, ?, ?, ?)"
36 #define INSERT_CASE_SENSITIVE_FORMAT \
37 "INSERT INTO %s " \
38 "(key, abc, \"ABC\", \"aBc\") " \
39 "VALUES (?, ?, ?, ?)"
40 #define INSERT_ALL_FORMAT \
41 "INSERT INTO %s " \
42 "(key, a, b, c, abc, \"ABC\", \"aBc\") " \
43 "VALUES (?, ?, ?, ?, ?, ?, ?)"
44 #define INSERT_BYTES_FORMAT "INSERT INTO %s (key, blobs, varints) VALUES (?, ?, ?)"
45
46 /**
47 * By name integration tests
48 */
49 class ByNameTests : public Integration {
50 public:
SetUp()51 virtual void SetUp() {
52 // Call the parent setup function
53 Integration::SetUp();
54
55 // Create the table for the test
56 session_.execute(format_string(TABLE_FORMAT, table_name_.c_str()));
57 }
58
59 protected:
60 /**
61 * Insert and validate
62 *
63 * @param statement Insert statement to use (not case sensitive format)
64 */
insert_and_validate(Statement statement)65 void insert_and_validate(Statement statement) {
66 // Insert values into the table by name
67 TimeUuid key = uuid_generator_.generate_timeuuid();
68 statement.bind<TimeUuid>("key", key);
69 statement.bind<Integer>("a", Integer(9042));
70 statement.bind<Boolean>("b", Boolean(true));
71 statement.bind<Text>("c", Text("yyz"));
72 session_.execute(statement);
73
74 // Validate the inserts into the table
75 Result result = session_.execute(default_select_all());
76 ASSERT_EQ(1u, result.row_count());
77 ASSERT_EQ(7u, result.column_count());
78 Row row = result.first_row();
79 ASSERT_EQ(key, row.column_by_name<TimeUuid>("key"));
80 ASSERT_EQ(Integer(9042), row.column_by_name<Integer>("a"));
81 ASSERT_EQ(Boolean(true), row.column_by_name<Boolean>("b"));
82 ASSERT_EQ(Text("yyz"), row.column_by_name<Text>("c"));
83 }
84
85 /**
86 * Insert and validate
87 *
88 * @param statement Insert statement to use (case sensitive format)
89 */
insert_and_validate_case_sensitive(Statement statement)90 void insert_and_validate_case_sensitive(Statement statement) {
91 // Insert values into the table by name
92 TimeUuid key = uuid_generator_.generate_timeuuid();
93 statement.bind<TimeUuid>("key", key);
94 statement.bind<Float>("\"abc\"", Float(1.1f));
95 statement.bind<Float>("\"ABC\"", Float(2.2f));
96 statement.bind<Float>("\"aBc\"", Float(3.3f));
97 session_.execute(statement);
98
99 // Validate the inserts into the table
100 Result result = session_.execute(default_select_all());
101 ASSERT_EQ(1u, result.row_count());
102 ASSERT_EQ(7u, result.column_count());
103 Row row = result.first_row();
104 ASSERT_EQ(key, row.column_by_name<TimeUuid>("key"));
105 ASSERT_EQ(Float(1.1f), row.column_by_name<Float>("\"abc\""));
106 ASSERT_EQ(Float(2.2f), row.column_by_name<Float>("\"ABC\""));
107 ASSERT_EQ(Float(3.3f), row.column_by_name<Float>("\"aBc\""));
108 }
109
110 /**
111 * Insert all values into the table
112 *
113 * @param statement Insert statement to use (all format)
114 */
insert_and_validate_all(Statement statement)115 void insert_and_validate_all(Statement statement) {
116 // Insert values into the table by name
117 TimeUuid key = uuid_generator_.generate_timeuuid();
118 statement.bind<TimeUuid>("key", key);
119 statement.bind<Integer>("a", Integer(9042));
120 statement.bind<Boolean>("b", Boolean(true));
121 statement.bind<Text>("c", Text("yyz"));
122 statement.bind<Float>("\"abc\"", Float(1.1f));
123 statement.bind<Float>("\"ABC\"", Float(2.2f));
124 statement.bind<Float>("\"aBc\"", Float(3.3f));
125 session_.execute(statement);
126
127 // Validate the inserts into the table
128 Result result = session_.execute(default_select_all());
129 ASSERT_EQ(1u, result.row_count());
130 ASSERT_EQ(7u, result.column_count());
131 Row row = result.first_row();
132 ASSERT_EQ(key, row.column_by_name<TimeUuid>("key"));
133 ASSERT_EQ(Integer(9042), row.column_by_name<Integer>("a"));
134 ASSERT_EQ(Boolean(true), row.column_by_name<Boolean>("b"));
135 ASSERT_EQ(Text("yyz"), row.column_by_name<Text>("c"));
136 ASSERT_EQ(Float(1.1f), row.column_by_name<Float>("\"abc\""));
137 ASSERT_EQ(Float(2.2f), row.column_by_name<Float>("\"ABC\""));
138 ASSERT_EQ(Float(3.3f), row.column_by_name<Float>("\"aBc\""));
139 }
140
141 /**
142 * Insert all values into the table
143 *
144 * @param statement Insert statement to use (all format)
145 */
insert_and_validate_all_null(Statement statement)146 void insert_and_validate_all_null(Statement statement) {
147 // Create NULL wrapped objects for easier inserting and validation
148 TimeUuid key = uuid_generator_.generate_timeuuid();
149 Integer a = Integer();
150 Boolean b = Boolean();
151 Text c = Text();
152 Float abc = Float();
153
154 // Insert values into the table by name
155 statement.bind<TimeUuid>("key", key);
156 statement.bind<Integer>("a", a);
157 statement.bind<Boolean>("b", b);
158 statement.bind<Text>("c", c);
159 statement.bind<Float>("\"abc\"", abc);
160 statement.bind<Float>("\"ABC\"", abc);
161 statement.bind<Float>("\"aBc\"", abc);
162 session_.execute(statement);
163
164 // Validate the inserts into the table
165 Result result = session_.execute(default_select_all());
166 ASSERT_EQ(1u, result.row_count());
167 ASSERT_EQ(7u, result.column_count());
168 Row row = result.first_row();
169 ASSERT_EQ(key, row.column_by_name<TimeUuid>("key"));
170 ASSERT_TRUE(row.column_by_name<Integer>("a").is_null());
171 ASSERT_TRUE(row.column_by_name<Boolean>("b").is_null());
172 ASSERT_TRUE(row.column_by_name<Text>("c").is_null());
173 ASSERT_TRUE(row.column_by_name<Float>("\"abc\"").is_null());
174 ASSERT_TRUE(row.column_by_name<Float>("\"ABC\"").is_null());
175 ASSERT_TRUE(row.column_by_name<Float>("\"aBc\"").is_null());
176 }
177 };
178
179 /**
180 * By name (bytes) integration tests
181 */
182 class ByNameBytesTests : public Integration {
SetUp()183 virtual void SetUp() {
184 // Call the parent setup function
185 Integration::SetUp();
186
187 // Create the table for the test
188 session_.execute(format_string(TABLE_BYTES_FORMAT, table_name_.c_str()));
189 }
190 };
191
192 /**
193 * Perform `by name` references using a prepared statement and validate
194 *
195 * This test will perform a `by name` insert using a prepared statement and
196 * validate the results a single node cluster.
197 *
198 * @test_category queries:prepared
199 * @since core:1.0.0
200 * @expected_result Cassandra values are inserted and validated by name
201 */
CASSANDRA_INTEGRATION_TEST_F(ByNameTests,Prepared)202 CASSANDRA_INTEGRATION_TEST_F(ByNameTests, Prepared) {
203 CHECK_FAILURE;
204
205 // Prepare, create, insert and validate
206 Prepared prepared = session_.prepare(format_string(INSERT_FORMAT, table_name_.c_str()));
207 insert_and_validate(prepared.bind());
208 }
209
210 /**
211 * Perform `by name` references using a simple (bound) statement and validate
212 *
213 * This test will perform a `by name` insert using a simple statement and
214 * validate the results a single node cluster.
215 *
216 * @test_category queries:basic
217 * @since core:1.0.0
218 * @expected_result Cassandra values are inserted and validated by name
219 */
CASSANDRA_INTEGRATION_TEST_F(ByNameTests,Simple)220 CASSANDRA_INTEGRATION_TEST_F(ByNameTests, Simple) {
221 CHECK_FAILURE;
222
223 // Prepare, create, insert and validate
224 Statement statement(format_string(INSERT_FORMAT, table_name_.c_str()), 4);
225 insert_and_validate(statement);
226 }
227
228 /**
229 * Perform case sensitive `by name` references using a prepared statement and
230 * validate
231 *
232 * This test will perform a case sensitive`by name` insert using a prepared
233 * statement and validate the results a single node cluster.
234 *
235 * @test_category queries:prepared
236 * @since core:1.0.0
237 * @expected_result Cassandra values are inserted and validated by name
238 * (case sensitive)
239 */
CASSANDRA_INTEGRATION_TEST_F(ByNameTests,PreparedCaseSensitive)240 CASSANDRA_INTEGRATION_TEST_F(ByNameTests, PreparedCaseSensitive) {
241 CHECK_FAILURE;
242
243 // Prepare, create, insert and validate
244 Prepared prepared =
245 session_.prepare(format_string(INSERT_CASE_SENSITIVE_FORMAT, table_name_.c_str()));
246 insert_and_validate_case_sensitive(prepared.bind());
247 }
248
249 /**
250 * Perform case sensitive `by name` references using a simple (bound) statement
251 * and validate
252 *
253 * This test will perform a case sensitive `by name` insert using a simple
254 * statement and validate the results a single node cluster.
255 *
256 * @test_category queries:basic
257 * @since core:1.0.0
258 * @cassandra_version 2.1.0
259 * @expected_result Cassandra values are inserted and validated by name
260 * (case sensitive)
261 */
CASSANDRA_INTEGRATION_TEST_F(ByNameTests,SimpleCaseSensitive)262 CASSANDRA_INTEGRATION_TEST_F(ByNameTests, SimpleCaseSensitive) {
263 CHECK_FAILURE;
264 CHECK_VERSION(2.1.0);
265
266 // Prepare, create, insert and validate
267 Statement statement(format_string(INSERT_CASE_SENSITIVE_FORMAT, table_name_.c_str()), 4);
268 insert_and_validate_case_sensitive(statement);
269 }
270
271 /**
272 * Perform `by name` references using a prepared statement to insert multiple
273 * value and validate
274 *
275 * This test will perform bindings of a value to multiple columns `by name`
276 * insert using a prepared statement and validate the results a single node
277 * cluster.
278 *
279 * @test_category queries:prepared
280 * @since core:1.0.0
281 * @expected_result Cassandra values are inserted and validated by name
282 */
CASSANDRA_INTEGRATION_TEST_F(ByNameTests,MultipleBinds)283 CASSANDRA_INTEGRATION_TEST_F(ByNameTests, MultipleBinds) {
284 CHECK_FAILURE;
285
286 // Prepare, bind, and insert the values into the table
287 Prepared prepared =
288 session_.prepare(format_string(INSERT_CASE_SENSITIVE_FORMAT, table_name_.c_str()));
289 Statement statement = prepared.bind();
290 TimeUuid key = uuid_generator_.generate_timeuuid();
291 statement.bind<TimeUuid>("key", key);
292 statement.bind<Float>("abc", Float(1.23f)); // This should bind to columns `abc`, `ABC`, and `aBc`
293 session_.execute(statement);
294
295 // Validate the inserts to multiple binded columns
296 Result result = session_.execute(default_select_all());
297 ASSERT_EQ(1u, result.row_count());
298 ASSERT_EQ(7u, result.column_count());
299 Row row = result.first_row();
300 ASSERT_EQ(key, row.column_by_name<TimeUuid>("key"));
301 ASSERT_EQ(Float(1.23f), row.column_by_name<Float>("\"abc\""));
302 ASSERT_EQ(Float(1.23f), row.column_by_name<Float>("\"ABC\""));
303 ASSERT_EQ(Float(1.23f), row.column_by_name<Float>("\"aBc\""));
304 }
305
306 /**
307 * Perform `by name` references using a prepared statement against an invalid
308 * column name
309 *
310 * This test will attempt to bind an invalid column name to a prepared statement
311 * using a single node cluster.
312 *
313 * @test_category queries:prepared
314 * @since core:1.0.0
315 * @expected_result Driver error will occur when binding value to invalid column
316 * name
317 */
CASSANDRA_INTEGRATION_TEST_F(ByNameTests,BindUsingInvalidName)318 CASSANDRA_INTEGRATION_TEST_F(ByNameTests, BindUsingInvalidName) {
319 CHECK_FAILURE;
320
321 // Prepare and create the insert statement
322 Prepared prepared = session_.prepare(format_string(INSERT_ALL_FORMAT, table_name_.c_str()));
323 Statement statement = prepared.bind();
324
325 // Bind values to invalid columns name and validate error
326 CassError error_code = cass_statement_bind_int32_by_name(statement.get(), "d", 0);
327 ASSERT_EQ(CASS_ERROR_LIB_NAME_DOES_NOT_EXIST, error_code);
328 error_code = cass_statement_bind_float_by_name(statement.get(), "\"aBC", 0.0f);
329 ASSERT_EQ(CASS_ERROR_LIB_NAME_DOES_NOT_EXIST, error_code);
330 error_code = cass_statement_bind_float_by_name(statement.get(), "\"abC", 0.0f);
331 }
332
333 /**
334 * Perform `by name` references against an invalid column name lookup
335 *
336 * This test will perform a `by name` insert using a prepared statement and
337 * attempt to retrieve a column using an invalid name against a single node
338 * cluster.
339 *
340 * @test_category queries:basic
341 * @since core:1.0.0
342 * @expected_result Driver error will occur when retrieving value from invalid
343 * column name
344 */
CASSANDRA_INTEGRATION_TEST_F(ByNameTests,RetrieveInvalidName)345 CASSANDRA_INTEGRATION_TEST_F(ByNameTests, RetrieveInvalidName) {
346 CHECK_FAILURE;
347
348 // Prepare, create, insert and validate (all)
349 Prepared prepared = session_.prepare(format_string(INSERT_ALL_FORMAT, table_name_.c_str()));
350 Statement statement = prepared.bind();
351 insert_and_validate_all(statement);
352
353 // Retrieve the row and validate error using invalid column name
354 Result result = session_.execute(default_select_all());
355 Row row = result.first_row();
356 ASSERT_TRUE(NULL == cass_row_get_column_by_name(row.get(), "d"));
357 ASSERT_TRUE(NULL == cass_row_get_column_by_name(row.get(), "\"aBC\""));
358 ASSERT_TRUE(NULL == cass_row_get_column_by_name(row.get(), "\"abC\""));
359 }
360
361 /**
362 * Perform `by name` references using a prepared statement and validate values
363 * are NULL
364 *
365 * This test will perform a `by name` NULL insert using a prepared statement and
366 * validate the results a single node cluster.
367 *
368 * @test_category queries:prepared
369 * @since core:1.0.0
370 * @expected_result Cassandra NULL values are inserted and validated by name
371 */
CASSANDRA_INTEGRATION_TEST_F(ByNameTests,NullPrepared)372 CASSANDRA_INTEGRATION_TEST_F(ByNameTests, NullPrepared) {
373 CHECK_FAILURE;
374
375 // Prepare, create, insert and validate
376 Prepared prepared = session_.prepare(format_string(INSERT_ALL_FORMAT, table_name_.c_str()));
377 insert_and_validate_all_null(prepared.bind());
378 }
379
380 /**
381 * Perform `by name` references using a simple (bound) statement and validate
382 * values are NULL
383 *
384 * This test will perform a `by name` NULL insert using a simple statement and
385 * validate the results a single node cluster.
386 *
387 * @test_category queries:basic
388 * @since core:1.0.0
389 * @cassandra_version 2.1.0
390 * @expected_result Cassandra NULL values are inserted and validated by name
391 */
CASSANDRA_INTEGRATION_TEST_F(ByNameTests,NullSimple)392 CASSANDRA_INTEGRATION_TEST_F(ByNameTests, NullSimple) {
393 CHECK_FAILURE;
394 CHECK_VERSION(2.1.0);
395
396 // Prepare, create, insert and validate
397 Statement statement(format_string(INSERT_ALL_FORMAT, table_name_.c_str()), 7);
398 insert_and_validate_all_null(statement);
399 }
400
401 /**
402 * Perform `by name` references using a prepared statement and validate using
403 * bytes
404 *
405 * This test will perform a `by name` bytes insert using a prepared statement
406 * for `blob` and `varint` data types validating inserts.
407 *
408 * NOTE: This will be using a single node cluster.
409 *
410 * @jira_ticket CPP-272
411 * @test_category queries:basic
412 * @since core:2.1.0-beta
413 * @expected_result Bytes will be bound to `blob` and `varint` valued and will
414 * be validated by name
415 */
CASSANDRA_INTEGRATION_TEST_F(ByNameBytesTests,Prepared)416 CASSANDRA_INTEGRATION_TEST_F(ByNameBytesTests, Prepared) {
417 CHECK_FAILURE;
418
419 // Create values to be inserted in the test
420 TimeUuid key = uuid_generator_.generate_timeuuid();
421 Blob blobs("68971169783116971203269110116101114112114105115101329911211245100114105118101114");
422 Varint varints("1234567890123456789012345678901234567890");
423
424 // Prepare, bind, and insert the values into the table
425 Prepared prepared = session_.prepare(format_string(INSERT_BYTES_FORMAT, table_name_.c_str()));
426 Statement statement = prepared.bind();
427 statement.bind<TimeUuid>("key", key);
428 statement.bind<Blob>("blobs", blobs);
429 statement.bind<Varint>("varints", varints);
430 session_.execute(statement);
431
432 // Validate the inserts
433 Result result = session_.execute(default_select_all());
434 ASSERT_EQ(1u, result.row_count());
435 ASSERT_EQ(3u, result.column_count());
436 Row row = result.first_row();
437 ASSERT_EQ(key, row.column_by_name<TimeUuid>("key"));
438 ASSERT_EQ(blobs, row.column_by_name<Blob>("blobs"));
439 ASSERT_EQ(varints, row.column_by_name<Varint>("varints"));
440 }
441