~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/functions/func.cc

  • Committer: Monty Taylor
  • Date: 2008-10-16 09:12:23 UTC
  • mto: (511.1.6 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081016091223-17ngih0qu9vssjs3
We pass -Wunused-macros now!

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#include "config.h"
 
20
#include <drizzled/server_includes.h>
 
21
 
 
22
#include CSTDINT_H
 
23
#include <cassert>
 
24
 
 
25
#include <drizzled/version.h>
21
26
 
22
27
#include <drizzled/sql_string.h>
23
28
#include <drizzled/sql_list.h>
24
29
 
25
 
#include <drizzled/function/math/int.h>
26
 
#include <drizzled/field/int64_t.h>
27
 
#include <drizzled/field/long.h>
28
 
#include <drizzled/field/double.h>
29
 
#include <drizzled/field/decimal.h>
30
 
#include <drizzled/session.h>
31
 
#include <drizzled/error.h>
32
 
#include <drizzled/check_stack_overrun.h>
33
 
#include <limits>
34
 
#include <algorithm>
35
 
 
36
 
using namespace std;
37
 
 
38
 
namespace drizzled
39
 
{
 
30
#include <drizzled/functions/int.h>
40
31
 
41
32
 
42
33
void Item_func::set_arguments(List<Item> &list)
44
35
  allowed_arg_cols= 1;
45
36
  arg_count=list.elements;
46
37
  args= tmp_arg;                                // If 2 arguments
47
 
  if (arg_count <= 2 || (args=(Item**) memory::sql_alloc(sizeof(Item*)*arg_count)))
 
38
  if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
48
39
  {
49
40
    List_iterator_fast<Item> li(list);
50
41
    Item *item;
59
50
  list.empty();          // Fields are used
60
51
}
61
52
 
62
 
Item_func::Item_func(List<Item> &list) :
63
 
  _session(*current_session),
64
 
  allowed_arg_cols(1)
 
53
Item_func::Item_func(List<Item> &list)
 
54
  :allowed_arg_cols(1)
65
55
{
66
 
  collation.set(DERIVATION_SYSCONST);
67
56
  set_arguments(list);
68
57
}
69
58
 
70
 
Item_func::Item_func(Session *session, Item_func *item) :
71
 
  Item_result_field(session, item),
72
 
  _session(*current_session),
73
 
  allowed_arg_cols(item->allowed_arg_cols),
74
 
  arg_count(item->arg_count),
75
 
  used_tables_cache(item->used_tables_cache),
76
 
  not_null_tables_cache(item->not_null_tables_cache),
77
 
  const_item_cache(item->const_item_cache)
 
59
Item_func::Item_func(THD *thd, Item_func *item)
 
60
  :Item_result_field(thd, item),
 
61
   allowed_arg_cols(item->allowed_arg_cols),
 
62
   arg_count(item->arg_count),
 
63
   used_tables_cache(item->used_tables_cache),
 
64
   not_null_tables_cache(item->not_null_tables_cache),
 
65
   const_item_cache(item->const_item_cache)
78
66
{
79
67
  if (arg_count)
80
68
  {
82
70
      args= tmp_arg;
83
71
    else
84
72
    {
85
 
      if (!(args=(Item**) session->alloc(sizeof(Item*)*arg_count)))
 
73
      if (!(args=(Item**) thd->alloc(sizeof(Item*)*arg_count)))
86
74
        return;
87
75
    }
88
76
    memcpy(args, item->args, sizeof(Item*)*arg_count);
89
77
  }
90
 
  collation.set(DERIVATION_SYSCONST);
91
78
}
92
79
 
93
80
 
96
83
 
97
84
  SYNOPSIS:
98
85
  fix_fields()
99
 
  session    Thread object
 
86
  thd    Thread object
100
87
  ref    Pointer to where this object is used.  This reference
101
88
  is used if we want to replace this object with another
102
89
  one (for example in the summary functions).
125
112
*/
126
113
 
127
114
bool
128
 
Item_func::fix_fields(Session *session, Item **)
 
115
Item_func::fix_fields(THD *thd, Item **ref __attribute__((unused)))
129
116
{
130
117
  assert(fixed == 0);
131
118
  Item **arg,**arg_end;
132
 
  void *save_session_marker= session->session_marker;
 
119
  void *save_thd_marker= thd->thd_marker;
133
120
  unsigned char buff[STACK_BUFF_ALLOC];      // Max argument in function
134
 
  session->session_marker= 0;
 
121
  thd->thd_marker= 0;
135
122
  used_tables_cache= not_null_tables_cache= 0;
136
123
  const_item_cache=1;
137
124
 
138
 
  if (check_stack_overrun(session, STACK_MIN_SIZE, buff))
 
125
  if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
139
126
    return true;        // Fatal error if flag is set!
140
127
  if (arg_count)
141
128
  {            // Print purify happy
146
133
        We can't yet set item to *arg as fix_fields may change *arg
147
134
        We shouldn't call fix_fields() twice, so check 'fixed' field first
148
135
      */
149
 
      if ((!(*arg)->fixed && (*arg)->fix_fields(session, arg)))
150
 
        return true;
 
136
      if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
 
137
        return true;        /* purecov: inspected */
151
138
      item= *arg;
152
139
 
153
140
      if (allowed_arg_cols)
174
161
    }
175
162
  }
176
163
  fix_length_and_dec();
177
 
  if (session->is_error()) // An error inside fix_length_and_dec occured
 
164
  if (thd->is_error()) // An error inside fix_length_and_dec occured
178
165
    return true;
179
166
  fixed= 1;
180
 
  session->session_marker= save_session_marker;
 
167
  thd->thd_marker= save_thd_marker;
181
168
  return false;
182
169
}
183
170
 
184
171
 
185
 
void Item_func::fix_after_pullout(Select_Lex *new_parent,
186
 
                                  Item **)
 
172
void Item_func::fix_after_pullout(st_select_lex *new_parent,
 
173
                                  Item **ref __attribute__((unused)))
187
174
{
188
175
  Item **arg,**arg_end;
189
176
 
228
215
    Item **arg,**arg_end;
229
216
 
230
217
    switch (order) {
231
 
    case (T_PREFIX):
 
218
    case(PREFIX):
232
219
      (*traverser)(this, argument);
233
220
      for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
234
221
      {
235
222
        (*arg)->traverse_cond(traverser, argument, order);
236
223
      }
237
224
      break;
238
 
    case (T_POSTFIX):
 
225
    case (POSTFIX):
239
226
      for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
240
227
      {
241
228
        (*arg)->traverse_cond(traverser, argument, order);
277
264
        return 0;
278
265
 
279
266
      /*
280
 
        Session::change_item_tree() should be called only if the tree was
 
267
        THD::change_item_tree() should be called only if the tree was
281
268
        really transformed, i.e. when a new item has been created.
282
269
        Otherwise we'll be allocating a lot of unnecessary memory for
283
270
        change records at each execution.
284
271
      */
285
272
      if (*arg != new_item)
286
 
        getSession().change_item_tree(arg, new_item);
 
273
        current_thd->change_item_tree(arg, new_item);
287
274
    }
288
275
  }
289
276
  return (this->*transformer)(argument);
331
318
      unsigned char *arg_v= *arg_p;
332
319
      Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
333
320
      if (new_item && *arg != new_item)
334
 
        current_session->change_item_tree(arg, new_item);
 
321
        current_thd->change_item_tree(arg, new_item);
335
322
    }
336
323
  }
