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