Drizzled Public API Documentation

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