~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/function/func.cc

  • Committer: Monty Taylor
  • Date: 2009-10-06 19:37:52 UTC
  • mto: This revision was merged to the branch mainline in revision 1184.
  • Revision ID: mordred@inaugust.com-20091006193752-4dx2c8u35j4em79g
Removed more server_includes.h from headers.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
20
#include <drizzled/server_includes.h>
 
21
 
 
22
#include <drizzled/sql_string.h>
 
23
#include <drizzled/sql_list.h>
 
24
 
 
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
void Item_func::set_arguments(List<Item> &list)
 
39
{
 
40
  allowed_arg_cols= 1;
 
41
  arg_count=list.elements;
 
42
  args= tmp_arg;                                // If 2 arguments
 
43
  if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
 
44
  {
 
45
    List_iterator_fast<Item> li(list);
 
46
    Item *item;
 
47
    Item **save_args= args;
 
48
 
 
49
    while ((item=li++))
 
50
    {
 
51
      *(save_args++)= item;
 
52
      with_sum_func|=item->with_sum_func;
 
53
    }
 
54
  }
 
55
  list.empty();          // Fields are used
 
56
}
 
57
 
 
58
Item_func::Item_func(List<Item> &list)
 
59
  :allowed_arg_cols(1)
 
60
{
 
61
  set_arguments(list);
 
62
}
 
63
 
 
64
Item_func::Item_func(Session *session, Item_func *item)
 
65
  :Item_result_field(session, item),
 
66
   allowed_arg_cols(item->allowed_arg_cols),
 
67
   arg_count(item->arg_count),
 
68
   used_tables_cache(item->used_tables_cache),
 
69
   not_null_tables_cache(item->not_null_tables_cache),
 
70
   const_item_cache(item->const_item_cache)
 
71
{
 
72
  if (arg_count)
 
73
  {
 
74
    if (arg_count <=2)
 
75
      args= tmp_arg;
 
76
    else
 
77
    {
 
78
      if (!(args=(Item**) session->alloc(sizeof(Item*)*arg_count)))
 
79
        return;
 
80
    }
 
81
    memcpy(args, item->args, sizeof(Item*)*arg_count);
 
82
  }
 
83
}
 
84
 
 
85
 
 
86
/*
 
87
  Resolve references to table column for a function and its argument
 
88
 
 
89
  SYNOPSIS:
 
90
  fix_fields()
 
91
  session    Thread object
 
92
  ref    Pointer to where this object is used.  This reference
 
93
  is used if we want to replace this object with another
 
94
  one (for example in the summary functions).
 
95
 
 
96
  DESCRIPTION
 
97
  Call fix_fields() for all arguments to the function.  The main intention
 
98
  is to allow all Item_field() objects to setup pointers to the table fields.
 
99
 
 
100
  Sets as a side effect the following class variables:
 
101
  maybe_null  Set if any argument may return NULL
 
102
  with_sum_func  Set if any of the arguments contains a sum function
 
103
  used_tables_cache Set to union of the tables used by arguments
 
104
 
 
105
  str_value.charset If this is a string function, set this to the
 
106
  character set for the first argument.
 
107
  If any argument is binary, this is set to binary
 
108
 
 
109
  If for any item any of the defaults are wrong, then this can
 
110
  be fixed in the fix_length_and_dec() function that is called
 
111
  after this one or by writing a specialized fix_fields() for the
 
112
  item.
 
113
 
 
114
  RETURN VALUES
 
115
  false  ok
 
116
  true  Got error.  Stored with my_error().
 
117
*/
 
118
 
 
119
bool
 
120
Item_func::fix_fields(Session *session, Item **)
 
