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