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_intersect_select.h>
00026 #include <drizzled/internal/m_string.h>
00027 #include <drizzled/key.h>
00028 #include <drizzled/table.h>
00029
00030 #include <vector>
00031
00032 using namespace std;
00033
00034 namespace drizzled
00035 {
00036
00037
00038 optimizer::QuickRorIntersectSelect::QuickRorIntersectSelect(Session *session_param,
00039 Table *table,
00040 bool retrieve_full_rows,
00041 memory::Root *parent_alloc)
00042 :
00043 cpk_quick(NULL),
00044 session(session_param),
00045 need_to_fetch_row(retrieve_full_rows),
00046 scans_inited(false)
00047 {
00048 index= MAX_KEY;
00049 head= table;
00050 record= head->record[0];
00051 if (! parent_alloc)
00052 {
00053 memory::init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
00054 }
00055 else
00056 {
00057 memset(&alloc, 0, sizeof(memory::Root));
00058 }
00059
00060 if (parent_alloc)
00061 {
00062 last_rowid= (unsigned char*) parent_alloc->alloc_root(head->cursor->ref_length);
00063 }
00064 else
00065 {
00066 last_rowid= (unsigned char*) alloc.alloc_root(head->cursor->ref_length);
00067 }
00068 }
00069
00070
00071 optimizer::QuickRorIntersectSelect::~QuickRorIntersectSelect()
00072 {
00073 for_each(quick_selects.begin(),
00074 quick_selects.end(),
00075 DeletePtr());
00076 quick_selects.clear();
00077 delete cpk_quick;
00078 alloc.free_root(MYF(0));
00079 if (need_to_fetch_row && head->cursor->inited != Cursor::NONE)
00080 {
00081 head->cursor->endTableScan();
00082 }
00083 return;
00084 }
00085
00086
00087 int optimizer::QuickRorIntersectSelect::init()
00088 {
00089
00090 return (! last_rowid);
00091 }
00092
00093
00094 int optimizer::QuickRorIntersectSelect::init_ror_merged_scan(bool reuse_handler)
00095 {
00096 vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
00097
00098
00099 assert(! need_to_fetch_row || reuse_handler);
00100 if (! need_to_fetch_row && reuse_handler)
00101 {
00102 optimizer::QuickRangeSelect *quick= *it;
00103 ++it;
00104
00105
00106
00107
00108 if (quick->init_ror_merged_scan(true))
00109 return 0;
00110 quick->cursor->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
00111 }
00112 while (it != quick_selects.end())
00113 {
00114 if ((*it)->init_ror_merged_scan(false))
00115 {
00116 return 0;
00117 }
00118 (*it)->cursor->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
00119
00120 (*it)->record= head->record[0];
00121 ++it;
00122 }
00123
00124 if (need_to_fetch_row && head->cursor->startTableScan(1))
00125 {
00126 return 0;
00127 }
00128 return 0;
00129 }
00130
00131
00132 int optimizer::QuickRorIntersectSelect::reset()
00133 {
00134 if (! scans_inited && init_ror_merged_scan(true))
00135 {
00136 return 0;
00137 }
00138 scans_inited= true;
00139 for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
00140 it != quick_selects.end();
00141 ++it)
00142 {
00143 (*it)->reset();
00144 }
00145 return 0;
00146 }
00147
00148
00149 bool
00150 optimizer::QuickRorIntersectSelect::push_quick_back(optimizer::QuickRangeSelect *quick)
00151 {
00152 quick_selects.push_back(quick);
00153 return false;
00154 }
00155
00156
00157 bool optimizer::QuickRorIntersectSelect::is_keys_used(const boost::dynamic_bitset<>& fields)
00158 {
00159 for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
00160 it != quick_selects.end();
00161 ++it)
00162 {
00163 if (is_key_used(head, (*it)->index, fields))
00164 {
00165 return 1;
00166 }
00167 }
00168 return 0;
00169 }
00170
00171
00172 int optimizer::QuickRorIntersectSelect::get_next()
00173 {
00174 optimizer::QuickRangeSelect *quick= NULL;
00175 vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
00176 int error;
00177 int cmp;
00178 uint32_t last_rowid_count= 0;
00179
00180 do
00181 {
00182
00183 quick= *it;
00184 ++it;
00185 error= quick->get_next();
00186 if (cpk_quick)
00187 {
00188 while (! error && ! cpk_quick->row_in_ranges())
00189 error= quick->get_next();
00190 }
00191 if (error)
00192 return error;
00193
00194 quick->cursor->position(quick->record);
00195 memcpy(last_rowid, quick->cursor->ref, head->cursor->ref_length);
00196 last_rowid_count= 1;
00197
00198 while (last_rowid_count < quick_selects.size())
00199 {
00201 if (it != quick_selects.end())
00202 {
00203 quick= *it;
00204 ++it;
00205 }
00206 else
00207 {
00208 it= quick_selects.begin();
00209 quick= *it;
00210 ++it;
00211 }
00212
00213 do
00214 {
00215 if ((error= quick->get_next()))
00216 return error;
00217 quick->cursor->position(quick->record);
00218 cmp= head->cursor->cmp_ref(quick->cursor->ref, last_rowid);
00219 } while (cmp < 0);
00220
00221
00222 if (cmp > 0)
00223 {
00224
00225 if (cpk_quick)
00226 {
00227 while (! cpk_quick->row_in_ranges())
00228 {
00229 if ((error= quick->get_next()))
00230 return error;
00231 }
00232 }
00233 memcpy(last_rowid, quick->cursor->ref, head->cursor->ref_length);
00234 last_rowid_count= 1;
00235 }
00236 else
00237 {
00238
00239 last_rowid_count++;
00240 }
00241 }
00242
00243
00244 if (need_to_fetch_row)
00245 error= head->cursor->rnd_pos(head->record[0], last_rowid);
00246 } while (error == HA_ERR_RECORD_DELETED);
00247 return error;
00248 }
00249
00250
00251 void optimizer::QuickRorIntersectSelect::add_info_string(string *str)
00252 {
00253 bool first= true;
00254 str->append("intersect(");
00255 for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
00256 it != quick_selects.end();
00257 ++it)
00258 {
00259 KeyInfo *key_info= head->key_info + (*it)->index;
00260 if (! first)
00261 str->append(",");
00262 else
00263 first= false;
00264 str->append(key_info->name);
00265 }
00266 if (cpk_quick)
00267 {
00268 KeyInfo *key_info= head->key_info + cpk_quick->index;
00269 str->append(",");
00270 str->append(key_info->name);
00271 }
00272 str->append(")");
00273 }
00274
00275
00276 void optimizer::QuickRorIntersectSelect::add_keys_and_lengths(string *key_names,
00277 string *used_lengths)
00278 {
00279 char buf[64];
00280 uint32_t length;
00281 bool first= true;
00282 for (vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
00283 it != quick_selects.end();
00284 ++it)
00285 {
00286 KeyInfo *key_info= head->key_info + (*it)->index;
00287 if (first)
00288 {
00289 first= false;
00290 }
00291 else
00292 {
00293 key_names->append(",");
00294 used_lengths->append(",");
00295 }
00296 key_names->append(key_info->name);
00297 length= internal::int64_t2str((*it)->max_used_key_length, buf, 10) - buf;
00298 used_lengths->append(buf, length);
00299 }
00300
00301 if (cpk_quick)
00302 {
00303 KeyInfo *key_info= head->key_info + cpk_quick->index;
00304 key_names->append(",");
00305 key_names->append(key_info->name);
00306 length= internal::int64_t2str(cpk_quick->max_used_key_length, buf, 10) - buf;
00307 used_lengths->append(",");
00308 used_lengths->append(buf, length);
00309 }
00310 }
00311
00312 }