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