~drizzle-trunk/drizzle/development

492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2008 Sun Microsystems
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
20
#include "config.h"
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
21
670.1.20 by Monty Taylor
Renamed functions to function... everything else is singular.
22
#include <drizzled/function/min_max.h>
584.4.7 by Monty Taylor
Removed a big bank of includes from item.h.
23
#include <drizzled/item/cmpfunc.h>
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
24
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
25
namespace drizzled
26
{
27
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
28
void Item_func_min_max::fix_length_and_dec()
29
{
30
  int max_int_part=0;
31
  bool datetime_found= false;
32
  decimals=0;
33
  max_length=0;
34
  maybe_null=0;
35
  cmp_type=args[0]->result_type();
36
37
  for (uint32_t i=0 ; i < arg_count ; i++)
38
  {
39
    set_if_bigger(max_length, args[i]->max_length);
40
    set_if_bigger(decimals, args[i]->decimals);
41
    set_if_bigger(max_int_part, args[i]->decimal_int_part());
42
    if (args[i]->maybe_null)
43
      maybe_null=1;
44
    cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
45
    if (args[i]->result_type() != ROW_RESULT && args[i]->is_datetime())
46
    {
47
      datetime_found= true;
48
      if (!datetime_item || args[i]->field_type() == DRIZZLE_TYPE_DATETIME)
49
        datetime_item= args[i];
50
    }
51
  }
52
  if (cmp_type == STRING_RESULT)
53
  {
54
    agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1);
55
    if (datetime_found)
56
    {
1633.4.7 by Brian Aker
Put a copy of the Session in the root of function to make use of.
57
      session= getSessionPtr();
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
58
      compare_as_dates= true;
59
    }
60
  }
61
  else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
62
    max_length= my_decimal_precision_to_length(max_int_part+decimals, decimals,
63
                                            unsigned_flag);
64
  cached_field_type= agg_field_type(args, arg_count);
65
}
66
67
68
/*
69
  Compare item arguments in the DATETIME context.
70
71
  SYNOPSIS
72
    cmp_datetimes()
73
    value [out]   found least/greatest DATE/DATETIME value
74
75
  DESCRIPTION
76
    Compare item arguments as DATETIME values and return the index of the
77
    least/greatest argument in the arguments array.
78
    The correct integer DATE/DATETIME value of the found argument is
79
    stored to the value pointer, if latter is provided.
80
81
  RETURN
1819.9.93 by Georgi Kodinov, Stewart Smith
Merge Revision revid:georgi.kodinov@oracle.com-20100820085216-qun679n9hg6n0q4k from MySQL InnoDB
82
   0	If one of arguments is NULL or there was a execution error
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
83
   #	index of the least/greatest argument
84
*/
85
86
uint32_t Item_func_min_max::cmp_datetimes(uint64_t *value)
87
{
88
  uint64_t min_max= 0;
89
  uint32_t min_max_idx= 0;
90
91
  for (uint32_t i=0; i < arg_count ; i++)
92
  {
93
    Item **arg= args + i;
779.3.10 by Monty Taylor
Turned on -Wshadow.
94
    bool is_null_unused;
95
    uint64_t res= get_datetime_value(session, &arg, 0, datetime_item,
96
                                     &is_null_unused);
1819.9.93 by Georgi Kodinov, Stewart Smith
Merge Revision revid:georgi.kodinov@oracle.com-20100820085216-qun679n9hg6n0q4k from MySQL InnoDB
97
98
    /* Check if we need to stop (because of error or KILL)  and stop the loop */
99
    if (session->is_error())
100
    {
101
      null_value= 1;
102
      return 0;
103
    }
104
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
105
    if ((null_value= args[i]->null_value))
106
      return 0;
107
    if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0)
108
    {
109
      min_max= res;
110
      min_max_idx= i;
111
    }
112
  }
113
  if (value)
114
  {
115
    *value= min_max;
575.5.1 by David Axmark
Changed NEWDATE to DATE. One failing test but I think its somewhere else in the code
116
    if (datetime_item->field_type() == DRIZZLE_TYPE_DATE)
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
117
      *value/= 1000000L;
118
  }
119
  return min_max_idx;
