00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
00065
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
00077
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
00089
00090
00091
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
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
00156
00157
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
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
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
00276
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);
00295 return 0.0;
00296 }
00297
00298
00299 int64_t Item_type_holder::val_int()
00300 {
00301 assert(0);
00302 return 0;
00303 }
00304
00305 type::Decimal *Item_type_holder::val_decimal(type::Decimal *)
00306 {
00307 assert(0);
00308 return 0;
00309 }
00310
00311 String *Item_type_holder::val_str(String*)
00312 {
00313 assert(0);
00314 return 0;
00315 }
00316
00317 void Item_result_field::cleanup()
00318 {
00319 Item::cleanup();
00320 result_field= 0;
00321 return;
00322 }
00323
00324 }