121
{
 
122
  assert(fixed == 0);
 
123
  Item **arg,**arg_end;
 
124
  void *save_session_marker= session->session_marker;
 
125
  unsigned char buff[STACK_BUFF_ALLOC];      // Max argument in function
 
126
  session->session_marker= 0;
 
127
  used_tables_cache= not_null_tables_cache= 0;
 
128
  const_item_cache=1;
 
129
 
 
130
  if (check_stack_overrun(session, STACK_MIN_SIZE, buff))
 
131
    return true;        // Fatal error if flag is set!
 
132
  if (arg_count)
 
133
  {            // Print purify happy
 
134
    for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
 
135
    {
 
136
      Item *item;
 
137
      /*
 
138
        We can't yet set item to *arg as fix_fields may change *arg
 
139
        We shouldn't call fix_fields() twice, so check 'fixed' field first
 
140
      */
 
141
      if ((!(*arg)->fixed && (*arg)->fix_fields(session, arg)))
 
142
        return true;
 
143
      item= *arg;
 
144
 
 
145
      if (allowed_arg_cols)
 
146
      {
 
147
        if (item->check_cols(allowed_arg_cols))
 
148
          return 1;
 
149
      }
 
150
      else
 
151
      {
 
152
        /*  we have to fetch allowed_arg_cols from first argument */
 
153
        assert(arg == args); // it is first argument
 
154
        allowed_arg_cols= item->cols();
 
155
        assert(allowed_arg_cols); // Can't be 0 any more
 
156
      }
 
157
 
 
158
      if (item->maybe_null)
 
159
        maybe_null=1;
 
160
 
 
161
      with_sum_func= with_sum_func || item->with_sum_func;
 
162
      used_tables_cache|=     item->used_tables();
 
163
      not_null_tables_cache|= item->not_null_tables();
 
164
      const_item_cache&=      item->const_item();
 
165
      with_subselect|=        item->with_subselect;
 
166
    }
 
167
  }
 
168
  fix_length_and_dec();
 
169
  if (session->is_error()) // An error inside fix_length_and_dec occured
 
170
    return true;
 
171
  fixed= 1;
 
172
  session->session_marker= save_session_marker;
 
173
  return false;
 
174
}
 
175
 
 
176
 
 
177
void Item_func::fix_after_pullout(Select_Lex *new_parent,
 
178
                                  Item **)
 
179
{
 
180
  Item **arg,**arg_end;
 
181
 
 
182
  used_tables_cache= not_null_tables_cache= 0;
 
183
  const_item_cache=1;
 
184
 
 
185
  if (arg_count)
 
186
  {
 
187
    for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
 
188
    {
 
189
      (*arg)->fix_after_pullout(new_parent, arg);
 
190
      Item *item= *arg;
 
191
 
 
192
      used_tables_cache|=     item->used_tables();
 
193
      not_null_tables_cache|= item->not_null_tables();
 
194
      const_item_cache&=      item->const_item();
 
195
    }
 
196
  }
 
197
}
 
198
 
 
199
 
 
200
bool Item_func::walk(Item_processor processor, bool walk_subquery,
 
201
                     unsigned char *argument)
 
202
{
 
203
  if (arg_count)
 
204
  {
 
205
    Item **arg,**arg_end;
 
206
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
 
207
    {
 
208
      if ((*arg)->walk(processor, walk_subquery, argument))
 
209
        return 1;
 
210
    }
 
211
  }
 
212
  return (this->*processor)(argument);
 
213
}
 
214
 
 
215
void Item_func::traverse_cond(Cond_traverser traverser,
 
216
                              void *argument, traverse_order order)
 
217
{
 
218
  if (arg_count)
 
219
  {
 
220
    Item **arg,**arg_end;
 
221
 
 
222
    switch (order) {
 
223
    case (T_PREFIX):
 
224
      (*traverser)(this, argument);
 
225
      for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
 
226
      {
 
227
        (*arg)->traverse_cond(traverser, argument, order);
 
228
      }
 
229
      break;
 
230
    case (T_POSTFIX):
 
231
      for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
 
232
      {
 
233
        (*arg)->traverse_cond(traverser, argument, order);
 
234
      }
 
235
      (*traverser)(this, argument);
 
236
    }
 
237
  }
 
238
  else
 
239
    (*traverser)(this, argument);
 
240
}
 
241
 
 
242
 
 
243
/**
 
244
   Transform an Item_func object with a transformer callback function.
 
245
 
 
246
   The function recursively applies the transform method to each
 
247
   argument of the Item_func node.
 
248
   If the call of the method for an argument item returns a new item
 
249
   the old item is substituted for a new one.
 
250
   After this the transformer is applied to the root node
 
251
   of the Item_func object.
 
252
   @param transformer   the transformer callback function to be applied to
 
253
   the nodes of the tree of the object
 
254
   @param argument      parameter to be passed to the transformer
 
255
 
 
256
   @return
 
257
   Item returned as the result of transformation of the root node
 
258
*/
 
