~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/function/func.cc

  • Committer: Andy Lester
  • Date: 2008-08-09 05:23:39 UTC
  • mto: (266.1.29 use-replace-funcs)
  • mto: This revision was merged to the branch mainline in revision 287.
  • Revision ID: andy@petdance.com-20080809052339-iafoesszmesweq6b
use NULL, not 0

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