~drizzle-trunk/drizzle/development

1237.13.44 by Padraig O'Sullivan
Moved the SEL_TREE and SEL_IMERGE classes out into their own header and implementation files.
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2008-2009 Sun Microsystems
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19
20
#include "config.h"
21
22
#include "drizzled/sql_base.h"
23
#include "drizzled/sql_select.h"
24
#include "drizzled/memory/sql_alloc.h"
25
#include "drizzled/optimizer/range.h"
26
#include "drizzled/optimizer/range_param.h"
27
#include "drizzled/optimizer/sel_arg.h"
28
#include "drizzled/optimizer/sel_tree.h"
29
#include "drizzled/optimizer/sel_imerge.h"
30
31
using namespace std;
32
using namespace drizzled;
33
34
static optimizer::SEL_ARG *key_or(optimizer::RangeParameter *param, optimizer::SEL_ARG *key1, optimizer::SEL_ARG *key2);
35
static bool eq_tree(optimizer::SEL_ARG* a, optimizer::SEL_ARG *b);
36
37
bool optimizer::sel_trees_can_be_ored(optimizer::SEL_TREE *tree1, 
38
                                      optimizer::SEL_TREE *tree2,
39
                                      optimizer::RangeParameter* param)
40
{
41
  key_map common_keys= tree1->keys_map;
42
  common_keys&= tree2->keys_map;
43
44
  if (common_keys.none())
45
  {
46
    return false;
47
  }
48
49
  /* trees have a common key, check if they refer to same key part */
50
  optimizer::SEL_ARG **key1,**key2;
51
  for (uint32_t key_no=0; key_no < param->keys; key_no++)
52
  {
53
    if (common_keys.test(key_no))
54
    {
55
      key1= tree1->keys + key_no;
56
      key2= tree2->keys + key_no;
57
      if ((*key1)->part == (*key2)->part)
58
      {
59
        return true;
60
      }
61
    }
62
  }
63
  return false;
64
}
65
66
67
/*
68
  Perform OR operation on 2 index_merge lists, storing result in first list.
69
70
  NOTES
71
    The following conversion is implemented:
72
     (a_1 &&...&& a_N)||(b_1 &&...&& b_K) = AND_i,j(a_i || b_j) =>
73
      => (a_1||b_1).
74
75
    i.e. all conjuncts except the first one are currently dropped.
76
    This is done to avoid producing N*K ways to do index_merge.
77
78
    If (a_1||b_1) produce a condition that is always true, NULL is returned
79
    and index_merge is discarded (while it is actually possible to try
80
    harder).
81
82
    As a consequence of this, choice of keys to do index_merge read may depend
83
    on the order of conditions in WHERE part of the query.
84
85
  RETURN
86
    0     OK, result is stored in *im1
87
    other Error, both passed lists are unusable
88
*/
89
90
static int imerge_list_or_list(optimizer::RangeParameter *param,
91
                               List<optimizer::SEL_IMERGE> *im1,
92
                               List<optimizer::SEL_IMERGE> *im2)
93
{
94
  optimizer::SEL_IMERGE *imerge= im1->head();
95
  im1->empty();
96
  im1->push_back(imerge);
97
98
  return imerge->or_sel_imerge_with_checks(param, im2->head());
99
}
100
101
102
/*
103
  Perform OR operation on index_merge list and key tree.
104
105
  RETURN
106
     0     OK, result is stored in *im1.
107
     other Error
108
 */
109
110
static int imerge_list_or_tree(optimizer::RangeParameter *param,
111
                               List<optimizer::SEL_IMERGE> *im1,
112
                               optimizer::SEL_TREE *tree)
113
{
114
  optimizer::SEL_IMERGE *imerge= NULL;
115
  List_iterator<optimizer::SEL_IMERGE> it(*im1);
116
  while ((imerge= it++))
117
  {
118
    if (imerge->or_sel_tree_with_checks(param, tree))
119
      it.remove();
120
  }
121
  return im1->is_empty();
122
}
123
124
125
optimizer::SEL_TREE *
126
optimizer::tree_or(optimizer::RangeParameter *param,
127
                   optimizer::SEL_TREE *tree1,
128
                   optimizer::SEL_TREE *tree2)
