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/records.h>
00023 #include <drizzled/util/functors.h>
00024 #include <drizzled/optimizer/quick_range_select.h>
00025 #include <drizzled/optimizer/quick_index_merge_select.h>
00026 #include <drizzled/internal/m_string.h>
00027 #include <drizzled/unique.h>
00028 #include <drizzled/key.h>
00029 #include <drizzled/table.h>
00030 #include <drizzled/system_variables.h>
00031
00032 #include <vector>
00033
00034 using namespace std;
00035
00036 namespace drizzled {
00037
00038 static int refpos_order_cmp(void *arg, const void *a, const void *b)
00039 {
00040 Cursor *cursor= (Cursor*)arg;
00041 return cursor->cmp_ref((const unsigned char *) a, (const unsigned char *) b);
00042 }
00043
00044 optimizer::QuickIndexMergeSelect::QuickIndexMergeSelect(Session *session_param,
00045 Table *table)
00046 :
00047 pk_quick_select(NULL),
00048 session(session_param)
00049 {
00050 index= MAX_KEY;
00051 head= table;
00052 memset(&read_record, 0, sizeof(read_record));
00053 alloc.init(session->variables.range_alloc_block_size);
00054 }
00055
00056 int optimizer::QuickIndexMergeSelect::init()
00057 {
00058 return 0;
00059 }
00060
00061 int optimizer::QuickIndexMergeSelect::reset()
00062 {
00063 return (read_keys_and_merge());
00064 }
00065
00066 void optimizer::QuickIndexMergeSelect::push_quick_back(optimizer::QuickRangeSelect *quick_sel_range)
00067 {
00068
00069
00070
00071
00072 if (head->cursor->primary_key_is_clustered() &&
00073 quick_sel_range->index == head->getShare()->getPrimaryKey())
00074 {
00075 pk_quick_select= quick_sel_range;
00076 }
00077 else
00078 {
00079 quick_selects.push_back(quick_sel_range);
00080 }
00081 }
00082
00083 optimizer::QuickIndexMergeSelect::~QuickIndexMergeSelect()
00084 {
00085 BOOST_FOREACH(QuickRangeSelect* it, quick_selects)
00086 it->cursor= NULL;
00087 for_each(quick_selects.begin(), quick_selects.end(), DeletePtr());
00088 quick_selects.clear();
00089 delete pk_quick_select;
00090 alloc.free_root(MYF(0));
00091 }
00092
00093
00094 int optimizer::QuickIndexMergeSelect::read_keys_and_merge()
00095 {
00096 vector<optimizer::QuickRangeSelect *>::iterator it= quick_selects.begin();
00097 optimizer::QuickRangeSelect *cur_quick= NULL;
00098 int result;
00099 Unique *unique= NULL;
00100 Cursor *cursor= head->cursor;
00101
00102 cursor->extra(HA_EXTRA_KEYREAD);
00103 head->prepare_for_position();
00104
00105 cur_quick= *it;
00106 ++it;
00107 assert(cur_quick != 0);
00108
00109
00110
00111
00112
00113 if (cur_quick->init() || cur_quick->reset())
00114 return 0;
00115
00116 unique= new Unique(refpos_order_cmp,
00117 (void *) cursor,
00118 cursor->ref_length,
00119 session->variables.sortbuff_size);
00120 if (! unique)
00121 return 0;
00122 for (;;)
00123 {
00124 while ((result= cur_quick->get_next()) == HA_ERR_END_OF_FILE)
00125 {
00126 cur_quick->range_end();
00127 if (it == quick_selects.end())
00128 {
00129 break;
00130 }
00131 cur_quick= *it;
00132 ++it;
00133 if (! cur_quick)
00134 break;
00135
00136 if (cur_quick->cursor->inited != Cursor::NONE)
00137 cur_quick->cursor->endIndexScan();
00138 if (cur_quick->init() || cur_quick->reset())
00139 return 0;
00140 }
00141
00142 if (result)
00143 {
00144 if (result != HA_ERR_END_OF_FILE)
00145 {
00146 cur_quick->range_end();
00147 return result;
00148 }
00149 break;
00150 }
00151
00152 if (session->getKilled())
00153 return 0;
00154
00155
00156 if (pk_quick_select && pk_quick_select->row_in_ranges())
00157 continue;
00158
00159 cur_quick->cursor->position(cur_quick->record);
00160 result= unique->unique_add((char*) cur_quick->cursor->ref);
00161 if (result)
00162 return 0;
00163
00164 }
00165
00166
00167 result= unique->get(head);
00168 delete unique;
00169 doing_pk_scan= false;
00170
00171 cursor->extra(HA_EXTRA_NO_KEYREAD);
00172
00173 if ((result= read_record.init_read_record(session, head, (optimizer::SqlSelect*) 0, 1, 1)))
00174 {
00175 head->print_error(result, MYF(0));
00176 return 0;
00177 }
00178 return result;
00179 }
00180
00181
00182 int optimizer::QuickIndexMergeSelect::get_next()
00183 {
00184 int result;
00185
00186 if (doing_pk_scan)
00187 return(pk_quick_select->get_next());
00188
00189 if ((result= read_record.read_record(&read_record)) == -1)
00190 {
00191 result= HA_ERR_END_OF_FILE;
00192 read_record.end_read_record();
00193
00194 if (pk_quick_select)
00195 {
00196 doing_pk_scan= true;
00197 if ((result= pk_quick_select->init()) ||
00198 (result= pk_quick_select->reset()))
00199 return result;
00200 return(pk_quick_select->get_next());
00201 }
00202 }
00203
00204 return result;
00205 }
00206
00207 bool optimizer::QuickIndexMergeSelect::is_keys_used(const boost::dynamic_bitset<>& fields)
00208 {
00209 BOOST_FOREACH(QuickRangeSelect* it, quick_selects)
00210 {
00211 if (is_key_used(head, it->index, fields))
00212 return 1;
00213 }
00214 return 0;
00215 }
00216
00217
00218 void optimizer::QuickIndexMergeSelect::add_info_string(string *str)
00219 {
00220 bool first= true;
00221 str->append("sort_union(");
00222 BOOST_FOREACH(QuickRangeSelect* it, quick_selects)
00223 {
00224 if (! first)
00225 str->append(",");
00226 else
00227 first= false;
00228 it->add_info_string(str);
00229 }
00230 if (pk_quick_select)
00231 {
00232 str->append(",");
00233 pk_quick_select->add_info_string(str);
00234 }
00235 str->append(")");
00236 }
00237
00238
00239 void optimizer::QuickIndexMergeSelect::add_keys_and_lengths(string *key_names,
00240 string *used_lengths)
00241 {
00242 char buf[64];
00243 uint32_t length= 0;
00244 bool first= true;
00245
00246 BOOST_FOREACH(QuickRangeSelect* it, quick_selects)
00247 {
00248 if (first)
00249 first= false;
00250 else
00251 {
00252 key_names->append(",");
00253 used_lengths->append(",");
00254 }
00255
00256 KeyInfo *key_info= head->key_info + it->index;
00257 key_names->append(key_info->name);
00258 length= internal::int64_t2str(it->max_used_key_length, buf, 10) - buf;
00259 used_lengths->append(buf, length);
00260 }
00261 if (pk_quick_select)
00262 {
00263 KeyInfo *key_info= head->key_info + pk_quick_select->index;
00264 key_names->append(",");
00265 key_names->append(key_info->name);
00266 length= internal::int64_t2str(pk_quick_select->max_used_key_length, buf, 10) - buf;
00267 used_lengths->append(",");
00268 used_lengths->append(buf, length);
00269 }
00270 }
00271
00272
00273 }