Drizzled Public API Documentation

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