~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/optimizer/quick_ror_union_select.cc

Merge Padraig

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "drizzled/server_includes.h"
 
21
#include "drizzled/session.h"
 
22
#include "drizzled/util/functors.h"
 
23
#include "drizzled/optimizer/range.h"
 
24
#include "drizzled/optimizer/quick_range_select.h"
 
25
#include "drizzled/optimizer/quick_ror_union_select.h"
 
26
 
 
27
#include <vector>
 
28
#include <algorithm>
 
29
 
 
30
using namespace std;
 
31
using namespace drizzled;
 
32
 
 
33
 
 
34
optimizer::QuickRorUnionSelect::QuickRorUnionSelect(Session *session_param,
 
35
                                                    Table *table)
 
36
  :
 
37
    session(session_param),
 
38
    scans_inited(false)
 
39
{
 
40
  index= MAX_KEY;
 
41
  head= table;
 
42
  rowid_length= table->cursor->ref_length;
 
43
  record= head->record[0];
 
44
  init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
 
45
  session_param->mem_root= &alloc;
 
46
}
 
47
 
 
48
/*
 
49
 * Function object that is used as the comparison function
 
50
 * for the priority queue in the QuickRorUnionSelect
 
51
 * class.
 
52
 */
 
53
class optimizer::compare_functor
 
54
{
 
55
  optimizer::QuickRorUnionSelect *self;
 
56
  public:
 
57
  compare_functor(optimizer::QuickRorUnionSelect *in_arg)
 
58
    : self(in_arg) { }
 
59
  inline bool operator()(const optimizer::QuickSelectInterface *i, const optimizer::QuickSelectInterface *j) const
 
60
  {
 
61
    int val= self->head->cursor->cmp_ref(i->last_rowid,
 
62
                                         j->last_rowid);
 
63
    return (val >= 0);
 
64
  }
 
65
};
 
66
 
 
67
 
 
68
int optimizer::QuickRorUnionSelect::init()
 
69
{
 
70
  queue=
 
71
    new priority_queue<optimizer::QuickSelectInterface *,
 
72
                       vector<optimizer::QuickSelectInterface *>,
 
73
                       optimizer::compare_functor >(optimizer::compare_functor(this));
 
74
  if (! (cur_rowid= (unsigned char*) alloc_root(&alloc, 2*head->cursor->ref_length)))
 
75
  {
 
76
    return 0;
 
77
  }
 
78
  prev_rowid= cur_rowid + head->cursor->ref_length;
 
79
  return 0;
 
80
}
 
81
 
 
82
 
 
83
int optimizer::QuickRorUnionSelect::reset()
 
84
{
 
85
  int error;
 
86
  have_prev_rowid= false;
 
87
  if (! scans_inited)
 
88
  {
 
89
    for (vector<optimizer::QuickSelectInterface *>::iterator it= quick_selects.begin();
 
90
         it != quick_selects.end();
 
91
         ++it)
 
92
    {
 
93
      if ((*it)->init_ror_merged_scan(false))
 
94
      {
 
95
        return 0;
 
96
      }
 
97
    }
 
98
    scans_inited= true;
 
99
  }
 
100
  while (! queue->empty())
 
101
  {
 
102
    queue->pop();
 
103
  }
 
104
  /*
 
105
    Initialize scans for merged quick selects and put all merged quick
 
106
    selects into the queue.
 
107
  */
 
108
  for (vector<optimizer::QuickSelectInterface *>::iterator it= quick_selects.begin();
 
109
       it != quick_selects.end();
 
110
       ++it)
 
111
  {
 
112
    if ((*it)->reset())
 
113
    {
 
114
      return 0;
 
115
    }
 
116
    
 
117
    error= (*it)->get_next();
 
118
    if (error)
 
119
    {
 
120
      if (error == HA_ERR_END_OF_FILE)
 
121
      {
 
122
        continue;
 
123
      }
 
124
    }
 
125
    (*it)->save_last_pos();
 
126
    queue->push(*it);
 
127
  }
 
128
 
 
129
  if (head->cursor->ha_rnd_init(1))
 
130
  {
 
131
    return 0;
 
132
  }
 
133
 
 
134
  return 0;
 
135
}
 
136
 
 
137
 
 
138
bool
 
139
optimizer::QuickRorUnionSelect::push_quick_back(QuickSelectInterface *quick_sel_range)
 
140
{
 
141
  quick_selects.push_back(quick_sel_range);
 
142
  return false;
 
143
}
 
