1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
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.
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.
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
20
#include <drizzled/server_includes.h>
22
#include <drizzled/sql_string.h>
23
#include <drizzled/sql_list.h>
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>
38
void Item_func::set_arguments(List<Item> &list)
41
arg_count=list.elements;
42
args= tmp_arg; // If 2 arguments
43
if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
45
List_iterator_fast<Item> li(list);
47
Item **save_args= args;
52
with_sum_func|=item->with_sum_func;
55
list.empty(); // Fields are used
58
Item_func::Item_func(List<Item> &list)
64
Item_func::Item_func(Session *session, Item_func *item)
65
:Item_result_field(session, item),
66
allowed_arg_cols(item->allowed_arg_cols),
67
arg_count(item->arg_count),
68
used_tables_cache(item->used_tables_cache),
69
not_null_tables_cache(item->not_null_tables_cache),
70
const_item_cache(item->const_item_cache)
78
if (!(args=(Item**) session->alloc(sizeof(Item*)*arg_count)))
81
memcpy(args, item->args, sizeof(Item*)*arg_count);
87
Resolve references to table column for a function and its argument
92
ref Pointer to where this object is used. This reference
93
is used if we want to replace this object with another
94
one (for example in the summary functions).
97
Call fix_fields() for all arguments to the function. The main intention
98
is to allow all Item_field() objects to setup pointers to the table fields.
100
Sets as a side effect the following class variables:
101
maybe_null Set if any argument may return NULL
102
with_sum_func Set if any of the arguments contains a sum function
103
used_tables_cache Set to union of the tables used by arguments
105
str_value.charset If this is a string function, set this to the
106
character set for the first argument.
107
If any argument is binary, this is set to binary
109
If for any item any of the defaults are wrong, then this can
110
be fixed in the fix_length_and_dec() function that is called
111
after this one or by writing a specialized fix_fields() for the
116
true Got error. Stored with my_error().
120
Item_func::fix_fields(Session *session, Item **)
123
Item **arg,**arg_end;
124
void *save_session_marker= session->session_marker;
125
unsigned char buff[STACK_BUFF_ALLOC]; // Max argument in function
126
session->session_marker= 0;
127
used_tables_cache= not_null_tables_cache= 0;
130
if (check_stack_overrun(session, STACK_MIN_SIZE, buff))
131
return true; // Fatal error if flag is set!
133
{ // Print purify happy
134
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
138
We can't yet set item to *arg as fix_fields may change *arg
139
We shouldn't call fix_fields() twice, so check 'fixed' field first
141
if ((!(*arg)->fixed && (*arg)->fix_fields(session, arg)))
145
if (allowed_arg_cols)
147
if (item->check_cols(allowed_arg_cols))
152
/* we have to fetch allowed_arg_cols from first argument */
153
assert(arg == args); // it is first argument
154
allowed_arg_cols= item->cols();
155
assert(allowed_arg_cols); // Can't be 0 any more
158
if (item->maybe_null)
161
with_sum_func= with_sum_func || item->with_sum_func;
162
used_tables_cache|= item->used_tables();
163
not_null_tables_cache|= item->not_null_tables();
164
const_item_cache&= item->const_item();
165
with_subselect|= item->with_subselect;
168
fix_length_and_dec();
169
if (session->is_error()) // An error inside fix_length_and_dec occured
172
session->session_marker= save_session_marker;
177
void Item_func::fix_after_pullout(Select_Lex *new_parent,
180
Item **arg,**arg_end;
182
used_tables_cache= not_null_tables_cache= 0;
187
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
189
(*arg)->fix_after_pullout(new_parent, arg);
192
used_tables_cache|= item->used_tables();
193
not_null_tables_cache|= item->not_null_tables();
194
const_item_cache&= item->const_item();
200
bool Item_func::walk(Item_processor processor, bool walk_subquery,
201
unsigned char *argument)
205
Item **arg,**arg_end;
206
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
208
if ((*arg)->walk(processor, walk_subquery, argument))
212
return (this->*processor)(argument);
215
void Item_func::traverse_cond(Cond_traverser traverser,
216
void *argument, traverse_order order)
220
Item **arg,**arg_end;
224
(*traverser)(this, argument);
225
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
227
(*arg)->traverse_cond(traverser, argument, order);
231
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
233
(*arg)->traverse_cond(traverser, argument, order);
235
(*traverser)(this, argument);
239
(*traverser)(this, argument);
244
Transform an Item_func object with a transformer callback function.
246
The function recursively applies the transform method to each
247
argument of the Item_func node.
248
If the call of the method for an argument item returns a new item
249
the old item is substituted for a new one.
250
After this the transformer is applied to the root node
251
of the Item_func object.
252
@param transformer the transformer callback function to be applied to
253
the nodes of the tree of the object
254
@param argument parameter to be passed to the transformer
257
Item returned as the result of transformation of the root node
260
Item *Item_func::transform(Item_transformer transformer, unsigned char *argument)
264
Item **arg,**arg_end;
265
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
267
Item *new_item= (*arg)->transform(transformer, argument);
272
Session::change_item_tree() should be called only if the tree was
273
really transformed, i.e. when a new item has been created.
274
Otherwise we'll be allocating a lot of unnecessary memory for
275
change records at each execution.
277
if (*arg != new_item)
278
current_session->change_item_tree(arg, new_item);
281
return (this->*transformer)(argument);
286
Compile Item_func object with a processor and a transformer
289
First the function applies the analyzer to the root node of
290
the Item_func object. Then if the analizer succeeeds (returns true)
291
the function recursively applies the compile method to each argument
292
of the Item_func node.
293
If the call of the method for an argument item returns a new item
294
the old item is substituted for a new one.
295
After this the transformer is applied to the root node
296
of the Item_func object.
298
@param analyzer the analyzer callback function to be applied to the
299
nodes of the tree of the object
300
@param[in,out] arg_p parameter to be passed to the processor
301
@param transformer the transformer callback function to be applied to the
302
nodes of the tree of the object
303
@param arg_t parameter to be passed to the transformer
306
Item returned as the result of transformation of the root node
309
Item *Item_func::compile(Item_analyzer analyzer, unsigned char **arg_p,
310
Item_transformer transformer, unsigned char *arg_t)
312
if (!(this->*analyzer)(arg_p))
316
Item **arg,**arg_end;
317
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
320
The same parameter value of arg_p must be passed
321
to analyze any argument of the condition formula.
323
unsigned char *arg_v= *arg_p;
324
Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
325
if (new_item && *arg != new_item)
326
current_session->change_item_tree(arg, new_item);
329
return (this->*transformer)(arg_t);
333
See comments in Item_cmp_func::split_sum_func()
336
void Item_func::split_sum_func(Session *session, Item **ref_pointer_array,
339
Item **arg, **arg_end;
340
for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
341
(*arg)->split_sum_func(session, ref_pointer_array, fields, arg, true);
345
void Item_func::update_used_tables()
349
for (uint32_t i=0 ; i < arg_count ; i++)
351
args[i]->update_used_tables();
352
used_tables_cache|=args[i]->used_tables();
353
const_item_cache&=args[i]->const_item();
358
table_map Item_func::used_tables() const
360
return used_tables_cache;
364
table_map Item_func::not_null_tables() const
366
return not_null_tables_cache;
370
void Item_func::print(String *str, enum_query_type query_type)
372
str->append(func_name());
374
print_args(str, 0, query_type);
379
void Item_func::print_args(String *str, uint32_t from, enum_query_type query_type)
381
for (uint32_t i=from ; i < arg_count ; i++)
385
args[i]->print(str, query_type);
390
void Item_func::print_op(String *str, enum_query_type query_type)
393
for (uint32_t i=0 ; i < arg_count-1 ; i++)
395
args[i]->print(str, query_type);
397
str->append(func_name());
400
args[arg_count-1]->print(str, query_type);
405
bool Item_func::eq(const Item *item, bool binary_cmp) const
407
/* Assume we don't have rtti */
410
if (item->type() != FUNC_ITEM)
412
Item_func *item_func=(Item_func*) item;
413
Item_func::Functype func_type;
414
if ((func_type= functype()) != item_func->functype() ||
415
arg_count != item_func->arg_count ||
416
(func_type != Item_func::FUNC_SP &&
417
func_name() != item_func->func_name()) ||
418
(func_type == Item_func::FUNC_SP &&
419
my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
421
for (uint32_t i=0; i < arg_count ; i++)
422
if (!args[i]->eq(item_func->args[i], binary_cmp))
428
bool Item_func::get_arg0_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
430
return (null_value=args[0]->get_date(ltime, fuzzy_date));
434
bool Item_func::get_arg0_time(DRIZZLE_TIME *ltime)
436
return (null_value=args[0]->get_time(ltime));
440
bool Item_func::is_null()
447
Field *Item_func::tmp_table_field(Table *table)
451
switch (result_type()) {
453
if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
454
field= new Field_int64_t(max_length, maybe_null, name, unsigned_flag);
456
field= new Field_long(max_length, maybe_null, name, unsigned_flag);
459
field= new Field_double(max_length, maybe_null, name, decimals);
462
return make_string_field(table);
464
field= new Field_new_decimal(my_decimal_precision_to_length(decimal_precision(),
474
// This case should never be chosen
485
my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
488
int2my_decimal(E_DEC_FATAL_ERROR, val_int(), unsigned_flag, decimal_value);
489
return decimal_value;
493
bool Item_func::agg_arg_collations(DTCollation &c, Item **items,
494
uint32_t nitems, uint32_t flags)
496
return agg_item_collations(c, func_name(), items, nitems, flags, 1);
500
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
505
return agg_item_collations_for_comparison(c, func_name(),
506
items, nitems, flags);
510
bool Item_func::agg_arg_charsets(DTCollation &c, Item **items, uint32_t nitems,
511
uint32_t flags, int item_sep)
513
return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep);
517
double Item_func::fix_result(double value)
519
static double fix_infinity= numeric_limits<double>::infinity();
521
if (value != fix_infinity && value != -fix_infinity)
528
void Item_func::fix_num_length_and_dec()
530
uint32_t fl_length= 0;
532
for (uint32_t i=0 ; i < arg_count ; i++)
534
set_if_bigger(decimals,args[i]->decimals);
535
set_if_bigger(fl_length, args[i]->max_length);
537
max_length=float_length(decimals);
538
if (fl_length > max_length)
540
decimals= NOT_FIXED_DEC;
541
max_length= float_length(NOT_FIXED_DEC);
546
Set max_length/decimals of function if function is fixed point and
547
result length/precision depends on argument ones.
550
void Item_func::count_decimal_length()
555
for (uint32_t i= 0 ; i < arg_count ; i++)
557
set_if_bigger(decimals, args[i]->decimals);
558
set_if_bigger(max_int_part, args[i]->decimal_int_part());
559
set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
561
int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
562
max_length= my_decimal_precision_to_length(precision, decimals,
568
Set max_length of if it is maximum length of its arguments.
571
void Item_func::count_only_length()
575
for (uint32_t i=0 ; i < arg_count ; i++)
577
set_if_bigger(max_length, args[i]->max_length);
578
set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
584
Set max_length/decimals of function if function is floating point and
585
result length/precision depends on argument ones.
588
void Item_func::count_real_length()
593
for (uint32_t i=0 ; i < arg_count ; i++)
595
if (decimals != NOT_FIXED_DEC)
597
set_if_bigger(decimals, args[i]->decimals);
598
set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
600
set_if_bigger(max_length, args[i]->max_length);
602
if (decimals != NOT_FIXED_DEC)
606
if (length < max_length) // If previous operation gave overflow
607
max_length= UINT32_MAX;
615
void Item_func::signal_divide_by_null()
617
Session *session= current_session;
618
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
623
Item *Item_func::get_tmp_table_item(Session *session)
625
if (!with_sum_func && !const_item() && functype() != SUSERVAR_FUNC)
626
return new Item_field(result_field);
627
return copy_or_same(session);