129
{
130
  if (! tree1 || ! tree2)
131
  {
132
    return 0;
133
  }
134
135
  if (tree1->type == optimizer::SEL_TREE::IMPOSSIBLE || tree2->type == optimizer::SEL_TREE::ALWAYS)
136
  {
137
    return tree2;
138
  }
139
140
  if (tree2->type == optimizer::SEL_TREE::IMPOSSIBLE || tree1->type == optimizer::SEL_TREE::ALWAYS)
141
  {
142
    return tree1;
143
  }
144
145
  if (tree1->type == optimizer::SEL_TREE::MAYBE)
146
  {
147
    return tree1; // Can't use this
148
  }
149
150
  if (tree2->type == optimizer::SEL_TREE::MAYBE)
151
  {
152
    return tree2;
153
  }
154
155
  optimizer::SEL_TREE *result= NULL;
156
  key_map  result_keys;
157
  result_keys.reset();
158
  if (sel_trees_can_be_ored(tree1, tree2, param))
159
  {
160
    /* Join the trees key per key */
161
    optimizer::SEL_ARG **key1= NULL;
162
    optimizer::SEL_ARG **key2= NULL;
163
    optimizer::SEL_ARG **end= NULL;
164
    for (key1= tree1->keys,key2= tree2->keys,end= key1+param->keys;
165
         key1 != end; 
166
         key1++, key2++)
167
    {
168
      *key1= key_or(param, *key1, *key2);
169
      if (*key1)
170
      {
171
        result= tree1; // Added to tree1
172
        result_keys.set(key1 - tree1->keys);
173
      }
174
    }
175
    if (result)
176
      result->keys_map= result_keys;
177
  }
178
  else
179
  {
180
    /* ok, two trees have KEY type but cannot be used without index merge */
181
    if (tree1->merges.is_empty() && tree2->merges.is_empty())
182
    {
183
      if (param->remove_jump_scans)
184
      {
185
        bool no_trees= optimizer::remove_nonrange_trees(param, tree1);
186
        no_trees= no_trees || optimizer::remove_nonrange_trees(param, tree2);
187
        if (no_trees)
188
        {
189
          return (new optimizer::SEL_TREE(optimizer::SEL_TREE::ALWAYS));
190
        }
191
      }
192
      optimizer::SEL_IMERGE *merge= NULL;
193
      /* both trees are "range" trees, produce new index merge structure */
194
      if (! (result= new optimizer::SEL_TREE()) || 
195
          ! (merge= new optimizer::SEL_IMERGE()) ||
196
          (result->merges.push_back(merge)) ||
197
          (merge->or_sel_tree(param, tree1)) ||
198
          (merge->or_sel_tree(param, tree2)))
199
      {
200
        result= NULL;
201
      }
202
      else
203
      {
204
        result->type= tree1->type;
205
      }
206
    }
207
    else if (!tree1->merges.is_empty() && !tree2->merges.is_empty())
208
    {
209
      if (imerge_list_or_list(param, &tree1->merges, &tree2->merges))
210
        result= new optimizer::SEL_TREE(optimizer::SEL_TREE::ALWAYS);
211
      else
212
        result= tree1;
213
    }
214
    else
215
    {
216
      /* one tree is index merge tree and another is range tree */
217
      if (tree1->merges.is_empty())
218
        std::swap(tree1, tree2);
219
220
      if (param->remove_jump_scans && optimizer::remove_nonrange_trees(param, tree2))
221
         return(new optimizer::SEL_TREE(optimizer::SEL_TREE::ALWAYS));
222
      /* add tree2 to tree1->merges, checking if it collapses to ALWAYS */
223
      if (imerge_list_or_tree(param, &tree1->merges, tree2))
224
        result= new optimizer::SEL_TREE(optimizer::SEL_TREE::ALWAYS);
225
      else
226
        result= tree1;
227
    }
228
  }
229
  return result;
230
}
231
232
233
static optimizer::SEL_ARG *
234
key_or(optimizer::RangeParameter *param, optimizer::SEL_ARG *key1, optimizer::SEL_ARG *key2)
235
{
236
  if (! key1)
237
  {
238
    if (key2)
239
    {
240
      key2->use_count--;
241
      key2->free_tree();
242
    }
243
    return 0;
244
  }
245
  if (! key2)
246
  {
247
    key1->use_count--;
248
    key1->free_tree();
249
    return 0;
250
  }
251
  key1->use_count--;
252
  key2->use_count--;
253
254
  if (key1->part != key2->part)
255
  {
256
    key1->free_tree();
257
    key2->free_tree();
258
    return 0;					// Can't optimize this
259
  }
260
261
  // If one of the key is MAYBE_KEY then the found region may be bigger
262
  if (key1->type == optimizer::SEL_ARG::MAYBE_KEY)
263
  {
264
    key2->free_tree();
265
    key1->use_count++;
266
    return key1;
267
  }
268
  if (key2->type == optimizer::SEL_ARG::MAYBE_KEY)
269
  {
270
    key1->free_tree();
271
    key2->use_count++;
272
    return key2;
273
  }
274
275
  if (key1->use_count > 0)
276
  {
277
    if (key2->use_count == 0 || key1->elements > key2->elements)
278
    {
279
      std::swap(key1,key2);
280
    }
281
    if (key1->use_count > 0 || !(key1=key1->clone_tree(param)))
282
      return 0;					// OOM
283
  }
284
285
  // Add tree at key2 to tree at key1
286
  bool key2_shared= key2->use_count != 0;
287
  key1->maybe_flag|= key2->maybe_flag;
288
289
  for (key2=key2->first(); key2; )
290
  {
291
    optimizer::SEL_ARG *tmp= key1->find_range(key2); // Find key1.min <= key2.min
292
    int cmp;
293
294
    if (! tmp)
295
    {
296
      tmp=key1->first(); // tmp.min > key2.min
297
      cmp= -1;
298
    }
299
    else if ((cmp=tmp->cmp_max_to_min(key2)) < 0)
300
    {						// Found tmp.max < key2.min
301
      optimizer::SEL_ARG *next= tmp->next;
302
      if (cmp == -2 && eq_tree(tmp->next_key_part,key2->next_key_part))
303
      {
304
        // Join near ranges like tmp.max < 0 and key2.min >= 0
305
        optimizer::SEL_ARG *key2_next=key2->next;
306
        if (key2_shared)
307
        {
308
          if (! (key2=new optimizer::SEL_ARG(*key2)))
309
            return 0;		// out of memory
310
          key2->increment_use_count(key1->use_count+1);
311
          key2->next= key2_next; // New copy of key2
312
        }
313
        key2->copy_min(tmp);
314
        if (! (key1=key1->tree_delete(tmp)))
315
        {					// Only one key in tree
316
          key1= key2;
317
          key1->make_root();
318
          key2= key2_next;
319
          break;
320
        }
321
      }
322
      if (! (tmp= next)) // tmp.min > key2.min
323
        break; // Copy rest of key2
324
    }
325
    if (cmp < 0)
326
    {						// tmp.min > key2.min
327
      int tmp_cmp;
328
      if ((tmp_cmp= tmp->cmp_min_to_max(key2)) > 0) // if tmp.min > key2.max
329
      {
330
        if (tmp_cmp == 2 && eq_tree(tmp->next_key_part,key2->next_key_part))
331
        {					// ranges are connected
332
          tmp->copy_min_to_min(key2);
333
          key1->merge_flags(key2);
334
          if (tmp->min_flag & NO_MIN_RANGE &&
335
              tmp->max_flag & NO_MAX_RANGE)
336
          {
337
            if (key1->maybe_flag)
338
              return new optimizer::SEL_ARG(optimizer::SEL_ARG::MAYBE_KEY);
339
            return 0;
340
          }
341
          key2->increment_use_count(-1);	// Free not used tree
342
          key2= key2->next;
343
          continue;
344
        }
345
        else
346
        {
347
          optimizer::SEL_ARG *next= key2->next; // Keys are not overlapping
348
          if (key2_shared)
349
          {
350
            optimizer::SEL_ARG *cpy= new optimizer::SEL_ARG(*key2); // Must make copy
351
            if (! cpy)
352
              return 0; // OOM
353
            key1= key1->insert(cpy);
354
            key2->increment_use_count(key1->use_count+1);
355
          }
356
          else
357
            key1= key1->insert(key2);		// Will destroy key2_root
358
          key2= next;
359
          continue;
360
        }
361
      }
362
    }
363
364
    // tmp.max >= key2.min && tmp.min <= key.cmax(overlapping ranges)
365
    if (eq_tree(tmp->next_key_part,key2->next_key_part))
366
    {
367
      if (tmp->is_same(key2))
368
      {
369
        tmp->merge_flags(key2);			// Copy maybe flags
370
        key2->increment_use_count(-1);		// Free not used tree
371
      }
372
      else
373
      {
374
        optimizer::SEL_ARG *last= tmp;
375
        while (last->next && last->next->cmp_min_to_max(key2) <= 0 &&
376
               eq_tree(last->next->next_key_part,key2->next_key_part))
377
        {
378
          optimizer::SEL_ARG *save= last;
379
          last= last->next;
380
          key1= key1->tree_delete(save);
381
        }
382
        last->copy_min(tmp);
383
        if (last->copy_min(key2) || last->copy_max(key2))
384
        {					// Full range
385
          key1->free_tree();
386
          for (; key2; key2= key2->next)
387
            key2->increment_use_count(-1);	// Free not used tree
388
          if (key1->maybe_flag)
389
            return new optimizer::SEL_ARG(optimizer::SEL_ARG::MAYBE_KEY);
390
          return 0;
391
        }
392
      }
393
      key2= key2->next;
394
      continue;
395
    }
396
397
    if (cmp >= 0 && tmp->cmp_min_to_min(key2) < 0)
398
    {						// tmp.min <= x < key2.min
399
      optimizer::SEL_ARG *new_arg= tmp->clone_first(key2);
400
      if (! new_arg)
401
        return 0;				// OOM
402
      if ((new_arg->next_key_part= key1->next_key_part))
403
        new_arg->increment_use_count(key1->use_count+1);
404
      tmp->copy_min_to_min(key2);
405
      key1= key1->insert(new_arg);
406
    }
407
408
    // tmp.min >= key2.min && tmp.min <= key2.max
409
    optimizer::SEL_ARG key(*key2); // Get copy we can modify
410
    for (;;)
411
    {
412
      if (tmp->cmp_min_to_min(&key) > 0)
413
      {						// key.min <= x < tmp.min
414
        optimizer::SEL_ARG *new_arg= key.clone_first(tmp);
415
        if (! new_arg)
416
          return 0;				// OOM
417
        if ((new_arg->next_key_part=key.next_key_part))
418
          new_arg->increment_use_count(key1->use_count+1);
419
        key1= key1->insert(new_arg);
420
      }
421
      if ((cmp=tmp->cmp_max_to_max(&key)) <= 0)
422
      {						// tmp.min. <= x <= tmp.max
423
        tmp->maybe_flag|= key.maybe_flag;
424
        key.increment_use_count(key1->use_count+1);
425
        tmp->next_key_part= key_or(param, tmp->next_key_part, key.next_key_part);
426
        if (! cmp)				// Key2 is ready
427
          break;
428
        key.copy_max_to_min(tmp);
429
        if (! (tmp= tmp->next))
430
        {
431
          optimizer::SEL_ARG *tmp2= new optimizer::SEL_ARG(key);
432
          if (! tmp2)
433
            return 0;				// OOM
434
          key1= key1->insert(tmp2);
435
          key2= key2->next;
436
          goto end;
437
        }
438
        if (tmp->cmp_min_to_max(&key) > 0)
439
        {
440
          optimizer::SEL_ARG *tmp2= new optimizer::SEL_ARG(key);
441
          if (! tmp2)
442
            return 0;				// OOM
443
          key1= key1->insert(tmp2);
444
          break;
445
        }
446
      }
447
      else
448
      {
449
        optimizer::SEL_ARG *new_arg= tmp->clone_last(&key); // tmp.min <= x <= key.max
450
        if (! new_arg)
451
          return 0;				// OOM
452
        tmp->copy_max_to_min(&key);
453
        tmp->increment_use_count(key1->use_count+1);
454
        /* Increment key count as it may be used for next loop */
455
        key.increment_use_count(1);
456
        new_arg->next_key_part= key_or(param, tmp->next_key_part, key.next_key_part);
457
        key1= key1->insert(new_arg);
458
        break;
459
      }
460
    }
461
    key2= key2->next;
462
  }
463
464
end:
465
  while (key2)
466
  {
467
    optimizer::SEL_ARG *next= key2->next;
468
    if (key2_shared)
469
    {
470
      optimizer::SEL_ARG *tmp= new optimizer::SEL_ARG(*key2);		// Must make copy
471
      if (! tmp)
472
        return 0;
473
      key2->increment_use_count(key1->use_count+1);
474
      key1= key1->insert(tmp);
475
    }
476
    else
477
      key1= key1->insert(key2);			// Will destroy key2_root
478
    key2= next;
479
  }
480
  key1->use_count++;
481
  return key1;
482
}
483
484
485
/*
486
  Remove the trees that are not suitable for record retrieval.
487
  SYNOPSIS
488
    param  Range analysis parameter
489
    tree   Tree to be processed, tree->type is KEY or KEY_SMALLER
490
491
  DESCRIPTION
492
    This function walks through tree->keys[] and removes the SEL_ARG* trees
493
    that are not "maybe" trees (*) and cannot be used to construct quick range
494
    selects.
495
    (*) - have type MAYBE or MAYBE_KEY. Perhaps we should remove trees of
496
          these types here as well.
497
498
    A SEL_ARG* tree cannot be used to construct quick select if it has
499
    tree->part != 0. (e.g. it could represent "keypart2 < const").
500
501
    WHY THIS FUNCTION IS NEEDED
502
503
    Normally we allow construction of optimizer::SEL_TREE objects that have SEL_ARG
504
    trees that do not allow quick range select construction. For example for
505
    " keypart1=1 AND keypart2=2 " the execution will proceed as follows:
506
    tree1= optimizer::SEL_TREE { SEL_ARG{keypart1=1} }
507
    tree2= optimizer::SEL_TREE { SEL_ARG{keypart2=2} } -- can't make quick range select
508
                                               from this
509
    call tree_and(tree1, tree2) -- this joins SEL_ARGs into a usable SEL_ARG
510
                                   tree.
511
512
    There is an exception though: when we construct index_merge optimizer::SEL_TREE,
513
    any SEL_ARG* tree that cannot be used to construct quick range select can
514
    be removed, because current range analysis code doesn't provide any way
515
    that tree could be later combined with another tree.
516
    Consider an example: we should not construct
517
    st1 = optimizer::SEL_TREE {
518
      merges = SEL_IMERGE {
519
                            optimizer::SEL_TREE(t.key1part1 = 1),
520
                            optimizer::SEL_TREE(t.key2part2 = 2)   -- (*)
521
                          }
522
                   };
523
    because
524
     - (*) cannot be used to construct quick range select,
525
     - There is no execution path that would cause (*) to be converted to
526
       a tree that could be used.
527
528
    The latter is easy to verify: first, notice that the only way to convert
529
    (*) into a usable tree is to call tree_and(something, (*)).
530
531
    Second look at what tree_and/tree_or function would do when passed a
532
    optimizer::SEL_TREE that has the structure like st1 tree has, and conlcude that
533
    tree_and(something, (*)) will not be called.
534
535
  RETURN
536
    0  Ok, some suitable trees left
537
    1  No tree->keys[] left.
538
*/
539
bool optimizer::remove_nonrange_trees(optimizer::RangeParameter *param, optimizer::SEL_TREE *tree)
540
{
541
  bool res= false;
542
  for (uint32_t i= 0; i < param->keys; i++)
543
  {
544
    if (tree->keys[i])
545
    {
546
      if (tree->keys[i]->part)
547
      {
548
        tree->keys[i]= NULL;
549
        tree->keys_map.reset(i);
550
      }
551
      else
552
        res= true;
553
    }
554
  }
555
  return ! res;
556
}
557
558
559
/* Compare if two trees are equal */
560
static bool eq_tree(optimizer::SEL_ARG *a, optimizer::SEL_ARG *b)
561
{
562
  if (a == b)
563
  {
564
    return true;
565
  }
566
567
  if (! a || ! b || ! a->is_same(b))
568
  {
569
    return false;
570
  }
571
572
  if (a->left != &optimizer::null_element && b->left != &optimizer::null_element)
573
  {
574
    if (! eq_tree(a->left,b->left))
575
      return false;
576
  }
577
  else if (a->left != &optimizer::null_element || b->left != &optimizer::null_element)
578
  {
579
    return false;
580
  }
581
582
  if (a->right != &optimizer::null_element && b->right != &optimizer::null_element)
583
  {
584
    if (! eq_tree(a->right,b->right))
585
      return false;
586
  }
587
  else if (a->right != &optimizer::null_element || b->right != &optimizer::null_element)
588
  {
589
    return false;
590
  }
591
592
  if (a->next_key_part != b->next_key_part)
593
  {						// Sub range
594
    if (! a->next_key_part != ! b->next_key_part ||
595
	      ! eq_tree(a->next_key_part, b->next_key_part))
596
      return false;
597
  }
598
599
  return true;
600
}