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 <drizzled/function/min_max.h>
00023 #include <drizzled/item/cmpfunc.h>
00024 #include <drizzled/session.h>
00025
00026 namespace drizzled
00027 {
00028
00029 void Item_func_min_max::fix_length_and_dec()
00030 {
00031 int max_int_part=0;
00032 bool datetime_found= false;
00033 decimals=0;
00034 max_length=0;
00035 maybe_null=0;
00036 cmp_type=args[0]->result_type();
00037
00038 for (uint32_t i=0 ; i < arg_count ; i++)
00039 {
00040 set_if_bigger(max_length, args[i]->max_length);
00041 set_if_bigger(decimals, args[i]->decimals);
00042 set_if_bigger(max_int_part, args[i]->decimal_int_part());
00043 if (args[i]->maybe_null)
00044 maybe_null=1;
00045 cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
00046 if (args[i]->result_type() != ROW_RESULT && args[i]->is_datetime())
00047 {
00048 datetime_found= true;
00049 if (!datetime_item || args[i]->field_type() == DRIZZLE_TYPE_DATETIME)
00050 datetime_item= args[i];
00051 }
00052 }
00053 if (cmp_type == STRING_RESULT)
00054 {
00055 agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1);
00056 if (datetime_found)
00057 {
00058 compare_as_dates= true;
00059 }
00060 }
00061 else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
00062 max_length= class_decimal_precision_to_length(max_int_part+decimals, decimals,
00063 unsigned_flag);
00064 cached_field_type= agg_field_type(args, arg_count);
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 uint32_t Item_func_min_max::cmp_datetimes(uint64_t *value)
00087 {
00088 uint64_t min_max= 0;
00089 uint32_t min_max_idx= 0;
00090
00091 for (uint32_t i=0; i < arg_count ; i++)
00092 {
00093 Item **arg= args + i;
00094 bool is_null_unused;
00095 uint64_t res= get_datetime_value(&getSession(), &arg, 0, datetime_item,
00096 &is_null_unused);
00097
00098
00099 if (getSession().is_error())
00100 {
00101 null_value= 1;
00102 return 0;
00103 }
00104
00105 if ((null_value= args[i]->null_value))
00106 return 0;
00107 if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0)
00108 {
00109 min_max= res;
00110 min_max_idx= i;
00111 }
00112 }
00113 if (value)
00114 {
00115 *value= min_max;
00116 if (datetime_item->field_type() == DRIZZLE_TYPE_DATE)
00117 *value/= 1000000L;
00118 }
00119 return min_max_idx;
00120 }
00121
00122
00123 String *Item_func_min_max::val_str(String *str)
00124 {
00125 assert(fixed == 1);
00126 if (compare_as_dates)
00127 {
00128 String *str_res;
00129 uint32_t min_max_idx= cmp_datetimes(NULL);
00130 if (null_value)
00131 return 0;
00132 str_res= args[min_max_idx]->val_str(str);
00133 if (args[min_max_idx]->null_value)
00134 {
00135
00136 null_value= 1;
00137 return NULL;
00138 }
00139 str_res->set_charset(collation.collation);
00140 return str_res;
00141 }
00142 switch (cmp_type) {
00143 case INT_RESULT:
00144 {
00145 int64_t nr=val_int();
00146 if (null_value)
00147 return 0;
00148 str->set_int(nr, unsigned_flag, &my_charset_bin);
00149 return str;
00150 }
00151
00152 case DECIMAL_RESULT:
00153 {
00154 type::Decimal dec_buf, *dec_val= val_decimal(&dec_buf);
00155 if (null_value)
00156 return 0;
00157 class_decimal2string(dec_val, 0, str);
00158 return str;
00159 }
00160
00161 case REAL_RESULT:
00162 {
00163 double nr= val_real();
00164 if (null_value)
00165 return 0;
00166 str->set_real(nr,decimals,&my_charset_bin);
00167 return str;
00168 }
00169
00170 case STRING_RESULT:
00171 {
00172 String *res= NULL;
00173
00174 for (uint32_t i=0; i < arg_count ; i++)
00175 {
00176 if (i == 0)
00177 res=args[i]->val_str(str);
00178 else
00179 {
00180 String *res2;
00181 res2= args[i]->val_str(res == str ? &tmp_value : str);
00182 if (res2)
00183 {
00184 int cmp= sortcmp(res,res2,collation.collation);
00185 if ((cmp_sign < 0 ? cmp : -cmp) < 0)
00186 res=res2;
00187 }
00188 }
00189 if ((null_value= args[i]->null_value))
00190 return 0;
00191 }
00192 res->set_charset(collation.collation);
00193 return res;
00194 }
00195
00196 case ROW_RESULT:
00197
00198 assert(0);
00199 return 0;
00200 }
00201
00202 return 0;
00203 }
00204
00205
00206 double Item_func_min_max::val_real()
00207 {
00208 assert(fixed == 1);
00209 double value=0.0;
00210 if (compare_as_dates)
00211 {
00212 uint64_t result= 0;
00213 (void)cmp_datetimes(&result);
00214 return (double)result;
00215 }
00216 for (uint32_t i=0; i < arg_count ; i++)
00217 {
00218 if (i == 0)
00219 value= args[i]->val_real();
00220 else
00221 {
00222 double tmp= args[i]->val_real();
00223 if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
00224 value=tmp;
00225 }
00226 if ((null_value= args[i]->null_value))
00227 break;
00228 }
00229 return value;
00230 }
00231
00232
00233 int64_t Item_func_min_max::val_int()
00234 {
00235 assert(fixed == 1);
00236 int64_t value=0;
00237 if (compare_as_dates)
00238 {
00239 uint64_t result= 0;
00240 (void)cmp_datetimes(&result);
00241 return (int64_t)result;
00242 }
00243 for (uint32_t i=0; i < arg_count ; i++)
00244 {
00245 if (i == 0)
00246 value=args[i]->val_int();
00247 else
00248 {
00249 int64_t tmp=args[i]->val_int();
00250 if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
00251 value=tmp;
00252 }
00253 if ((null_value= args[i]->null_value))
00254 break;
00255 }
00256 return value;
00257 }
00258
00259
00260 type::Decimal *Item_func_min_max::val_decimal(type::Decimal *dec)
00261 {
00262 assert(fixed == 1);
00263 type::Decimal tmp_buf, *tmp, *res= NULL;
00264
00265 if (compare_as_dates)
00266 {
00267 uint64_t value= 0;
00268 (void)cmp_datetimes(&value);
00269 uint64_t2decimal(value, dec);
00270 return dec;
00271 }
00272 for (uint32_t i=0; i < arg_count ; i++)
00273 {
00274 if (i == 0)
00275 res= args[i]->val_decimal(dec);
00276 else
00277 {
00278 tmp= args[i]->val_decimal(&tmp_buf);
00279 if (tmp && (class_decimal_cmp(tmp, res) * cmp_sign) < 0)
00280 {
00281 if (tmp == &tmp_buf)
00282 {
00283
00284 class_decimal2decimal(tmp, dec);
00285 res= dec;
00286 }
00287 else
00288 res= tmp;
00289 }
00290 }
00291 if ((null_value= args[i]->null_value))
00292 {
00293 res= 0;
00294 break;
00295 }
00296 }
00297 return res;
00298 }
00299
00300 }