259
 
 
260
Item *Item_func::transform(Item_transformer transformer, unsigned char *argument)
 
261
{
 
262
  if (arg_count)
 
263
  {
 
264
    Item **arg,**arg_end;
 
265
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
 
266
    {
 
267
      Item *new_item= (*arg)->transform(transformer, argument);
 
268
      if (!new_item)
 
269
        return 0;
 
270
 
 
271
      /*
 
272
        Session::change_item_tree() should be called only if the tree was
 
273
        really transformed, i.e. when a new item has been created.
 
274
        Otherwise we'll be allocating a lot of unnecessary memory for
 
275
        change records at each execution.
 
276
      */
 
277
      if (*arg != new_item)
 
278
        current_session->change_item_tree(arg, new_item);
 
279
    }
 
280
  }
 
281
  return (this->*transformer)(argument);
 
282
}
 
283
 
 
284
 
 
285
/**
 
286
   Compile Item_func object with a processor and a transformer
 
287
   callback functions.
 
288
 
 
289
   First the function applies the analyzer to the root node of
 
290
   the Item_func object. Then if the analizer succeeeds (returns true)
 
291
   the function recursively applies the compile method to each argument
 
292
   of the Item_func node.
 
293
   If the call of the method for an argument item returns a new item
 
294
   the old item is substituted for a new one.
 
295
   After this the transformer is applied to the root node
 
296
   of the Item_func object.
 
297
 
 
298
   @param analyzer      the analyzer callback function to be applied to the
 
299
   nodes of the tree of the object
 
300
   @param[in,out] arg_p parameter to be passed to the processor
 
301
   @param transformer   the transformer callback function to be applied to the
 
302
   nodes of the tree of the object
 
303
   @param arg_t         parameter to be passed to the transformer
 
304
 
 
305
   @return
 
306
   Item returned as the result of transformation of the root node
 
307
*/
 
308
 
 
309
Item *Item_func::compile(Item_analyzer analyzer, unsigned char **arg_p,
 
310
                         Item_transformer transformer, unsigned char *arg_t)
 
311
{
 
312
  if (!(this->*analyzer)(arg_p))
 
313
    return 0;
 
314
  if (arg_count)
 
315
  {
 
316
    Item **arg,**arg_end;
 
317
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
 
318
    {
 
319
      /*
 
320
        The same parameter value of arg_p must be passed
 
321
        to analyze any argument of the condition formula.
 
322
      */
 
323
      unsigned char *arg_v= *arg_p;
 
324
      Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
 
325
      if (new_item && *arg != new_item)
 
326
        current_session->change_item_tree(arg, new_item);
 
327
    }
 
328
  }
 
329
  return (this->*transformer)(arg_t);
 
330
}
 
331
 
 
332
/**
 
333
   See comments in Item_cmp_func::split_sum_func()
 
334
*/
 
335
 
 
336
void Item_func::split_sum_func(Session *session, Item **ref_pointer_array,
 
337
                               List<Item> &fields)
 
338
{
 
339
  Item **arg, **arg_end;
 
340
  for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
 
341
    (*arg)->split_sum_func(session, ref_pointer_array, fields, arg, true);
 
342
}
 
343
 
 
344
 
 
345
void Item_func::update_used_tables()
 
346
{
 
347
  used_tables_cache=0;
 
348
  const_item_cache=1;
 
349
  for (uint32_t i=0 ; i < arg_count ; i++)
 
350
  {
 
351
    args[i]->update_used_tables();
 
352
    used_tables_cache|=args[i]->used_tables();
 
353
    const_item_cache&=args[i]->const_item();
 
354
  }
 
355
}
 
356
 
 
357
 
 
358
table_map Item_func::used_tables() const
 
359
{
 
360
  return used_tables_cache;
 
361
}
 
362
 
 
363
 
 
364
table_map Item_func::not_null_tables() const
 
365
{
 
366
  return not_null_tables_cache;
 
367
}
 
368
 
 
369
 
 
370
void Item_func::print(String *str, enum_query_type query_type)
 
371
{
 
372
  str->append(func_name());
 
373
  str->append('(');
 
374
  print_args(str, 0, query_type);
 
375
  str->append(')');
 
376
}
 
377
 
 
378
 
 
379
void Item_func::print_args(String *str, uint32_t from, enum_query_type query_type)
 
