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 #include <drizzled/system_variables.h>
00028
00029 #include <vector>
00030 #include <algorithm>
00031
00032 using namespace std;
00033
00034 namespace drizzled {
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 alloc.init(session->variables.range_alloc_block_size);
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= new priority_queue<QuickSelectInterface*, vector<QuickSelectInterface*>, compare_functor>(compare_functor(this));
00073 cur_rowid= alloc.alloc(2 * head->cursor->ref_length);
00074 prev_rowid= cur_rowid + head->cursor->ref_length;
00075 return 0;
00076 }
00077
00078
00079 int optimizer::QuickRorUnionSelect::reset()
00080 {
00081 have_prev_rowid= false;
00082 if (not scans_inited)
00083 {
00084 BOOST_FOREACH(QuickSelectInterface* it, quick_selects)
00085 {
00086 if (it->init_ror_merged_scan(false))
00087 {
00088 return 0;
00089 }
00090 }
00091 scans_inited= true;
00092 }
00093 while (not queue->empty())
00094 {
00095 queue->pop();
00096 }
00097
00098
00099
00100
00101 BOOST_FOREACH(QuickSelectInterface* it, quick_selects)
00102 {
00103 if (it->reset())
00104 return 0;
00105 if (it->get_next() == HA_ERR_END_OF_FILE)
00106 continue;
00107 it->save_last_pos();
00108 queue->push(it);
00109 }
00110 if (head->cursor->startTableScan(1))
00111 return 0;
00112 return 0;
00113 }
00114
00115
00116 void optimizer::QuickRorUnionSelect::push_quick_back(QuickSelectInterface *quick_sel_range)
00117 {
00118 quick_selects.push_back(quick_sel_range);
00119 }
00120
00121
00122 optimizer::QuickRorUnionSelect::~QuickRorUnionSelect()
00123 {
00124 while (! queue->empty())
00125 {
00126 queue->pop();
00127 }
00128 delete queue;
00129 for_each(quick_selects.begin(),
00130 quick_selects.end(),
00131 DeletePtr());
00132 quick_selects.clear();
00133 if (head->cursor->inited != Cursor::NONE)
00134 {
00135 head->cursor->endTableScan();
00136 }
00137 alloc.free_root(MYF(0));
00138 }
00139
00140
00141 bool optimizer::QuickRorUnionSelect::is_keys_used(const boost::dynamic_bitset<>& fields)
00142 {
00143 BOOST_FOREACH(QuickSelectInterface* it, quick_selects)
00144 {
00145 if (it->is_keys_used(fields))
00146 return true;
00147 }
00148 return false;
00149 }
00150
00151
00152 int optimizer::QuickRorUnionSelect::get_next()
00153 {
00154 int error;
00155 int dup_row;
00156 optimizer::QuickSelectInterface *quick= NULL;
00157 unsigned char *tmp= NULL;
00158
00159 do
00160 {
00161 do
00162 {
00163 if (queue->empty())
00164 return HA_ERR_END_OF_FILE;
00165
00166
00167 quick= queue->top();
00168 memcpy(cur_rowid, quick->last_rowid, rowid_length);
00169
00170
00171 if ((error= quick->get_next()))
00172 {
00173 if (error != HA_ERR_END_OF_FILE)
00174 return(error);
00175 queue->pop();
00176 }
00177 else
00178 {
00179 quick->save_last_pos();
00180 queue->pop();
00181 queue->push(quick);
00182 }
00183
00184 if (!have_prev_rowid)
00185 {
00186
00187 dup_row= false;
00188 have_prev_rowid= true;
00189 }
00190 else
00191 dup_row= ! head->cursor->cmp_ref(cur_rowid, prev_rowid);
00192 } while (dup_row);
00193
00194 tmp= cur_rowid;
00195 cur_rowid= prev_rowid;
00196 prev_rowid= tmp;
00197
00198 error= head->cursor->rnd_pos(quick->record, prev_rowid);
00199 } while (error == HA_ERR_RECORD_DELETED);
00200 return error;
00201 }
00202
00203
00204 void optimizer::QuickRorUnionSelect::add_info_string(string *str)
00205 {
00206 bool first= true;
00207 str->append("union(");
00208 BOOST_FOREACH(QuickSelectInterface* it, quick_selects)
00209 {
00210 if (first)
00211 first= false;
00212 else
00213 str->append(",");
00214 it->add_info_string(str);
00215 }
00216 str->append(")");
00217 }
00218
00219
00220 void optimizer::QuickRorUnionSelect::add_keys_and_lengths(string *key_names, string *used_lengths)
00221 {
00222 bool first= true;
00223 BOOST_FOREACH(QuickSelectInterface* it, quick_selects)
00224 {
00225 if (first)
00226 first= false;
00227 else
00228 {
00229 used_lengths->append(",");
00230 key_names->append(",");
00231 }
00232 it->add_keys_and_lengths(key_names, used_lengths);
00233 }
00234 }
00235
00236 }