1
/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
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.
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.
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 */
16
// First include (the generated) my_config.h, to get correct platform defines.
17
#include "my_config.h"
18
#include <gtest/gtest.h>
20
#include "test_utils.h"
22
#include "opt_range.cc"
24
namespace opt_range_unittest {
26
using my_testing::Server_initializer;
28
class SelArgTest : public ::testing::Test
33
memset(&m_opt_param, 0, sizeof(m_opt_param));
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);
45
virtual void TearDown()
47
initializer.TearDown();
48
free_root(&m_alloc, MYF(0));
51
THD *thd() { return initializer.thd(); }
53
Server_initializer initializer;
55
RANGE_OPT_PARAM m_opt_param;
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).
63
const int num_iterations= 10;
64
const int num_allocs= 10;
66
TEST_F(SelArgTest, AllocateExplicit)
68
for (int ix= 0; ix < num_iterations; ++ix)
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;
76
TEST_F(SelArgTest, AllocateImplicit)
78
for (int ix= 0; ix < num_iterations; ++ix)
80
free_root(thd()->mem_root, MYF(MY_KEEP_PREALLOC));
81
for (int ii= 0; ii < num_allocs; ++ii)
87
We cannot do EXPECT_NE(NULL, get_mm_tree(...))
88
because of limits in google test.
90
const SEL_TREE *null_tree= NULL;
91
const SEL_ARG *null_arg= NULL;
94
class Mock_field_long : public Field_long
97
Mock_field_long(THD *thd, Item *item)
98
: Field_long(0, // ptr_arg
100
NULL, // null_ptr_arg
102
Field::NONE, // unireg_check_arg
103
"field_name", // field_name_arg
105
false) // unsigned_arg
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);
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;
117
memset(&m_table, 0, sizeof(m_table));
120
bitmap_init(&tbl_readset, 0, sizeof(my_bitmap_map), 0);
121
m_table.read_set= &tbl_readset;
123
bitmap_init(&tbl_writeset, 0, sizeof(my_bitmap_map), 0);
124
m_table.write_set= &tbl_writeset;
128
this->table_name= &m_table_name;
129
this->table= &m_table;
130
this->ptr= (uchar*) alloc_root((thd->mem_root), KEY_LENGTH);
132
item->save_in_field_no_warnings(this, true);
136
bitmap_free(&share_allset);
137
bitmap_free(&tbl_readset);
138
bitmap_free(&tbl_writeset);
141
// #bytes to store the value - see Field_long::key_lenght()
142
static const int KEY_LENGTH= 4;
143
const char *m_table_name;
146
MY_BITMAP share_allset;
147
MY_BITMAP tbl_readset;
148
MY_BITMAP tbl_writeset;
152
static void print_selarg_ranges(String *s, SEL_ARG *sel_arg,
153
const KEY_PART_INFO *kpi)
155
for (SEL_ARG *cur= sel_arg->first();
156
cur != &null_element;
159
String current_range;
160
append_range(¤t_range, kpi, cur->min_value, cur->max_value,
161
cur->min_flag | cur->max_flag);
164
s->append(STRING_WITH_LEN("\n"));
166
s->append(current_range);
171
TEST_F(SelArgTest, SimpleCond)
173
EXPECT_NE(null_tree, get_mm_tree(&m_opt_param, new Item_int(42)));
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
183
TEST_F(SelArgTest, EqualCond)
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);
194
TEST_F(SelArgTest, SelArgOnevalue)
196
Mock_field_long field_long7(thd(), new Item_int(7));
199
kpi.init_from_field(&field_long7);
201
uchar range_val7[field_long7.KEY_LENGTH];
202
field_long7.get_key_image(range_val7, kpi.length, Field::itRAW);
204
SEL_ARG sel_arg7(&field_long7, range_val7, range_val7);
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());
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());
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());
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());
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());
237
TEST_F(SelArgTest, SelArgBetween)
239
Mock_field_long field_long3(thd(), new Item_int(3));
240
Mock_field_long field_long5(thd(), new Item_int(5));
243
kpi.init_from_field(&field_long3);
245
uchar range_val3[field_long3.KEY_LENGTH];
246
field_long3.get_key_image(range_val3, kpi.length, Field::itRAW);
248
uchar range_val5[field_long5.KEY_LENGTH];
249
field_long5.get_key_image(range_val5, kpi.length, Field::itRAW);
251
SEL_ARG sel_arg35(&field_long3, range_val3, range_val5);
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());
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());
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());
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());
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());
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());
291
TEST_F(SelArgTest, CopyMax)
293
Mock_field_long field_long3(thd(), new Item_int(3));
294
Mock_field_long field_long5(thd(), new Item_int(5));
297
kpi.init_from_field(&field_long3);
299
uchar range_val3[field_long3.KEY_LENGTH];
300
field_long3.get_key_image(range_val3, kpi.length, Field::itRAW);
302
uchar range_val5[field_long5.KEY_LENGTH];
303
field_long5.get_key_image(range_val5, kpi.length, Field::itRAW);
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;
311
print_selarg_ranges(&range_string, &sel_arg3, &kpi);
312
const char expected[]= "field_name <= 3";
313
EXPECT_STREQ(expected, range_string.c_ptr());
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());
322
-inf ----------------3-5----------- +inf
323
sel_arg3: [-------------------->
324
sel_arg5: [---------------------->
325
Below: merge these two ranges into sel_arg3 using copy_max()
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);
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());
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());
345
-inf ----------------3-5----------- +inf
346
sel_arg3: [---------------------->
347
sel_arg5: <---------------]
348
Below: merge these two ranges into sel_arg3 using copy_max()
351
full_range= sel_arg3.copy_max(&sel_arg5);
352
// The new range covers all possible values
353
EXPECT_TRUE(full_range);
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());
361
TEST_F(SelArgTest, CopyMin)
363
Mock_field_long field_long3(thd(), new Item_int(3));
364
Mock_field_long field_long5(thd(), new Item_int(5));
367
kpi.init_from_field(&field_long3);
369
uchar range_val3[field_long3.KEY_LENGTH];
370
field_long3.get_key_image(range_val3, kpi.length, Field::itRAW);
372
uchar range_val5[field_long5.KEY_LENGTH];
373
field_long5.get_key_image(range_val5, kpi.length, Field::itRAW);
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;
381
print_selarg_ranges(&range_string, &sel_arg3, &kpi);
382
const char expected[]= "3 <= field_name";
383
EXPECT_STREQ(expected, range_string.c_ptr());
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());
392
-inf ----------------3-5----------- +inf
393
sel_arg3: <-----------------]
394
sel_arg5: <---------------]
395
Below: merge these two ranges into sel_arg3 using copy_max()
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);
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());
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());
415
-inf ----------------3-5----------- +inf
416
sel_arg3: [-------------------->
417
sel_arg5: <-----------------]
418
Below: merge these two ranges into sel_arg5 using copy_min()
421
full_range= sel_arg5.copy_min(&sel_arg3);
422
// The new range covers all possible values
423
EXPECT_TRUE(full_range);
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());
432
TEST_F(SelArgTest, KeyOr1)
434
Mock_field_long field_long3(thd(), new Item_int(3));
435
Mock_field_long field_long4(thd(), new Item_int(4));
438
kpi.init_from_field(&field_long3);
440
uchar range_val3[field_long3.KEY_LENGTH];
441
field_long3.get_key_image(range_val3, kpi.length, Field::itRAW);
443
uchar range_val4[field_long4.KEY_LENGTH];
444
field_long4.get_key_image(range_val4, kpi.length, Field::itRAW);
446
SEL_ARG sel_arg_lt3(&field_long3, range_val3, range_val3);
448
sel_arg_lt3.min_flag= NO_MIN_RANGE;
449
sel_arg_lt3.max_flag= NEAR_MAX;
451
SEL_ARG sel_arg_gt3(&field_long3, range_val3, range_val3);
453
sel_arg_gt3.min_flag= NEAR_MIN;
454
sel_arg_gt3.max_flag= NO_MAX_RANGE;
456
SEL_ARG sel_arg_lt4(&field_long4, range_val4, range_val4);
458
sel_arg_lt4.min_flag= NO_MIN_RANGE;
459
sel_arg_lt4.max_flag= NEAR_MAX;
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());
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());
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());
479
-inf ----------------34----------- +inf
480
sel_arg_lt3: [-------------------->
481
sel_arg_gt3: <---------------]
482
sel_arg_lt4: [--------------------->
485
SEL_ARG *tmp= key_or(NULL, &sel_arg_lt3, &sel_arg_gt3);
489
-inf ----------------34----------- +inf
490
tmp: [--------------------><---------------]
491
sel_arg_lt4: [--------------------->
493
range_string.length(0);
494
print_selarg_ranges(&range_string, tmp, &kpi);
495
const char expected_merged[]=
498
EXPECT_STREQ(expected_merged, range_string.c_ptr());
500
SEL_ARG *tmp2= key_or(NULL, tmp, &sel_arg_lt4);
501
EXPECT_EQ(null_arg, tmp2);