380
{
 
381
  for (uint32_t i=from ; i < arg_count ; i++)
 
382
  {
 
383
    if (i != from)
 
384
      str->append(',');
 
385
    args[i]->print(str, query_type);
 
386
  }
 
387
}
 
388
 
 
389
 
 
390
void Item_func::print_op(String *str, enum_query_type query_type)
 
391
{
 
392
  str->append('(');
 
393
  for (uint32_t i=0 ; i < arg_count-1 ; i++)
 
394
  {
 
395
    args[i]->print(str, query_type);
 
396
    str->append(' ');
 
397
    str->append(func_name());
 
398
    str->append(' ');
 
399
  }
 
400
  args[arg_count-1]->print(str, query_type);
 
401
  str->append(')');
 
402
}
 
403
 
 
404
 
 
405
bool Item_func::eq(const Item *item, bool binary_cmp) const
 
406
{
 
407
  /* Assume we don't have rtti */
 
408
  if (this == item)
 
409
    return 1;
 
410
  if (item->type() != FUNC_ITEM)
 
411
    return 0;
 
412
  Item_func *item_func=(Item_func*) item;
 
413
  Item_func::Functype func_type;
 
414
  if ((func_type= functype()) != item_func->functype() ||
 
415
      arg_count != item_func->arg_count ||
 
416
      (func_type != Item_func::FUNC_SP &&
 
417
       func_name() != item_func->func_name()) ||
 
418
      (func_type == Item_func::FUNC_SP &&
 
419
       my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
 
420
    return 0;
 
421
  for (uint32_t i=0; i < arg_count ; i++)
 
422
    if (!args[i]->eq(item_func->args[i], binary_cmp))
 
423
      return 0;
 
424
  return 1;
 
425
}
 
426
 
 
427
 
 
428
bool Item_func::get_arg0_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
 
429
{
 
430
  return (null_value=args[0]->get_date(ltime, fuzzy_date));
 
431
}
 
432
 
 
433
 
 
434
bool Item_func::get_arg0_time(DRIZZLE_TIME *ltime)
 
435
{
 
436
  return (null_value=args[0]->get_time(ltime));
 
437
}
 
438
 
 
439
 
 
440
bool Item_func::is_null()
 
441
{
 
442
  update_null_value();
 
443
  return null_value;
 
444
}
 
445
 
 
446
 
 
447
Field *Item_func::tmp_table_field(Table *table)
 
448
{
 
449
  Field *field;
 
450
 
 
451
  switch (result_type()) {
 
452
  case INT_RESULT:
 
453
    if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
 
454
      field= new Field_int64_t(max_length, maybe_null, name, unsigned_flag);
 
455
    else
 
456
      field= new Field_long(max_length, maybe_null, name, unsigned_flag);
 
457
    break;
 
458
  case REAL_RESULT:
 
459
    field= new Field_double(max_length, maybe_null, name, decimals);
 
460
    break;
 
461
  case STRING_RESULT:
 
462
    return make_string_field(table);
 
463
  case DECIMAL_RESULT:
 
464
    field= new Field_new_decimal(my_decimal_precision_to_length(decimal_precision(),
 
465
                                                                decimals,
 
466
                                                                unsigned_flag),
 
467
                                 maybe_null,
 
468
                                 name,
 
469
                                 decimals,
 
470
                                 unsigned_flag);
 
471
    break;
 
472
  case ROW_RESULT:
 
473
  default:
 
474
    // This case should never be chosen
 
475
    assert(0);
 
476
    field= 0;
 
477
    break;
 
478
  }
 
479
  if (field)
 
480
    field->init(table);
 
481
  return field;
 
482
}
 
483
 
 
484
 
 
485
my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
 
486
{
 
487
  assert(fixed);
 
488
  int2my_decimal(E_DEC_FATAL_ERROR, val_int(), unsigned_flag, decimal_value);
 
489
  return decimal_value;
 
490
}
 
491
 
 
492
 
 
493
bool Item_func::agg_arg_collations(DTCollation &c, Item **items,
 
494
                                   uint32_t nitems, uint32_t flags)
 
495
{
 
496
  return agg_item_collations(c, func_name(), items, nitems, flags, 1);
 
497
}
 
498
 
 
499
 
 
500
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
 
501
                                                  Item **items,
 
502
                                                  uint32_t nitems,
 
503
                                                  uint32_t flags)
 
504
{
 
505
  return agg_item_collations_for_comparison(c, func_name(),
 
506
                                            items, nitems, flags);
 
507
}
 
508
 
 
509
 
 
510
bool Item_func::agg_arg_charsets(DTCollation &c, Item **items, uint32_t nitems,
 
511
                                 uint32_t flags, int item_sep)
 
512
{
 
513
  return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep);
 
514
}
 
