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>
37
void Item_func::set_arguments(List<Item> &list)
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)))
44
List_iterator_fast<Item> li(list);
46
Item **save_args= args;
51
with_sum_func|=item->with_sum_func;
54
list.empty(); // Fields are used
57
Item_func::Item_func(List<Item> &list)
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)
77
if (!(args=(Item**) session->alloc(sizeof(Item*)*arg_count)))
80
memcpy(args, item->args, sizeof(Item*)*arg_count);
86
Resolve references to table column for a function and its argument
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).
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.
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
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
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
115
true Got error. Stored with my_error().
119
Item_func::fix_fields(Session *session, Item **)
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;
129
if (check_stack_overrun(session, STACK_MIN_SIZE, buff))
130
return true; // Fatal error if flag is set!
132
{ // Print purify happy
133
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
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
140
if ((!(*arg)->fixed && (*arg)->fix_fields(session, arg)))
141
return true; /* purecov: inspected */
144
if (allowed_arg_cols)
146
if (item->check_cols(allowed_arg_cols))
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
157
if (item->maybe_null)
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;
167
fix_length_and_dec();
168
if (session->is_error()) // An error inside fix_length_and_dec occured
171
session->session_marker= save_session_marker;
176
void Item_func::fix_after_pullout(Select_Lex *new_parent,
179
Item **arg,**arg_end;
181
used_tables_cache= not_null_tables_cache= 0;
186
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
188
(*arg)->fix_after_pullout(new_parent, arg);
191
used_tables_cache|= item->used_tables();
192
not_null_tables_cache|= item->not_null_tables();
193
const_item_cache&= item->const_item();
199
bool Item_func::walk(Item_processor processor, bool walk_subquery,
200
unsigned char *argument)
204
Item **arg,**arg_end;
205
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
207
if ((*arg)->walk(processor, walk_subquery, argument))
211
return (this->*processor)(argument);
214
void Item_func::traverse_cond(Cond_traverser traverser,
215
void *argument, traverse_order order)
219
Item **arg,**arg_end;
223
(*traverser)(this, argument);
224
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
226
(*arg)->traverse_cond(traverser, argument, order);
230
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
232
(*arg)->traverse_cond(traverser, argument, order);
234
(*traverser)(this, argument);
238
(*traverser)(this, argument);
243
Transform an Item_func object with a transformer callback function.
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
256
Item returned as the result of transformation of the root node
259
Item *Item_func::transform(Item_transformer transformer, unsigned char *argument)
263
Item **arg,**arg_end;
264
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
266
Item *new_item= (*arg)->transform(transformer, argument);
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.
276
if (*arg != new_item)
277
current_session->change_item_tree(arg, new_item);
280
return (this->*transformer)(argument);
285
Compile Item_func object with a processor and a transformer
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.
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
305
Item returned as the result of transformation of the root node
308
Item *Item_func::compile(Item_analyzer analyzer, unsigned char **arg_p,
309
Item_transformer transformer, unsigned char *arg_t)
311
if (!(this->*analyzer)(arg_p))
315
Item **arg,**arg_end;
316
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
319
The same parameter value of arg_p must be passed
320
to analyze any argument of the condition formula.
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);
328
return (this->*transformer)(arg_t);
332
See comments in Item_cmp_func::split_sum_func()
335
void Item_func::split_sum_func(Session *session, Item **ref_pointer_array,
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);
344
void Item_func::update_used_tables()
348
for (uint32_t i=0 ; i < arg_count ; i++)
350
args[i]->update_used_tables();
351
used_tables_cache|=args[i]->used_tables();
352
const_item_cache&=args[i]->const_item();
357
table_map Item_func::used_tables() const
359
return used_tables_cache;
363
table_map Item_func::not_null_tables() const
365
return not_null_tables_cache;
369
void Item_func::print(String *str, enum_query_type query_type)
371
str->append(func_name());
373
print_args(str, 0, query_type);
378
void Item_func::print_args(String *str, uint32_t from, enum_query_type query_type)
380
for (uint32_t i=from ; i < arg_count ; i++)
384
args[i]->print(str, query_type);
389
void Item_func::print_op(String *str, enum_query_type query_type)
392
for (uint32_t i=0 ; i < arg_count-1 ; i++)
394
args[i]->print(str, query_type);
396
str->append(func_name());
399
args[arg_count-1]->print(str, query_type);
404
bool Item_func::eq(const Item *item, bool binary_cmp) const
406
/* Assume we don't have rtti */
409
if (item->type() != FUNC_ITEM)
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())))
420
for (uint32_t i=0; i < arg_count ; i++)
421
if (!args[i]->eq(item_func->args[i], binary_cmp))
427
bool Item_func::get_arg0_date(DRIZZLE_TIME *ltime, uint32_t fuzzy_date)
429
return (null_value=args[0]->get_date(ltime, fuzzy_date));
433
bool Item_func::get_arg0_time(DRIZZLE_TIME *ltime)
435
return (null_value=args[0]->get_time(ltime));
439
bool Item_func::is_null()
446
Field *Item_func::tmp_table_field(Table *table)
450
switch (result_type()) {
452
if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
453
field= new Field_int64_t(max_length, maybe_null, name, unsigned_flag);
455
field= new Field_long(max_length, maybe_null, name, unsigned_flag);
458
field= new Field_double(max_length, maybe_null, name, decimals);
461
return make_string_field(table);
463
field= new Field_new_decimal(
464
my_decimal_precision_to_length(decimal_precision(),
467
maybe_null, name, decimals, unsigned_flag);
471
// This case should never be chosen
482
my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
485
int2my_decimal(E_DEC_FATAL_ERROR, val_int(), unsigned_flag, decimal_value);
486
return decimal_value;
490
bool Item_func::agg_arg_collations(DTCollation &c, Item **items,
491
uint32_t nitems, uint32_t flags)
493
return agg_item_collations(c, func_name(), items, nitems, flags, 1);
497
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
502
return agg_item_collations_for_comparison(c, func_name(),
503
items, nitems, flags);
507
bool Item_func::agg_arg_charsets(DTCollation &c, Item **items, uint32_t nitems,
508
uint32_t flags, int item_sep)
510
return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep);
514
double Item_func::fix_result(double value)
516
static double fix_infinity= numeric_limits<double>::infinity();
518
if (value != fix_infinity && value != -fix_infinity)
525
void Item_func::fix_num_length_and_dec()
527
uint32_t fl_length= 0;
529
for (uint32_t i=0 ; i < arg_count ; i++)
531
set_if_bigger(decimals,args[i]->decimals);
532
set_if_bigger(fl_length, args[i]->max_length);
534
max_length=float_length(decimals);
535
if (fl_length > max_length)
537
decimals= NOT_FIXED_DEC;
538
max_length= float_length(NOT_FIXED_DEC);
543
Set max_length/decimals of function if function is fixed point and
544
result length/precision depends on argument ones.
547
void Item_func::count_decimal_length()
552
for (uint32_t i=0 ; i < arg_count ; i++)
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);
558
int precision= cmin(max_int_part + decimals, DECIMAL_MAX_PRECISION);
559
max_length= my_decimal_precision_to_length(precision, decimals,
565
Set max_length of if it is maximum length of its arguments.
568
void Item_func::count_only_length()
572
for (uint32_t i=0 ; i < arg_count ; i++)
574
set_if_bigger(max_length, args[i]->max_length);
575
set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
581
Set max_length/decimals of function if function is floating point and
582
result length/precision depends on argument ones.
585
void Item_func::count_real_length()
590
for (uint32_t i=0 ; i < arg_count ; i++)
592
if (decimals != NOT_FIXED_DEC)
594
set_if_bigger(decimals, args[i]->decimals);
595
set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
597
set_if_bigger(max_length, args[i]->max_length);
599
if (decimals != NOT_FIXED_DEC)
603
if (length < max_length) // If previous operation gave overflow
604
max_length= UINT32_MAX;
612
void Item_func::signal_divide_by_null()
614
Session *session= current_session;
615
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
620
Item *Item_func::get_tmp_table_item(Session *session)
622
if (!with_sum_func && !const_item() && functype() != SUSERVAR_FUNC)
623
return new Item_field(result_field);
624
return copy_or_same(session);