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