120
}
121
122
123
String *Item_func_min_max::val_str(String *str)
124
{
125
  assert(fixed == 1);
126
  if (compare_as_dates)
127
  {
128
    String *str_res;
129
    uint32_t min_max_idx= cmp_datetimes(NULL);
130
    if (null_value)
131
      return 0;
132
    str_res= args[min_max_idx]->val_str(str);
1819.9.93 by Georgi Kodinov, Stewart Smith
Merge Revision revid:georgi.kodinov@oracle.com-20100820085216-qun679n9hg6n0q4k from MySQL InnoDB
133
    if (args[min_max_idx]->null_value)
134
    {
135
      // check if the call to val_str() above returns a NULL value
136
      null_value= 1;
137
      return NULL;
138
    }
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
139
    str_res->set_charset(collation.collation);
140
    return str_res;
141
  }
142
  switch (cmp_type) {
143
  case INT_RESULT:
2008 by Brian Aker
Formatting + remove default from switch/case.
144
    {
145
      int64_t nr=val_int();
146
      if (null_value)
147
        return 0;
148
      str->set_int(nr, unsigned_flag, &my_charset_bin);
149
      return str;
150
    }
151
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
152
  case DECIMAL_RESULT:
2008 by Brian Aker
Formatting + remove default from switch/case.
153
    {
154
      my_decimal dec_buf, *dec_val= val_decimal(&dec_buf);
155
      if (null_value)
156
        return 0;
157
      my_decimal2string(E_DEC_FATAL_ERROR, dec_val, 0, 0, 0, str);
158
      return str;
159
    }
160
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
161
  case REAL_RESULT:
2008 by Brian Aker
Formatting + remove default from switch/case.
162
    {
163
      double nr= val_real();
164
      if (null_value)
165
        return 0;
166
      str->set_real(nr,decimals,&my_charset_bin);
167
      return str;
168
    }
169
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
170
  case STRING_RESULT:
171
    {
2008 by Brian Aker
Formatting + remove default from switch/case.
172
      String *res= NULL;
173
174
      for (uint32_t i=0; i < arg_count ; i++)
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
175
      {
2008 by Brian Aker
Formatting + remove default from switch/case.
176
        if (i == 0)
177
          res=args[i]->val_str(str);
178
        else
179
        {
180
          String *res2;
181
          res2= args[i]->val_str(res == str ? &tmp_value : str);
182
          if (res2)
183
          {
184
            int cmp= sortcmp(res,res2,collation.collation);
185
            if ((cmp_sign < 0 ? cmp : -cmp) < 0)
186
              res=res2;
187
          }
188
        }
189
        if ((null_value= args[i]->null_value))
190
          return 0;
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
191
      }
2008 by Brian Aker
Formatting + remove default from switch/case.
192
      res->set_charset(collation.collation);
193
      return res;
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
194
    }
2008 by Brian Aker
Formatting + remove default from switch/case.
195
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
196
  case ROW_RESULT:
197
    // This case should never be chosen
198
    assert(0);
199
    return 0;
200
  }
2008 by Brian Aker
Formatting + remove default from switch/case.
201
492.3.13 by Lee
code clean move Item_func_floor, Item_func_length, Item_func_min_max, Item_func_rand, Item_func_round to functions directory
202
  return 0;					// Keep compiler happy
203
}
204
205
206
double Item_func_min_max::val_real()
207
{
208
  assert(fixed == 1);
209
  double value=0.0;
210
  if (compare_as_dates)
211
  {
212
    uint64_t result= 0;
213
    (void)cmp_datetimes(&result);
214
    return (double)result;
215
  }
216
  for (uint32_t i=0; i < arg_count ; i++)
217
  {
218
    if (i == 0)
219
      value= args[i]->val_real();
220
    else
221
    {
222
      double tmp= args[i]->val_real();
223
      if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
224
	value=tmp;
225
    }
226
    if ((null_value= args[i]->null_value))
227
      break;
228
  }
229
  return value;
230
}
231
232
233
int64_t Item_func_min_max::val_int()
234
{
235
  assert(fixed == 1);
236
  int64_t value=0;
237
  if (compare_as_dates)
238
  {
239
    uint64_t result= 0;
240
    (void)cmp_datetimes(&result);
241
    return (int64_t)result;
242
  }
243
  for (uint32_t i=0; i < arg_count ; i++)
244
  {
245
    if (i == 0)
246
      value=args[i]->val_int();
247
    else
248
    {
249
      int64_t tmp=args[i]->val_int();
250
      if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
251
	value=tmp;
252
    }
253
    if ((null_value= args[i]->null_value))
254
      break;
255
  }
256
  return value;
257
}
258
259
260
my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
261
{
262
  assert(fixed == 1);
263
  my_decimal tmp_buf, *tmp, *res= NULL;
264
265
  if (compare_as_dates)
266
  {
267
    uint64_t value= 0;
268
    (void)cmp_datetimes(&value);
269
    uint64_t2decimal(value, dec);
270
    return dec;
271
  }
272
  for (uint32_t i=0; i < arg_count ; i++)
273
  {
274
    if (i == 0)
275
      res= args[i]->val_decimal(dec);
276
    else
277
    {
278
      tmp= args[i]->val_decimal(&tmp_buf);      // Zero if NULL
279
      if (tmp && (my_decimal_cmp(tmp, res) * cmp_sign) < 0)
280
      {
281
        if (tmp == &tmp_buf)
282
        {
283
          /* Move value out of tmp_buf as this will be reused on next loop */
284
          my_decimal2decimal(tmp, dec);
285
          res= dec;
286
        }
287
        else
288
          res= tmp;
289
      }
290
    }
291
    if ((null_value= args[i]->null_value))
292
    {
293
      res= 0;
294
      break;
295
    }
296
  }
297
  return res;
298
}
299
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
300
} /* namespace drizzled */