Drizzled Public API Documentation

type_holder.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 <float.h>
00023 
00024 #include <algorithm>
00025 
00026 #include <drizzled/error.h>
00027 #include <drizzled/function/func.h>
00028 #include <drizzled/item/sum.h>
00029 #include <drizzled/item/type_holder.h>
00030 #include <drizzled/field/enum.h>
00031 
00032 using namespace std;
00033 
00034 namespace drizzled
00035 {
00036 
00037 Item_type_holder::Item_type_holder(Session *session, Item *item)
00038   :Item(session, item), enum_set_typelib(0), fld_type(get_real_type(item))
00039 {
00040   assert(item->fixed);
00041   maybe_null= item->maybe_null;
00042   collation.set(item->collation);
00043   get_full_info(item);
00044   /* fix variable decimals which always is NOT_FIXED_DEC */
00045   if (Field::result_merge_type(fld_type) == INT_RESULT)
00046     decimals= 0;
00047   prev_decimal_int_part= item->decimal_int_part();
00048 }
00049 
00050 
00051 Item_result Item_type_holder::result_type() const
00052 {
00053   return Field::result_merge_type(fld_type);
00054 }
00055 
00056 
00057 enum_field_types Item_type_holder::get_real_type(Item *item)
00058 {
00059   switch(item->type())
00060   {
00061   case FIELD_ITEM:
00062   {
00063     /*
00064       Item_fields::field_type ask Field_type() but sometimes field return
00065       a different type, like for enum/set, so we need to ask real type.
00066     */
00067     Field *field= ((Item_field *) item)->field;
00068     enum_field_types type= field->real_type();
00069     if (field->is_created_from_null_item)
00070       return DRIZZLE_TYPE_NULL;
00071     return type;
00072   }
00073   case SUM_FUNC_ITEM:
00074   {
00075     /*
00076       Argument of aggregate function sometimes should be asked about field
00077       type
00078     */
00079     Item_sum *item_sum= (Item_sum *) item;
00080     if (item_sum->keep_field_type())
00081       return get_real_type(item_sum->args[0]);
00082     break;
00083   }
00084   case FUNC_ITEM:
00085     if (((Item_func *) item)->functype() == Item_func::GUSERVAR_FUNC)
00086     {
00087       /*
00088         There are work around of problem with changing variable type on the
00089         fly and variable always report "string" as field type to get
00090         acceptable information for client in send_field, so we make field
00091         type from expression type.
00092       */
00093       switch (item->result_type()) {
00094       case STRING_RESULT:
00095         return DRIZZLE_TYPE_VARCHAR;
00096       case INT_RESULT:
00097         return DRIZZLE_TYPE_LONGLONG;
00098       case REAL_RESULT:
00099         return DRIZZLE_TYPE_DOUBLE;
00100       case DECIMAL_RESULT:
00101         return DRIZZLE_TYPE_DECIMAL;
00102       case ROW_RESULT:
00103         assert(0);
00104         return DRIZZLE_TYPE_VARCHAR;
00105       }
00106     }
00107     break;
00108   default:
00109     break;
00110   }
00111   return item->field_type();
00112 }
00113 
00114 
00115 bool Item_type_holder::join_types(Session *, Item *item)
00116 {
00117   uint32_t max_length_orig= max_length;
00118   uint32_t decimals_orig= decimals;
00119   fld_type= Field::field_type_merge(fld_type, get_real_type(item));
00120   {
00121     int item_decimals= item->decimals;
00122     /* fix variable decimals which always is NOT_FIXED_DEC */
00123     if (Field::result_merge_type(fld_type) == INT_RESULT)
00124       item_decimals= 0;
00125     decimals= max((int)decimals, item_decimals);
00126   }
00127   if (Field::result_merge_type(fld_type) == DECIMAL_RESULT)
00128   {
00129     decimals= min((int)max(decimals, item->decimals), DECIMAL_MAX_SCALE);
00130     int precision= min(max(prev_decimal_int_part, item->decimal_int_part())
00131                        + decimals, DECIMAL_MAX_PRECISION);
00132     unsigned_flag&= item->unsigned_flag;
00133     max_length= class_decimal_precision_to_length(precision, decimals,
00134                                                unsigned_flag);
00135   }
00136 
00137   switch (Field::result_merge_type(fld_type))
00138   {
00139   case STRING_RESULT:
00140     {
00141       const char *old_cs, *old_derivation;
00142       uint32_t old_max_chars= max_length / collation.collation->mbmaxlen;
00143       old_cs= collation.collation->name;
00144       old_derivation= collation.derivation_name();
00145       if (collation.aggregate(item->collation, MY_COLL_ALLOW_CONV))
00146       {
00147         my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
00148                  old_cs, old_derivation,
00149                  item->collation.collation->name,
00150                  item->collation.derivation_name(),
00151                  "UNION");
00152         return(true);
00153       }
00154       /*
00155         To figure out max_length, we have to take into account possible
00156         expansion of the size of the values because of character set
00157         conversions.
00158       */
00159       if (collation.collation != &my_charset_bin)
00160       {
00161         max_length= max(old_max_chars * collation.collation->mbmaxlen,
00162                         display_length(item) /
00163                         item->collation.collation->mbmaxlen *
00164                         collation.collation->mbmaxlen);
00165       }
00166       else
00167         set_if_bigger(max_length, display_length(item));
00168       break;
00169     }
00170   case REAL_RESULT:
00171     {
00172       if (decimals != NOT_FIXED_DEC)
00173       {
00174         int delta1= max_length_orig - decimals_orig;
00175         int delta2= item->max_length - item->decimals;
00176         max_length= max(delta1, delta2) + decimals;
00177         if (fld_type == DRIZZLE_TYPE_DOUBLE && max_length > DBL_DIG + 2)
00178         {
00179           max_length= DBL_DIG + 7;
00180           decimals= NOT_FIXED_DEC;
00181         }
00182       }
00183       else
00184         max_length= DBL_DIG+7;
00185       break;
00186     }
00187 
00188   case INT_RESULT:
00189   case DECIMAL_RESULT:
00190   case ROW_RESULT:
00191     max_length= max(max_length, display_length(item));
00192   };
00193   maybe_null|= item->maybe_null;
00194   get_full_info(item);
00195 
00196   /* Remember decimal integer part to be used in DECIMAL_RESULT handleng */
00197   prev_decimal_int_part= decimal_int_part();
00198 
00199   return(false);
00200 }
00201 
00202 
00203 uint32_t Item_type_holder::display_length(Item *item)
00204 {
00205   if (item->type() == Item::FIELD_ITEM)
00206     return ((Item_field *)item)->max_disp_length();
00207 
00208   switch (item->field_type())
00209   {
00210   case DRIZZLE_TYPE_TIME:
00211   case DRIZZLE_TYPE_BOOLEAN:
00212   case DRIZZLE_TYPE_UUID:
00213   case DRIZZLE_TYPE_MICROTIME:
00214   case DRIZZLE_TYPE_TIMESTAMP:
00215   case DRIZZLE_TYPE_DATETIME:
00216   case DRIZZLE_TYPE_DATE:
00217   case DRIZZLE_TYPE_VARCHAR:
00218   case DRIZZLE_TYPE_DECIMAL:
00219   case DRIZZLE_TYPE_ENUM:
00220   case DRIZZLE_TYPE_BLOB:
00221     return item->max_length;
00222   case DRIZZLE_TYPE_LONG:
00223     return MY_INT32_NUM_DECIMAL_DIGITS;
00224   case DRIZZLE_TYPE_DOUBLE:
00225     return 53;
00226   case DRIZZLE_TYPE_NULL:
00227     return 0;
00228   case DRIZZLE_TYPE_LONGLONG:
00229     return 20;
00230   }
00231   assert(0);
00232   abort();
00233 }
00234 
00235 
00236 Field *Item_type_holder::make_field_by_type(Table *table)
00237 {
00238   /*
00239     The field functions defines a field to be not null if null_ptr is not 0
00240   */
00241   unsigned char *null_ptr= maybe_null ? (unsigned char*) "" : 0;
00242   Field *field;
00243 
00244   switch (fld_type) {
00245   case DRIZZLE_TYPE_ENUM:
00246     assert(enum_set_typelib);
00247     field= new Field_enum((unsigned char *) 0,
00248                           max_length,
00249                           null_ptr,
00250                           0,
00251                           name,
00252                           enum_set_typelib,
00253                           collation.collation);
00254     if (field)
00255       field->init(table);
00256     return field;
00257   case DRIZZLE_TYPE_NULL:
00258     return make_string_field(table);
00259   default:
00260     break;
00261   }
00262   return tmp_table_field_from_field_type(table, 0);
00263 }
00264 
00265 
00266 void Item_type_holder::get_full_info(Item *item)
00267 {
00268   if (fld_type == DRIZZLE_TYPE_ENUM)
00269   {
00270     if (item->type() == Item::SUM_FUNC_ITEM &&
00271         (((Item_sum*)item)->sum_func() == Item_sum::MAX_FUNC ||
00272          ((Item_sum*)item)->sum_func() == Item_sum::MIN_FUNC))
00273       item = ((Item_sum*)item)->args[0];
00274     /*
00275       We can have enum/set type after merging only if we have one enum|set
00276       field (or MIN|MAX(enum|set field)) and number of NULL fields
00277     */
00278     assert((enum_set_typelib &&
00279                  get_real_type(item) == DRIZZLE_TYPE_NULL) ||
00280                 (!enum_set_typelib &&
00281                  item->type() == Item::FIELD_ITEM &&
00282                  (get_real_type(item) == DRIZZLE_TYPE_ENUM) &&
00283                  ((Field_enum*)((Item_field *) item)->field)->typelib));
00284     if (!enum_set_typelib)
00285     {
00286       enum_set_typelib= ((Field_enum*)((Item_field *) item)->field)->typelib;
00287     }
00288   }
00289 }
00290 
00291 
00292 double Item_type_holder::val_real()
00293 {
00294   assert(0); // should never be called
00295   return 0.0;
00296 }
00297 
00298 
00299 int64_t Item_type_holder::val_int()
00300 {
00301   assert(0); // should never be called
00302   return 0;
00303 }
00304 
00305 type::Decimal *Item_type_holder::val_decimal(type::Decimal *)
00306 {
00307   assert(0); // should never be called
00308   return 0;
00309 }
00310 
00311 String *Item_type_holder::val_str(String*)
00312 {
00313   assert(0); // should never be called
00314   return 0;
00315 }
00316 
00317 void Item_result_field::cleanup()
00318 {
00319   Item::cleanup();
00320   result_field= 0;
00321   return;
00322 }
00323 
00324 } /* namespace drizzled */