Drizzled Public API Documentation

sel_arg.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/optimizer/range.h>
00022 #include <drizzled/optimizer/range_param.h>
00023 #include <drizzled/optimizer/sel_arg.h>
00024 #include <drizzled/util/test.h>
00025 
00026 namespace drizzled {
00027 
00028 /* Functions to fix up the tree after insert and delete */
00029 static void left_rotate(optimizer::SEL_ARG **root, optimizer::SEL_ARG *leaf)
00030 {
00031   optimizer::SEL_ARG *y= leaf->right;
00032   leaf->right= y->left;
00033   if (y->left != &optimizer::null_element)
00034     y->left->parent= leaf;
00035   if (! (y->parent=leaf->parent))
00036     *root= y;
00037   else
00038     *leaf->parent_ptr()= y;
00039   y->left= leaf;
00040   leaf->parent= y;
00041 }
00042 
00043 
00044 static void right_rotate(optimizer::SEL_ARG **root, optimizer::SEL_ARG *leaf)
00045 {
00046   optimizer::SEL_ARG *y= leaf->left;
00047   leaf->left= y->right;
00048   if (y->right != &optimizer::null_element)
00049     y->right->parent= leaf;
00050   if (! (y->parent=leaf->parent))
00051     *root= y;
00052   else
00053     *leaf->parent_ptr()= y;
00054   y->right= leaf;
00055   leaf->parent= y;
00056 }
00057 
00058 
00059 /* Get overlapping range */
00060 optimizer::SEL_ARG *optimizer::SEL_ARG::clone_and(optimizer::SEL_ARG *arg)
00061 {
00062   unsigned char *new_min= NULL;
00063   unsigned char *new_max= NULL;
00064   uint8_t flag_min= 0;
00065   uint8_t flag_max= 0;
00066 
00067   if (cmp_min_to_min(arg) >= 0)
00068   {
00069     new_min= min_value;
00070     flag_min= min_flag;
00071   }
00072   else
00073   {
00074     new_min=arg->min_value;
00075     flag_min=arg->min_flag;
00076   }
00077   if (cmp_max_to_max(arg) <= 0)
00078   {
00079     new_max= max_value;
00080     flag_max= max_flag;
00081   }
00082   else
00083   {
00084     new_max= arg->max_value;
00085     flag_max= arg->max_flag;
00086   }
00087   return new SEL_ARG(field, part, new_min, new_max, flag_min, flag_max, test(maybe_flag && arg->maybe_flag));
00088 }
00089 
00090 
00091 /* min <= X , arg->min */
00092 optimizer::SEL_ARG *optimizer::SEL_ARG::clone_first(optimizer::SEL_ARG *arg)
00093 {
00094   return new SEL_ARG(field,part, min_value, arg->min_value, min_flag, arg->min_flag & NEAR_MIN ? 0 : NEAR_MAX, maybe_flag | arg->maybe_flag);
00095 }
00096 
00097 
00098 /* min <= X <= key_max */
00099 optimizer::SEL_ARG *optimizer::SEL_ARG::clone_last(optimizer::SEL_ARG *arg)
00100 {
00101   return new SEL_ARG(field, part, min_value, arg->max_value, min_flag, arg->max_flag, maybe_flag | arg->maybe_flag);
00102 }
00103 
00104 
00105 /* Get overlapping range */
00106 bool optimizer::SEL_ARG::copy_min(optimizer::SEL_ARG *arg)
00107 {
00108   if (cmp_min_to_min(arg) > 0)
00109   {
00110     min_value= arg->min_value;
00111     min_flag=arg->min_flag;
00112     if ((max_flag & (NO_MAX_RANGE | NO_MIN_RANGE)) ==
00113         (NO_MAX_RANGE | NO_MIN_RANGE))
00114     {
00115       return 1; // Full range
00116     }
00117   }
00118   maybe_flag|= arg->maybe_flag;
00119   return 0;
00120 }
00121 
00122 /* Get overlapping range */
00123 bool optimizer::SEL_ARG::copy_max(optimizer::SEL_ARG *arg)
00124 {
00125   if (cmp_max_to_max(arg) <= 0)
00126   {
00127     max_value= arg->max_value;
00128     max_flag= arg->max_flag;
00129     if ((max_flag & (NO_MAX_RANGE | NO_MIN_RANGE)) ==
00130         (NO_MAX_RANGE | NO_MIN_RANGE))
00131     {
00132       return 1; // Full range
00133     }
00134   }
00135   maybe_flag|= arg->maybe_flag;
00136   return 0;
00137 }
00138 
00139 void optimizer::SEL_ARG::copy_min_to_min(optimizer::SEL_ARG *arg)
00140 {
00141   min_value= arg->min_value;
00142   min_flag= arg->min_flag;
00143 }
00144 
00145 
00146 void optimizer::SEL_ARG::copy_min_to_max(optimizer::SEL_ARG *arg)
00147 {
00148   max_value= arg->min_value;
00149   max_flag= arg->min_flag & NEAR_MIN ? 0 : NEAR_MAX;
00150 }
00151 
00152 void optimizer::SEL_ARG::copy_max_to_min(optimizer::SEL_ARG *arg)
00153 {
00154   min_value= arg->max_value;
00155   min_flag= arg->max_flag & NEAR_MAX ? 0 : NEAR_MIN;
00156 }
00157 
00158 
00159 int optimizer::SEL_ARG::store_min(uint32_t length, unsigned char **min_key, uint32_t min_key_flag)
00160 {
00161   /* "(kp1 > c1) AND (kp2 OP c2) AND ..." -> (kp1 > c1) */
00162   if ((! (min_flag & NO_MIN_RANGE) &&
00163       ! (min_key_flag & (NO_MIN_RANGE | NEAR_MIN))))
00164   {
00165     if (maybe_null && *min_value)
00166     {
00167       **min_key= 1;
00168       memset(*min_key+1, 0, length-1);
00169     }
00170     else
00171     {
00172       memcpy(*min_key,min_value,length);
00173     }
00174     (*min_key)+= length;
00175     return 1;
00176   }
00177   return 0;
00178 }
00179 
00180 
00181 int optimizer::SEL_ARG::store_max(uint32_t length, unsigned char **max_key, uint32_t max_key_flag)
00182 {
00183   if (! (max_flag & NO_MAX_RANGE) &&
00184       ! (max_key_flag & (NO_MAX_RANGE | NEAR_MAX)))
00185   {
00186     if (maybe_null && *max_value)
00187     {
00188       **max_key= 1;
00189       memset(*max_key + 1, 0, length-1);
00190     }
00191     else
00192     {
00193       memcpy(*max_key,max_value,length);
00194     }
00195     (*max_key)+= length;
00196     return 1;
00197   }
00198   return 0;
00199 }
00200 
00201 
00202 int optimizer::SEL_ARG::store_min_key(KEY_PART *key, unsigned char **range_key, uint32_t *range_key_flag)
00203 {
00204   optimizer::SEL_ARG *key_tree= first();
00205   uint32_t res= key_tree->store_min(key[key_tree->part].store_length,
00206                                     range_key,
00207                                     *range_key_flag);
00208   *range_key_flag|= key_tree->min_flag;
00209 
00210   if (key_tree->next_key_part &&
00211       key_tree->next_key_part->part == key_tree->part+1 &&
00212       ! (*range_key_flag & (NO_MIN_RANGE | NEAR_MIN)) &&
00213       key_tree->next_key_part->type == optimizer::SEL_ARG::KEY_RANGE)
00214   {
00215     res+= key_tree->next_key_part->store_min_key(key,
00216                                                  range_key,
00217                                                  range_key_flag);
00218   }
00219   return res;
00220 }
00221 
00222 int optimizer::SEL_ARG::store_max_key(KEY_PART *key, unsigned char **range_key, uint32_t *range_key_flag)
00223 {
00224   SEL_ARG *key_tree= last();
00225   uint32_t res= key_tree->store_max(key[key_tree->part].store_length,
00226                                     range_key,
00227                                     *range_key_flag);
00228   (*range_key_flag)|= key_tree->max_flag;
00229   if (key_tree->next_key_part &&
00230       key_tree->next_key_part->part == key_tree->part+1 &&
00231       ! (*range_key_flag & (NO_MAX_RANGE | NEAR_MAX)) &&
00232       key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
00233     res+= key_tree->next_key_part->store_max_key(key,
00234                                                  range_key,
00235                                                  range_key_flag);
00236   return res;
00237 }
00238 
00239 optimizer::SEL_ARG::SEL_ARG(optimizer::SEL_ARG &arg)
00240   :
00241     memory::SqlAlloc()
00242 {
00243   type= arg.type;
00244   min_flag= arg.min_flag;
00245   max_flag= arg.max_flag;
00246   maybe_flag= arg.maybe_flag;
00247   maybe_null= arg.maybe_null;
00248   part= arg.part;
00249   field= arg.field;
00250   min_value= arg.min_value;
00251   max_value= arg.max_value;
00252   next_key_part= arg.next_key_part;
00253   use_count=1;
00254   elements=1;
00255 }
00256 
00257 
00258 void optimizer::SEL_ARG::make_root()
00259 {
00260   left= right= &optimizer::null_element;
00261   color= BLACK;
00262   next= prev =0;
00263   use_count= 0;
00264   elements= 1;
00265 }
00266 
00267 optimizer::SEL_ARG::SEL_ARG(Field *f,
00268                             const unsigned char *min_value_arg,
00269                             const unsigned char *max_value_arg)
00270   :
00271     min_flag(0),
00272     max_flag(0),
00273     maybe_flag(0),
00274     maybe_null(f->real_maybe_null()),
00275     elements(1),
00276     use_count(1),
00277     field(f),
00278     min_value((unsigned char*) min_value_arg),
00279     max_value((unsigned char*) max_value_arg),
00280     next(0),
00281     prev(0),
00282     next_key_part(0),
00283     color(BLACK),
00284     type(KEY_RANGE)
00285 {
00286   left= right= &optimizer::null_element;
00287 }
00288 
00289 optimizer::SEL_ARG::SEL_ARG(Field *field_,
00290                             uint8_t part_,
00291                             unsigned char *min_value_,
00292                             unsigned char *max_value_,
00293                 uint8_t min_flag_,
00294                             uint8_t max_flag_,
00295                             uint8_t maybe_flag_)
00296   :
00297     min_flag(min_flag_),
00298     max_flag(max_flag_),
00299     maybe_flag(maybe_flag_),
00300     part(part_),
00301     maybe_null(field_->real_maybe_null()),
00302     elements(1),
00303     use_count(1),
00304     field(field_),
00305     min_value(min_value_),
00306     max_value(max_value_),
00307     next(0),
00308     prev(0),
00309     next_key_part(0),
00310     color(BLACK),
00311     type(KEY_RANGE)
00312 {
00313   left= right= &optimizer::null_element;
00314 }
00315 
00316 optimizer::SEL_ARG *optimizer::SEL_ARG::clone(RangeParameter *param, optimizer::SEL_ARG *new_parent, optimizer::SEL_ARG **next_arg)
00317 {
00318   optimizer::SEL_ARG *tmp= NULL;
00319 
00320   /* Bail out if we have already generated too many SEL_ARGs */
00321   if (++param->alloced_sel_args > MAX_SEL_ARGS)
00322     return 0;
00323 
00324   if (type != KEY_RANGE)
00325   {
00326     tmp= new (*param->mem_root) optimizer::SEL_ARG(type);
00327     tmp->prev= *next_arg; // Link into next/prev chain
00328     (*next_arg)->next= tmp;
00329     (*next_arg)= tmp;
00330   }
00331   else
00332   {
00333     tmp= new (*param->mem_root) optimizer::SEL_ARG(field, part, min_value, max_value, min_flag, max_flag, maybe_flag);
00334     tmp->parent= new_parent;
00335     tmp->next_key_part= next_key_part;
00336     if (left != &optimizer::null_element)
00337       if (! (tmp->left= left->clone(param, tmp, next_arg)))
00338   return 0; // OOM
00339 
00340     tmp->prev= *next_arg; // Link into next/prev chain
00341     (*next_arg)->next= tmp;
00342     (*next_arg)= tmp;
00343 
00344     if (right != &optimizer::null_element)
00345       if (! (tmp->right= right->clone(param, tmp, next_arg)))
00346   return 0; // OOM
00347   }
00348   increment_use_count(1);
00349   tmp->color= color;
00350   tmp->elements= this->elements;
00351   return tmp;
00352 }
00353 
00354 optimizer::SEL_ARG *optimizer::SEL_ARG::first()
00355 {
00356   optimizer::SEL_ARG *next_arg= this;
00357   if (! next_arg->left)
00358     return 0; // MAYBE_KEY
00359   while (next_arg->left != &optimizer::null_element)
00360     next_arg= next_arg->left;
00361   return next_arg;
00362 }
00363 
00364 optimizer::SEL_ARG *optimizer::SEL_ARG::last()
00365 {
00366   SEL_ARG *next_arg= this;
00367   if (! next_arg->right)
00368     return 0; // MAYBE_KEY
00369   while (next_arg->right != &optimizer::null_element)
00370     next_arg=next_arg->right;
00371   return next_arg;
00372 }
00373 
00374 
00375 optimizer::SEL_ARG *optimizer::SEL_ARG::clone_tree(RangeParameter *param)
00376 {
00377   optimizer::SEL_ARG tmp_link;
00378   optimizer::SEL_ARG* next_arg= NULL;
00379   next_arg= &tmp_link;
00380   optimizer::SEL_ARG* root= clone(param, (SEL_ARG *) 0, &next_arg);
00381   if (not root)
00382     return 0;
00383   next_arg->next= 0; // Fix last link
00384   tmp_link.next->prev= 0; // Fix first link
00385   if (root) // If not OOM
00386     root->use_count= 0;
00387   return root;
00388 }
00389 
00390 
00391 optimizer::SEL_ARG *
00392 optimizer::SEL_ARG::insert(optimizer::SEL_ARG *key)
00393 {
00394   optimizer::SEL_ARG *element= NULL;
00395   optimizer::SEL_ARG **par= NULL;
00396   optimizer::SEL_ARG *last_element= NULL;
00397 
00398   for (element= this; element != &optimizer::null_element; )
00399   {
00400     last_element= element;
00401     if (key->cmp_min_to_min(element) > 0)
00402     {
00403       par= &element->right; element= element->right;
00404     }
00405     else
00406     {
00407       par= &element->left; element= element->left;
00408     }
00409   }
00410   *par= key;
00411   key->parent= last_element;
00412   /* Link in list */
00413   if (par == &last_element->left)
00414   {
00415     key->next= last_element;
00416     if ((key->prev=last_element->prev))
00417       key->prev->next= key;
00418     last_element->prev= key;
00419   }
00420   else
00421   {
00422     if ((key->next= last_element->next))
00423       key->next->prev= key;
00424     key->prev= last_element;
00425     last_element->next= key;
00426   }
00427   key->left= key->right= &optimizer::null_element;
00428   optimizer::SEL_ARG *root= rb_insert(key); // rebalance tree
00429   root->use_count= this->use_count;   // copy root info
00430   root->elements= this->elements+1;
00431   root->maybe_flag= this->maybe_flag;
00432   return root;
00433 }
00434 
00435 
00436 /*
00437 ** Find best key with min <= given key
00438 ** Because the call context this should never return 0 to get_range
00439 */
00440 optimizer::SEL_ARG *
00441 optimizer::SEL_ARG::find_range(optimizer::SEL_ARG *key)
00442 {
00443   optimizer::SEL_ARG *element= this;
00444   optimizer::SEL_ARG *found= NULL;
00445 
00446   for (;;)
00447   {
00448     if (element == &optimizer::null_element)
00449       return found;
00450     int cmp= element->cmp_min_to_min(key);
00451     if (cmp == 0)
00452       return element;
00453     if (cmp < 0)
00454     {
00455       found= element;
00456       element= element->right;
00457     }
00458     else
00459       element= element->left;
00460   }
00461 }
00462 
00463 
00464 /*
00465   Remove a element from the tree
00466 
00467   SYNOPSIS
00468     tree_delete()
00469     key   Key that is to be deleted from tree (this)
00470 
00471   NOTE
00472     This also frees all sub trees that is used by the element
00473 
00474   RETURN
00475     root of new tree (with key deleted)
00476 */
00477 optimizer::SEL_ARG *
00478 optimizer::SEL_ARG::tree_delete(optimizer::SEL_ARG *key)
00479 {
00480   enum leaf_color remove_color;
00481   optimizer::SEL_ARG *root= NULL;
00482   optimizer::SEL_ARG *nod= NULL;
00483   optimizer::SEL_ARG **par= NULL;
00484   optimizer::SEL_ARG *fix_par= NULL;
00485 
00486   root= this;
00487   this->parent= 0;
00488 
00489   /* Unlink from list */
00490   if (key->prev)
00491     key->prev->next= key->next;
00492   if (key->next)
00493     key->next->prev= key->prev;
00494   key->increment_use_count(-1);
00495   if (! key->parent)
00496     par= &root;
00497   else
00498     par= key->parent_ptr();
00499 
00500   if (key->left == &optimizer::null_element)
00501   {
00502     *par= nod= key->right;
00503     fix_par= key->parent;
00504     if (nod != &optimizer::null_element)
00505       nod->parent= fix_par;
00506     remove_color= key->color;
00507   }
00508   else if (key->right == &optimizer::null_element)
00509   {
00510     *par= nod= key->left;
00511     nod->parent= fix_par= key->parent;
00512     remove_color= key->color;
00513   }
00514   else
00515   {
00516     optimizer::SEL_ARG *tmp= key->next; // next bigger key (exist!)
00517     nod= *tmp->parent_ptr()= tmp->right;  // unlink tmp from tree
00518     fix_par= tmp->parent;
00519     if (nod != &optimizer::null_element)
00520       nod->parent= fix_par;
00521     remove_color= tmp->color;
00522 
00523     tmp->parent= key->parent;     // Move node in place of key
00524     (tmp->left= key->left)->parent= tmp;
00525     if ((tmp->right=key->right) != &optimizer::null_element)
00526       tmp->right->parent= tmp;
00527     tmp->color= key->color;
00528     *par= tmp;
00529     if (fix_par == key)       // key->right == key->next
00530       fix_par= tmp;       // new parent of nod
00531   }
00532 
00533   if (root == &optimizer::null_element)
00534     return 0;       // Maybe root later
00535   if (remove_color == BLACK)
00536     root= rb_delete_fixup(root, nod, fix_par);
00537 
00538   root->use_count= this->use_count;   // Fix root counters
00539   root->elements= this->elements-1;
00540   root->maybe_flag= this->maybe_flag;
00541   return root;
00542 }
00543 
00544 
00545 optimizer::SEL_ARG *
00546 optimizer::SEL_ARG::rb_insert(optimizer::SEL_ARG *leaf)
00547 {
00548   optimizer::SEL_ARG *y= NULL;
00549   optimizer::SEL_ARG *par= NULL;
00550   optimizer::SEL_ARG *par2= NULL;
00551   optimizer::SEL_ARG *root= NULL;
00552 
00553   root= this;
00554   root->parent= 0;
00555 
00556   leaf->color= RED;
00557   while (leaf != root && (par= leaf->parent)->color == RED)
00558   {         // This can't be root or 1 level under
00559     if (par == (par2= leaf->parent->parent)->left)
00560     {
00561       y= par2->right;
00562       if (y->color == RED)
00563       {
00564         par->color= BLACK;
00565         y->color= BLACK;
00566         leaf= par2;
00567         leaf->color= RED;   /* And the loop continues */
00568       }
00569       else
00570       {
00571         if (leaf == par->right)
00572         {
00573           left_rotate(&root,leaf->parent);
00574           par= leaf; /* leaf is now parent to old leaf */
00575         }
00576         par->color= BLACK;
00577         par2->color= RED;
00578         right_rotate(&root, par2);
00579         break;
00580       }
00581     }
00582     else
00583     {
00584       y= par2->left;
00585       if (y->color == RED)
00586       {
00587         par->color= BLACK;
00588         y->color= BLACK;
00589         leaf= par2;
00590         leaf->color= RED;   /* And the loop continues */
00591       }
00592       else
00593       {
00594         if (leaf == par->left)
00595         {
00596           right_rotate(&root,par);
00597           par= leaf;
00598         }
00599         par->color= BLACK;
00600         par2->color= RED;
00601         left_rotate(&root, par2);
00602         break;
00603       }
00604     }
00605   }
00606   root->color= BLACK;
00607 
00608   return root;
00609 }
00610 
00611 
00612 optimizer::SEL_ARG *optimizer::rb_delete_fixup(optimizer::SEL_ARG *root,
00613                                                optimizer::SEL_ARG *key,
00614                                                optimizer::SEL_ARG *par)
00615 {
00616   optimizer::SEL_ARG *x= NULL;
00617   optimizer::SEL_ARG *w= NULL;
00618   root->parent= 0;
00619 
00620   x= key;
00621   while (x != root && x->color == optimizer::SEL_ARG::BLACK)
00622   {
00623     if (x == par->left)
00624     {
00625       w= par->right;
00626       if (w->color == optimizer::SEL_ARG::RED)
00627       {
00628         w->color= optimizer::SEL_ARG::BLACK;
00629         par->color= optimizer::SEL_ARG::RED;
00630         left_rotate(&root, par);
00631         w= par->right;
00632       }
00633       if (w->left->color == optimizer::SEL_ARG::BLACK &&
00634           w->right->color == optimizer::SEL_ARG::BLACK)
00635       {
00636         w->color= optimizer::SEL_ARG::RED;
00637         x= par;
00638       }
00639       else
00640       {
00641         if (w->right->color == optimizer::SEL_ARG::BLACK)
00642         {
00643           w->left->color= optimizer::SEL_ARG::BLACK;
00644           w->color= optimizer::SEL_ARG::RED;
00645           right_rotate(&root, w);
00646           w= par->right;
00647         }
00648         w->color= par->color;
00649         par->color= optimizer::SEL_ARG::BLACK;
00650         w->right->color= optimizer::SEL_ARG::BLACK;
00651         left_rotate(&root, par);
00652         x= root;
00653         break;
00654       }
00655     }
00656     else
00657     {
00658       w= par->left;
00659       if (w->color == optimizer::SEL_ARG::RED)
00660       {
00661         w->color= optimizer::SEL_ARG::BLACK;
00662         par->color= optimizer::SEL_ARG::RED;
00663         right_rotate(&root, par);
00664         w= par->left;
00665       }
00666       if (w->right->color == optimizer::SEL_ARG::BLACK &&
00667           w->left->color == optimizer::SEL_ARG::BLACK)
00668       {
00669         w->color= optimizer::SEL_ARG::RED;
00670         x= par;
00671       }
00672       else
00673       {
00674         if (w->left->color == SEL_ARG::BLACK)
00675         {
00676           w->right->color= optimizer::SEL_ARG::BLACK;
00677           w->color= optimizer::SEL_ARG::RED;
00678           left_rotate(&root, w);
00679           w= par->left;
00680         }
00681         w->color= par->color;
00682         par->color= optimizer::SEL_ARG::BLACK;
00683         w->left->color= optimizer::SEL_ARG::BLACK;
00684         right_rotate(&root, par);
00685         x= root;
00686         break;
00687       }
00688     }
00689     par= x->parent;
00690   }
00691   x->color= optimizer::SEL_ARG::BLACK;
00692   return root;
00693 }
00694 
00695 
00696 } /* namespace drizzled */