144
 
 
145
 
 
146
optimizer::QuickRorUnionSelect::~QuickRorUnionSelect()
 
147
{
 
148
  while (! queue->empty())
 
149
  {
 
150
    queue->pop();
 
151
  }
 
152
  delete queue;
 
153
  for_each(quick_selects.begin(),
 
154
           quick_selects.end(),
 
155
           DeletePtr());
 
156
  quick_selects.clear();
 
157
  if (head->cursor->inited != Cursor::NONE)
 
158
  {
 
159
    head->cursor->ha_rnd_end();
 
160
  }
 
161
  free_root(&alloc,MYF(0));
 
162
  return;
 
163
}
 
164
 
 
165
 
 
166
bool optimizer::QuickRorUnionSelect::is_keys_used(const MyBitmap *fields)
 
167
{
 
168
  for (vector<optimizer::QuickSelectInterface *>::iterator it= quick_selects.begin();
 
169
       it != quick_selects.end();
 
170
       ++it)
 
171
  {
 
172
    if ((*it)->is_keys_used(fields))
 
173
    {
 
174
      return true;
 
175
    }
 
176
  }
 
177
  return false;
 
178
}
 
179
 
 
180
 
 
181
int optimizer::QuickRorUnionSelect::get_next()
 
182
{
 
183
  int error;
 
184
  int dup_row;
 
185
  optimizer::QuickSelectInterface *quick= NULL;
 
186
  unsigned char *tmp= NULL;
 
187
 
 
188
  do
 
189
  {
 
190
    do
 
191
    {
 
192
      if (queue->empty())
 
193
        return HA_ERR_END_OF_FILE;
 
194
      /* Ok, we have a queue with >= 1 scans */
 
195
 
 
196
      quick= queue->top();
 
197
      memcpy(cur_rowid, quick->last_rowid, rowid_length);
 
198
 
 
199
      /* put into queue rowid from the same stream as top element */
 
200
      if ((error= quick->get_next()))
 
201
      {
 
202
        if (error != HA_ERR_END_OF_FILE)
 
203
          return(error);
 
204
        queue->pop();
 
205
      }
 
206
      else
 
207
      {
 
208
        quick->save_last_pos();
 
209
        queue->pop();
 
210
        queue->push(quick);
 
211
      }
 
212
 
 
213
      if (!have_prev_rowid)
 
214
      {
 
215
        /* No rows have been returned yet */
 
216
        dup_row= false;
 
217
        have_prev_rowid= true;
 
218
      }
 
219
      else
 
220
        dup_row= ! head->cursor->cmp_ref(cur_rowid, prev_rowid);
 
221
    } while (dup_row);
 
222
 
 
223
    tmp= cur_rowid;
 
224
    cur_rowid= prev_rowid;
 
225
    prev_rowid= tmp;
 
226
 
 
227
    error= head->cursor->rnd_pos(quick->record, prev_rowid);
 
228
  } while (error == HA_ERR_RECORD_DELETED);
 
229
  return error;
 
230
}
 
231
 
 
232
 
 
233
void optimizer::QuickRorUnionSelect::add_info_string(String *str)
 
234
{
 
235
  bool first= true;
 
236
  str->append(STRING_WITH_LEN("union("));
 
237
  for (vector<optimizer::QuickSelectInterface *>::iterator it= quick_selects.begin();
 
238
       it != quick_selects.end();
 
239
       ++it)
 
240
  {
 
241
    if (! first)
 
242
      str->append(',');
 
243
    else
 
244
      first= false;
 
245
    (*it)->add_info_string(str);
 
246
  }
 
247
  str->append(')');
 
248
}
 
249
 
 
250
 
 
251
void optimizer::QuickRorUnionSelect::add_keys_and_lengths(String *key_names,
 
252
                                                          String *used_lengths)
 
253
{
 
254
  bool first= true;
 
255
  for (vector<optimizer::QuickSelectInterface *>::iterator it= quick_selects.begin();
 
256
       it != quick_selects.end();
 
257
       ++it)
 
258
  {
 
259
    if (first)
 
260
    {
 
261
      first= false;
 
262
    }
 
263
    else
 
264
    {
 
265
      used_lengths->append(',');
 
266
      key_names->append(',');
 
267
    }
 
268
    (*it)->add_keys_and_lengths(key_names, used_lengths);
 
269
  }
 
270
}
 
271