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
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>
42
void Item_func::set_arguments(List<Item> &list)
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)))
49
List_iterator_fast<Item> li(list);
51
Item **save_args= args;
56
with_sum_func|=item->with_sum_func;
59
list.empty(); // Fields are used
62
Item_func::Item_func(List<Item> &list)
68
Item_func::Item_func(Session *session, Item_func *item)
69
:Item_result_field(session, item),
70
allowed_arg_cols(item->allowed_arg_cols),
71
arg_count(item->arg_count),
72
used_tables_cache(item->used_tables_cache),
73
not_null_tables_cache(item->not_null_tables_cache),
74
const_item_cache(item->const_item_cache)
82
if (!(args=(Item**) session->alloc(sizeof(Item*)*arg_count)))
85
memcpy(args, item->args, sizeof(Item*)*arg_count);
91
Resolve references to table column for a function and its argument
96
ref Pointer to where this object is used. This reference
97
is used if we want to replace this object with another
98
one (for example in the summary functions).
101
Call fix_fields() for all arguments to the function. The main intention
102
is to allow all Item_field() objects to setup pointers to the table fields.
104
Sets as a side effect the following class variables:
105
maybe_null Set if any argument may return NULL
106
with_sum_func Set if any of the arguments contains a sum function
107
used_tables_cache Set to union of the tables used by arguments
109
str_value.charset If this is a string function, set this to the
110
character set for the first argument.
111
If any argument is binary, this is set to binary
113
If for any item any of the defaults are wrong, then this can
114
be fixed in the fix_length_and_dec() function that is called
115
after this one or by writing a specialized fix_fields() for the
120
true Got error. Stored with my_error().
124
Item_func::fix_fields(Session *session, Item **)
127
Item **arg,**arg_end;
128
void *save_session_marker= session->session_marker;
129
unsigned char buff[STACK_BUFF_ALLOC]; // Max argument in function
130
session->session_marker= 0;
131
used_tables_cache= not_null_tables_cache= 0;
134
if (check_stack_overrun(session, STACK_MIN_SIZE, buff))
135
return true; // Fatal error if flag is set!
137
{ // Print purify happy
138
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
142
We can't yet set item to *arg as fix_fields may change *arg
143
We shouldn't call fix_fields() twice, so check 'fixed' field first
145
if ((!(*arg)->fixed && (*arg)->fix_fields(session, arg)))
149
if (allowed_arg_cols)
151
if (item->check_cols(allowed_arg_cols))
156
/* we have to fetch allowed_arg_cols from first argument */
157
assert(arg == args); // it is first argument
158
allowed_arg_cols= item->cols();
159
assert(allowed_arg_cols); // Can't be 0 any more
162
if (item->maybe_null)
165
with_sum_func= with_sum_func || item->with_sum_func;
166
used_tables_cache|= item->used_tables();
167
not_null_tables_cache|= item->not_null_tables();
168
const_item_cache&= item->const_item();
169
with_subselect|= item->with_subselect;
172
fix_length_and_dec();
173
if (session->is_error()) // An error inside fix_length_and_dec occured
176
session->session_marker= save_session_marker;
181
void Item_func::fix_after_pullout(Select_Lex *new_parent,
184
Item **arg,**arg_end;
186
used_tables_cache= not_null_tables_cache= 0;
191
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
193
(*arg)->fix_after_pullout(new_parent, arg);
196
used_tables_cache|= item->used_tables();
197
not_null_tables_cache|= item->not_null_tables();
198
const_item_cache&= item->const_item();
204
bool Item_func::walk(Item_processor processor, bool walk_subquery,
205
unsigned char *argument)
209
Item **arg,**arg_end;
210
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
212
if ((*arg)->walk(processor, walk_subquery, argument))
216
return (this->*processor)(argument);
219
void Item_func::traverse_cond(Cond_traverser traverser,
220
void *argument, traverse_order order)
224
Item **arg,**arg_end;
228
(*traverser)(this, argument);
229
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
231
(*arg)->traverse_cond(traverser, argument, order);
235
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
237
(*arg)->traverse_cond(traverser, argument, order);
239
(*traverser)(this, argument);
243
(*traverser)(this, argument);
248
Transform an Item_func object with a transformer callback function.
250
The function recursively applies the transform method to each
251
argument of the Item_func node.
252
If the call of the method for an argument item returns a new item
253
the old item is substituted for a new one.
254
After this the transformer is applied to the root node
255
of the Item_func object.
256
@param transformer the transformer callback function to be applied to
257
the nodes of the tree of the object
258
@param argument parameter to be passed to the transformer
261
Item returned as the result of transformation of the root node
264
Item *Item_func::transform(Item_transformer transformer, unsigned char *argument)
268
Item **arg,**arg_end;
269
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
271
Item *new_item= (*arg)->transform(transformer, argument);
276
Session::change_item_tree() should be called only if the tree was
277
really transformed, i.e. when a new item has been created.
278
Otherwise we'll be allocating a lot of unnecessary memory for
279
change records at each execution.
281
if (*arg != new_item)
282
current_session->change_item_tree(arg, new_item);
285
return (this->*transformer)(argument);
290
Compile Item_func object with a processor and a transformer
293
First the function applies the analyzer to the root node of
294
the Item_func object. Then if the analizer succeeeds (returns true)
295
the function recursively applies the compile method to each argument
296
of the Item_func node.
297
If the call of the method for an argument item returns a new item
298
the old item is substituted for a new one.
299
After this the transformer is applied to the root node
300
of the Item_func object.
302
@param analyzer the analyzer callback function to be applied to the
303
nodes of the tree of the object
304
@param[in,out] arg_p parameter to be passed to the processor
305
@param transformer the transformer callback function to be applied to the
306
nodes of the tree of the object
307
@param arg_t parameter to be passed to the transformer
310
Item returned as the result of transformation of the root node
313
Item *Item_func::compile(Item_analyzer analyzer, unsigned char **arg_p,
314
Item_transformer transformer, unsigned char *arg_t)
316
if (!(this->*analyzer)(arg_p))
320
Item **arg,**arg_end;
321
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
324
The same parameter value of arg_p must be passed
325
to analyze any argument of the condition formula.
327
unsigned char *arg_v= *arg_p;
328
Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
329
if (new_item && *arg != new_item)
330
current_session->change_item_tree(arg, new_item);
333
return (this->*transformer)(arg_t);
337
See comments in Item_cmp_func::split_sum_func()
340
void Item_func::split_sum_func(Session *session, Item **ref_pointer_array,
343
Item **arg, **arg_end;
344
for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
345
(*arg)->split_sum_func(session, ref_pointer_array, fields, arg, true);
349
void Item_func::update_used_tables()
353
for (uint32_t i=0 ; i < arg_count ; i++)
355
args[i]->update_used_tables();
356
used_tables_cache|=args[i]->used_tables();
357
const_item_cache&=args[i]->const_item();
362
table_map Item_func::used_tables() const
364
return used_tables_cache;
368
table_map Item_func::not_null_tables() const
370
return not_null_tables_cache;
374
void Item_func::print(String *str, enum_query_type query_type)
376
str->append(func_name());
378
print_args(str, 0, query_type);
383
void Item_func::print_args(String *str, uint32_t from, enum_query_type query_type)
385
for (uint32_t i=from ; i < arg_count ; i++)
389
args[i]->print(str, query_type);
394
void Item_func::print_op(String *str, enum_query_type query_type)
397
for (uint32_t i=0 ; i < arg_count-1 ; i++)
399
args[i]->print(str, query_type);
401
str->append(func_name());
404
args[arg_count-1]->print(str, query_type);
409
bool Item_func::eq(const Item *item, bool binary_cmp) const
411
/* Assume we don't have rtti */
414
if (item->type() != FUNC_ITEM)
416
Item_func *item_func=(Item_func*) item;
417
Item_func::Functype func_type;
418
if ((func_type= functype()) != item_func->functype() ||
419
arg_count != item_func->arg_count ||
420
(func_type != Item_func::FUNC_SP &&
421
func_name() != item_func->func_name()) ||
422
(func_type == Item_func::FUNC_SP &&
423
my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
425
for (uint32_t i=0; i < arg_count ; i++)
426
if (!args[i]->eq(item_func->args[i], binary_cmp))
432
bool Item_func::get_arg0_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
434
return (null_value=args[0]->get_date(ltime, fuzzy_date));
438
bool Item_func::get_arg0_time(DRIZZLE_TIME *ltime)
440
return (null_value=args[0]->get_time(ltime));
444
bool Item_func::is_null()
451
Field *Item_func::tmp_table_field(Table *table)
455
switch (result_type()) {
457
if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
458
field= new Field_int64_t(max_length, maybe_null, name, unsigned_flag);
460
field= new Field_long(max_length, maybe_null, name, unsigned_flag);
463
field= new Field_double(max_length, maybe_null, name, decimals);
466
return make_string_field(table);
468
field= new Field_decimal(my_decimal_precision_to_length(decimal_precision(),
478
// This case should never be chosen
489
my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
492
int2my_decimal(E_DEC_FATAL_ERROR, val_int(), unsigned_flag, decimal_value);
493
return decimal_value;
497
bool Item_func::agg_arg_collations(DTCollation &c, Item **items,
498
uint32_t nitems, uint32_t flags)
500
return agg_item_collations(c, func_name(), items, nitems, flags, 1);
504
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
509
return agg_item_collations_for_comparison(c, func_name(),
510
items, nitems, flags);
514
bool Item_func::agg_arg_charsets(DTCollation &c, Item **items, uint32_t nitems,
515
uint32_t flags, int item_sep)
517
return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep);
521
double Item_func::fix_result(double value)
523
static double fix_infinity= numeric_limits<double>::infinity();
525
if (value != fix_infinity && value != -fix_infinity)
532
void Item_func::fix_num_length_and_dec()
534
uint32_t fl_length= 0;
536
for (uint32_t i=0 ; i < arg_count ; i++)
538
set_if_bigger(decimals,args[i]->decimals);
539
set_if_bigger(fl_length, args[i]->max_length);
541
max_length=float_length(decimals);
542
if (fl_length > max_length)
544
decimals= NOT_FIXED_DEC;
545
max_length= float_length(NOT_FIXED_DEC);
550
Set max_length/decimals of function if function is fixed point and
551
result length/precision depends on argument ones.
554
void Item_func::count_decimal_length()
559
for (uint32_t i= 0 ; i < arg_count ; i++)
561
set_if_bigger(decimals, args[i]->decimals);
562
set_if_bigger(max_int_part, args[i]->decimal_int_part());
563
set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
565
int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
566
max_length= my_decimal_precision_to_length(precision, decimals,
572
Set max_length of if it is maximum length of its arguments.
575
void Item_func::count_only_length()
579
for (uint32_t i=0 ; i < arg_count ; i++)
581
set_if_bigger(max_length, args[i]->max_length);
582
set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
588
Set max_length/decimals of function if function is floating point and
589
result length/precision depends on argument ones.
592
void Item_func::count_real_length()
597
for (uint32_t i=0 ; i < arg_count ; i++)
599
if (decimals != NOT_FIXED_DEC)
601
set_if_bigger(decimals, args[i]->decimals);
602
set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
604
set_if_bigger(max_length, args[i]->max_length);
606
if (decimals != NOT_FIXED_DEC)
610
if (length < max_length) // If previous operation gave overflow
611
max_length= UINT32_MAX;
619
void Item_func::signal_divide_by_null()
621
Session *session= current_session;
622
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
627
Item *Item_func::get_tmp_table_item(Session *session)
629
if (!with_sum_func && !const_item() && functype() != SUSERVAR_FUNC)
630
return new Item_field(result_field);
631
return copy_or_same(session);
635
} /* namespace drizzled */