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