@@ -144,12 +144,42 @@ class Item_bool_func :public Item_int_func
144
144
virtual SEL_TREE *get_func_mm_tree (RANGE_OPT_PARAM *param,
145
145
Field *field, Item *value)
146
146
{
147
- DBUG_ENTER (" Item_bool_func2 ::get_func_mm_tree" );
147
+ DBUG_ENTER (" Item_bool_func ::get_func_mm_tree" );
148
148
DBUG_ASSERT (0 );
149
149
DBUG_RETURN (0 );
150
150
}
151
+ /*
152
+ Return the full select tree for "field_item" and "value":
153
+ - a single SEL_TREE if the field is not in a multiple equality, or
154
+ - a conjuction of all SEL_TREEs for all fields from
155
+ the same multiple equality with "field_item".
156
+ */
151
157
SEL_TREE *get_full_func_mm_tree (RANGE_OPT_PARAM *param,
152
158
Item_field *field_item, Item *value);
159
+ /* *
160
+ Test if "item" and "value" are suitable for the range optimization
161
+ and get their full select tree.
162
+
163
+ "Suitable" means:
164
+ - "item" is a field or a field reference
165
+ - "value" is NULL (e.g. WHERE field IS NULL), or
166
+ "value" is an unexpensive item (e.g. WHERE field OP value)
167
+
168
+ @param item - the argument that is checked to be a field
169
+ @param value - the other argument
170
+ @returns - NULL if the arguments are not suitable for the range optimizer.
171
+ @returns - the full select tree if the arguments are suitable.
172
+ */
173
+ SEL_TREE *get_full_func_mm_tree_for_args (RANGE_OPT_PARAM *param,
174
+ Item *item, Item *value)
175
+ {
176
+ DBUG_ENTER (" Item_bool_func::get_full_func_mm_tree_for_args" );
177
+ Item *field= item->real_item ();
178
+ if (field->type () == Item::FIELD_ITEM && !field->const_item () &&
179
+ (!value || !value->is_expensive ()))
180
+ DBUG_RETURN (get_full_func_mm_tree (param, (Item_field *) field, value));
181
+ DBUG_RETURN (NULL );
182
+ }
153
183
SEL_TREE *get_mm_parts (RANGE_OPT_PARAM *param, Field *field,
154
184
Item_func::Functype type, Item *value);
155
185
SEL_TREE *get_ne_mm_tree (RANGE_OPT_PARAM *param,
@@ -324,33 +354,15 @@ class Item_in_optimizer: public Item_bool_func
324
354
*/
325
355
class Item_bool_func2 :public Item_bool_func
326
356
{ /* Bool with 2 string args */
327
- bool have_rev_func () const { return rev_functype () != UNKNOWN_FUNC; }
328
357
protected:
329
358
void add_key_fields_optimize_op (JOIN *join, KEY_FIELD **key_fields,
330
359
uint *and_level, table_map usable_tables,
331
360
SARGABLE_PARAM **sargables, bool equal_func);
332
- SEL_TREE *get_func_mm_tree (RANGE_OPT_PARAM *param,
333
- Field *field, Item *value)
334
- {
335
- DBUG_ENTER (" Item_bool_func2::get_func_mm_tree" );
336
- /*
337
- Here the function for the following predicates are processed:
338
- <, <=, =, <=>, >=, >, LIKE, spatial relations
339
- If the predicate is of the form (value op field) it is handled
340
- as the equivalent predicate (field rev_op value), e.g.
341
- 2 <= a is handled as a >= 2.
342
- */
343
- Item_func::Functype func_type=
344
- (value != arguments ()[0 ]) ? functype () : rev_functype ();
345
- DBUG_RETURN (get_mm_parts (param, field, func_type, value));
346
- }
347
361
public:
348
362
Item_bool_func2 (THD *thd, Item *a, Item *b):
349
363
Item_bool_func (thd, a, b) { }
350
- virtual enum Functype rev_functype () const { return UNKNOWN_FUNC; }
351
364
352
365
bool is_null () { return MY_TEST (args[0 ]->is_null () || args[1 ]->is_null ()); }
353
- SEL_TREE *get_mm_tree (RANGE_OPT_PARAM *param, Item **cond_ptr);
354
366
COND *remove_eq_conds (THD *thd, Item::cond_result *cond_value,
355
367
bool top_level);
356
368
bool count_sargable_conds (uchar *arg);
@@ -368,15 +380,87 @@ class Item_bool_func2 :public Item_bool_func
368
380
*/
369
381
return STRING_RESULT;
370
382
}
383
+ SEL_TREE *get_mm_tree (RANGE_OPT_PARAM *param, Item **cond_ptr)
384
+ {
385
+ DBUG_ENTER (" Item_bool_func2::get_mm_tree" );
386
+ DBUG_ASSERT (arg_count == 2 );
387
+ SEL_TREE *ftree= get_full_func_mm_tree_for_args (param, args[0 ], args[1 ]);
388
+ if (!ftree)
389
+ ftree= Item_func::get_mm_tree (param, cond_ptr);
390
+ DBUG_RETURN (ftree);
391
+ }
392
+ };
393
+
394
+
395
+ /* *
396
+ A class for functions and operators that can use the range optimizer and
397
+ have a reverse function/operator that can also use the range optimizer,
398
+ so this condition:
399
+ WHERE value OP field
400
+ can be optimized as equivalent to:
401
+ WHERE field REV_OP value
402
+
403
+ This class covers:
404
+ - scalar comparison predicates: <, <=, =, <=>, >=, >
405
+ - MBR and precise spatial relation predicates (e.g. SP_TOUCHES(x,y))
406
+
407
+ For example:
408
+ WHERE 10 > field
409
+ can be optimized as:
410
+ WHERE field < 10
411
+ */
412
+ class Item_bool_func2_with_rev :public Item_bool_func2
413
+ {
414
+ protected:
415
+ SEL_TREE *get_func_mm_tree (RANGE_OPT_PARAM *param,
416
+ Field *field, Item *value)
417
+ {
418
+ DBUG_ENTER (" Item_bool_func2_with_rev::get_func_mm_tree" );
419
+ Item_func::Functype func_type=
420
+ (value != arguments ()[0 ]) ? functype () : rev_functype ();
421
+ DBUG_RETURN (get_mm_parts (param, field, func_type, value));
422
+ }
423
+ public:
424
+ Item_bool_func2_with_rev (THD *thd, Item *a, Item *b):
425
+ Item_bool_func2 (thd, a, b) { }
426
+ virtual enum Functype rev_functype () const = 0;
427
+ SEL_TREE *get_mm_tree (RANGE_OPT_PARAM *param, Item **cond_ptr)
428
+ {
429
+ DBUG_ENTER (" Item_bool_func2_with_rev::get_mm_tree" );
430
+ DBUG_ASSERT (arg_count == 2 );
431
+ SEL_TREE *ftree;
432
+ /*
433
+ Even if get_full_func_mm_tree_for_args(param, args[0], args[1]) will not
434
+ return a range predicate it may still be possible to create one
435
+ by reversing the order of the operands. Note that this only
436
+ applies to predicates where both operands are fields. Example: A
437
+ query of the form
438
+
439
+ WHERE t1.a OP t2.b
440
+
441
+ In this case, args[0] == t1.a and args[1] == t2.b.
442
+ When creating range predicates for t2,
443
+ get_full_func_mm_tree_for_args(param, args[0], args[1])
444
+ will return NULL because 'field' belongs to t1 and only
445
+ predicates that applies to t2 are of interest. In this case a
446
+ call to get_full_func_mm_tree_for_args() with reversed operands
447
+ may succeed.
448
+ */
449
+ if (!(ftree= get_full_func_mm_tree_for_args (param, args[0 ], args[1 ])) &&
450
+ !(ftree= get_full_func_mm_tree_for_args (param, args[1 ], args[0 ])))
451
+ ftree= Item_func::get_mm_tree (param, cond_ptr);
452
+ DBUG_RETURN (ftree);
453
+ }
371
454
};
372
455
373
- class Item_bool_rowready_func2 :public Item_bool_func2
456
+
457
+ class Item_bool_rowready_func2 :public Item_bool_func2_with_rev
374
458
{
375
459
protected:
376
460
Arg_comparator cmp;
377
461
public:
378
462
Item_bool_rowready_func2 (THD *thd, Item *a, Item *b):
379
- Item_bool_func2 (thd, a, b), cmp(tmp_arg, tmp_arg + 1 )
463
+ Item_bool_func2_with_rev (thd, a, b), cmp(tmp_arg, tmp_arg + 1 )
380
464
{
381
465
allowed_arg_cols= 0 ; // Fetch this value from first argument
382
466
}
@@ -1495,7 +1579,14 @@ class Item_func_null_predicate :public Item_bool_func
1495
1579
Item_func_null_predicate (THD *thd, Item *a): Item_bool_func(thd, a) { }
1496
1580
void add_key_fields (JOIN *join, KEY_FIELD **key_fields, uint *and_level,
1497
1581
table_map usable_tables, SARGABLE_PARAM **sargables);
1498
- SEL_TREE *get_mm_tree (RANGE_OPT_PARAM *param, Item **cond_ptr);
1582
+ SEL_TREE *get_mm_tree (RANGE_OPT_PARAM *param, Item **cond_ptr)
1583
+ {
1584
+ DBUG_ENTER (" Item_func_null_predicate::get_mm_tree" );
1585
+ SEL_TREE *ftree= get_full_func_mm_tree_for_args (param, args[0 ], NULL );
1586
+ if (!ftree)
1587
+ ftree= Item_func::get_mm_tree (param, cond_ptr);
1588
+ DBUG_RETURN (ftree);
1589
+ }
1499
1590
CHARSET_INFO *compare_collation () const
1500
1591
{ return args[0 ]->collation .collation ; }
1501
1592
void fix_length_and_dec () { decimals=0 ; max_length=1 ; maybe_null=0 ; }
@@ -1608,6 +1699,12 @@ class Item_func_like :public Item_bool_func2
1608
1699
String cmp_value1, cmp_value2;
1609
1700
bool with_sargable_pattern () const ;
1610
1701
protected:
1702
+ SEL_TREE *get_func_mm_tree (RANGE_OPT_PARAM *param,
1703
+ Field *field, Item *value)
1704
+ {
1705
+ DBUG_ENTER (" Item_func_like::get_func_mm_tree" );
1706
+ DBUG_RETURN (get_mm_parts (param, field, LIKE_FUNC, value));
1707
+ }
1611
1708
SEL_ARG *get_mm_leaf (RANGE_OPT_PARAM *param, Field *field,
1612
1709
KEY_PART *key_part,
1613
1710
Item_func::Functype type, Item *value);
0 commit comments