Drizzled Public API Documentation

quick_ror_union_select.cc
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008-2009 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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  * Function object that is used as the comparison function
00052  * for the priority queue in the QuickRorUnionSelect
00053  * class.
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     Initialize scans for merged quick selects and put all merged quick
00099     selects into the queue.
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       /* Ok, we have a queue with >= 1 scans */
00166 
00167       quick= queue->top();
00168       memcpy(cur_rowid, quick->last_rowid, rowid_length);
00169 
00170       /* put into queue rowid from the same stream as top element */
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         /* No rows have been returned yet */
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 } /* namespace drizzled */