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