337
324
  return (this->*transformer)(arg_t);
341
328
   See comments in Item_cmp_func::split_sum_func()
342
329
*/
343
330
 
344
 
void Item_func::split_sum_func(Session *session, Item **ref_pointer_array,
 
331
void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
345
332
                               List<Item> &fields)
346
333
{
347
334
  Item **arg, **arg_end;
348
335
  for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
349
 
    (*arg)->split_sum_func(session, ref_pointer_array, fields, arg, true);
 
336
    (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, true);
350
337
}
351
338
 
352
339
 
468
455
    break;
469
456
  case STRING_RESULT:
470
457
    return make_string_field(table);
 
458
    break;
471
459
  case DECIMAL_RESULT:
472
 
    field= new Field_decimal(my_decimal_precision_to_length(decimal_precision(),
473
 
                                                            decimals,
474
 
                                                            unsigned_flag),
475
 
                             maybe_null,
476
 
                             name,
477
 
                             decimals,
478
 
                             unsigned_flag);
 
460
    field= new Field_new_decimal(
 
461
                       my_decimal_precision_to_length(decimal_precision(),
 
462
                                                      decimals,
 
463
                                                      unsigned_flag),
 
464
                       maybe_null, name, decimals, unsigned_flag);
479
465
    break;
480
466
  case ROW_RESULT:
