Drizzled Public API Documentation

func.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 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 
00022 #include <drizzled/check_stack_overrun.h>
00023 #include <drizzled/current_session.h>
00024 #include <drizzled/error.h>
00025 #include <drizzled/field/decimal.h>
00026 #include <drizzled/field/double.h>
00027 #include <drizzled/field/int32.h>
00028 #include <drizzled/field/int64.h>
00029 #include <drizzled/field/size.h>
00030 #include <drizzled/function/math/int.h>
00031 #include <drizzled/item/field.h>
00032 #include <drizzled/session.h>
00033 #include <drizzled/sql_list.h>
00034 #include <drizzled/sql_string.h>
00035 
00036 #include <limits>
00037 #include <algorithm>
00038 
00039 using namespace std;
00040 
00041 namespace drizzled
00042 {
00043 
00044 
00045 Item_func::Item_func(void):
00046   _session(*current_session),
00047   allowed_arg_cols(1), arg_count(0),
00048   const_item_cache(false)
00049   {
00050     with_sum_func= 0;
00051     collation.set(DERIVATION_SYSCONST);
00052   }
00053 
00054 Item_func::Item_func(Item *a):
00055   _session(*current_session),
00056   allowed_arg_cols(1), arg_count(1),
00057   const_item_cache(false)
00058   {
00059     args= tmp_arg;
00060     args[0]= a;
00061     with_sum_func= a->with_sum_func;
00062     collation.set(DERIVATION_SYSCONST);
00063   }
00064 
00065 Item_func::Item_func(Item *a,Item *b):
00066   _session(*current_session),
00067   allowed_arg_cols(1), arg_count(2),
00068   const_item_cache(false)
00069   {
00070     args= tmp_arg;
00071     args[0]= a; args[1]= b;
00072     with_sum_func= a->with_sum_func || b->with_sum_func;
00073     collation.set(DERIVATION_SYSCONST);
00074   }
00075 
00076 Item_func::Item_func(Item *a,Item *b,Item *c):
00077   _session(*current_session),
00078   allowed_arg_cols(1),
00079   const_item_cache(false)
00080   {
00081     arg_count= 0;
00082     if ((args= (Item**) memory::sql_alloc(sizeof(Item*)*3)))
00083     {
00084       arg_count= 3;
00085       args[0]= a; args[1]= b; args[2]= c;
00086       with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func;
00087     }
00088     collation.set(DERIVATION_SYSCONST);
00089   }
00090 
00091 Item_func::Item_func(Item *a,Item *b,Item *c,Item *d):
00092   _session(*current_session),
00093   allowed_arg_cols(1),
00094   const_item_cache(false)
00095   {
00096     arg_count= 0;
00097     if ((args= (Item**) memory::sql_alloc(sizeof(Item*)*4)))
00098     {
00099       arg_count= 4;
00100       args[0]= a; args[1]= b; args[2]= c; args[3]= d;
00101       with_sum_func= a->with_sum_func || b->with_sum_func ||
00102         c->with_sum_func || d->with_sum_func;
00103     }
00104     collation.set(DERIVATION_SYSCONST);
00105   }
00106 
00107 Item_func::Item_func(Item *a,Item *b,Item *c,Item *d,Item* e):
00108   _session(*current_session),
00109   allowed_arg_cols(1),
00110   const_item_cache(false)
00111   {
00112     arg_count= 5;
00113     if ((args= (Item**) memory::sql_alloc(sizeof(Item*)*5)))
00114     {
00115       args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e;
00116       with_sum_func= a->with_sum_func || b->with_sum_func ||
00117         c->with_sum_func || d->with_sum_func || e->with_sum_func ;
00118     }
00119     collation.set(DERIVATION_SYSCONST);
00120   }
00121 
00122 
00123 void Item_func::set_arguments(List<Item> &list)
00124 {
00125   allowed_arg_cols= 1;
00126   arg_count=list.size();
00127   args= tmp_arg;                                // If 2 arguments
00128   if (arg_count <= 2 || (args=(Item**) memory::sql_alloc(sizeof(Item*)*arg_count)))
00129   {
00130     List<Item>::iterator li(list.begin());
00131     Item *item;
00132     Item **save_args= args;
00133 
00134     while ((item=li++))
00135     {
00136       *(save_args++)= item;
00137       with_sum_func|=item->with_sum_func;
00138     }
00139   }
00140   list.clear();          // Fields are used
00141 }
00142 
00143 Item_func::Item_func(List<Item> &list) :
00144   _session(*current_session),
00145   allowed_arg_cols(1),
00146   const_item_cache(false)
00147 {
00148   collation.set(DERIVATION_SYSCONST);
00149   set_arguments(list);
00150 }
00151 
00152 Item_func::Item_func(Session *session, Item_func *item) :
00153   Item_result_field(session, item),
00154   _session(*current_session),
00155   allowed_arg_cols(item->allowed_arg_cols),
00156   arg_count(item->arg_count),
00157   used_tables_cache(item->used_tables_cache),
00158   not_null_tables_cache(item->not_null_tables_cache),
00159   const_item_cache(item->const_item_cache)
00160 {
00161   if (arg_count)
00162   {
00163     if (arg_count <=2)
00164       args= tmp_arg;
00165     else
00166     {
00167       if (!(args=(Item**) session->getMemRoot()->allocate(sizeof(Item*)*arg_count)))
00168         return;
00169     }
00170     memcpy(args, item->args, sizeof(Item*)*arg_count);
00171   }
00172   collation.set(DERIVATION_SYSCONST);
00173 }
00174 
00175 
00176 /*
00177   Resolve references to table column for a function and its argument
00178 
00179   SYNOPSIS:
00180   fix_fields()
00181   session    Thread object
00182   ref    Pointer to where this object is used.  This reference
00183   is used if we want to replace this object with another
00184   one (for example in the summary functions).
00185 
00186   DESCRIPTION
00187   Call fix_fields() for all arguments to the function.  The main intention
00188   is to allow all Item_field() objects to setup pointers to the table fields.
00189 
00190   Sets as a side effect the following class variables:
00191   maybe_null  Set if any argument may return NULL
00192   with_sum_func  Set if any of the arguments contains a sum function
00193   used_tables_cache Set to union of the tables used by arguments
00194 
00195   str_value.charset If this is a string function, set this to the
00196   character set for the first argument.
00197   If any argument is binary, this is set to binary
00198 
00199   If for any item any of the defaults are wrong, then this can
00200   be fixed in the fix_length_and_dec() function that is called
00201   after this one or by writing a specialized fix_fields() for the
00202   item.
00203 
00204   RETURN VALUES
00205   false  ok
00206   true  Got error.  Stored with my_error().
00207 */
00208 
00209 bool
00210 Item_func::fix_fields(Session *session, Item **)
00211 {
00212   assert(fixed == 0);
00213   Item **arg,**arg_end;
00214   void *save_session_marker= session->session_marker;
00215   unsigned char buff[STACK_BUFF_ALLOC];      // Max argument in function
00216   session->session_marker= 0;
00217   used_tables_cache= not_null_tables_cache= 0;
00218   const_item_cache= true;
00219 
00220   if (check_stack_overrun(session, STACK_MIN_SIZE, buff))
00221     return true;        // Fatal error if flag is set!
00222   if (arg_count)
00223   {            // Print purify happy
00224     for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
00225     {
00226       Item *item;
00227       /*
00228         We can't yet set item to *arg as fix_fields may change *arg
00229         We shouldn't call fix_fields() twice, so check 'fixed' field first
00230       */
00231       if ((!(*arg)->fixed && (*arg)->fix_fields(session, arg)))
00232         return true;
00233       item= *arg;
00234 
00235       if (allowed_arg_cols)
00236       {
00237         if (item->check_cols(allowed_arg_cols))
00238           return 1;
00239       }
00240       else
00241       {
00242         /*  we have to fetch allowed_arg_cols from first argument */
00243         assert(arg == args); // it is first argument
00244         allowed_arg_cols= item->cols();
00245         assert(allowed_arg_cols); // Can't be 0 any more
00246       }
00247 
00248       if (item->maybe_null)
00249         maybe_null=1;
00250 
00251       with_sum_func= with_sum_func || item->with_sum_func;
00252       used_tables_cache|=     item->used_tables();
00253       not_null_tables_cache|= item->not_null_tables();
00254       const_item_cache&=      item->const_item();
00255       with_subselect|=        item->with_subselect;
00256     }
00257   }
00258   fix_length_and_dec();
00259   if (session->is_error()) // An error inside fix_length_and_dec occured
00260     return true;
00261   fixed= 1;
00262   session->session_marker= save_session_marker;
00263   return false;
00264 }
00265 
00266 
00267 void Item_func::fix_after_pullout(Select_Lex *new_parent,
00268                                   Item **)
00269 {
00270   Item **arg,**arg_end;
00271 
00272   used_tables_cache= not_null_tables_cache= 0;
00273   const_item_cache= false;
00274 
00275   if (arg_count)
00276   {
00277     for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
00278     {
00279       (*arg)->fix_after_pullout(new_parent, arg);
00280       Item *item= *arg;
00281 
00282       used_tables_cache|=     item->used_tables();
00283       not_null_tables_cache|= item->not_null_tables();
00284       const_item_cache&=      item->const_item();
00285     }
00286   }
00287 }
00288 
00289 
00290 bool Item_func::walk(Item_processor processor, bool walk_subquery,
00291                      unsigned char *argument)
00292 {
00293   if (arg_count)
00294   {
00295     Item **arg,**arg_end;
00296     for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
00297     {
00298       if ((*arg)->walk(processor, walk_subquery, argument))
00299         return 1;
00300     }
00301   }
00302   return (this->*processor)(argument);
00303 }
00304 
00305 void Item_func::traverse_cond(Cond_traverser traverser,
00306                               void *argument, traverse_order order)
00307 {
00308   if (arg_count)
00309   {
00310     Item **arg,**arg_end;
00311 
00312     switch (order) {
00313     case (T_PREFIX):
00314       (*traverser)(this, argument);
00315       for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
00316       {
00317         (*arg)->traverse_cond(traverser, argument, order);
00318       }
00319       break;
00320     case (T_POSTFIX):
00321       for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
00322       {
00323         (*arg)->traverse_cond(traverser, argument, order);
00324       }
00325       (*traverser)(this, argument);
00326     }
00327   }
00328   else
00329     (*traverser)(this, argument);
00330 }
00331 
00332 
00350 Item *Item_func::transform(Item_transformer transformer, unsigned char *argument)
00351 {
00352   if (arg_count)
00353   {
00354     Item **arg,**arg_end;
00355     for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
00356     {
00357       Item *new_item= (*arg)->transform(transformer, argument);
00358       if (!new_item)
00359         return 0;
00360       *arg= new_item;
00361     }
00362   }
00363   return (this->*transformer)(argument);
00364 }
00365 
00366 
00391 Item *Item_func::compile(Item_analyzer analyzer, unsigned char **arg_p,
00392                          Item_transformer transformer, unsigned char *arg_t)
00393 {
00394   if (!(this->*analyzer)(arg_p))
00395     return 0;
00396   if (arg_count)
00397   {
00398     Item **arg,**arg_end;
00399     for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
00400     {
00401       /*
00402         The same parameter value of arg_p must be passed
00403         to analyze any argument of the condition formula.
00404       */
00405       unsigned char *arg_v= *arg_p;
00406       Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
00407       if (new_item && *arg != new_item)
00408         *arg= new_item;
00409     }
00410   }
00411   return (this->*transformer)(arg_t);
00412 }
00413 
00418 void Item_func::split_sum_func(Session *session, Item **ref_pointer_array,
00419                                List<Item> &fields)
00420 {
00421   Item **arg, **arg_end;
00422   for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
00423     (*arg)->split_sum_func(session, ref_pointer_array, fields, arg, true);
00424 }
00425 
00426 
00427 void Item_func::update_used_tables()
00428 {
00429   used_tables_cache=0;
00430   const_item_cache= true;
00431   for (uint32_t i=0 ; i < arg_count ; i++)
00432   {
00433     args[i]->update_used_tables();
00434     used_tables_cache|=args[i]->used_tables();
00435     const_item_cache&=args[i]->const_item();
00436   }
00437 }
00438 
00439 
00440 table_map Item_func::used_tables() const
00441 {
00442   return used_tables_cache;
00443 }
00444 
00445 
00446 table_map Item_func::not_null_tables() const
00447 {
00448   return not_null_tables_cache;
00449 }
00450 
00451 
00452 void Item_func::print(String *str)
00453 {
00454   str->append(func_name());
00455   str->append('(');
00456   print_args(str, 0);
00457   str->append(')');
00458 }
00459 
00460 
00461 void Item_func::print_args(String *str, uint32_t from)
00462 {
00463   for (uint32_t i=from ; i < arg_count ; i++)
00464   {
00465     if (i != from)
00466       str->append(',');
00467     args[i]->print(str);
00468   }
00469 }
00470 
00471 
00472 void Item_func::print_op(String *str)
00473 {
00474   str->append('(');
00475   for (uint32_t i=0 ; i < arg_count-1 ; i++)
00476   {
00477     args[i]->print(str);
00478     str->append(' ');
00479     str->append(func_name());
00480     str->append(' ');
00481   }
00482   args[arg_count-1]->print(str);
00483   str->append(')');
00484 }
00485 
00486 
00487 bool Item_func::eq(const Item *item, bool binary_cmp) const
00488 {
00489   /* Assume we don't have rtti */
00490   if (this == item)
00491     return 1;
00492   if (item->type() != FUNC_ITEM)
00493     return 0;
00494   Item_func *item_func=(Item_func*) item;
00495   Item_func::Functype func_type;
00496   if ((func_type= functype()) != item_func->functype() ||
00497       arg_count != item_func->arg_count ||
00498       (func_type != Item_func::FUNC_SP &&
00499        func_name() != item_func->func_name()) ||
00500       (func_type == Item_func::FUNC_SP &&
00501        my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
00502     return 0;
00503   for (uint32_t i=0; i < arg_count ; i++)
00504     if (!args[i]->eq(item_func->args[i], binary_cmp))
00505       return 0;
00506   return 1;
00507 }
00508 
00509 
00510 bool Item_func::get_arg0_date(type::Time &ltime, uint32_t fuzzy_date)
00511 {
00512   return (null_value=args[0]->get_date(ltime, fuzzy_date));
00513 }
00514 
00515 
00516 bool Item_func::get_arg0_time(type::Time &ltime)
00517 {
00518   return (null_value= args[0]->get_time(ltime));
00519 }
00520 
00521 
00522 bool Item_func::is_null()
00523 {
00524   update_null_value();
00525   return null_value;
00526 }
00527 
00528 
00529 Field *Item_func::tmp_table_field(Table *table)
00530 {
00531   Field *field= NULL;
00532 
00533   switch (result_type()) {
00534   case INT_RESULT:
00535     if (unsigned_flag)
00536     {
00537       field= new field::Size(max_length, maybe_null, name, true);
00538     } 
00539     else if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
00540     {
00541       field= new field::Int64(max_length, maybe_null, name, false);
00542     }
00543     else
00544     {
00545       field= new field::Int32(max_length, maybe_null, name, false);
00546     }
00547 
00548     break;
00549 
00550   case REAL_RESULT:
00551     field= new Field_double(max_length, maybe_null, name, decimals);
00552     break;
00553 
00554   case STRING_RESULT:
00555     return make_string_field(table);
00556 
00557   case DECIMAL_RESULT:
00558     field= new Field_decimal(class_decimal_precision_to_length(decimal_precision(),
00559                                                             decimals,
00560                                                             unsigned_flag),
00561                              maybe_null,
00562                              name,
00563                              decimals,
00564                              unsigned_flag);
00565     break;
00566   case ROW_RESULT:
00567     // This case should never be chosen
00568     assert(0);
00569     break;
00570   }
00571 
00572   if (field)
00573     field->init(table);
00574 
00575   return field;
00576 }
00577 
00578 
00579 type::Decimal *Item_func::val_decimal(type::Decimal *decimal_value)
00580 {
00581   assert(fixed);
00582   int2_class_decimal(E_DEC_FATAL_ERROR, val_int(), unsigned_flag, decimal_value);
00583   return decimal_value;
00584 }
00585 
00586 
00587 bool Item_func::agg_arg_collations(DTCollation &c, Item **items,
00588                                    uint32_t nitems, uint32_t flags)
00589 {
00590   return agg_item_collations(c, func_name(), items, nitems, flags, 1);
00591 }
00592 
00593 
00594 bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
00595                                                   Item **items,
00596                                                   uint32_t nitems,
00597                                                   uint32_t flags)
00598 {
00599   return agg_item_collations_for_comparison(c, func_name(),
00600                                             items, nitems, flags);
00601 }
00602 
00603 
00604 bool Item_func::agg_arg_charsets(DTCollation &c, Item **items, uint32_t nitems,
00605                                  uint32_t flags, int item_sep)
00606 {
00607   return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep);
00608 }
00609 
00610 
00611 double Item_func::fix_result(double value)
00612 {
00613   static double fix_infinity= numeric_limits<double>::infinity();
00614 
00615   if (value != fix_infinity && value != -fix_infinity)
00616     return value;
00617   null_value=1;
00618   return 0.0;
00619 }
00620 
00621 
00622 void Item_func::fix_num_length_and_dec()
00623 {
00624   uint32_t fl_length= 0;
00625   decimals=0;
00626   for (uint32_t i=0 ; i < arg_count ; i++)
00627   {
00628     set_if_bigger(decimals,args[i]->decimals);
00629     set_if_bigger(fl_length, args[i]->max_length);
00630   }
00631   max_length=float_length(decimals);
00632   if (fl_length > max_length)
00633   {
00634     decimals= NOT_FIXED_DEC;
00635     max_length= float_length(NOT_FIXED_DEC);
00636   }
00637 }
00638 
00644 void Item_func::count_decimal_length()
00645 {
00646   int max_int_part= 0;
00647   decimals= 0;
00648   unsigned_flag= 1;
00649   for (uint32_t i= 0 ; i < arg_count ; i++)
00650   {
00651     set_if_bigger(decimals, args[i]->decimals);
00652     set_if_bigger(max_int_part, args[i]->decimal_int_part());
00653     set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
00654   }
00655   int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
00656   max_length= class_decimal_precision_to_length(precision, decimals,
00657                                              unsigned_flag);
00658 }
00659 
00660 
00665 void Item_func::count_only_length()
00666 {
00667   max_length= 0;
00668   unsigned_flag= 0;
00669   for (uint32_t i=0 ; i < arg_count ; i++)
00670   {
00671     set_if_bigger(max_length, args[i]->max_length);
00672     set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
00673   }
00674 }
00675 
00676 
00682 void Item_func::count_real_length()
00683 {
00684   uint32_t length= 0;
00685   decimals= 0;
00686   max_length= 0;
00687   for (uint32_t i=0 ; i < arg_count ; i++)
00688   {
00689     if (decimals != NOT_FIXED_DEC)
00690     {
00691       set_if_bigger(decimals, args[i]->decimals);
00692       set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
00693     }
00694     set_if_bigger(max_length, args[i]->max_length);
00695   }
00696   if (decimals != NOT_FIXED_DEC)
00697   {
00698     max_length= length;
00699     length+= decimals;
00700     if (length < max_length)  // If previous operation gave overflow
00701       max_length= UINT32_MAX;
00702     else
00703       max_length= length;
00704   }
00705 }
00706 
00707 
00708 
00709 void Item_func::signal_divide_by_null()
00710 {
00711   my_error(ER_DIVISION_BY_ZERO, MYF(0));
00712   null_value= 0;
00713 }
00714 
00715 
00716 Item *Item_func::get_tmp_table_item(Session *session)
00717 {
00718   if (!with_sum_func && !const_item() && functype() != SUSERVAR_FUNC)
00719     return new Item_field(result_field);
00720   return copy_or_same(session);
00721 }
00722 
00723 
00724 } /* namespace drizzled */