~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to drizzled/function/func.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

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