481
467
  default:
524
510
 
525
511
double Item_func::fix_result(double value)
526
512
{
527
 
  static double fix_infinity= numeric_limits<double>::infinity();
528
 
 
529
 
  if (value != fix_infinity && value != -fix_infinity)
 
513
  if (CMATH_NAMESPACE::isfinite(value))
530
514
    return value;
531
515
  null_value=1;
532
516
  return 0.0;
533
517
}
534
 
 
535
 
 
536
 
void Item_func::fix_num_length_and_dec()
537
 
{
538
 
  uint32_t fl_length= 0;
539
 
  decimals=0;
540
 
  for (uint32_t i=0 ; i < arg_count ; i++)
541
 
  {
542
 
    set_if_bigger(decimals,args[i]->decimals);
543
 
    set_if_bigger(fl_length, args[i]->max_length);
544
 
  }
545
 
  max_length=float_length(decimals);
546
 
  if (fl_length > max_length)
547
 
  {
548
 
    decimals= NOT_FIXED_DEC;
549
 
    max_length= float_length(NOT_FIXED_DEC);
550
 
  }
551
 
}
552
 
 
553
 
/**
554
 
  Set max_length/decimals of function if function is fixed point and
555
 
  result length/precision depends on argument ones.
556
 
*/
557
 
 
558
 
void Item_func::count_decimal_length()
559
 
{
560
 
  int max_int_part= 0;
561
 
  decimals= 0;
562
 
  unsigned_flag= 1;
563
 
  for (uint32_t i= 0 ; i < arg_count ; i++)
564
 
  {
565
 
    set_if_bigger(decimals, args[i]->decimals);
566
 
    set_if_bigger(max_int_part, args[i]->decimal_int_part());
567
 
    set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
568
 
  }
569
 
  int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
570
 
  max_length= my_decimal_precision_to_length(precision, decimals,
571
 
                                             unsigned_flag);
572
 
}
573
 
 
574
 
 
575
 
/**
576
 
  Set max_length of if it is maximum length of its arguments.
577
 
*/
578
 
 
579
 
void Item_func::count_only_length()
580
 
{
581
 
  max_length= 0;
582
 
  unsigned_flag= 0;
583
 
  for (uint32_t i=0 ; i < arg_count ; i++)
584
 
  {
585
 
    set_if_bigger(max_length, args[i]->max_length);
586
 
    set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
587
 
  }
588
 
}
589
 
 
590
 
 
591
 
/**
592
 
  Set max_length/decimals of function if function is floating point and
593
 
  result length/precision depends on argument ones.
594
 
*/
595
 
 
596
 
void Item_func::count_real_length()
597
 
{
598
 
  uint32_t length= 0;
599
 
  decimals= 0;
600
 
  max_length= 0;
601
 
  for (uint32_t i=0 ; i < arg_count ; i++)
602
 
  {
603
 
    if (decimals != NOT_FIXED_DEC)
604
 
    {
605
 
      set_if_bigger(decimals, args[i]->decimals);
606
 
      set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
607
 
    }
608
 
    set_if_bigger(max_length, args[i]->max_length);
609
 
  }
610
 
  if (decimals != NOT_FIXED_DEC)
611
 
  {
612
 
    max_length= length;
613
 
    length+= decimals;
614
 
    if (length < max_length)  // If previous operation gave overflow
615
 
      max_length= UINT32_MAX;
616
 
    else
617
 
      max_length= length;
618
 
  }
619
 
}
620
 
 
621
 
 
622
 
 
623
 
void Item_func::signal_divide_by_null()
624
 
{
625
 
  push_warning(getSessionPtr(), DRIZZLE_ERROR::WARN_LEVEL_ERROR, ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
626
 
  null_value= 1;
627
 
}
628
 
 
629
 
 
630
 
Item *Item_func::get_tmp_table_item(Session *session)
631
 
{
632
 
  if (!with_sum_func && !const_item() && functype() != SUSERVAR_FUNC)
633
 
    return new Item_field(result_field);
634
 
  return copy_or_same(session);
635
 
}
636
 
 
637
 
 
638
 
} /* namespace drizzled */