515
 
 
516
 
 
517
double Item_func::fix_result(double value)
 
518
{
 
519
  static double fix_infinity= numeric_limits<double>::infinity();
 
520
 
 
521
  if (value != fix_infinity && value != -fix_infinity)
 
522
    return value;
 
523
  null_value=1;
 
524
  return 0.0;
 
525
}
 
526
 
 
527
 
 
528
void Item_func::fix_num_length_and_dec()
 
529
{
 
530
  uint32_t fl_length= 0;
 
531
  decimals=0;
 
532
  for (uint32_t i=0 ; i < arg_count ; i++)
 
533
  {
 
534
    set_if_bigger(decimals,args[i]->decimals);
 
535
    set_if_bigger(fl_length, args[i]->max_length);
 
536
  }
 
537
  max_length=float_length(decimals);
 
538
  if (fl_length > max_length)
 
539
  {
 
540
    decimals= NOT_FIXED_DEC;
 
541
    max_length= float_length(NOT_FIXED_DEC);
 
542
  }
 
543
}
 
544
 
 
545
/**
 
546
  Set max_length/decimals of function if function is fixed point and
 
547
  result length/precision depends on argument ones.
 
548
*/
 
549
 
 
550
void Item_func::count_decimal_length()
 
551
{
 
552
  int max_int_part= 0;
 
553
  decimals= 0;
 
554
  unsigned_flag= 1;
 
555
  for (uint32_t i= 0 ; i < arg_count ; i++)
 
556
  {
 
557
    set_if_bigger(decimals, args[i]->decimals);
 
558
    set_if_bigger(max_int_part, args[i]->decimal_int_part());
 
559
    set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
 
560
  }
 
561
  int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
 
562
  max_length= my_decimal_precision_to_length(precision, decimals,
 
563
                                             unsigned_flag);
 
564
}
 
565
 
 
566
 
 
567
/**
 
568
  Set max_length of if it is maximum length of its arguments.
 
569
*/
 
570
 
 
571
void Item_func::count_only_length()
 
572
{
 
573
  max_length= 0;
 
574
  unsigned_flag= 0;
 
575
  for (uint32_t i=0 ; i < arg_count ; i++)
 
576
  {
 
577
    set_if_bigger(max_length, args[i]->max_length);
 
578
    set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
 
579
  }
 
580
}
 
581
 
 
582
 
 
583
/**
 
584
  Set max_length/decimals of function if function is floating point and
 
585
  result length/precision depends on argument ones.
 
586
*/
 
587
 
 
588
void Item_func::count_real_length()
 
589
{
 
590
  uint32_t length= 0;
 
591
  decimals= 0;
 
592
  max_length= 0;
 
593
  for (uint32_t i=0 ; i < arg_count ; i++)
 
594
  {
 
595
    if (decimals != NOT_FIXED_DEC)
 
596
    {
 
597
      set_if_bigger(decimals, args[i]->decimals);
 
598
      set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
 
599
    }
 
600
    set_if_bigger(max_length, args[i]->max_length);
 
601
  }
 
602
  if (decimals != NOT_FIXED_DEC)
 
603
  {
 
604
    max_length= length;
 
605
    length+= decimals;
 
606
    if (length < max_length)  // If previous operation gave overflow
 
607
      max_length= UINT32_MAX;
 
608
    else
 
609
      max_length= length;
 
610
  }
 
611
}
 
612
 
 
613
 
 
614
 
 
615
void Item_func::signal_divide_by_null()
 
616
{
 
617
  Session *session= current_session;
 
618
  push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
 
619
  null_value= 1;
 
620
}
 
621
 
 
622
 
 
623
Item *Item_func::get_tmp_table_item(Session *session)
 
624
{
 
625
  if (!with_sum_func && !const_item() && functype() != SUSERVAR_FUNC)
 
626
    return new Item_field(result_field);
 
627
  return copy_or_same(session);
 
628
}
 
629
 
 
630