1 /* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
22
23 // First include (the generated) my_config.h, to get correct platform defines.
24 #include "my_config.h"
25 #include <gtest/gtest.h>
26
27 #include "test_utils.h"
28
29 #include "opt_range.cc"
30
31 namespace opt_range_unittest {
32
33 using my_testing::Server_initializer;
34
35 class SelArgTest : public ::testing::Test
36 {
37 protected:
SelArgTest()38 SelArgTest()
39 {
40 memset(&m_opt_param, 0, sizeof(m_opt_param));
41 }
42
SetUp()43 virtual void SetUp()
44 {
45 initializer.SetUp();
46 m_opt_param.thd= thd();
47 m_opt_param.mem_root= &m_alloc;
48 m_opt_param.current_table= 1<<0;
49 init_sql_alloc(&m_alloc, thd()->variables.range_alloc_block_size, 0);
50 }
51
TearDown()52 virtual void TearDown()
53 {
54 initializer.TearDown();
55 free_root(&m_alloc, MYF(0));
56 }
57
thd()58 THD *thd() { return initializer.thd(); }
59
60 Server_initializer initializer;
61 MEM_ROOT m_alloc;
62 RANGE_OPT_PARAM m_opt_param;
63 };
64
65 /*
66 Experiment with these to measure performance of
67 'new (thd->mem_root)' Foo vs. 'new Foo'.
68 With gcc 4.4.2 I see ~4% difference (in optimized mode).
69 */
70 const int num_iterations= 10;
71 const int num_allocs= 10;
72
TEST_F(SelArgTest,AllocateExplicit)73 TEST_F(SelArgTest, AllocateExplicit)
74 {
75 for (int ix= 0; ix < num_iterations; ++ix)
76 {
77 free_root(thd()->mem_root, MYF(MY_KEEP_PREALLOC));
78 for (int ii= 0; ii < num_allocs; ++ii)
79 new (thd()->mem_root) SEL_ARG;
80 }
81 }
82
TEST_F(SelArgTest,AllocateImplicit)83 TEST_F(SelArgTest, AllocateImplicit)
84 {
85 for (int ix= 0; ix < num_iterations; ++ix)
86 {
87 free_root(thd()->mem_root, MYF(MY_KEEP_PREALLOC));
88 for (int ii= 0; ii < num_allocs; ++ii)
89 new SEL_ARG;
90 }
91 }
92
93 /*
94 We cannot do EXPECT_NE(NULL, get_mm_tree(...))
95 because of limits in google test.
96 */
97 const SEL_TREE *null_tree= NULL;
98 const SEL_ARG *null_arg= NULL;
99
100
101 class Mock_field_long : public Field_long
102 {
103 public:
Mock_field_long(THD * thd,Item * item)104 Mock_field_long(THD *thd, Item *item)
105 : Field_long(0, // ptr_arg
106 8, // len_arg
107 NULL, // null_ptr_arg
108 0, // null_bit_arg
109 Field::NONE, // unireg_check_arg
110 "field_name", // field_name_arg
111 false, // zero_arg
112 false) // unsigned_arg
113 {
114 m_table_name= "mock_table";
115 memset(static_cast<void*>(&m_share), 0, sizeof(m_share));
116 const char *foo= "mock_db";
117 m_share.db.str= const_cast<char*>(foo);
118 m_share.db.length= strlen(m_share.db.str);
119
120 bitmap_init(&share_allset, 0, sizeof(my_bitmap_map), 0);
121 bitmap_set_above(&share_allset, 0, 1); //all bits 1
122 m_share.all_set= share_allset;
123
124 memset(static_cast<void*>(&m_table), 0, sizeof(m_table));
125 m_table.s= &m_share;
126
127 bitmap_init(&tbl_readset, 0, sizeof(my_bitmap_map), 0);
128 m_table.read_set= &tbl_readset;
129
130 bitmap_init(&tbl_writeset, 0, sizeof(my_bitmap_map), 0);
131 m_table.write_set= &tbl_writeset;
132
133 m_table.map= 1<<0;
134 m_table.in_use= thd;
135 this->table_name= &m_table_name;
136 this->table= &m_table;
137 this->ptr= (uchar*) alloc_root((thd->mem_root), KEY_LENGTH);
138 if (item)
139 item->save_in_field_no_warnings(this, true);
140 }
~Mock_field_long()141 ~Mock_field_long()
142 {
143 bitmap_free(&share_allset);
144 bitmap_free(&tbl_readset);
145 bitmap_free(&tbl_writeset);
146 }
147
148 // #bytes to store the value - see Field_long::key_lenght()
149 static const int KEY_LENGTH= 4;
150 const char *m_table_name;
151 TABLE_SHARE m_share;
152 TABLE m_table;
153 MY_BITMAP share_allset;
154 MY_BITMAP tbl_readset;
155 MY_BITMAP tbl_writeset;
156 };
157
158
print_selarg_ranges(String * s,SEL_ARG * sel_arg,const KEY_PART_INFO * kpi)159 static void print_selarg_ranges(String *s, SEL_ARG *sel_arg,
160 const KEY_PART_INFO *kpi)
161 {
162 for (SEL_ARG *cur= sel_arg->first();
163 cur != &null_element;
164 cur= cur->right)
165 {
166 String current_range;
167 append_range(¤t_range, kpi, cur->min_value, cur->max_value,
168 cur->min_flag | cur->max_flag);
169
170 if (s->length() > 0)
171 s->append(STRING_WITH_LEN("\n"));
172
173 s->append(current_range);
174 }
175 }
176
177
TEST_F(SelArgTest,SimpleCond)178 TEST_F(SelArgTest, SimpleCond)
179 {
180 EXPECT_NE(null_tree, get_mm_tree(&m_opt_param, new Item_int(42)));
181 }
182
183
184 /*
185 TODO: Here we try to build a range, but a lot of mocking remains
186 before it works as intended. Currently get_mm_tree() returns NULL
187 because m_opt_param.key_parts and m_opt_param.key_parts_end have not
188 been setup.
189 */
TEST_F(SelArgTest,EqualCond)190 TEST_F(SelArgTest, EqualCond)
191 {
192 Mock_field_long field_long(thd(), NULL);
193 m_opt_param.table= &field_long.m_table;
194 SEL_TREE *tree= get_mm_tree(&m_opt_param,
195 new Item_equal(new Item_int(42),
196 new Item_field(&field_long)));
197 EXPECT_EQ(null_tree, tree);
198 }
199
200
TEST_F(SelArgTest,SelArgOnevalue)201 TEST_F(SelArgTest, SelArgOnevalue)
202 {
203 Mock_field_long field_long7(thd(), new Item_int(7));
204
205 KEY_PART_INFO kpi;
206 kpi.init_from_field(&field_long7);
207
208 uchar range_val7[field_long7.KEY_LENGTH];
209 field_long7.get_key_image(range_val7, kpi.length, Field::itRAW);
210
211 SEL_ARG sel_arg7(&field_long7, range_val7, range_val7);
212 String range_string;
213 print_selarg_ranges(&range_string, &sel_arg7, &kpi);
214 const char expected[]= "7 <= field_name <= 7";
215 EXPECT_STREQ(expected, range_string.c_ptr());
216
217 sel_arg7.min_flag|= NO_MIN_RANGE;
218 range_string.length(0);
219 print_selarg_ranges(&range_string, &sel_arg7, &kpi);
220 const char expected2[]= "field_name <= 7";
221 EXPECT_STREQ(expected2, range_string.c_ptr());
222
223 sel_arg7.max_flag= NEAR_MAX;
224 range_string.length(0);
225 print_selarg_ranges(&range_string, &sel_arg7, &kpi);
226 const char expected3[]= "field_name < 7";
227 EXPECT_STREQ(expected3, range_string.c_ptr());
228
229 sel_arg7.min_flag= NEAR_MIN;
230 sel_arg7.max_flag= NO_MAX_RANGE;
231 range_string.length(0);
232 print_selarg_ranges(&range_string, &sel_arg7, &kpi);
233 const char expected4[]= "7 < field_name";
234 EXPECT_STREQ(expected4, range_string.c_ptr());
235
236 sel_arg7.min_flag= 0;
237 range_string.length(0);
238 print_selarg_ranges(&range_string, &sel_arg7, &kpi);
239 const char expected5[]= "7 <= field_name";
240 EXPECT_STREQ(expected5, range_string.c_ptr());
241 }
242
243
TEST_F(SelArgTest,SelArgBetween)244 TEST_F(SelArgTest, SelArgBetween)
245 {
246 Mock_field_long field_long3(thd(), new Item_int(3));
247 Mock_field_long field_long5(thd(), new Item_int(5));
248
249 KEY_PART_INFO kpi;
250 kpi.init_from_field(&field_long3);
251
252 uchar range_val3[field_long3.KEY_LENGTH];
253 field_long3.get_key_image(range_val3, kpi.length, Field::itRAW);
254
255 uchar range_val5[field_long5.KEY_LENGTH];
256 field_long5.get_key_image(range_val5, kpi.length, Field::itRAW);
257
258 SEL_ARG sel_arg35(&field_long3, range_val3, range_val5);
259
260 String range_string;
261 print_selarg_ranges(&range_string, &sel_arg35, &kpi);
262 const char expected[]= "3 <= field_name <= 5";
263 EXPECT_STREQ(expected, range_string.c_ptr());
264
265 range_string.length(0);
266 sel_arg35.min_flag= NEAR_MIN;
267 print_selarg_ranges(&range_string, &sel_arg35, &kpi);
268 const char expected2[]= "3 < field_name <= 5";
269 EXPECT_STREQ(expected2, range_string.c_ptr());
270
271 range_string.length(0);
272 sel_arg35.max_flag= NEAR_MAX;
273 print_selarg_ranges(&range_string, &sel_arg35, &kpi);
274 const char expected3[]= "3 < field_name < 5";
275 EXPECT_STREQ(expected3, range_string.c_ptr());
276
277 range_string.length(0);
278 sel_arg35.min_flag= 0;
279 print_selarg_ranges(&range_string, &sel_arg35, &kpi);
280 const char expected4[]= "3 <= field_name < 5";
281 EXPECT_STREQ(expected4, range_string.c_ptr());
282
283 range_string.length(0);
284 sel_arg35.min_flag= NO_MIN_RANGE;
285 sel_arg35.max_flag= 0;
286 print_selarg_ranges(&range_string, &sel_arg35, &kpi);
287 const char expected5[]= "field_name <= 5";
288 EXPECT_STREQ(expected5, range_string.c_ptr());
289
290 range_string.length(0);
291 sel_arg35.min_flag= 0;
292 sel_arg35.max_flag= NO_MAX_RANGE;
293 print_selarg_ranges(&range_string, &sel_arg35, &kpi);
294 const char expected6[]= "3 <= field_name";
295 EXPECT_STREQ(expected6, range_string.c_ptr());
296 }
297
TEST_F(SelArgTest,CopyMax)298 TEST_F(SelArgTest, CopyMax)
299 {
300 Mock_field_long field_long3(thd(), new Item_int(3));
301 Mock_field_long field_long5(thd(), new Item_int(5));
302
303 KEY_PART_INFO kpi;
304 kpi.init_from_field(&field_long3);
305
306 uchar range_val3[field_long3.KEY_LENGTH];
307 field_long3.get_key_image(range_val3, kpi.length, Field::itRAW);
308
309 uchar range_val5[field_long5.KEY_LENGTH];
310 field_long5.get_key_image(range_val5, kpi.length, Field::itRAW);
311
312 SEL_ARG sel_arg3(&field_long3, range_val3, range_val3);
313 sel_arg3.min_flag= NO_MIN_RANGE;
314 SEL_ARG sel_arg5(&field_long5, range_val5, range_val5);
315 sel_arg5.min_flag= NO_MIN_RANGE;
316
317 String range_string;
318 print_selarg_ranges(&range_string, &sel_arg3, &kpi);
319 const char expected[]= "field_name <= 3";
320 EXPECT_STREQ(expected, range_string.c_ptr());
321
322 range_string.length(0);
323 print_selarg_ranges(&range_string, &sel_arg5, &kpi);
324 const char expected2[]= "field_name <= 5";
325 EXPECT_STREQ(expected2, range_string.c_ptr());
326
327 /*
328 Ranges now:
329 -inf ----------------3-5----------- +inf
330 sel_arg3: [-------------------->
331 sel_arg5: [---------------------->
332 Below: merge these two ranges into sel_arg3 using copy_max()
333 */
334 bool full_range= sel_arg3.copy_max(&sel_arg5);
335 // The merged range does not cover all possible values
336 EXPECT_FALSE(full_range);
337
338 range_string.length(0);
339 print_selarg_ranges(&range_string, &sel_arg3, &kpi);
340 const char expected3[]= "field_name <= 5";
341 EXPECT_STREQ(expected3, range_string.c_ptr());
342
343 range_string.length(0);
344 sel_arg5.min_flag= 0;
345 sel_arg5.max_flag= NO_MAX_RANGE;
346 print_selarg_ranges(&range_string, &sel_arg5, &kpi);
347 const char expected4[]= "5 <= field_name";
348 EXPECT_STREQ(expected4, range_string.c_ptr());
349
350 /*
351 Ranges now:
352 -inf ----------------3-5----------- +inf
353 sel_arg3: [---------------------->
354 sel_arg5: <---------------]
355 Below: merge these two ranges into sel_arg3 using copy_max()
356 */
357
358 full_range= sel_arg3.copy_max(&sel_arg5);
359 // The new range covers all possible values
360 EXPECT_TRUE(full_range);
361
362 range_string.length(0);
363 print_selarg_ranges(&range_string, &sel_arg3, &kpi);
364 const char expected5[]= "field_name";
365 EXPECT_STREQ(expected5, range_string.c_ptr());
366 }
367
TEST_F(SelArgTest,CopyMin)368 TEST_F(SelArgTest, CopyMin)
369 {
370 Mock_field_long field_long3(thd(), new Item_int(3));
371 Mock_field_long field_long5(thd(), new Item_int(5));
372
373 KEY_PART_INFO kpi;
374 kpi.init_from_field(&field_long3);
375
376 uchar range_val3[field_long3.KEY_LENGTH];
377 field_long3.get_key_image(range_val3, kpi.length, Field::itRAW);
378
379 uchar range_val5[field_long5.KEY_LENGTH];
380 field_long5.get_key_image(range_val5, kpi.length, Field::itRAW);
381
382 SEL_ARG sel_arg3(&field_long3, range_val3, range_val3);
383 sel_arg3.max_flag= NO_MAX_RANGE;
384 SEL_ARG sel_arg5(&field_long5, range_val5, range_val5);
385 sel_arg5.max_flag= NO_MAX_RANGE;
386
387 String range_string;
388 print_selarg_ranges(&range_string, &sel_arg3, &kpi);
389 const char expected[]= "3 <= field_name";
390 EXPECT_STREQ(expected, range_string.c_ptr());
391
392 range_string.length(0);
393 print_selarg_ranges(&range_string, &sel_arg5, &kpi);
394 const char expected2[]= "5 <= field_name";
395 EXPECT_STREQ(expected2, range_string.c_ptr());
396
397 /*
398 Ranges now:
399 -inf ----------------3-5----------- +inf
400 sel_arg3: <-----------------]
401 sel_arg5: <---------------]
402 Below: merge these two ranges into sel_arg3 using copy_max()
403 */
404 bool full_range= sel_arg5.copy_min(&sel_arg3);
405 // The merged range does not cover all possible values
406 EXPECT_FALSE(full_range);
407
408 range_string.length(0);
409 print_selarg_ranges(&range_string, &sel_arg5, &kpi);
410 const char expected3[]= "3 <= field_name";
411 EXPECT_STREQ(expected3, range_string.c_ptr());
412
413 range_string.length(0);
414 sel_arg3.max_flag= 0;
415 sel_arg3.min_flag= NO_MIN_RANGE;
416 print_selarg_ranges(&range_string, &sel_arg3, &kpi);
417 const char expected4[]= "field_name <= 3";
418 EXPECT_STREQ(expected4, range_string.c_ptr());
419
420 /*
421 Ranges now:
422 -inf ----------------3-5----------- +inf
423 sel_arg3: [-------------------->
424 sel_arg5: <-----------------]
425 Below: merge these two ranges into sel_arg5 using copy_min()
426 */
427
428 full_range= sel_arg5.copy_min(&sel_arg3);
429 // The new range covers all possible values
430 EXPECT_TRUE(full_range);
431
432 range_string.length(0);
433 print_selarg_ranges(&range_string, &sel_arg5, &kpi);
434 const char expected5[]= "field_name";
435 EXPECT_STREQ(expected5, range_string.c_ptr());
436 }
437
438
TEST_F(SelArgTest,KeyOr1)439 TEST_F(SelArgTest, KeyOr1)
440 {
441 Mock_field_long field_long3(thd(), new Item_int(3));
442 Mock_field_long field_long4(thd(), new Item_int(4));
443
444 KEY_PART_INFO kpi;
445 kpi.init_from_field(&field_long3);
446
447 uchar range_val3[field_long3.KEY_LENGTH];
448 field_long3.get_key_image(range_val3, kpi.length, Field::itRAW);
449
450 uchar range_val4[field_long4.KEY_LENGTH];
451 field_long4.get_key_image(range_val4, kpi.length, Field::itRAW);
452
453 SEL_ARG sel_arg_lt3(&field_long3, range_val3, range_val3);
454 sel_arg_lt3.part= 0;
455 sel_arg_lt3.min_flag= NO_MIN_RANGE;
456 sel_arg_lt3.max_flag= NEAR_MAX;
457
458 SEL_ARG sel_arg_gt3(&field_long3, range_val3, range_val3);
459 sel_arg_gt3.part= 0;
460 sel_arg_gt3.min_flag= NEAR_MIN;
461 sel_arg_gt3.max_flag= NO_MAX_RANGE;
462
463 SEL_ARG sel_arg_lt4(&field_long4, range_val4, range_val4);
464 sel_arg_lt4.part= 0;
465 sel_arg_lt4.min_flag= NO_MIN_RANGE;
466 sel_arg_lt4.max_flag= NEAR_MAX;
467
468 String range_string;
469 print_selarg_ranges(&range_string, &sel_arg_lt3, &kpi);
470 const char expected_lt3[]= "field_name < 3";
471 EXPECT_STREQ(expected_lt3, range_string.c_ptr());
472
473 range_string.length(0);
474 print_selarg_ranges(&range_string, &sel_arg_gt3, &kpi);
475 const char expected_gt3[]= "3 < field_name";
476 EXPECT_STREQ(expected_gt3, range_string.c_ptr());
477
478 range_string.length(0);
479 print_selarg_ranges(&range_string, &sel_arg_lt4, &kpi);
480 const char expected_lt4[]= "field_name < 4";
481 EXPECT_STREQ(expected_lt4, range_string.c_ptr());
482
483
484 /*
485 Ranges now:
486 -inf ----------------34----------- +inf
487 sel_arg_lt3: [-------------------->
488 sel_arg_gt3: <---------------]
489 sel_arg_lt4: [--------------------->
490 */
491
492 SEL_ARG *tmp= key_or(NULL, &sel_arg_lt3, &sel_arg_gt3);
493
494 /*
495 Ranges now:
496 -inf ----------------34----------- +inf
497 tmp: [--------------------><---------------]
498 sel_arg_lt4: [--------------------->
499 */
500 range_string.length(0);
501 print_selarg_ranges(&range_string, tmp, &kpi);
502 const char expected_merged[]=
503 "field_name < 3\n"
504 "3 < field_name";
505 EXPECT_STREQ(expected_merged, range_string.c_ptr());
506
507 SEL_ARG *tmp2= key_or(NULL, tmp, &sel_arg_lt4);
508 EXPECT_EQ(null_arg, tmp2);
509 }
510
511 }
512
513
514