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 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
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
00064
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
00076
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
00088
00089
00090
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
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
00155
00156
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
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
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 }