00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021 #include <drizzled/session.h>
00022 #include <drizzled/util/functors.h>
00023 #include <drizzled/optimizer/range.h>
00024 #include <drizzled/optimizer/quick_range_select.h>
00025 #include <drizzled/optimizer/quick_ror_union_select.h>
00026 #include <drizzled/table.h>
00027
00028 #include <vector>
00029 #include <algorithm>
00030
00031 using namespace std;
00032
00033 namespace drizzled
00034 {
00035
00036 optimizer::QuickRorUnionSelect::QuickRorUnionSelect(Session *session_param,
00037 Table *table)
00038 :
00039 session(session_param),
00040 scans_inited(false)
00041 {
00042 index= MAX_KEY;
00043 head= table;
00044 rowid_length= table->cursor->ref_length;
00045 record= head->record[0];
00046 memory::init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
00047 session_param->mem_root= &alloc;
00048 }
00049
00050
00051
00052
00053
00054
00055 class optimizer::compare_functor
00056 {
00057 optimizer::QuickRorUnionSelect *self;
00058 public:
00059 compare_functor(optimizer::QuickRorUnionSelect *in_arg)
00060 : self(in_arg) { }
00061 inline bool operator()(const optimizer::QuickSelectInterface *i, const optimizer::QuickSelectInterface *j) const
00062 {
00063 int val= self->head->cursor->cmp_ref(i->last_rowid,
00064 j->last_rowid);
00065 return (val >= 0);
00066 }
00067 };
00068
00069
00070 int optimizer::QuickRorUnionSelect::init()
00071 {
00072 queue=
00073 new priority_queue<optimizer::QuickSelectInterface *,
00074 vector<optimizer::QuickSelectInterface *>,
00075 optimizer::compare_functor >(optimizer::compare_functor(this));
00076 if (! (cur_rowid= (unsigned char*) alloc.alloc_root(2 * head->cursor->ref_length)))
00077 {
00078 return 0;
00079 }
00080 prev_rowid= cur_rowid + head->cursor->ref_length;
00081 return 0;
00082 }
00083
00084
00085 int optimizer::QuickRorUnionSelect::reset()
00086 {
00087 int error;
00088 have_prev_rowid= false;
00089 if (! scans_inited)
00090 {
00091 for (vector<optimizer::QuickSelectInterface *>::iterator it= quick_selects.begin();
00092 it != quick_selects.end();
00093 ++it)
00094 {
00095 if ((*it)->init_ror_merged_scan(false))
00096 {
00097 return 0;
00098 }
00099 }
00100 scans_inited= true;
00101 }
00102 while (! queue->empty())
00103 {
00104 queue->pop();
00105 }
00106
00107
00108
00109
00110 for (vector<optimizer::QuickSelectInterface *>::iterator it= quick_selects.begin();
00111 it != quick_selects.end();
00112 ++it)
00113 {
00114 if ((*it)->reset())
00115 {
00116 return 0;
00117 }
00118
00119 error= (*it)->get_next();
00120 if (error)
00121 {
00122 if (error == HA_ERR_END_OF_FILE)
00123 {
00124 continue;
00125 }
00126 }
00127 (*it)->save_last_pos();
00128 queue->push(*it);
00129 }
00130
00131 if (head->cursor->startTableScan(1))
00132 {
00133 return 0;
00134 }
00135
00136 return 0;
00137 }
00138
00139
00140 bool
00141 optimizer::QuickRorUnionSelect::push_quick_back(QuickSelectInterface *quick_sel_range)
00142 {
00143 quick_selects.push_back(quick_sel_range);
00144 return false;
00145 }
00146
00147
00148 optimizer::QuickRorUnionSelect::~QuickRorUnionSelect()
00149 {
00150 while (! queue->empty())
00151 {
00152 queue->pop();
00153 }
00154 delete queue;
00155 for_each(quick_selects.begin(),
00156 quick_selects.end(),
00157 DeletePtr());
00158 quick_selects.clear();
00159 if (head->cursor->inited != Cursor::NONE)
00160 {
00161 head->cursor->endTableScan();
00162 }
00163 alloc.free_root(MYF(0));
00164 }
00165
00166
00167 bool optimizer::QuickRorUnionSelect::is_keys_used(const boost::dynamic_bitset<>& fields)
00168 {
00169 for (vector<optimizer::QuickSelectInterface *>::iterator it= quick_selects.begin();
00170 it != quick_selects.end();
00171 ++it)
00172 {
00173 if ((*it)->is_keys_used(fields))
00174 {
00175 return true;
00176 }
00177 }
00178 return false;
00179 }
00180
00181
00182 int optimizer::QuickRorUnionSelect::get_next()
00183 {
00184 int error;
00185 int dup_row;
00186 optimizer::QuickSelectInterface *quick= NULL;
00187 unsigned char *tmp= NULL;
00188
00189 do
00190 {
00191 do
00192 {
00193 if (queue->empty())
00194 return HA_ERR_END_OF_FILE;
00195
00196
00197 quick= queue->top();
00198 memcpy(cur_rowid, quick->last_rowid, rowid_length);
00199
00200
00201 if ((error= quick->get_next()))
00202 {
00203 if (error != HA_ERR_END_OF_FILE)
00204 return(error);
00205 queue->pop();
00206 }
00207 else
00208 {
00209 quick->save_last_pos();
00210 queue->pop();
00211 queue->push(quick);
00212 }
00213
00214 if (!have_prev_rowid)
00215 {
00216
00217 dup_row= false;
00218 have_prev_rowid= true;
00219 }
00220 else
00221 dup_row= ! head->cursor->cmp_ref(cur_rowid, prev_rowid);
00222 } while (dup_row);
00223
00224 tmp= cur_rowid;
00225 cur_rowid= prev_rowid;
00226 prev_rowid= tmp;
00227
00228 error= head->cursor->rnd_pos(quick->record, prev_rowid);
00229 } while (error == HA_ERR_RECORD_DELETED);
00230 return error;
00231 }
00232
00233
00234 void optimizer::QuickRorUnionSelect::add_info_string(string *str)
00235 {
00236 bool first= true;
00237 str->append("union(");
00238 for (vector<optimizer::QuickSelectInterface *>::iterator it= quick_selects.begin();
00239 it != quick_selects.end();
00240 ++it)
00241 {
00242 if (! first)
00243 str->append(",");
00244 else
00245 first= false;
00246 (*it)->add_info_string(str);
00247 }
00248 str->append(")");
00249 }
00250
00251
00252 void optimizer::QuickRorUnionSelect::add_keys_and_lengths(string *key_names,
00253 string *used_lengths)
00254 {
00255 bool first= true;
00256 for (vector<optimizer::QuickSelectInterface *>::iterator it= quick_selects.begin();
00257 it != quick_selects.end();
00258 ++it)
00259 {
00260 if (first)
00261 {
00262 first= false;
00263 }
00264 else
00265 {
00266 used_lengths->append(",");
00267 key_names->append(",");
00268 }
00269 (*it)->add_keys_and_lengths(key_names, used_lengths);
00270 }
00271 }
00272
00273 }