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 Item_type_holder::Item_type_holder(Session *session, Item *item)
00037   :Item(session, item), enum_set_typelib(0), fld_type(get_real_type(item))
00038 {
00039   assert(item->fixed);
00040   maybe_null= item->maybe_null;
00041   collation.set(item->collation);
00042   get_full_info(item);
00043   /* fix variable decimals which always is NOT_FIXED_DEC */
00044   if (Field::result_merge_type(fld_type) == INT_RESULT)
00045     decimals= 0;
00046   prev_decimal_int_part= item->decimal_int_part();
00047 }
00048 
00049 
00050 Item_result Item_type_holder::result_type() const
00051 {
00052   return Field::result_merge_type(fld_type);
00053 }
00054 
00055 
00056 enum_field_types Item_type_holder::get_real_type(Item *item)
00057 {
00058   switch(item->type())
00059   {
00060   case FIELD_ITEM:
00061   {
00062     /*
00063       Item_fields::field_type ask Field_type() but sometimes field return
00064       a different type, like for enum/set, so we need to ask real type.
00065     */
00066     Field *field= ((Item_field *) item)->field;
00067     enum_field_types type= field->real_type();
00068     if (field->is_created_from_null_item)
00069       return DRIZZLE_TYPE_NULL;
00070     return type;
00071   }
00072   case SUM_FUNC_ITEM:
00073   {
00074     /*
00075       Argument of aggregate function sometimes should be asked about field
00076       type
00077     */
00078     Item_sum *item_sum= (Item_sum *) item;
00079     if (item_sum->keep_field_type())
00080       return get_real_type(item_sum->args[0]);
00081     break;
00082   }
00083   case FUNC_ITEM:
00084     if (((Item_func *) item)->functype() == Item_func::GUSERVAR_FUNC)
00085     {
00086       /*
00087         There are work around of problem with changing variable type on the
00088         fly and variable always report "string" as field type to get
00089         acceptable information for client in send_field, so we make field
00090         type from expression type.
00091       */
00092       switch (item->result_type()) {
00093       case STRING_RESULT:
00094         return DRIZZLE_TYPE_VARCHAR;
00095       case INT_RESULT:
00096         return DRIZZLE_TYPE_LONGLONG;
00097       case REAL_RESULT:
00098         return DRIZZLE_TYPE_DOUBLE;
00099       case DECIMAL_RESULT:
00100         return DRIZZLE_TYPE_DECIMAL;
00101       case ROW_RESULT:
00102         assert(0);
00103         return DRIZZLE_TYPE_VARCHAR;
00104       }
00105     }
00106     break;
00107   default:
00108     break;
00109   }
00110   return item->field_type();
00111 }
00112 
00113 
00114 bool Item_type_holder::join_types(Session *, Item *item)
00115 {
00116   uint32_t max_length_orig= max_length;
00117   uint32_t decimals_orig= decimals;
00118   fld_type= Field::field_type_merge(fld_type, get_real_type(item));
00119   {
00120     int item_decimals= item->decimals;
00121     /* fix variable decimals which always is NOT_FIXED_DEC */
00122     if (Field::result_merge_type(fld_type) == INT_RESULT)
00123       item_decimals= 0;
00124     decimals= max((int)decimals, item_decimals);
00125   }
00126   if (Field::result_merge_type(fld_type) == DECIMAL_RESULT)
00127   {
00128     decimals= min((int)max(decimals, item->decimals), DECIMAL_MAX_SCALE);
00129     int precision= min(max(prev_decimal_int_part, item->decimal_int_part())
00130                        + decimals, DECIMAL_MAX_PRECISION);
00131     unsigned_flag&= item->unsigned_flag;
00132     max_length= class_decimal_precision_to_length(precision, decimals,
00133                                                unsigned_flag);
00134   }
00135 
00136   switch (Field::result_merge_type(fld_type))
00137   {
00138   case STRING_RESULT:
00139     {
00140       const char *old_cs, *old_derivation;
00141       uint32_t old_max_chars= max_length / collation.collation->mbmaxlen;
00142       old_cs= collation.collation->name;
00143       old_derivation= collation.derivation_name();
00144       if (collation.aggregate(item->collation, MY_COLL_ALLOW_CONV))
00145       {
00146         my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
00147                  old_cs, old_derivation,
00148                  item->collation.collation->name,
00149                  item->collation.derivation_name(),
00150                  "UNION");
00151         return true;
00152       }
00153       /*
00154         To figure out max_length, we have to take into account possible
00155         expansion of the size of the values because of character set
00156         conversions.
00157       */
00158       if (collation.collation != &my_charset_bin)
00159       {
00160         max_length= max(old_max_chars * collation.collation->mbmaxlen,
00161                         display_length(item) /
00162                         item->collation.collation->mbmaxlen *
00163                         collation.collation->mbmaxlen);
00164       }
00165       else
00166         set_if_bigger(max_length, display_length(item));
00167       break;
00168     }
00169   case REAL_RESULT:
00170     {
00171       if (decimals != NOT_FIXED_DEC)
00172       {
00173         int delta1= max_length_orig - decimals_orig;
00174         int delta2= item->max_length - item->decimals;
00175         max_length= max(delta1, delta2) + decimals;
00176         if (fld_type == DRIZZLE_TYPE_DOUBLE && max_length > DBL_DIG + 2)
00177         {
00178           max_length= DBL_DIG + 7;
00179           decimals= NOT_FIXED_DEC;
00180         }
00181       }
00182       else
00183         max_length= DBL_DIG+7;
00184       break;
00185     }
00186 
00187   case INT_RESULT:
00188   case DECIMAL_RESULT:
00189   case ROW_RESULT:
00190     max_length= max(max_length, display_length(item));
00191   };
00192   maybe_null|= item->maybe_null;
00193   get_full_info(item);
00194 
00195   /* Remember decimal integer part to be used in DECIMAL_RESULT handleng */
00196   prev_decimal_int_part= decimal_int_part();
00197 
00198   return false;
00199 }
00200 
00201 
00202 uint32_t Item_type_holder::display_length(Item *item)
00203 {
00204   if (item->type() == Item::FIELD_ITEM)
00205     return ((Item_field *)item)->max_disp_length();
00206 
00207   switch (item->field_type())
00208   {
00209   case DRIZZLE_TYPE_TIME:
00210   case DRIZZLE_TYPE_BOOLEAN:
00211   case DRIZZLE_TYPE_UUID:
00212   case DRIZZLE_TYPE_IPV6:
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 */