~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/function/func.cc

Moved the last of the libdrizzleclient calls into Protocol.

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