~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/function/func.cc

  • Committer: Mark Atwood
  • Date: 2008-10-03 01:39:40 UTC
  • mto: This revision was merged to the branch mainline in revision 437.
  • Revision ID: mark@fallenpegasus.com-20081003013940-mvefjo725dltz41h
rename logging_noop to logging_query

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